问题
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