我正在开发一个依赖于ELF二进制文件的Android应用程序:我们的Java代码与这个二进制文件交互以完成任务.需要在Application启动和应用程序退出/按需启动和终止此运行时.
问题:
我假设我们将能够使用Runtime.exec()API执行此二进制文件.对于我需要将库放在文件夹结构中的位置有什么限制吗?系统运行时如何找到此可执行文件?是否有某种类路径设置?
由于应用程序依赖于此运行时,因此我考虑将其包装在服务中,以便可以根据需要启动或停止它.在Android项目中处理此类可执行文件的最佳方法是什么?
假设我没有此可执行文件的源代码,还有什么其他选择?
请指教.
谢谢.
Ale*_*dam 42
1)不,除了那些访问系统文件因此需要root权限之外,应该没有约束.最好的地方是直接/ data/data/[your_package_name]以避免在其他地方造成污染.
2)有关编译本机库的详细讨论可以在这里找到:http://www.aton.com/android-native-libraries-for-java-applications/.另一种选择是arm的交叉编译器(这里是用于编译内核的,它是免费的:http://www.codesourcery.com/sgpp/lite/arm).如果您计划维护一个执行您的cammand的服务,请注意可以随时停止并重新启动服务.
3)现在,如果您没有源代码,我希望您的文件至少被编译为arm可执行文件.如果没有,我看不出你怎么能运行它.
您将通过在java类中运行以下命令来执行该文件:
String myExec = "/data/data/APPNAME/FILENAME";
Process process = Runtime.getRuntime().exec(myExec);
DataOutputStream os = new DataOutputStream(process.getOutputStream());
DataInputStream osRes = new DataInputStream(process.getInputStream());
Run Code Online (Sandbox Code Playgroud)
我对你的可执行文件一无所知,所以你可能需要或者不需要实际获取inputStream和outputStream.
我假设运行adb来推送二进制文件是不可能的,所以我正在寻找一种巧妙的方法来打包它.我发现了一篇关于在您的应用中包含可执行文件的精彩帖子 在这里查看:http: //gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
重要的是这一个(强调我的):
来自Android Java app,使用
assets文件夹
- 在资源文件夹中包含二进制文件.
- 使用
getAssets().open(FILENAME)获得的InputStream.- 将其写入
/data/data/APPNAME(例如/data/data/net.gimite.nativeexe),您的应用程序可以在其中写入文件并使其可执行./system/bin/chmod 744 /data/data/APPNAME/FILENAME使用上面的代码运行.- 使用上面的代码运行您的可执行文件
帖子使用assets文件raw夹,安装了android为静态文件建议的文件夹:
提示:如果要在编译时在应用程序中保存静态文件,请将该文件保存在项目res/raw /目录中.你可以用openRawResource()打开它,传递R.raw.资源ID.此方法返回一个可用于读取文件的InputStream(但您无法写入原始文件).
要访问数据文件夹,您可以按照此处的说明操作:http:
//developer.android.com/guide/topics/data/data-storage.html#filesInternal
此外,还有一个File#setExecutable(boolean);方法可以使用而不是shell命令.
所以,把所有东西放在一起,我会尝试:
InputStream ins = context.getResources().openRawResource (R.raw.FILENAME)
byte[] buffer = new byte[ins.available()];
ins.read(buffer);
ins.close();
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(buffer);
fos.close();
File file = getFileStreamPath (FILENAME);
file.setExecutable(true);
Run Code Online (Sandbox Code Playgroud)
当然,所有这些只能在安装后完成一次.您可以快速检查内部onCreate()或检查文件是否存在,并执行所有这些命令(如果文件不存在).
如果有效,请告诉我.祝好运!
mat*_*411 10
以下是有关如何打包和运行可执行文件的完整指南.我的基础是我在这里找到的和其他链接,以及我自己的试验和错误.
1.)在SDK项目中,将可执行文件放在/ assets文件夹中
2.)以编程方式获取该文件目录的字符串(/ data/data/your_app_name/files)
String appFileDirectory = getFilesDir().getPath();
String executableFilePath = appFileDirectory + "/executable_file";
Run Code Online (Sandbox Code Playgroud)
3.)在您的应用程序项目中的Java代码:使用以下函数将/ assets文件夹中的可执行文件复制到应用程序的"files"子文件夹(通常是/ data/data/your_app_name/files)中:
private void copyAssets(String filename) {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
Log.d(TAG, "Attempting to copy this file: " + filename); // + " to: " + assetCopyDestination);
try {
in = assetManager.open(filename);
Log.d(TAG, "outDir: " + appFileDirectory);
File outFile = new File(appFileDirectory, 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);
}
Log.d(TAG, "Copy success: " + filename);
}
Run Code Online (Sandbox Code Playgroud)
4.)更改executable_file上的文件权限以实际使其可执行.用Java调用来做:
File execFile = new File(executableFilePath);
execFile.setExecutable(true);
Run Code Online (Sandbox Code Playgroud)
5.)执行如下文件:
Process process = Runtime.getRuntime().exec(executableFilePath);
Run Code Online (Sandbox Code Playgroud)
请注意,此处引用的任何文件(例如输入和输出文件)都必须构造其完整路径字符串.这是因为这是一个单独的衍生过程,它没有"pwd"的概念.
如果你想读取命令的stdout,你可以这样做,但到目前为止,它只对我有用的系统命令(如"ls"),而不是可执行文件:
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.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();
process.waitFor();
Run Code Online (Sandbox Code Playgroud)
Log.d(TAG,"output:"+ output.toString());
对于从 Android 10 开始执行二进制文件,只能从只读文件夹中执行。这意味着您应该将二进制文件与您的应用程序一起打包。安卓文档
android:extractNativeLibs="true"AndroidManifest;src/main/resources/lib/*目录中,其中*– 代表 CPU 的架构,例如armeabi-v7a;使用这样的代码来执行:
private fun exec(command: String, params: String): String {
try {
val process = ProcessBuilder()
.directory(File(filesDir.parentFile!!, "lib"))
.command(command, params)
.redirectErrorStream(true)
.start()
val reader = BufferedReader(
InputStreamReader(process.inputStream)
)
val text = reader.readText()
reader.close()
process.waitFor()
return text
} catch (e: Exception) {
return e.message ?: "IOException"
}
}
Run Code Online (Sandbox Code Playgroud)这是与 android 团队在reddit上的回答的讨论。
| 归档时间: |
|
| 查看次数: |
18927 次 |
| 最近记录: |