2010-12-15 8 views
6

Existe-t-il un moyen de transmettre/obtenir un objet de contexte android dans mon application ndk? Je veux utiliser SharedPreferences dans mon application ndk via l'interface jni. Pour obtenir une instance de l'objet SharedPreferences, je dois appeler le getSharedPreferences() sur l'objet Context. Mais je n'ai pas accès à l'objet contextuel.Accéder au contexte android dans l'application ndk

OU

Comment puis-je lire et écrire un fichier XML à partir NDK?

Des pointeurs seront appréciés.

+0

Comment lire et écrire le fichier xml: http://xmlsoft.org/ – ognian

+0

Tout en ayant aucune expérience avec le NDK, je ne pense pas que vous pouvez accéder au contexte. Le développement NDK est uniquement pour les choses critiques en termes de temps, de haute performance et de bas niveau. Je vous suggère de trouver les données de configuration les plus critiques dont vous avez besoin et de les écrire en format JSON ou XML et de les analyser à partir de votre code NDK. –

+0

@cppdev maintenant je fais aussi face à ce même problème, si vous avez implémenté cela, pouvez-vous partager –

Répondre

6

Il n'y a rien de spécial à faire, c'est comme un mécanisme JNI normal. Vous devez obtenir un pointeur vers l'objet de contexte, puis récupérer l'ID de la méthode que vous souhaitez appeler, puis l'appeler avec les arguments souhaités.

Bien sûr, dans les mots, cela semble super simple, mais dans le code, il devient vraiment salissant puisque tous les contrôles et les appels JNI. Donc, à mon avis, je n'essaierai pas de mettre en œuvre tout le code natif/JNI, mais je vais implémenter une méthode d'aide en Java qui fait tout le travail et qui reçoit juste les données nécessaires pour lire/écrire la préférence.

Cela simplifiera beaucoup votre code natif et le rendra plus facile à maintenir.

par exemple:

//Somewhere inside a function in your native code 
void Java_com_example_native_MainActivity_nativeFunction(JNIEnv* env, jobject thiz) 
{ 
    jclass cls = (*env)->FindClass(env,"PreferenceHelper"); 
    if (cls == 0) printf("Sorry, I can't find the class"); 

    jmethodID set_preference_method_id; 

    if(cls != NULL) 
    { 
     set_preference_method_id = (*env)->GetStaticMethodID(env, cls, "setPreference", "(Ljava/lang/String;Ljava/lang/StringV"); 

     if(set_preference_method_id != NULL) 
     { 
      jstring preference_name = (*env)->NewStringUTF(env, "some_preference_name"); 
      jstring value = (*env)->NewStringUTF(env, "value_for_preference"); 

      (*env)->CallStaticVoidMethod(env, cls, get_main_id, preference_name, value); 
     } 
    } 
} 

Notez que je viens d'écrire le code de mémoire afin de ne pas attendre à travailler hors de la boîte.

+0

Quelle est la variable 'env'? Est-ce qu'un contexte doit être adopté dans Android? –

+1

@IgorGanapolsky Il n'a pas besoin d'être explicitement passé en argument dans l'appel de la fonction JNI car la machine virtuelle JVM l'envoie en interne. Voir https://en.wikipedia.org/wiki/Java_Native_Interface#How_the_JNI_works – aasu

1

On dirait que les choses ont changé récemment et que la solution ci-dessus et quelques autres postées sur d'autres publications SO ne fonctionnaient pas pour moi. Après quelques essais, j'ai été en mesure de faire le travail de solution suivante. Mon objectif était de transmettre l'objet de contexte à JNI et d'obtenir un chemin de stockage absolu.

void Java_com_path_to_my_class_jniInit(JNIEnv* env, jobject thiz, jobject contextObject) { 

    try { 
     //Get Context Class descriptor 
     jclass contextClass = env->FindClass("android/content/Context"); 
     //Get methodId from Context class 
     jmethodID getFilesDirMethodId = env->GetMethodID(contextClass,"getFilesDir","()Ljava/io/File;"); 

     //Call method on Context object which is passed in 
     jobject fileObject = env->CallObjectMethod(contextObject,getFilesDirMethodId); 

     //Get File class descriptor 
     jclass fileClass = env->FindClass("java/io/File"); 
     //Get handle to the method that is to be called 
     jmethodID absolutePathMethodId = env->GetMethodID(fileClass,"getAbsolutePath","()Ljava/lang/String;"); 
     //Call the method using fileObject 
     jstring stringObject = (jstring)env->CallObjectMethod(fileObject,absolutePathMethodId); 
     } 
     catch(exception& ex){ 
      JNIExceptionHelper::throwException(env, ex.what()); 
      return; 
     } 
} 
+0

Je pensais que les arguments vont dans la dernière position dans la liste des paramètres de 'GetMethodID' selon http://journals.ecs.soton.ac.uk/java/ tutorial/native1.1/implementation/method.html. Cependant, vous passez 'contextClass' comme premier paramètre? –