日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Android 8.0 进程拉活 --- 蓝牙唤醒

發(fā)布時間:2023/12/25 综合教程 47 生活家
生活随笔 收集整理的這篇文章主要介紹了 Android 8.0 进程拉活 --- 蓝牙唤醒 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言:

IPhone 可以通過 ibeacon 設(shè)備發(fā)出的藍牙廣播來喚醒應(yīng)用,但android有沒有類似的機制來進行喚醒app呢?

很開心的告訴你,在 android 8.0(android 0) 以上的系統(tǒng)已經(jīng)支持了!!!

說明:

在android 8.0 的 API中,藍牙庫中的android.bluetooth.le.BluetoothLeScanner類增加了一個新方法,看下圖

注:api level 26 即 android 8.0

該方法是用于掃描手機周邊的藍牙設(shè)備。在8.0以前,google提供的藍牙掃描方法都是需要app進程還活。但該方法只要調(diào)用成功,無論app進程是否還活著,系統(tǒng)都會在后臺持續(xù)執(zhí)行藍牙掃描。如果手機靠近指定的藍牙設(shè)備附近,app就能被喚醒接收藍牙的掃描結(jié)果。

用途:

該機制雖然只能在特定的區(qū)域?qū)pp進行喚醒,但在很多業(yè)務(wù)場景上非常實用,舉幾個栗子:

1.室內(nèi)定位

2.進入商場用戶立馬能收到商場的活動信息

3.運動手環(huán)需要即時上報數(shù)據(jù)(如:電量不足等)

....

開發(fā):

支持該機制的拉活,實際上就是讓app去掃描一個特定的藍牙廣播,等待系統(tǒng)返回結(jié)果。相信有弄過藍牙開發(fā)的小伙伴都知道藍牙開發(fā)這個坑有多深,而下面是一個跳坑的教程。

一.權(quán)限:

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

注:ACCESS_FINE_LOCATION在android 6.0以上需要運行獲取(見6.0以上運行時權(quán)限申請)。

app除獲取了上述權(quán)限,還需要確保藍牙開啟,以下是代碼開啟藍牙的方法:

//判斷如果藍牙沒有開啟的話,則進行提示用戶開啟
BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

二.API調(diào)用

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

        //指定需要識別到的藍牙設(shè)備
        List<ScanFilter> scanFilterList = new ArrayList<>();
        ScanFilter.Builder builder = new ScanFilter.Builder();
        builder.setServiceUuid(ParcelUuid.fromString(UUID_SERVICE));
        ScanFilter scanFilter = builder.build();
        scanFilterList.add(scanFilter);

        //指定藍牙的方式,這里設(shè)置的ScanSettings.SCAN_MODE_LOW_LATENCY是比較高頻率的掃描方式
        ScanSettings.Builder settingBuilder = new ScanSettings.Builder();
        settingBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        settingBuilder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
        settingBuilder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
        settingBuilder.setLegacy(true);
        ScanSettings settings = settingBuilder.build();

        //指定掃描到藍牙后是以什么方式通知到app端,這里將以可見服務(wù)的形式進行啟動
        PendingIntent callbackIntent = PendingIntent.getForegroundService(
                this,
                1,
                new Intent("com.hungrytree.receiver.BleService").setPackage(getPackageName()),
                PendingIntent.FLAG_UPDATE_CURRENT );

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

這是開啟藍牙掃描的代碼,此處不做過多的說明,有想對android藍牙開發(fā)有更深入了解的小伙伴,可以前往這里的傳送門。不過需要提醒一下大家要注意兩個點:

1.builder.setServiceUuid(ParcelUuid.fromString("填入您需要掃描的設(shè)備uuid")); 
此處的uuid就相當于是你藍牙設(shè)備的標志,是一定要與你的設(shè)備匹配上的,不能隨便亂填。
2.PendingIntent建議以前臺服務(wù)(getForegroundService)方式create。經(jīng)過測試,如果以getService,getBroadcast方法進行創(chuàng)建PendingIntent的話在拉活方面存在比較多的兼容問題.而getForegroundService方式在國內(nèi)主流機型上可正常拉活進程(經(jīng)過測試的機型有:華為,小米,oppo,vivo等)
PendingIntent.getForegroundService(
                this,
                1,
                new Intent("com.hungrytree.receiver.BleService").setPackage(getPackageName()),
                PendingIntent.FLAG_UPDATE_CURRENT );

上面代碼已經(jīng)實現(xiàn)藍牙掃描觸發(fā),而下面是實現(xiàn)藍牙廣播的接收:

    //AndroidManifest中的服務(wù)聲明
<service android:name=".TestService"> <intent-filter> <action android:name="com.hungrytree.receiver.BleService"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service>
@TargetApi(26)
public class TestService extends Service {
    
    @Override
    public void onCreate() {
        super.onCreate();
        //以前臺服務(wù)的方式啟動,要調(diào)用startForeground,否則會出現(xiàn)arn異常
        Notification notification = new Notification.Builder(this, NotificationChannel.DEFAULT_CHANNEL_ID)
                .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
                .build();
        startForeground(110, notification);
    }

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

