实现一个Android APP主要需求:
1、APP连接蓝牙转以太网的转接板给底板配置广播信息;
2、广播板的状态能通过蓝牙转接板透传给APP;
蓝牙搜索,发现这些之前一个app都做过,但是读写数据没有做,关键点是:
1、GATT连接;
2、服务特征UUID/读特征UUID 配置特征UUID/写特征UUID,这几个特征UUID 最好是找厂家确认。
要接收到蓝牙的数据,关键是读配置Enable功能:setBleNotification方法,网上这块有很多方法,最后生效的是下面的方法。
@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // services are discoverd Log.d(TAG, "onServicesDiscovered: GATT_SUCCESS"); mBluetoothGatt = gatt; } List<BluetoothGattService> list = gatt.getServices(); for(BluetoothGattService service: list){ serviceUid = service.getUuid(); for(BluetoothGattCharacteristic characteristic : service.getCharacteristics()){ //获取到相应的服务UUID和特征UUID characterUid = characteristic.getUuid(); if (characterUid.toString().contains("8e32")){ //readd characterReadUid = characterUid; m_bluetoothGattCharacteristic_read = characteristic; gatt.setCharacteristicNotification(characteristic, true); } if (characterUid.toString().contains("8e40")){ //write characterWriteUid = characterUid; } if (characterUid.toString().contains("2902")){ //read config characterReadConfigUid = characterUid; } } if (serviceUid.toString().contains("8e20")){ break; } } gatt.requestMtu(200); } //关键是这个方法,网上的说法很多,但是最后生效的还是下面的方法 private void setBleNotification(){ if (characterReadConfigUid == null){ characterReadConfigUid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); } BluetoothGattService service = mBluetoothGatt.getService(serviceUid); if(m_bluetoothGattCharacteristic_read != null) { List<BluetoothGattDescriptor> descriptors = m_bluetoothGattCharacteristic_read.getDescriptors(); Log.v(TAG, "len:"+descriptors.size()); // 遍历设置 BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE 值 , 并写出 for(BluetoothGattDescriptor descriptor : descriptors) { descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } // BluetoothGattDescriptor descriptor = m_bluetoothGattCharacteristic_read.getDescriptor(characterReadConfigUid); // descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); // mBluetoothGatt.writeDescriptor(descriptor); // descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); // mBluetoothGatt.writeDescriptor(descriptor); mBluetoothGatt.readCharacteristic(m_bluetoothGattCharacteristic_read); } }
3、写完成的回调;
写需要设置最大MTU,否则大于MTU的字符串发不出去
@Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // services are discoverd Log.d(TAG, "onServicesDiscovered: GATT_SUCCESS"); mBluetoothGatt = gatt; } gatt.requestMtu(200); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { Log.v(TAG, "onMtuChanged:"+status + ",mtu:"+mtu); if(status == BluetoothGatt.GATT_SUCCESS){ setBleNotification(); } }
4、读数据的回调函数;onCharacteristicChanged 蓝牙收到数据的回调方法,网上有说是onCharacteristicRead方法,实际是这个。
@Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { if (characteristic.getUuid().equals(characterReadUid)) { //step 7-1:读取出characteristic的value值 // 收到的数据 byte[] receiveByte = characteristic.getValue(); String res = new String(receiveByte); Log.i(TAG, "=====>2 value =" + res + ",len:" + receiveByte.length); if (notifyCallback != null){ notifyCallback.notifyMessage(res); } } }
5、蓝牙转接板居然还有一个NAT的问题,蓝牙转接板主动转发过来的UDP包,必须使用相同的端口回过去,否则转接板收不到包。
6、主要代码:
GattCommnucationManage.java代码
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.util.Log; import java.util.List; import java.util.UUID; import top.keepempty.MyApplication; public class GattCommnucationManager { static GattCommnucationManager instanceGattMgr = new GattCommnucationManager(); private BluetoothDevice selectBleDevice; private Context mContext; public static final String TAG = "GattCommnucationManager"; BluetoothGatt mBluetoothGatt; private UUID serviceUid; private UUID characterUid; private UUID characterReadUid; private UUID characterReadConfigUid; private UUID characterWriteUid; private BleMessageNotify notifyCallback; private GattCommnucationManager(){ } public static GattCommnucationManager getInstance(){ if (instanceGattMgr == null){ instanceGattMgr = new GattCommnucationManager(); } return instanceGattMgr; } public void registerInterface(BleMessageNotify callback){ notifyCallback = callback; } public void setDevice(BluetoothDevice device){ mContext = MyApplication.getInstance(); if (selectBleDevice != null && mBluetoothGatt != null){ mBluetoothGatt.disconnect(); mBluetoothGatt.close(); mBluetoothGatt = null; } selectBleDevice = device; connectSelectDevice(); } public void connectSelectDevice(){ if (selectBleDevice == null){ return; } mBluetoothGatt = selectBleDevice.connectGatt(mContext, false, mGattCallback); } //关闭蓝牙和Gatt输入通道 避免出现Gatt 133状态错误 public void closeBlueToothGatt(){ if (mBluetoothGatt == null){ return; } mBluetoothGatt.disconnect(); mBluetoothGatt.close(); mBluetoothGatt = null; selectBleDevice = null; } /** * 向设备发送数据 * @param value * @return */ public boolean writeRXCharacteristic(byte[] value) { if (mBluetoothGatt == null){ return false; } BluetoothGattService rxService = mBluetoothGatt.getService(serviceUid); if (rxService == null) { //Service not supported Log.d(TAG, "writeRXCharacteristic: Service not supported"); return false; } BluetoothGattCharacteristic rxChar = rxService.getCharacteristic(characterWriteUid); if (rxChar == null) { // service not supported Log.d(TAG, "writeRXCharacteristic: Service not supported"); return false; } rxChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); rxChar.setValue(value); Log.d(TAG, "writeRXCharacteristic: "+String.valueOf(rxChar)); return mBluetoothGatt.writeCharacteristic(rxChar); } public final UUID DEVICE_INFO_SERVICE_UUID = UUID.fromString("00001800-0000-1000-8000-00805f9b34fb"); //Charcteristic UUID public final UUID VID_PID_CHARACTERISTIC_UUID = UUID.fromString("00002a00-0000-1000-8000-00805f9b34fb"); BluetoothGattCharacteristic m_bluetoothGattCharacteristic_read; /** * 连接成功或者失败的回调函数 */ public final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Log.d(TAG, "onConnectionStateChange: "+newState); if (newState == BluetoothProfile.STATE_CONNECTED) { //bluetooth is connected so discover services Log.d(TAG, "onConnectionStateChange: "+mBluetoothGatt.getDevice().getName()); mBluetoothGatt.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { //Bluetooth is disconnected Log.d(TAG, "onConnectionStateChange: disconnected"); mBluetoothGatt = null; } } private void setBleNotification(){ if (characterReadConfigUid == null){ characterReadConfigUid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); } BluetoothGattService service = mBluetoothGatt.getService(serviceUid); if(m_bluetoothGattCharacteristic_read != null) { List<BluetoothGattDescriptor> descriptors = m_bluetoothGattCharacteristic_read.getDescriptors(); Log.v(TAG, "len:"+descriptors.size()); // 遍历设置 BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE 值 , 并写出 for(BluetoothGattDescriptor descriptor : descriptors) { descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } // BluetoothGattDescriptor descriptor = m_bluetoothGattCharacteristic_read.getDescriptor(characterReadConfigUid); // descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); // mBluetoothGatt.writeDescriptor(descriptor); // descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); // mBluetoothGatt.writeDescriptor(descriptor); mBluetoothGatt.readCharacteristic(m_bluetoothGattCharacteristic_read); } } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { Log.v(TAG, "onMtuChanged:"+status + ",mtu:"+mtu); if(status == BluetoothGatt.GATT_SUCCESS){ setBleNotification(); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { // services are discoverd Log.d(TAG, "onServicesDiscovered: GATT_SUCCESS"); mBluetoothGatt = gatt; } List<BluetoothGattService> list = gatt.getServices(); for(BluetoothGattService service: list){ serviceUid = service.getUuid(); for(BluetoothGattCharacteristic characteristic : service.getCharacteristics()){ //获取到相应的服务UUID和特征UUID characterUid = characteristic.getUuid(); if (characterUid.toString().contains("8e32")){ //readd characterReadUid = characterUid; m_bluetoothGattCharacteristic_read = characteristic; gatt.setCharacteristicNotification(characteristic, true); } if (characterUid.toString().contains("8e40")){ //write characterWriteUid = characterUid; } if (characterUid.toString().contains("2902")){ //read config characterReadConfigUid = characterUid; } } if (serviceUid.toString().contains("8e20")){ break; } } gatt.requestMtu(200); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { String value = ""; if (characteristic.getUuid().equals(characterReadUid)) { //step 7-1:读取出characteristic的value值 // 收到的数据 byte[] receiveByte = characteristic.getValue(); Log.i(TAG, "=====>读取到 value =" +String.valueOf(receiveByte) + ",len:"+receiveByte.length); //step 7-2:此处为ascii表字符,需转换为十进制ascii值 //再将十进制ascii值,转换为十六进制 //String VID = changeAsciiTo16(value.charAt(0)); //String PID = changeAsciiTo16(value.charAt(value.length() - 1)); //设备VID、PID读取成功,handle更新主线程界面UI //Log.i(TAG, characteristic.getUuid()+",VID:"+VID+",PID:"+PID); } } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { if (characteristic.getUuid().equals(characterReadUid)) { //step 7-1:读取出characteristic的value值 // 收到的数据 byte[] receiveByte = characteristic.getValue(); String res = new String(receiveByte); Log.i(TAG, "=====>2 value =" + res + ",len:" + receiveByte.length); if (notifyCallback != null){ notifyCallback.notifyMessage(res); } } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { super.onCharacteristicWrite(gatt, characteristic, status); if (status == BluetoothGatt.GATT_SUCCESS) { mBluetoothGatt.readCharacteristic(m_bluetoothGattCharacteristic_read); } } }; static public interface BleMessageNotify { void notifyMessage(String msg); } }
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com