(原创:http://www.cnblogs.com/linguanh)

目录:

  前序

  一,问题描述

  二,为何会如此"无情"?

  三,目前存在该问题的知名SDK

  四,解决方案,1 对 N

前序:

  嫌无聊的请跳过。上次发博文是同年8月,时光荏苒,空闲时间少,现在都接近年关了,其实这4个月学了很多,接触了IM(非第三方),学习了 golang 并采用它成功完成仿朋友圈页面的服务端api,等等..等等..,由于这个问题的确是业界超级"毒瘤",趁午休时间,尽我程序员的"干货"思维,少废话,尽通俗。

    码字发文。

一,问题描述

  先简单阐述下几个概念,这些不是重点。

  1,Android 编译时候的 api 版本,指的是你要生成的这个 apk 所依赖的 sdk 版本,例如 api 23 即是 Android 6.0 ;

  2,.so 动态链接库,为 Linux 下的库文件,Windows 是 .dll,Android 是基于 Linux 内核的,所以使用的是 .so,在安卓上面,一般由 C/C++ 语言进行 Jni 编程后,采用 NDK 工具编译后所生成的,可以参考下我之前的一篇教程博文:http://www.cnblogs.com/linguanh/p/4624768.html

  3,.so的作用,主要是提供系统底层函数,供应用层使用。不用它行不?可以,在Android已经提供了的情况下,你不需要再自己添加,例如一个 View 的绘制,里面都有很多 Native 关键词的函数,这个就是底层函数,Android api 对应的是它已经提供了。那么如果,你老板要去实现,语音,图像,视频处理等系统没有的功能,你就只能自己写 .so 来供调用了。

  问题来了:

    发生的环境:此类问题一般发生在 Android 6.0 及其以上的系统,具体也存在于其他的 api 版本,主要集中在 api >=23;

    具体表现是:同一个 APP 在 api <=22 的 sdk 情况下编译,可以运行正常,不存在闪退或者 .so 库加载失败的情况,当你采用 api >=23 的sdk 编译的时候,安装到 Android 6.0 及其以上的手机的时候,大范围出现崩溃 或者 .so 库加载失败,而在 6.0 以下的手机却正常;

    Catch的信息:dlopen failed: cannot locate symbol "XXXX" xxxx.so, XX 是泛配,此类崩溃信息,你完全可以对号入我"座"。

二,为何如此无情?

   如果只为解决问题,可以不看这部分。

  现在我用一句话说白它,就是:不同链接方式时,dlopen会打开指定的系统中(手机中)或提供的动态库,并使用 dlsym 获取符号地址,也就是说,如果,在此时的手机中如果找不到,那么就会出问题,一般和 API 有关系。

  人为因素就是,编译这个 .so 库的人,他在编译的时候没考虑到下面这些情况,导致提供给别人用的时候,或者自己用的时候在高 API 版本手机出现问题。

  感兴趣的就接着看下面详解吧!上面问题描述的第二点提到 .so 是运行在 Linux 环境下的,而且在 Android 里面一般由 NDK 编译,编译的时候,我们可以指明一种文件叫做 Application.mk,里面有一行 APP_STL := XXX 指明库的链接方式,默认是静态,STL的取值:

    1)system,默认的值,最危险方式,直接和手机系统版本挂钩,采用手机最小版本的.so库链接

    2)gabi++_static

    3)gabi++_shared

    4)stlport_static

    5)stlport_shared

    6)gnustl_static

    7)gnustl_shared

  如果不特别定义的话,“system”运行时库是默认的值。除此之外,凡是后面带“_static”的,表示其是一个静态链接的运行时库(运行时库的代码包含在编译后的程序中);而凡是后面带“_shared”的,表示其是一个动态链接的运行时库(运行时库在程序运行时被动态加载进来)。如果去除动态或静态链接的因素,则除了默认的“system”运行时库之外,还有所谓的“gabi++”运行时库、“stlport”运行时库和“gunstl”运行时库。如果想支持C++异常的话,必须要使用gunstl运行时库。

  主要是两种,静态链接,动态链接:

    动态链接,是指在生成可执行文件时不将所有程序用到的函数链接到一个文件,因为有许多函数在操作系统带的dll文件中,当程序运行时直接从操作系统中找。

    静态链接,是把所有用到的函数全部链接到 .so 文件中;

  重点来了,上面说到了,静态链接是会把所需要的都搞到exe中,其实不然,这个说法是早期的了,对于现在的 Android 发展来说,为了使程序方便扩展,具备通用性,已经采用插件形式来链接动态库,编译时的静态和动态链接仅仅是程度问题。插件加载形式有:

    1)dlopen

    2)dlsym

    3)dlclose

  dlopen打开指定的系统中(手机中)动态库。并使用 dlsym 获取符号地址,也就是说,如果,在此时的手机中如果找不到,那么就会出问题,一般和 API 有关系。

