Android藍牙開發系列文章-掃不到藍牙設備,你的姿勢對了嗎?

在寫《Android藍牙開發系列文章-藍牙音箱連接》時,計劃細化出兩篇文章,分別是:

關於藍牙設備類型分類的,這個已經完成了,閱讀請點擊《Android藍牙開發系列文章-藍牙設備類型知多少?》

今天我們要完成的是另外一篇:如何掃描藍牙設備,怎麼快速的、準確的掃描設備。

你也許會問,什麼叫準確的掃描設備?難道我們在掃描的時候可以指定要掃描設備嗎?

答案是肯定的,讓我們慢慢講來~

目錄

1.姿勢一:掃描經典藍牙

2.姿勢二:用過時的接口掃描低功耗藍牙

3.姿勢三:用時髦的接口掃描低功耗藍牙

4.總結



1.姿勢一:掃描經典藍牙

《Android藍牙開發系列文章-藍牙設備類型知多少?》中,我們沒有提“經典藍牙”和“低功耗藍牙”的事兒,這裏怎麼又冒出了這兩個概念?

其實,我們在上一節說的藍牙設備類型,是從功能角度出發進行定義的一種概念。就是說這個藍牙設備是個音箱,還是一個鼠標。

而今天說的這兩個類型是比較專業化的概念,一般人,我是不告訴他的,誰讓你關注了我呢,來,讓我告訴你。

經典藍牙設備:又稱爲傳統藍牙設備,英文爲Classic Bluetooth,主要用於傳輸數據量比較大的功能傳輸,例如,藍牙音箱。

低功耗藍牙設備:英文爲Bluetooth Low Energy,最大的特點是功耗的降低,主要用於實時性要求較高、但數據量不大的產品中,例如,藍牙燈、藍牙手環等等。

講完了這兩個概念,我們再來講兩個: 單模設備、雙模設備。

單模設備:是指進具有經典藍牙設備功能或者低功耗藍牙功能的設備。例如,僅僅具有心率測量功能的手環。

雙模設備:是指同時具有經典藍牙設備功能和低功耗藍牙功能的設備。例如,既具有心率測量功能,又具有通話功能的手環。再例如,我們現在智能電視的藍牙遙控器(語音功能使用的是經典藍牙,按鍵功能使用的是低功耗藍牙)。再例如,小米的小愛音箱,它就是典型的雙模設備,具有兩個mac地址。

在這裏要說一下,不是所有的雙模設備都是兩個mac地址,有的也僅是一個mac地址。我抽空會再寫一下藍牙mac 地址的分類(如果一直這樣細化下去,不知道我的藍牙專題是否要寫100+篇?),不知道你是否期待?

講完了概念,我們接着講“姿勢一”,如果你讀過我之前寫的藍牙音箱連接的文章,你應該知道了經典藍牙設備如何掃描了。

調用BluetoothAdapter::startDiscovery()接口,然後接受廣播,從廣播中解析出你想要的設備。這種方法掃描出的藍牙設備不僅僅是隻能掃描到經典藍牙,也會掃描到低功耗藍牙。如果你要掃描經典藍牙的話,只能忍受這一個弊端了,因爲沒有別的招了。

如想了解經典藍牙設備的掃描,請移步《Android藍牙開發系列文章-藍牙音箱連接》。我在這裏就不再講解一遍了。

2.姿勢二:用過時的接口掃描低功耗藍牙

下面開始講一下經典藍牙設備的掃描。

第一步,要先申請必要的權限,

    <!--藍牙權限-->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!--BLE掃描權限-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <!--藍牙ble feature檢查,只有在由此feature的設備上才能安裝本應用-->
    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

我在寫demo的過程中發現,靜態申請了BLE掃描的權限沒有生效,沒有掃描到任何設備,經過上網百度獲悉,從Android6.0開始需要動態申請位置權限,所以有了如下一段代碼:

 private void requestPermission() {
        //動態申請是否有必要看sdk版本哈
        if (Build.VERSION.SDK_INT < 23){return;}
        //判斷是否有權限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //請求權限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
        }

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            //請求權限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
        }
    }

 先獲取BluetoothAdapter對象,然後調用BluetoothAdapter::startLeScan(LeScanCallback callback)發起設備掃描。

