Android中通过代码执行settings命令读取全局设置失败的问题排查
解决Android代码读取全局设置的权限问题
我来帮你搞定这个问题!首先得搞清楚为什么ADB能执行settings list global但你的APP代码不行:ADB shell是拥有系统级权限的,而普通Android APP运行在沙箱环境里,权限受到严格限制。你遇到的INTERACT_ACROSS_USERS是系统签名级权限,普通APP根本没法通过常规权限申请流程拿到,这就是shell命令执行失败的核心原因。
下面给你两种解决方案,优先推荐第一种官方API的方式:
方案一:使用Android官方API(推荐)
Android SDK提供了Settings.Global类专门用来读取和修改全局设置,这是官方支持的稳定方式,完全不需要依赖shell命令,也能避开权限问题。
步骤1:声明权限
在AndroidManifest.xml中添加读取设置的权限:
<uses-permission android:name="android.permission.READ_SETTINGS" />
步骤2:编写读取代码
可以直接读取单个设置项,或者查询所有全局设置:
private void readGlobalSettings() { // 读取单个设置项:比如stay_on_while_plugged_in try { int stayOnValue = Settings.Global.getInt( getContentResolver(), Settings.Global.STAY_ON_WHILE_PLUGGED_IN, -1 // 默认值,当读取失败时返回 ); Log.d("settings", "stay_on_while_plugged_in = " + stayOnValue); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); Log.e("settings", "Failed to read stay_on_while_plugged_in"); } // 读取所有全局设置项 Cursor cursor = getContentResolver().query( Settings.Global.CONTENT_URI, null, null, null, null ); if (cursor != null) { while (cursor.moveToNext()) { String key = cursor.getString(cursor.getColumnIndex(Settings.Global.NAME)); String value = cursor.getString(cursor.getColumnIndex(Settings.Global.VALUE)); Log.d("settings", key + "=" + value); } cursor.close(); } }
说明
- 这个方法不需要申请
ACTION_MANAGE_WRITE_SETTINGS权限(除非你要修改设置),读取只需要READ_SETTINGS权限。 - 对于Android 13及以上版本,部分敏感设置项可能需要额外的权限,但大部分全局设置都可以通过这种方式正常读取。
方案二:使用Shell命令(仅特殊场景)
如果因为某些原因必须用settings命令,那只有两种可行途径,但都有局限性:
- 系统签名:给你的APP签名设备的系统证书,这样APP就能获得系统级权限,执行
settings命令就不会报错。但系统签名文件一般只有ROM厂商或定制ROM开发者能获取,普通开发者很难拿到。 - Root权限:在设备root的前提下,通过
su命令提升权限后执行settings命令,示例代码如下:
private void executeSettingsCommand() { try { String command = "su -c settings list global"; Process shell = Runtime.getRuntime().exec(command); shell.waitFor(); BufferedReader br = new BufferedReader(new InputStreamReader(shell.getInputStream())); String line; while ((line = br.readLine()) != null) { Log.d("settings", line); } // 读取错误输出排查问题 BufferedReader errBr = new BufferedReader(new InputStreamReader(shell.getErrorStream())); String errLine; while ((errLine = errBr.readLine()) != null) { Log.e("settings_err", errLine); } } catch (Exception e) { e.printStackTrace(); } }
但root权限会带来安全风险,而且不是所有用户的设备都有root权限,所以不推荐普通APP使用这种方式。
内容的提问来源于stack exchange,提问作者Giovesoft




