安卓蓝牙4.0和蓝牙多通道

安卓蓝牙4.0和蓝牙多通道
1.首先连接蓝牙的时候需要在配置文件manifest中增加权限

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

这个时候我们才算正式开始进入主题

2.判断你的移动设备是否支持蓝牙
如果你想声明你的应用程序只能在支持BLE的设备上运行,可以将下面声明包含进你的应用程序manifest文<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
想让你的应用程序也能够在不支持BLE的设备上运行,你就应该将上面标签中的属性设置为required=”false”。然后在运行的过程中使用PackageManager.hasSystemFeature()方法来判断设备是否支持BLE:

if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
            Toast.makeText(this, “没有可提供的蓝牙设备”, Toast.LENGTH_SHORT).show();
            finish();
}

3.获取蓝牙适配器 BluetoothAdapter
先声明 private BluetoothAdapter mBluetoothAdapter;
然后

final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

//如果蓝牙设配器里面没有数据的话就让它返回

if(mBluetoothAdapter == null){
            Toast.makeText(this, “没有可提供的蓝牙设备”, Toast.LENGTH_SHORT).show();
            finish();
            return;
}

4.搜索蓝牙

/**
* 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
*/
//我这里使用了需要连接多台蓝牙设备 所有放在list里面
private LinkedList mDeviceContainer = new LinkedList();

private ArrayList mDeviceList = new ArrayList();

private void scanLeDevice(final boolean enable){
        if(enable){
            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        Thread.sleep(SCAN_PERIOD);
                        if(mScanning){   //10秒钟后停止搜索
                            mScanning = false;  //状态标记为false

                            mBluetoothAdapter.stopLeScan(mLeScanCallback);
                            invalidateOptionsMenu();
                        }

                    } catch (InterruptedException e) {

                        e.printStackTrace();
                    }

                }
            }).start();

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback); //开始搜索
        }else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);  //停止搜索
        }

        invalidateOptionsMenu();
}

5.搜到设备的时候有一个回调接口

private BluetoothAdapter.LeScanCallback mLeScanCallback = new LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    if(!mDeviceContainer.isEmpty()){
                        if(!isEquals(device)){
                            connectBle(device);
                        }
                    }else{
                        connectBle(device);
                    }

                }
            });

        }
    };

6.启用蓝牙模块

private final ServiceConnection mServiceConnection = new ServiceConnection() {

    @Override
    public void onServiceDisconnected(ComponentName name) {

        mBluetoothLeService = null;
    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        mBluetoothLeService = ((TemperatureServices.LocalBinder)service).getService();
        if(!mBluetoothLeService.initialize()){
            Log.e(TAG, "Unable to initialize Bluetooth");
            finish();
        }
        Log.e(TAG, "mBluetoothLeService is okay");
    }
};