        //獲取返回的錯誤碼
        int errorCode = intent.getIntExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, -1);//ScanSettings.SCAN_FAILED_*
        //獲取到的藍牙設(shè)備的回調(diào)類型
        int callbackType = intent.getIntExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, -1);//ScanSettings.CALLBACK_TYPE_*
        if (errorCode == -1) {
            //掃描到藍牙設(shè)備信息
            List<ScanResult> scanResults = (List<ScanResult>) intent.getSerializableExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT);
            if (scanResults != null) {
                for (ScanResult result : scanResults) {
                    //打印所有設(shè)備的地址
                    String address = result.getDevice().getAddress();
                    Log.i("haha", "device address " + address);
                }
            }
        } else {
            //此處為掃描失敗的錯誤處理

        }
        return super.onStartCommand(intent, flags, startId);
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

此處是一個的ForegroundService的創(chuàng)建,他和普通服務(wù)的創(chuàng)建沒什么大區(qū)別,不同的地方是在服務(wù)創(chuàng)建后要即時調(diào)用startForeground()方法,否則會出現(xiàn)anr異常。正常調(diào)用了startForeground()方法,手機通知欄會出現(xiàn)相應(yīng)的通知提示,但國內(nèi)很多機型是不會顯示通知欄的,所以按這種方式很多用戶也看不到進程被拉活了( ̄▽ ̄)。

通過intent回調(diào)過來的參數(shù)見下表:

常量(BluetoothLeScanner.java中)

描述
EXTRA_CALLBACK_TYPE 見 android.bluetooth.le.ScanSettings.CALLBACK_TYPE_* 回調(diào)的內(nèi)容類型
EXTRA_ERROR_CODE 見android.bluetooth.le.ScanCallback.SCAN_FAILED_* 掃描失敗的錯誤碼,若成為,則該字段為空
EXTRA_LIST_SCAN_RESULT 見 List<android.bluetooth.le.ScanResult> 掃描成功之后獲得的藍牙設(shè)備息

有啟動掃描,當然有關(guān)閉方法,見以下代碼:

    @TargetApi(26)
    public void onClose(View view){
        PendingIntent callbackIntent = PendingIntent.getBroadcast(
                this,
                1,
                new Intent("com.hungrytree.receiver.BleReceiver")
                        .setPackage(getPackageName()),
                PendingIntent.FLAG_UPDATE_CURRENT );
        BluetoothManager bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
        bluetoothAdapter.getBluetoothLeScanner().stopScan(callbackIntent);
    }

三、注意事項

以上的api調(diào)用在主流機型親測是沒有問題,但如果遇到以下問題可償試用以下方式解決

1.藍牙無法拉活

大多數(shù)國內(nèi)的手機里面都有一個很神奇的權(quán)限----自啟動權(quán)限,它的意思不僅僅包含手機啟動的時候啟動app,同時還有其它應(yīng)用(包含系統(tǒng)應(yīng)用)能否拉活你的應(yīng)用。簡單的說,如果發(fā)現(xiàn)不能被拉活,那就可能是系統(tǒng)的限制,試一下打開app的自啟動權(quán)限。

2.無論怎么樣都無法掃描到藍牙

在android 6.0以上的系統(tǒng),部分手機如果想掃描到藍牙設(shè)備,還要檢查位置服務(wù)或定位服務(wù)是否開啟!!!在位置服務(wù)打開之后是有其它選項要求的。一般有三種選項,分別是 1.高精確度(GPS+網(wǎng)絡(luò))2.低耗電量(網(wǎng)絡(luò)) 3.權(quán)限設(shè)備(GPS)。需要用到藍牙掃描的話就只能選1或者2,選3是沒有用的。以下小米的位置服務(wù)為例,看下圖。

3.用戶關(guān)閉藍牙后再打開,會停止原先所有的藍牙掃描,也意味著終止了app喚醒

假設(shè)進程還活著的時候,監(jiān)測藍牙開關(guān)再觸發(fā)藍牙掃描是沒有問題的。但如果進程死后,用戶關(guān)閉藍牙,那暫時還沒找到合適的辦法。

參考資料:

https://developer.android.com/reference/android/bluetooth/le/ScanSettings(需要科學上網(wǎng))

結(jié)論:

android 8.0以上也可以支持類似像ios ibeacon方式的喚醒,同時不會像蘋果局限于只能用ibeacon,能給許多的業(yè)務(wù)帶來更好的擴展。

如果該拉活方式只是為了提供給用戶在特定的場景有更好的體驗,那我是建議的。但如果要用來讓app持續(xù)性后臺運行,這種方式就有點濫用了。哪天google或者國內(nèi)的產(chǎn)商一不開心就......

最后,感謝各位大牛的閱讀,如果有不對的地方希望能幫忙提醒改正,在此先謝過。

總結(jié)

以上是生活随笔為你收集整理的Android 8.0 进程拉活 --- 蓝牙唤醒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。