久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android之Bluetooth

 fhr625 2013-10-30

對于Android的英文幫助文檔,總是看了記不住,,遠不如對中文資料那么印象深,,所以下面的敘述都是對Android幫助文檔Bluetooth的翻譯。

一,、Bluetooth
Android平臺包含了對Bluetooth協(xié)議棧的支持,,允許機器通過Bluetooth設(shè)備進行無線數(shù)據(jù)交換。應(yīng)用框架通過Android Bluetooth API訪問Bluetooth功能模塊,。 這些API能讓應(yīng)用無線連接其他Bluetooth設(shè)備,實現(xiàn)點對點和多點之間的通信,。
運用藍牙API,,Android應(yīng)用程序可以完成如下操作:
1、掃描其他Bluetooth設(shè)備,。
2,、查詢配對Bluetooth設(shè)備的本地Bluetooth適配器。
3,、建立RFCOMM通道,。
4、通過服務(wù)探索連接到其他設(shè)備,。
5,、與其他設(shè)備進行數(shù)據(jù)傳輸。
6,、管理多個連接

二,、The Basics
本文描述如何使用Android Bluetooth APIs完成Bluetooth通訊的4個必要任務(wù):設(shè)置Bluetooth,搜尋本地配對或者可用的Bluetooth設(shè)備,,連接Bluetooth設(shè)備,,與Bluetooth設(shè)備進行數(shù)據(jù)傳輸。
所有可用的Bluetooth APIs都包含在android.bluetooth包中,。下面是建立Bluetooth連接需要用到的類和接口的總結(jié):
1,、BluetoothAdapter
描述本地Bluetooth適配器(Bluetooth接收器)。BluetoothAdapter是所有Bluetooth相關(guān)活動的入口,。運用 BluetoothAdapter可以發(fā)現(xiàn)其他Bluetooth設(shè)備,,查詢連接(或配對)的設(shè)備列表,用已知MAC地址實例化一個 BluetoothDevice對象,,創(chuàng)建一個BluetoothServerSocket對象偵聽其他設(shè)備的通信,。
2、BluetoothDevice
描述一個遠程Bluetooth設(shè)備,??梢杂盟ㄟ^一個BluetoothSocket請求一個遠程設(shè)備的連接,或者查詢遠程設(shè)備的名稱、地址,、類,、連接狀態(tài)等信息。
3,、BluetoothSocket
描述一個Bluetooth Socket接口(類似于TCP Socket),。應(yīng)用通過InputStream和OutputStream.與另外一個Bluetooth設(shè)備交換數(shù)據(jù),即它是應(yīng)用與另外一個設(shè)備交換數(shù)據(jù)的連接點,。
4,、BluetoothServerSocket
描述一個開放的socket服務(wù)器,用來偵聽連接進來的請求(類似于RCP ServerSocket),。為了連接兩個Android設(shè)備,,一個設(shè)備必須使用該類來開啟一個socket做服務(wù)器,當另外一個設(shè)備對它發(fā)起連接請求時 并且請求被接受時,,BluetoothServerSocket會返回一個連接的BluetoothSocket對象,。
5、BluetoothClass
描述一個Bluetooth設(shè)備的一般規(guī)格和功能,。這個是用來定義設(shè)備類和它的服務(wù)的只讀屬性集,。然而,它并不是可靠的描述設(shè)備支持的所有Bluetooth配置和服務(wù),,而只是一些設(shè)備類型的有用特征,。
6、BluetoothProfile
描述Bluetooth Profile的接口,。Bluetooth Profile是兩個設(shè)備基于藍牙通訊的無線接口描述,。
(對Bluetooth Profile的詳細解釋,來自百度:為了更容易的保持Bluetooth設(shè)備之間的兼容,,Bluetooth規(guī)范中定義了 Profile,。Profile定義了設(shè)備如何實現(xiàn)一種連接或者應(yīng)用,你可以把Profile理解為連接層或者應(yīng)用層協(xié)議,。 比如,,如果一家公司希望它們的Bluetooth芯片支援所有的Bluetooth耳機,那么它只要支持HeadSet Profile即可,,而無須考慮該芯片與其它Bluetooth設(shè)備的通訊與兼容性問題,。如果你想購買Bluetooth產(chǎn)品,你應(yīng)該了解你的應(yīng)用需要哪 些Profile來完成,,并且確保你購買的Bluetooth產(chǎn)品支持這些Profile,。)
7、BluetoothHeadset
提供移動電話的Bluetooth耳機支持,。包括Bluetooth耳機和Hands-Free (v1.5) profiles,。
8,、BluetoothA2dp
定義兩個設(shè)備間如何通過Bluetooth連接進行高質(zhì)量的音頻傳輸。
A2DP(Advanced Audio Distribution Profile):高級音頻傳輸模式,。
9,、BluetoothProfile.ServiceListener
一個接口描述,在與服務(wù)連接或者斷連接的時候通知BluetoothProfile IPC(這是內(nèi)部服務(wù)運行的一個特定的模式<profile>),。

