首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过NDK使用c代码检查运行API级别的设备?

如何通过NDK使用c代码检查运行API级别的设备?
EN

Stack Overflow用户
提问于 2012-04-18 01:52:14
回答 3查看 6.3K关注 0票数 5

我开始使用NDK在Android上工作,我想检查一下设备在我的c代码上运行的Android API级别。我该怎么做呢?

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-09 15:47:34

我刚刚编写了一些JNI代码,希望按照Jona所描述的那样查询正在运行的OS构建版本。我想尽可能早地这样做(例如在JNI_OnLoad中),所以我不想像FUBU所描述的那样从Java上交。从API4开始,此信息就可以作为android.os.Build.VERSION中的int字段SDK_INT提供,这就是我在下面的代码片段中查找的内容:

代码语言:javascript
复制
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规范,但值得重申的好观点!)

票数 9
EN

Stack Overflow用户

发布于 2015-10-22 04:46:31

存在完全原生的解决方案:

您可以使用sys/system_properties.h

的更新版本

使用编译时工具链常量检查#if __ANDROID_API__ < 21在这两种实现之间切换。

票数 4
EN

Stack Overflow用户

发布于 2012-04-19 00:41:05

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10196361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档