Android检测仪开发---BleBluetooth 多连接

前言

天道好轮回,苍天饶过谁。之前开发的OBD检测仪,由于提供的硬件都是经典蓝牙,所以对blebluetooth当时只写了一个小demo就完事了,谁知道这次特么新的检测仪,我们采购的蓝牙模块全部是Ble的,你说坑爹不坑爹,折腾不折腾,典型的不作死就不会死系列。但是,既然选择了,你还有什么办法,只能上啊,然后去官网查资料,在google查资料,期间又有好些文章提到blebluetooth有好多坑,目前我只遇到了一个,因为我测试手机比较少,如果再遇到再说,开始正题。

正文

  1. 声明权限
/**
 *定位权限,是因为高版本需要,而且我这个确定是ble,
 *所以我这个apk是不允许在不支持ble的设备上运行的,
 *如果你允许,就把true改为false即可,
 *另外高版本,这些权限要动态申请的。
 */
 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
   <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
   <uses-permission android:name="android.permission.BLUETOOTH" />

   <uses-feature
       android:name="android.hardware.bluetooth_le"
       android:required="true" />
   <uses-feature
       android:name="android.bluetooth.le"
       android:required="true" />
  1. 申请权限
//TODO--这里我用了easypermission
    private static final String[] BLUETOOTH_AND_LOCATION = {
    Manifest.permission.BLUETOOTH, 
    Manifest.permission.BLUETOOTH_ADMIN,
    Manifest.permission.ACCESS_COARSE_LOCATION, 
    Manifest.permission.ACCESS_FINE_LOCATION};

   private static final int RC_BLUETOOTH_PERM = 123;
   
   
   private void checkBluetoothPermission() {
       bluetoothUtils = new BluetoothUtils(this);
       if (!EasyPermissions.hasPermissions(this, BLUETOOTH_AND_LOCATION)) {
           EasyPermissions.requestPermissions(this, "程序需要以下权限", RC_BLUETOOTH_PERM, BLUETOOTH_AND_LOCATION);
           Log.e("mess", "-----no permission------");
       } else {
           bluetoothAdapter = bluetoothUtils.getBluetoothAdapter();
           Log.e("mess", "-----has permission------");
       }
   }
   
       @Override
   public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
       super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
   }

   @Override
   public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
       Log.e(TAG, "permission granted:" + requestCode);
       switch (requestCode) {
           case RC_BLUETOOTH_PERM:
               bluetoothAdapter = bluetoothUtils.getBluetoothAdapter();
               break;
       }
   }

   @Override
   public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
       Log.e(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size());
       if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
           new AppSettingsDialog.Builder(this).build().show();
       }
   }
  1. 扫描设备
//我这里还是用的老版的扫描api

    private BluetoothAdapter.LeScanCallback mLeScanCallBack = new BluetoothAdapter.LeScanCallback() {
       @Override
       public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
           Log.e("mess", "onLeScan.....");
           if (device != null && !TextUtils.isEmpty(device.getName())) {
               runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                       deviceListAdapter.addDevice(device);
                       deviceListAdapter.notifyDataSetChanged();
                   }
               });
           }
       }
   };
   
   /**
   *开始搜索之前,一定要停止之前的搜索,而且这个扫描是一个耗时耗资源的操作,所以最好在子线程干,
   *或者在主线程也行,但是要及时停止扫描。
   */
   private void startSearchDevices(){
     if (bluetoothAdapter != null) {
                   bluetoothAdapter.stopLeScan(mLeScanCallBack);
                   bluetoothAdapter.startLeScan(mLeScanCallBack);
               }
   
   }
   

4.连接蓝牙

/***
 * 这里定义了我的Ble硬件的一些UUID,包括service, notify,write
 *
 */
public class BleSppGattAttributes {
   private static HashMap<String, String> attributes = new HashMap();

   public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";

   //B-0002/B-0004/TLS-01/STB-01
//    Service UUID:fee0
//    Notify:fee1
//    Write:fee1
   public static String BLE_SPP_Service = "0000fee0-0000-1000-8000-00805f9b34fb";
   public static String BLE_SPP_Notify_Characteristic = "0000fee1-0000-1000-8000-00805f9b34fb";
   public static String  BLE_SPP_Write_Characteristic = "0000fee2-0000-1000-8000-00805f9b34fb";
   public static String  BLE_SPP_AT_Characteristic = "0000fee3-0000-1000-8000-00805f9b34fb";
   static {
       //B-0002/B-0004/TRL-01 SPP Service
       attributes.put(BLE_SPP_Service, "BLE SPP Service");
       attributes.put(BLE_SPP_Notify_Characteristic, "BLE SPP Notify Characteristic");
       attributes.put(BLE_SPP_Write_Characteristic, "BLE SPP Write Characteristic");
       attributes.put(BLE_SPP_AT_Characteristic, "BLE SPP AT Characteristic");
   }

