Android:使用BLE蓝牙

Android手机支持BLE(蓝牙4.0)通信。笔者遇到了不少问题,供大家分享下。

1、开启蓝牙

BlueAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (!adapter.isEnabled()) {
	ToastUtil.showToast("请打开蓝牙服务");
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    this.startActivity(intent);
}
else
    showDevice();

2、显示附近的蓝牙
这里使用了recyclerView列出所有蓝牙。较为简单,不过要去重

ArrayList<BluetoothDevice> foundDevice = new ArrayList<>();
ArrayList<String> tempDevice = new ArrayList<>();

// 将已配对的设备加入到队列中
foundDevice.addAll(adapter.getBondedDevices());
for (BluetoothDevice device : adapter.getBondedDevices()) {
    if (!tempDevice.contains(device.getName() + device.getAddress()))
        tempDevice.add(device.getName() + device.getAddress());
}
LogUtil.d("showDevice", "已连接的设备" + tempDevice);

AlertDialog.Builder builder = new AlertDialog.Builder(this);

// 使用弹出窗。将view加载到弹出窗中
View tempView = LayoutInflater.from(this.getContext()).inflate(R.layout.alert_show_device, null);
recyclerView = (RecyclerView) tempView.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
// 设置recyclerView的适配器。这里较为简单就不贴出代码了。
recyclerView.setAdapter(Adapter);

builder.setView(tempView);
alertDialog = builder.create();
alertDialog.setCancelable(true);
// 监听窗口消失事件。如果窗口消失,则取消蓝牙扫描
builder.setOnCancelListener(new MyCancelListener());
builder.setOnDismissListener(new MyDimissListener());
// 显示弹出窗
alertDialog.show();


// 注册两个广播:发现蓝牙和扫描蓝牙结束
receiver = new BlueToothReceiver();
this.registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
this.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
// 开始扫描
adapter.startDiscovery();

3、监听扫描信息,将扫描到的蓝牙加入到recyclerView中

    /**
     * 蓝牙广播接收器
     */
    class BlueToothReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            // 如果发现了蓝牙
            if (action.equals(BluetoothDevice.ACTION_FOUND)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                LogUtil.d("onReceive", "扫描到了" + device.getName() + "\t" + device.getAddress());
                // 避免重复添加
                if (!tempDevice.contains(device.getName() + device.getAddress())) {
                    LogUtil.d("onReceive", "发现了蓝牙设备: " + device.getName() + "\t" + device.getAddress());
                    foundDevice.add(device);
                    tempDevice.add(device.getName() + device.getAddress());
                    recyclerView.getAdapter().notifyDataSetChanged();
                    LogUtil.d("onReceive", tempDevice);
                }
            }
            // 扫描蓝牙结束了
            else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                ToastUtil.showToast("扫描结束");
                LogUtil.d("onReceive", "扫描结束");
            }
        }
    }

4、监听弹出窗关闭,如果弹出窗关闭,则取消扫描

	class MyCancelListener implements AlertDialog.OnCancelListener {

        @Override
        public void onCancel(DialogInterface dialog) {
            // 停止蓝牙扫描
            foundDevice.clear();
            tempDevice.clear();
            adapter.cancelDiscovery();
        }
    }

    class MyDimissListener implements AlertDialog.OnDismissListener {

        @Override
        public void onDismiss(DialogInterface dialog) {
            // 停止蓝牙扫描
            foundDevice.clear();
            tempDevice.clear();
            adapter.cancelDiscovery();
        }
    }

5、实现recyclerView子项点击事件,这里由于使用了ItemClick接口,并且已经和recyclerView的adapter做了绑定。所以就不摆出代码了

    // 蓝牙列表的点击事件实现
    class MyBlueItemClick implements ItemClick {

        @Override
        public void itemClick(View view, int position) {
            // 关闭弹出窗
            alertDialog.dismiss();
            // 连接设备,得到gatt对象
            BluetoothDevice device = foundDevice.get(position);
            BluetoothGatt gatt = foundDevice.get(position).connectGatt(MyApplication.context, false, new MyBack());
        }
    }

6、实现回调。编写MyBack类

    // 蓝牙设备的监听函数
    class MyBack extends BluetoothGattCallback {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            // 如果连接设备成功,则获取所有的services
            if (newState == BluetoothGatt.STATE_CONNECTED) {
	            gatt.discoverServices());
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            // 如果查找服务成功,则获取所有的服务
            if (status == BluetoothGatt.GATT_SUCCESS) {
                // 得到所有的服务
                List<BluetoothGattService> services = gatt.getServices();

                List<BluetoothGattCharacteristic> characteristicss = new ArrayList<>();
                // 遍历所有的服务,取characteristics
                for (int i = 0; i < services.size(); i++) {
                    // 获取第i个服务
                    BluetoothGattService service = services.get(i);
                    LogUtil.d("onServicesDiscovered", service.getUuid());
              characteristicss.add(service.getCharacteristics());
                }
                LogUtil.d("onServicesDiscovered", "================可用服务在上面");

                // 输出所有的uuid
                for (int i = 0; i < characteristicss.size(); i++) {
                    List<BluetoothGattCharacteristic> temp = characteristicss.get(i);
                    for (BluetoothGattCharacteristic item : temp)
                        LogUtil.d("onServicesDiscovered", item.getUuid());
                    LogUtil.d("onServicesDiscovered", "=============");
                }
            }


			// 如果需要设置监听某一个BluetoothGattCharacteristic
          gatt.setCharacteristicNotification(characteristic, true));
            // 设置描述
            List<BluetoothGattDescriptor> descriptors = characteristic.getDescriptors();
            for (BluetoothGattDescriptor dp : descriptors) {
                dp.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                gatt.writeDescriptor(dp);
            }

        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic
                characteristic, int status) {
        }

        /**
         * 从蓝牙读取数据
         *
         * @param gatt           读取的数据源
         * @param characteristic 读取的内容
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic
                characteristic) {
            // 解析数据
            byte[] bytes = characteristic.getValue();
            String s = "";
            for (int i = 0; i < bytes.length; i++) {
                s += (Integer.toHexString((bytes[i] & 0xff)) + " ");
            }
            // 控制台输出数据
            Log.d("onCharacteristicChanged", characteristic.getUuid() + "\t" + s);
        }


        @Override
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
                                     int status) {
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
                                      int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
        }

    }

7、向蓝牙发送数据

public void sendData2Device() {
                BluetoothGattService service = gatt.getService(uuid1);
                BluetoothGattCharacteristic characteristic = service.getCharacteristic(uuid2);
                characteristic.setValue(new byte[]{0x01});
                LogUtil.d("sendData2Device", "write:" + gatt.writeCharacteristic(characteristic));
        }
    }

至此,BLE收发数据就完成了

猜你喜欢

转载自blog.csdn.net/new_Aiden/article/details/52150177