Android蓝牙开发前,首先要区分是经典蓝牙开发还是BLE(低功耗)蓝牙开发,它们的开发是有区别的,如果还分不清经典蓝牙和BLE(低功耗)蓝牙的小伙伴,可以先问问度娘。
/** * 自动打开蓝牙(异步:蓝牙不会立刻就处于开启状态) * 这个方法打开蓝牙不会弹出提示 */ public void openBlueAsyn(){ if (isSupportBlue()) { mBluetoothAdapter.enable(); } }
/** * 自动打开蓝牙(同步) * 这个方法打开蓝牙会弹出提示 * 需要在onActivityResult 方法中判断resultCode == RESULT_OK true为成功 */ public void openBlueSync(Activity activity, int requestCode){ Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(intent, requestCode); }
记得添加权限啊:
<!-- 使用蓝牙的权限 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <!-- 扫描蓝牙设备或者操作蓝牙设置 --> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!--模糊定位权限,仅作用于6.0+--> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!--精准定位权限,仅作用于6.0+--> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
话不多说直接copy吧,至于为什么要加定位权限。我也没有深究,这里6.0+记得加上动态申请定位权限的。不加,你懂的。。
经典的就不贴了。
这个时候你已经能获取到你要扫描的设备;
连接模式是固定的;通过扫描到的设备发起连接,并设置一个GattCallBack即可。通过这个callback,我们可以获取到
当前设备的连接状态 onConnectionStateChange、设备服务对象onServicesDiscovered包括该服务的一下特征uuid等
onCharacteristicChanged当设备特征发生改变时回回调该方法。可在这里接收蓝牙设备发过来的数据。
device.createBond();//配对,天仙配之后才能连接(目前我做的不用配对,嘿嘿) public DeviceConnetMannager connet(Context context, BluetoothDevice device) { bluetoothGatt = device.connectGatt(context, true, mGattCallback); return this; } private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (null != bleStatusChange) { bleStatusChange.statusChange(gatt, newState); } if (newState == BluetoothProfile.STATE_CONNECTED) { mConnectionState = STATE_CONNECTED; bluetoothGatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mConnectionState = STATE_DISCONNECTED; } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { List<BluetoothGattService> services = bluetoothGatt.getServices(); for (int i = 0; i < services.size(); i++) { HashMap<String, BluetoothGattCharacteristic> charMap = new HashMap<>(); BluetoothGattService bluetoothGattService = services.get(i); String serviceUuid = bluetoothGattService.getUuid().toString(); List<BluetoothGattCharacteristic> characteristics = bluetoothGattService.getCharacteristics(); for (int j = 0; j < characteristics.size(); j++) { charMap.put(characteristics.get(j).getUuid().toString(), characteristics.get(j)); } servicesMap.put(serviceUuid, charMap); } BluetoothGattCharacteristic bluetoothGattCharacteristic = getBluetoothGattCharacteristic(UUID_SERVICE, UUID_CHARACTERISTIC); if (bluetoothGattCharacteristic == null) { return; } enableGattServicesNotification(bluetoothGattCharacteristic); } else { Log.w(TAG, " --------- onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.d(TAG, "onCharacteristicRead: status---=" + status); if (status == BluetoothGatt.GATT_SUCCESS) { } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { String s = Arrays.toString(characteristic.getValue()); Log.d("收到数据=", "onCharacteristicChanged: -----------=" + s); if (null != MessageMannager.build().getReciverData()) { MessageMannager.build().getReciverData().parseData(characteristic); } } }; /** * 根据服务UUID和特征UUID,获取一个特征{@link BluetoothGattCharacteristic} * * @param serviceUUID 服务UUID * @param characterUUID 特征UUID */ private BluetoothGattCharacteristic getBluetoothGattCharacteristic(String serviceUUID, String characterUUID) { if (!isEnable(context)) { throw new IllegalArgumentException(" Bluetooth is no enable please call BluetoothAdapter.enable()"); } if (null == bluetoothGatt) { Log.e(TAG, "mBluetoothGatt is null"); return null; } //找服务 Map<String, BluetoothGattCharacteristic> bluetoothGattCharacteristicMap = servicesMap.get(serviceUUID); if (null == bluetoothGattCharacteristicMap) { Log.e(TAG, "Not found the serviceUUID!"); return null; } //找特征 Set<Map.Entry<String, BluetoothGattCharacteristic>> entries = bluetoothGattCharacteristicMap.entrySet(); BluetoothGattCharacteristic gattCharacteristic = null; for (Map.Entry<String, BluetoothGattCharacteristic> entry : entries) { if (characterUUID.equals(entry.getKey())) { gattCharacteristic = entry.getValue(); break; } } return gattCharacteristic; } /** * 当前蓝牙是否打开 */ private boolean isEnable(Context c) { if (null != BLEManager.build().getBluetoothAdapter(c)) { return BLEManager.build().getBluetoothAdapter(c).isEnabled(); } return false; } private void enableGattServicesNotification(BluetoothGattCharacteristic gattCharacteristic) { if (gattCharacteristic == null) { return; } setNotify(gattCharacteristic); } private void setNotify(BluetoothGattCharacteristic characteristic) { final int charaProp = characteristic.getProperties(); if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) { // If there is an active notification on a characteristic, clear // it first so it doesn't update the data field on the user interface. if (mNotifyCharacteristic1 != null) { setCharacteristicNotification( mNotifyCharacteristic1, false); mNotifyCharacteristic1 = null; } readCharacteristic(characteristic); } if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) { mNotifyCharacteristic1 = characteristic; setCharacteristicNotification( characteristic, true); } } /** * Enables or disables notification on a give characteristic. * * @param characteristic Characteristic to act on. * @param enabled If true, enable notification. False otherwise. */ public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if (BLEManager.build().getBluetoothAdapter(context) == null || bluetoothGatt == null) { Log.w(TAG, " --------- BluetoothAdapter not initialized --------- "); return; } bluetoothGatt.setCharacteristicNotification(characteristic, enabled); if (UUID_CHARACTERISTIC.equals(characteristic.getUuid().toString())) { BluetoothGattDescriptor descriptor = characteristic.getDescriptor( UUID.fromString(UUID_DESCRIPTOR)); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); bluetoothGatt.writeDescriptor(descriptor); Log.d(TAG, " --------- Connect setCharacteristicNotification --------- " + characteristic.getUuid()); } } /** * Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported * asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} * callback. * * @param characteristic The characteristic to read from. */ public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (BLEManager.build().getBluetoothAdapter(context) == null || bluetoothGatt == null) { Log.w(TAG, " --------- BluetoothAdapter not initialized --------- "); return; } bluetoothGatt.readCharacteristic(characteristic); }以上,就能接收外围设备发过来的数据了。
怎么发送给设备:
通过连接蓝牙时返回的BluetoothGatt 对象可以获取到该设备的服务对象即BluetoothGattService,这里BluetoothGattService还不能直接操作发送数据,因为BluetoothGattService没有设置数据的方法只能通过bluetoothGattCharacteristic 特性描述添加数据。
然后再由BluetoothGatt 发送bluetoothGattCharacteristic 携带的数据给蓝牙设备。
public boolean writeRXCharacteristic(byte... value) { //这里的mBluetoothGattService 是通过mBluetoothGatt.getService(RX_SERVICE_UUID)获取; //bluetoothGattCharacteristic 是通过mBluetoothGattService.getCharacteristic(RX_CHAR_UUID); 这里的两个UUID一般是固定。硬件给定 if (mBluetoothGatt == null) { return false; } if (mBluetoothGattService == null) { return false; } if (bluetoothGattCharacteristic == null) { return false; } if (!isConnet) { return false; } bluetoothGattCharacteristic.setValue(value); boolean status = mBluetoothGatt.writeCharacteristic(bluetoothGattCharacteristic); Log.d(TAG, "write TXchar - status=" + status); return status; }剩下的就是具体的封装通用代码了,我们项目要外接四个设备。所以简单封装了一个基类代码。上面差不多都摘出来的核心代码。
到此最简单的通信完成,剩下的坑慢慢踩。核心代码都在了,就不给demo了。撒U拉纳