Android API Guides---Bluetooth
Bluetooth
Android平台包括藍芽網路通訊協定棧,它允許裝置以無線方式與其他藍牙裝置進行資料交換的支援。應用程式架構提供了訪問通過Android藍芽API的藍芽功能。這些API使應用程式無線方式串連到其它藍牙裝置,實現點對點和多點無線功能。
使用藍芽的API,Android應用程式可以執行以下操作:
掃描其他藍牙裝置
查詢本地藍芽適配器配對的藍牙裝置
建立RFCOMM通道
串連到通過服務發現其他裝置
傳送資料和從其他裝置
管理多個串連
本文介紹如何使用傳統藍芽。經典藍芽是有關電池密集型操作,如流媒體和Android裝置之間的通訊是正確的選擇。對於低功耗的要求藍牙裝置的Andr??oid 4.3(API等級18)引入了低功耗藍芽API支援。要瞭解更多資訊,請參閱藍芽低功耗。
基礎
本文介紹了如何使用Android的藍芽API來完成必要的四大任務,使用藍芽通訊:建立藍芽,發現要麼在當地配對或可用,串連裝置的裝置和裝置之間的資料轉送。
所有藍芽API都是在android.bluetooth封裝。這裡有您需要建立藍芽串連的類和介面的摘要:
BluetoothAdapter
代表本地藍芽適配器(藍芽無線電)。該BluetoothAdapter是進入點所有藍芽互動。利用這一點,你會發現其他藍牙裝置,查詢保稅(配對)的裝置列表,使用已知的MAC地址執行個體化一個BluetoothDevice類,並建立一個BluetoothServerSocket監聽來自其他裝置的通訊。
BluetoothDevice類
表示遠程藍牙裝置。使用這個請求通過繞裝置的BluetoothSocket或查詢的資訊與遠程裝置的串連,如它的名稱,地址,類別,和結合狀態。
的BluetoothSocket
表示為藍芽通訊端介面(類似於TCP插座)。這是連接點,它允許應用程式通過InputStream和OutputStream其它藍牙裝置交換資料。
BluetoothServerSocket
表示偵聽傳入請求(類似於TCP ServerSocket的)一個開放的伺服器通訊端。為了串連兩個Android裝置,一台裝置必須開啟這個類的伺服器通訊端。當一個遠程藍牙裝置建立串連請求到該裝置中,當串連被接受的BluetoothServerSocket將返回一個串連的BluetoothSocket。
BluetoothClass
描述的一般特徵和藍牙裝置的能力。這是一個唯讀設定定義裝置的主要和次要裝置類和它的服務性質。但是,這並不能可靠地描述了裝置支援的所有藍芽設定檔和服務,而且是作為一個提示裝置類型非常有用。
BluetoothProfile
表示藍芽設定檔的介面。藍芽設定檔是裝置間基於藍芽的通訊的無線介面規範。一個例子是免提模式。對於設定檔的詳細討論,請參閱使用設定檔
藍芽耳機
藍芽耳機提供了支援,與手機一起使用。這包括藍芽耳機和免提(V1.5)型材。
BluetoothA2dp
如何定義高品質音頻,可從流一個裝置到另一個通過藍芽串連。 “A2DP”代表進階音頻傳輸模式。
BluetoothHealth
表示控制藍芽服務醫療設備規範代理。
BluetoothHealthCallback
您用來實現BluetoothHealth回調的一個抽象類別。您必須擴充這個類,並實現回調方法來接收有關在應用程式的註冊狀態和藍芽通道狀態的變化更新。
BluetoothHealthAppConfiguration
表示藍芽醫學第三方應用註冊與遠程藍牙裝置的健康通訊的應用程式配置。
BluetoothProfile.ServiceListener
該通知時,他們已經被串連到或從服務斷開BluetoothProfile的IPC用戶端的介面(即,運行一個特定的輪廓內部服務)。
藍芽許可權
為了使用應用程式中的藍芽功能,您必須聲明藍芽許可權藍芽。你需要這個許可權才能執行任何藍芽通訊,比如請求串連,接受串連,傳輸資料。
如果你希望你的應用程式來啟動裝置發現或操縱藍芽設定,您還必須聲明BLUETOOTH_ADMIN許可。大多數應用程式需要這個許可權僅用於發現本地的藍牙裝置的能力。通過此許可權授予其他的能力不應該被使用,除非應用程式是一個“電源管理”,將根據使用者的請求修改藍芽設定。註:如果您使用BLUETOOTH_ADMIN許可,則還必須具備藍芽許可權。
聲明在您的應用程式資訊清單檔案的藍芽許可權(S)。例如:
...
請參閱有關聲明應用程式許可權的詳細資料<使用許可權>引用。
設定藍芽
圖1:啟用藍芽對話方塊。
在應用程式能夠通過藍芽通訊,您需要驗證支援藍牙裝置上,如果是這樣,請確保它已啟用。
如果不支援藍芽,那麼你應該優雅地禁用任何藍芽功能。如果支援藍芽,但被禁用,則可以要求使用者啟用藍芽無需離開應用程式。這種設定兩個步驟來完成,使用BluetoothAdapter。
擷取BluetoothAdapter
該BluetoothAdapter需要的任何和所有藍芽活動。要獲得BluetoothAdapter,調用靜態getDefaultAdapter()方法。返回表示裝置自身的藍芽適配器(藍芽無線電)一BluetoothAdapter。還有一個藍芽適配器為整個系統和應用程式可以使用這個對象與它進行互動。如果getDefaultAdapter()返回null,則該裝置不支援藍芽和你的故事在這裡結束。例如:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) { // Device does not support Bluetooth}
啟用藍芽
接下來,您需要確保藍芽已啟用。調用isEnabled()檢查藍芽當前是否啟用。如果此方法返回false,那麼藍芽被禁用。要請求藍芽啟用,調用startActivityForResult()與ACTION_REQUEST_ENABLE行動意圖。這將發出一個請求通過系統設定來啟用藍芽(無需停止應用程式)。 例如:
if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}
將出現一個對話方塊,要求使用者權限才能啟用藍芽功能,1。如果使用者回答“是”,系統將開始啟用藍芽,一旦該過程完成後(或失敗),焦點將返回到應用程式。
)傳遞給startActivityForResult(該REQUEST_ENABLE_BT常量是一個本地定義整數(必須大於0更大),系統傳回在你的onActivityResult()實現為requestCode參數。
如果啟用藍芽成功,你的活動收到了的onActivityResult()回調RESULT_OK結果代碼。如果藍芽沒有由於啟用錯誤(或使用者回答“否”),那麼結果代碼RESULT_CANCELED。
或者,您的應用程式還可以偵聽廣播ACTION_STATE_CHANGED意圖,這每當藍芽狀態發生變化,系統將播出。此廣播包含了額外的欄位EXTRA_STATE和EXTRA以前的狀態,包含新老藍芽狀態,分別為。這些額外的欄位可能的值是STATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF和STATE_OFF。偵聽此廣播可以檢測到您的應用程式正在運行,而藍芽狀態所做的更改非常有用。
提示:啟用可發現會自動啟用藍芽。如果您計劃執行藍芽活動前始終使裝置可發現,你可以跳過上面的步驟2。閱讀關於啟用可發現,下文。
尋找裝置
使用BluetoothAdapter,可以發現無論是通過裝置發現,或通過查詢配對(保稅)的裝置列表遠程藍牙裝置。
裝置發現的是,搜尋藍牙裝置的局部地區??,然後請求關於每一個的一些資訊(這有時被稱為“發現”,“查詢”或“掃描”)的掃描過程。然而,只有當它當前已啟用可被發現局部地區內的藍牙裝置會以發現請求作出響應。如果一個裝置是可發現,它會通過共用一些資訊,例如裝置名稱,類和其特有的MAC地址的發現請求作出響應。使用該資訊,該裝置執行發現隨後可以選擇發起對所發現的裝置的串連。
一旦串連與用於第一次的遠程裝置製成,配對請求被自動呈現給使用者。當一個裝置被配對,關於該裝置的基本資料(例如裝置名稱,類和MAC地址)被儲存,並且可以使用藍芽API來讀取。使用公知的MAC地址為遠程裝置中,串連可以用它在任何時間發起而不執行發現(假設裝置在範圍內)。
記得有被配對並串連之間的差。進行配對意味著兩個裝置都知道彼此的存在,具有可以用於認證的共用連結密鑰,並且能夠建立與彼此的加密串連的。要串連意味著裝置目前共用一個RFCOMM通道,並且能夠彼此傳輸資料。目前Android藍芽API的要求,可以建立一個RFCOMM串連之前配對的裝置。 (當你開始使用藍芽API的一個加密的串連會自動進行配對。)
以下部分描述了如何找到已配對的裝置,或使用裝置發現發現新的裝置。
註:Android系統的裝置預設情況下不被發現。使用者可以使裝置可發現在有限的時間通過系統設定,或者應用程式可以要求使用者能夠發現能力,而無需離開應用程式。如何啟用可發現在下面討論。
查詢配對裝置
執行裝置發現之前,看到了它的價值查詢組配對的裝置,如果需要的裝置是已知的。要做到這一點,調用getBondedDevices()。這將返回一組表示配對裝置BluetoothDevices的。例如,您可以查詢所有配對裝置,然後顯示每個裝置的使用者名稱,使用ArrayAdapter:
Set pairedDevices = mBluetoothAdapter.getBondedDevices();// If there are paired devicesif (pairedDevices.size() > 0) { // Loop through paired devices for (BluetoothDevice device : pairedDevices) { // Add the name and address to an array adapter to show in a ListView mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); }}
所有這一切從BluetoothDevice類對象所需要的,以發起串連的MAC地址。在這個例子中,它的儲存做為所顯示給使用者一個ArrayAdapter的一部分。 MAC地址可在以後以發起串連被提取。您可以瞭解更多有關建立大約串連裝置部分的串連。
發現裝置
要開始尋找裝置,只需調用startDiscovery()。這個過程是非同步,該方法將立即布爾值,指示是否發現已成功啟動恢複。發現過程通常需要約12秒的查詢掃描,隨後每發現裝置檢索其藍芽名稱的頁面掃描。
您的應用程式必須註冊為ACTION_FOUND意圖一個BroadcastReceiver接收關於發現的每個裝置的資訊。對於每個裝置,該系統將播出ACTION_FOUND意圖。此意向進行額外的領域和EXTRA_DEVICE額外的類,分別包含藍牙裝置和BluetoothClass。例如,下面是當裝置被發現,你如何註冊處理廣播:
// Create a BroadcastReceiver for ACTION_FOUNDprivate final BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // Add the name and address to an array adapter to show in a ListView mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } }};// Register the BroadcastReceiverIntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
所有這一切從BluetoothDevice類對象所需要的,以發起串連的MAC地址。在這個例子中,它的儲存做為所顯示給使用者一個ArrayAdapter的一部分。 MAC地址可在以後以發起串連被提取。您可以瞭解更多有關建立大約串連裝置部分的串連。
注意:執行裝置發現是藍芽適配器一個沉重的程式,會消耗大量的資源。一旦你找到了串連一個裝置,可以肯定,你總是在嘗試串連之前停止與發現cancelDiscovery()。此外,如果你已經持有一個裝置的串連,然後執行發現能顯著減少可用於串連頻寬,所以你不應該在串連上執行搜尋。
啟用可發現
如果你想使本地裝置可被其他裝置,調用startActivityForResult(意向,INT)與ACTION_REQUEST_DISCOVERABLE行動意圖。這將發出一個請求,以使通過系統設定發現模式(無需停止應用程式)。預設情況下,該裝置將成為可發現120秒。您可以通過添加EXTRA_DISCOVERABLE_DURATION意向額外的定義不同的期間。一個應用程式可以設定的最長期間為3600秒,值為0意味著裝置總是發現。低於0或高於3600的任何值會自動化佈建為120秒)。例如,該片段設定期限為300:
Intent discoverableIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);
將顯示一個對話方塊,要求使用者權限,使裝置可發現,2。如果使用者回答“是”,則該裝置將成為發現了指定的時間量。那麼你的活動將接收呼叫到的onActivityResult())回調,結果代碼等於該裝置是可發現的期間。如果使用者回答“否”,或者如果發生錯誤,結果代碼將被RESULT_CANCELED。
注意:如果藍芽尚未在裝置上啟用,則使裝置可發現會自動啟用藍芽。
該裝置會悄悄地留在發現模式指定的時間。如果您希望得到通知時,發現模式發生了變化,你可以註冊為ACTION_SCAN_MODE_CHANGED意圖廣播接收器。這將包含額外的領域EXTRA SCAN_MODE和EXTRA_PREVIOUS_SCAN_MODE,它告訴你新老掃描模式,分別為。對於每一個可能的值有SCAN_MODE串連發現,SCAN_MODE_CONNECTABLE或SCAN_MODE_NONE,這表明該裝置是可發現模式,而不是在發現模式,但仍然能夠接收發現模式串連,或者沒有,無法分別接收串連。
不需要啟用裝置可發現如果將發起到遠程裝置的串連。啟用可發現,當你想你的應用程式託管的伺服器通訊端將接受傳入的串連僅僅是必要的,因為遠程裝置必須能夠發現裝置才可以發起串連。
串連裝置
為了建立兩個裝置上的應用程式之間的串連,必須同時實現伺服器端和用戶端的機制,因為一台裝置必須開啟一個伺服器通訊端,另一個必鬚髮起串連(使用伺服器裝置的MAC地址啟動串連)。伺服器和用戶端被認為是相互串連時,他們每個人都有在同一個RFCOMM通道串連的BluetoothSocket。在這一點上,每個裝置都可以擷取輸入和輸出資料流和資料轉送可以開始,這是在大約管理一個串連的部分討論。本節將介紹如何啟動兩個裝置之間的串連。
伺服器裝置和用戶端裝置的每個獲得以不同的方式所需的BluetoothSocket。伺服器將收到它時,傳入的串連被接受。當它開啟一個RFCOMM通道到伺服器的用戶端將收到它。
圖3:藍芽配對對話方塊。
一種實現方法是自動準備每個裝置作為伺服器,讓每個人都有一台伺服器通訊端開啟並偵聽串連。然後或者可以發起與其他的串連,並成為用戶端。另外,一台裝置可以明確的“主機”的串連,並開啟需求的伺服器插座和其他裝置可以簡單地啟動串連。
注意:如果兩個裝置都沒有進行過配對,那麼Android架構會自動顯示在串連過程中的配對請求通知或對話方塊給使用者,作為嘗試串連的裝置所以當3所示,你的應用程式不需要關注裝置是否被配對。你的RFCOMM串連嘗試將阻塞,直到使用者已成功配對,或者如果使用者拒絕配對,如果配對失敗或者逾時就會失敗。
串連作為伺服器
當你想串連兩個裝置,一個必須由持開放BluetoothServerSocket充當伺服器。伺服器通訊端的目的是監聽傳入的串連請求和當一個被接受時,提供一個串連的BluetoothSocket。當的BluetoothSocket從BluetoothServerSocket獲得的,該BluetoothServerSocket可以(也應該)被丟棄,除非你想接受更多的串連。
關於UUID
通用唯一識別碼(UUID)是用來唯一標識資訊的字串ID標準化的128位格式。一個UUID的一點是,它足夠大,你可以選擇任何隨機的,也不會發生衝突。在這種情況下,它是用來唯一標識應用程式的藍芽服務。要獲得UUID與你的應用程式中使用,則可以使用Web上的許多隨機UUID產生器之一,則初始化fromString(String)將UUID。
這裡是基本的程式建立一個伺服器通訊端並接受串連:
通過調用listenUsingRfcommWithServiceRecord(字串,UUID)擷取BluetoothServerSocket。
該字串是你的服務,系統會自動寫入到一個新的服務發現協議在裝置上(SDP)資料庫條目的識別名稱(名稱是任意的,可以簡單地將您的應用程式名稱)。的UUID也包含在SDP條目和將用於與所述用戶端裝置的串連協定的基礎。也就是說,當用戶端試圖與此裝置串連,其將攜帶唯一標識與它要已連線的服務一個UUID。這些的UUID必須以使串連被接受(在下一步驟)相匹配。
開始通過調用accept()方法監聽串連請求。
這是一個阻塞調用。當任一串連被接受或者已經發生異常它將返回。一個串連被接受,只有當遠程裝置已派出匹配與此監聽通訊端伺服器中註冊的一個UUID的串連請求。如果成功,accept()方法將返回一個串連的BluetoothSocket。
除非你想接受更多的串連,調用close()。
這將釋放伺服器插槽及其所有資源,但不會關閉一個已經被接受返回的串連的BluetoothSocket()。不像TCP / IP,RFCOMM只允許每個通道的一個串連的用戶端的時間,因此,在大多數情況下,它是有道理的接受串連通訊端後立即關閉()的調用BluetoothServerSocket。
的接受()調用不應該在主活動UI線程,因為它是一個阻塞調用,並防止與應用程式的任何其它互動來執行。它通常情理之中的事了BluetoothServerSocket或全部的BluetoothSocket工作,你的應用程式管理的一個新的線程。要中止阻塞調用,如接受(),從另一個線程調用clZ喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc2WjqKOp1NpCbHVldG9vdGhTZXJ2ZXJTb2NrZXSjqLvytcRCbHVldG9vdGhTb2NrZXSjqbrN1+jI+7X308O9q8GivLS3tbvYoaPQ6NKq16LS4rXEysfU2kJsdWV0b290aFNlcnZlclNvY2tldLvytcRCbHVldG9vdGhTb2NrZXS1xMv509C3vbeoysfP37PMsLLIq7XEoaM8YnI+Cjxicj4KPGJyPgrA/Txicj4KPGJyPgo8YnI+Cs/Cw+bKx73Tyty0q8jrway907XEt/7O8cb31+m8/rXEvPK7r7Dmsb6jujxicj4KPC9wPgo8cD48L3A+CjxwcmUgY2xhc3M9"brush:java;">private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; public AcceptThread() { // Use a temporary object that is later assigned to mmServerSocket, // because mmServerSocket is final BluetoothServerSocket tmp = null; try { // MY_UUID is the app's UUID string, also used by the client code tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (IOException e) { } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // Keep listening until exception occurs or a socket is returned while (true) { try { socket = mmServerSocket.accept(); } catch (IOException e) { break; } // If a connection was accepted if (socket != null) { // Do work to manage the connection (in a separate thread) manageConnectedSocket(socket); mmServerSocket.close(); break; } } } /** Will cancel the listening socket, and cause the thread to finish */ public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { } }}在本實施例中,只有一個傳入的串連是需要的,所以只要一個串連被接受以及的BluetoothSocket被擷取時,應用程式發送所擷取的BluetoothSocket到一個單獨的線程,關閉BluetoothServerSocket並中斷環路。
需要注意的是accept()返回的BluetoothSocket的時候,插座已串連,所以你不應該調用connect()(當你從用戶端做的)。
管理器串連插座()是在將啟動該線程用於傳送資料,這是在大約管理一個串連部分中所討論的應用的一個虛構的方法。
通常你應該儘快關閉BluetoothServerSocket為你做偵聽傳入串連。在這個例子中,接近()被儘快的BluetoothSocket擷取調用。您可能還需要提供你的線程公開的方法,可以在你需要停止監聽伺服器通訊端上的事件關閉的BluetoothSocket私人。
串連作為用戶端
為了與遠程裝置(裝置保持一個開放的伺服器通訊端)的串連,您必須首先擷取表示遠程裝置BluetoothDevice類的對象。 (擷取一個BluetoothDevice類是覆蓋在關於尋找裝置上面的部分。)然後,您必須使用BluetoothDevice類收購的BluetoothSocket,並啟動串連。
這裡的基本步驟:
使用BluetoothDevice類,通過調用createRfcommSocketToServiceRecord(UUID)獲得的BluetoothSocket。
這一個初始化的BluetoothSocket將串連到BluetoothDevice類。這裡傳遞的UUID必須開業時其BluetoothServerSocket(帶listenUsingRfcommWithServiceRecord(字串,UUID))由伺服器裝置使用的UUID相匹配。使用相同的UUID是一個簡單的硬式編碼UUID字串到您的應用程式,然後從伺服器端和用戶端的代碼都引用它的問題。
啟動通過調用串連的串連()。
在此呼叫時,系統會以匹配的UUID遠程裝置上執行的SDP尋找。如果尋找成功與遠程裝置接受串連,它會共用串連過程中使用和connect()將返回RFCOMM通道。這種方法是一個阻塞調用。如果因任何原因,串連失敗或者connect()方法逾時(約12秒後),那麼它會拋出異常。
由於串連()是一個阻塞調用,這個串連過程應始終在一個線程執行從主線程的活動分開。
注意:您應始終確保裝置未進行裝置發現,當你調用connect()。如果發現是進行中中,那麼串連嘗試將顯著減緩,更可能失敗。
例
這裡是發起藍芽串連一個線程的一個基本的例子:
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { // Use a temporary object that is later assigned to mmSocket, // because mmSocket is final BluetoothSocket tmp = null; mmDevice = device; // Get a BluetoothSocket to connect with the given BluetoothDevice try { // MY_UUID is the app's UUID string, also used by the server code tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { } mmSocket = tmp; } public void run() { // Cancel discovery because it will slow down the connection mBluetoothAdapter.cancelDiscovery(); try { // Connect the device through the socket. This will block // until it succeeds or throws an exception mmSocket.connect(); } catch (IOException connectException) { // Unable to connect; close the socket and get out try { mmSocket.close(); } catch (IOException closeException) { } return; } // Do work to manage the connection (in a separate thread) manageConnectedSocket(mmSocket); } /** Will cancel an in-progress connection, and close the socket */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } }}
注意到cancelDiscovery()由串連之前被調用。你應該總是串連之前做到這一點,它是安全的,而無需實際檢查它是否正在運行或不調用(但如果你想查詢,調用isDiscovering())。
manageConnectedSocket()是在將啟動該線程用於傳送資料,這是在大約管理一個串連部分中所討論的應用的一個虛構的方法。
當你與你的BluetoothSocket完成後,總是調用close()進行清理。這樣做將立即關??閉串連通訊端,並清理所有內部資源。
管理串連
當您成功串連的兩個(或多個)裝置,每一個都會有一個串連的BluetoothSocket。這是有趣的開始,因為你可以在裝置之間共用資料。使用的BluetoothSocket,一般方法來傳輸任意資料是簡單的:
獲得通過通訊端控制代碼傳輸的InputStream和OutputStream,通過的getInputStream()和的getOutputStream(),分別為。
具有讀取讀取和寫入資料流(位元組[])和寫(位元組[])。
而已。
有,當然,實現的細節要考慮。首先,你應該使用一個專用的線程所有流讀取和寫入。這是重要的,因為這兩種讀取(位元組[])和寫(位元組[])方法阻塞調用。閱讀(位元組[])將阻塞,直到有東西從流中讀取。寫(位元組[])通常不阻塞,但如果遠程裝置沒有調用read(位元組[])的速度不夠快,並在中間緩衝區已滿可以阻止流量控制。所以,你線上程主迴圈應專門用於從InputStream讀取。線上程一個單獨的公用方法可以用於啟動寫入到輸出資料流。
例
這裡有一個如何這可能外觀的樣本:
private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // Get the input and output streams, using temp objects because // member streams are final try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { byte[] buffer = new byte[1024]; // buffer store for the stream int bytes; // bytes returned from read() // Keep listening to the InputStream until an exception occurs while (true) { try { // Read from the InputStream bytes = mmInStream.read(buffer); // Send the obtained bytes to the UI activity mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer) .sendToTarget(); } catch (IOException e) { break; } } } /* Call this from the main activity to send data to the remote device */ public void write(byte[] bytes) { try { mmOutStream.write(bytes); } catch (IOException e) { } } /* Call this from the main activity to shutdown the connection */ public void cancel() { try { mmSocket.close(); } catch (IOException e) { } }}
建構函式擷取必要的資料流和執行一次,該線程將等待資料來通過InputStream的。當讀取(位元組[])與從流的位元組返回時,資料是使用從父類中的成員處理常式發送到主活性。然後它返回,並等待從流更多的位元組。
發送傳出資料是從調用的主要活動線程的write()方法,並在位元組傳遞給發送一樣簡單。然後,此方法簡單地調用寫(位元組[])的資料發送到遠程裝置。
線程的取消()方法是重要的,這樣的串連可以在任何時候,通過關閉所述的BluetoothSocket被終止。當你使用藍芽串連來完成這應始終被調用。
對於使用藍芽API的示範,請參見藍芽聊天應用程式範例。
使用設定檔
在Android 3.0的開始,藍芽API包括與藍芽設定檔的工作的支援。藍芽設定檔是裝置間基於藍芽的通訊的無線介面規範。一個例子是免提模式。對於手機串連到一個無線耳機,兩個裝置必須支援免提模式。
您可以實現介面BluetoothProfile編寫自己的類來支援特定的Bluetooth設定檔。 Android的藍芽API提供實現以下藍芽規範:
耳機。耳機設定檔提供與手機使用藍芽耳機的支援。機器人提供BluetoothHeadset類,它是對經由處理序間通訊(IPC)控制所述藍芽耳機服務的代理。這包括藍芽耳機和免提(V1.5)型材。該BluetoothHeadset類包括AT命令的支援。有關此主題的更多討論,請參閱供應商特定的AT命令
A2DP。進階音頻傳輸模式(A2DP)設定檔定義了如何高品質的音頻檔案可以被串流從一個裝置到另一個通過藍芽串連。機器人提供BluetoothA2dp類,它是通過IPC控制A2DP藍芽服務的代理。
衛生裝置。搭載Android 4.0(API層級14)引入了藍芽醫療設備規範(HDP)的支援。這使您可以建立使用藍芽與支援藍芽的醫療設備,如心臟速率監視器,血液米,溫度計,衡器等通訊的應用程式。對於支援的裝置及其相應的裝置資料專業化代碼的列表,請參閱在www.bluetooth.org支援藍芽編號分配。請注意,這些值也在ISO / IEEE 11073-20601 [7]規範作為MDC_DEV_SPEC_PROFILE_ *的命名代碼附件中引用。對於HDP的更多討論,請參見醫療設備規範。
下面是用於與資訊的工作的基本步驟:
擷取預設的適??配器,如設定藍芽描述。
使用getProfileProxy()建立與設定檔關聯的設定檔的代理對象的串連。在下面的例子中,設定檔代理對象是BluetoothHeadset的一個執行個體。
設定一個BluetoothProfile.ServiceListener。此偵聽通知BluetoothProfile IPC用戶端時,他們已經串連或從服務斷開。
在onServiceConnected(),得到一個處理設定檔代理對象。
一旦你的輪廓代理對象,你可以用它來監視串連的狀態,並執行相關的該設定檔等操作。
例如,下面的程式碼片段展示了如何串連到一個BluetoothHeadset代理對象,這樣就可以控制耳機設定檔:
BluetoothHeadset mBluetoothHeadset;// Get the default adapterBluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// Establish connection to the proxy.mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = (BluetoothHeadset) proxy; } } public void onServiceDisconnected(int profile) { if (profile == BluetoothProfile.HEADSET) { mBluetoothHeadset = null; } }};// ... call functions on mBluetoothHeadset// Close proxy connection after use.mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
供應商特定的AT命令
在Android 3.0的開始,應用可以註冊來接收的系統廣播預定義的供應商特定的AT通過耳機(如Plantronics的+ XEVENT命令)發送的命令。例如,應用程式可以接收指示一個串連的裝置的電池電量廣播並可以通知使用者或根據需要採取其他行動。建立用於ACTION_VENDOR_SPECIFIC_HEADSET_EVENT意圖處理廠商特定的AT的耳機命令的廣播接收機。
醫療設備規範
搭載Android 4.0(API層級14)引入了藍芽醫療設備規範(HDP)的支援。這使您可以建立使用藍芽與支援藍芽的醫療設備,如心臟速率監視器,血液米,溫度計,並且可擴充到通訊的應用程式。藍芽健康API包括類BluetoothHealth,BluetoothHealthCallback和BluetoothHealthAppConfiguration,這在基礎知識介紹。
在使用藍芽API健康,它有助於理解這些關鍵概念HDP:
概念說明
源HDP定義的角色。源是一種健康的裝置,傳輸醫學資料(計重秤,血糖計,溫度計等),智慧型裝置如Android手機或平板電腦。
下沉HDP定義的角色。在HDP,水槽是接收醫學資料智慧型裝置。在一個Android應用程式HDP,水槽由BluetoothHealthAppConfiguration對象表示。
註冊是指註冊水槽特定保健裝置。
串連是指開啟保健裝置與智慧型裝置之間的通道,例如Android手機或平板電腦。
建立HDP應用
以下是參與建立一個Android應用程式HDP的基本步驟:
擷取到BluetoothHealth代理對象的引用。
類似普通耳機和A2DP功能的裝置,你必須調用getProfileProxy()與BluetoothProfile.ServiceListener和健康情況的類型,建立與輪廓的代理對象的串連。
建立BluetoothHealthCallback並註冊充當健康水槽應用程式配置(BluetoothHealthAppConfiguration)。
建立到衛生裝置的串連。有些裝置將啟動串連。它是不需要進行此步驟的那些裝置。
當成功地串連到一個醫療設備,讀/寫使用檔案描述符衛生裝置。
所接收的資料需要使用它實現了IEEE 11073-XXXXX規格健康管理器來解釋。
完成後,關閉健康頻道和登出應用程式。當有擴充活動的通道也關閉。
對於說明了這些步驟的完整程式碼範例,請參閱藍芽HDP(醫療設備設定檔)。