原文连接:http://www.lupaworld.com/home.php?mod=space&uid=345712&do=blog&id=248921php
很久没有写bolg了,前些天遇到一个很纠结的问题,就是如何将一个可执行文件打包到APK中而且运行该文件,开始想用NDK的方式将其以动态库的方式打包至APK中,但是因为条件限制没有源码只有一个可执行文件。无奈之下只好采起曲线救国的道路。好了闲话少说咱们进入主题吧shell
首先咱们要知道APK的打包原理有哪些文件时能够打包到APK中去的先将APK文件用winRAR工具打开能够看到起文件目录结果以下工具
|-assest
|-lib
|-META-INF
|-res
|-AndroidManifest.xml
|-classes.dex
|-resources.arsc
从上述能够看出 Android的apk文件中除了一些标准的资源文件,咱们还能够在/assets和/res/raw中置入一些非标准的文件,可是却只能经过输入流访问,由于这些文件在安装时并无被复制到data目录下。这个限制在Java层可能并没有大碍,可是若是想经过本地C/C++代码访问的话,彷佛就只能指定路径了。
想要将一个可执行文件打包入APK咱们能够将可执行文件当作资源文件打包至APK,接下来就是读取/assets和/res/raw下的文件,而后经过FileOutputStream openFileOutput (String name, int mode)将其写入到对应数据目录下的files目录,以后文件路径能够经过getFilesDir()+"filename"取得,编码上稍微有点繁琐。核心代码以下ui
//先检查files目录下是否存在该文件不能存在拷贝该文件到files目录下
if (!fileIsExists(executablePath))
{编码
String executableFilePath = getFilesDir().getParent()+ "/files/" + commandtext.getText().toString();spa
tryxml
{blog
InputStream input = getResources().getAssets() .open( commandtext.getText().toString());读取Assets目录下的可执行文件到输入流资源
int filesize = input.available(); //获取文件小
writeFileData(executableFilePath, input, filesize);//将文件写到executableFilePath下
} catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void writeFileData(String fileName, InputStream message, int filesize)
{get
try
{
FileOutputStream fout = new FileOutputStream(fileName);
byte[] bytes = new byte[filesize];
message.read(bytes);
fout.write(bytes);
fout.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public boolean fileIsExists(String fileName)
{
File f = new File(fileName);
if (!f.exists())
{
return false;
}
return true;
}
执行可执行文件核心代码以下
File elfFile = new File(executableFilePath);
boolean b = elfFile .setExecutable(true, true); //设置可执行权限
Runtime runtime = Runtime.getRuntime();
Process proc = null;
try
{
proc = runtime.exec(executableFilePath);
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
在API Level 9及以上版本中,可经过File类的boolean setExecutable(boolean executable, boolean ownerOnly)方法将文件从新加上可执行权限。API Level 9如下版本则需经过shell命令,而且须要root权限,具体作法以下:Process process = Runtime.getRuntime().exec("su");DataOutputStream os = new DataOutputStream(process.getOutputStream());os.writeBytes("chmod 555 " + executablePath + " \n");os.flush();os.writeBytes(executablePath + " &" + " \n");os.flush();os.writeBytes("exit \n");os.flush();