三,、Bluetooth Permissions
要使用Bluetooth功能,至少需要2個Bluetooth權(quán)限:BLUETOOTHBLUETOOTH_ADMIN.
BLUETOOTH:用來授權(quán)任何Bluetooth通信,,如請求連接,,接受連接,傳輸數(shù)據(jù)等,。
BLUETOOTH_ADMIN:用來授權(quán)初始化設(shè)備搜索或操作Bluetooth設(shè)置,。大多數(shù)應(yīng)用需要它的唯一場合是用來搜索本地Bluetooth設(shè) 備。本授權(quán)的其他功能不應(yīng)該被使用,,除非是需要修改Bluetooth設(shè)置的“power manager(電源管理)”應(yīng)用,。
注意:需要BLUETOOTH_ADMIN權(quán)限的場合,,BLUETOOTH權(quán)限也是必需的,。
需要在manifest文件中聲明Bluetooth權(quán)限,示例如下:
<manifest ... >
  <uses-permission android:name="android.permission.BLUETOOTH" />
  ...
</manifest>

四,、Setting Up Bluetooth
在用Bluetooth通訊之前,,需要確認設(shè)備是否支持Bluetooth,如果支持,,還得確保Bluetooth是可用的,。
如果設(shè)備不支持Bluetooth,需要優(yōu)雅的將Bluetooth置為不可用,。如果支持Bluetooth,,但沒有開啟,可以在應(yīng)用中請求開啟Bluetooth,。該設(shè)置使用BluetoothAdapter.通過兩個步驟完成,。
1、獲取BluetoothAdapter
BluetoothAdapter是每個Bluetooth的Activity都需要用到的,。用靜態(tài)方法getDefaultAdapter()獲取 BluetoothAdapter,,返回一個擁有Bluetooth 適配器的BluetoothAdapter對象。如果返回null,,說明設(shè)備不支持Bluetooth,,關(guān)于Bluetooth的故事到此就結(jié)束了(因為 你干不了什么了)。示例:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
    // Device does not support Bluetooth
}
2,、Enable Bluetooth
接下來,,就是確保Bluetooth功能是開啟的,。調(diào)用isEnabled()來檢查Bluetooth當前是否是開啟的。用 ACTION_REQUEST_ENABLE action Intent調(diào)用startActivityForResult()來請求開啟Bluetooth,,這會通過系統(tǒng)設(shè)置發(fā)出一個Bluetooth使能請求 (并且不會停止本應(yīng)用程序),。示例:
if (!mBluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
用戶請求使能Bluetooth時,會顯示一個對話框,。選擇“Yes”,,系統(tǒng)會使能Bluetooth,并且焦點會返回你的應(yīng)用程序,。
如果使能Bluetooth成功,,你的Activity會在onActivityResult()回調(diào)函數(shù)中收到RESULT_OK的結(jié)果碼。如果Bluetooth使能因發(fā)生錯誤(或用戶選擇了“No”)而失敗,,收到的結(jié)果碼將是RESULT_CANCELED,。
作為可選項,應(yīng)用也可以偵聽ACTION_STATE_CHANGED broadcast Intent,,這樣無論Bluetooth狀態(tài)何時被改變系統(tǒng)都會發(fā)出broadcast(廣播),。該廣播包含附加的字段信息EXTRA_STATE和 EXTRA_PREVIOUS_STATE分別代表新的和舊的Bluetooth狀態(tài),該字段可能的值為STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, 和STATE_OFF,。應(yīng)用運行時,,偵聽ACTION_STATE_CHANGED廣播來檢測Bluetooth狀態(tài)的改變是很有用的。
提示:啟用Bluetooth可被發(fā)現(xiàn)功能能夠自動開啟Bluetooth,。如果在完成Activity之前需要持續(xù)的使能Bluetooth可被發(fā)現(xiàn)功能,,那么上面的第2步就可以忽略。

五,、Finding Devices
使用BluetoothAdapter可以通過設(shè)備搜索或查詢配對設(shè)備找到遠程Bluetooth設(shè)備,。
Device discovery(設(shè)備搜索)是一個掃描搜索本地已使能Bluetooth設(shè)備并且從搜索到的設(shè)備請求一些信息的過程(有時候會收到類似 “discovering”,“inquiring”或“scanning”),。但是,,搜索到的本地Bluetooth設(shè)備只有在打開被發(fā)現(xiàn)功能后才會響 應(yīng)一個discovery請求,響應(yīng)的信息包括設(shè)備名,,類,,唯一的MAC地址。發(fā)起搜尋的設(shè)備可以使用這些信息來初始化跟被發(fā)現(xiàn)的設(shè)備的連接,。
一旦與遠程設(shè)備的第一次連接被建立,,一個pairing請求就會自動提交給用戶。如果設(shè)備已配對,,配對設(shè)備的基本信息(名稱,,類,MAC地址)就被保存下 來了,,能夠使用Bluetooth API來讀取這些信息,。使用已知的遠程設(shè)備的MAC地址,,連接可以在任何時候初始化而不必先完成搜索(當然這是假設(shè)遠程設(shè)備是在可連接的空間范圍內(nèi))。

需要記住,,配對和連接是兩個不同的概念
配對意思是兩個設(shè)備相互意識到對方的存在,,共享一個用來鑒別身份的鏈路鍵(link-key),能夠與對方建立一個加密的連接,。
連接意思是兩個設(shè)備現(xiàn)在共享一個RFCOMM信道,,能夠相互傳輸數(shù)據(jù)。

目前Android Bluetooth API's要求設(shè)備在建立RFCOMM信道前必須配對(配對是在使用Bluetooth API初始化一個加密連接時自動完成的),。

下面描述如何查詢已配對設(shè)備,,搜索新設(shè)備。
注意:Android的電源設(shè)備默認是不能被發(fā)現(xiàn)的,。用戶可以通過系統(tǒng)設(shè)置讓它在有限的時間內(nèi)可以被發(fā)現(xiàn),,或者可以在應(yīng)用程序中要求用戶使能被發(fā)現(xiàn)功能。

1,、Querying paired devices
在搜索設(shè)備前,,查詢配對設(shè)備看需要的設(shè)備是否已經(jīng)是已經(jīng)存在是很值得的,可以調(diào)用getBondedDevices()來做到,,該函數(shù)會返回一個描述配對 設(shè)備BluetoothDevice的結(jié)果集,。例如,可以使用ArrayAdapter查詢所有配對設(shè)備然后顯示所有設(shè)備名給用戶:
Set<BluetoothDevice> 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地址,。

2,、Discovering devices
要開始搜索設(shè)備,,只需簡單的調(diào)用startDiscovery(),。該函數(shù)時異步的,調(diào)用后立即返回,,返回值表示搜索是否成功開始,。搜索處理通常包括一個12秒鐘的查詢掃描,然后跟隨一個頁面顯示搜索到設(shè)備Bluetooth名稱,。
應(yīng)用中可以注冊一個帶CTION_FOUND Intent的BroadcastReceiver,,搜索到每一個設(shè)備時都接收到消息。對于每一個設(shè)備,,系統(tǒng)都會廣播ACTION_FOUND Intent,,該Intent攜帶著而外的字段信息EXTRA_DEVICE和EXTRA_CLASS,分別包含一個BluetoothDevice和一 個BluetoothClass,。下面的示例顯示如何注冊和處理設(shè)備被發(fā)現(xiàn)后發(fā)出的廣播:
// 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

警告:完成設(shè)備搜索對于Bluetooth適配器來說是一個重量級的處理,,要消耗大量它的資源。一旦你已經(jīng)找到一個設(shè)備來連接,,請確保你在嘗試連接 前使用了cancelDiscovery()來停止搜索,。同樣,,如果已經(jīng)保持了一個連接的時候,同時執(zhí)行搜索設(shè)備將會顯著的降低連接的帶寬,,所以在連接的 時候不應(yīng)該執(zhí)行搜索發(fā)現(xiàn),。

3、Enabling discoverability
如果想讓本地設(shè)備被其他設(shè)備發(fā)現(xiàn),,可以帶ACTION_REQUEST_DISCOVERABLE action Intent調(diào)用startActivityForResult(Intent, int) 方法,。該方法會提交一個請求通過系統(tǒng)剛設(shè)置使設(shè)備出于可以被發(fā)現(xiàn)的模式(而不影響應(yīng)用程序)。默認情況下,,設(shè)備在120秒后變?yōu)榭梢员话l(fā)現(xiàn)的,。可以通過額 外增加EXTRA_DISCOVERABLE_DURATION Intent自定義一個值,,最大值是3600秒,,0表示設(shè)備總是可以被發(fā)現(xiàn)的(小于0或者大于3600則會被自動設(shè)置為120秒)。下面示例設(shè)置時間為 300:
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
詢問用戶是否允許打開設(shè)備可以被發(fā)現(xiàn)功能時會顯示一個對話框,。如果用戶選擇“Yes”,,設(shè)備會在指定時間過后變?yōu)榭梢员话l(fā)現(xiàn)的。Activity的 onActivityResult()回調(diào)函數(shù)被調(diào)用,,結(jié)果碼等于設(shè)備變?yōu)榭梢员话l(fā)現(xiàn)所需時長,。如果用戶選擇“No”或者有錯誤發(fā)生,結(jié)果碼會是 Activity.RESULT_CANCELLED,。
提示:如果Bluetooth沒有啟用,,啟用Bluetooth可被發(fā)現(xiàn)功能能夠自動開啟Bluetooth。
在規(guī)定的時間內(nèi),,設(shè)備會靜靜的保持可以被發(fā)現(xiàn)模式,。如果想在可以被發(fā)現(xiàn)模式被更改時受到通知,可以用ACTION_SCAN_MODE_CHANGED Intent注冊一個BroadcastReceiver,,包含額外的字段信息EXTRA_SCAN_MODE和 EXTRA_PREVIOUS_SCAN_MODE分別表示新舊掃描模式,,其可能的值為 SCAN_MODE_CONNECTABLE_DISCOVERABLE(discoverable mode),SCAN_MODE_CONNECTABLE(not in discoverable mode but still able to receive connections),,SCAN_MODE_NONE(not in discoverable mode and unable to receive connections),。
如果只需要連接遠程設(shè)備就不需要打開設(shè)備的可以被發(fā)現(xiàn)功能。只在應(yīng)用作為一個服務(wù)器socket的宿主用來接收進來的連接時才需要使能可以被發(fā)現(xiàn)功能,,因為遠程設(shè)備在初始化連接前必須先發(fā)現(xiàn)了你的設(shè)備,。

六、Connecting Devices
為了建立兩個設(shè)備之間的應(yīng)用的連接,,需要完成服務(wù)器端和客戶端,,因為一個設(shè)備必須打開一個服務(wù)器socket而另外一個設(shè)備必須初始化連接(用服務(wù)器端的 MAC地址)。服務(wù)器和客戶端在各自獲得一個基于同一個RFCOMM信道的已連接的BluetoothSocket對象后就被認為連接已經(jīng)建立,。這個時 候,,雙方設(shè)備可以獲取輸入輸出流,,數(shù)據(jù)傳輸可以開始了。本節(jié)描述如何在兩個設(shè)備之間初始化連接,。
服務(wù)器設(shè)備和客戶端設(shè)備用不同的方式獲取各自需要的BluetoothSocket對象,。服務(wù)器端的在接收一個進來的連接時獲取到,客戶端的在打開一個與服務(wù)器端的RFCOMM信道的時候獲取到,。
一個實現(xiàn)技巧是自動把每個設(shè)備作為服務(wù)器,,這樣就擁有了一個打開的socket用來偵聽連接。然后任一設(shè)備就能夠發(fā)起與另一個設(shè)備的連接,,并成為客戶端,。另外,一個設(shè)備也可以明確的成為“host”,,并打開一個服務(wù)端socket,,另一個設(shè)備可以簡單的發(fā)起連接。
注意:如果兩個設(shè)備之前沒有配對,,那么在連接處理過程中Android應(yīng)用框架會自動顯示一個配對請求的通知或?qū)υ捒蚪o用戶,。因此,當嘗試連接設(shè)備時,,應(yīng) 用不需要關(guān)心設(shè)備是否已經(jīng)配對,。RFCOMM連接會阻塞直到用戶成功將設(shè)備配對(如果用戶拒絕配對或者配對超時了連接會失敗)。