三,目前存在该问题的知名SDK

  根据我所了解到的,存在这类问题的 SDK 有,百度地图、环信、高德地图、语音库 speex, 不知道修复没有,这些 SDK 一但在你的 APK 编译版中中设置 API >=23 就会出现各种问题,闪退或者抛出异常。

  

四,解决方案,1 对 N

  主要有两种:

    1- 委曲求全,指标不治本,把你的 APK target API 先降低到 23以下,若不行再把 编译时 API 降低到 23 以下,还出问题就继续降低,这意味着,你很多 Android Sdk 的新控件用不了;

    2- 在 Application.mk 中修改 APP_STL,重新编译 .so ,如果,我说如果你没有源码,那么悲剧了,要么等他们解决,要么采用第一种,建议尝试,APP_STL := gnustl_shared,

  这种方式,对于所需要的外部动态链接函数、符号,在 NDK 13b 中都会独立生成一份,全部引用就解决此类问题,例如

 private void load() {
try {
System.loadLibrary("gnustl_shared"); // 也可以不写这一句,但是要保证 gnustl_shared.so 放置在 libs 里面
System.loadLibrary("speex");
} catch (Throwable e) {
Log.d("zzzzz","加载语音库异常 :"+e.toString());
}
}

    3- 如果需要 libgnustl_shared.so 的,留邮箱,我发一份你。

  至此,基本讲完了,下期 开源二次开发的IM 服务端系统。

Android 5.0 到 Android 6.0 + 的深坑之一 之 .so 动态库的适配的更多相关文章

  1. android MultiDex multidex原理原理下遇见的N个深坑(二)

    android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multi ...

  2. Android数据存储之Android 6.0运行时权限下文件存储的思考

    前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...

  3. Android权限管理之Android 6.0运行时权限及解决办法

    前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...

  4. [Android]Android端ORM框架——RapidORM(v2.0)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5626716.html [Android]Android端ORM ...

  5. Android requires compiler compliance level 5.0 or 6.0. Found '1.4' instead的解决办法

    今天在导入工程进Eclipse的时候竟然出错了,控制台输出的是: [2013-02-04 22:17:13 - takepicture] Android requires compiler compl ...

  6. [Android]Android端ORM框架——RapidORM(v1.0)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4748077.html  Android上主流的ORM框架有很多 ...

  7. Could not find com.android.tools.build:gradle:1.3.0.

    * What went wrong:          A problem occurred configuring project ':TZYJ_Android'.> Could not re ...

  8. Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead. Please use Android Tools>Fix project Properties.

    重装操作系统之后,或者破坏了Android的开发环境之后,需要重新配置好Android的开发环境.但是配置好后,导入原有的项目时,报错: Android requires compiler compl ...

  9. Qt5.3.0 for Android开发环境配置

    1.去官网下载Qt5.3.0 for Android 2.去http://developer.android.com下载Ndk 和SDk            3.去http://ant.apache ...

随机推荐

  1. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率

    之前一篇里写过字符串常用类的三种方式<java中的字符串相关知识整理>,只不过这个只是分析并不知道他们之间会有多大的区别,或者所谓的StringBuffer能提升多少拼接效率呢?为此写个简 ...

  2. Linux虚拟机的安装(使用Centos6.3)

    1.什么是虚拟机? 虚拟机指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统 2.安装Linux虚拟机前要做的准备 2.1:一台windows环境的pc 2.2:下载VM ...

  3. 探索ASP.NET MVC5系列之~~~6.Session篇(进程外Session)

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  4. 移动硬盘不能识别的常见7种解决方案 ~ By 逆天经验

    服务器汇总:http://www.cnblogs.com/dunitian/p/4822808.html#iis 服务器异常: http://www.cnblogs.com/dunitian/p/45 ...

  5. Android权限管理之RxPermission解决Android 6.0 适配问题

    前言: 上篇重点学习了Android 6.0的运行时权限,今天还是围绕着Android 6.0权限适配来总结学习,这里主要介绍一下我们公司解决Android 6.0权限适配的方案:RxJava+RxP ...

  6. 【原创分享·微信支付】 C# MVC 微信支付教程系列之扫码支付

    微信支付教程系列之扫码支付                  今天,我们来一起探讨一下这个微信扫码支付.何为扫码支付呢?这里面,扫的码就是二维码了,就是我们经常扫一扫的那种二维码图片,例如,我们自己添 ...

  7. iOS开发之再探多线程编程:Grand Central Dispatch详解

    Swift3.0相关代码已在github上更新.之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread.操作队列以及GCD,介绍的不够深入.今天就以GCD为主题来全面的总结一下GCD ...

  8. SQL Server2016升级前几点自检

    SQL Server2016已经出来一段时间了,而且最新的SP1包也于2016年11月18日正式发布,各种新的特性推出让我们跃跃欲试.那么对于我们真实的业务环境,特别是生产环境要不要"跟风& ...

  9. vue入门学习(基础篇)

    vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...

  10. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...