android 藍牙源碼分析


BluetoothService類中定義的Native方法都在android_server_BluetoothServer.cpp里建立jni調用

一、開啟(BT Turn on Turn off) (藍牙的打開關閉由類BluetoothEnabler控制。)

1.由BluetoothEnabler控制界面操作,在其構造函數里會先調用 LocalBluetoothManager.getInstance(context)。

2.然后在LocalBluetoothManager類的getInstance函數里會調用當前類下的init()函數,該init()函數中通過BluetoothAdapter.getDefaultAdapter()獲得藍牙設備的句柄,如果當前沒有藍牙設備則返回null。 

3.初始化完畢會監聽checkbox的狀態,當觸發點擊checkbox會響應onPreferenceChange方法,其中將調用 LocalBluetoothManager.setBluetoothEnabled(enable)方法。

而LocalBluetoothManager.setBluetoothEnabled(enable)方法,會調用mAdapter.enable()方法,enable()方法又會調用 BluetoothService.enable()方法。其中,

(1)打開(關閉)操作成功后會有一個異步事件ACTION_STATE_CHANGED返回,異步事件由類BluetoothEventRedirector控制(接收廣播,進行處理)。在收到ACTION_STATE_CHANGED異步事件后,還需要做update本地設備profile的事情,讀取上次關閉前搜索到的藍牙設備。

(1.1)update本地設備profile的事情:?

(1.2)讀取上次關閉前搜索到的藍牙設備:

通過LocalBluetoothManager.setBluetoothStateInt(int state)方法調到 CachedBluetoothDeviceManager.onBluetoothStateChanged方法來讀取上次關閉之前搜索到device. 

(2)來開啟EnableThread線程,進行打開操作,藍牙的打開關閉屬於異步操作。

ps:在啟動藍牙的時候,要注意的地方是不能正常啟動藍牙的情況,因為正常啟動的時候會返回BluetoothIntent.ENABLED_ACTION 這個Intent,當時當啟動出現異常的時候是沒有Intent返回的,android使用回調函數來解決這個問題。下面是在bluetoothdeviceservice.java 里面enable(IBluetoothDeviceCallback callback 的過程:(以下代碼屬於較低版本的android源碼,與較高版本源碼中已有所不同,只作為參考...)

View Code
  1 public synchronized boolean enable(IBluetoothDeviceCallback callback) {
  2         checkPermissionBluetoothAdmin();
  3         Log.d(TAG,"start enable! ");
  4         // Airplane mode can prevent Bluetooth radio from being turned on.
  5         if (mIsAirplaneSensitive && isAirplaneModeOn()) {
  6             return false;
  7         }
  8         if (mIsEnabled) {
  9             return false;
 10         }
 11         if (mEnableThread != null && mEnableThread.isAlive()) {
 12             return false;
 13         }
 14    //   主要的啟動過程是放在一個新起的線程里面,但是不管能不能啟動 
 15    //    仍然返回了true
 16         mEnableThread = new EnableThread(callback);
 17         mEnableThread.start();
 18       //   
 19         return true;
 20   
 21         }
 22    
 23     private EnableThread mEnableThread;
 24     private class EnableThread extends Thread {
 25         private final IBluetoothDeviceCallback mEnableCallback;
 26         public EnableThread(IBluetoothDeviceCallback callback) {
 27             mEnableCallback = callback;
 28         }
 29         public void run() {
 30             boolean res = enableNative();
 31             if (res) {
 32                 mEventLoop.start();
 33             }
 34 
 35             if (mEnableCallback != null) {
 36                 try {
 37                  
 38                     // 通過回調函數來表明是否正常啟動藍牙設備
 39                     mEnableCallback.onEnableResult(res ?
 40                                                    BluetoothDevice.RESULT_SUCCESS :
 41                                                    BluetoothDevice.RESULT_FAILURE);
 42                 } catch (RemoteException e) {}
 43             }
 44 
 45             if (res) {
 46                 mIsEnabled = true;
 47                 mIsDiscovering = false;
 48 
 49                 Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
 50                 mContext.sendBroadcast(intent);
 51                 }
 52             }else{
 53                 mIsEnabled = false;
 54                 mIsDiscovering = false;
 55             }
 56             mEnableThread = null;
 57         }
 58 }
 59 
 60 
 61 
 62 
 63 
 64     
 65 
 66 //  這個回調函數將被作為參數傳進bluetoothservice 里面的enable(IBluetoothDeviceCallback callback)
 67 static class DeviceCallback extends IBluetoothDeviceCallback.Stub {
 68         Handler messageHandler;
 69 
 70         public void setHandler(Handler handler) {
 71             synchronized (this) {
 72                 messageHandler = handler;
 73             }
 74    
 75    
 76         public void onEnableResult(int result) {
 77             switch(result) {
 78 
 79   //  啟動不成功的時候執行
 80                 case BluetoothDevice.RESULT_FAILURE:
 81                      messageHandler.sendMessage(messageHandler.obtainMessage(EVENT_FAILED_BT_ENABLE,0));
 82                     break;
 83             }
 84         }
 85        
 86 
 87 //   配對完成時執行
 88 public void onCreateBondingResult(String address, int result) {
 89             synchronized (this) {
 90                 if (messageHandler != null) {
 91                     if (result == BluetoothDevice.RESULT_FAILURE) {
 92                         messageHandler.sendMessage(messageHandler.obtainMessage(
 93                                 HANDLE_PAIRING_FAILED, address));
 94                     } else {
 95                         messageHandler.sendMessage(messageHandler.obtainMessage(
 96                                 HANDLE_PAIRING_PASSED, address));
 97                     }
 98                 }
 99             }
100         }
101 
102     }

 

 

涉及到的類: 

BluetoothService(最主要的類,開啟具體命令的線程進行enable,disable等操作) 
LocalBluetoothManager(本機藍牙設備管理,開啟關閉,搜索等等,初始化BluetoothAdapter) 
BluetoothEnabler(界面的點擊和狀態文字的顯示) 
BluetoothAdapter(framework封裝的類,提供本地藍牙設備的配置,包括開啟藍牙,搜索周圍藍牙設備,設置本地藍牙可見性;建立LocalBluetoothManager和BluetoothService的映射關系,主要是通過它調用BluetoothService的函數)

BluetoothEventRedirector(接收Bluetooth API 的廣播和回調,並且將Settings中的UI線程上的事件分派到正確的類)

 

二、可檢測性(Discoverable)

1.藍牙的discoverable mode由類BluetoothDiscoverableEnabler控制。點擊將觸發OnPreferenceChangeListener監聽事件,調用onPreferenceChange()方法,該方法中調用setEnabled(true),而setEnabled(true)方法將調用到BluetoothAdapter的setScanMode () 方法。

藍牙模式有兩種模式SCAN_MODE_CONNECTABLE_DISCOVERABLE(可連接可發現)和SCAN_MODE_CONNECTABLE(可連接但不可發現)

 
涉及到的類:
LocalBluetoothManager 
BluetoothDiscoverableEnabler 
BluetoothAdapter

 

三、掃描 

1.在BluetoothSetting里觸發點擊,調用LocalBluetoothManager.startScanning(true)函數,通過BluetoothAdapter的startDiscovery調用到BluetoothService里的startDiscovery來調用Native函數 startDiscoveryNative()。 

startDiscovery()是個異步函數,會立即返回,通過注冊 ACTION_DISCOVERY_STARTED、ACTION_DISCOVERY_FINISHED、ACTION_FOUND,來確定當前的狀態。 

當藍牙由disable變成enable時會調用掃描,當距離上次掃描超過5分鍾的前提下,退出頁面,再進到頁面的時候也會啟動掃描。 

在啟動scan的時候,還會判斷當前是否在播放音樂,如果在播放音樂,則不啟動掃描。 

點擊查找設備后,會把設備列表里沒有配對的設備清除掉,保留配對狀態的設備。

掃描的過程是一個很耗費資源的過程,在掃描過程,不會去嘗試進行新的連接,掃描時間默認是12秒,它是以一個系統服務的形式存在的,可以調用cancelDiscovery()來取消掃描。 

 

四、連接 

1.1 在setting界面點擊連接,會調到CachedBluetoothDevice類的connect方法。

1.2 而connect方法會調用connectWithoutResettingTimer()方法。

1.3 而connectWithoutResettingTimer()方法會調用 connectInt方法。

在connectInt里,根據不同的profile來獲得profilemanger,然后調用 profilemanger.connect()函數 。此處的鏈接會涉及到的profile有A2DP AVRCP DUN HSP HFP 等。

同理如果配對或者解除配對,也會調到CachedBluetoothDevice類的pair()方法和unpair()。

 

以A2DP為例,在connectInt里,根據不同的profile來獲得profilemanger,然后調用 profilemanger.connect()函數,在這個函數里調用了BluetoothA2dpService的connectSink()函數,最后調到Native方法

connectSinkNative()去建立連接。 

涉及到的一些類: 

CachedBluetoothDevice(搜索到的設備) 
BluetoothDevice(設備類) 
LocalBluetoothProfileManager(是一個抽象類,各種ProfileManger,實例化各種Profile的service) 
SettingsBtStatus(藍牙的狀態類) 
BluetoothA2dp(為LocalBluetoothProfileManager和BluetoothA2dpService建立映射關系) 
BluetoothA2dpService(最終的服務類,由它調用連接、斷開等Native函數,和底層通信)

 

其他文件作用(接收與發送類似)

1.BluetoothOppReceiver.java 這個類里描述的是藍牙傳輸文件過程中接收到的廣播事件。

2.BluetoothOppTransfer.java 管理文件傳輸的類

3. BluetoothOppService.java 藍牙傳輸文件后台的類

4. BluetoothOppObexClientSession.java 具體實現文件傳輸的類

 

 

通過源碼分析藍牙執行過程:(Bluetooth--->BT)
1、開啟

步驟1:首先從BTSettings開始,執行onCreate方法。因為是初始化狀態,所以if(action.equal(BTDevicePicker.ACTION_LAUNCH))不滿足,故執行else語句。

步驟2:初始化mEnable對象,調用BTEnable構造函數。通過LocalBTManager.getInstance調用init方法,再通過init方法調用BTAdapter.getDefaultAdapter()獲得適配器句柄。

步驟3:各種初始化完畢后,執行BTSettings中的onResume方法,調用BTEnabler.resume方法,該resume方法為組合框設置監聽事件。

步驟4:當藍牙開啟時,該組合框被選中,將響應監聽事件,執行BTEnabler.onPreferenceChange方法。該方法中會調用LocalBTManager.setBTEnabled方法。而setBTEnabled方法會調用BTAdapter.enable()方法,繼而調用BTService.enable()方法,繼而調用BTService.enable(true)方法。在該方法中,

(1)當enable(true)方法返回true時,在setBTEnabled方法中會調用BTService中的setBTStateInt方法,繼而廣播出去,由BTEventRedirector類接收。

(2)開啟新的線程,主要的啟動過程是放在這個新啟動的線程里面。

(3)開啟藍牙后,會調用CachedBTDeviceManager.onBTStateChanged方法來讀取上次關閉前搜索到的藍牙設備。

2.可檢測的

點擊“可檢測性”組合框,將觸發BTDiscoverableEnabler.onPreferenceChange方法,然后調用同個類中的setEnabled方法,來調用BTAdapter.setScanMode方法(其中傳遞SCAN_MODE_CONNECTABLE_DISCOVERABLE參數),繼而會調用BTService.setScanMode方法,在該方法中,會通過setDiscoverableTimeout方法設置檢測時間。

3.掃描

BTSettings的onResume方法繼續往下運行,將調用LocalBTManager.startScanning方法,該方法會調用BTAdapter.startDiscovery方法,繼而調用BTService.startDiscovery方法,再調用startDIscoveryNative方法。

4.連接

步驟1:在setting界面點擊連接,會調到CachedBluetoothDevice類的connect方法。

步驟2:而connect方法會調用connectWithoutResettingTimer()方法。

步驟3:而connectWithoutResettingTimer()方法會調用 connectInt方法。

步驟4:在connectInt里,根據不同的profile來獲得profilemanger,然后調用 profilemanger.connect()函數 。此處的鏈接會涉及到的profile有A2DP AVRCP DUN HSP HFP 等。

同理如果配對或者解除配對,也會調到CachedBluetoothDevice類的pair()方法和unpair()。

 

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM