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
,而是需要通过 dlopen
和 dlsym
加载函数,以确保二进制文件可加载到旧版本版本。 (或者,您可以构建单独的共享库,其中一个共享库可以在所有平台上加载,而另一个共享库只能在较新的平台上加载。)
一些 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
.
进行构建
我正在开发一个大量使用 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
,而是需要通过dlopen
和dlsym
加载函数,以确保二进制文件可加载到旧版本版本。 (或者,您可以构建单独的共享库,其中一个共享库可以在所有平台上加载,而另一个共享库只能在较新的平台上加载。)一些 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
.