18

設備短版:減少BLE startScan檢測到的是Android 5.0棒棒糖

在我的Android 5.0棒棒糖測試中,我已經注意到android.bluetooth.le.BluetoothLeScanner檢測BLE裝置的頻率低於Android 4.4的奇巧。這是爲什麼,還有其他選擇嗎?

龍版本:

我開發一個Android應用程序,專爲Nexus 7平板電腦,側重於檢測藍牙低功耗(BLE)設備。該應用主要關注信標的RSSI值,以確定它們與平板電腦的距離。這意味着我不需要連接到BLE設備,因爲RSSI值在檢測到設備時傳遞給掃描回調。

在Android 4.4 KitKat中,當我呼叫BluetoothAdapter.startLeScan(LeScanCallback)時,對於每個檢測到的BLE設備,我的回調只被調用一次。 (我見過some discussions聲稱這種行爲可能會因設備而異)但是,我對不斷變化的RSSI值感興趣,所以目前推薦的方法是連續進行startLeScan和stopLeScan,並設置間隔(本例中爲250ms):

public class TheOldWay { 

    private static final int SCAN_INTERVAL_MS = 250; 

    private Handler scanHandler = new Handler(); 
    private boolean isScanning = false; 

    public void beginScanning() { 
     scanHandler.post(scanRunnable); 
    } 

    private Runnable scanRunnable = new Runnable() { 
     @Override 
     public void run() { 
      BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 

      if (isScanning) { 
       adapter.stopLeScan(leScanCallback); 
      } else if (!adapter.startLeScan(leScanCallback)) { 
       // an error occurred during startLeScan 
      } 

      isScanning = !isScanning; 

      scanHandler.postDelayed(this, SCAN_INTERVAL_MS); 
     } 
    }; 

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { 
     @Override 
     public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { 
      // use the RSSI value 
     } 
    }; 

} 

從本質上講,這給了我所需的結果,但是這個過程非常耗費資源,最終導致藍牙適配器無響應。

由於這些原因,我將Nexus 7升級到Android 5.0 Lollipop,查看我的BLE問題是否會得到解決。在棒棒糖BluetoothAdapter.startLeScan(LeScanCallback)已被棄用,並替換爲a new API,允許更多的控制掃描過程。從我第一次測試,這似乎startScan不會連續調用我的回調(在我的Nexus 7)當RSSI值的變化,所以我還是需要使用startScan/stopScan實現:

@TargetApi(21) 
public class TheNewWay { 

    private static final int SCAN_INTERVAL_MS = 250; 

    private Handler scanHandler = new Handler(); 
    private List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(); 
    private ScanSettings scanSettings; 
    private boolean isScanning = false; 

    public void beginScanning() { 
     ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder(); 
     scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY); 
     scanSettings = scanSettingsBuilder.build(); 

     scanHandler.post(scanRunnable); 
    } 

    private Runnable scanRunnable = new Runnable() { 
     @Override 
     public void run() { 
      BluetoothLeScanner scanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner(); 

      if (isScanning) { 
       scanner.stopScan(scanCallback); 
      } else { 
       scanner.startScan(scanFilters, scanSettings, scanCallback); 
      } 

      isScanning = !isScanning; 

      scanHandler.postDelayed(this, SCAN_INTERVAL_MS); 
     } 
    }; 

    private ScanCallback scanCallback = new ScanCallback() { 
     @Override 
     public void onScanResult(int callbackType, ScanResult result) { 
      super.onScanResult(callbackType, result); 

      int rssi = result.getRssi(); 

      // do something with RSSI value 
     } 

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

      // a scan error occurred 
     } 
    }; 

} 

正如你所看到的,我已經使用ScanSettings類配置掃描儀,它允許您設置scanMode。我使用ScanSettings.SCAN_MODE_LOW_LATENCY,其中包含以下文檔:「使用最高佔空比掃描。建議僅在應用程序在前臺運行時使用此模式。」聽起來和我想要的完全一樣,但不幸的是,我只能每隔15-30秒檢測一次信標,在這個掃描間隔裏,KitKat版本每隔1到2秒就會顯示一次相同的信標。

你有什麼想法可能是這種差異的原因?我錯過了什麼,也許一些新的設置?有沒有其他的方法來做到這一點?

非常感謝!

阿貝爾

PS:我想包括更多的鏈接,我已經使用的資源,但我沒有代表點呢。

+0

在棒棒糖中「當RSSI值改變時,startScan不會連續調用我的回調(在我的Nexus 7上)」。但它是否至少每隔一段時間再打一次或只打一次?對不起,我沒有測試Nexus 7。在我的Nexus 5中,SCAN_MODE_LOW_POWER每秒都會調用它。 – sorianiv 2014-11-26 15:33:36