   public static String lookup(String uuid, String defaultName) {
       String name = attributes.get(uuid);
       return name == null ? defaultName : name;
   }
}

核心都在这个Service里面,单设备,多设备都可以用

//TODO---核心监听,这个是必备的,因为考虑到多设备,所以每个gatt的广播,我都带着蓝牙地址发出去的,
//每个蓝牙就监听自己地址的广播就可以了,这样也不会乱
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
       //TODO---当连接状态发生改变时,一定会回调这个方法,
       @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
       @Override
       public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
           Log.e(TAG, "onConnectionStateChange:" + gatt.getDevice().getAddress()+",status:"+status);
           StringBuffer intentAction = new StringBuffer(gatt.getDevice().getAddress());
           if (newState == BluetoothProfile.STATE_CONNECTED) {
               intentAction.append(ACTION_GATT_CONNECTED);
               mConnectionState = STATE_CONNECTED;
               Log.i(TAG, "Connected to GATT server.");
               //TODO---这里我虽然写在了log,但是gatt.discouverServices()是必要的,否则找不到服务
               Log.i(TAG, "Attempting to start service discovery:" + gatt.discoverServices());
           } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
               intentAction.append(ACTION_GATT_DISCONNECTED);
               mConnectionState = STATE_DISCONNECTED;
               Log.i(TAG, "Disconnected from GATT server.");
               
           }
           
           broadcastUpdate(intentAction.toString());
       }

       //TODO---发现服务的回调
       @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
       @Override
       public void onServicesDiscovered(BluetoothGatt gatt, int status) {
           Log.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress());
           if (status == BluetoothGatt.GATT_SUCCESS) {
               // 默认先使用 B-0006/TL8266 服务发现
               BluetoothGattService service = gatt.getService(UUID.fromString(BleSppGattAttributes.BLE_SPP_Service));
               if (service != null) {
                   //找到服务,继续查找特征值
                   mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
                   mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Write_Characteristic));
               }

               if (mNotifyCharacteristic != null) {
                   broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_DISCOVERED);
                   //使能Notify
                   setCharacteristicNotification(gatt, mNotifyCharacteristic, true);
               }

               if (mWriteCharacteristic == null) //适配没有FEE2的B-0002/04
               {
                   mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
               }

               if (service == null) {
                   Log.v("log", "service is null");
                   broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_NO_DISCOVERED);

               }

           } else {
               Log.w(TAG, "onServicesDiscovered received: " + status);
           }
       }


       @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
       @Override
       public void onCharacteristicRead(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic,
                                        int status) {
           Log.e(TAG, "onCharacteristicRead:" + gatt.getDevice().getAddress());
           if (status == BluetoothGatt.GATT_SUCCESS) {
               Log.e(TAG, "onCharacteristicRead");
               broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
           }
       }

       //接收蓝牙发送的数据回调
       @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
       @Override
       public void onCharacteristicChanged(BluetoothGatt gatt,
                                           BluetoothGattCharacteristic characteristic) {
           Log.e(TAG, "onCharacteristicChanged:" + gatt.getDevice().getAddress());
           broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
       }

       //蓝牙发送数据成功的时候回调
       @Override
       public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
           Log.e(TAG, "onCharacteristicWrite:" + gatt.getDevice().getAddress());
           if (status == BluetoothGatt.GATT_SUCCESS) {
               broadcastUpdate(gatt.getDevice().getAddress() + ACTION_WRITE_SUCCESSFUL);
               Log.v("log", "Write OK");
           }
       }

   };

然后我们的连接蓝牙代码

//这里用到同步锁,既然是多连接,我就把所有建立的连接存到了Map<address,BluetoothGatt>里面,
 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
   public synchronized  boolean connect(final String address) {
       if (mBluetoothAdapter == null || address == null || !mBluetoothAdapter.isEnabled()) {
           Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
           return false;
       }

       //gat个数是有限的,所以连接的时候,先关闭之前的连接
       BluetoothGatt btg = connectionQueue.get(address);
       if (btg != null) {
           btg.disconnect();
       }
       //如果已经连接上app,由于超出了范围,链接断了,可以用到btg.connect()去重连;
   	//当然如果你不想重连,那就断掉之前的连接,重新建立连接即可
   	
       final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
       BluetoothGatt mBluetoothGatt = null;
       //TOTO---这里的连接会有坑,所以做了版本适配,也把坑填上了
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
       } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           try {
               Method connectGattMethod = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
               connectGattMethod.setAccessible(true);
               mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
           } catch (Exception ex) {
               Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex);
           }
       }

       if (mBluetoothGatt == null) {
           mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
       }

       connectionQueue.put(address, mBluetoothGatt);
       Log.d(TAG, "Trying to create a new connection." + address + "," + (mBluetoothGatt == null));
       mBluetoothDeviceAddress = address;
       mConnectionState = STATE_CONNECTING;
       return true;
   }

