以编程方式连接已配对的蓝牙设备

57

有没有一种使用Android SDK的方法可以以编程方式连接已配对的蓝牙设备?

换句话说:我可以进入"设置"->"无线和网络"->"蓝牙设置",然后点击设备(列为“已配对但未连接”),此时它将连接。我希望能够以编程方式执行此操作,但看不到任何方法。

我看到创建RFCOMM套接字的选项,对于SPP设备,我认为那也会处理连接部分,但对于A2DP设备,实际数据传输将由操作系统而非我的应用程序处理,因此我认为这不适用?


你解决了这个问题吗?我也想知道。 - JonatanEkstedt
4个回答

59

好的,由于这件事让我抓狂了,我研究了一下源代码,并找到了一种100%可靠(至少在我的Nexus 4,Android 4.3上)连接到已配对的A2DP设备(例如耳机或蓝牙音频设备)的解决方案。我发布了一个完全可用的示例项目(使用Android Studio轻松构建),您可以在Github上找到

基本上,你需要做的是:

  • 获取BluetoothAdapter的实例
  • 使用此实例,获取A2DP的配置文件代理:

adapter.getProfileProxy (context, listener, BluetoothProfile.A2DP);

其中listener是一个ServiceListener,将在其onServiceConnected()回调中接收BluetoothProfile(可以转换为BluetoothA2dp实例)

  • 使用反射获取代理上的connect(BluetoothDevice)方法:

Method connect = BluetoothA2dp.class.getDeclaredMethod("connect", BluetoothDevice.class);

  • 找到您的BluetoothDevice


String deviceName = "My_Device_Name";

BluetoothDevice result = null;

Set<BluetoothDevice> devices = adapter.getBondedDevices();
if (devices != null) {
    for (BluetoothDevice device : devices) {
        if (deviceName.equals(device.getName())) {
            result = device;
            break;
        }
    }
}

  • 然后调用connect()方法:

connect.invoke(proxy, result);

对我来说,这至少立即连接了设备。


1
@kcoppock 先生,请查看https://dev59.com/3oTca4cB1Zd3GeqPBvnC以获取SPP配置文件。 - Ajit
1
@user8264:还有一个 BluetoothHeadset 类以及一个 BluetoothProfile.HEADSET 常量。使用这些的更改应该是相当微不足道的。 - Kevin Coppock
1
@WayWay 你可以从你的 BroadcastReceiver 中启动一个新的 IntentService(使用 onReceive 中提供的 Context 来启动它),并让该服务执行蓝牙服务绑定。 - Kevin Coppock
不,这是专门用于解决蓝牙自动连接无法工作的问题。 - Kevin Coppock
3
@KevinCoppock,你真是太棒了!刚才你帮我节省了时间!谢谢! - Georgiy Chebotarev
显示剩余12条评论

4
我发现解决问题的最佳方法是找到可以创建一个按钮来打开蓝牙设置屏幕。我之前并不知道这一点,否则我就会从一开始就这么做了。
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));

2
这不是“编程式”的方法。仍需要用户交互。 - David162795

3
如果设备已经配对成功,您就可以使用它了。
if(device.getBondState()==device.BOND_BONDED){

        Log.d(TAG,device.getName());
        //BluetoothSocket mSocket=null;
        try {


            mSocket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            Log.d(TAG,"socket not created");
            e1.printStackTrace();
        }
        try{

            mSocket.connect();

        }
        catch(IOException e){
            try {

                mSocket.close();
                Log.d(TAG,"Cannot connect");
            } catch (IOException e1) {
                Log.d(TAG,"Socket not closed");
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }


        }

使用MY_UUID

private static final UUID MY_UUID = UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");

以上代码片段仅用于将您的设备连接到支持A2DP的设备。希望它能够正常工作。


这会强制连接一个A2DP耳机吗? - Alec B. Plumb
它只会连接到支持A2DP配置文件的设备,作为一个不安全的套接字,它将在不要求配对的情况下直接连接(因为我们希望如此,因为您的设备已经配对)。 - nam_ph
1
请将UUID更改为“0000110A-0000-1000-8000-00805F9B34FB”或“0000110B-0000-1000-8000-00805F9B34FB”...上述UUID适用于AVRCP而非A2DP,我刚才想错了。 - nam_ph
这段代码能够连接所有不安全的蓝牙设备吗? - abh22ishek

1

1
Marc:感谢回复。这对于点对点应用程序连接非常好,其中您的应用程序想要发送数据(因此抓取BluetoothSocket),但在这种情况下,我只需要为A2DP建立连接;实际数据流由操作系统处理。 - rmc47
啊,我之前没有明白你的其他设备不是安卓设备。 - Marc Bernstein
你找到了与其他蓝牙设备(已配对)非安卓@rmc47的连接解决方案了吗? - nafees ahmed

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