使用NDK下获取文件目录

哥很纠结,时至今天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);

.......................................................

 

你可能感兴趣的:(使用NDK下获取文件目录)