【问题标题】:Programmatically pair Bluetooth device without the user entering pin无需用户输入密码即可以编程方式配对蓝牙设备
【发布时间】:2013-09-27 10:01:23
【问题描述】:

我尝试连接的蓝牙设备始终具有相同的密码。这应该可以通过编程设置引脚来配对设备。

在尝试搜索如何做到这一点后,我最终得到了以下代码:

BluetoothDevice device = getDevice();

//To avoid the popup notification:
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device, true);
byte[] pin = ByteBuffer.allocate(4).putInt(1234).array();
//int pinn = 1234;

//Entering pin programmatically:  
Method ms = device.getClass().getMethod("setPin", byte[].class);
//Method ms = device.getClass().getMethod("setPasskey", int.class);
ms.invoke(device, pin);

//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);

cancelPairingUserInput 给了我一个NoSuchMethodException,这很奇怪,因为该方法确实存在于BluetoothDevice 类中。

看起来像 SetpinSetPasskey 没有做任何事情。该设备只是不会配对。只有在手动输入密码后才能配对。

所以唯一有效的代码行是:

//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);

Logcat 输出:

09-27 12:34:46.408: ERROR/App(11671): cancelPairingUserInput [boolean]
        java.lang.NoSuchMethodException: cancelPairingUserInput [boolean]
        at java.lang.Class.getConstructorOrMethod(Class.java:460)
        at java.lang.Class.getMethod(Class.java:915)
        at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.pair(BluetoothDiscoveryAndPairing.java:97)
        at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.access$000(BluetoothDiscoveryAndPairing.java:25)
        at test.app.bluetooth.model.BluetoothDiscoveryAndPairing$1.onReceive(BluetoothDiscoveryAndPairing.java:79)
        at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:756)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4921)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
        at dalvik.system.NativeStart.main(Native Method)

那我做错了什么?

【问题讨论】:

  • @DuncanJones 我将堆栈跟踪添加到我的 startpost。

标签: java android bluetooth


【解决方案1】:

您的设备中不存在隐藏方法 cancelPairingUserInput。不要使用它。

  1. 您应该为 android.bluetooth.device.action.PAIRING_REQUEST 注册 BroadcastReceiver
  2. 调用 createBond()
  3. 等待 BroadcastReceiver 触发
  4. 如果 action 是 android.bluetooth.device.action.PAIRING_REQUEST 在 BroadcastReceiver 调用这个方法
public void setBluetoothPairingPin(BluetoothDevice device)
{
    byte[] pinBytes = convertPinToBytes("0000");
    try {
          Log.d(TAG, "Try to set the PIN");
          Method m = device.getClass().getMethod("setPin", byte[].class);
          m.invoke(device, pinBytes);
          Log.d(TAG, "Success to add the PIN.");
          try {
                device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
                Log.d(TAG, "Success to setPairingConfirmation.");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                Log.e(TAG, e.getMessage());
                e.printStackTrace();
            } 
        } catch (Exception e) {
          Log.e(TAG, e.getMessage());
          e.printStackTrace();
        }
}

它也适用于装有 Jelly Bean 版本 (4.1.2) 的 Android 设备。

【讨论】:

  • 这可以在 API Level 19 之前完成吗? android.bluetooth.device.action.PAIRING_REQUEST 仅在 API 19 上引入
  • 为什么需要 setPairingConfirmation() ? Android 文档说它仅适用于 PAIRING_VARIANT_PASSKEY_CONFIRMATION,不适用于旧版配对。此外,在 Android6 上它需要 BLUETOOTH_PRIVILEGED
  • 如果任何人都无法访问 convertPinToBytes,可以在这里找到源代码:android.googlesource.com/platform/frameworks/base/+/master/core/…
  • 这不起作用,因为它需要 BLUETOOTH_PRIVILEGED 权限,该权限仅在系统应用上可用。
【解决方案2】:

这对我有用:

    IntentFilter filter2 = new IntentFilter(
            "android.bluetooth.device.action.PAIRING_REQUEST");
    mActivity.registerReceiver(
            pairingRequest, filter2);

private final BroadcastReceiver pairingRequest = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
            mBluetoothDevice = needed;
                try {
                    byte[] pin = (byte[]) BluetoothDevice.class.getMethod("convertPinToBytes", String.class).invoke(BluetoothDevice.class, "1234");
                    Method m = mBluetoothDevice.getClass().getMethod("setPin", byte[].class);
                    m.invoke(mBluetoothDevice, pin);
                    mBluetoothDevice.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(mBluetoothDevice, true);
}
    catch(Exception e)
{

    e.printStackTrace();

}

【讨论】:

  • 只有尝试配对的设备才需要此代码吗?我们不需要其他正在配对的设备上的任何代码吗?
  • 您不需要其他设备的任何代码。您应该只接受连接。 (我为连接到移动打印机的安卓手机编写了这段代码。)
猜你喜欢
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 2011-07-07
  • 2013-06-25
相关资源
最近更新 更多