1. 程式人生 > >Android 藍芽自動配對連線

Android 藍芽自動配對連線

藍芽工具類:

public class BTReceiverUtils {
    /**
     * 與裝置配對
     */
    static public boolean createBond(Class btClass, BluetoothDevice btDevice) throws Exception {
        Method createBondMethod = btClass.getMethod("createBond");
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
        return
returnValue.booleanValue(); } /** * 與裝置解除配對 */ 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) { e.printStackTrace(); } return true; } /** * 取消使用者輸入 */ static public boolean cancelPairingUserInput(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelPairingUserInput"); Boolean returnValue = (Boolean) createBondMethod.invoke(device); return returnValue.booleanValue(); } /** * 取消配對 */ static public boolean cancelBondProcess(Class<?> btClass, BluetoothDevice device) throws Exception { Method createBondMethod = btClass.getMethod("cancelBondProcess"); Boolean returnValue = (Boolean) createBondMethod.invoke(device); return returnValue.booleanValue(); } /** * 確認配對 */ static public void setPairingConfirmation(Class<?> btClass,BluetoothDevice device,boolean isConfirm)throws Exception { Method setPairingConfirmation = btClass.getDeclaredMethod("setPairingConfirmation",boolean.class); setPairingConfirmation.invoke(device,isConfirm); } }

藍芽搜尋連線:
(預設以 0000 pin連線,不需要使用者輸入)

    private BTReceiverAdapter btReceiverAdapter;
    private LinearLayoutManager linearLayoutManager;
    private BluetoothAdapter mBluetoothAdapter;
    private IntentFilter mFilter;
    private BluetoothDevice mBluetoothDevice;//搜尋出來的

    /**
     * 需要連線的藍芽裝置
     */
    private BluetoothDevice bluetoothDevice; //選擇的裝置
    private SharedPreferences sharedPreferences;
    private int clickSelect;//選擇的藍芽裝置在列表中的位置
    private List<BluetoothDevice> bluetoothDeviceList = new ArrayList<>();//搜尋出的裝置集合

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.leftmenu_btreceiver);
        ButterKnife.bind(this);
        sharedPreferences = getApplicationContext().getSharedPreferences(UserInfoConstant.USERINFO_SHREDPREFERENCE, Context.MODE_PRIVATE);
        initPairingInfo();
    }

    /**
     * 填充已配對藍芽裝置資訊
     */
    private void initPairingInfo() {
        leftmenuBtreceiverName.setText(SharedPreferencesUtil.getSharedPreferences(this, UserInfoConstant.USERINFO_SHREDPREFERENCE, UserInfoConstant.USERINFO_BLUETOOTHNAME));
        leftmenuBtreceiverId.setText(SharedPreferencesUtil.getSharedPreferences(this, UserInfoConstant.USERINFO_SHREDPREFERENCE, UserInfoConstant.USERINFO_BLUETOOTHID));
    }

    @OnClick({R.id.leftmenu_btreceiver_back, R.id.leftmenu_btreceiver_scan})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.leftmenu_btreceiver_back:
                finish();
                break;
            case R.id.leftmenu_btreceiver_scan:
                methodRequiresTwoPermission();
                break;
        }
    }

    /**
     * 檢測是否有藍芽許可權和模糊定位許可權
     */
    private void methodRequiresTwoPermission() {
        String[] perms = {Manifest.permission.BLUETOOTH, Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.ACCESS_COARSE_LOCATION};
        if (EasyPermissions.hasPermissions(this, perms)) {
            inspect();
        } else {
            EasyPermissions.requestPermissions(this, getString(R.string.permissions_hint), 0, perms);
        }
    }

    /**
     * 藍芽是否開啟,未開啟則提示使用者,開啟則彈出選擇框
     */
    private void inspect() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter.isEnabled()) {
            /**註冊搜尋藍芽receiver*/
            mFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
            mFilter.addAction(BluetoothDevice.ACTION_FOUND);
            mFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
            mFilter.addAction("android.bluetooth.device.action.PAIRING_REQUEST");
            bluetoothDeviceList.clear();
            registerReceiver(mReceiver, mFilter);
            mBluetoothAdapter.startDiscovery();
            scanDialog();
        } else {
            Toast.makeText(this, R.string.BTReceiverActivity_open_hint, Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 點選掃描彈出框
     */
    private void scanDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        LinearLayout scanDialog = (LinearLayout) getLayoutInflater().inflate(R.layout.leftmenu_btreceiver_popup, null);
        builder.setView(scanDialog);
        builder.setCancelable(false);
        final AlertDialog dialog = builder.create();
        dialog.show();

        Button cancel = scanDialog.findViewById(R.id.leftmenu_btreceiver_popup_cancel);
        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mBluetoothAdapter.cancelDiscovery();
                dialog.cancel();
            }
        });
        RecyclerView deviceRecycler = scanDialog.findViewById(R.id.leftmenu_btreceiver_popup_device);
        linearLayoutManager = new LinearLayoutManager(this);
        deviceRecycler.setLayoutManager(linearLayoutManager);
        deviceRecycler.setHasFixedSize(true);
        btReceiverAdapter = new BTReceiverAdapter(bluetoothDeviceList);
        deviceRecycler.setAdapter(btReceiverAdapter);
        btReceiverAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d(TAG, "onItemClick: " + position);
                clickSelect = position;
                mBluetoothAdapter.cancelDiscovery();
                dialog.cancel();
                pairing();
            }
        });
    }

    /**
     * 進行檢測配對操作
     */
    private void pairing() {
        //判斷是否已經配對
        if (bluetoothDeviceList.get(clickSelect).getBondState() == BluetoothDevice.BOND_BONDED) {
            // 儲存
            Log.d(TAG, "已配對: " + bluetoothDeviceList.get(clickSelect).getName());
            Toast.makeText(BTReceiverActivity.this, R.string.BTReceiverActivity_pairing_succeed, Toast.LENGTH_SHORT).show();
            SharedPreferences.Editor edt = sharedPreferences.edit();
            edt.putString(UserInfoConstant.USERINFO_BLUETOOTHNAME, bluetoothDeviceList.get(clickSelect).getName());
            edt.putString(UserInfoConstant.USERINFO_BLUETOOTHID, bluetoothDeviceList.get(clickSelect).getAddress());
            edt.apply();
            initPairingInfo();
        } else {
            // 進行配對
            try {
                BTReceiverUtils.createBond(bluetoothDeviceList.get(clickSelect).getClass(), bluetoothDeviceList.get(clickSelect));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 處理廣播
     */
    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            /** 搜尋到的藍芽裝置*/
            if (action.equals(BluetoothDevice.ACTION_FOUND)) {
                mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                bluetoothDeviceList.add(mBluetoothDevice);
                Log.d("mReceiver", "search......" + mBluetoothDevice.getName());
                btReceiverAdapter.notifyDataSetChanged();
            } else if (action.equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
                /** 配對 */
                Log.d(TAG, "getDeviceName; " + bluetoothDeviceList.get(clickSelect).getName());
                bluetoothDevice = bluetoothDeviceList.get(clickSelect);
                Log.d(TAG, "bluetoothDevice.getName : " + bluetoothDevice.getName());
                try {
                    //終止有序廣播
                    mReceiver.abortBroadcast();//如果沒有將廣播終止,則會出現一個一閃而過的配對框。
                    //呼叫setPin方法進行配對...
                    boolean ret = BTReceiverUtils.setPin(bluetoothDevice.getClass(), bluetoothDevice, ModelConstants.BLUETOOTH_PIN);
                    //確認配對
                    BTReceiverUtils.setPairingConfirmation(bluetoothDevice.getClass(), bluetoothDevice, true);
                    //取消使用者輸入
                    BTReceiverUtils.cancelPairingUserInput(bluetoothDevice.getClass(), bluetoothDevice);
                    Log.d("pairing", "ret: " + ret + "  name" + bluetoothDevice.getName() + " address " + bluetoothDevice.getAddress());
                    if (ret) {
                        saveBluetoothDevice();
                    } else {
                        Toast.makeText(BTReceiverActivity.this, R.string.BTReceiverActivity_pairing_failure, Toast.LENGTH_SHORT).show();
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                switch (mBluetoothDevice.getBondState()) {
                    case BluetoothDevice.BOND_BONDING://正在配對
                        Log.d(TAG, "正在配對......");
                        break;
                    case BluetoothDevice.BOND_BONDED://配對結束
                        Log.d(TAG, "完成配對");
                        saveBluetoothDevice();
                        break;
                    case BluetoothDevice.BOND_NONE://取消配對/未配對
                        if (bluetoothDevice.getName().contains("Bluetooth Rec")){
                            saveBluetoothDevice();
                        }
                    default:
                        break;
                }
            }
        }
    };

    /**
     * 儲存配對
     */
    private void saveBluetoothDevice(){
        Toast.makeText(BTReceiverActivity.this, R.string.BTReceiverActivity_pairing_succeed, Toast.LENGTH_SHORT).show();
        SharedPreferences.Editor edt = sharedPreferences.edit();
        edt.putString(UserInfoConstant.USERINFO_BLUETOOTHNAME, bluetoothDevice.getName());
        edt.putString(UserInfoConstant.USERINFO_BLUETOOTHID, bluetoothDevice.getAddress());
        edt.apply();
        initPairingInfo();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //把申請許可權的回撥交由EasyPermissions處理
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {
        inspect();
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {
        Toast.makeText(this, getString(R.string.permissions_hint), Toast.LENGTH_SHORT).show();
    }
}