藍牙應該是現在每一部智能手機的標配了。想當年在山寨機橫行的年代里,藍牙都可以做為一個賣點~~~
廢話不多說了,進入正題:
使用藍牙功能是需要權限的,關於藍牙的權限也就兩個:
<uses-permission android:name=”android.permission.BLUETOOTH” /> <uses-permission android:name=”android.permission.BLUETOOTH_ADMIN” />
第一個是最基本的,打開藍牙,請求連接,接受連接都需要這個。
每二個從字面上看都覺得高級一點,它主要用於像建立搜索、對藍牙進行設置這些操作。
添加好權限之后就可以開始使用了
Android系統為我們提供了一個功能極其強大的類用於進行藍牙操作,這個類就是BluetoothAdapter。通過這個類的方法可以滿足我們的大多數操作了。
要獲得這個類的對象我們可以直接調用它的一個靜態方法getDefaultAdapter()。順便看看它的源碼是怎樣的吧:
public static synchronized BluetoothAdapter getDefaultAdapter() { if (sAdapter == null) { IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE); if (b != null) { IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b); sAdapter = new BluetoothAdapter(managerService); } else { Log.e(TAG, "Bluetooth binder is null"); } } return sAdapter; }
典型的單例模式:
打開藍牙
首先要先確實您的設備是否有藍牙,這個驗證還是很有必要的,因為我們要考慮到我們的應用不一定就是給手機用的,也可能是平板之類的。
private boolean isBluetoothAvaliable() { return BluetoothAdapter.getDefaultAdapter() != null; }
我們一般打開藍牙會使用到系統提供的一個Activity。這個Activity的action為:BluetoothAdapter.ACTION_REQUEST_ENABLE。
然后我們要使用startActivityForResult()這個方法來啟動它。
這個Activity是有返回值的,如果用戶選擇的是打開,我們應該可以收到一個RESULT_OK
如果用戶選擇的是取消,我們應該可以收到一個RESULT_CANCELED。
比如像下面的這一段代碼:
public void openBluetooth() { Intent enableBT = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBT, 1); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1) { if (resultCode == RESULT_OK) { System.out.println("藍牙已打開"); } else if (resultCode == RESULT_CANCELED) { System.out.println("取消打開"); } } }
監聽藍牙狀態的變化
當藍牙的狀態發生改變時,系統是會發出一個為BluetoothAdapter.ACTION_STATE_CHANGED的廣播。
該廣播攜帶兩個參數,一個是BluetoothAdapter.EXTRA_PREVIOUS_STATE,表示之前的藍牙狀態。
另一個是BluetoothAdapter.EXTRA_STATE,表示當前的藍牙狀態。而它們的值為以下四個:
BluetoothAdapter.STATE_TURNING_ON;
BluetoothAdapter.STATE_ON;
BluetoothAdapter.STATE_TURNING_OFF;
BluetoothAdapter.STATE_OFF;
分別代表,打開中,已打開,關閉中,已關閉。
private class BluetoothStateListener extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); String msg = null; switch (state) { case BluetoothAdapter.STATE_TURNING_ON: msg = "turning on"; break; case BluetoothAdapter.STATE_ON: msg = "on"; break; case BluetoothAdapter.STATE_TURNING_OFF: msg = "turning off"; break; case BluetoothAdapter.STATE_OFF: msg = "off"; break; } System.out.println(msg); } } protected void onResume() { super.onResume(); // 藍牙開閉狀態接收器 listener = new BluetoothStateListener(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); registerReceiver(listener, filter); }
當然在程序中的某刻,我們可以調用BludetoothAdapter的getState()這個方法,該方法的返回值為上面的四個中的一個,不再贅述。
查找藍牙設備
這個關於查找設備要分為兩個部分,一個是已綁定的設備,另一個是搜索新的設備。
對於已綁定的設備,我們可以直接通過BluetoothAdapter的getBondedDevices()這個方法來獲得。
該方法返回的是一個Set<BluetoothDevice>我們可以直接從人獲得我們需要的信息:
public void getBoundedDevices() { System.out.println("getPairedDevices"); // 這個要在打開藍牙的情況下才可以,不然為空集 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Set<BluetoothDevice> devices = adapter.getBondedDevices(); for (BluetoothDevice device : devices) { System.out.println(device.getName() + " : " + device.getAddress()); } }
另外就是查找新的設備了,這時我們要調用startDiscovery()方法,這個方法並不會在我們的程序中執行,它是系統進程來的,然后通過異步發送廣播的方式來通知。
所以我們還要注冊一個廣播接收器來接收系統的廣播,這個廣播的action為BluetoothDevice.ACTION_FOUND。
它攜帶兩個值,一個是BluetoothDevice.EXTRA_DEVICE另一個是BluetoothDevice.EXTRA_CLASS分別表示哪一個具體的設備和這個設備的類型。
private class BluetoothDeviceScanListener extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 這里可以把我們的將我們的設備添加到一個列表中 System.out.println(device.getName() + " : " + device.getAddress()); } }
在官方的文檔中一直強調,查找設備這個動作是會消耗大量的系統資源的,而且它會大大減少藍牙的可用帶寬,所以當我們找到了目標設備后,應該由我們主動調用cancelDiscovery()這個方法來取消搜索,而不應該期待默認的搜索時間到了,由系統來取消搜索。
設置可被搜索
藍牙的默認設置是不允許被搜索到的,這一點有時候挺蛋疼的。
所以我們自己通過編程來實現打開可被搜索的選擇,使用是很裝簡單的,也是調用系統的一個Activity。這個activity的action是BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE它同樣是有返回值的。並且,這個我們可以通過BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION這個參數來指定可被搜索的時間。
public void discoverable() { BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); // 這個可以用來設置時間 intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200); startActivityForResult(intent, 2); }
這個Activity還同時具有打開藍牙的功能,所以我們並不需要先打開藍牙,再設置可被發現的時間,一次就可以搞定。
最后,這個狀態的改變系統也是會發出廣播的,我們可以注冊一個廣播接收器來捕捉這個狀態的變化,或是通過調用BluetoothAdapter的getScanMod()這個方法來確定,和之前是一樣的。不再細說了。
(未定待續)