连接上之后,我们能监听接收的数据,另外关心的就是写数据了

 //同样,既然是多链接,肯定是各蓝牙连接写各自的数据
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
   public void writeData(String address, byte[] data) {

       if (mWriteCharacteristic != null && data != null) {
           mWriteCharacteristic.setValue(data);

           BluetoothGatt mBluetoothGatt = connectionQueue.get(address);
           if (mBluetoothGatt != null) {
               mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);
           }
       }

   }

最后不用的时候,一定要断开连接,如果不主动断开连接,虽然app退出了,但是tcp连接是一直存在的,这样会消耗资源


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
   public void close() {

       for (String addr : connectionQueue.keySet()) {
           BluetoothGatt mBluetoothGatt = connectionQueue.get(addr);
           if (mBluetoothGatt != null) {
               mBluetoothGatt.close();
               connectionQueue.remove(addr);
               mBluetoothGatt = null;
           }
       }
   }

OK,还是把Service整体看下



package kd.com.auroa_brake_detector;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
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.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.util.Log;

import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Service for managing connection and data communication with a GATT server hosted on a
 * given Bluetooth LE device.
 */
public class BluetoothLeMultipleService extends Service {
    private final static String TAG = BluetoothLeMultipleService.class.getSimpleName();

    private BluetoothManager mBluetoothManager;
    private BluetoothAdapter mBluetoothAdapter;
    private String mBluetoothDeviceAddress;
    //ble characteristic
    private BluetoothGattCharacteristic mNotifyCharacteristic;
    private BluetoothGattCharacteristic mWriteCharacteristic;
    private Map<String, BluetoothGatt> connectionQueue = new LinkedHashMap<>();

    private int mConnectionState = STATE_DISCONNECTED;

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTING = 1;
    private static final int STATE_CONNECTED = 2;

    /**
     * intent action 前面加上蓝牙地址,便于区分
     */
    public final static String ACTION_GATT_CONNECTED = "kd.com.auroa_brake_detector.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED = "kd.com.auroa_brake_detector.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "kd.com.auroa_brake_detector.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_AVAILABLE = "kd.com.auroa_brake_detector.ACTION_DATA_AVAILABLE";
    public final static String EXTRA_DATA = "kd.com.auroa_brake_detector.EXTRA_DATA";
    public final static String ACTION_WRITE_SUCCESSFUL = "kd.com.auroa_brake_detector.WRITE_SUCCESSFUL";
    public final static String ACTION_GATT_SERVICES_NO_DISCOVERED = "kd.com.auroa_brake_detector.GATT_SERVICES_NO_DISCOVERED";

