Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android API Guides---Bluetooth

Android API Guides---Bluetooth

編輯:關於Android編程

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 devices
if (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_FOUND
private 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 BroadcastReceiver
IntentFilter 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 = new
Intent(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喎?/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 adapter
BluetoothAdapter 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(健康設備配置文件)。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved