如何以编程方式判断是否已连接蓝牙设备?


86

我了解如何获取已配对设备的列表,但是如何知道它们是否已连接?

由于我在手机的蓝牙设备列表中看到了它们,并指出了它们的连接状态,因此这是必须的。

Answers:


155

向您的AndroidManifest添加蓝牙权限,

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

然后使用意图过滤器来听ACTION_ACL_CONNECTEDACTION_ACL_DISCONNECT_REQUESTEDACTION_ACL_DISCONNECTED广播:

public void onCreate() {
    ...
    IntentFilter filter = new IntentFilter();
    filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
    filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
    this.registerReceiver(mReceiver, filter);
}

//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

        if (BluetoothDevice.ACTION_FOUND.equals(action)) {
           ... //Device found
        }
        else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
           ... //Device is now connected
        }
        else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
           ... //Done searching
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
           ... //Device is about to disconnect
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
           ... //Device has disconnected
        }           
    }
};

一些注意事项:

  • 在应用程序启动时无法检索已连接设备的列表。蓝牙API不允许您查询,而是允许您收听更改。
  • 解决上述问题的一项繁琐工作是检索所有已知/已配对设备的列表……然后尝试连接到每个设备(以确定是否已连接)。
  • 或者,您可以让后台服务监视Bluetooth API并将设备状态写入磁盘,以供您的应用程序以后使用。

2
只要我的应用程序正在运行,这就很好,但是如何获得当前列表呢?
dchappelle 2011年

2
在没有“运行”应用程序的情况下,如何计划执行代码?如果您是说您需要从“活动”以外的其他方式访问此内容,请访问Google Android服务,构建其中一个以收听广播,并将其保存到列表中。
Skylar Sutton

6
我可以听取意图,但是如何获得已连接的蓝牙设备的初始列表?如果在我的活动或服务启动时已经连接了任何设备,我将不会知道。我想(希望)这些数据在某处可用?我不想只为了听这些意图而创建一项服务(只要打开手机,它就会一直运行)。
dchappelle 2011年

11
在应用程序启动时无法检索已连接设备的列表。蓝牙API仅允许您监听连接更改。因此,是的,唯一的方法是创建一个长期运行的服务并添加/删除到公共列表。这是很多开发人员的抱怨。根据您的性能需求,您可以检索已配对设备的列表,然后尝试连接到每个设备。如果失败,则不可用。警告词:.connect()是阻塞操作。
Skylar Sutton

1
@skylarsutton +1非常感谢您的回答,帮助我开始使用蓝牙
AgentKnopf 2012年

33

在我的用例中,我只想查看是否为VoIP应用程序连接了蓝牙耳机。以下解决方案为我工作:

public static boolean isBluetoothHeadsetConnected() {
    BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
            && mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED;
} 

当然,您需要蓝牙许可:

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


2
这是我想要的。只是在启动时检查蓝牙是否已连接。谢谢工作!
sud007 '17

11

非常感谢Skylarsutton的回答。我将其发布为对他的回应,但由于我正在发布代码,因此无法作为评论回复。我已经赞成他的回答,所以我不在寻找任何要点。只是支付它。

由于某些原因,Android Studio无法解析BluetoothAdapter.ACTION_ACL_CONNECTED。也许在Android 4.2.2中已弃用?这是他的代码的修改。注册码是一样的;接收方代码略有不同。我在一项服务中使用了此服务,该服务会更新该应用程序其他部分引用的蓝牙连接标志。

    public void onCreate() {
        //...
        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        this.registerReceiver(BTReceiver, filter);
    }

    //The BroadcastReceiver that listens for bluetooth broadcasts
    private final BroadcastReceiver BTReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();

        if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
            //Do something if connected
            Toast.makeText(getApplicationContext(), "BT Connected", Toast.LENGTH_SHORT).show();
        }
        else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
            //Do something if disconnected
            Toast.makeText(getApplicationContext(), "BT Disconnected", Toast.LENGTH_SHORT).show();
        }
        //else if...
    }
};

1
您的代码是正确的;它在4.2.2中没有被弃用。BluetoothAdapter类不包含ACTION_ACL_CONNECTED。该字符串在BluetoothDevice类中。
RobLabs

感谢您的澄清!
pmont

4

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java中的BluetoothDevice系统API中有一个isConnected函数。

如果您想知道有界(配对)设备当前是否已连接,以下功能对我来说很好:

public static boolean isConnected(BluetoothDevice device) {
    try {
        Method m = device.getClass().getMethod("isConnected", (Class[]) null);
        boolean connected = (boolean) m.invoke(device, (Object[]) null);
        return connected;
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
}

您是否看到过与仅检查是否给出不同的结果bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED
Gumby The Green

据我所知,它们确实给出了相同的结果。请注意,对于Kotlin用户,前两行分别是justval m: Method = device.javaClass.getMethod("isConnected")val connected = m.invoke(device)
Gumby The Green

谢谢,正是我所需要的!这是此方法的kotlin等效项:fun isConnected(device: BluetoothDevice): Boolean { return try { val m: Method = device.javaClass.getMethod( "isConnected" ) m.invoke(device) as Boolean } catch (e: Exception) { throw IllegalStateException(e) } }
Takeya

1

该代码用于耳机配置文件,可能也适用于其他配置文件。首先,您需要提供配置文件侦听器(科特琳代码):

private val mProfileListener = object : BluetoothProfile.ServiceListener {
    override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
        if (profile == BluetoothProfile.HEADSET) 
            mBluetoothHeadset = proxy as BluetoothHeadset            
    }

    override fun onServiceDisconnected(profile: Int) {
        if (profile == BluetoothProfile.HEADSET) {
            mBluetoothHeadset = null
        }
    }
}

然后在检查蓝牙时:

mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET)
if (!mBluetoothAdapter.isEnabled) {
    return Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
}

在调用onSeviceConnected之前需要花费一些时间。之后,您可以从以下位置获取已连接的耳机设备的列表:

mBluetoothHeadset!!.connectedDevices

0

BluetoothAdapter.getDefaultAdapter().isEnabled ->蓝牙打开时返回true

val audioManager = this.getSystemService(Context.AUDIO_SERVICE) as AudioManager

audioManager.isBluetoothScoOn ->连接设备时返回true


0

我确实在寻找一种方法来获取设备的连接状态,而不是监听连接事件。这对我有用:

BluetoothManager bm = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bm.getConnectedDevices(BluetoothGatt.GATT);
int status = -1;

for (BluetoothDevice device : devices) {
  status = bm.getConnectionState(device, BLuetoothGatt.GATT);
  // compare status to:
  //   BluetoothProfile.STATE_CONNECTED
  //   BluetoothProfile.STATE_CONNECTING
  //   BluetoothProfile.STATE_DISCONNECTED
  //   BluetoothProfile.STATE_DISCONNECTING
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.