Как проверить работу устройства на уровне API с помощью кода c через NDK?

Я начинаю работать на Android с NDK, и я хочу проверить, какой уровень API для Android работает на моем c-коде. Как я могу это сделать?

Сначала я думал, что могу использовать определение __ANDROID_API__ под /android/api-level.h, но это было неправильное предположение.

** Примечание. Я НЕ спрашиваю, как проверить уровень API через java.

Я только что работал над некоторым кодом JNI и хотел запросить версию операционной версии OS, как описано Jona . Я хотел сделать это как можно раньше (например, в JNI_OnLoad ), поэтому предпочел бы не передавать его с Java, как описано FUBU . Начиная с API уровня 4 эта информация была доступна как int field SDK_INT в android.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; } 

Вся информация, которая мне нужна для написания этого кода, четко задокументирована в PDF-документе, озаглавленном «Интерфейс Java Native: руководство и спецификация программиста» Шэн Лян, который раньше был доступен на сайте Oracle, но также можно приобрести в виде книги (например, здесь ). JNI – очень мощная технология, и я настоятельно рекомендую, чтобы любой разработчик, желающий получить доступ к нему, читал этот PDF-файл, а также советы разработчиков JNI для разработчиков Android.

О, и, наконец, нельзя подчеркнуть, насколько важно понимать местные и глобальные ссылки. В блоге разработчиков Android есть хорошая статья, в которой описываются изменения в ICS (ничто не отклоняется от спецификации JNI, но имеет смысл повторить!).

Существуют полностью собственные решения:

  1. Перед Android L вы можете использовать __system_property_get("ro.build.version.sdk") из sys/system_properties.h
  2. Для Android L и новее вы можете использовать popen("getprop ro.build.version.sdk")

Используйте константу постоянной #if __ANDROID_API__ < 21 инструмента компиляции #if __ANDROID_API__ < 21 для переключения между этими двумя реализациями.

Вы можете передать один раз, уровень API, который вы получаете в JAVA, в код C и запасите его в глобальной переменной. Для меня это более простой способ сделать это.