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

时间:2011-02-14 07:54:42

标签: android bluetooth

对于我的应用程序,我正在尝试以编程方式配对蓝牙设备。我能够显示我想要配对的设备的配对对话框,我可以输入密码。当我按下“配对”时,对话框被删除,没有任何反应。

我只需要支持Android 2.0及更新版本的设备。

目前我正在使用以下代码启动配对进度:


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);
    }

在开始配对请求之前,我停止扫描新设备。

我的应用程序具有以下蓝牙权限:

  • android.permission.BLUETOOTH_ADMIN
  • android.permission.BLUETOOTH

10 个答案:

答案 0 :(得分:10)

我设法通过作为服务的应用程序自动请求与键盘特色设备的配对程序,检查是否存在特定类型的设备和设置应用程序的修改版本。

我不得不说我正在开发运行Android 4.0.3而没有外部控件的自定义设备(没有后退/主页/确认按钮):在启动完成时将控制器配对,无需任何交互,直到PIN请求为止。

首先,我创建了一个启动活动的服务(android.intent.action.BOOT_COMPLETEDandroid.permission.RECEIVE_BOOT_COMPLETED)定期检查是否存在1344类设备(键盘,是根据请求输入数据的唯一方法) onReceive回调:

public void onReceive(Context context, Intent intent) 
...
    BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
...
if(dev.getBluetoothClass().getDeviceClass() == 1344){...}

一旦过滤,我选择第一个可用的键盘,然后将BT地址传递给设置应用程序:

Intent btSettingsIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
btSettingsIntent.putExtra("btcontroller", dev.getAddress());
startActivityForResult(btSettingsIntent, 1);

棘手的部分是寻找调用配对过程的最佳位置。仅使用

intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, PAIRING_VARIANT_PIN);

引导我进入一个削弱的对话框,一旦关闭,我就会将设备配对,但无法使用。

深入研究com.Android.settings.Bluetooth的课程我找到了通过

的方法
createDevicePreference(CachedBluetoothDevice cachedDevice) 
DeviceListPreferenceFragment中的

从那里,我确实将我之前选择的BT地址与可用的BT地址进行了比较,一旦成功匹配,我就打电话

cachedDevice.startPairing();

我知道,这很棘手并需要访问Android源代码,但在自定义环境中它可以运行。

我希望这可能有所帮助。

答案 1 :(得分:4)

不幸的是,我认为您将获得的最佳功能是打开设置/无线&用户的网络/蓝牙设置如下:

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

答案 2 :(得分:4)

这是我的答案:

onCreate()中的

写下这个:

private final BroadcastReceiver incomingPairRequestReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {
            BluetoothDevice dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            //pair from device: dev.getName()
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                dev.setPairingConfirmation(true);
                //successfull pairing
            } else {
                //impossible to automatically perform pairing,
                //your Android version is below KITKAT
            }
        }
    }
};

然后创建变量

mrg_stacks(s1, s2)

答案 3 :(得分:3)

使用反射,您可以从BluetoothDevice类调用方法createBond。

请参阅此帖子:How to unpair or delete paired bluetooth device programmatically on android?

还有一个非配对解决方案。

答案 4 :(得分:2)

反思是DODGY,不同的制造商可以按照自己的意愿改变这些基本方法!我在这里的10个设备上测试了许多不同的应用程序,这些反射方法仅适用于大约75%的设备。如果你想要一个适合每个人的应用程序在使用反射时要非常小心 - 尝试一些云测试来测试你的应用程序在100多个设备上并检查故障率。

在这种情况下,自API 19(KitKat 4.4)

以来根本不需要反射

BluetoothDevice有新方法CreateBond。

 private void pairDevice(BluetoothDevice device) {

            device.createBond();
    }

developer.android.com/reference/android/bluetooth/BluetoothDevice.html

答案 5 :(得分:0)

您可能需要startActivityForResult而不仅仅是startActivity吗?

其他选项是查看BluetoothChat应用程序示例并启动RFComm连接套接字,一旦启动套接字,配对请求将自动显示,而无需发送单独的配对意图。这样您就不需要处理配对了。

http://developer.android.com/resources/samples/BluetoothChat/index.html

答案 6 :(得分:0)

我正在使用此课程在客户端智能手机和服务器设备之间建立连接:

private class ConnectThread extends Thread
{
    private final BluetoothSocket mmSocket;

    private final UUID WELL_KNOWN_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

    public ConnectThread(BluetoothDevice device)
    {
        // Use a temporary object that is later assigned to mmSocket,because
        // mmSocket is final
        BluetoothSocket tmp = null;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try
        {
            tmp = device.createRfcommSocketToServiceRecord(WELL_KNOWN_UUID);
            //This is the trick
            Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
            tmp = (BluetoothSocket) m.invoke(device, 1);
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        mmSocket = tmp;
    }

    public void run()
    {
        DebugLog.i(TAG, "Trying to connect...");
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        try
        {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
            DebugLog.i(TAG, "Connection stablished");
        } catch (IOException connectException)
        {
            // Unable to connect; close the socket and get out
            DebugLog.e(TAG, "Fail to connect!", connectException);
            try
            {
                mmSocket.close();
            } catch (IOException closeException)
            {
                DebugLog.e(TAG, "Fail to close connection", closeException);
            }
            return;
        }
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel()
    {
        try
        {
            mmSocket.close();
        } catch (IOException e)
        {
        }
    }
}

首先,获取要连接的BluetoothDevice对象(列出配对设备或发现设备)。然后做:

ConnectThread ct = new ConnectThread(device);
ct.start();

因为connect()是阻塞调用,所以应始终在与主活动线程分开的线程中执行此连接过程。有关详细信息,请参阅Android Developers

答案 7 :(得分:-1)

我发现为PAIRING_VARIANT_PIN使用不同的值会导致不同的配对UI行为。

查看此页面: http://code.google.com/p/backport-android-bluetooth/source/browse/trunk/backport-android-bluetooth201/src/backport/android/bluetooth/BluetoothDevice.java?spec=svn67&r=67

我怀疑你遇到的问题是两台设备都是蓝牙2.1,在这种情况下,配对请求应该会在两台设备上显示6位密码。

我能够实现的最佳结果是使用PAIRING_VARIANT_PIN = 0.当我的应用程序提示时,我输入了针脚1234并且我的目标设备上出现了一个6位数的密钥。配对UI完成,就是这样。

您需要了解如何使用其他配对变体或配对变体引脚启动蓝牙2.1配对请求。或者,您没有捕获正常运行的活动的结果。

考虑到我尝试这样做的时间,我决定在使用我的应用程序之前,我的最终用户只需使用android设置进行配对。

答案 8 :(得分:-1)

这就是我得到它的方式:

Bluetooth device = mBtAdapter.getRemoteDevice(address);
//address:11:23:FF:cc:22 
Method m = device.getClass()        
 .getMethod("createBond", (Class[]) null);
         m.invoke(device, (Object[]) null); // send pairing dialog request

After pairing//
       connectDevice(address);

答案 9 :(得分:-2)

除了我的评论,顺便说一下,即使这些ACTION类型确实存在,也不是你如何使用它们。这是一个例子:

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);