【Android】藍牙開發——經典藍牙:配對與解除配對 & 實現配對或連接時不彈出配對框

目錄

一、配對方法 

二、解除配對方法

三、配對/解除配對結果

四、justwork配對模式下,不彈出配對框

五、pincode配對模式下,不彈出配對框

六、小結


在之前的文章【Android】藍牙開發—— 經典藍牙配對介紹(Java代碼實現演示)附Demo源碼 中,簡單介紹和演示了經典藍牙的配對方式,今天就在之前的基礎上繼續講講,藍牙的配對、解除配對以及如何實現不彈出配對框。

關於“配對”、“解除配對”的說法,還有叫“綁定”、“解綁”,這裏提前說一下,在之前的文章中出現,防止小夥伴們不理解。

一、配對方法 

藍牙配對方式,目前有兩種,一種是通過反射的方法,還有一種是直接調用官方API的方法。

第一種:反射的方法,在低於Android API 19時,配對的方法是隱藏的方法,所以只有通過反射方法實現。

 /**
     * 第一種
     * 執行配對 反射
     * @param bluetoothDevice 藍牙設備
     * @return true 執行綁定 false 未執行綁定
     */
    public boolean boundDevice(BluetoothDevice bluetoothDevice){
        if(bluetoothDevice == null){
            Log.e(TAG,"boundDevice-->bluetoothDevice == null");
            return false;
        }

        try {
            return ClsUtils.createBond(BluetoothDevice.class,bluetoothDevice);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

 ClsUtils.java中createBond()方法如下:

/**
     * 與設備配對 參考源碼:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */
    @SuppressWarnings("unchecked")
    static public boolean createBond(@SuppressWarnings("rawtypes") Class btClass, BluetoothDevice btDevice)
            throws Exception {
        Method createBondMethod = btClass.getMethod("createBond");
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

 第二種:官方API,但是隻支持Android API 19以上的設備。

/**
     * 第二種
     * 執行配對 官方API
     * @param bluetoothDevice  藍牙設備
     * @return  true 執行綁定 false 未執行綁定
     */
    public boolean boundDeviceAPI(BluetoothDevice bluetoothDevice){
        if(bluetoothDevice == null){
            return false;
        }

        //注意:Android 4.4版本之後的API
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            return bluetoothDevice.createBond();
        }
        return false;
    }

 

二、解除配對方法

藍牙解除配對的方式,因爲是隱藏的方法,目前只有通過反射進行調用。

/**
     * 執行解除配對  反射
     * @param bluetoothDevice 藍牙設備
     * @return  true 執行解綁  false未執行解綁
     */
    public boolean disBoundDevice(BluetoothDevice bluetoothDevice){
        if(bluetoothDevice == null){
            Log.e(TAG,"disBoundDevice-->bluetoothDevice == null");
            return false;
        }

        try {
            return ClsUtils.removeBond(BluetoothDevice.class,bluetoothDevice);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return true;
    }

 ClsUtils.java中removeBond()方法如下:

/**
     * 與設備解除配對 參考源碼:platform/packages/apps/Settings.git
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
     */
    @SuppressWarnings("unchecked")
    static public boolean removeBond(Class btClass, BluetoothDevice btDevice)
            throws Exception {
        Method removeBondMethod = btClass.getMethod("removeBond");
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
        return returnValue.booleanValue();
    }

三、配對/解除配對結果

配對、解除配對的結果是通過系統廣播出來的,所以我們在使用的時候,需要註冊廣播接收器來獲取配對狀態。

這裏我們自定義廣播接收器。在onCreate()中註冊該廣播,在onDestroy()中註銷廣播。

 /**
     * 藍牙廣播接收器
     */
    private class BtBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(TextUtils.equals(action,BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int bondSate = bluetoothDevice.getBondState();
                switch(bondSate) {
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "已解除配對");
                        break;

                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "正在配對...");
                        break;

                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "已配對");
                        break;
                }
            }
        }
    }
 //註冊廣播接收
 btBroadcastReceiver = new BtBroadcastReceiver();
 IntentFilter intentFilter = new IntentFilter();
 intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配對狀態監聽
 registerReceiver(btBroadcastReceiver,intentFilter);
//註銷廣播接收
unregisterReceiver(btBroadcastReceiver);

四、justwork配對模式下,不彈出配對框

1、配對的時候

justwork配對模式下,不管是調用反射的配對方法還是官方API的配對方法,都不會彈出配對框,實現自動配對。

2、經典藍牙第一次連接的時候(即連接之前,與設備是沒有配對的狀態)

經典藍牙建立連接時,有兩種方式,一種是建立安全的連接,即需要配對的連接;

