如何在Android中以编程方式配对蓝牙设备

41

我正在开发一个应用程序,我想连接一个蓝牙设备。主要问题是我不希望用户输入所需的PIN码,而是希望应用程序自己完成。我没有任何连接相关的问题,只是想让应用程序自己插入和完成PIN验证码过程。

我找到了下面的代码,我确定它可以工作,但不确定如何在这个代码中添加PIN码?

private void pairDevice(BluetoothDevice device) {
        try {
            Log.d("pairDevice()", "Start Pairing...");
            Method m = device.getClass().getMethod("createBond", (Class[]) null);
            m.invoke(device, (Object[]) null);
            Log.d("pairDevice()", "Pairing finished.");
        } catch (Exception e) {
            Log.e("pairDevice()", e.getMessage());
        }
    }

有人知道如何在上述代码或类似代码中输入 PIN 以解决问题吗?谢谢


也许这可以帮助你。https://dev59.com/aG025IYBdhLWcg3wpXod干杯, - MSA
@ManolescuSebastian -- 我想创建一个安全连接... - Sandip Jadhav
请尝试我的答案。我希望它对您有用。 - Dan Bray
我在这篇文章中回答了这个问题:https://dev59.com/fW445IYBdhLWcg3wM3bx#22201805 - DragonT
请在此处检查我的答案 https://dev59.com/l2Qn5IYBdhLWcg3wAjPJ#30362616 - Rodolfo Abarca
这个答案帮助我动态配对和取消配对蓝牙设备。 - RAJESH KUMAR ARUMUGAM
8个回答

27

12

所以,我有一个问题,如果有人需要在Android 4.4.2上工作的答案。

 IntentFilter filter = new IntentFilter(
                "android.bluetooth.device.action.PAIRING_REQUEST");


        /*
         * Registering a new BTBroadcast receiver from the Main Activity context
         * with pairing request event
         */
        registerReceiver(
                new PairingRequest(), filter);

接收器的代码。

  public static class PairingRequest extends BroadcastReceiver {
        public PairingRequest() {
            super();
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
                try {
                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    int pin=intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY", 0);
                    //the pin in case you need to accept for an specific pin
                    Log.d("PIN", " " + intent.getIntExtra("android.bluetooth.device.extra.PAIRING_KEY",0));
                    //maybe you look for a name or address
                    Log.d("Bonded", device.getName());
                    byte[] pinBytes;
                    pinBytes = (""+pin).getBytes("UTF-8");
                    device.setPin(pinBytes);
                    //setPairing confirmation if neeeded
                    device.setPairingConfirmation(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

在清单文件中也要进行相应的操作。

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

以及广播接收器。

 <receiver android:name=".MainActivity$PairingRequest">
                <intent-filter>
                    <action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
                    <action android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
                </intent-filter>
</receiver>

这个解决方案也适用于 Android Pie 吗?因为我仍然收到确认对话框。 - Tejas Pandya
不,我不认为这个解决方案适用于Android 4.4.2和Android 5,对于Android 6及以上版本不确定。@TejasPandya - Rodolfo Abarca
1
这个解决方案是否可以在没有 Bluetooth_Priveldge 权限的情况下工作? 难道不需要上述权限才能使 device.setPairingConfirmation(true); 这一行代码生效吗? - Harrish Selvarajah
@Harrish,这应该可以工作,但这取决于设备,有些设备需要发送配对确认,而有些设备则认为一旦连接就已经配对了。此解决方案适用于Android 4.4.2和Android 5,因此您可能需要针对Android 6及以上版本进行类似的操作。 - Rodolfo Abarca
方法setPairingConfirmation需要蓝牙特权权限(BLUETOOTH_PRIVILEDGED),但第三方应用程序无法获得该权限。但是使用abortBroadcast,在我的Pixel 4 XL上可以正常工作! - mbo
显示剩余2条评论

7
如何设置 PIN 码已经在上面得到了回答(这对我很有帮助)。然而,我在下面分享我的简单代码,适用于 Android 6:
BluetoothAdapter mBTA = BluetoothAdapter.getDefaultAdapter();
if (mBTA.isDiscovering()) mBTA.cancelDiscovery();
mBTA.startDiscovery();
...

/** In a broadcast receiver: */

if (BluetoothDevice.ACTION_FOUND.equals(action)) { // One device found.

    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    Log.d(TAG, "Start Pairing... with: " + device.getName());
    device.createBond();
}

// If you want to auto-input the pin#:
else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)){

                    BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    device.setPin("1234".getBytes());
}

5

尝试这段代码:

public void pairDevice(BluetoothDevice device)
{
    String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
    Intent intent = new Intent(ACTION_PAIRING_REQUEST);
    String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
    intent.putExtra(EXTRA_DEVICE, device);
    String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT";
    int PAIRING_VARIANT_PIN = 0;
    intent.putExtra(EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);
}

Intent intent = new Intent(BluetoothDevice.ACTION_PAIRING_REQUEST);
intent.putExtra(EXTRA_DEVICE, device);
int PAIRING_VARIANT_PIN = 272;
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);
sendBroadcast(intent);

Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
startActivityForResult(intent, REQUEST_PAIR_DEVICE);

我希望这可以帮到您。
参考:http://pastebin.com/N8dR4Aa1

请帮我......我想要一个启用了蓝牙的设备列表,并在单击特定蓝牙设备后,将其与我们的设备配对。 - Denny Sharma
4
我理解第一个方法,但你建议我们对另外两个代码块怎么处理? - gregm

5
在onCreate()中注册一个BluetoothDevice.ACTION_PAIRING_REQUEST接收器。
val pairingRequestFilter = IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST)
        registerReceiver(pairingReceiver, pairingRequestFilter)

