Android 8.0 藍牙喚醒 Ble 鎖屏 保活 後臺 持續掃描 進程拉活 自動喚醒

主要是api的說明,嫌囉嗦的可以直接看demo,demo中有個檢測鎖屏時間重複開啓掃描的代碼,主要是如果APP沒有獲得電量或者後臺運行的權限,只能持續後臺運行幾小時。

這個demo的作用是實現8.0以後的後臺監測到特定藍牙信號自動喚醒APP的功能,首先需要另外一個裝了可以發射藍牙信號軟件的手機,我這邊是選取的ios平臺上的lightblue,然後在這個軟件裏面新建一個虛擬設備名稱是要demo搜索的藍牙模塊名稱。然後把app殺掉,過一段時間打開lightblue發射藍牙信號,然後關掉,再次打開demo,會發現demo中記錄的時間就是你發射藍牙信號的時間,說明被殺後它還是在監測藍牙信號的

先看gif的效果

Demo的Github地址如下

https://github.com/TracyEminem/BleSingle    

 

在Android 8.0以上的版本中,Google提供了一種可以在後臺持續掃描的方式,如果不給後臺運行的權限,也是可以在鎖屏後持續進行藍牙掃描,可以持續大概幾個小時,還可以利用傳的intent來從後臺喚醒APP。。。我做了嘗試,如果把app從任務欄刪掉,再發出藍牙信號也可以讓app自動運行喚醒。。。如果你給與了電量限制,後臺運行相關的權限,那麼這個掃描是可以持續很久的,使用前臺service我做到過5天保持掃描一直在運行。而且這個耗電量很低,基本上忽略不計。。原理有點類似於IOS上的IBEACON喚醒APP,雖然Android也有類似的Eddystone,但是Eddystone不支持後臺持續監測,Eddystone可以利用Google nearby的api檢測到甚至IBEACON也是可以檢測的,但是google nearby的檢測方式依賴於你何時按下鎖屏按鈕的,如果你在beacon附近沒有按鎖屏按鈕,那麼是不會再後臺檢測BEACON信號的。。

喚醒的api如下

很明顯,也是利用了ScanFilter來檢測指定的設備,來實現這個後臺掃描的功能的,實際上單純只是鎖屏後臺持續掃描的API還有另外一個,也是利用了ScanFilter。。另外一個api如下

 

下面是如何使用 首先是一堆權限 

   <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

然後是創建一個Penddingintent來執行喚醒操作

   callbackIntent = PendingIntent.getForegroundService(
                this,
                1,
                new Intent("com.hungrytree.receiver.BleService").setPackage(getPackageName()),
                PendingIntent.FLAG_UPDATE_CURRENT );

這個callbackIntent在開啓和關閉藍牙掃描時也要用到,然後開啓藍牙的掃描,這一步可以在Activity中操作,也可以在service中操作。。。

    public void onOpen(){
        //BluetoothManager是向藍牙設備通訊的入口
        BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

        //指定需要識別到的藍牙設備
        List<ScanFilter> scanFilterList = new ArrayList<>();

        ScanFilter.Builder builder2 = new ScanFilter.Builder();
        builder2.setDeviceName("test2");//你要掃描的設備的名稱,如果使用lightble這個app來模擬藍牙可以直接設置name,這個只是filter的一種,你可以指定uuid,這個只是指定設備名
        ScanFilter scanFilter2 = builder2.build();

//        scanFilterList.add(scanFilter);
        scanFilterList.add(scanFilter2);

        //指定藍牙的方式,這裏設置的ScanSettings.SCAN_MODE_LOW_POWER是比較節電的掃描方式,而且在效率方面沒有很大的影響,而且相當省電
        ScanSettings.Builder settingBuilder = new ScanSettings.Builder();
        settingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER);
        settingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
        settingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
        settingBuilder.setLegacy(true);
        ScanSettings settings = settingBuilder.build();


        //啓動藍牙掃描
        bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilterList,settings,callbackIntent);
        // bluetoothAdapter.getBluetoothLeScanner().startScan(scanFilterList,settings,mScanCallback);
    }

後面是關閉藍牙掃描

   public void onClose(){
        BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();

        bluetoothAdapter.getBluetoothLeScanner().stopScan(callbackIntent);
        //這個callbackintent必須是之前創建的那個,不然無法關閉掃描

    }

下面是接收藍牙掃描的結果,在Service中接收結果,並且處理

     <service android:name=".TestService">
            <intent-filter>
                <action android:name="com.hungrytree.receiver.BleService"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </service>

處理是在service的onstartcommand方法中,結果會不斷的回調該方法,在該方法中進行處理

  @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent.getAction() == null) {
            return START_STICKY;
        }

        //獲取返回的錯誤碼
        int errorCode = intent.getIntExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, -1);//ScanSettings.SCAN_FAILED_*
        //獲取到的藍牙設備的回調類型
        int callbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);//ScanSettings.CALLBACK_TYPE_*
        if (errorCode == -1) {
            //掃描到藍牙設備信息
            List<ScanResult> scanResults = (List<ScanResult>) intent.getSerializableExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
            if (scanResults != null) {
                for (ScanResult result : scanResults) {
                   Utils.writeFile(getApplicationContext(),"wakeup.log",Integer.toString(numRSSI));
                    Log.i("Wakeup", "onScanResult2: name: " + result.getDevice().getName() +
                            ", address: " + result.getDevice().getAddress() +
                            ", rssi: " + result.getRssi() + ", scanRecord: " + result.getScanRecord());
                }
            }
        } else {
            //此處爲掃描失敗的錯誤處理

        }
        return START_STICKY;
    }

如果中途關閉藍牙,那麼掃描會自動恢復。。如果被殺了,你關閉藍牙,那麼無法再執行喚醒的操作。。。如果要利用手機發出特定的藍牙信號,可以安裝LightBlue 這個app,要發出beacon信號的話,請安裝玩轉Beacon。。這兩個app都是ios平臺的

 

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