Android 7.0调用第三方库出现加载失败的问题


在Android7.0 ,自己编译的APK放到系统里,调用第三方库没有问题,但是通过SD卡点击apk文件安装,就出现

 
 
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib64/libxxx.so" needed or dlopened by "/system/lib64/libnativeloader.so" is not accessible for the namespace "classloader-namespace"
经历了几天的调查,发现 http://www.jianshu.com/p/4be3d1dafbec文章写的情况跟自己遇到的十分相似
   
   
一.那为啥刚刷机时APK可以用,Install这个apk后就不能用了呢?

这个apk可是系统权限的哟,就是apk的清单AndroidManifest中有下面一句
android:sharedUserId="android.uid.system"

正常来说,这种高端apk的permitted_paths是包含system/lib64的,从源码可以知道
/frameworks/base/core/java/android/app/LoadedApk.java

        //如果是系统apk并且没有升级过
        final boolean isBundledApp = mApplicationInfo.isSystemApp()
                && !mApplicationInfo.isUpdatedSystemApp();

        String libraryPermittedPath = mDataDir;
        if (isBundledApp) {   //permitted_paths就增加system/lib64
            // This is necessary to grant bundled apps access to
            // libraries located in subdirectories of /system/lib
            libraryPermittedPath += File.pathSeparator +
                                    System.getProperty("java.library.path");
        }

看上面的注释就知道啦,如果是系统apk并且没有升级过的话,so库的搜索路径就会增加一个system/lib64。我去,google搞啥呢,为什么还要限定不能升级。
因为install -r来安装apk就相当于升级,所以刷机时apk可以用,install升级后不能用。



    
    

二.那如何解决这个鬼问题呢?

我纯粹是为了调试方便,所以参考google的链接
https://source.android.com/devices/tech/config/namespaces_libraries

应用可以调用/vendor/etc/public.libraries.txt和/system/etc/public.libraries.txt里面的所有so库,所以往这个文件写入自己希望被调用的so,这个库就变成共用的了,任意应用就可以找到这个so库了
    
    
总结: 1.Android N 不能直接调用系统的一些私有库了,公用的库都定义在public.libraries.txt里面。 2.系统应用刚刷机是能够调用system/lib64下的库,但通过install升级该应用时,应用打开会挂。因为升级后permitted_paths就不再包含system/lib64了。所以我们可以将apk要用到的库名称写到public.libraries.txt中去解决快速调试问题。
作者:九九叔 链接:http://www.jianshu.com/p/4be3d1dafbec 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 7.0 无法调用 JNI 是由于系统在该版本中进行了一些安全策略的更新,这旨在加强应用程序和系统的安全性。在该版本中,应用程序需要申请访问特定的 JNI 调用权限才能调用 JNI 接口。 要调用 JNI 接口,首先需要在 AndroidManifest.xml 文件中声明访问 JNI 的权限。您需要在 `<application>` 标签中添加以下权限声明: ```xml <uses-permission android:name="android.permission.INTERNET" /> ``` 此外,在 Java 代码中,您还需要获取权限才能调用 JNI 接口。您可以使用以下代码获取权限: ```java if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.INTERNET}, MY_PERMISSIONS_REQUEST_INTERNET); } ``` 然后,您可以在回调方法 `onRequestPermissionsResult()` 中处理权限请求的结果: ```java @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case MY_PERMISSIONS_REQUEST_INTERNET: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 当权限被授予后可以进行 JNI 调用 } else { // 当权限被拒绝,无法进行 JNI 调用 } return; } } } ``` 请注意,此处只是一个示例,实际的权限请求和处理可能需要根据您的应用程序的具体需求进行更改。 希望这些信息对您有所帮助,如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值