哥很纠结,时至今天NDK R8仍然没有修复这个BUG,从android_main(struct android_app* state)传入参数,state中获取ANativeActivity对象里面internalDataPath; externalDataPath;两个字段在android 2.3上面运行常为0,正确应该都是路径字符串,目前只有3.0以上的系统修复了,但哥的手机很悲剧的是2.3.5版的系统,不想刷机,只好换个方法实现了。
哥一直以为JNI只是JAVA搞C的道具,如今发现C也可以通过JNI搞JAVA,而且我发现这种方式获取程序运行路径是最好的,网上很多人说通过/data/data/+获取程序运行名的方式搞,而在Imagination Technologies提供他的芯片开源图形库里面也是按这种方式搞,但哥说这种方式不靠谱,一些没ROOT的机压根就进不去系统目录,用c获取的路径全是空的,因为没有权限,ANDROID上面只允许受权的程序搞那个,但很悲剧C/C++搞NDK的时候并没有JAVA搞SDK那样方便得到授权。程序总不能只跑在破解了的系统上面,只好用JNI了。
准确来说NDK搞的C/C++代码也并非纯纯的C/C++代码,即使现在NDK的库已经支持可以一句JAVA也不写就能跑起来,这些程序还是受JVM的管理的,所以也不用太在意什么C调JAVA的事情了。
关键性的代码贴上分享下:
void
android_main(struct android_app* state)
{
struct stOsContextEngine engine;
// Make sure glue isn't stripped.
app_dummy();
memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.m_app = state;
// Prepare to monitor accelerometer
engine.m_sensorManager = ASensorManager_getInstance();
engine.m_accelerometerSensor = ASensorManager_getDefaultSensor(
engine.m_sensorManager, ASENSOR_TYPE_ACCELEROMETER);
engine.m_sensorEventQueue = ASensorManager_createEventQueue(
engine.m_sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL);
// 获取AAssetManager,这个类其实是调用JAVA的类,这里通过NDK入口的传入参数获取。作用是管理资源文件的
AAssetManager* pAssetManager = state->activity->assetManager;
HResult hres = CPeckerFileIOBase::SetPrivateAPKManager(pAssetManager);
__android_log_print(LOGINFO_INFO, "android_main", "CPeckerFileIOBase::SetPrivateAPKManager result = %d",hres);
// 获取ANativeActivity,这个类其实也是调用JAVA的类,这里通过NDK入口的传入参数获取。作用是窗口Activity的
ANativeActivity* pActivity = state->activity;
// 通过Activity里面getPackageCodePath的方法获取程序运行路径,通过JNI用C++搞JAVA
JNIEnv* env = pActivity->env;
jclass clazz = env->GetObjectClass(pActivity->clazz);
jmethodID methodID = env->GetMethodID(clazz, "getPackageCodePath", "()Ljava/lang/String;");
jobject result = env->CallObjectMethod(pActivity->clazz, methodID);
ConstStringChars strPath;
jboolean isCopy;
strPath.m_pStrBuf = env->GetStringUTFChars((jstring)result, &isCopy);
strPath.m_nStrLen = env->GetStringLength((jstring)result);
__android_log_print(LOGINFO_INFO, "android_main", "Code Path =%d %s",strPath.m_nStrLen,strPath.m_pStrBuf);
CPeckerFileIOBase::SetInstallFilePath(strPath);
// 记得搞完后要清理下哦
env->ReleaseStringUTFChars((jstring)result,strPath.m_pStrBuf);
.......................................................