复制并执行本机服务二进制文件&检查日志

时间:2014-11-15 06:19:55

标签: java android shell android-ndk java-native-interface

我正在构建一个使用Native服务二进制文件的应用程序。

现在我的要求是:

将本机服务二进制文件放在应用程序的assets文件夹中。

  1. 当应用程序运行时,将此本机文件复制到设备中(路径如getExternalFilesDir(null)
  2. 在设备中执行此二进制文件。
  3. 检查文件是否已在日志中成功执行。
  4. 现在复制文件,我已经使用过:

    private void copyAssets() {
        AssetManager assetManager = getAssets();
        String[] files = null;
        try {
            files = assetManager.list("");
        } catch (IOException e) {
            Log.e("tag", "Failed to get asset file list.", e);
        }
        for (String filename : files) {
            if (filename.equals("native-file")) { // native-file is the file name present is assets folder
                InputStream in = null;
                OutputStream out = null;
                try {
                    in = assetManager.open(filename);
                    File outFile = new File(getExternalFilesDir(null), filename);
                    out = new FileOutputStream(outFile);
                    copyFile(in, out);
                    in.close();
                    in = null;
                    out.flush();
                    out.close();
                    out = null;
    
                } catch (IOException e) {
                    Log.e("tag", "Failed to copy asset file: " + filename, e);
                }
                break;
            }
        }
    }
    

    复制后执行文件我使用:

    File sdCard = getExternalFilesDir(null); // directory where native file is placed
    Process proc = Runtime.getRuntime().exec("sh -c shell " + sdCard.getAbsolutePath() + "/native-file "+ sdCard.getAbsolutePath() +"/native-file.log\" "); // command 1
    proc = Runtime.getRuntime().exec("sh -c less " + sdCard.getAbsolutePath() +"/native-file.log\""); // command 2
    

    的问题:

    1. 如何确保放置文件。
    2. 如何确保执行它。因为我在运行应用程序时无法找到并记录文件(native-file.log)。
    3. PS - 由于专有问题,我无法提供我的JNI文件。所以我想我们可以使用一个开源asl库。(有一个名为asl-native的本机文件)

1 个答案:

答案 0 :(得分:2)

您当前的代码并不太远,但您需要注意一些细节:

  1. 正如已经评论过的那样,您无法执行已放入/sdcard的文件。但是,您可以在内部存储器中执行文件。因此,请使用getExternalFilesDir(null)
  2. 而不是getFilesDir()
  3. 将可执行文件复制到目标目录后,需要使其可执行。您可以运行Runtime.getRuntime().exec("chmod 755 " + getFilesDir() + "/native-file").waitFor();或尝试使用私有android.os.FileUtils类(如https://stackoverflow.com/a/11408378/3115956中所述)。
  4. 你不需要任何额外的" sh -c shell"在启动您的应用时,这就足够了:Process proc = Runtime.getRuntime().exec(getFilesDir() + "/native-file");
  5. 如果要从可执行文件中读取stdout / stderr输出(以验证它是否正确运行),您可以执行以下操作:这样:

    InputStream stdout = proc.getInputStream();
    InputStream stderr = proc.getErrorStream();
    BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
    String line;
    while ((line = br.readLine()) != null)
        System.out.println("stdout: " + line);
    br = new BufferedReader(new InputStreamReader(stderr));
    while ((line = br.readLine()) != null)
        System.out.println("stderr: " + line);
    
  6. 为了简化步骤1和2,并且为了避免必须自己处理本机二进制文件的不同体系结构,您可以重命名命令行可执行文件以匹配模式lib<something>.so并将其放入{{1您项目中的目录。然后它将被APK打包程序选中,并像任何本机库一样打包。要执行它,您只需执行libs/<abi>

    即可