动态引入so库
为什么要动态引入so库?
遇到的问题:因为要做一些系统级别的工具,所以要调用一些系统的so库,如果把so库直接放在lib目录下的话,在android程序启动的时候会默认加载lib目录下的所有库,但是这些so库会在一些地方存在冲突,所以为了解决这个冲突的问题,就使用动态加载so库的方式,通过一些条件的判断是否要加载这个so库。
如何动态加载so库?
1.首先把so库放在assets资源目录下,一般会放两个so库,一个32位一个64位的
2.动态加载,就是在需要使用的时候,从assets资源目录下复制到app-libs目录下
public static boolean loadLibrary(Context context, String oldFileName, String libName) throws IOException {
// 获取应用的私有模式的libs目录(真实的目录是app-libs)
File libs_dir = context.getDir("libs", Context.MODE_PRIVATE);
// 可以获取到assets资源文件的数据流
InputStream open = context.getAssets().open(oldFileName);
String new_file_name = libs_dir.getPath() + "/" + libName;
// 把资源文件的数据流写入到app-libs目录下
if (!copyLibrary(open, new_file_name)) {
return false;
}
try {
System.load(new_file_name);
} catch (Exception ex) {
ex.printStackTrace();
return false;
}
return true;
}
//从assets资源目录下复制到app-libs目录下
public static boolean copyLibrary(InputStream fileInputStream, String new_file) {
FileOutputStream fos = null;
try {
File file = new File(new_file);
fos = new FileOutputStream(file);
int dataSize;
byte[] dataBuffer = new byte[2048];
while ((dataSize = fileInputStream.read(dataBuffer)) != -1) {
fos.write(dataBuffer, 0, dataSize);
}
fos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
Log.e("NativeLibraryLoader",e.getMessage());
} finally {
try {
if (fos != null) fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
3.判断系统是多少位的然后在静态代码块里加载不同的so库
static {
//注册
try {
Context context = MainApplication.getContextObject();
String osName = "lib32.so";
//如果这个SUPPORTED_ABIS包含64就是64位的系统
if (SUPPORTED_ABIS[0].contains("64")) {
osName = "lib64.so";
}
NativeLibraryLoader.loadLibrary(context, osName, "libtv.so");
} catch (Exception e) {
e.printStackTrace();
}
}
4.存在问题
在没有关闭selinux的情况下,System.load(xxxx.so)会因为权限的原因导致失败 Permission denied;
如果权限够的话,可以直接使用暴力的方法,直接把assert目录的文件直接复制到lib目录下,然后使用System.loadLibrary(libsitatv.so)就能直接加载