目前连接的蓝牙设备(Android)

17

我能看到 Android 上的蓝牙设备有两种状态: 1. 已配对 2. 连接中。
我正在尝试获取当前已连接的 Android 蓝牙设备。但我只能从 adapter.getBondedDevices(); 获取已配对的设备列表。我需要获取当前连接的设备。请有经验的人帮助我实现这个功能。先谢谢。


<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> 使用这些权限,同时查看此链接 http://stackoverflow.com/questions/14834318/android-how-to-pair-bluetooth-devices-programmatically - Android
这个问题对我来说并不十分清楚。你具体做了什么?当你执行 btlDevice.CreateRfcommSocketToServiceRecord (MY_UUID) 时,你创建了一个已连接的 btlDevice;或者系统会使用上一次连接的 btlDevice。请更详细地说明你在做什么。 - Majkl
请查看此链接:https://dev59.com/q4Tba4cB1Zd3GeqP3DkJ - Jitender Dev
1
我找到了一个解决方案,它适用于Android 10。 code - Kirill Martyuk
4个回答

11

这很简单。Android BluetoothManager 有一个方法叫做

getConnectedDevices()

实现方式如下:

BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
    List<BluetoothDevice> connected = manager.getConnectedDevices(GATT);
    Log.i("Connected Devices: ", connected.size()+"");

如果您想了解有关连接设备的更多详细信息,则可以使用上面的列表方法将其放入循环中,并获取每个已连接蓝牙设备的内部详细信息。

日志:

12-20 18:04:09.679 14933-14933/com.salman.dleague.blescanning I/Connected Devices:: 2
希望它有所帮助 :)

你有一个 <API 18的解决方案吗? - lawonga
4
这是用于BLE吗?我尝试连接我的智能手机进行媒体音频传输。无论是GATT还是GATT_SERVER都返回0大小。 - Yeung
我的设备已经连接了蓝牙,但是仍然在Yeung处收到“0”。请问您有什么解决方案吗? - GNK
@GNK。抱歉,我不需要继续处理这个问题了。如果您想查看Android设置界面中的蓝牙设备,可以查看设置应用程序源代码。我已经看过了,但是它非常复杂...此外,在问题下面的评论(适用于Android 10)可能会有所帮助。 - Yeung
1
将“GATT = BluetoothProfile.GATT_SERVER”设置,同样有效。 - Chakib Temal
这是一个非常不专业的回答,因为它无法返回所有连接的设备。 - user924

2
在你的清单文件中添加以下内容:
<receiver android:name=".MyBluetoothReceiver" >
<intent-filter>
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" 
/>
<action 
android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" 
/>           
</intent-filter>  
</receiver>  

添加这个类

public class MyBluetoothReceiver extends BroadcastReceiver {
 @Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();

    // When discovery finds a device
    if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {

    BluetoothDevice device = intent
                .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

     Toast.makeText(getApplicationContext(),device.getName() +" CONNECTED",Toast.LENGTH_LONG).show();

    } else if (BluetoothAdapter.ACL_DISCONNECTED
            .equals(action)) {

    }
}
}

2
这将只在设备连接时发出通知。如果设备已经连接,然后再启动您的应用程序呢?如何获取已连接的设备? - M. Usman Khan

0

我之前使用了一种方法来获取通过“耳机”配置文件连接的设备,但是我在使用三星Galaxy Watch 4时遇到了问题,因为它被识别为“耳机”设备,即使它不支持音频。当只是询问是否连接了“耳机”时,这会带来问题,因为您可能会无意中尝试将音频发送到该设备,即使它不支持音频。

要获取所有已连接的设备,您需要使用ServiceListener。好消息是,服务侦听器将始终列出已连接的设备,并且您可以使用它来检查它们是否支持音频。为了进一步简化事情,我使用了以下回调流程:

@OptIn(ExperimentalCoroutinesApi::class)
internal fun headsetConnectedAndSupportsAudio() = callbackFlow<Boolean> {
    val serviceListener = object : BluetoothProfile.ServiceListener {

        override fun onServiceDisconnected(profile: Int) = Unit // no op

        override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
            var connected = false
            var supportsAudio = false

            // check for a device that supports audio and is connected in our connected bluetooth devices.
            for (device in proxy.connectedDevices) {
                connected = proxy.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED
                supportsAudio = device.bluetoothClass.hasService(BluetoothClass.Service.AUDIO)

                Timber.d("Bluetooth Device - ${device.name} isConnected: $connected supportsAudio: $supportsAudio")
                // we have found a connected device that supports audio, stop iterating and emit a success
                if (connected && supportsAudio) { break }
            }

            trySend(connected && supportsAudio)
                .onClosed { throwable -> Timber.e(throwable) }
                .isSuccess

            getBluetoothAdapter().closeProfileProxy(profile, proxy)

            close()
        }
    }

    // register our service listener to receive headset connection updates
    getBluetoothAdapter().getProfileProxy(
        context,
        serviceListener,
        BluetoothProfile.HEADSET
    )

    awaitClose { channel.close() }
}

