zoukankan      html  css  js  c++  java
  • 关于BLE的android开发,你该知道的一切

     

    一、关键概念:

    Generic Attribute Profile (GATT)
     
    通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
     
    Attribute Protocol (ATT)
     
    GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。
    每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
     
    Characteristic
    Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。
     
    Descriptor
    对Characteristic的描述,例如范围、计量单位等。
     
    Service
    Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,
    它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。
     

    二、角色和职责:

    Android设备与BLE设备交互有两组角色:
     
    中心设备和外围设备(Central vs. peripheral);
    GATT server vs. GATT client.
     
    Central vs. peripheral:
    中心设备和外围设备的概念针对的是BLE连接本身。
    Central角色负责scan advertisement。而peripheral角色负责make advertisement。
     
    GATT server vs. GATT client:
    这两种角色取决于BLE连接成功后,两个设备间通信的方式。
     
    举例说明:
    现有一个活动追踪的BLE设备和一个支持BLE的Android设备。
    Android设备支持Central角色,而BLE设备支持peripheral角色。
    创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
     
    当连接建立后,它们之间就需要传输GATT数据。
    谁做server,谁做client,则取决于具体数据传输的情况。
    例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;
    而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。
     

    三、权限及feature:

     
    和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,
    如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:
     
    1. <uses-permission android:name="android.permission.BLUETOOTH"/>
      <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
     
    除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
     
    1. 1 <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
     
    按时required为true时,则应用只能在支持BLE的Android设备上安装运行
    required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature:
     
    1. 1 // Use this check to determine whether BLE is supported on the device. Then
      2 // you can selectively disable BLE-related features.
      3 if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
      4 Toast.makeText(this, R.string.ble_not_supported,Toast.LENGTH_SHORT).show();
      5 finish();
      6 }
     
     

    四、启动蓝牙:

     
    在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),
    另外要需要确认蓝牙是否打开。 
    如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。
     
    打开蓝牙的步骤:

    1、获取BluetoothAdapter

    BluetoothAdapter是Android系统中所有蓝牙操作都需要的,它对应本地Android设备的蓝牙模块,
    在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙操作了。
     
    获取BluetoothAdapter代码示例如下:
     
    1. // Initializes Bluetooth adapter.
      finalBluetoothManager bluetoothManager =
      (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
      mBluetoothAdapter = bluetoothManager.getAdapter();
     
     
    注:这里通过getSystemService获取BluetoothManager,
    再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API level 18)。
     

    2、判断是否支持蓝牙,并打开蓝牙

     
    获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。
    如果没打开,需要让用户打开蓝牙:
     
    1. privateBluetoothAdapter mBluetoothAdapter;
      ...
      // Ensures Bluetooth is available on the device and it is enabled. If not,
      // displays a dialog requesting user permission to enable Bluetooth.
      if(mBluetoothAdapter ==null||!mBluetoothAdapter.isEnabled()){
      Intent enableBtIntent =newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
      startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
      }
     
     

    五、搜索BLE设备:

     
     
    通过调用BluetoothAdapter的startLeScan()搜索BLE设备。
    调用此方法时需要传入 BluetoothAdapter.LeScanCallback参数。
    因此你需要实现 BluetoothAdapter.LeScanCallback接口,BLE设备的搜索结果将通过这个callback返回。
     
    由于搜索需要尽量减少功耗,因此在实际使用时需要注意:
     
    1、当找到对应的设备后,立即停止扫描;
    2、不要循环搜索设备,为每次搜索设置适合的时间限制。
     
    避免设备不在可用范围的时候持续不停扫描,消耗电量。
     
    搜索的示例代码如下:
    /**
    * Activity for scanning and displaying available BLE devices.
    */
    public class DeviceScanActivity extends ListActivity {
        private BluetoothAdapter mBluetoothAdapter;
        private boolean mScanning;
        private Handler mHandler;
        // Stops scanning after 10 seconds.
        private static final long SCAN_PERIOD = 10000;
        ...
        private void scanLeDevice(final boolean enable) {
            if (enable) {
                // Stops scanning after a pre-defined scan period.
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mScanning = false;
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    }
                }, SCAN_PERIOD);
                mScanning = true;
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            ...
        }
    ...
    }
     
     
    如果你只需要搜索指定UUID的外设,
    你可以调用 startLeScan(UUID[], BluetoothAdapter.LeScanCallback)方法。
    其中UUID数组指定你的应用程序所支持的GATT Services的UUID。
    BluetoothAdapter.LeScanCallback的实现示例如下:
    private LeDeviceListAdapter mLeDeviceListAdapter;
    ...
    // Device scan callback.
    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi,
                byte[] scanRecord) {
            runOnUiThread(new Runnable() {          
               @Override
               public void run() {
                   mLeDeviceListAdapter.addDevice(device);
                   mLeDeviceListAdapter.notifyDataSetChanged();
               }
           });
       }
    };
    1.  
     
    注意:搜索时,你只能搜索传统蓝牙设备或者BLE设备,两者完全独立,不可同时被搜索。
     

    六、连接GATT Server:

    两个设备通过BLE通信,首先需要建立GATT连接。
    这里我们讲的是Android设备作为client端,连接GATT Server。
    连接GATTServer,你需要调用BluetoothDevice的connectGatt()方法。此函数带三个参数:
    Context、autoConnect(boolean)和BluetoothGattCallback对象。调用示例:
     
    1. mBluetoothGatt = device.connectGatt(this,false, mGattCallback);
     
    函数成功,返回BluetoothGatt对象,它是GATT profile的封装。通过这个对象,我们就能进行GATT Client端的相关操作。BluetoothGattCallback用于传递一些连接状态及结果。
     
    BluetoothGatt常规用到的几个操作示例:
     
    connect() :连接远程设备。
    discoverServices() : 搜索连接设备所支持的service。
    disconnect():断开与远程设备的GATT连接。
    close():关闭GATT Client端。
    readCharacteristic(characteristic) :读取指定的characteristic。
    setCharacteristicNotification(characteristic, enabled) :设置当指定characteristic值变化时,发出通知。
    getServices() :获取远程设备所支持的services。
     
    等等。
     
    注:
    1、某些函数调用之间存在先后关系。例如首先需要connect上才能discoverServices。
    2、一些函数调用是异步的,需要得到的值不会立即返回,而会在BluetoothGattCallback的回调函数中返回。
    例如discoverServices与onServicesDiscovered回调,readCharacteristic与onCharacteristicRead回调,
    setCharacteristicNotification与onCharacteristicChanged回调等。
     
     
     
     
     

    声明:

    1.由于互联网数据的分享性,如果我发表的文章,来源于您的原创文章,且我没有注明,请邮件macouen@gmail.com说明。
    2.欢迎转载,但请注明文章原始出处。
      作者:Oak
      出处:http://www.cnblogs.com/oakMac/



  • 相关阅读:
    接口
    java基础
    java的反射
    按照字典序打印所有的字符串
    求幂的问题
    时间复杂度与空间复杂度
    孩子们的游戏(圆圈中最后剩下的数)
    约瑟夫环问题
    翻转单词顺序列
    复杂链表的复制
  • 原文地址:https://www.cnblogs.com/oakMac/p/4164607.html
Copyright © 2011-2022 走看看