Android中使用su、cp命令复制文件到/system目录失败求助
问题分析与解决方案
首先,你的代码存在两个核心问题,导致文件复制操作失败:
1. 独立进程导致root权限无法传递
每次调用Runtime.getRuntime().exec()都会启动一个全新的进程,你执行的su只是打开了一个root权限的shell进程,但这个进程和后面的mount、cp进程完全无关——后面的命令都是以普通APP权限执行的,自然无法修改受保护的/system目录。
2. 错误的raw资源路径
你代码里写的/raw/test.ogg是不存在的路径!APP的res/raw目录下的资源是打包在APK内部的,无法通过文件系统路径直接访问,必须通过Android的资源API读取后写入临时文件,再进行复制操作。
修正后的完整代码示例
下面是修复后的代码,解决了上述两个问题:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 第一步:把raw资源写入临时文件 String tempFilePath = getCacheDir() + "/temp_test.ogg"; try (InputStream inputStream = getResources().openRawResource(R.raw.test); FileOutputStream outputStream = new FileOutputStream(tempFilePath)) { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); return; } // 第二步:用su -c执行所有需要root权限的命令(在同一个shell进程中) String[] commands = { "su", "-c", "mount -o rw,remount /system && " + "cp " + tempFilePath + " /system/test.png && " + "mount -o ro,remount /system" }; try { Process process = Runtime.getRuntime().exec(commands); // 可选:读取命令输出,用于调试错误 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); String line; while ((line = reader.readLine()) != null) { Log.d("RootCommand", line); } while ((line = errorReader.readLine()) != null) { Log.e("RootCommandError", line); } process.waitFor(); // 执行完成后删除临时文件 new File(tempFilePath).delete(); } catch (IOException | InterruptedException e) { e.printStackTrace(); } }
额外注意事项
- 设备root权限:确保你的设备已经获取完整root权限,并且APP被授予了root权限(部分root管理器会弹出授权请求,需要手动允许)。
- /system分区的可写性:Android 10及以上的部分设备,
/system分区默认是只读的,可能需要使用/system_root作为挂载点,或者需要禁用AVB验证(具体操作视设备型号而定)。 - 文件权限调整:复制到
/system后的文件可能需要调整权限,比如在命令串中添加chmod 644 /system/test.png,避免后续因权限问题无法访问该文件。
内容的提问来源于stack exchange,提问作者Sventra
相关产品推荐
相关产品推荐