/**
*接收从BlutoothLeService发送过来的广播
包扣 连接 未连接 以及发送过来的数据 
*/
private final BroadcastReceiver mGattUpdateRecevicer = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        Bundle extras = intent.getExtras();

        if(TemperatureServices.ACTION_GATT_CONNECTED.equals(action)){
            Log.i(TAG, "Only gatt, just wait");
        }else if(TemperatureServices.ACTION_GATT_DISCONNECTED.equals(action)){
            if(!mDeviceList.isEmpty()){
                String strAddress = intent.getStringExtra("DEVICE_ADDRESS");
                if(removeDevice(strAddress)){
                    int deviceNum = mDeviceList.size() - 1;
                    numDevice.setText(deviceText+deviceNum);
                }
            }

            invalidateOptionsMenu();
        }else if(TemperatureServices.ACTION_GATT_SERVICES_DISCOVERED.equals(action)){
            if(!mDeviceContainer.isEmpty()){
                String strAddress =intent.getStringExtra("DEVICE_ADDRESS");

                for(BluetoothDevice bluetoothDevice:mDeviceContainer){
                    if(bluetoothDevice.getAddress().equals(strAddress)){
                        mDeviceList.add(bluetoothDevice);
                    }
                }
            }
            numDevice.setText(deviceText+mDeviceList.size());

            Log.e(TAG, "Discover GATT Services");
            invalidateOptionsMenu();

        }else if(TemperatureServices.ACTION_DATA_AVAILABLE.equals(action)){
            Log.i(TAG, "ACTION_DATA_AVAILABLE");
            String data = intent.getStringExtra(TemperatureServices.EXTRA_DATA_TEMP);
            if(extras.containsKey(TemperatureServices.EXTRA_DATA_TEMP)){

                if (data != null) {
                    if (mDataField.length() > 500) {
                        mDataField.setText("");
                    }
                    mDataField.append(data);
                    Log.i("==temp_data==", data); // 打印温度
                }
            }else if (extras.containsKey(TemperatureService.EXTRA_DATA)) {
                // 如果是蓝牙的读取通知到显示

            }
        }



    }
};
/**
     * 连接蓝牙
     * @param device
     */
    private void connectBle(BluetoothDevice device){
        mDeviceContainer.add(device);
        while (true) {
            if(mBluetoothLeService!=null){
                mBluetoothLeService.connect(device.getAddress(), this);
                break;
            }else{
                try{
                    Thread.sleep(250);

                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

        }
    }

7.最主要的 服务
从上面代码中我们可以看到 有一个mBluetoothLeSerivice 它正是我们创建的BluetoothLeService他继承了Service。接下来这个类我详细讲解。

public class BluetoothLeService extends Service{
    private static final String TAG="BluetoothLeService";  //这里是用来打印的
    private String mBluetoothDeviceAddress;  //蓝牙地址
    private BluetoothManager mBluetoothManager; //通过BluetoothManager来获取BluetoothAdapter 
    private BluetoothGatt mBluetoothGatt; //通过BluetoothGatt可以连接设备(connect),发现服务(discoverServices),并把相应地属性返回到BluetoothGattCallback 

//常用的广播
    public final static String ACTION_GATT_CONNECTED           = "com.example.bluetooth.le.ACTION_GATT_CONNECTED";   //连接
    public final static String ACTION_GATT_DISCONNECTED        = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";  //断开链接
    public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; //发现设备
    public final static String ACTION_DATA_AVAILABLE           = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";    //官方的demo里面有这四个
    //这2个是我自己需要读取的所以增加了
    public final static String EXTRA_DATA                      = "com.example.bluetooth.le.EXTRA_DATA";    //有数据的时候传输数据

    public final static String EXTRA_DATA_TEMP            = "com.example.bluetooth.le.EXTRA_DATA_TEMP";  //温度类型变量

    private BluetoothAdapter mBluetoothAdapter = null;

    private ArrayList<BluetoothGatt> connectionQueue = new ArrayList<BluetoothGatt>();  //创建一个BluetoothGatt的队列
    //相当于一个数据类型,它包括一个value和0~n个value的描述(BluetoothGattDescriptor)
    public BluetoothGattCharacteristic mNotifyCharacteristic;

    private Context mContext; //上下文

    //查找服务
    public void findService(BluetoothGatt gatt){
        List<BluetoothGattService> gattservices = gatt.getServices();
        Log.i(TAG,"Count is:"+gattservices.size());
        for(BluetoothGattService gattservice : gattservices){
            Log.i(TAG,gattservice.getUuid().toString());
            //如果服务要等于温度服务
            if(gattservice.getUuid().toString().equalsIgnoreCase(GattAttributes.HEALTH_THERMO_SERVICE)){
                List<BluetoothGattCharacteristic> gattCharacteristics = gattservice.getCharacteristics();
                Log.i(TAG,"Count is:"+gattCharacteristics.size());


                for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics){
                    String uuidchara = gattCharacteristic.getUuid().toString();
                    //如果是温度计的类型的话
                    /**
                    注意:这里的GattAttributes 这个值相当于
                    //实际用你们自己的
                    public static final String HEALTH_TEMP_MEASUREMENT = "0000xxxx-0000-1000-8000-00805f9b34fb";
                    */
                    if(uuidchara.equalsIgnoreCase(GattAttributes.TEMPERATURE_TYPE)){
                        prepareBroadcastDataRead(gattCharacteristic);
                    }

                    //如果是温度计的度数的时候
                else if(uuidchara.equalsIgnoreCase(GattAttributes.HEALTH_TEMP_MEASUREMENT)){
                        prepareBroadcastDataIndicate(gattCharacteristic);

                        //发现服务获取设备的地址
                        brocastUpdate(ACTION_GATT_SERVICES_DISCOVERED, gatt.getDevice().getAddress());
                    }
                }
            }
        }


    }

    /**
     * 最重要的回调
     */
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt,int status,int newState){
            String initAction;
            Log.i(TAG,"oldStatus = "+status+"NewStates"+newState); //打印出来
            if(status == BluetoothGatt.GATT_SUCCESS){ //这个值一般返回的为0
                //如果连接成功
                if(newState == BluetoothProfile.STATE_CONNECTED){
                    initAction = ACTION_GATT_CONNECTED;

                    brocastUpdate(initAction);

                    //连接之后马上去发现服务
                    gatt.discoverServices();
                }
            }else if(newState == BluetoothProfile.STATE_DISCONNECTED){ //断开连接
                initAction = ACTION_GATT_DISCONNECTED;

                brocastUpdate(initAction, gatt.getDevice().getAddress());
            }

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if(status == BluetoothGatt.GATT_SUCCESS){
                Log.w(TAG, "onServicesDiscovered received: " + status);
                findService(gatt);
            }else{
                if(gatt.getDevice().getUuids() == null){
                    Log.w(TAG, "onServicesDiscovered received: " + status);
                }
            }
        };
        //这个是读取数据
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if(status == BluetoothGatt.GATT_SUCCESS){
                brocastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        };

        //当数据发生改变的时候
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            brocastUpdate(ACTION_DATA_AVAILABLE, characteristic);

        };
        //写入数据
        @Override
         public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {

            if (status == BluetoothGatt.GATT_SUCCESS) {
             System.out.println("onDescriptorWriteonDescriptorWrite = " + status + ", descriptor =" + descriptor.getUuid().toString());
            } 
          };
    };




    /**
     * 接收广播可读的特征
     */
    public void prepareBroadcastDataRead(BluetoothGattCharacteristic gattCharacteristic){
        if((gattCharacteristic.getProperties()|BluetoothGattCharacteristic.PROPERTY_READ)>0){
            readCharacteristic(gattCharacteristic); //当特征为可读的特征的时候就直接可以读取
        }
    }

    /**
     * 接收广播通知特性
     */
    public void prepareBroadcastDataIndicate(BluetoothGattCharacteristic gattCharacteristic){
        if((gattCharacteristic.getProperties()|BluetoothGattCharacteristic.PROPERTY_INDICATE)>0){
            setCharacteristicIndication(gattCharacteristic,
                    true);  //当特征为不可读的时候哪么就是为通知
        }
    }

    /**
     * 处理连接蓝牙后进入这里面操作
     */
    private final IBinder mBinder = new LocalBinder();

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


    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // After using a given device, you should make sure that BluetoothGatt.close() is called
        // such that resources are cleaned up properly.  In this particular example, close() is
        // invoked when the UI is disconnected from the Service.
        close();
        return super.onUnbind(intent);
    }


    /**
     * 对外事件处理类
     * 更新广播事件
     */
    private void brocastUpdate(final String action){
        final Intent intent = new Intent(action);
        sendBroadcast(intent);
    }

    /**
     * 传地址广播
     * @param action
     * @param strAddress
     */
    private void brocastUpdate(final String action,final String strAddress){
        final Intent intent = new Intent(action);
        intent.putExtra("DEVICE_ADDRESS", strAddress);
        sendBroadcast(intent);
    }

    private void brocastUpdate(final String action,final BluetoothGattCharacteristic characteristic){
        final Intent intent = new Intent(action);

        //当温度计为温度类型的时候
        if(characteristic.getUuid().equals(UUIDDatabase.UUID_HEALTH_THERMOMETER_SENSOR_LOCATION)){
            String a = HTMParser.getHealthThermoSensorLocation(characteristic, mContext);
            intent.putExtra(EXTRA_DATA, a);
        }

        else if(characteristic.getUuid().equals(UUIDDatabase.UUID_HEALTH_THERMOMETER)){
            String health_temp = HTMParser.getHealthThermo(characteristic, mContext);
            intent.putExtra(EXTRA_DATA_TEMP, health_temp);
        }

        sendBroadcast(intent);
    }

    /**
     * 初始化一个参考本地蓝牙适配器
     * @return
     */
    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;
    }


    /**
     * 连接代码 
     * @param address
     * @param context
     * @return
     */
    public boolean connect(final String address,Context context){
        mContext = context;
        if(mBluetoothAdapter == null && address == null){
             Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
             return false;
        }

        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);

        if(device == null){
            Log.w(TAG,"Device not found.  Unable to connect.");
            return false;
        }

        BluetoothGatt bluetoothGatt;

        bluetoothGatt = device.connectGatt(mContext, false, mGattCallback);
        if(checkGatt(bluetoothGatt)){
            connectionQueue.add(bluetoothGatt);
        }

        Log.d(TAG, "Trying to create a new connection.");

        return true;


    }

    /**
     * 检查是否加入了相同的特征 如果相同就移除掉
     * @param bluetoothGatt
     * @return
     */
    private boolean checkGatt(BluetoothGatt bluetoothGatt){
        if(!connectionQueue.isEmpty()){
            for(BluetoothGatt btg:connectionQueue){
                if(btg.equals(bluetoothGatt)){
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * 断开蓝牙连接 一按断开是全部都断开
     */
    public void disConnect(){
        if(mBluetoothAdapter == null && connectionQueue.isEmpty()){
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }

        for(BluetoothGatt bluetoothGatt:connectionQueue){
            bluetoothGatt.disconnect();
        }
    }

    public void close(){
        if(connectionQueue.isEmpty()){
            return;
        }

        listClose(null);
    }

    /**
     * 清除连接蓝牙的数据
     * 我这里用的是连接多台的设备,所以清除的时候需要一个一个的移除掉
     * @param gatt
     */
    private synchronized void listClose(BluetoothGatt gatt){
        if(!connectionQueue.isEmpty()){
            if(gatt!=null){
                for(final BluetoothGatt bluetoothGatt:connectionQueue){
                    if(bluetoothGatt.equals(gatt)){
                        bluetoothGatt.close();

                        new Thread(new Runnable() {

                            @Override
                            public void run() {
                                try{
                                    Thread.sleep(250);
                                    connectionQueue.remove(bluetoothGatt);

                                }catch(Exception ex){
                                    ex.printStackTrace();
                                }

                            }
                        }).start();
                    }
                }
            }else{
                for(BluetoothGatt bluetoothGatt:connectionQueue){
                    bluetoothGatt.close();
                }

                connectionQueue.clear();
            }
        }
    }

    /**
     * 读取蓝牙数据
     */
    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || connectionQueue.isEmpty()) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        for (BluetoothGatt bluetoothGatt : connectionQueue) {
            bluetoothGatt.readCharacteristic(characteristic);
        }
    }

     /**
     * 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 (mBluetoothAdapter == null || connectionQueue.isEmpty()) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }

        for(BluetoothGatt bluetoothGatt:connectionQueue){
            bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        }
    }

    /**
     * 蓝牙温度计最关键的一步 有些特征只能通过这个 读取  并启用通知更新数据
     * Enables or disables indications on a give characteristic.
     * 启用或禁用一个给定特性的指示
     * @param characteristic Characteristic to act on.
     * @param enabled        If true, enable indications. False otherwise.
     */
    public void setCharacteristicIndication(
            BluetoothGattCharacteristic characteristic, boolean enabled) {
        String serviceUUID = characteristic.getService().getUuid().toString();

        String characteristicUUID = characteristic.getUuid().toString();

        Log.i("==TAG==",serviceUUID+"   "+characteristicUUID);

        for(BluetoothGatt mBluetoothGatt:connectionQueue){

            if (mBluetoothAdapter == null || mBluetoothGatt == null) {
                return;
            }

            if (characteristic.getDescriptor(UUID
                    .fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG)) != null) {
                if (enabled == true) {
                    BluetoothGattDescriptor descriptor = characteristic
                            .getDescriptor(UUID
                                    .fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                    descriptor
                            .setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                    mBluetoothGatt.writeDescriptor(descriptor);

                } else {
                    BluetoothGattDescriptor descriptor = characteristic
                            .getDescriptor(UUID
                                    .fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
                    descriptor
                            .setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                    mBluetoothGatt.writeDescriptor(descriptor);

                }
            }
            mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        }
    }


}

其中我里面用了一些外部的方法代码如下

/**
* Class used for parsing Health temperature related information
* 用于解析温度相关信息的类
*/

public class HTMParser {

    private static ArrayList<String> mTempInfo = new ArrayList<String>();

    //Byte character format
    private static final String BYTE_CHAR_FORMAT = "%02X ";

    //Switch case Constants
    private static final int CASE_ARMPIT = 1;
    private static final int CASE_BODY = 2;
    private static final int CASE_EAR_LOBE = 3;
    private static final int CASE_FINGER = 4;
    private static final int CASE_GIT = 5;
    private static final int CASE_MOUTH = 6;
    private static final int CASE_RECTUM = 7;
    private static final int CASE_TYMPANUM = 8;
    private static final int CASE_TOE = 9;
    private static final int CASE_TOE_REP = 10;

    /**
     * Get the thermometer reading
     * 温度计的读数
     *
     * @param characteristic
     * @return
     */
    public static String getHealthThermo(
            BluetoothGattCharacteristic characteristic, Context context) {
        String tempUnit = "";
        // For all other profiles, writes the data formatted in HEX.
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            byte flagByte = data[0];
            if ((flagByte & 0x01) != 0) {
                tempUnit = context.getString(R.string.tt_fahren_heit);
            } else {
                tempUnit = context.getString(R.string.tt_celcius);
            }
            for (byte byteChar : data)
                stringBuilder.append(String.format(BYTE_CHAR_FORMAT, byteChar));
        }
        final float temperature = characteristic.getFloatValue(BluetoothGattCharacteristic.FORMAT_FLOAT, 1);

        //Logger.i("tempRate " + temperature);

        String ss = temperature+","+tempUnit;
        //mTempInfo.add(1, tempUnit);
        return ss;
    }

    /**
     * Get the thermometer sensor location
     *
     * @param characteristic
     * @return
     */
    public static String getHealthThermoSensorLocation(
            BluetoothGattCharacteristic characteristic, Context context) {
        String healthTherSensorLocation = "";
        final byte[] data = characteristic.getValue();
        if (data != null && data.length > 0) {
            final StringBuilder stringBuilder = new StringBuilder(data.length);
            for (byte byteChar : data)
                stringBuilder.append(String.format(BYTE_CHAR_FORMAT, byteChar));
            int healthBodySensor = Integer.valueOf(stringBuilder.toString()
                    .trim());
            switch (healthBodySensor) {
                case CASE_ARMPIT:
                //这个R.string.armpit 里面就是这个airpit的英文意思
                    healthTherSensorLocation = context.getString(R.string.armpit);
                    break;
                case CASE_BODY:
                    healthTherSensorLocation = context.getString(R.string.body);
                    break;
                case CASE_EAR_LOBE:
                    healthTherSensorLocation = context.getString(R.string.ear);
                    break;
                case CASE_FINGER:
                    healthTherSensorLocation = context.getString(R.string.finger);
                    break;
                case CASE_GIT:
                    healthTherSensorLocation = context.getString(R.string.intestine);
                    break;
                case CASE_MOUTH:
                    healthTherSensorLocation = context.getString(R.string.mouth);
                    break;
                case CASE_RECTUM:
                    healthTherSensorLocation = context.getString(R.string.rectum);
                    break;
                case CASE_TYMPANUM:
                    healthTherSensorLocation = context.getString(R.string.tympanum);
                    break;
                case CASE_TOE:
                    healthTherSensorLocation = context.getString(R.string.toe_1);
                    break;
                case CASE_TOE_REP:
                    healthTherSensorLocation = context.getString(R.string.toe_2);
                    break;
                default:
                    healthTherSensorLocation = context.getString(R.string.reserverd);
                    break;
            }

        }
        return healthTherSensorLocation;
    }
}

8.总结:
蓝牙连接最主要的是要掌握 BluetoothLeService这个类里面的内容,主要包扣BluetoothGattCallback 回调
这里面是处理蓝牙数据的核心,包扣连接设备回调 断开设备回调 发现服务回调 发现数据回调。多台连接蓝牙设备的时候 把BluetoothGatt 放到一个List里面去。断开的时候也要移次的移除掉 list里面的BluetoothGatt数据。

源码下载地址 http://download.csdn.net/detail/a1989214/9709664

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

面包超人吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值