原文連接: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();