andorid 蓝牙相关

kotlin协程

一个线程的多个协程:

  • 一个线程对应多个协程:在 Kotlin 中,协程是协作式的,它们可以在单个线程上启动和运行多个协程。协程通过挂起和恢复操作来协作,而不是通过阻塞线程。

  • 一个线程的多个协程可以同时工作:这里的“同时工作”需要从并发和并行的角度来理解。在单核处理器上,协程通过快速切换来给人一种同时工作的错觉,这实际上是并发,而不是并行。当一个协程挂起时(例如,等待 I/O 操作或另一个协程的结果),它会释放线程的控制权,让其他协程在同一线程上运行。这样,尽管在任意给定时刻只有一个协程在执行,但由于挂起操作的非阻塞性质,多个协程可以在同一时间段内完成它们的工作。

线程vs协程【感觉也没啥用】

  • 线程:线程是由操作系统管理的,它们是相对重量级的,因为每个线程都有自己的栈空间和上下文。线程的创建、切换和管理需要较多的资源和时间。在单核 CPU 上,线程之间的切换可能会导致性能开销,尤其是在线程数量很多的情况下。

  • 协程:协程是用户态的轻量级线程,它们共享同一线程的栈空间,并且协程的切换通常比线程切换要快得多,因为它们不需要涉及操作系统的上下文切换。协程的挂起和恢复操作是由程序控制的,这意味着它们可以在更细的粒度上进行切换,从而实现更高效的并发处理。

蓝牙UUID

UUID就是编号,对应不同服务的一个唯一的编号,用于区分不同的服务及服务特性的个体

服务:比如音频播放

不同的uuid类似网络应用中的端口号分配,例如80是HTTP协议的端口

权限申请与回调

onRequestPermissionsResult 方法 只有在主动调用 requestPermissions 或 ActivityCompat.requestPermissions 请求权限时才会触发。

蓝牙连接与传文件

与已知蓝牙地址设备建立连接,注:以下中服务器端为已知蓝牙地址的目标设备,客户端为自主连接设备。

1.获取目标设备

在客户端(想与已知蓝牙地址连接的设备:

String deviceAddress = "XX:XX:XX:XX:XX:XX"; // 设备 B 的蓝牙地址
BluetoothDevice targetDevice = bluetoothAdapter.getRemoteDevice(deviceAddress);

2.配对设备/监听

在客户端(想与已知蓝牙地址连接的设备:

// 检查设备是否已配对
if (targetDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
    // 发起配对请求
    targetDevice.createBond();
}

// 监听配对状态
BroadcastReceiver pairingReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
            if (device.getAddress().equals(targetDevice.getAddress())) {
                if (bondState == BluetoothDevice.BOND_BONDED) {
                    Log.d("BluetoothPairing", "Device paired successfully");
                } else if (bondState == BluetoothDevice.BOND_NONE) {
                    Log.d("BluetoothPairing", "Pairing failed or device unpaired");
                }
            }
        }
    }
};

// 注册广播接收器
IntentFilter pairingFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(pairingReceiver, pairingFilter);

在服务器端:

会弹出弹框,点击确认 

3.配对成功,建立socket连接

客户端:

// 使用 UUID 创建蓝牙 socket
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // 标准串行 UUID
BluetoothSocket socket = null;
try {
    socket = targetDevice.createRfcommSocketToServiceRecord(uuid);
    socket.connect(); // 连接服务器端,即目标设备
    Log.d("BluetoothConnection", "Connected to device B");
} catch (IOException e) {
    Log.e("BluetoothConnection", "Connection failed: " + e.getMessage());
    try {
        socket.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

服务器端:

// 使用 UUID 创建蓝牙 server socket
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // 标准串行 UUID
BluetoothServerSocket serverSocket = null;
BluetoothSocket socket = null;
try {
    serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("BluetoothFileTransfer", uuid);
    Log.d("BluetoothConnection", "Waiting for connection...");
    socket = serverSocket.accept(); // 阻塞等待客户端连接
    Log.d("BluetoothConnection", "Connected to device A");
} catch (IOException e) {
    Log.e("BluetoothConnection", "Connection failed: " + e.getMessage());
} finally {
    try {
        serverSocket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

4.进行传输

5.关闭socket

wifi-direct连接

初始化wifiManager,channel--discoverPeeres--requestPeers--connect

如果想指定Group owner(GO):【A:GO,未知mac地址,B:group member,已知mac地址】
1.A创建group

manager.createGroup(channel, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        Log.d("WiFiDirect", "Group created successfully");
        // 设备 A 现在是 Group Owner
    }

    @Override
    public void onFailure(int reason) {
        Log.d("WiFiDirect", "Group creation failed: " + reason);
    }
});

2.设备 A 作为 Group Owner,需要监听来自设备 B 的连接请求,A注册广播监听

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
            if (networkInfo.isConnected()) {
                // 连接成功,获取连接信息
                manager.requestConnectionInfo(channel, connectionInfo -> {
                    if (connectionInfo.groupFormed && connectionInfo.isGroupOwner) {
                        Log.d("WiFiDirect", "Device A is Group Owner");
                        // 设备 A 作为 Group Owner,可以开始文件传输
                        startFileTransferAsGroupOwner();
                    }
                });
            }
        }
    }
};

// 注册广播接收器
IntentFilter filter = new IntentFilter();
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
registerReceiver(receiver, filter);

3.B请求连接A

WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = deviceAAddress; // 设备 A 的 MAC 地址
config.groupOwnerIntent = 0; // 设备 B 不希望成为 Group Owner

manager.connect(channel, config, new WifiP2pManager.ActionListener() {
    @Override
    public void onSuccess() {
        Log.d("WiFiDirect", "Connection request sent to device A");
    }

    @Override
    public void onFailure(int reason) {
        Log.d("WiFiDirect", "Connection failed: " + reason);
    }
});

4.B注册监听广播

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {
            NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
            if (networkInfo.isConnected()) {
                // 连接成功,获取连接信息
                manager.requestConnectionInfo(channel, connectionInfo -> {
                    if (connectionInfo.groupFormed && !connectionInfo.isGroupOwner) {
                        Log.d("WiFiDirect", "Device B is connected to Group Owner");
                        // 设备 B 作为客户端,可以开始文件传输
                        startFileTransferAsClient(connectionInfo.groupOwnerAddress);
                    }
                });
            }
        }
    }
};

// 注册广播接收器
IntentFilter filter = new IntentFilter();
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
registerReceiver(receiver, filter);

5.建立socket,进行文件传输,关闭socket

A:ServerSocket serverSocket = new ServerSocket(8888);
B:Socket socket = new Socket(groupOwnerAddress, 8888); // 连接到 Group Owner
manager.requestConnectionInfo(channel, connectionInfo -> {
    if (connectionInfo.groupFormed && !connectionInfo.isGroupOwner) {
        InetAddress groupOwnerAddress = connectionInfo.groupOwnerAddress;
        Log.d("WiFiDirect", "Group Owner IP: " + groupOwnerAddress.getHostAddress());
        // 使用 Group Owner 的 IP 地址进行文件传输
        startFileTransferAsClient(groupOwnerAddress.getHostAddress());
    }
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值