Доступ к контексту Android в приложении ndk

Есть ли способ передать/получить объект контекста Android в моем приложении ndk. Я хочу использовать SharedPreferences в своем приложении ndk через интерфейс jni. Чтобы получить экземпляр объекта SharedPreferences, мне нужно вызвать getSharedPreferences() для объекта Context. Но у меня нет доступа к объекту контекста.

OR

Как я могу читать и записывать xml-файл из NDK?

Любые указатели будут оценены.


person cppdev    schedule 15.12.2010    source источник
comment
Как читать и писать XML-файл: xmlsoft.org   -  person ognian    schedule 15.12.2010
comment
Не имея опыта работы с NDK, я не думаю, что вы можете получить доступ к контексту. Разработка NDK предназначена только для срочных, высокопроизводительных и низкоуровневых вещей. Я предлагаю вам найти наиболее важные данные конфигурации, которые вам нужны, записать их в формате JSON или XML и проанализировать их из кода NDK.   -  person Sebastian Roth    schedule 15.12.2010
comment
@cppdev теперь я столкнулся с той же проблемой, если вы реализовали это, можете поделиться   -  person Mr.Cool    schedule 22.05.2013


Ответы (2)


Вам не нужно делать ничего особенного, это похоже на обычный механизм JNI. Вам нужно получить указатель на объект контекста, затем получить идентификатор метода, который вы хотите вызвать, а затем вызвать его с нужными аргументами.

Конечно, на словах это звучит очень просто, но в коде это становится очень запутанным, поскольку все проверки и вызовы JNI.

Поэтому, на мой взгляд, я не буду пытаться реализовать все это из собственного/JNI-кода, вместо этого я реализую вспомогательный метод на Java, который делает все и просто получает необходимые данные для чтения/записи предпочтения.

Это значительно упростит ваш нативный код и упростит его поддержку.

eg:

//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);
        }
    }
}

Обратите внимание, что я просто написал код по памяти, так что ожидайте, что он не будет работать сразу после установки.

person Lucas S.    schedule 22.12.2010
comment
Что такое переменная env? Является ли контекст для передачи в Android? - person IgorGanapolsky; 12.04.2016
comment
@IgorGanapolsky Его не нужно явно передавать в качестве аргумента в вызове функции JNI, потому что JVM передает его внутри. См. en.wikipedia.org/wiki/Java_Native_Interface#How_the_JNI_works. - person aasu; 08.09.2016

Похоже, что недавно что-то изменилось, и решение, приведенное выше, и несколько других, опубликованных в других сообщениях SO, не сработали для меня. После нескольких попыток я смог заставить работать следующее решение. Моя цель состояла в том, чтобы передать объект контекста в JNI и получить абсолютный путь к хранилищу.

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;
      }
}
person dev    schedule 16.02.2016
comment
Я думал, что аргументы идут в последнюю позицию в списке параметров для GetMethodID в соответствии с journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/. Однако вы передаете contextClass в качестве первого параметра? - person IgorGanapolsky; 12.04.2016