轉自 http://www.cnblogs.com/chenbin7/archive/2012/07/26/2608135.html
BluetoothService類中定義的Native方法都在android_server_BluetoothServer.cpp裡建立jni調用
一,開啟(BT開啟關閉)(藍牙的打開關閉由類BluetoothEnabler控制。)
1.由BluetoothEnabler控制界面操作,在其構造函數裡會先調用LocalBluetoothManager.getInstance(上下文)。
2.然後在LocalBluetoothManager類的getInstance函數裡會調用當前類下的init()函數,該init()函數中通過BluetoothAdapter.getDefaultAdapter()獲得藍牙設備的句柄,如果當前沒有藍牙設備則返回null。
3.初始化完畢會監聽checkbox的狀態,當觸發點擊checkbox會響應onPreferenceChange方法,其中將調用LocalBluetoothManager.setBluetoothEnabled(啟用)方法。
而LocalBluetoothManager.setBluetoothEnabled(enable)方法,會調用mAdapter.enable()方法,enable()方法又會調用BluetoothService.enable()方法。其中,
(1)打開(關閉)操作成功後會有一個異步事件ACTION_STATE_CHANGED返回,異步事件由類BluetoothEventRedirector控制(接收廣播,進行處理)。在收到ACTION_STATE_CHANGED異步事件後,還需要做update本地設備profile的事情,讀取上次關閉前搜索到的藍牙設備。
(1.1)更新本地設備配置文件的事情:
(1.2)讀取上次關閉前搜索到的藍牙設備:
通過LocalBluetoothManager.setBluetoothStateInt(INT狀態)方法調到CachedBluetoothDeviceManager.onBluetoothStateChanged方法來讀取上次關閉之前搜索到device.
(2)來開啟EnableThread線程,進行打開操作,藍牙的打開關閉屬於異步操作。
ps:在啟動藍牙的時候,要注意的地方是不能正常啟動藍牙的情況,因為正常啟動的時候會返回BluetoothIntent.ENABLED_ACTION這個Intent,當時當啟動出現異常的時候是沒有Intent返回的,android使用回調函數來解決這個問題。下面是在bluetoothdeviceservice.java裡面能((IBluetoothDeviceCallback回調)的過程:(以下代碼屬於較低版本的android源碼,與較高版本源碼中已有所不同,只作為參考...)
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()。
|
沒有留言:
張貼留言