1,、Connecting as a server
如果要連接兩個設(shè)備,,其中一個必須充當服務(wù)器,通過持有一個打開的BluetoothServerSocket對象,。服務(wù)器socket的作用是偵聽進來 的連接,,如果一個連接被接受,提供一個連接好的BluetoothSocket對象,。從BluetoothServerSocket獲取到 BluetoothSocket對象之后,,BluetoothServerSocket就可以(也應(yīng)該)丟棄了,,除非你還要用它來接收更多的連接,。

下面是建立服務(wù)器socket和接收一個連接的基本步驟:
1.通過調(diào)用listenUsingRfcommWithServiceRecord(String, UUID)得到一個BluetoothServerSocket對象。
該字符串為服務(wù)的識別名稱,,系統(tǒng)將自動寫入到一個新的服務(wù)發(fā)現(xiàn)協(xié)議(SDP)數(shù)據(jù)庫接入口到設(shè)備上的(名字是任意的,,可以簡單地是應(yīng)用程序的名稱)項。 UUID也包括在SDP接入口中,,將是客戶端設(shè)備連接協(xié)議的基礎(chǔ),。也就是說,當客戶端試圖連接本設(shè)備,,它將攜帶一個UUID用來唯一標識它要連接的服 務(wù),,UUID必須匹配,,連接才會被接受。
2.通過調(diào)用accept()來偵聽連接請求,。
這是一個阻塞的調(diào)用,,知道有連接進來或者產(chǎn)生異常才會返回。只有遠程設(shè)備發(fā)送一個連接請求,,并且攜帶的UUID與偵聽它socket注冊的UUID匹配,,連接請求才會被接受。如果成功,,accept()將返回一個連接好的BluetoothSocket對象,。
3.除非需要再接收另外的連接,否則的話調(diào)用close(),。
close()釋放server socket和它的資源,,但不會關(guān)閉連接accept()返回的連接好的BluetoothSocket對象。與TCP/IP不同,,RFCOMM同一時刻 一個信道只允許一個客戶端連接,,因此大多數(shù)情況下意味著在BluetoothServerSocket接受一個連接請求后應(yīng)該立即調(diào)用close()。