然后要使用回调流,你可以这样做:

mainScope.launch {
   headsetConnectedAndSupportsAudio().cancellable().collect { btAudioSourceConnected ->
       if (btAudioSourceConnected) {
           Timber.d("Bluetooth headset connected + supports audio"
       } else {
           Timber.d("No Bluetooth headset connected that supports audio")
       }
   }

}


如何使其始终运行?这只能像方法调用一样工作,而不是像广播接收器一样? - Rohit gupta
我已经设置了一个回调流程来使用。对我来说,这简化了检查过程,因为我可以将其视为一个函数调用,它会返回答案。这也让我在想要进行检查时非常明确,这对我的使用情况很重要。 - notmystyle

0

我终于找到了下面的方法可以工作

我们可以使用反射技术来调用Android SDK方法以获取已连接设备。以下是对我有效的代码。

private void checkBluetoothGamepadIsConnected() {
        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;
        boolean isConnectedGamePad = false;
        try {
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState",
                                                                    (Class[]) null);
            //Open permission.
            method.setAccessible(true);
            int state = (int) method.invoke(adapter, (Object[]) null);
            LogUtil.d("MainViewModel" + "getConnectedBluetooth() state:" + state);
            LogUtil.d(TAG + "getConnectedBluetooth() state:" + state
                              + " stateSTATE_CONNECTED:" + BluetoothAdapter.STATE_CONNECTED
                              + " STATE_CONNECTING:" + BluetoothAdapter.STATE_CONNECTING
                              + " STATE_DISCONNECTED:" + BluetoothAdapter.STATE_DISCONNECTED);

            Set<BluetoothDevice> devices = adapter.getBondedDevices();
            LogUtil.d(TAG + "getConnectedBluetooth devices.size:" + devices.size());
            for (BluetoothDevice device : devices) {
                Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected",
                                                                                   (Class[]) null);
                method.setAccessible(true);
                boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                LogUtil.d(TAG + "getConnectedBluetooth() isConnected:" + isConnected
                                  + " getAddress:" + device.getAddress() + " getName:" + device.getName());
                if (isConnected) {
                    LogUtil.d(TAG + "getConnectedBluetooth() ** Connected getAddress:"
                                      + device.getAddress() + " getName:" + device.getName() + " getBondState:"
                                      + device.getBondState() + " getType:" + device.getType());
                    if(device.getName().contains(GAMEPAD_NAME)){
                        isConnectedGamePad = true;
                        break;
                    }
                }
            }

        } catch (Exception e) {
            LogUtil.d(TAG + "getConnectedBluetooth() error:" + e.toString());
            e.printStackTrace();
        }
        isGamePadConnectedData.postValue(isConnectedGamePad);
    }

详细解释

您使用以下方法无法知道设备当前是否连接,必须使用调用来检查连接或未连接。

Set<BluetoothDevice> devices = adapter.getBondedDevices();

最重要的在这里

    Set<BluetoothDevice> devices = adapter.getBondedDevices();
            LogUtil.d(TAG + "getConnectedBluetooth devices.size:" + devices.size());
            for (BluetoothDevice device : devices) {
                Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected",
                                                                                   (Class[]) null);
                method.setAccessible(true);
                boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                LogUtil.d(TAG + "getConnectedBluetooth() isConnected:" + isConnected
                                  + " getAddress:" + device.getAddress() + " getName:" + device.getName());
                if (isConnected) {
                    LogUtil.d(TAG + "getConnectedBluetooth() ** Connected getAddress:"
                                      + device.getAddress() + " getName:" + device.getName() + " getBondState:"
                                      + device.getBondState() + " getType:" + device.getType());
                    if(device.getName().contains(GAMEPAD_NAME)){
                        isConnectedGamePad = true;
                        break;
                    }
                }
            }

解释重要内容

关于常量GAMEPAD_NAME是我的蓝牙设备名称, 我的做法是检查我的蓝牙是否已连接。

当我的蓝牙连接时,它将返回true。 变量isConnectedGamePad = true;

我的livedata将发布布尔值isConnect。

这个功能非常好用。


新版Android中禁止使用反射。 - user924

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