Получение имени Android APK с использованием C ++ и класса NativeActivity - PullRequest
3 голосов
/ 09 октября 2011

Я пишу приложение для Android, используя NDK и NativeActivity.Мое приложение зависит от нескольких сторонних кодов, которые поставляются в качестве активов.В настоящее время я работаю над тем, чтобы извлечь эти ресурсы, сохранив структуру папок без изменений.

Я пытался использовать AssetManager, но чтобы сохранить структуру папок без изменений, казалось, что потребуется огромное количество кода., для простой задачи, такой как то, что я упомянул.С тех пор я переключил фокус, пытаясь реализовать обработку APK как ZIP-файла и извлекать его содержимое таким образом.Но для этого нужно найти точный путь к APK.

В обычном приложении для Android можно использовать getPackageCodePath, но это абстрактный метод, прикрепленный к классу Context.Мой вопрос заключается в том, как получить точный путь к APK, если не используется обычная активность?

Также я попытался вызвать getPackageCodePath через JNI, но это привело к падению приложения из-за невозможности найти метод.

РЕДАКТИРОВАТЬ: это вообще возможно?

Ответы [ 5 ]

5 голосов
/ 10 декабря 2011

Я действительно смог позвонить getPackageCodePath через JNI и заставить его работать.Следующий код, помещенный вверху android_main в образце native-активности в NDK r7, регистрирует правильный путь и не дает сбоя:

void android_main(struct android_app* state) {
    struct engine engine;

    ANativeActivity* activity = state->activity;
    JNIEnv* env = activity->env;

    jclass clazz = (*env)->GetObjectClass(env, activity->clazz);
    jmethodID methodID = (*env)->GetMethodID(env, clazz, "getPackageCodePath", "()Ljava/lang/String;");
    jobject result = (*env)->CallObjectMethod(env, activity->clazz, methodID);

    const char* str;
    jboolean isCopy;
    str = (*env)->GetStringUTFChars(env, (jstring)result, &isCopy);
    LOGI("Looked up package code path: %s", str);

    ...
}

Мне кажется, что это может быть не лучшим решением,хоть.Меня волнуют две вещи:

  1. Безопасность потока - появляется ужасное предупреждение об использовании только env члена ANativeActivity в основном потоке Java, и если я правильно понимаю, этокод будет запущен в потоке нативного действия.
  2. ANativeActivity член clazz, по-видимому, неправильно назван и фактически является экземпляром Java NativeActivity вместо объекта класса.В противном случае этот код не будет работать.Я действительно ненавижу полагаться на что-то, что явно названо так.

Помимо этого, это работает, и я фактически собираюсь использовать это сам, чтобы попытаться извлечь активы из .apkиспользуя libzip и в каталог данных.

2 голосов
/ 15 августа 2016

Вы пытались прочитать / proc / self / cmdline из своего приложения?Вы должны быть в состоянии открыть его как обычно (насколько нормальны файлы proc :-), чтобы вы могли читать из файла до EOF, но не искать) c FILE и читать из него.

КакНапример, для приложения для телефона я вижу из ps в android, что имя приложения - это ожидаемое имя приложения:

 # ps | grep phone 
 radio     1588  839   1467420 103740 SyS_epoll_ 7f7de374ac S com.android.phone

И проверка cmdline для этого pid возвращает правильное имя приложения:

 # cat /proc/1588/cmdline
 com.android.phone
2 голосов
/ 27 июля 2014

Пришлось изменить это в 2014 году.

ANativeActivity* activity = state->activity;
JNIEnv* env=0;

activity->vm->AttachCurrentThread(&env, NULL);

jclass clazz = env->GetObjectClass(activity->clazz);
jmethodID methodID = env->GetMethodID(clazz, "getPackageCodePath", "()Ljava/lang/String;");
jobject result = env->CallObjectMethod(activity->clazz, methodID);

jboolean isCopy;
std::string res = env->GetStringUTFChars((jstring)result, &isCopy);
LOG_DEBUG("Looked up package code path: %s", res.c_str());

activity->vm->DetachCurrentThread();
2 голосов
/ 24 июля 2012

Поскольку мне просто нужно было найти, как именно выполнять вызовы присоединения / отсоединения, я вставлю обновленную версию здесь.

Похоже, что следующее расположение дает правильное местоположение без сбоев (после минимального тестирования)

    ANativeActivity* activity = state->activity;
    JNIEnv* env=0;

    (*activity->vm)->AttachCurrentThread(activity->vm, &env, 0);

    jclass clazz = (*env)->GetObjectClass(env, activity->clazz);
    jmethodID methodID = (*env)->GetMethodID(env, clazz, "getPackageCodePath", "()Ljava/lang/String;");
    jobject result = (*env)->CallObjectMethod(env, activity->clazz, methodID);

    const char* str;
    jboolean isCopy;
    str = (*env)->GetStringUTFChars(env, (jstring)result, &isCopy);
    LOGI("Looked up package code path: %s", str);

    (*activity->vm)->DetachCurrentThread(activity->vm);
2 голосов
/ 30 ноября 2011

Вызовите getPackageCodePath() в Java и передайте jstring в ваше приложение C ++ с помощью собственного метода

...