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

Android中如何通过Process p = Runtime.getRuntime().exec("su")运行Java或C代码?

解决通过su进程运行自定义Java/C代码的问题

我明白你的痛点——用su启动了root进程,但只能敲终端命令,没法直接跑自己的业务代码,这确实有点受限。其实核心问题是:su启动的是一个独立的shell进程,它和你的App主进程完全隔离,没有加载App的Dalvik/ART虚拟机环境,所以没法直接执行你的Java代码;但咱们有几个可行的方案绕开这个限制:

方案一:把需要root权限的逻辑做成独立C/C++可执行文件

这是最常用也最稳定的方式,因为su进程可以直接执行系统级的二进制可执行文件:

  1. 编写并编译C/C++代码
    用NDK编写需要root权限的逻辑(比如修改系统文件、操作/dev设备等),然后在构建脚本里配置生成可执行文件(不是普通的.so库)。比如在CMakeLists.txt里这样配置:

    add_executable(root_task
        src/main/cpp/root_task.cpp
    )
    target_link_libraries(root_task
        log
        android
    )
    
  2. 部署可执行文件
    把编译好的root_task放到App的assets目录,在App启动时复制到私有目录(比如/data/data/com.your.package/files/),然后给它添加可执行权限:

    // 复制文件到私有目录
    InputStream is = getAssets().open("root_task");
    File outputFile = new File(getFilesDir(), "root_task");
    FileOutputStream os = new FileOutputStream(outputFile);
    byte[] buffer = new byte[1024];
    int length;
    while ((length = is.read(buffer)) != -1) {
        os.write(buffer, 0, length);
    }
    is.close();
    os.close();
    
    // 添加可执行权限
    outputFile.setExecutable(true);
    
  3. 通过su调用
    现在就可以用su启动这个可执行文件了,还能通过标准输入输出传递参数或获取结果:

    Process process = Runtime.getRuntime().exec(new String[]{
        "su", "-c", outputFile.getAbsolutePath() + " 参数1 参数2"
    });
    // 读取输出
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while ((line = reader.readLine()) != null) {
        // 处理输出内容
    }
    process.waitFor();
    

方案二:用app_process运行Java代码

如果你更倾向于用Java实现root逻辑,可以借助Android系统的app_process工具——它是系统用来启动应用进程的入口,可以加载指定的Java类并执行main方法:

  1. 编写独立Java类
    写一个不含App上下文依赖的Java类,比如:

    public class RootJavaTask {
        public static void main(String[] args) {
            // 这里写需要root权限的逻辑,比如修改系统文件
            try {
                Process process = Runtime.getRuntime().exec("chmod 777 /system/etc/hosts");
                process.waitFor();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
  2. 通过su调用app_process
    su启动app_process并指定要执行的类,注意要传入类的完整包名:

    Process process = Runtime.getRuntime().exec(new String[]{
        "su", "-c", "app_process /system/bin com.your.package.RootJavaTask"
    });
    // 处理输入输出和进程状态
    

    👉 注意:这个类不能依赖App的资源或上下文,因为它运行在独立的进程里,没有加载你的App APK环境,所有操作都要用绝对路径。

方案三:通过Shell脚本间接调用

如果你的逻辑比较复杂,比如需要先做一些环境准备、权限检查,可以写一个Shell脚本,把调用可执行文件或app_process的逻辑放到脚本里,然后通过su执行脚本:

  1. 编写脚本(比如root_script.sh

    #!/system/bin/sh
    # 检查是否有root权限
    if [ $(id -u) -ne 0 ]; then
        echo "Not root"
        exit 1
    fi
    # 调用你的可执行文件
    /data/data/com.your.package/files/root_task
    
  2. 部署并执行脚本
    和可执行文件一样,把脚本复制到私有目录,添加可执行权限,然后用su执行:

    File scriptFile = new File(getFilesDir(), "root_script.sh");
    // 复制脚本并加权限...
    Process process = Runtime.getRuntime().exec(new String[]{
        "su", "-c", scriptFile.getAbsolutePath()
    });
    

关键注意事项

  • 权限验证:每次调用su后,最好检查进程的退出码(process.exitValue()),确认是否获取到了root权限;
  • 用户授权:如果用的是SuperSU或Magisk,第一次调用su会弹出授权弹窗,要避免进程阻塞,最好处理好输入流;
  • 兼容性:不同Android版本的app_process路径或参数可能有差异,多测试几个版本;
  • 安全性:root权限风险极高,不要把可执行文件或脚本暴露给其他App,也不要执行未验证的外部命令。

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

火山引擎 最新活动