2012-04-17 23 views
3

我开始使用NDK与Android一起工作,我想检查设备在我的c代码上运行的Android API级别。我怎样才能做到这一点?如何使用c代码通过NDK检查运行API级别的设备?

起初我以为我可以使用/android/api-level.h下的定义__ANDROID_API__,但这是一个错误的假设。

**注意:我不问如何通过java检查API级别。

+1

您的代码是通过JNI接口运行还是直接在底层os层上作为可执行文件运行? – Samveen 2012-04-27 10:47:27

+0

通过JNI接口。 – Jona 2012-04-28 03:37:42

+0

然后FABUs的答案会完美解决。你只需要在c代码中定义一个函数,让'setVersion'将版本存储到一个静态变量中,其余的C代码就可以访问这个变量。 setVersion函数可以作为初始化的一部分被调用。有关在Java中获取Android API版本的信息,请参阅http://stackoverflow.com/questions/3423754/retrieving-android-api-version-programmatically。 – Samveen 2012-04-28 06:54:15

回答

6

我刚刚工作的一些JNI代码,并希望通过乔纳描述查询运行OS Build版本。我想尽早做到这一点(例如,在JNI_OnLoad),所以不要把它交给Java,如FUBUs所述。由于API级别4此信息已可与int场SDK_INTandroid.os.Build.VERSION这就是我在这个片段中查找:

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; 
} 

所有我需要写这个代码是在明确记载的信息由Sheng Liang提供的标题为“Java本地接口:程序员指南和规范”的PDF,以前可从Oracle的站点here获得,但也可作为书籍(例如here)购买。 JNI是一项非常强大的技术,我强烈建议任何希望掌握它的开发人员阅读PDF以及Android Developers的JNI Tips

哦,最后,不能强调它是多么重要的是了解本地和全球的参考。 Android的开发人员博客有一篇很好的文章here,涵盖了ICS的变化(没有偏离JNI规范,但重申的重点!)。

+0

这是一个通过JNI获取实际Build类的值的好方法。谢谢! – Jona 2012-05-17 16:34:58

+0

为我工作得很好! – Halsafar 2013-10-01 17:14:31

1

您可以将JAVA中获得的API级别一次性传递给C代码并将其存储在全局变量中。对我而言,更简单的方法就是做到这一点。

相关问题