ble兼容Android 4 进行的部分优化

转载自[android BLE 编程详解](http://blog.csdn.net/qiyei2009/article/details/52026096 “博客”)

最近可穿戴设备发展的很火,而且蓝牙4.0 以上支持低功耗模式,因此,android4.3(API18)以上支持蓝牙BLE编程。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。下面介绍android 的BLE开发。

1.   基本概念介绍

  • BluetoothManager :管理蓝牙服务的一个类,主要用于得到一个蓝牙适配器BluetoothAdapter。
  • BluetoothAdapter类:代表了一个本地的蓝牙适配器。它是所有蓝牙交互的的入口点。利用它你可以发现其他蓝牙设备,查询绑定了的设备,使用已知的MAC地址实例化一个蓝牙设备和建立一个BluetoothServerSocket(作为服务器端)来监听来自其他设备的连接。 
  • BluetoothDevice类:代表了一个远端的蓝牙设备,使用它请求远端蓝牙设备连接或者获取远端蓝牙设备的名称、地址、种类和绑定状态。
  • BluetoothGatt类:符合BLE GATT协议,封装了与其他蓝牙设备通信功能的一个类。可以通过BluetoothDevice的connectGatt(Context, boolean, BluetoothGattCallback)得到其实例。
  • GATT(Generic Attribute Profile) 通用属性参数文件,通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。蓝牙 4.0特有。可以理解为一个规范文件。
  • ATT(Attribute Protocol) 属性协议。GATT是基于ATTProtocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics 和services的形式传输。
  • Service 服务。Characteristic的集合。例如一个service叫做“Heart RateMonitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement”的Characteristic
  • Characteristic 特性。Characteristic可以理解为一个数据类型,它包括1个value和0至多个Descriptor
  • Descriptor 对Characteristic的描述,例如范围、计量单位等,一个Descriptor包含一个Value

其中Service、Characteristic、Descriptor,这三部分是BLE的核心,都由UUID作为唯一标示符。一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY。

 

2.   BLE编程

1.      权限配置

由于android4.3及以上才支持BLE,因此需指定编译版本为targetSdkVersion大于等于18。并且需要在AndroidManifest.xml文件中配置如下所示的权限

  1. <uses-permissionandroid:nameuses-permissionandroid:name=“android.permission.BLUETOOTH”/>  
  2. <uses-permissionandroid:nameuses-permissionandroid:name=“android.permission.BLUETOOTH_ADMIN”/>  
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>

2.      编程步骤

1.获取BluetoothManager服务及BluetoothAdapter实例

BluetoothManager是系统管理蓝牙的一种服务,获取了BluetoothManager我们就可以通过其getAdapter()获取蓝牙适配器了。

  1. //1.获取蓝牙管理服务及BluetoothAdapter实例  
  2. mBluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);  
  3. mBluetoothAdapter = mBluetoothManager.getAdapter();  
  4. if (mBluetoothAdapter == null){  
  5.      return;  
  6. }  
       //1.获取蓝牙管理服务及BluetoothAdapter实例
       mBluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
       mBluetoothAdapter = mBluetoothManager.getAdapter();
       if (mBluetoothAdapter == null){
            return;
       }

2.打开蓝牙

         接下来调用BluetoothAdapter的isEnabled()判断蓝牙是否打开,未打开我们可以发送一个action为BluetoothAdapter.ACTION_REQUEST_ENABLE的intent来打开蓝牙。

  1. //2. 判断蓝牙是否打开,没有打开就打开  
  2. if (!mBluetoothAdapter.isEnabled()){  
  3.      Intent intent = newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
  4.     startActivityForResult(intent,REQUEST_ENABLE_BT);  
  5. }  
       //2. 判断蓝牙是否打开,没有打开就打开
       if (!mBluetoothAdapter.isEnabled()){
            Intent intent = newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
           startActivityForResult(intent,REQUEST_ENABLE_BT);
       }

         这时界面上回弹出一个对话框提示我们打开蓝牙,打开成功后会回调Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法,我们可以在里面提示一些信息。比如提示蓝牙已经打开等。

  1. @Override  
  2. protected void onActivityResult(int requestCode, int resultCode, Intentdata) {  
  3.     super.onActivityResult(requestCode, resultCode, data);  
  4.   
  5.     if (resultCode != RESULT_OK){  
  6.          return;  
  7.     }  
  8.     if (requestCode == REQUEST_ENABLE_BT){  
  9.          Toast.makeText(this,“蓝牙已开启”,Toast.LENGTH_LONG).show();  
  10.     }  
  11. }  
   @Override
   protected void onActivityResult(int requestCode, int resultCode, Intentdata) {
       super.onActivityResult(requestCode, resultCode, data);

       if (resultCode != RESULT_OK){
            return;
       }
       if (requestCode == REQUEST_ENABLE_BT){
            Toast.makeText(this,"蓝牙已开启",Toast.LENGTH_LONG).show();
       }
   }

        

3.扫描周围的BLE蓝牙设备

         扫描BLE蓝牙设备,对于4.3以上的系统,直接调用startLeScan(BluetoothAdapter.LeScanCallbackcallback)即可扫描出BLE设备,在callback中会回调。但是对于5.0以上的系统,android添加了新的API,原有的startLeScan(BluetoothAdapter.LeScanCallback callback)已经被废弃,在5.0以上的系统中是使用BluetoothLeScanner的startScan(ScanCallbackcallback),回调也是ScanCallback了。

  1. /** 
  2.  * 扫描Bluetooth LE 
  3.  * @param enable 
  4.  */  
  5. private void scanBleDevice(boolean enable){  
  6.     //android 5.0 以前  
  7.     if (Build.VERSION.SDK_INT < 21){  
  8.         if (enable){  
  9.             mHandler.postDelayed(new Runnable() {  
  10.                 @Override  
  11.                 public void run() {  
  12.                     mScaning = false;  
  13.                     mBluetoothAdapter.stopLeScan(mLeScanCallback);  
  14.                 }  
  15.             },SCAN_SECOND);  
  16.             mScaning = true;  
  17.             mBluetoothAdapter.startLeScan(mLeScanCallback);  
  18.         } else {  
  19.             mScaning = false;  
  20.             mBluetoothAdapter.stopLeScan(mLeScanCallback);  
  21.         }  
  22.     } else {  
  23.         scanner = mBluetoothAdapter.getBluetoothLeScanner();  
  24.         scanner.startScan(mScanCallback);  
  25.         mHandler.postDelayed(new Runnable() {  
  26.             @Override  
  27.             public void run() {  
  28.                 scanner.stopScan(mScanCallback);  
  29.             }  
  30.         },SCAN_SECOND);  
  31.     }  
  32. }  
    /**
     * 扫描Bluetooth LE
     * @param enable
     */
    private void scanBleDevice(boolean enable){
        //android 5.0 以前
        if (Build.VERSION.SDK_INT < 21){
            if (enable){
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mScaning = false;
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    }
                },SCAN_SECOND);
                mScaning = true;
                mBluetoothAdapter.startLeScan(mLeScanCallback);
            } else {
                mScaning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
            }
        } else {
            scanner = mBluetoothAdapter.getBluetoothLeScanner();
            scanner.startScan(mScanCallback);
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    scanner.stopScan(mScanCallback);
                }
            },SCAN_SECOND);
        }
    }

 扫描的回调如下:

  1. //sacn扫描回调 5.0以上用  
  2. private ScanCallback mScanCallback = new ScanCallback() {  
  3.     @Override  
  4.     public void onScanResult(int callbackType, ScanResult result) {  
  5.          BluetoothDevice device =result.getDevice();  
  6.          if (device != null){  
  7.              //过滤掉其他设备  
  8.              if (device.getName() != null&& device.getName().startsWith(“WINPOS”)){  
  9.                  BLEDevice bleDevice = newBLEDevice(device.getName(),device.getAddress());  
  10.                  if(!mBLEDeviceList.contains(bleDevice)){  
  11.                     mBLEDeviceList.add(bleDevice);  
  12.                     showBluetoothLeDevice(bleDevice);  
  13.                  }  
  14.              }  
  15.          }  
  16.     }  
  17.   
  18.     @Override  
  19.     public void onBatchScanResults(List<ScanResult> results) {  
  20.   
  21.         Log.d(TAG,”onBatchScanResults”);  
  22.     }  
  23.   
  24.     @Override  
  25.     public void onScanFailed(int errorCode) {  
  26.         Log.d(TAG,”onScanFailed”);  
  27.     }  
  28. };  
  29.   
  30.   
  31. //4.3以上  
  32. private BluetoothAdapter.LeScanCallback mLeScanCallback = newBluetoothAdapter.LeScanCallback() {  
  33.     @Override  
  34.     public void onLeScan(final BluetoothDevice bluetoothDevice, int i,byte[] bytes) {  
  35.   
  36.          if (bluetoothDevice != null){  
  37.              //过滤掉其他设备  
  38.              if (bluetoothDevice.getName()!= null && bluetoothDevice.getName().startsWith(“WINPOS”)){  
  39.                  BLEDevice bleDevice = newBLEDevice(bluetoothDevice.getName(),bluetoothDevice.getAddress());  
  40.                  if(!mBLEDeviceList.contains(bleDevice)){  
  41.                     mBLEDeviceList.add(bleDevice);  
  42.                     showBluetoothLeDevice(bleDevice);  
  43.                  }  
  44.              }  
  45.          }  
  46.     }  
  47. };  
   //sacn扫描回调 5.0以上用
   private ScanCallback mScanCallback = new ScanCallback() {
       @Override
       public void onScanResult(int callbackType, ScanResult result) {
            BluetoothDevice device =result.getDevice();
            if (device != null){
                //过滤掉其他设备
                if (device.getName() != null&& device.getName().startsWith("WINPOS")){
                    BLEDevice bleDevice = newBLEDevice(device.getName(),device.getAddress());
                    if(!mBLEDeviceList.contains(bleDevice)){
                       mBLEDeviceList.add(bleDevice);
                       showBluetoothLeDevice(bleDevice);
                    }
                }
            }
       }

       @Override
       public void onBatchScanResults(List<ScanResult> results) {

           Log.d(TAG,"onBatchScanResults");
       }

       @Override
       public void onScanFailed(int errorCode) {
           Log.d(TAG,"onScanFailed");
       }
   };


   //4.3以上
   private BluetoothAdapter.LeScanCallback mLeScanCallback = newBluetoothAdapter.LeScanCallback() {
       @Override
       public void onLeScan(final BluetoothDevice bluetoothDevice, int i,byte[] bytes) {

            if (bluetoothDevice != null){
                //过滤掉其他设备
                if (bluetoothDevice.getName()!= null && bluetoothDevice.getName().startsWith("WINPOS")){
                    BLEDevice bleDevice = newBLEDevice(bluetoothDevice.getName(),bluetoothDevice.getAddress());
                    if(!mBLEDeviceList.contains(bleDevice)){
                       mBLEDeviceList.add(bleDevice);
                       showBluetoothLeDevice(bleDevice);
                    }
                }
            }
       }
   };

         这里我预先定义了BLEDevice类,用来表示BLE设备。定义如下:

  1. public class BLEDevice {  
  2.    private String name;  
  3.    private String mac;  
  4.    public BLEDevice(String name, String mac) {  
  5.        this.name = name;  
  6.        this.mac = mac;  
  7.    }  
  8.    
  9.    public String getName() {  
  10.        return name;  
  11.    }  
  12.    
  13.    public void setName(String name) {  
  14.        this.name = name;  
  15.    }  
  16.    
  17.    public String getMac() {  
  18.        return mac;  
  19.    }  
  20.    
  21.    public void setMac(String mac) {  
  22.        this.mac = mac;  
  23.    }  
  24.    
  25.    @Override  
  26.    public boolean equals(Object o) {  
  27.    
  28.        return !TextUtils.isEmpty(this.mac) &&!TextUtils.isEmpty(((BLEDevice)o).mac)  
  29.                 &&this.mac.equals(((BLEDevice) o).getMac());  
  30.    
  31.    }  
  32. }  
