Android SDK≥32时如何获取用户可编辑的设备名称(非型号)
问题场景
此前通过读取Settings.Secure.BLUETOOTH_NAME获取用户自定义设备名称,代码如下:
public static String getDeviceName(ContentResolver contentResolver) { String userDeviceName = Settings.Secure.getString(contentResolver, "bluetooth_name"); if (userDeviceName == null) return ""; Log.d(TAG, "getDeviceName: userDeviceName: " + userDeviceName); return userDeviceName; }
但当应用target SDK≥32时,会抛出如下SecurityException:
Caused by java.lang.SecurityException: Settings key: <bluetooth_name> is only readable to apps with targetSdkVersion lower than or equal to: 31
at android.provider.Settings$NameValueCache.getStringForUser(Settings.java:3323)
at android.provider.Settings$Secure.getStringForUser(Settings.java:9400)
at android.provider.Settings$Secure.getString(Settings.java:9356)
at com.bytecode.sola_android.utils.ValueUtils.getDeviceName(ValueUtils.java:26)
at com.bytecode.sola_android.activity.MainActivity.onCreate(MainActivity.java:55)
at android.app.Activity.performCreate(Activity.java:8591)
..............................
尝试使用Settings.Global.getString(application.contentResolver, Settings.Global.DEVICE_NAME) ?: "UNKNOWN",但该方法返回的是设备型号,而非用户在「设置->关于手机->设备名称」或「设置->蓝牙->设备名称」中修改的自定义名称。
解决方案
权限配置
在AndroidManifest.xml中添加对应蓝牙权限,适配不同版本:
<!-- Android 12及以下版本所需权限 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <!-- Android 13+所需权限 --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
代码实现
通过BluetoothAdapterAPI获取用户自定义设备名称,同时处理权限和版本兼容:
import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import android.provider.Settings; public static String getCustomDeviceName(Context context) { BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 13+ 需检查BLUETOOTH_CONNECT权限 if (context.checkSelfPermission(android.Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) { String customName = bluetoothAdapter.getName(); if (customName != null && !customName.isEmpty()) { return customName; } } } else { // Android 12及以下直接获取蓝牙名称 String customName = bluetoothAdapter.getName(); if (customName != null && !customName.isEmpty()) { return customName; } // 降级使用原Settings方法兜底 String settingsName = Settings.Secure.getString(context.getContentResolver(), "bluetooth_name"); if (settingsName != null && !settingsName.isEmpty()) { return settingsName; } } } // 所有方案失败时返回设备型号作为兜底 return Build.MODEL; }
关键说明
- Android 13+限制了
Settings.Secure.BLUETOOTH_NAME的读取权限,必须通过BluetoothAdapter.getName()获取自定义名称,且需动态申请BLUETOOTH_CONNECT权限。 - 用户在系统设置中修改的设备名称(蓝牙/关于手机中的名称)是同步的,
BluetoothAdapter.getName()可直接获取该自定义值。 - 若蓝牙未开启或权限未授予,最终返回设备型号作为兜底。
内容的提问来源于stack exchange,提问作者ganjaam