還有一種就是建立不安全的連接,即不需要配對的連接。建立不安全的連接,實際上是因爲沒有進行配對,當然就不會有配對框彈出。

//1、建立安全的藍牙連接,會彈出配對框
BluetoothSocket BluetoothSocket=bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
//2、建立不安全的藍牙連接,不進行配對,就不彈出配對框
BluetoothSocket BluetoothSocket=bluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(uuid));

五、pincode配對模式下,不彈出配對框

1、註冊BluetoothDevice.ACTION_PAIRING_REQUEST廣播監聽

 //註冊廣播接收
 btBroadcastReceiver = new BtBroadcastReceiver();
 IntentFilter intentFilter = new IntentFilter();
 intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配對狀態監聽
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);  //配對請求
        }
 registerReceiver(btBroadcastReceiver,intentFilter);

2、在廣播接收器中處理

 /**
     * 藍牙廣播接收器
     */
    private class BtBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(TextUtils.equals(action,BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int bondSate = bluetoothDevice.getBondState();
                switch(bondSate) {
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "已解除配對");
                        break;

                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "正在配對...");
                        break;

                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "已配對");
                        break;
                }
            }else if(TextUtils.equals(action,BluetoothDevice.ACTION_PAIRING_REQUEST)){
                int type = -1;
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                    type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,BluetoothDevice.ERROR);
                    Log.d(TAG, "ACTION_PAIRING_REQUEST--"+type);
                    //PAIRING_VARIANT_PIN 0 
                    if(type == BluetoothDevice.PAIRING_VARIANT_PIN){
                        //防止彈出一閃而過的配對框
                        abortBroadcast();
                        //彈框後自動輸入密碼、自動確定
                        boolean isSetPin = curBluetoothDevice.setPin("0000".getBytes());
                        Log.d(TAG, "setPin()-->" + isSetPin);

                    }
            }
        }
    }

 因爲官方的BluetoothDevice.setPin() 是支持API 19以上的設備,所以在低於API 19的設備上,需要使用反射的方法來獲取setPin()方法。

 /**
     * 藍牙廣播接收器
     */
    private class BtBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(TextUtils.equals(action,BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
                BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int bondSate = bluetoothDevice.getBondState();
                switch(bondSate) {
                    case BluetoothDevice.BOND_NONE:
                        Log.d(TAG, "已解除配對");
                        break;

                    case BluetoothDevice.BOND_BONDING:
                        Log.d(TAG, "正在配對...");
                        break;

                    case BluetoothDevice.BOND_BONDED:
                        Log.d(TAG, "已配對");
                        break;
                }
            }else if(TextUtils.equals(action,BluetoothDevice.ACTION_PAIRING_REQUEST)){
                int type = -1;
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                    type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,BluetoothDevice.ERROR);
                    Log.d(TAG, "ACTION_PAIRING_REQUEST--"+type);
                    //PAIRING_VARIANT_CONSENT 0 
                    if(type == BluetoothDevice.PAIRING_VARIANT_PIN){
                        //防止彈出一閃而過的配對框
                        abortBroadcast();
                        //彈框後自動輸入密碼、自動確定
                        try {
                            boolean isSetPin = ClsUtils.autoBond(BluetoothDevice.class,curBluetoothDevice,"0000");
                            Log.d(TAG, "setPin()-->" + isSetPin);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
            }
        }
    }

ClsUtils.java中autoBond()方法如下:

 //自動配對設置Pin值
    static public boolean autoBond(Class btClass,BluetoothDevice device,String strPin) throws Exception {
        Method autoBondMethod = btClass.getMethod("setPin",new Class[]{byte[].class});
        Boolean result = (Boolean)autoBondMethod.invoke(device,new Object[]{strPin.getBytes()});
        return result;
    }

 

六、小結

1、justwork配對模式下,

(1)調用反射的配對方法或者官方API的配對方法,都能實現自動配對,不會彈出配對框。

(2)調用官方API首次連接,且建立非安全的連接,不會彈出配對框,但是本質是因爲沒有執行配對操作。

2、pincode配對模式下,實現自動配對的方法,只適用Android 8.0及以下的系統,Android 9.0及以上系統不生效。

3、如果想要實現彈出配對框時自動輸入或點擊,可以使用無障礙服務(Accessibility Service)。通過獲取界面的控件,比如輸入框、按鈕,然後模擬輸入或點擊,實現自動配對。

注意:上面所說的justwork或pincode模式也不是絕對的,因爲這完全是由藍牙設備軟件工程師決定的,所以實際開發時還是要根據實際的設備進行方式的選擇。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章