2012-04-17 47 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代碼並將其存儲在全局變量中。對我而言,更簡單的方法就是做到這一點。

相關問題