使用C++和NativeActivity类获取Android APK的名称

rst*_*at1 3 android android-ndk native-activity

我正在使用NDK和NativeActivity编写Android应用程序.我的应用程序依赖于作为资产提供的一些第三方代码.目前我正在尝试提取这些资产,同时保持文件夹结构不变.

我已经尝试过使用AssetManager,但为了保持文件夹结构的完整性,似乎会涉及大量的代码,对于一个简单的任务,比如我所提到的.我已经转而专注于尝试将APK视为ZIP文件并以这种方式提取其内容.但这要求我找到APK的确切路径.

在普通的Android应用程序中,可以使用getPackageCodePath,但这是一个附加到Context类的抽象方法.我的问题是如何在不使用普通活动时获取APK的确切路径?

此外,我尝试通过JNI调用getPackageCodePath,但由于无法找到该方法而导致应用程序崩溃.

编辑:这甚至可能吗?

mat*_*att 5

我实际上能够getPackageCodePath通过JNI 打电话让它工作.以下代码放在android_mainNDK r7中的native-activity示例的顶部,记录正确的路径并且不会崩溃:

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

不过,我觉得这可能不是一个很好的解决方案.有两件事让我担心:

  1. 线程安全 - 有一个丑陋的警告只关于使用主Java线程中的env成员ANativeActivity,如果我理解正确,这段代码将在本机活动的线程中运行.
  2. ANativeActivityclazz成员似乎是错误名称,实际上是Java的实例NativeActivity而不是类对象.否则此代码将无效.我真的很讨厌依赖于这样明显错误名称的东西.

除此之外,它可以工作,而我实际上是要自己使用它来尝试使用libzip从数据目录中提取资源.apk.

  • 关于我关注的问题#1:事实证明,使用JavaVM的AttachCurrentThread函数可以实现线程安全.这将创建/检索应该使用的JNIEnv,而不是我上面列出的那个.ANativeActivity的vm成员是JavaVM.当在线程中使用JNIEnv完成时,您应该调用JavaVM的DetachCurrentThread并停止使用JNIEnv.我给出的原始代码实际上是在某些设备上崩溃,但是当Attach/DetachCurrentThread开始被调用时,它停止了崩溃并且工作得很好. (2认同)