在Android5.0系统上加载位于SD卡上的本地动态库
最近在加载位于Android设备SDCARD上的本地动态库时遇到权限问题,估计是5.0系统权限管理限制更多,而SDCARD上文件基本上没有可执行权限,而一般非root用户无法通过chmod为其添加.
加载代码(APP启动时):
System.load("/mnt/sdcard/libfeatureA.so");
异常闪退:
dlopen("/mnt/sdcard/libfeatureA.so", RTLD_LAZY) failed: dlopen failed: couldn't map "/mnt/sdcard/libfeatureA.so" segment 2: Operation not permitted
加载位于SD卡的so权限不够,那么将so复制到APP内部数据空间再加载呢,经测试是可行的.
加载代码(APP启动时):
NativeLibraryLoader.loadLibrary(this, "/mnt/sdcard", "libfeatureA.so"); NativeLibraryLoader.loadLibrary(this, "/mnt/sdcard", "libfeatureB.so");
库加载类NativeLibraryLoader实现
/** * Created by linnvv_0011@163.com on 2015/10/10. */ public class NativeLibraryLoader { public static boolean loadLibrary(Context context, String libPath, String libName) { File libs_dir = context.getDir("libs", Context.MODE_PRIVATE); String new_file_name = libs_dir.getPath() + "/" + libName; String old_file_name = libPath + "/" + libName; if (!copyLibrary(new_file_name, old_file_name)) { return false; } try { System.load(new_file_name); } catch (Exception ex) { ex.printStackTrace(); return false; } return true; } private static boolean copyLibrary(String new_file_name, String old_file_name) { FileInputStream fis = null; FileOutputStream fos = null; try { File new_file = new File(new_file_name); File old_file = new File(old_file_name); /* delete old library if exists. */ if (new_file.exists()) new_file.delete(); fis = new FileInputStream(old_file); fos = new FileOutputStream(new_file); int dataSize; byte[] dataBuffer = new byte[2048]; while ((dataSize = fis.read(dataBuffer)) != -1) { fos.write(dataBuffer, 0, dataSize); } fos.flush(); return true; } catch (Exception e) { e.printStackTrace(); } finally { try { if (fos != null) fos.close(); } catch (Exception e) { e.printStackTrace(); } try { if (fis != null) fis.close(); } catch (Exception e) { e.printStackTrace(); } } return false; } }