accept()調(diào)用不應(yīng)該在主Activity UI線程中進行,,因為這是個阻塞的調(diào)用,,會妨礙其他的交互。經(jīng)常是在在一個新線程中做BluetoothServerSocket或 BluetoothSocket的所有工作來避免UI線程阻塞,。注意所有BluetoothServerSocket或BluetoothSocket的 方法都是線程安全的,。

示例:
下面是一個簡單的接受連接的服務(wù)器組件代碼示例:
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,,就發(fā)送獲取到的BluetoothSocket給一個單獨的線程,然后關(guān)閉BluetoothServerSocket并跳出循環(huán),。
注意:accept()返回BluetoothSocket后,,socket已經(jīng)連接了,所以在客戶端不應(yīng)該呼叫connnect(),。
manageConnectedSocket()是一個虛方法,,用來初始化線程好傳輸數(shù)據(jù)。
通常應(yīng)該在處理完偵聽到的連接后立即關(guān)閉BluetoothServerSocket,。在本例中,,close()在得到BluetoothSocket后 馬上被調(diào)用。還需要在線程中提供一個公共的方法來關(guān)閉私有的BluetoothSocket,,停止服務(wù)端socket的偵聽,。

2、Connecting as a client
為了實現(xiàn)與遠程設(shè)備的連接,你必須首先獲得一個代表遠程設(shè)備BluetoothDevice對象,。然后使用BluetoothDevice對象來獲取一個BluetoothSocket來實現(xiàn)來接,。
下面是基本的步驟:
1.用BluetoothDevice調(diào)用createRfcommSocketToServiceRecord(UUID)獲取一個BluetoothSocket對象。
這個初始化的BluetoothSocket會連接到BluetoothDevice,。UUID必須匹配服務(wù)器設(shè)備在打開 BluetoothServerSocket 時用到的UUID(用listenUsingRfcommWithServiceRecord(String, UUID)),。可以簡單的生成一個UUID串然后在服務(wù)器和客戶端都使用該UUID,。
2.調(diào)用connect()完成連接
當調(diào)用這個方法的時候,,系統(tǒng)會在遠程設(shè)備上完成一個SDP查找來匹配UUID。如果查找成功并且遠程設(shè)備接受連接,,就共享RFCOMM信道,,connect()會返回。這也是一個阻塞的調(diào)用,,不管連接失敗還是超時(12秒)都會拋出異常,。
注意:要確保在調(diào)用connect()時沒有同時做設(shè)備查找,如果在查找設(shè)備,,該連接嘗試會顯著的變慢,,慢得類似失敗了。

