我正在使用NDK和NativeActivity编写Android应用程序。我的应用程序依赖于作为资产提供的一些第三方代码。目前我正在尝试提取这些资产,同时保持文件夹结构不变。
我已经尝试过使用AssetManager,但为了保持文件夹结构的完整性,似乎会涉及大量的代码,对于一个简单的任务,例如我所提到的。我已经转而专注于尝试将APK视为ZIP文件并以这种方式提取其内容。但这需要我找到APK的确切路径。
在普通的Android应用程序中,可以使用getPackageCodePath,但这是一个附加到Context类的抽象方法。我的问题是如何在不使用普通活动时获取APK的确切路径?
此外,我尝试通过JNI调用getPackageCodePath,但由于无法找到该方法而导致应用程序崩溃。
编辑: 这甚至可能吗?
答案 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);
...
}
但是,我觉得这可能不是一个很好的解决方案。有两件事让我担心:
env
ANativeActivity
成员有一个丑陋的警告,如果我理解正确,这段代码将在本机活动中运行线程。ANativeActivity
的{{1}}成员似乎被误名,实际上是Java clazz
的实例,而不是类对象。否则此代码将无效。我真的很讨厌依赖于这样明显错误名称的东西。除此之外,它有效,我实际上是要自己使用它来尝试使用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