掃碼到的設備都會在onLeScan()中拿到。

        //藍牙編程千古不變:第一行代碼
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Log.d(TAG, "mBluetoothAdapter = " + mBluetoothAdapter);
        //設備回調,掃描到的設備都在onLeScan()中拿到
        private static LeScanCallback mLeScanCallback = new LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
                if(device == null || device.getName() == null || device.getAddress() == null)             {
                    return;
                }
                Log.d(TAG, "onLeScan(), device = " + device.getName() +  "mac = " + device.getAddress() + "rssi = " + rssi);
                for (int i = 0; i < scanRecord.length; i++) {
                    Log.d(TAG, "onLeScan(), device = " + device.getName() + "content = " + scanRecord[i]);
                }
            }
        };
        //調用BluetoothAdapter.startLeScan(LeScanCallback callback)發起設備掃描
        private void startBleScan1() {
            boolean ret = mBluetoothAdapter.startLeScan(mLeScanCallback);
            Log.d(TAG, "startBtScan(),ret = " + ret);
        }

運行一下我們的demo,看一下掃描結果,家裏的唯一一個低功耗設備,藍牙體脂秤,被掃描出來了。

03-16 21:07:32.130 9909-9909/com.atlas.devicefinder D/MainActivity: mBluetoothAdapter = android.bluetooth.BluetoothAdapter@ddeeda9
03-16 21:07:32.131 9909-9909/com.atlas.devicefinder D/MainActivity: mBluetoothLeScanner = android.bluetooth.le.BluetoothLeScanner@e0adf2e
03-16 21:07:34.947 9909-9909/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e036fde VFED..C.. ...P.... 0,0-426,144 #7f070042 app:id/bt_start_blescan1}
03-16 21:07:34.970 9909-9909/com.atlas.devicefinder D/MainActivity: startBtScan(),ret = true
03-16 21:07:40.498 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9mac = 08:7C:BE:48:65:ADrssi = -78
03-16 21:07:40.499 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 10
03-16 21:07:40.501 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 9
03-16 21:07:40.503 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 49
03-16 21:07:40.505 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 76
03-16 21:07:40.508 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 83
03-16 21:07:40.509 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 95
03-16 21:07:40.512 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 87
03-16 21:07:40.513 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 95
03-16 21:07:40.515 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 57
03-16 21:07:40.517 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 0
03-16 21:07:40.518 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 0
03-16 21:07:40.519 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 2
03-16 21:07:40.521 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 1
03-16 21:07:40.524 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 6
03-16 21:07:40.526 9909-9909/com.atlas.devicefinder D/MainActivity: onLeScan(), device = 1LS_W_9content = 5

因爲家裏只有一個低功耗藍牙設備,所以沒有掃描出來其他設備(這可不是因爲這個接口具有掃描指定設備的功能哈,因爲它並沒有,不然怎麼被廢棄了呢)。 

3.姿勢三:用時髦的接口掃描低功耗藍牙

