Android 11 JNI禁用fdsan时未声明函数编译问题如何解决
Android fdsan接口调用适配方案
编译错误修复
android_fdsan_set_error_level是Android 10(API 29)新增的系统接口,编译未找到标识符的问题可以通过两种方式解决:
方案1:修改编译配置(适合拆分独立库的场景)
在独立库的Android.mk中添加如下配置,指定编译时使用API 29及以上的NDK版本:
# 指定编译使用的SDK版本 LOCAL_SDK_VERSION := 29 # 指定NDK编译的API等级 LOCAL_NDK_API_LEVEL := 29 # 可选:限制该库仅支持Android 10及以上系统,避免低版本设备加载 LOCAL_MIN_SDK_VERSION := 29
配置完成后重新编译,即可正常识别fdsan相关接口。
方案2:添加函数弱声明(无需拆分库,兼容性更好)
不需要调整全局编译配置,直接在用到该接口的cpp文件头部添加弱引用声明即可,编译时不会报错,运行时会自动判断函数是否存在:
#include <android/api-level.h> // 弱引用声明,低版本系统无该函数时指针为NULL extern "C" void android_fdsan_set_error_level(uint32_t level) __attribute__((weak)); // 定义fdsan错误等级常量,和系统定义保持一致 #define ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE 2
运行时调用逻辑
非拆分库场景
直接在应用初始化的native逻辑中添加如下判断:
if (android_get_device_api_level() >= 30) { if (android_fdsan_set_error_level != nullptr) { android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE); } }
拆分独立库场景
- Java层加载so前先判断系统版本,仅Android 10及以上加载该独立库:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { System.loadLibrary("你的独立so库名称"); // 仅Android 11及以上调用禁用fdsan的接口 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { FdsanUtil.disableFdsan(); } }
- 独立库的native代码直接实现disableFdsan接口即可,无需额外判断函数存在性:
#include <android/fdsan.h> #include <android/api-level.h> extern "C" JNIEXPORT void JNICALL Java_xxx_FdsanUtil_disableFdsan(JNIEnv *env, jclass clazz) { if(android_get_device_api_level()>=30) { android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_WARN_ONCE); } }
内容的提问来源于stack exchange,提问作者Filipe Madureira
相关产品推荐
相关产品推荐

