在Android开发中,调用系统命令是一个相对高级的操作,通常用于实现需要底层系统权限的功能,如设备调试、系统服务管理或硬件交互等,Android基于Linux内核,因此许多Linux命令可以通过特定的API或工具在应用中执行,由于安全限制,直接调用系统命令在普通应用中受到严格限制,通常需要系统级权限(如root权限)或通过Android提供的官方API间接实现,本文将详细介绍Android调用系统命令的方法、注意事项及实际应用场景。

调用系统命令的方法
在Android中,调用系统命令主要有以下几种方式,每种方式适用于不同的场景和权限级别。
使用Runtime.exec()方法
Runtime.exec()是最常用的调用系统命令的方式,通过Java的Runtime类或ProcessBuilder类执行命令并获取输出,基本语法如下:
try {
Process process = Runtime.getRuntime().exec("command");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
Log.d("CommandOutput", line);
}
process.waitFor();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
注意事项:
- 命令需要以字符串数组形式传递,避免空格和特殊字符导致的解析错误。
new String[]{"ls", "-l"}。 - 需要处理命令的输入流(
InputStream)和错误流(ErrorStream),否则可能导致进程阻塞。 - 此方法需要
android.permission.INTERNET权限(部分场景下),且在Android 10(API 29)以上,对后台执行命令的限制更严格。
使用Shell脚本
对于复杂的命令序列,可以编写Shell脚本(如script.sh),将其放入应用的assets目录,然后通过Runtime.exec()执行脚本,执行前需将脚本复制到可执行目录(如/data/local/tmp)并赋予执行权限:

String[] cmd = {"sh", "/data/local/tmp/script.sh"};
Process process = Runtime.getRuntime().exec(cmd);
使用Android Debug Bridge (ADB)
在调试阶段,可以通过ADB命令在设备或模拟器上执行操作,通过adb shell进入命令行界面后直接执行命令,在应用中,可以通过Process类调用ADB命令:
String[] cmd = {"adb", "shell", "pm list packages"};
Process process = Runtime.getRuntime().exec(cmd);
使用反射调用隐藏API
某些系统命令可能通过Android的隐藏API提供支持,通过反射调用ServiceManager或ActivityManager的隐藏方法:
try {
Class<?> serviceManager = Class.forName("android.os.ServiceManager");
Method getService = serviceManager.getMethod("getService", String.class);
Object binder = getService.invoke(null, "window");
// 进一步处理binder对象
} catch (Exception e) {
e.printStackTrace();
}
注意事项:隐藏API可能在系统更新后失效,且需要应用签名与系统签名一致(或使用HiddenApiAccessibility配置)。
权限与安全限制
Android对系统命令的调用有严格的安全限制,普通应用无法直接执行敏感命令(如reboot、su等),以下是主要限制:

- 普通应用权限:默认只能调用非敏感命令(如
ls、dumpsys部分参数),且无法获取root权限。 - Root权限:需要设备已root,并通过
su命令提升权限。Process process = Runtime.getRuntime().exec(new String[]{"su", "-c", "reboot"});风险:Root权限可能导致安全漏洞,且应用无法通过Google Play审核。
- SELinux策略:Android 7.0以上启用了SELinux,限制了对系统目录的访问,需确保命令符合上下文安全策略。
实际应用场景
- 设备信息获取:通过
dumpsys命令获取系统服务信息(如电池状态、内存使用情况)。String[] cmd = {"dumpsys", "battery"}; Process process = Runtime.getRuntime().exec(cmd); - 系统设置修改:通过
settings命令修改系统配置(如亮度、音量),需WRITE_SECURE_SETTINGS权限。 - 硬件控制:通过
echo命令控制GPIO引脚(需硬件支持),String[] cmd = {"sh", "-c", "echo 1 > /sys/class/gpio/gpio18/value"}; Process process = Runtime.getRuntime().exec(cmd);
常见问题与解决方案
命令执行后进程阻塞
原因:未及时读取命令的输入流或错误流,导致缓冲区满。
解决方案:使用单独的线程读取输入流和错误流,或使用ProcessBuilder重定向流。
命令无权限执行
原因:命令需要root权限或系统级权限。
解决方案:检查应用权限配置,或通过su提权(需设备root)。
相关问答FAQs
问题1:为什么在Android 10以上调用Runtime.exec()执行某些命令会失败?
解答:Android 10(API 29)引入了更严格的分区存储和后台执行限制,某些命令(如访问/system目录)需要android.permission.QUERY_ALL_PACKAGES或系统级权限,后台应用无法直接执行长时间运行的命令,需通过JobScheduler或ForegroundService实现。
问题2:如何安全地在应用中调用需要root权限的命令?
解答:安全调用root权限命令需注意以下几点:
- 确保设备已root,且应用被授予
su权限(通过Superuser等管理工具)。 - 避免硬编码敏感命令,通过用户输入或加密参数传递。
- 限制命令执行范围,避免不必要的系统操作。
- 使用
su -c命令以最小权限原则执行,Process process = Runtime.getRuntime().exec(new String[]{"su", "-c", "ls /data"});需明确告知用户root权限的风险,并确保应用签名可信。