實例:
下面是一個完成Bluetooth連接的樣例線程:
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()在連接操作前被調(diào)用,。在連接之前,,不管搜索有沒有進行,該調(diào)用都是安全的,,不需要確認(當然如果有要確認的需求,,可以調(diào)用isDiscovering())。
manageConnectedSocket()是一個虛方法,,用來初始化線程好傳輸數(shù)據(jù),。
在對BluetoothSocket的處理完成后,記得調(diào)用close()來關(guān)閉連接的socket和清理所有的內(nèi)部資源,。

七,、Managing a Connection
如果已經(jīng)連接了兩個設(shè)備,他們都已經(jīng)擁有各自的連接好的BluetoothSocket對象,。那就是一個有趣的開始,,因為你可以在設(shè)備間共享數(shù)據(jù)了。使用BluetoothSocket,,傳輸任何數(shù)據(jù)通常來說都很容易了:
1.通過socket獲取輸入輸出流來處理傳輸(分別使用getInputStream()和getOutputStream()),。
2.用read(byte[])和write(byte[])來實現(xiàn)讀寫。
僅此而已,。

當然,還是有很多細節(jié)需要考慮的,。首要的,,需要用一個專門的線程來實現(xiàn)流的讀寫,。只是很重要的,因為read(byte[])和 write(byte[])都是阻塞的調(diào)用,。read(byte[])會阻塞直到流中有數(shù)據(jù)可讀,。write(byte[])通常不會阻塞,但是如果遠程 設(shè)備調(diào)用read(byte[])不夠快導(dǎo)致中間緩沖區(qū)滿,,它也可能阻塞,。所以線程中的主循環(huán)應(yīng)該用于讀取InputStream。線程中也應(yīng)該有單獨的 方法用來完成寫OutputStream,。

