一、開啟(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
public synchronized boolean enable(IBluetoothDeviceCallback callback) {
checkPermissionBluetoothAdmin();
Log.d(TAG,"start enable! ");
Airplane mode can prevent Bluetooth radio from being turned on.
if (mIsAirplaneSensitive && isAirplaneModeOn()) {
return false;
}
if (mIsEnabled) {
return false;
}
if (mEnableThread != null && mEnableThread.isAlive()) {
return false;
}
主要的啟動過程是放在一個新起的執行緒裡面,但是不管能不能啟動
仍然返回了true
mEnableThread = new EnableThread(callback);
mEnableThread.start();
//
return true;

 

}

 

private EnableThread mEnableThread;
private class EnableThread extends Thread {
private final IBluetoothDeviceCallback mEnableCallback;
public EnableThread(IBluetoothDeviceCallback callback) {
mEnableCallback = callback;
}
public void run() {
boolean res = enableNative();
if (res) {
mEventLoop.start();
}

 

if (mEnableCallback != null) {
try {

 

通過回呼函數來表明是否正常啟動藍牙設備
mEnableCallback.onEnableResult(res ?
BluetoothDevice.RESULT_SUCCESS :
BluetoothDevice.RESULT_FAILURE);
} catch (RemoteException e) {}
}

 

if (res) {
mIsEnabled = true;
mIsDiscovering = false;

 

Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION);
mCoNtext.sendBroadcast(intent);
}
}else{
mIsEnabled = false;
mIsDiscovering = false;
}
mEnableThread = null;
}
}








這個回呼函數將被作為參數傳進bluetoothservice 裡面的enable(IBluetoothDeviceCallback callback)
static class DeviceCallback extends IBluetoothDeviceCallback.Stub {
Handler messageHandler;

 

public void setHandler(Handler handler) {
synchronized (this) {
messageHandler = handler;
}



public void onEnableResult(int result) {
switch(result) {

 

啟動不成功的時候執行
case BluetoothDevice.RESULT_FAILURE:
messageHandler.sendMessage(messageHandler.obtainMessage(EVENT_FAILED_BT_ENABLE,0));
break;
}
}



配對完成時執行
public void onCreateBondingResult(String address, int result) {
synchronized (this) {
if (messageHandler != null) {
if (result == BluetoothDevice.RESULT_FAILURE) {
messageHandler.sendMessage(messageHandler.obtainMessage(
HANDLE_PAIRING_FAILED, address));
} else {
messageHandler.sendMessage(messageHandler.obtainMessage(
HANDLE_PAIRING_PASSED, address));
}
}
}
}

 

}

 

涉及到的類:

 

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 具體實現檔案傳輸的類

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()。
創作者介紹

資訊園

shadow 發表在 痞客邦 PIXNET 留言(1) 人氣()


留言列表 (1)

發表留言
  • abc
  • 作者你好
    我想請問如果我希望開啟手機的"可檢測的"的功能
    但不想通過系統跳出視窗,改成系統直接設定讓他可檢測
    請問如何實作?
找更多相關文章與討論