android BLE 实践

1、 权限和相关属性这是最基本的啦

<uses-featureandroid:name="android.hardware.bluetooth_le"android:required="true"/>

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

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


android 6以后还需要增加动态权限申请 不然无法获取蓝牙设备
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

2、初始化蓝牙

private void initBluetooth() {
             BluetoothManager mBluetoothManager = (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
             if (mBluetoothManager != null) {
                       BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
                           if (mBluetoothAdapter != null) {
                                     if (!mBluetoothAdapter.isEnabled()) {
                                          mBluetoothAdapter.enable();  //打开蓝牙
                             }
                     }
               }
   }

3、获取本地ble对象(BluetoothAdapter),它对应本地Android设备的蓝牙模块,可能这么称呼为本地ble对象不太准确,但我老人家开心这么称呼。从此段代码开始可以把这些有关ble通信的代码写到一个class中当做一个ble工具class,以便代码清晰查看和方便调用。这里我们就当这个工具类叫BleManager

相关API参考如下:

BluetoothManager:从名字可以看出是用来管理蓝牙设备的,用它来获取BluetoothAdapter;
BluetoothAdapter:蓝牙适配器,针对蓝牙模块的操作,比如:关闭,打开,扫描等;
LeScanCallback:在蓝牙扫描过程中,发现一个设备,就会回调一次;
BluetoothDevice:代表一个远程的蓝牙设备
BluetoothGatt:代表一个Bluetooth GATT Profile,用来控制蓝牙开关,和特征的读写等;
BluetoothGattCallback:这个可就厉害了,针对蓝牙的连接状态,读写等操作,这里都会有相应的回调;
BluetoothGattService:表示一个服务;
BluetoothGattCharacteristic:表示一个特征;
BluetoothGattDescriptor:表示一个描述;

private BluetoothAdapter mBluetoothAdapter; 

private BluetoothDevice mBluetoothDevice; 

private BluetoothGatt mBluetoothGatt;

private boolean isScanning = false;

private BleManager(Context context) {
           this.mContext = context;
           BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);  //BluetoothManager只在android4.3以上有
           if (bluetoothManager == null) {
                       TLog.e(TAG, "Unable to initialize BluetoothManager.");
                        return;
           }

          mBluetoothAdapter = bluetoothManager.getAdapter();
	}

4、既然获得了BluetoothAdapter对象,那么接下来就可以搜索ble设备了,这时就需要用到BluetoothAdapter的startLeScan()这个方法了

public void startLeScan() {
        if (mBluetoothAdapter == null) {
            return;
        }

        if (isScanning) {
            return;
        }
        isScanning = true;

        mBluetoothAdapter.startLeScan(mLeScanCallback);   //此mLeScanCallback为回调函数

        mHandler.sendEmptyMessageDelayed(STOP_LESCAN, 10000);  //这个搜索10秒,如果搜索不到则停止搜索
    }

在4.3之前的api是通过注册广播来处理搜索时发生的一些事件,而支持ble的新的api中,是通过回调的方式来处理的,而mLeScanCallback就是一个接口对象

private LeScanCallback mLeScanCallback = new LeScanCallback() {
    @Override
          public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
                   TLog.i(TAG, "onLeScan() DeviceName------>"+device.getName());  //在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
                   if(device.getName() == null){  
                           return;
                   }
                  if (device.getName().contains("Ble_Name")) {    //判断是否搜索到你需要的ble设备
                             TLog.i(TAG, "onLeScan() DeviceAddress------>"+device.getAddress());
                             mBluetoothDevice = device;   //获取到周边设备
                             stopLeScan();   //1、当找到对应的设备后,立即停止扫描;2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。

                             connect();  //连接
                 } 
      }
	};

  private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case STOP_LESCAN:
                    T.showLong(mContext,         mContext.getResources().getString(R.string.msg_connect_failed));
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    broadcastUpdate(Config.ACTION_GATT_DISCONNECTED);
                    isScanning = false;
                    TLog.i(TAG, "Scan time is up");
                    break;
            }
        };
    };

5、搜索到当然就是连接了,就是上面那个connect()方法了

public boolean connect() {
       if (mBluetoothDevice == null) {
       TLog.i(TAG, "BluetoothDevice is null.");
       return false;
	}

//两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server

  mBluetoothGatt =mBluetoothDevice.connectGatt(mContext,false,mGattCallback);  //mGattCallback为回调接口

if(mBluetoothGatt !=null)

    {

        if (mBluetoothGatt.connect()) {
            TLog.d(TAG, "Connect succeed.");
            return true;
        } else {
            TLog.d(TAG, "Connect fail.");
            return false;
        }
    } else

    {
        TLog.d(TAG, "BluetoothGatt null.");
        return false;
    }

}


    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                gatt.discoverServices(); //执行到这里其实蓝牙已经连接成功了

                TLog.i(TAG, "Connected to GATT server.");
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                if (mBluetoothDevice != null) {
                    TLog.i(TAG, "重新连接");
                    connect();
                } else {
                    TLog.i(TAG, "Disconnected from GATT server.");
                }
            }
        }


        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                TLog.i(TAG, "onServicesDiscovered");
                getBatteryLevel();  //获取电量
            } else {
                TLog.i(TAG, "onServicesDiscovered status------>" + status);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            TLog.d(TAG, "onCharacteristicRead------>" + Utils.bytesToHexString(characteristic.getValue()));

//判断UUID是否相等
            if (Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals(characteristic.getUuid().toString())) {
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            TLog.d(TAG, "onCharacteristicChanged------>" + Utils.bytesToHexString(characteristic.getValue()));

//判断UUID是否相等
            if (Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals(characteristic.getUuid().toString())) {
            }
        }

        //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发onCharacteristicWrite
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            TLog.d(TAG, "status = " + status);
            TLog.d(TAG, "onCharacteristicWrite------>" + Utils.bytesToHexString(characteristic.getValue()));
        }
    };


    public void getBatteryLevel() {
        BluetoothGattCharacteristic batteryLevelGattC = getCharcteristic(
                Values.UUID_KEY_BATTERY_LEVEL_SERVICE, Values.UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS);
        if (batteryLevelGattC != null) {
            readCharacteristic(batteryLevelGattC);
            setCharacteristicNotification(batteryLevelGattC, true); //设置当指定characteristic值变化时,发出通知。
        }
    }

6、获取服务与特征

   //a.获取服务

    public BluetoothGattService getService(UUID uuid) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            TLog.e(TAG, "BluetoothAdapter not initialized");
            return null;
        }
        return mBluetoothGatt.getService(uuid);
    }

//b.获取特征

    private BluetoothGattCharacteristic getCharcteristic(String serviceUUID, String characteristicUUID) {

//得到服务对象
        BluetoothGattService service = getService(UUID.fromString(serviceUUID));  //调用上面获取服务的方法

        if (service == null) {
            TLog.e(TAG, "Can not find 'BluetoothGattService'");
            return null;
        }

//得到此服务结点下Characteristic对象
        final BluetoothGattCharacteristic gattCharacteristic = service.getCharacteristic(UUID.fromString(characteristicUUID));
        if (gattCharacteristic != null) {
            return gattCharacteristic;
        } else {
            TLog.e(TAG, "Can not find 'BluetoothGattCharacteristic'");
            return null;
        }
    }


//获取数据

    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            TLog.e(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
    }


    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            TLog.e(TAG, "BluetoothAdapter not initialized");
            return false;
        }
        return mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    }

7、写入数据,在上面的方法中我们已经得到了设备服务和服务里的特征characteristic,那么就可以对这个特征写入或者说是赋值

public void write(byte[] data) {   //一般都是传byte
        //得到可写入的characteristic Utils.isAIRPLANE(mContext) && 
        if (!mBleManager.isEnabled()) {
            TLog.e(TAG, "writeCharacteristic 开启飞行模式");
            //closeBluetoothGatt();
            isGattConnected = false;
            broadcastUpdate(Config.ACTION_GATT_DISCONNECTED);
            return;
        }
        BluetoothGattCharacteristic writeCharacteristic = getCharcteristic(Values.UUID_KEY_SERVICE, Values.UUID_KEY_WRITE);  //这个UUID都是根据协议号的UUID
        if (writeCharacteristic == null) {
            TLog.e(TAG, "Write failed. GattCharacteristic is null.");
            return;
        }
        writeCharacteristic.setValue(data); //为characteristic赋值
        writeCharacteristicWrite(writeCharacteristic);

    }


    public void writeCharacteristicWrite(BluetoothGattCharacteristic characteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            TLog.e(TAG, "BluetoothAdapter not initialized");
            return;
        }
        TLog.e(TAG, "BluetoothAdapter 写入数据");
        boolean isBoolean = false;
        isBoolean = mBluetoothGatt.writeCharacteristic(characteristic);
        TLog.e(TAG, "BluetoothAdapter_writeCharacteristic = " + isBoolean);  //如果isBoolean返回的是true则写入成功
    }

8、写到这其实基本差不多了,最后再就是在activity中调用了,其实在调用的时候直接在需要搜索蓝牙的activity调用startLeScan()这个方法就可以了,至于搜索到的结果也显示在这个方法里面了,找到了对应的设备名称然后再连接,对于中间一系列的回调函数,startLeScan();  调用此方法,如果搜索到有设备则自然的去连接它了,到时候连接时回回调mGattCallback 这个回调函数,如果成功你可以发送一个广播出来提醒用户蓝牙与设备连接成功;

 搜索成功后,你就可以根据你的需要写入信息传送了。简单说说,就是你在一个button事件中调用上面的write(byte[] byte)这个方法,对于里面的参数byte就是根据你们所设置的byte了,最后写入的成功与否就看writeCharacteristicWrite这个方法下面的返回值是true还是false了,true表示成成功。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值