Reference:
http://developer.android.com/guide/topics/connectivity/bluetooth.htmlGet BluetoothAdapter:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
Enable Bluetooth:
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
Quering paired devices:
MAC address可以用來初始化BluetoothDevice物件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());
}
}
Discovering devices:
只要呼叫 startDiscovery()就可以開始尋找device應用程式需要註冊一個broadcase receiver來接收搜尋到的device的資訊
// 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
注意:
執行搜尋device會消耗很多資源,所以當找到一個要連接的device,在連接前要先呼叫cancelDiscovery(),停止搜尋device。
另外,當已經在連接中的情況下進行搜尋device,會減少已連接的連線的頻寬,所以在已連接的情況下不要再搜尋device
Get BluetoothDevice:
BluetoothAdapterpublic BluetoothDevice getRemoteDevice (String address)
Valid Bluetooth hardware addresses must be upper case, in a format such as "00:11:22:33:AA:BB". The helper checkBluetoothAddress(String) is available to validate a Bluetooth address.
Parameters
address
valid Bluetooth MAC address
Throws
IllegalArgumentException
if address is invalid
Ex:
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
BluetoothSocket
public BluetoothDevice getRemoteDevice ()
Get the remote device this socket is connecting, or connected, to.
Returns
remote device
Ex:
socket.getRemoteDevice()
Enabling discoverability:
要讓你的Device成為Discoverable,要呼叫StartActivityForResult(Intent,int),Intent要使用ACTION_REQUEST_DISCOVERABLEDiscoverable時間:
Default: 120s
Maximum: 3600s
Set to 0: always
< 0 或 > 3600: 120s
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
無論Discoverable成功或失敗,onActivityResult callback function都會收到呼叫
如果Device的Bluetooth還沒開啟,當Device變成Discoverable時,會自動開啟Bluetooth
若要知道Discoverable mode是否發生改變,可以註冊一個Broadcase receiver監聽ACTION_SCAN_MODE_CHANGED的intent,intent裡面會包含EXTRA_SCAN_MODE 和EXTRA_PREVIOUS_SCAN_MODE
mode分為以下三種:
SCAN_MODE_CONNECTABLE_DISCOVERABLE: 在Discoverable mode
SCAN_MODE_CONNECTABLE: 不在Discoverable mode,但仍可以接收connection
SCAN_MODE_NONE: 不在Disoverable mode,並且也不能接收connection
Connecting Devices:
要在兩台Device之間建立連線,一台Device(Server side)要先打開server socket,另外一台Device(Client side)要初始化connection(使用server device的MAC address)。當兩台Device在同一個RFCOMM channel上都有了已連接的BluetoothSocket,就可以取得input和output stream,進行資料交換Server和Client取得Bluetooth的方法如下:
Server: when an incoming connection is accepted
Client: when it opens an RFCOMM channel to the server
實作方法:
法一:每一台device都打開server socket,等待device接收connection,當有一台server初始化connection,就變成client
法二:某一台device打開server socket,負責管理connection,其他device只要負責初始化connection
注意:
RFCOMM connection attempt會block住直到配對成功、使用者拒絕配對、配對失敗或time out
Connecting as a server:
server socket的目的是監聽connection request,當接收到request後,就會提供一個BluetoothSocket,當從BlutoothServerSocket取得BluetoothSocket後,除非想要接收更多的connection,否則就應該把BlutoothServerSocket關閉設定和接受connection的步驟如下:
1. 取得 BluetoothServerSocket:
呼叫 listenUsingRfcommWithServiceRecord(String, UUID)
BluetoothAdapter
public BluetoothServerSocket listenUsingRfcommWithServiceRecord (String name, UUID uuid)
Parameters
name
service name for SDP record
uuid
uuid for SDP record
Returns
a listening RFCOMM BluetoothServerSocket
Throws
IOException
on error, for example Bluetooth not available, or insufficient permissions, or channel in use.
2. 監聽connection request:
呼叫 accept()
BluetoothServerSocket
public BluetoothSocket accept ()
Returns
a connected BluetoothSocket
Throws
IOException
on error, for example this call was aborted, or timeout
3. 釋放 server socket (除非想要接收額外的connection)
呼叫 close()
BluetoothServerSocket
public void close ()
Throws
IOException
注意:
不應該在 Activity main UI thread呼叫 accept(),因為它是個 blocking call,會把 Application給block住。在使用BluetoothServerSocket和 BluetoothSocket時,應該在新的thread裡執行。
Connecting as a client
要初始化和remote device(擁有 open server socket)之間的connection,先要取得 BluetoothDevice物件代表這個 remote device步驟:
1. 取得 BluetoothSocket
呼叫createRfcommSocketToServiceRecord(UUID uuid)
uuid必須符合server service在開啟BluetoothServerSocket (with listenUsingRfcommWithServiceRecord(String, UUID))時所用uuid
BluetoothDevice
public BluetoothSocket createRfcommSocketToServiceRecord (UUID uuid)
Parameters
uuid
service record uuid to lookup RFCOMM channel
Returns
a RFCOMM BluetoothServerSocket ready for an outgoing connection
Throws
IOException
on error, for example Bluetooth not available, or insufficient permissions
2. 初始化connection
呼叫connect()
BluetoothSocket
public void connect ()
Throws
IOException
on error, for example connection failure
呼叫了connect(),system會查詢 remote device是否有符合的uuid,如果查詢成功,remote
device會接受這個connection,並分享RFCOMM channel。
connect()是一個blocking call,當connection fail或 connect()發生time out(約12秒),就會丟出
exception
注意:
當呼叫 connect時,避免 device正在執行device discovery,否則 connection attempt會變得很慢,並且可能會fail
Managing a connction:
傳送任意資料的步驟:1. 取得 InputStream和 OutputStream來處理資料傳輸
呼叫 getInputStream()和 getOutputStream
2. 讀取 steam的資料
呼叫 read(byte[])和 write(byte[])
注意:
因為 read(byte[])和 write(byte[])是 blocking call,所以應該create新的thread來讀取stream。
read(byte[])會 block住直到 stream有資料可以讀取;只有當device的讀取速度不夠快,導致bufer滿了,write(byte[])才會 block住
沒有留言:
張貼留言