+0

@abelcookingfox我幾乎得到了和你一樣不好的結果,我使用的是一加一,CM ROM 5.0.2,有時候掃描時間超過30秒,但有時候它就像死了一樣。你現在有什麼解決方案嗎? – Shawn 2015-02-07 12:57:57

+0

我重新測試,我的One plus手機只掃描2次,那麼回調將永遠不會被解僱。 – Shawn 2015-02-07 13:25:14

回答

5

我使用運行新的Android 5.0掃描API的Nexus 5獲得了非常不同的結果。當使用SCAN_MODE_LOW_LATENCY時,BLE數據包的檢測幾乎實時進入,每100毫秒發送10Hz的BLE信標。

你可以在這裏閱讀完整的結果:

http://developer.radiusnetworks.com/2014/10/28/android-5.0-scanning.html

這些測試都基於運行開源的Android燈塔圖書館2.0的實驗機器人-1- API的分支here的。

這不是明顯的區別是在您的測試結果是什麼,但有可能是啓動和停止掃描正在發生變化的結果。

編輯:也能夠硬件的差異。查看Nexus 4上類似時間的報告:https://github.com/AltBeacon/android-beacon-library/issues/59#issuecomment-64281446

+0

感謝您的建議@davidgyoung!任何機會的任何更新這種情況? :) – abelcookingfox 2015-01-27 14:38:43

+0

我還沒有能夠重現你描述的症狀,所以我不知道任何比上面描述的更多。 – davidgyoung 2015-01-27 16:24:43

+0

嗨大衛你能幫我添加掃描間隔在Android設備使用服務的藍牙lescan。 – 2015-01-29 06:35:50

2

我在KitKat和棒棒糖中都遇到了與Nexus 4非常相似的結果。

隨着KitKat的藍牙適配器也最終沒有響應;起初我雖然認爲它可能與短掃描間隔(200毫秒)有關,但增加這個數字甚至一秒鐘都沒有幫助,在那種情況下,我發現當無響應地以編程方式禁用和啓用適配器時,有時可以解決問題。不幸的是,我不能說它一直工作。

現在的棒棒糖,其中我有很高的期望來解決這個問題,我經歷了你所描述的相同的行爲。我還必須使用startScan/stopScan實現,獲得與檢測時間相似的結果。可悲的是,我還沒有找到解決辦法來更快獲得結果。

根據你的描述,我想這可能是一個硬件問題,即使的Nexus 7和Nexus 4來自不同的製造商(華碩和LG)。

我知道我在這裏沒有提供太多的幫助,除了試圖回答你關於你缺少的東西的問題;我不這麼認爲,我認爲這個問題就像硬件或藍牙API一樣,仍然不適用於不同設備。

+0

謝謝,@marp。現在我將繼續使用startScan/stopScan程序。 – abelcookingfox 2015-01-27 14:39:47

5

我的評論還沒有50的評論,所以請耐心等待,本評論將以答案的形式發佈。在代碼中,不應把該部分:

if (isScanning) { scanner.startScan(...)

是這個:

if (!isScanning) { 
scanner.startScan(...) 

因爲下面的代碼,你開始掃描之前調用stopScan()。如果stopScan()方法是冪等/安全的,它可能不會對結果產生直接影響。但是你知道,爲了代碼的可理解性,你應該編輯這個問題。而這樣做,以你的代碼,有時拜占庭的東西在作怪;)

您是否嘗試過較大值SCAN_INTERVAL_MS?如果是,有多大?

+0

謝謝,我編輯了我的問題。我的代碼是正確的。 :)是的,我已經嘗試了1000毫秒的掃描間隔,但這意味着您不太經常使用掃描結果。當使用<200的掃描間隔時,藍牙適配器並不總是能夠檢測到設備。 – abelcookingfox 2015-02-27 08:30:08

0

如果搜索BW13_DayOne_Session1 Bluetooth Advanced在谷歌,你會發現一個PDF文檔,讓您根據針對發現(見第8頁)中的設置設備的延遲。我猜你的問題與這些時間有關。您可以通過確定您正在測試的設備(Adv Int,佔空比)的廣告配置來進行驗證,然後確定API設置在配置掃描間隔等方面所做的工作。一旦擁有這些設置,您就可以使用該表插入,看看你是否得到你期望的結果。

我知道這是一個軟件網站,但通常在與硬件接口時需要知道協議,否則在黑暗中拍攝。

+2

你可以發表該pdf嗎?我無法找到它。 – bluewhile 2015-10-14 10:24:03

+0

該搜索字詞的唯一谷歌搜索是這個頁面和它的鏡像! – 2016-05-19 10:19:28