示例:
下面是一個如上面描述那樣的例子:
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) { }
    }
}
構(gòu)造函數(shù)中得到需要的流,,一旦執(zhí)行,線程會等待從InputStream來的數(shù)據(jù),。當read(byte[])返回從流中讀到的字節(jié)后,,數(shù)據(jù)通過父類的成員Handler被送到主Activity,然后繼續(xù)等待讀取流中的數(shù)據(jù),。
向外發(fā)送數(shù)據(jù)只需簡單的調(diào)用線程的write()方法,。
線程的cancel()方法時很重要的,以便連接可以在任何時候通過關(guān)閉BluetoothSocket來終止,。它應(yīng)該總在處理完Bluetooth連接后被調(diào)用,。

八、Working with Profiles
從Android 3.0開始,,Bluetooth API就包含了對Bluetooth profiles的支持,。Bluetooth profile是基于藍牙的設(shè)備之間通信的無線接口規(guī)范。例如Hands-Free profile(免提模式),。如果移動電話要連接一個無線耳機,,他們都要支持Hands-Free profile。
你在你的類里可以完成BluetoothProfile接口來支持某一Bluetooth profiles,。Android Bluetooth API完成了下面的Bluetooth profile:
Headset:Headset profile提供了移動電話上的Bluetooth耳機支持,。Android提供了BluetoothHeadset類,它是一個協(xié)議,,用來通過 IPC(interprocess communication)控制Bluetooth Headset Service,。BluetoothHeadset既包含Bluetooth Headset profile也包含Hands-Free profile,還包括對AT命令的支持,。
A2DP:Advanced Audio Distribution Profile (A2DP) profile,,高級音頻傳輸模式。Android提供了BluetoothA2dp類,,這是一個通過IPC來控制Bluetooth A2DP的協(xié)議,。

下面是使用profile的基本步驟:
1.獲取默認的Bluetooth適配器。
2.使用getProfileProxy()來建立一個與profile相關(guān)的profile協(xié)議對象的連接。在下面的例子中,,profile協(xié)議對象是BluetoothHeadset的一個實例,。
3.設(shè)置BluetoothProfile.ServiceListener。該listener通知BluetoothProfile IPC客戶端,,當客戶端連接或斷連服務(wù)器的時候,。
4.在onServiceConnected()內(nèi),得到一個profile協(xié)議對象的句柄,。
5. 一旦擁有了profile協(xié)議對象,,就可以用它來監(jiān)控連接的狀態(tài),完成于該profile相關(guān)的其他操作,。

例如,,下面的代碼片段顯示如何連接到一個BluetoothHeadset協(xié)議對象,用來控制Headset profile:
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);

1,、Vendor-specific AT commands
從Android 3.0開始,,應(yīng)用程序可以注冊偵聽預(yù)定義的Vendor-specific AT命令這樣的系統(tǒng)廣播(如Plantronics +XEVENT command)。例如,,應(yīng)用可以接收到一個廣播,,該廣播表明連接的設(shè)備電量過低,然后通知用戶做好其他需要的操作,。創(chuàng)建一個帶 ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intent的broadcast receiver來為耳機處理
Vendor-specific AT commands,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多