安卓基於藍牙4.0的BLE開發

藍牙4.0分爲標準藍牙和低功耗藍牙(BLE),標準藍牙就是手機上常用的那種,低功能耗藍牙由於其具有最大化的待機時間、快速連接和低峯值的發送和接收特性,被廣泛用於智能手錶、智能手環等可穿戴設備上。

標準藍牙的的開發和BLE不同。標準藍牙連接裏有兩個角色一個是客戶端一個是服務器,當客戶端搜索到藍牙服務器後並與之配對後,才能通過UUID(這個是唯一的,服務器端必須與客戶端一致)建立socket,然後使用流像文件讀寫和網絡通信那樣傳輸數據就行了。在BLE裏,變成了中心設備(central)和外圍設備(peripheral),中心設備就是你的手機,外圍設備就是智能手環一類的東西。開發BLE的應用都得遵守Generic Attribute Profile (GATT),一個BLE藍牙設備包含多個service,每個service又包含多個characteristic。每個characteristic有一個value和多個descriptor,通過characteristic中心設備與外圍設備進行通信。descriptor顧名思義,包含了BLE設備的一些信息。不同service、characteristic和descriptor都有各自己唯一的UUID。想要跟BLE設備通信,首先通過UUID獲取目標服務,然後再通過UUID獲取characteristic,charateristic起着載體的作用,通過writeCharacteristic()和readCharacteristic(),可以寫入和讀出信息。每個characteristic都有一些自己的屬性,其中在property裏,說明了該characteristic的屬性,例如READ|WRITE|WRITE_NO_RESPONSE|NOTIFY。

在android 4.3中,谷歌發佈了官方的BLE開發的API,而在android 5.0後引入了新的API。所以在開發的時候,需要注意版本的兼容性。例如,minSdkVersion =13,targetSdkVersion = 19,而編譯環境compileSdkVersion 22,如果直接用4.3 API中提供的方法,會無法編譯,原因是minSdkVersion的版本低於18,其次,compileSdkVersion 大於21。針對這些問題,接下來,我會詳細說明BLE的開發。

1、權限

在AndroidManifest.xml里加入

<!-- 允許程序連接到已配對的藍牙設備 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 允許程序發現和配對藍牙設備 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

還需要

<!-- BLE需要 Android 5.0以前的權限-->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
<!-- BLE需要 Android 5.0之後的權限-->
<uses-feature android:name="android.bluetooth.le" android:required="false"/>

其中,required爲true時,則應用只能在支持BLE的Android設備上安裝運行;required爲false時,Android設備均可正常安裝運行,需要在代碼運行時判斷設備是否支持BLE feature。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

...

}

2、版本的兼容性問題

用@TargetApi註解的方式

因爲BLE的API需要基於android 18以上,所以需要

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class TestActivity extends BaseActivity {

又由於android 21的API不一樣,如果在android 22的編譯環境中使用舊的API,這樣編譯的API運行之後,調用舊的API方法是不會執行本應該實現的方法。所以需要判斷版本。例如:

private void initCallBack(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
        initScanCallBack();
    }else{
        initLeScanCallBack();
    }
}

3、獲取BluetoothAdapter

final BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
    Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
    finish();
    return;
}
//啓動藍牙
mBluetoothAdapter.enable();

4、獲取執行回調的ScanCallBack

Android 4.3 是

BluetoothAdapter.LeScanCallback leScanCallback;

通過startScan()方法掃描周圍的BLE設備。當搜索到目標設備或者搜索一定時間後通過BluetoothScanner的stopScan()方法停止搜索。

Android 5.0是

ScanCallback scanCallback;

BluetoothLeScanner scanner

scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();

通過scanner的startScan()方法掃描周圍的BLE設備。當搜索到目標設備或者搜索一定時間後通過scanner的stopScan()方法停止搜索。

5、從ScanCallBack的回調函數中獲取的廣播數據的解析

Android 4.3中,

leScanCallback = new BluetoothAdapter.LeScanCallback() {

    @Override
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
        runOnUiThread(new Runnable() {
            final iBeacon ibeacon = iBeaconClass.fromScanData(device, rssi, scanRecord);

            @Override
            public void run() {
                
            }
        });
    }
};

Android 5.0

scanCallback = new ScanCallback() {

    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        final iBeacon ibeacon = iBeaconClass.fromScanData(result.getDevice(),
                result.getRssi(), result.getScanRecord().getBytes());
       

    }

    @Override
    public void onScanFailed(int errorCode) {
        super.onScanFailed(errorCode);

        // a scan error occurred
    }
};

Android 4.3的scanRecord和 Android 5.0 ScanResult.getScanRecord().getBytes()攜帶了Beacon設備廣播的字符串,接下來,就是對字符串的解析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章