最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android藍(lán)牙服務(wù)查找附近設(shè)備分析探索

 更新時(shí)間:2023年01月18日 14:14:23   作者:c小旭  
這篇文章主要介紹了Android藍(lán)牙服務(wù)實(shí)現(xiàn)查找附近設(shè)備,了解內(nèi)部原理是為了幫助我們做擴(kuò)展,同時(shí)也是驗(yàn)證了一個(gè)人的學(xué)習(xí)能力,如果你想讓自己的職業(yè)道路更上一層樓,這些底層的東西你是必須要會(huì)的

一、APP端調(diào)用

1、注冊(cè)廣播監(jiān)聽查找結(jié)果

//藍(lán)牙發(fā)現(xiàn)設(shè)備和查找結(jié)束廣播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(btReceiver, intentFilter);
BroadcastReceiver btReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device != null) {
                //這里收到的是單條設(shè)備信息,可以放到List中進(jìn)行刷新列表
                //設(shè)備名稱:device.getName()
                //設(shè)備地址:device.getAddress()
                if(device.getBondState() == BluetoothDevice.BOND_BONDED) {
                    //已配對(duì)設(shè)備
                }
            }
        } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())) {
                //查找結(jié)束
        }
    }
};

2、開始查找附近設(shè)備

btAdapter.startDiscovery();

3、異常處理

上面代碼無法接收到 BluetoothDevice.ACTION_FOUND 廣播,查找資料發(fā)現(xiàn) Android 6.0 后需要增加兩個(gè)權(quán)限并且需要?jiǎng)討B(tài)申請(qǐng)。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M
         && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)!= PackageManager.PERMISSION_GRANTED) {//請(qǐng)求權(quán)限
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
}

這里的權(quán)限動(dòng)態(tài)申請(qǐng)就簡單處理一下,不做詳細(xì)介紹了。

另一個(gè)問題是收到發(fā)現(xiàn)設(shè)備廣播數(shù)據(jù),很多數(shù)據(jù)的 getName() 為 null,這里還需要做一些判空處理。

二、查找設(shè)備源碼分析

1、BluetoothAdapter.startDiscovery()

private IBluetooth mService;
public boolean startDiscovery() {
    if (getState() != STATE_ON) {
        return false;
    }
    try {
        mServiceLock.readLock().lock();
        if (mService != null) {
            return mService.startDiscovery(mAttributionSource);
        }
    } catch (RemoteException e) {
        Log.e(TAG, "", e);
    } finally {
        mServiceLock.readLock().unlock();
    }
    return false;
}

可以看到這里直接調(diào)用 mService.startDiscovery(),IBluetooth 的實(shí)現(xiàn)類為 AdapterService,相較于藍(lán)牙開關(guān)功能,省去了調(diào)用 BluetoothManagerService 的部分。

2、AdapterService.startDiscovery()

public boolean startDiscovery(AttributionSource attributionSource) {
    AdapterService service = getService();
    if (service == null || !callerIsSystemOrActiveUser(TAG, "startDiscovery")) {
        return false;
    }
    if (!Utils.checkScanPermissionForDataDelivery(
        service, attributionSource, "Starting discovery.")) {
        return false;
    }
    return service.startDiscovery(attributionSource);
}
boolean startDiscovery(AttributionSource attributionSource) {
    UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId());
    debugLog("startDiscovery");
    String callingPackage = attributionSource.getPackageName();
    mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
    boolean isQApp = Utils.isQApp(this, callingPackage);
    boolean hasDisavowedLocation = Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled);
    String permission = null;
    if (Utils.checkCallerHasNetworkSettingsPermission(this)) {
        permission = android.Manifest.permission.NETWORK_SETTINGS;
    } else if (Utils.checkCallerHasNetworkSetupWizardPermission(this)) {
        permission = android.Manifest.permission.NETWORK_SETUP_WIZARD;
    } else if (!hasDisavowedLocation) {
        if (isQApp) {
            if (!Utils.checkCallerHasFineLocation(this, attributionSource, callingUser)) {
                return false;
            }
            permission = android.Manifest.permission.ACCESS_FINE_LOCATION;
        } else {
            if (!Utils.checkCallerHasCoarseLocation(this, attributionSource, callingUser)) {
                return false;
            }
            permission = android.Manifest.permission.ACCESS_COARSE_LOCATION;
        }
    }
    synchronized (mDiscoveringPackages) {
        mDiscoveringPackages.add(new DiscoveringPackage(callingPackage, permission, hasDisavowedLocation));
    }
    return startDiscoveryNative();
}