這裏將一個時髦的藍牙掃描接口,BluetoothLeScanner::startScan()。這個接口的定義如下所示,第一個參數就是對掃描到的設備的過濾條件,第二個參數表示的是對本次掃描的設置,第三個參數用於接收掃描結果(如果有過濾條件,則是經過濾後的設備)。

   /**
     * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
     * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
     * resumed when screen is turned on again. To avoid this, do filetered scanning by
     * using proper {@link ScanFilter}.
     * <p>
     * An app must hold
     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
     * in order to get results.
     *
     * @param filters {@link ScanFilter}s for finding exact BLE devices.
     * @param settings Settings for the scan.
     * @param callback Callback used to deliver scan results.
     * @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
    public void startScan(List<ScanFilter> filters, ScanSettings settings,
            final ScanCallback callback) {
        startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
    }

我們先不設置過濾條件,看一下該方法如何使用:

先獲取BluetoothLeScanner對象,然後調用其startScan(ScanCallback callback)方法,看到沒,就只有一個回調參數。

    //先獲取BluetoothLeScanner對象
    private BluetoothLeScanner mBluetoothLeScanner = null;
    mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
    private void startBleScan2() {
        mBluetoothLeScanner.startScan(mScanCallback);
    }
    
    //回調接口
    private static ScanCallback mScanCallback = new ScanCallback() {
        //每掃描到一個BLE設備,就接收到一次回調
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            Log.d(TAG, "onScanResult, result = " + result);

        }
        //批量回調接口
        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            Log.d(TAG, "onBatchScanResults");

        }
        //掃描失敗的回調,可以根據失敗的原因執行不同策略,例如,重新掃描或者
        //先停止當前掃描,再重新發起掃描
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.d(TAG, "onScanFailed, errorCode = " + errorCode);
        }
    };

我們這樣搞,會得到一個什麼樣的掃描結果呢?可以看到除了我家的體脂秤,也掃描到了另外一個BLE設備(反正不是俺家的,不知道誰的)。我還特意把我家的藍牙音箱打開了,結果可想而知:掃不到~

03-15 20:41:37.946 10425-10425/com.atlas.devicefinder D/MainActivity: mBluetoothAdapter = android.bluetooth.BluetoothAdapter@bc4da35
03-15 20:41:37.947 10425-10425/com.atlas.devicefinder D/MainActivity: mBluetoothLeScanner = android.bluetooth.le.BluetoothLeScanner@74b3eca
03-15 20:41:41.476 10425-10425/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e98ee7a VFED..C.. ...P.... 0,288-426,432 #7f070043 app:id/bt_start_blescan2}
03-15 20:41:47.466 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-97, mTimestampNanos=86214200338022}
03-15 20:41:52.332 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86219088416145}
03-15 20:41:56.438 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86223197857185}
03-15 20:41:58.892 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-93, mTimestampNanos=86225651024476}
03-15 20:42:04.863 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-95, mTimestampNanos=86231621502599}
03-15 20:42:05.935 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86232694169265}
03-15 20:42:12.296 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-71, mTimestampNanos=86239051067804}
03-15 20:42:12.436 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-94, mTimestampNanos=86239196387388}
03-15 20:42:12.712 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-98, mTimestampNanos=86239469748846}
03-15 20:42:17.346 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-87, mTimestampNanos=86244101039261}
03-15 20:42:17.616 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-87, mTimestampNanos=86244372349886}
03-15 20:42:22.388 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-42, mTimestampNanos=86249143803842}
03-15 20:42:22.657 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-42, mTimestampNanos=86249413593842}
03-15 20:42:27.374 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-50, mTimestampNanos=86254130413424}
03-15 20:42:27.421 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-96, mTimestampNanos=86254178738632}
03-15 20:42:27.642 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-38, mTimestampNanos=86254399760298}
03-15 20:42:27.693 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-96, mTimestampNanos=86254451050298}
03-15 20:42:32.251 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-39, mTimestampNanos=86259010351130}
03-15 20:42:32.309 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5B:CE:4F:45:38:61, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, -47, -34, -112]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-93, mTimestampNanos=86259068604255}
03-15 20:42:32.527 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-40, mTimestampNanos=86259282907588}
03-15 20:42:37.525 10425-10425/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=5A:C1:FA:54:54:0F, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=null, mManufacturerSpecificData={76=[16, 5, 81, 28, 17, 115, -33]}, mServiceData={}, mTxPowerLevel=12, mDeviceName=null], mRssi=-37, mTimestampNanos=86264281754670}

既然這種掃描方式可以對掃描和過濾進行設置,那我們來試一下子吧~

在這裏,我想僅僅掃描家裏的體脂秤,所以,調用了setDeviceAddress(string)方法,把體脂秤的mac地址傳遞進去。

其實,這個時候就OK了,因爲藍牙mac地址是設備的唯一標識嘛,這樣設備就一定會只掃描到我的目標設備了。

可是,我想把事情搞大一點,給過濾再加點限制,看是否還能掃描成功。

我又setServiceUuid()方法將體脂秤支持的service uuid傳遞進來。

        //過濾條件
        List<ScanFilter> bleScanFilters = new ArrayList<>();
        ScanFilter filter = new ScanFilter.Builder().setDeviceAddress("08:7C:BE:48:65:AD").setServiceUuid(ParcelUuid.fromString("0000fee7-0000-1000-8000-00805f9b34fb")).build();
        bleScanFilters.add(filter);

 再來對掃描設置進行一些定製:

設置掃描模式爲低延遲模式,這種模式下可以更快的進行設備掃描,除此之外,還有均衡模式(SCAN_MODE_BALANCED)、低功耗模式(SCAN_MODE_LOW_POWER)。從字面意思,你應該也能猜出來,低延遲模式掃描設備最快,低功耗模式掃描設備最慢,均衡模式居中。

設置回調模式爲全匹配(CALLBACK_TYPE_ALL_MATCHES),就是說,如果我們設置了過濾條件,則只上報過濾條件都完全匹配的設備,如果沒有設置任何過濾條件,則上報掃描到的所有設備。

設置粘性匹配,就是在掃描到的設備滿足一定信號強度時,纔去跟過濾條件進行匹配,信號強度太弱,藍牙固件直接丟棄,也不會去做匹配操作。

最後,我們將兩個參數傳遞到startScan()方法中來。

        //掃描設置
        ScanSettings scanSetting = new ScanSettings.Builder().setScanMode(SCAN_MODE_LOW_LATENCY).setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES).setMatchMode(ScanSettings.MATCH_MODE_STICKY).build();
        mBluetoothLeScanner.startScan(bleScanFilters, scanSetting, mScanCallback);

看一下此時的掃描結果,我們的目標設備是可以正常掃描到,並且上報設備的粒度明顯降低了。

03-15 21:12:14.335 16060-16060/com.atlas.devicefinder D/MainActivity: onClick,View = androidx.appcompat.widget.AppCompatButton{e98ee7a VFED..C.. ...P.... 0,288-426,432 #7f070043 app:id/bt_start_blescan2}
03-15 21:12:15.177 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-77, mTimestampNanos=88041917514200}
03-15 21:12:19.962 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-85, mTimestampNanos=88046719595240}
03-15 21:12:22.366 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88049124682114}
03-15 21:12:24.775 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88051533382946}
03-15 21:12:27.180 16060-16060/com.atlas.devicefinder D/MainActivity: onScanResult, result = ScanResult{mDevice=08:7C:BE:48:65:AD, mScanRecord=ScanRecord [mAdvertiseFlags=6, mServiceUuids=[0000fee7-0000-1000-8000-00805f9b34fb, 0000d618-0000-1000-8000-00805f9b34fb], mManufacturerSpecificData={0=[8, 124, -66, 72, 101, -83]}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=1LS_W_9����], mRssi=-70, mTimestampNanos=88053936127529}

4.總結

利用上面提到了方式3 來進行設備掃描有什麼好處呢?

在藍牙固件中即進行設備匹配,可以大大減少藍牙協議棧以及應用層的操作,降低內存佔用、CPU佔用。

可以根據需要進行掃描參數的設置,實現動態調整,進而實現快速掃描目標設備。

 

天不早了,該休息了~

本博客始終堅持理論與實踐相結合,想盡最大努力將知識點講解清楚,但不知道實際效果如何,

如果有任何建議,可以隨時跟我溝通,謝謝。

如果想持續關注本博客內容,請掃描關注個人微信公衆號,或者微信搜索:萬物互聯技術。

 

 


 

 

 

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