我正在构建一个使用 native 服务二进制文件的应用程序。
现在我的要求是:
将 native 服务二进制文件放在应用程序的 Assets 文件夹中。
- 当应用程序运行时,将此 native 文件复制到设备中(路径类似于
getExternalFilesDir(null)
) - 在设备中执行这个二进制文件。
- 在日志中检查文件是否已成功执行。
现在要复制文件,我使用了:
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
问题:
- 如何确保文件已放置。
- 如何确保它被执行。因为我在运行应用程序时无法找到并记录文件 (native-file.log)。
PS - 由于专有问题,我无法提供我的 JNI 文件。所以我想我们可以使用开源 asl库。(有一个名为 asl-native 的 native 文件)
最佳答案
您当前的代码并不太远,但是您需要注意一些细节:
- 如前所述,您无法执行您放入
/sdcard
中的文件。 .但是,您可以执行内部存储器中的文件。因此,而不是getExternalFilesDir(null)
, 使用getFilesDir()
- 将可执行文件复制到目标目录后,您需要使其可执行。您可以运行
Runtime.getRuntime().exec("chmod 755 " + getFilesDir() + "/native-file").waitFor();
或尝试使用私有(private)android.os.FileUtils
类(如 https://stackoverflow.com/a/11408378/3115956 )。 - 启动应用程序时不需要任何额外的“sh -c shell”,这就足够了:
Process proc = Runtime.getRuntime().exec(getFilesDir() + "/native-file");
如果您想从可执行文件中读取 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);
为了简化第 1 步和第 2 步,并避免自己处理 native 二进制文件的不同架构,您可以重命名命令行可执行文件以匹配模式 lib<something>.so
并将其放入 libs/<abi>
项目中的目录。然后它将被 APK 打包器拾取并像任何 native 库一样打包。要执行它,您可以简单地执行 Process proc = Runtime.getRuntime().exec(getApplicationInfo().nativeLibraryDir + "/libnative-file.so");
关于java - 复制并执行 native 服务二进制文件并检查日志,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26943176/