這里可以看到權(quán)限驗(yàn)證相關(guān)的內(nèi)容。最后調(diào)用 startDiscoveryNative() 進(jìn)入 JNI 層,在com_android_bluetooth_btservice_AdapterService.cpp文件中,調(diào)用startDiscoveryNative方法。

3、startDiscoveryNative()

源碼位置:packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterService.cpp

static jboolean startDiscoveryNative(JNIEnv* env, jobject obj) {
    ALOGV("%s", __func__);
    if (!sBluetoothInterface) return JNI_FALSE;
    int ret = sBluetoothInterface->start_discovery();
    return (ret == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

4、start_discovery() 掃描入口

源碼位置:system/bt/btif/src/bluetooth.cc

static int start_discovery(void) {
    if (!interface_ready()) return BT_STATUS_NOT_READY;
  
    do_in_main_thread(FROM_HERE, base::BindOnce(btif_dm_start_discovery));
    return BT_STATUS_SUCCESS;
}

5、btif_dm_start_discovery() 配置參數(shù)

源碼位置:/system/bt/btif/src/btif_dm.cc

設(shè)備管理(DM)相關(guān)的功能

void btif_dm_start_discovery(void) {
    ...... 
    /* Will be enabled to true once inquiry busy level has been received */
    btif_dm_inquiry_in_progress = false;
    /* find nearby devices */
    BTA_DmSearch(btif_dm_search_devices_evt, is_bonding_or_sdp());
}

6、BTA_DmSearch() 搜索對(duì)等藍(lán)牙設(shè)備

源碼位置:/system/bt/bta/dm/bta_dm_api.cc

它執(zhí)行查詢并獲取設(shè)備的遠(yuǎn)程名稱。

void BTA_DmSearch(tBTA_DM_SEARCH_CBACK* p_cback, bool is_bonding_or_sdp) {
    tBTA_DM_API_SEARCH* p_msg = (tBTA_DM_API_SEARCH*)osi_calloc(sizeof(tBTA_DM_API_SEARCH));
    /* Queue request if a device is bonding or performing service discovery */
    if (is_bonding_or_sdp) {
        p_msg->hdr.event = BTA_DM_API_QUEUE_SEARCH_EVT;
    } else {
        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
    }
    p_msg->p_cback = p_cback;
    bta_sys_sendmsg(p_msg);
}

7、bta_sys_sendmsg() 發(fā)送掃描消息

源碼位置:/system/bt/bta/sys/bta_sys_main.cc

向 BTU TASK 發(fā)送掃描消息,由藍(lán)牙設(shè)備管理模塊處理。

void bta_sys_sendmsg(void* p_msg) {
    if (do_in_main_thread(
            FROM_HERE,
            base::Bind(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg))) !=
        BT_STATUS_SUCCESS) {
      LOG(ERROR) << __func__ << ": do_in_main_thread failed";
    }
}

這里調(diào)用的是 do_in_main_thread() 方法,這個(gè)方法其實(shí)在 4 中已經(jīng)調(diào)用過一次。這個(gè)方法只是返回一個(gè)狀態(tài)。

位置:/system/bt/stack/btu/btu_task.cc

bt_status_t do_in_main_thread(const base::Location& from_here, base::OnceClosure task) {
    if (!main_thread.DoInThread(from_here, std::move(task))) {
      LOG(ERROR) << __func__ << ": failed from " << from_here.ToString();
      return BT_STATUS_FAIL;
    }
    return BT_STATUS_SUCCESS;
}

BTU TASK收到消息后,調(diào)用 bta_dm_main.c 的(用于DM的狀態(tài)機(jī)事件處理函數(shù)) bta_dm_search_sm_execute() 執(zhí)行狀態(tài)切換和 inquiry 流程。這里就不往下分析了。

到此這篇關(guān)于Android藍(lán)牙服務(wù)查找附近設(shè)備分析探索的文章就介紹到這了,更多相關(guān)Android查找附近設(shè)備內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android編程實(shí)現(xiàn)鬧鐘的方法詳解

    Android編程實(shí)現(xiàn)鬧鐘的方法詳解

    這篇文章主要介紹了Android編程實(shí)現(xiàn)鬧鐘的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Android鬧鐘的原理、布局、權(quán)限控制及相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-02-02
  • Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn)

    Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn)

    這篇文章主要介紹了Flutter 全局點(diǎn)擊空白處隱藏鍵盤實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Android 中Fragment與Activity通訊的詳解

    Android 中Fragment與Activity通訊的詳解

    這篇文章主要介紹了Android 中Fragment與Activity通訊的詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握如何通信的,需要的朋友可以參考下
    2017-10-10
  • Android Studio 下載視頻到本地

    Android Studio 下載視頻到本地

    這篇文章主要介紹了Android Studio 下載視頻到本地,利用GreenDao實(shí)現(xiàn)多線程斷點(diǎn)續(xù)傳,這樣的話,下次用戶再次下載時(shí),將繼續(xù)上次數(shù)據(jù)庫的接著下載,這樣用戶體驗(yàn)就會(huì)很好,也大大節(jié)省了成本.具體實(shí)現(xiàn)代碼大家參考下本文
    2018-03-03
  • Android基于MLKit實(shí)現(xiàn)條形碼掃碼的代碼示例

    Android基于MLKit實(shí)現(xiàn)條形碼掃碼的代碼示例

    這篇文章將借助開源庫?MLKit?實(shí)現(xiàn)條形碼掃描,對(duì)于商品條形碼也可以很好地識(shí)別成功,該庫的使用內(nèi)容非常豐富,除了條碼識(shí)別,還有文字識(shí)別、圖像標(biāo)記、人臉檢測(cè)等等,本文篇文章就只介紹最基本的條形碼掃描使用,需要的朋友可以參考下
    2023-08-08
  • Android camera實(shí)時(shí)預(yù)覽 實(shí)時(shí)處理,人臉識(shí)別示例

    Android camera實(shí)時(shí)預(yù)覽 實(shí)時(shí)處理,人臉識(shí)別示例

    本篇文章主要介紹了Android camera實(shí)時(shí)預(yù)覽 實(shí)時(shí)處理,面部認(rèn)證示例,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • Android實(shí)戰(zhàn)APP啟動(dòng)速度優(yōu)化

    Android實(shí)戰(zhàn)APP啟動(dòng)速度優(yōu)化

    本篇文章給大家通過實(shí)戰(zhàn)總結(jié)了Android開發(fā)APP啟動(dòng)速度優(yōu)化的方法以及需要注意的地方,有需要的朋友可以參考下。
    2018-05-05
  • Android APT 實(shí)現(xiàn)控件注入框架SqInject的示例

    Android APT 實(shí)現(xiàn)控件注入框架SqInject的示例

    這篇文章主要介紹了Android APT 實(shí)現(xiàn)控件注入框架SqInject的示例,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下
    2021-03-03
  • Android 實(shí)現(xiàn)無網(wǎng)絡(luò)頁面切換的示例代碼

    Android 實(shí)現(xiàn)無網(wǎng)絡(luò)頁面切換的示例代碼

    本篇文章主要介紹了Android 實(shí)現(xiàn)無網(wǎng)絡(luò)頁面切換的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Android Studio全局搜索快捷鍵(Ctrl+Shift+F)失效問題及解決

    Android Studio全局搜索快捷鍵(Ctrl+Shift+F)失效問題及解決

    這篇文章主要介紹了Android Studio全局搜索快捷鍵(Ctrl+Shift+F)失效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01

最新評(píng)論

汪清县| 怀远县| 广元市| 洪洞县| 磐安县| 南郑县| 宜州市| 玉林市| 宜州市| 芜湖县| 德阳市| 丰城市| 富阳市| 紫阳县| 苏州市| 马尔康县| 启东市| 双柏县| 扎赉特旗| 荔浦县| 新安县| 武定县| 民丰县| 建始县| 芦山县| 武汉市| 吴川市| 九龙县| 烟台市| 庄河市| 都江堰市| 广德县| 昔阳县| 黎平县| 荔波县| 湘潭市| 涞源县| 登封市| 北辰区| 颍上县| 内黄县|