我开始使用NDK在Android上工作,我想检查一下设备在我的c代码上运行的Android API级别。我该怎么做呢?
起初,我认为我可以使用/android/api-level.h下的定义__ANDROID_API__,但这是一个错误的假设。
**注意:我不是在问如何通过java查看API级别。
发布于 2012-05-09 15:47:34
我刚刚编写了一些JNI代码,希望按照Jona所描述的那样查询正在运行的OS构建版本。我想尽可能早地这样做(例如在JNI_OnLoad中),所以我不想像FUBU所描述的那样从Java上交。从API4开始,此信息就可以作为android.os.Build.VERSION中的int字段SDK_INT提供,这就是我在下面的代码片段中查找的内容:
static const char* TAG = "testjnjni";
static bool _disableHttpKeepAliveOnBuggyPlatforms(JNIEnv *env)
{
// Based on article here:
// http://android-developers.blogspot.co.uk/2011/09/androids-http-clients.html
// Which references the issue documented here:
// http://code.google.com/p/android/issues/detail?id=2939
// We need to set "http.keepAlive" to "false" if running an OS version earlier than Froyo (API Level 8)
if ((*env)->ExceptionCheck(env))
return false; // already got an exception pending
bool success = true;
// VERSION is a nested class within android.os.Build (hence "$" rather than "/")
jclass versionClass = (*env)->FindClass(env, "android/os/Build$VERSION");
if (NULL == versionClass)
success = false;
jfieldID sdkIntFieldID = NULL;
if (success)
success = (NULL != (sdkIntFieldID = (*env)->GetStaticFieldID(env, versionClass, "SDK_INT", "I")));
jint sdkInt = 0;
if (success)
{
sdkInt = (*env)->GetStaticIntField(env, versionClass, sdkIntFieldID);
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "sdkInt = %d", sdkInt);
}
if (success && sdkInt < 8)
{
jclass systemClass = (*env)->FindClass(env, "java/lang/System");
if (NULL == systemClass)
success = false;
jmethodID setPropertyMethodID = NULL;
if (success)
success = (NULL != (setPropertyMethodID = (*env)->GetStaticMethodID(env, systemClass, "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;")));
jstring propString = NULL;
if (success)
success = (NULL != (propString = (*env)->NewStringUTF(env, "http.keepAlive")));
jstring valueString = NULL;
if (success)
success = (NULL != (valueString = (*env)->NewStringUTF(env, "false")));
jobject oldValueString = NULL;
if (success)
{
__android_log_print(ANDROID_LOG_VERBOSE, TAG, "Disabling http.keepAlive");
oldValueString = (*env)->CallStaticObjectMethod(env, systemClass, setPropertyMethodID, propString, valueString);
}
// cleanup
(*env)->DeleteLocalRef(env, propString);
(*env)->DeleteLocalRef(env, valueString);
(*env)->DeleteLocalRef(env, oldValueString);
(*env)->DeleteLocalRef(env, systemClass);
}
// cleanup
(*env)->DeleteLocalRef(env, versionClass);
return success;
}我写这段代码所需的所有信息都清楚地记录在盛亮的《Java Native Interface: Programmer's Guide and Specification》一书中,这本书以前可以从甲骨文的网站here上获得,但也可以作为一本书(例如here)购买。JNI是一种非常强大的技术,我强烈建议任何想要掌握它的开发人员阅读PDF和Android开发人员的JNI Tips。
哦,最后,理解本地和全局引用的重要性怎么强调都不为过。安卓的开发者博客有一篇很好的文章here,涵盖了ICS的变化(没有偏离JNI规范,但值得重申的好观点!)
发布于 2015-10-22 04:46:31
存在完全原生的解决方案:
您可以使用sys/system_properties.h
Android L中的__system_property_get("ro.build.version.sdk")
popen("getprop ro.build.version.sdk")的更新版本
使用编译时工具链常量检查#if __ANDROID_API__ < 21在这两种实现之间切换。
发布于 2012-04-19 00:41:05
您可以将JAVA中获得的API级别一次性传递给C代码,并将其存储在全局变量中。对我来说,这是更简单的方法。
https://stackoverflow.com/questions/10196361
复制相似问题