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

时间:2011-10-09 06:22:49

标签: android android-ndk native-activity

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

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

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

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

编辑: 这甚至可能吗?

5 个答案:

答案 0 :(得分:5)

我实际上能够通过JNI呼叫getPackageCodePath并使其正常工作。以下代码放在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);

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

  1. 线程安全 - 在主Java线程中只使用env ANativeActivity成员有一个丑陋的警告,如果我理解正确,这段代码将在本机活动中运行线程。
  2. ANativeActivity的{​​{1}}成员似乎被误名,实际上是Java clazz的实例,而不是类对象。否则此代码将无效。我真的很讨厌依赖于这样明显错误名称的东西。
  3. 除此之外,它有效,我实际上是要自己使用它来尝试使用libzip从数据目录中提取资源。

答案 1 :(得分:2)

在Java中调用getPackageCodePath()并通过本机方法将jstring传递给您的C ++应用程序

答案 2 :(得分:2)

由于我只是要搜索确切如何进行附加/分离调用,我将在此处粘贴更新版本。

以下似乎可以获得正确的位置而不会崩溃(在最小化测试之后)

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

答案 3 :(得分: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();

答案 4 :(得分:2)

您是否尝试从应用程序中读取/ proc / self / cmdline? 您应该能够正常打开它(因为proc文件是正常的:-)所以你可以从文件中读取,直到EOF,但不能查找)c FILE并从中读取。

作为手机应用程序的一个示例,我可以从Android中的ps看到应用程序的名称是预期的应用程序名称:

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

检查该pid的cmdline会返回一个好的应用名称:

 # cat /proc/1588/cmdline
 com.android.phone