在非root的安卓手机上运行本地ARM二进制文件是否可行?

22

我一直在进行低级别的Android编程(使用CodeSourcery工具链的本地C/C++),我在模拟器上试过可执行文件,它可以运行。我想在真实设备上尝试一下。于是我插入我的Nexus并将文件推送到文件系统上,然后尝试执行二进制文件,但是出现了权限错误。无论我如何挂载它或将其发送到何处,我都不是root用户,无法执行它。有没有任何办法可以让非ROOT手机运行这样的程序?


你几乎肯定需要root权限。如果你的手机没有root,你怎么把它安装到手机上的? - Falmarri
4
你把二进制文件放在哪里了?你不能把它放在SD卡上,因为它被挂载为“noexec”选项(除非已经root)。 - Luke Dunstan
没错,这就是为什么它在sdcard上无法运行的原因。我成功将其放入/data目录中(但它无法执行甚至让我chmod)。至于如何将可执行文件放到文件系统中:使用“adb push”。 - AnimatedRNG
1
在某些手机上,您可以将其复制到/data/local/tmp/,然后添加+x权限,它就会运行。不作为答案发布,因为这仅适用于少数设备。 - Mark K Cowan
1个回答

41

更新:请注意,目标API级别为29(Android 10)及以上的应用程序将无法使用下面的技巧,因为操作系统将限制执行权限。请参见行为更改:目标API 29+

在使用Android NDK中提供的工具链编译二进制文件后,您可以将它们与典型的Android应用程序打包,并将它们作为子进程生成。

您需要在应用程序的assets文件夹中包含所有必要的文件。为了运行它们,您必须让程序将它们从assets文件夹复制到可运行位置,例如:/data/data/com.yourdomain.yourapp/nativeFolder。

以下是示例代码:

private static void copyFile(String assetPath, String localPath, Context context) {
    try {
        InputStream in = context.getAssets().open(assetPath);
        FileOutputStream out = new FileOutputStream(localPath);
        int read;
        byte[] buffer = new byte[4096];
        while ((read = in.read(buffer)) > 0) {
            out.write(buffer, 0, read);
        }
        out.close();
        in.close();
    
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

请记住,assetPath 不是绝对路径,而是相对于 assets/ 的路径。

例如:“assets/nativeFolder” 只是 “nativeFolder”。

然后,要运行应用程序并读取其输出,您可以执行以下操作:

  Process nativeApp = Runtime.getRuntime().exec("/data/data/com.yourdomain.yourapp/nativeFolder/application");
                            
                        
            BufferedReader reader = new BufferedReader(new InputStreamReader(nativeApp.getInputStream()));
            int read;
            char[] buffer = new char[4096];
            StringBuffer output = new StringBuffer();
            while ((read = reader.read(buffer)) > 0) {
                output.append(buffer, 0, read);
            }
            reader.close();
            
            // Waits for the command to finish.
            nativeApp.waitFor();
            
            String nativeOutput =  output.toString();

1
很高兴能够帮忙。希望看到谷歌能够让NDK的非JNI部分更易于使用。 - sarwar
嘿,你提到了“在上面的回答上进行拓展”,但是并没有"上述回答",你能否编辑你的帖子添加"上述回答"(可能是已删除的)? - speeder
我猜作者已经删除了它,我会移除这个引用。我相信它只是建议“你应该查看NDK”。 - sarwar
5
如果你正在使用Java的File对象,请确保将新的(复制的)二进制文件标记为可执行:mBin.setExecutable(true); - jpalm
2
是的,Android有一个chmod命令,但它至少曾经是一个简单的命令,只接受八进制模式,而不是大多数桌面Unix系统上可用的文本标志。此外,Android的shell错误消息非常不具体——权限被拒绝实际上可能是任何问题。 - Chris Stratton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接