How to get the Android context instance when calling JNI method?

☆樱花仙子☆ 提交于 2021-02-16 08:41:25

问题


I have already read some relevant answers on stackoverflow,but seems no one has answered my question.I will get the android ID from native code,i.e. calling the method getAndroidIDfromNativeCode in C code,(so the JVM is inited in the native code by method create_vm),you know that when calling the method getContentResolver,you must use a Android Context instance to call it,so how to get this Context instance?

    static jstring
    native_code_getAndroidID(JNIEnv *env, jobject thiz)
    {
        jclass c_settings_secure = (*env)->FindClass(env, "android/provider/Settings$Secure");
        jclass c_context = (*env)->FindClass(env,"android/content/Context");
        if(c_settings_secure == NULL || c_context == NULL){
            return NULL;
        }
        //Get the getContentResolver method
        jmethodID m_get_content_resolver = (*env)->GetMethodID(env, c_context, "getContentResolver",
                                                               "()Landroid/content/ContentResolver;");
        if(m_get_content_resolver == NULL){
            return NULL;
        }
        //Get the Settings.Secure.ANDROID_ID constant
        jfieldID f_android_id = (*env)->GetStaticFieldID(env, c_settings_secure, "ANDROID_ID", "Ljava/lang/String;");

        if(f_android_id == NULL){
            return NULL;
        }
        jstring s_android_id = (*env)->GetStaticObjectField(env, c_settings_secure, f_android_id);

        //create a ContentResolver instance context.getContentResolver()
        /*
          where can I get the context instance from Anroid APP??
        */
        jobject o_content_resolver = (*env)->CallObjectMethod(env, context, m_get_content_resolver);
        if(o_content_resolver == NULL || s_android_id == NULL){
            return NULL;
        }
        //get the method getString
        jmethodID m_get_string = (*env)->GetStaticMethodID(env, c_settings_secure, "getString",
                                                           "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;");

        if(m_get_string == NULL){
            return NULL;
        }
        //get the Android ID
        jstring android_id = (*env)->CallStaticObjectMethod(env, c_settings_secure,
                                                            m_get_string,
                                                            o_content_resolver,
                                                            s_android_id);
        return android_id;
    }

    JNIEnv* create_vm() {
      JavaVM* jvm;
      JNIEnv* env;
      JavaVMInitArgs args;
      JavaVMOption options[1];

      /* There is a new JNI_VERSION_1_4, but it doesn't add anything for the purposes of our example. */
      args.version = JNI_VERSION_1_4;
      args.nOptions = 1;
      options[0].optionString = "-Djava.class.path=-jar-path";
      args.options = options;
      args.ignoreUnrecognized = JNI_FALSE;

      JNI_CreateJavaVM(&jvm, (void **)&env, &args);
      return env;
    }

    char *jstringTostr(jstring android)
    {
      ...
    }

    //I will call this function from native code.

    char *getAndroidIDfromNativeCode()
    {

      JNIEnv* env = NULL;

      env = create_vm();
      jstring androidID = native_code_getAndroidID(env,NULL);
      return jstringTostr(androidID);

    }

回答1:


The following method can get a Context instance.

static jobject getGlobalContext(JNIEnv *env)
{

    jclass activityThread = (*env)->FindClass(env,"android/app/ActivityThread");
    jmethodID currentActivityThread = (*env)->GetStaticMethodID(env,activityThread, "currentActivityThread", "()Landroid/app/ActivityThread;");
    jobject at = (*env)->CallStaticObjectMethod(env,activityThread, currentActivityThread);

    jmethodID getApplication = (*env)->GetMethodID(env,activityThread, "getApplication", "()Landroid/app/Application;");
    jobject context = (*env)->CallObjectMethod(env,at, getApplication);
    return context;
}



回答2:


The last parameter of type jobject is the instance of the class in which you are keeping the Native method declaration.

So if you declare your method inside an activity, you can directly use the last parameter thiz as an instance of your context.

Otherwise you will need to add another parameter of type Context in your native declaration and of type jobject in the method defination.



来源:https://stackoverflow.com/questions/46869901/how-to-get-the-android-context-instance-when-calling-jni-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!