本机库只能使用公共 API,且不得链接到非 NDK 平台库。此规则从 API 24 开始实施,此后应用便无法再加载非 NDK 平台库。此规则由动态链接器执行,因此无论代码使用何种方式加载,都无法访问非公共库:System.loadLibrary(...)、DT_NEEDED 条目以及直接调用 dlopen(...) 都会同样失败。
对于各项更新,用户获得的应用体验应该是一致的,而开发者应不必进行紧急更新应用以应对平台变更。因此,我们建议不要使用私有 C/C++ 符号。所有 Android 设备都必须通过的兼容性测试套件 (CTS) 并不包含对私有符号进行测试。此类符号可能不存在,也可能会采用不同的行为方式。这可能导致使用私有符号的应用在某些设备上,或在未来发布的新版本系统中无法使用。当 Android 6.0 Marshmallow 从 OpenSSL 切换到 BoringSSL 后,很多开发者都发现了这种问题。
为了减少这种过渡对用户的影响,我们确定了 Google Play 上安装量最大的应用中颇为常用且我们短期内仍可提供支持的一些库(包括 libandroid_runtime.so、libcutils.so、libcrypto.so 和 libssl.so)。为了给您留出更多时间进行过渡,我们会暂时支持这些库;因此,如果看到表示您的代码在将来发布的版本中会无效的警告信息,请立即予以更正!
$ readelf --dynamic libBroken.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libnativehelper.so]
0x00000001 (NEEDED) Shared library: [libutils.so]
0x00000001 (NEEDED) Shared library: [libstagefright_foundation.so]
0x00000001 (NEEDED) Shared library: [libmedia_jni.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libz.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
潜在问题:
从 API 24 开始,动态链接器将无法加载私有库,从而导致应用无法加载。
解决方案:
重写本机代码,使其仅依赖公共 API。短期解决方案是:将没有复杂依存关系的平台库 (libcutils.so) 复制到项目;长期解决方案是将相关代码复制到项目树。SSL/Media/JNI internal/binder API 不得通过本机代码访问。必要时,本机代码应调用适当的公共 Java API 方法。
NDK 的 platforms/android-API/usr/lib 下列出了所有的公共库。
注意:SSL/crypto 是一种特殊情况,应用不得直接使用平台 libcrypto 和 libssl 库,即使在较早版本的平台上也不可以。所有应用都应使用 GMS 安全提供程序,以确保应用免遭已知漏洞攻击。