Android 藍(lán)牙自動(dòng)匹配PIN碼跳過(guò)用戶交互示例
近期項(xiàng)目中需要連接藍(lán)牙設(shè)備,起初只是設(shè)置藍(lán)牙列表界面讓用戶點(diǎn)擊然后輸入默認(rèn)PIN碼,后來(lái)改需求了 = = ,要求自動(dòng)連接指定設(shè)備并不需要用戶手動(dòng)輸入PIN碼,作為Android 小白的我是拒絕的,但是拒絕有什么用~
首先說(shuō)一下之后會(huì)用到的關(guān)于藍(lán)牙方面的東西:
- 斷開藍(lán)牙已配對(duì)的設(shè)備
- 搜索附近藍(lán)牙設(shè)備
- 攔截用戶交互頁(yè)面,使用代碼輸入
- 由于在最后連接的時(shí)候使用的是設(shè)備的SDK所以在這里就不介紹了
1.斷開已配對(duì)設(shè)備
最后在項(xiàng)目中發(fā)現(xiàn)沒(méi)有用。這里就先記錄一下。
//得到配對(duì)的設(shè)備列表,清除已配對(duì)的設(shè)備 public void removePairDevice() { if (mBluetoothAdapter != null) { //mBluetoothAdapter初始化方式 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); //這個(gè)就是獲取已配對(duì)藍(lán)牙列表的方法 Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices(); for (BluetoothDevice device : bondedDevices) { //這里可以通過(guò)device.getName() device.getAddress()來(lái)判斷是否是自己需要斷開的設(shè)備 unpairDevice(device); } } } //反射來(lái)調(diào)用BluetoothDevice.removeBond取消設(shè)備的配對(duì) private void unpairDevice(BluetoothDevice device) { try { Method m = device.getClass().getMethod("removeBond", (Class[]) null); m.invoke(device, (Object[]) null); } catch (Exception e) { Log.e("mate", e.getMessage()); } }
2.搜索附近藍(lán)牙
首先我們需要注冊(cè)兩個(gè)廣播,第一個(gè)為正在搜索時(shí)的,第二個(gè)為搜索完成的。
// Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mFindBlueToothReceiver, filter); // Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mFindBlueToothReceiver, filter); //需要時(shí)開始搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } mBluetoothAdapter.startDiscovery();
然后對(duì)廣播進(jìn)行處理。這里要說(shuō)明一下ClsUtils.createBond()這個(gè)方法如果連接設(shè)備SDK中有配對(duì)的方法,建議把這個(gè)方法去掉,我這里是去掉的,加上的話偶爾會(huì)Toast出無(wú)法配對(duì)。
private final BroadcastReceiver mFindBlueToothReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_FOUND.equals(action)) { //TODO 開始搜索 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // if (device.getBondState() != BluetoothDevice.BOND_BONDED) {//判斷藍(lán)牙狀態(tài),是否是已配對(duì) //TODO 可以在這判斷名字 如果搜索結(jié)束后沒(méi)有,再到已配對(duì)中尋找 String BTName[] = device.getName().split("-"); if (BTName[0].equals("xxx")) { //在這連接設(shè)備 一般需要藍(lán)牙地址 device.getAddress(); try { ClsUtils.createBond(device.getClass(), device); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } // } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //TODO 搜索結(jié)束 Toast.makeText(context, "搜索結(jié)束",Toast.LENGTH_SHORT).show(); } } };
這里在Activity結(jié)束時(shí)記得取消注冊(cè)和取消搜索
unregisterReceiver(mFindBlueToothReceiver); if (mBluetoothAdapter != null) { mBluetoothAdapter.cancelDiscovery(); }
3.攔截用戶交互頁(yè)面
通過(guò)廣播可以監(jiān)聽到輸入PIN碼的那個(gè)頁(yè)面將要彈出
<receiver android:name=".BluetoothConnectActivityReceiver" > <intent-filter android:priority="1000"> <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" /> </intent-filter> </receiver>
廣播中需要做的事情,注意一定要調(diào)用abortBroadcast(),不然交互頁(yè)面還是會(huì)出現(xiàn)一下然后消失。就是這個(gè)方法找了一天(╯‵□′)╯︵┴─┴。。。
public class BluetoothConnectActivityReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.bluetooth.device.action.PAIRING_REQUEST")) { BluetoothDevice mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); try { //(三星)4.3版本測(cè)試手機(jī)還是會(huì)彈出用戶交互頁(yè)面(閃一下),如果不注釋掉下面這句頁(yè)面不會(huì)取消但可以配對(duì)成功。(中興,魅族4(Flyme 6))5.1版本手機(jī)兩中情況下都正常 //ClsUtils.setPairingConfirmation(mBluetoothDevice.getClass(), mBluetoothDevice, true); abortBroadcast();//如果沒(méi)有將廣播終止,則會(huì)出現(xiàn)一個(gè)一閃而過(guò)的配對(duì)框。 //3.調(diào)用setPin方法進(jìn)行配對(duì)... boolean ret = ClsUtils.setPin(mBluetoothDevice.getClass(), mBluetoothDevice, "你需要設(shè)置的PIN碼"); } catch (Exception e) { e.printStackTrace(); } } } }
然后只要在搜索到自己需要的設(shè)備后連接進(jìn)行操作就可以了?。?!一定要記得加權(quán)限~
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH" />
在Android6.0之后還需要一個(gè)模糊定位的權(quán)限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
最后把ClsUtils類奉上,網(wǎng)上有很多的。
/**************** 藍(lán)牙配對(duì)函數(shù) ***************/ import java.lang.reflect.Field; import java.lang.reflect.Method; import android.bluetooth.BluetoothDevice; import android.util.Log; public class ClsUtils { /** * 與設(shè)備配對(duì) 參考源碼:platform/packages/apps/Settings.git * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java */ static public boolean createBond(Class btClass, BluetoothDevice btDevice) throws Exception { Method createBondMethod = btClass.getMethod("createBond"); Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice); return returnValue.booleanValue(); } /** * 與設(shè)備解除配對(duì) 參考源碼:platform/packages/apps/Settings.git * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java */ static public boolean removeBond(Class<?> btClass, BluetoothDevice btDevice) throws Exception { Method removeBondMethod = btClass.getMethod("removeBond"); Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice); return returnValue.booleanValue(); } static public boolean setPin(Class<? extends BluetoothDevice> btClass, BluetoothDevice btDevice, String str) throws Exception { try { Method removeBondMethod = btClass.getDeclaredMethod("setPin", new Class[]{byte[].class}); Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice, new Object[] {str.getBytes()}); Log.e("returnValue", "" + returnValue); } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; } // 取消用戶輸入 static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelPairingUserInput"); // cancelBondProcess(btClass, device); Boolean returnValue = (Boolean) createBondMethod.invoke(device); return returnValue.booleanValue(); } // 取消配對(duì) static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelBondProcess"); Boolean returnValue = (Boolean) createBondMethod.invoke(device); return returnValue.booleanValue(); } //確認(rèn)配對(duì) static public void setPairingConfirmation(Class<?> btClass, BluetoothDevice device, boolean isConfirm) throws Exception { Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation", boolean.class); setPairingConfirmation.invoke(device, isConfirm); } /** * * @param clsShow */ static public void printAllInform(Class clsShow) { try { // 取得所有方法 Method[] hideMethod = clsShow.getMethods(); int i = 0; for (; i < hideMethod.length; i++) { Log.e("method name", hideMethod[i].getName() + ";and the i is:"+ i); } // 取得所有常量 Field[] allFields = clsShow.getFields(); for (i = 0; i < allFields.length; i++) { Log.e("Field name", allFields[i].getName()); } } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android ListView實(shí)現(xiàn)圖文列表顯示
這篇文章主要為大家詳細(xì)介紹了Android ListView實(shí)現(xiàn)圖文列表顯示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01Android?AMS啟動(dòng)App進(jìn)程原理分析
這篇文章主要介紹了Android?AMS啟動(dòng)App進(jìn)程原理,系統(tǒng)fork函數(shù)是如何創(chuàng)建進(jìn)程,文中有詳細(xì)的代碼示例,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-05-05一文搞懂Android RecyclerView點(diǎn)擊展開、折疊效果的實(shí)現(xiàn)代碼
雖然在日常開發(fā)中已經(jīng)多次接觸過(guò)RecycleView,但也只是用到其最基本的功能,并沒(méi)有深入研究其他內(nèi)容。接下來(lái)將抽出時(shí)間去了解RecycleView的相關(guān)內(nèi)容,這篇文章主要是介紹Android RecyclerView點(diǎn)擊展開、折疊效果的實(shí)現(xiàn)方式,一起看看吧2021-06-06Android開發(fā)之DialogFragment用法實(shí)例總結(jié)
這篇文章主要介紹了Android開發(fā)之DialogFragment用法,結(jié)合實(shí)例形式總結(jié)分析了Android使用DialogFragment代替Dialog功能的相關(guān)使用技巧與注意事項(xiàng),需要的朋友可以參考下2017-11-11詳解Android Service 使用時(shí)的注意事項(xiàng)
這篇文章主要介紹了詳解Android Service 使用時(shí)的注意事項(xiàng),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10Android 實(shí)現(xiàn)圓角圖片的簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android 實(shí)現(xiàn)圓角圖片的簡(jiǎn)單實(shí)例的相關(guān)資料,Android 圓角圖片的實(shí)現(xiàn)形式,包括用第三方、也有系統(tǒng),需要的朋友可以參考下2017-07-07Android組件ContextMenu實(shí)現(xiàn)長(zhǎng)按事件
這篇文章主要為大家詳細(xì)介紹了Android組件ContextMenu實(shí)現(xiàn)長(zhǎng)按事件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04Android 搜索結(jié)果匹配關(guān)鍵字且高亮顯示功能
這篇文章主要介紹了Android 搜索結(jié)果匹配關(guān)鍵字且高亮顯示功能,需要的朋友可以參考下2017-05-05