You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何获取蓝牙设置中已配对设备修改后的新名称并监听该变化?

如何获取蓝牙设置中已配对设备修改后的新名称并监听该变化?

你遇到的这个问题我之前帮开发者排查过好多次——明明在系统蓝牙设置里改了配对设备的名称,但不管是遍历bondedDevicesname,还是用MAC地址获取RemoteDevicename,甚至重启重连后都还是旧名字,而且ACTION_LOCAL_NAME_CHANGED只负责监听自己手机的蓝牙名称变化,完全不是你要的配对设备的,对吧?

别着急,我给你拆解下问题本质和解决办法:

一、先搞懂为什么旧方法拿不到新名称

Android里,蓝牙设备的getName()返回的是设备自身广播的原始名称,而你在系统设置里修改的是本地自定义别名——这个别名只存在你手机的系统设置数据库里,不会同步到蓝牙设备本身,所以直接调用getName()肯定拿不到修改后的名字。

二、获取修改后的新名称的正确姿势

分Android版本处理:

1. Android 12(API 31)及以上

系统直接提供了BluetoothDevice.getAlias()方法,专门返回用户修改后的自定义别名,用法很简单:

val bluetoothManager = context.getSystemService<BluetoothManager>()
val bluetoothAdapter = bluetoothManager?.adapter
val targetDevice = bluetoothAdapter?.getRemoteDevice("2C:4D:79:C2:46:E7")

// 获取用户修改后的别名
val customDeviceName = targetDevice?.let {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        it.alias
    } else {
        // 低版本降级处理
        it.name
    }
}

2. Android 12以下版本

系统没有公开的getAlias()方法,得用反射调用隐藏的API来获取本地别名:

fun getBluetoothDeviceAlias(device: BluetoothDevice): String {
    return try {
        val getAliasMethod = BluetoothDevice::class.java.getMethod("getAlias")
        getAliasMethod.invoke(device) as String
    } catch (e: Exception) {
        // 反射失败就 fallback 到设备原始名称
        device.name
    }
}

三、监听配对设备的别名变化

遗憾的是,Android系统没有提供专门的广播来通知单个配对设备的别名修改,但我们可以通过两种方式实现监听:

1. 监听系统设置变化广播

注册ACTION_SETTINGS_CHANGED广播,当蓝牙设置发生变化时,重新获取设备别名:

val settingsChangeFilter = IntentFilter(Intent.ACTION_SETTINGS_CHANGED)
val settingsChangeReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        if (intent?.action == Intent.ACTION_SETTINGS_CHANGED) {
            // 过滤蓝牙设置相关的变化
            val category = intent.getStringExtra(Intent.EXTRA_CATEGORY)
            if (category == Settings.CATEGORY_BLUETOOTH) {
                // 重新获取目标设备的别名并更新你的UI或数据
                val targetDevice = bluetoothAdapter?.getRemoteDevice("2C:4D:79:C2:46:E7")
                targetDevice?.let {
                    val updatedName = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                        it.alias
                    } else {
                        getBluetoothDeviceAlias(it)
                    }
                    // 这里处理更新后的名称,比如刷新列表、弹窗提示等
                }
            }
        }
    }
}

// 注册广播接收器,记得在合适的地方(比如onDestroy)注销
context?.registerReceiver(settingsChangeReceiver, settingsChangeFilter)

2. 内容观察者监听蓝牙设置数据库

如果觉得广播太宽泛,也可以用ContentObserver监听蓝牙设置的内容URI,不过这个URI不同系统版本可能有差异,兼容性稍差:

val bluetoothSettingsUri = Settings.Secure.getUriFor("bluetooth_devices")
val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
    override fun onChange(selfChange: Boolean, uri: Uri?) {
        super.onChange(selfChange, uri)
        if (uri == bluetoothSettingsUri) {
            // 重新获取设备别名
            updateDeviceAlias()
        }
    }
}

// 注册内容观察者,记得注销
context?.contentResolver?.registerContentObserver(bluetoothSettingsUri, true, contentObserver)

四、注意事项

  • 权限:API31+需要申请BLUETOOTH_CONNECT权限;API31以下需要BLUETOOTHACCESS_FINE_LOCATION权限(部分机型可能还需要ACCESS_COARSE_LOCATION)。
  • 注销资源:广播接收器和内容观察者一定要在组件销毁时(比如Activity的onDestroy)注销,避免内存泄漏。

内容来源于stack exchange

火山引擎 最新活动