4

NDK と NativeActivity を使用して Android アプリを作成しています。私のアプリは、アセットとして出荷されたいくつかのサードパーティ コードに依存しています。現在、フォルダー構造をそのまま維持しながら、これらのアセットを抽出しようと取り組んでいます。

私は AssetManager を使用してみましたが、フォルダー構造をそのまま維持するために、私が言及したような単純なタスクには、膨大な量のコードが必要になるように思われました。それ以来、APK を ZIP ファイルとして扱う実装を試み、その内容をそのように抽出することに焦点を切り替えました。しかし、それには APK への正確なパスを見つける必要があります。

通常の Android アプリでは getPackageCodePath を使用しますが、これは Context クラスにアタッチされた抽象メソッドです。私の質問は、通常のアクティビティを使用していないときに APK への正確なパスを取得するにはどうすればよいですか?

また、JNI 経由で getPackageCodePath を呼び出してみましたが、メソッドが見つからないためにアプリがクラッシュしました。

編集:これは可能ですか?

4

5 に答える 5

7

getPackageCodePath私は実際にJNI経由で呼び出して動作させることができました。NDK r7 のネイティブ アクティビティ サンプルの先頭にある次のコードはandroid_main、正しいパスをログに記録し、クラッシュしません。

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

    ...
}

しかし、これは素晴らしい解決策ではないかもしれないと感じています。気になる点は次の2点です。

  1. envスレッドの安全性 - のメンバーのみをメインの Java スレッドで使用するという見苦しい警告がありANativeActivityます。正しく理解すれば、このコードはネイティブ アクティビティのスレッドで実行されます。
  2. ANativeActivityclazzメンバーの名前が間違っているようで、実際にNativeActivityはクラス オブジェクトではなく Java のインスタンスです。そうしないと、このコードは機能しません。このように明らかに間違った名前のものに頼るのは本当に嫌いです。

それとは別に、それは機能します。私は実際にそれを自分で使用して、libzip を使用して .apk からアセットを抽出し、データ ディレクトリに入れようとしています。

于 2011-12-09T22:01:01.463 に答える
4

アタッチ/デタッチ呼び出しを行う方法を正確に検索する必要があったため、更新されたバージョンをここに貼り付けます。

以下は、クラッシュすることなく正しい場所を取得しているようです(最小限のテストの後)

    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);
于 2012-07-24T11:07:32.880 に答える
2

Java で呼び出しgetPackageCodePath()、ネイティブ メソッドを介して jstring を C++ アプリに渡します

于 2011-11-30T17:20:41.500 に答える
2

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();
于 2014-07-27T04:42:04.300 に答える