You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中执行Root权限ADB命令开关飞行模式失效问题咨询

问题根因

你写的Root执行代码存在两个核心问题,导致命令虽然触发了Root授权,但实际没有正确执行:

  • 命令参数解析错误:Runtime.getRuntime().exec() 不会像ADB Shell环境那样自动解析单引号/双引号等Shell语法,它默认按空白字符拆分传入的整条字符串为命令参数。你写的su -c 'settings put global airplane_mode_on 1'会被拆分为su、-c、'settings、put、global、airplane_mode_on、1'几个参数,等于传给su执行的命令是首尾带多余单引号的无效字符串,系统根本找不到名为'settings的可执行文件,命令直接执行失败。你看到的超级用户授权Toast只是证明su进程被成功唤起,不代表后续传入的命令能正常运行。
  • 进程上下文隔离:你两次单独调用exec()会启动两个完全独立的Root权限进程,两个进程的Shell会话不互通,部分定制ROM会对跨会话的系统设置修改、系统广播发送做额外权限校验,就算第一条命令修改了设置值,第二条广播也可能因为上下文不匹配被系统拦截。同时你没有读取命令的执行返回和错误流,完全感知不到执行报错。

另外补充:Android 4.2及以上版本发送飞行模式变更广播时,必须携带--ez state 布尔值的附加参数,否则部分厂商ROM的系统服务不会响应广播切换飞行模式状态,你ADB执行时没加参数能生效是因为部分旧版系统兼容了无参数的广播,不代表应用内执行也能兼容。

正确实现代码

不要使用带单引号的su -c 'xxx'写法,推荐直接获取su进程的输出流,将所有待执行命令一次性写入同一个Root Shell会话执行,避免参数拆分错误和进程隔离问题,Kotlin实现代码如下:

// 启动Root权限进程
val suProcess = Runtime.getRuntime().exec("su")
// 获取进程输出流,用于向Root Shell写入待执行命令
val commandWriter = suProcess.outputStream.bufferedWriter()

// 1. 写入全局配置,设置飞行模式为开启状态(值为0则是关闭)
commandWriter.write("settings put global airplane_mode_on 1\n")
// 2. 写入广播发送命令,携带state参数通知系统状态变更
commandWriter.write("am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true\n")
// 写入退出命令结束Shell会话
commandWriter.write("exit\n")
commandWriter.flush()

// 等待命令执行完成,获取执行返回码,返回0代表执行成功
val execResult = suProcess.waitFor()
commandWriter.close()

// 调试阶段可以读取suProcess.errorStream的内容,打印排查执行报错
额外注意事项
  • 不要多次单独调用exec()启动多个su进程执行多条关联命令,既会重复触发Root权限校验,也容易出现上下文隔离导致的执行失败。
  • 如果需要关闭飞行模式,只需要把airplane_mode_on的值改为0,同时把广播参数里的true改为false即可。
  • 部分Android 10+的定制ROM加强了飞行模式的权限管控,就算有Root权限,部分场景下发送广播也可能被系统拦截,这种情况可以尝试调用系统服务的隐藏API实现,不过Root环境下上述Shell命令方案在绝大多数设备上都可正常生效。

内容的提问来源于stack exchange,提问作者Rest0rer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:27:26