    public final static UUID UUID_BLE_SPP_NOTIFY = UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic);


    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.e(TAG, "onConnectionStateChange:" + gatt.getDevice().getAddress()+",status:"+status);
            StringBuffer intentAction = new StringBuffer(gatt.getDevice().getAddress());
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction.append(ACTION_GATT_CONNECTED);
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction.toString());
                Log.i(TAG, "Connected to GATT server.");
                Log.i(TAG, "Attempting to start service discovery:" + gatt.discoverServices());
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction.append(ACTION_GATT_DISCONNECTED);
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction.toString());
            }
        }

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            Log.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress());
            if (status == BluetoothGatt.GATT_SUCCESS) {
                // 默认先使用 B-0006/TL8266 服务发现
                BluetoothGattService service = gatt.getService(UUID.fromString(BleSppGattAttributes.BLE_SPP_Service));
                if (service != null) {
                    //找到服务,继续查找特征值
                    mNotifyCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
                    mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Write_Characteristic));
                }

                if (mNotifyCharacteristic != null) {
                    broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_DISCOVERED);
                    //使能Notify
                    setCharacteristicNotification(gatt, mNotifyCharacteristic, true);
                }

                if (mWriteCharacteristic == null) //适配没有FEE2的B-0002/04
                {
                    mWriteCharacteristic = service.getCharacteristic(UUID.fromString(BleSppGattAttributes.BLE_SPP_Notify_Characteristic));
                }

                if (service == null) {
                    Log.v("log", "service is null");
                    broadcastUpdate(gatt.getDevice().getAddress() + ACTION_GATT_SERVICES_NO_DISCOVERED);

                }

            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
            }
        }


        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                                         BluetoothGattCharacteristic characteristic,
                                         int status) {
            Log.e(TAG, "onCharacteristicRead:" + gatt.getDevice().getAddress());
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.e(TAG, "onCharacteristicRead");
                broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
            }
        }

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            Log.e(TAG, "onCharacteristicChanged:" + gatt.getDevice().getAddress());
            broadcastUpdate(gatt.getDevice().getAddress() + ACTION_DATA_AVAILABLE, characteristic);
        }

        //Will call this when write successful
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.e(TAG, "onCharacteristicWrite:" + gatt.getDevice().getAddress());
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(gatt.getDevice().getAddress() + ACTION_WRITE_SUCCESSFUL);
                Log.v("log", "Write OK");
            }
        }

    };

    private void broadcastUpdate(final String action) {
        Log.e(TAG, "broadcastUpdate:" + action);
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) {
        Log.e(TAG, "broadcastUpdate2:" + action);
        final Intent intent = new Intent(action);
        if (UUID_BLE_SPP_NOTIFY.equals(characteristic.getUuid())) {
            // For all other profiles, writes the data formatted in HEX.
            final byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                intent.putExtra(EXTRA_DATA, data);
            }
        }

        sendBroadcast(intent);
    }

    public class LocalBinder extends Binder {
        BluetoothLeMultipleService getService() {
            return BluetoothLeMultipleService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "bind.....");
        return mBinder;
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    @Override
    public boolean onUnbind(Intent intent) {
        close();
        return super.onUnbind(intent);
    }

    private final IBinder mBinder = new LocalBinder();

    /**
     * Initializes a reference to the local Bluetooth adapter.
     *
     * @return Return true if the initialization is successful.
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public boolean initialize() {
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e(TAG, "Unable to initialize BluetoothManager.");
                return false;
            }
        }


        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
            return false;
        }

        return true;
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public   boolean connect(final String address) {
        if (mBluetoothAdapter == null || address == null || !mBluetoothAdapter.isEnabled()) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        //先关闭连接
        BluetoothGatt btg = connectionQueue.get(address);
        if (btg != null) {
            btg.disconnect();
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        BluetoothGatt mBluetoothGatt = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                Method connectGattMethod = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class);
                connectGattMethod.setAccessible(true);
                mBluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(device, this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
            } catch (Exception ex) {
                Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex);
            }
        }

        if (mBluetoothGatt == null) {
            mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
        }

        connectionQueue.put(address, mBluetoothGatt);
        Log.d(TAG, "Trying to create a new connection." + address + "," + (mBluetoothGatt == null));
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        return true;
    }



 
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void close() {

        for (String addr : connectionQueue.keySet()) {
            BluetoothGatt mBluetoothGatt = connectionQueue.get(addr);
            if (mBluetoothGatt != null) {
                mBluetoothGatt.close();
                connectionQueue.remove(addr);
                mBluetoothGatt = null;
            }
        }
    }



    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void setCharacteristicNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if (mBluetoothAdapter == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        gatt.setCharacteristicNotification(characteristic, enabled);

        // This is specific to BLE SPP Notify.
        if (UUID_BLE_SPP_NOTIFY.equals(characteristic.getUuid())) {
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                    UUID.fromString(BleSppGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
            descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            gatt.writeDescriptor(descriptor);

        }
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void writeData(String address, byte[] data) {

        if (mWriteCharacteristic != null && data != null) {
            mWriteCharacteristic.setValue(data);

            BluetoothGatt mBluetoothGatt = connectionQueue.get(address);
            if (mBluetoothGatt != null) {
                mBluetoothGatt.writeCharacteristic(mWriteCharacteristic);
            }
        }

    }

}

注册蓝牙广播,假如你连接的蓝牙地址是mAddress,所以注册蓝牙监听广播的时候,要带上地址

 public static IntentFilter makeGattUpdateIntentFilter(String address) {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(address+BluetoothLeService.ACTION_DATA_AVAILABLE);
        intentFilter.addAction(address+BluetoothLeService.ACTION_WRITE_SUCCESSFUL);
        intentFilter.addAction(address+BluetoothLeService.ACTION_GATT_SERVICES_NO_DISCOVERED);
        return intentFilter;
    }
     //这样广播就只会接收本蓝牙连接的广播消息了
    context.registerReceiver(receiver,makeGattUpdateIntentFilter(address))
 

结束

核心差不多就这么多,记录一下,方便自己查找,如果有问题,希望多交流交流,因为这个玩意我也是只弄了一周,因为工期比较赶,项目代码不方便上传,如果有问题留言交流吧,或者我的qq:1031012395

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值