Android NDK 和更新版本 API 支持

Android NDK and Newer API Support

我正在开发一个大量使用 NDK 的 Android 应用程序。在 Java 方面,我们以 SDK 19 为目标,最小 SDK 为 16。有没有办法在 NDK 方面做类似的事情?

现在我们的 Application.mk 文件有 APP_PLATFORM := android-16。有没有办法以平台 19 为目标,但在 NDK 端仍然兼容回到 16?

看看https://developer.android.com/ndk/guides/stable_apis.html

例如,如果您不使用 OpenGL ES 3.0 和 OpenGL ES 3.1 APIs 并且不使用 link libGLESv3,那么您的应用具有 API 级别的兼容性14.

这是可行的,但并不容易。

对于 java 代码,如您所知,您可以设置任何更高的目标 SDK 版本并使用此类功能,只要您确保这些代码路径仅在较新的设备上执行 - 简单。

对于本机代码,原则上您可以将 APP_PLATFORM 设置为高于基线的值,并尝试这样做,但您需要注意一些细节:

  • 您不能无条件地link使用较新平台的功能,您需要动态加载它们。也就是说,不是直接调用函数并将库添加到 LOCAL_LDLIBS,而是需要通过 dlopendlsym 加载函数,以确保二进制文件可加载到旧版本版本。 (或者,您可以构建单独的共享库,其中一个共享库可以在所有平台上加载,而另一个共享库只能在较新的平台上加载。)

  • 一些 bionic libc 函数发生了变化(主要在 android-21 中,但在此之前也有一些小的变化)- 之前确实存在但更改了符号名称的函数。已更改的更常见函数之一是 rand - 在 android-21 之前,rand 是一个实际调用 lrand48() 的内联函数,因此您的二进制文件最终取决于 lrand48 存在于较旧的 android 版本的 libc.so 中,而它们那里没有任何 rand。在 android-21 中,添加了很多这样的函数,并删除了内联函数,因此如果您使用 APP_PLATFORM := android-21 构建,您的二进制文件将最终取决于函数 rand 而不是以前不存在。有关详细信息,请参阅 https://whosebug.com/a/27093163/3115956 and https://whosebug.com/a/27338365/3115956

  • 请记住,您不需要将APP_PLATFORM设置为与java端的目标SDK相同,您只(可能)需要设置如果您想在较新的固件版本上有选择地使用较新的功能。

由于第二个问题,您可能根本不想设置更高的 APP_PLATFORM。如果您使用 dlopen(因此您实际上不需要 .so 文件来 link),您可以通过从较新的平台复制那些新的 headers 来轻松管理将版本添加到您自己的项目中,并使用较旧的 APP_PLATFORM.

进行构建