如何将一个可执行的文件打包到APK中,用户在下载APK后直接使用,我现在想到了两种方法:一种是将C程序直接打包到APK中,这种适合于独立执行程序或者你手上没有源码;另一种是将C程序作为库然后使用JNI来调用C程序;
解压缩即可看到APK如下目录:
|-AndroidManifest.xml
|-res
|-assets/
|-META-INF
|-class.dex
|-resource.arsc
1. 方法一
我们可以在/assets 和 /res/raw 中放置一些费标准的文件,但是需要通过输入流来访问。当用户将APK文件安装后,可以将非标准指定目录下的assets和res/raw下的可执行文件复制到到data目录下(注意:每一个APK在安装后都会在系统创建一个” /data/data/com.报名/ “ 此目录属于此APK的私有目录,然后你就可以在此目录中添加删除文件。有人说就象是linux home目录一样,的确很形象)。 下面是一个实现文件复制的代码,还有注意的地方是如果你的是可执行文件记得将此文件设置成可执行权限的。SDK API 9 以后有 File.Executable(true, true); API 8 及以下都不可使用此方法。
public static boolean copyStream(InputStream in, OutputStream out) {
Log.d(TAG, "copyStream("+ in + " ," + out+ ")");
try {
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String getAppPrivateDir(Context ctx) {
File dataDir = ctx.getDir("data", Context.MODE_PRIVATE);
return dataDir.getAbsolutePath();
}
public static boolean copyAsset(Context ctx, String assetFile,
String saveToFile) {
Log.d(TAG, "copyAssets(" + assetFile + " -> " + saveToFile);
File outputFile = new File(saveToFile);
if (outputFile.exists()) {
return true;
}
// init output stream(file)
OutputStream out;
try {
out = new FileOutputStream(outputFile);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
return false;
}
boolean copyResult = false;
InputStream in = null;
try {
in = ctx.getAssets().open(assetFile);
copyResult = copyStream(in, out);
Log.d(TAG, "copy " + assetFile + " - " + copyResult);
} catch (IOException e1) {
e1.printStackTrace();
} finally {
// close input stream(file)
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
// close output stream (file)
try {
if (out != null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
// return copy result
// add file execute permission
File fs = new File(saveToFile);
try {
fs.setExecutable(true, true);
} catch (Exception e) {
e.printStackTrace();
}
Log.d(TAG, "copyAsset() return " + copyResult);
return copyResult;
}
字符串处理优化方法
StringBuilder sb = new StringBuilder();
sb.append(getAppPrivateDir(this)).append("/server");
2. 方法二
将C程序作为库,在java层通过JNI来调用,此处不做细说。