public class BLEDevice {
   private String name;
   private String mac;
   public BLEDevice(String name, String mac) {
       this.name = name;
       this.mac = mac;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String getMac() {
       return mac;
   }

   public void setMac(String mac) {
       this.mac = mac;
   }

   @Override
   public boolean equals(Object o) {

       return !TextUtils.isEmpty(this.mac) &&!TextUtils.isEmpty(((BLEDevice)o).mac)
                &&this.mac.equals(((BLEDevice) o).getMac());

   }
}

         扫描时我将扫描到的设备添加到List<BLEDevice> mBLEDeviceList中并显示出来。

  1. /** 
  2.  * 显示BLE设备 
  3.  * @param device 
  4.  */  
  5. private void showBluetoothLeDevice(BLEDevice device){  
  6.     if (device == null){  
  7.          showToast(”没有发现BLE设备”);  
  8.          return;  
  9.     }  
  10.     mTextView.append(device.getName() + ”   ” + device.getMac() + “\n”);  
  11. }  
   /**
    * 显示BLE设备
    * @param device
    */
   private void showBluetoothLeDevice(BLEDevice device){
       if (device == null){
            showToast("没有发现BLE设备");
            return;
       }
       mTextView.append(device.getName() + "   " + device.getMac() + "\n");
   }

4.获取远程设备,连接GATT服务



                </div>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值