學習緣由
上個禮拜公司要開發個簡單的五子棋遊戲!其中一個需求就是支持藍牙對戰!所以苦逼的我學習藍牙方面的知識了!
簡介
-
Bluetooth是目前使用最廣泛的無線通訊協議,近距離無線通訊的標準。傳說瑞典有個國王特別愛吃藍莓導致自己的牙齒天天都是藍色的,在他執政期間這位國王非常善於交際,能說會到,和鄰國的搞得關係非常好,這個Bluetooth的發明者覺得藍牙它的作用就是在近距離溝通周圍的設備,跟這個國王很類似,於是起名叫藍牙。
-
主要針對短距離設備通訊(10米)
-
無線耳機,無線鼠標,無線鍵盤
Android 中的使用
藍牙 API 簡單簡介
- BluetoothAdapter (藍牙本地適配器)
cancelDiscovery()
停止當前搜索藍牙的 Taskdisable()
關閉藍牙enable()
打開藍牙getAddress()
得到本地藍牙適配器的地址getBondedDevices()
得到已經綁定的藍牙的設備getDefaultAdapter()
得到本地藍牙適配器getName()
得到本地藍牙的名稱getRemoteDevice(byte[] address)
得到遠程藍牙設備getRemoteDevice(String address)
得到遠程藍牙設備isEnabled()
判斷藍牙是否打開setName(String name)
設置藍牙名稱startDiscovery()
開始搜多附近藍牙listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
創建 BluetoothServerSocket
- BluetoothDevice
createBond()
藍牙配對 (低版本不支持,>=api19)createRfcommSocketToServiceRecord(UUID uuid)
創建 BluetoothSocketgetBondState()
得到配對的狀態getAddress()
得到遠程藍牙適配器的地址getName()
得到遠程藍牙的名稱
- BluetoothSocket 與 BluetoothServerSocket
這兩個 API 和Socket 和ServerSocket 差不多 這裏不予介紹
*** 當然了,Android 中藍牙相關的API還很多!這裏我只說了幾個常用的!!!! ***
Android 中的實戰
** 現在我們就按照正常的邏輯來走! **
第一步
我們要先得到 藍牙本地適配器,來判斷設備是否支持藍牙!
mAdapter=BluetoothAdapter.getDefaultAdapter();
//判斷設備是否支持藍牙
if (mAdapter==null){
Toast.makeText(this, "不支持藍牙", Toast.LENGTH_SHORT).show();
}
第二步
好了!現在下面要做的就是判斷藍牙是否打開了!沒有打開則打開!
if (!mAdapter.isEnabled()){//藍牙沒有打開
// mAdapter.enable();//不支持這樣寫,影響用戶體驗
//建議使用這種方式
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 200);
}
代碼寫得很清楚!我就不解釋啦!!!
第三步
成功打開藍牙之後,要想別人的適配上能夠發現,我們得設置藍牙的可見性,現在我就來設置藍牙的可見性!看代碼
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==200){
Intent dis=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
dis.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(dis);
}
}
不知大家有沒有注意到,我是在 onActivityResult(int
requestCode, int resultCode, Intent data)
這個回調函數中設置藍牙可見性的!因爲我們在打開藍牙的時候用了 startActivityForResult(Intent
intent,int requestCode)
這個方法!還有一點大家也要注意 就是藍牙在設置可見性的時候,有個時常。就是這個字段 BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION
對應的值!這個最大值是300秒!
第四步
至此,我們就可以搜索附近的藍牙啦!那麼有同學會問了,我們怎麼知道有設備被搜索到呢?這個很簡單哦!但我們搜索到設備的時候,系統就會給我們發送廣播啦!我們只有註冊個廣播接收器就行啦!
mAdapter.startDiscovery();//開始搜索
//註冊藍牙廣播接收器。
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);//發現藍牙動作
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索結束動作
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//搜素開始動作
registerReceiver(blueReceiver, filter);
/**
* 藍牙接收器
**/
public class BlueReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceList.add(device);
adapter.notifyDataSetChanged();
}
if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
}
if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
}
}
}
在 BlueReceiver
中我只是簡單的把搜索到得設備放到集合中。被沒有做過多的操作!
第五步
現在到了比較重要的步驟了!當我們搜索到了藍牙的之後,我要配對,因爲只有在配對之後才能連接哦!
BluetoothDevice device = (BluetoothDevice) adapter.getItem(i);
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {//是否已配對
connect(device);
} else {
try {
Method boned=device.getClass().getMethod("createBond");
boolean isok= (boolean) boned.invoke(device);
if(isok)
{
connect(device);
}
} catch (Exception e) {
e.printStackTrace();
}
}
這裏,我想說明的是就是這個配對,在 API19 之後 createBond()
Android對外提供了這個方法!但是在
API19 以前並沒有提供這個方法,所以呢我只能用反射了!這個兼容性比較好奧!!
第六步
現在,就很簡答啦!只要連接就行啦!在這裏我放在了一個線程中了!
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
@Override
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
mAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException e) {
connectionFailed();
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
BlueToothService.this.start();
return;
}
synchronized (BlueToothService.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice);//這裏是另外一個讀取數據的線程,這裏就和socket操作一樣了
write("start".getBytes());
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
** 好啦!如果你讀到這裏 就也就學會了藍牙的簡單操作了! **