在接收器中使用 setPin() 设置您的 PIN,并调用 abortBroadcast()

val PAIRING_PIN=1234

private var pairingReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent!!.action
            if (BluetoothDevice.ACTION_PAIRING_REQUEST == action) {
                val device: BluetoothDevice? =intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                val type =intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR)
                if (type == BluetoothDevice.PAIRING_VARIANT_PIN) {
                    device?.setPin(PAIRING_PIN.toByteArray())
                    abortBroadcast()
                }
            }
        }
    }

不要忘记在onDestroy()方法中注销广播接收器

override fun onDestroy() {
        super.onDestroy()
        unregisterReceiver(pairingReceiver)
    }

如果对您不起作用,请尝试将接收器的优先级设置为较高。

val pairingRequestFilter = IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST)          
pairingRequestFilter.priority = IntentFilter.SYSTEM_HIGH_PRIORITY - 1
            registerReceiver(pairingReceiver, pairingRequestFilter)

您可以注册一个带有 BluetoothDevice.ACTION_BOND_STATE_CHANGED 的接收器来读取配对状态。
val filter = IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        registerReceiver(receiver, filter)

这是解决该问题的最佳答案。它在我的Android 10 Pixel 4 XL上运行!如果我不调用abortBroadcast,对话框会弹出并在2秒后关闭。 - mbo

1
尝试这个,
BluetoothDevice device = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device);

0
    BluetoothSocket bluetoothSocket = null;
    try {
        bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUID_DIVING));
    } catch (IOException e) {
        Log.i("Bluetooth", "IOException = " + e.getMessage());
        e.printStackTrace();
    }

    try {
        byte[] pin = (byte[]) BluetoothDevice.class.getMethod("convertPinToBytes", String.class).invoke(BluetoothDevice.class, "0000");
        Method m = device.getClass().getMethod("setPin", byte[].class);
        m.invoke(device, (Object) pin);
        device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
    } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        Log.i("Bluetooth", "IOException = " + e.getMessage());
        e.printStackTrace();
    }

    try {
        if (bluetoothSocket != null) {
            bluetoothSocket.connect();
            Log.i("Bluetooth", "bluetoothSocket.connect() ");
            InputStream inputStream = bluetoothSocket.getInputStream();
            OutputStream outputStream = bluetoothSocket.getOutputStream();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

0

bluetoothDevice.createBond方法,可用于配对

要检查配对状态,您必须注册广播接收器BluetoothDevice.ACTION_BOND_STATE_CHANGED

在您的接收器类中,您可以检查blueToothDevice.getBondState


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接