【问题标题】:Creating temporary files in Android with NDK使用 NDK 在 Android 中创建临时文件
【发布时间】:2011-11-27 13:29:20
【问题描述】:

我目前正在开发一个基于 C、基于 NDK 的 Android 应用程序。此应用程序需要创建临时文件。在常规的 Linux 系统上,我会使用 tmpfile 来确保这些文件在临时目录中正确创建并在进程结束时清理。

但是,我对各种 Android 设备的调查似乎表明

  • tmpfile 总是失败;
  • 没有/tmp目录;
  • 目录/data/local/tmp 并不存在于所有Android 变体上;
  • 没有设置TEMP环境变量;
  • mkstemp 并不比 tmpfile 好用。

现在,我确信我可以一起破解一些东西,但是看到 SDK 为 Java 应用程序提供了 context.getCacheDirFile.createTempFile,我希望在 C 级也有一个等价物。

有人知道创建临时文件的可靠且跨 Android 的良好方法吗?

【问题讨论】:

    标签: android-ndk temporary-files


    【解决方案1】:

    我们发现最好的方法是在启动时调用Context.getCacheDir,使用getAbsolutePath 获取其路径,然后调用JNI 函数将该路径存储在全局中。任何想要创建临时文件的函数只需将合适的临时文件名附加到该路径即可。

    如果你真的想从 JNI 中获取它,另一种选择是将 Context 传递给 JNI 函数,并使用一堆 GetMethodID / CallObjectMethod 东西将 Java 回调到 getCacheDir,但前一种方法要简单得多。

    很遗憾,目前似乎没有更优雅的解决方案。

    【讨论】:

    【解决方案2】:

    据我所知,android 中没有全局 /tmp,您应该使用缓存目录。使用 getCacheDir() 获取“tmp”目录。

    http://developer.android.com/guide/topics/data/data-storage.html#filesInternalhttp://developer.android.com/reference/android/content/Context.html#getCacheDir%28%29

    【讨论】:

      【解决方案3】:

      mkstemp 在 NDK 中的 stdlib.h 下可用

      【讨论】:

      • 这有帮助吗?我认为 mkstemp 使用了一个 template 包含临时目录的完整路径。
      【解决方案4】:

      下面是 Ertebolle 引用的 GetMethodID / CallObjectMethod 过程。如果您正在使用纯本机应用程序(例如由 Visual Studio 2015 构建)并且无法使用 java 代码,则这是必需的。

      std::string android_temp_folder( struct android_app *app ) {
          JNIEnv* env;
          app->activity->vm->AttachCurrentThread( &env, NULL );
      
          jclass activityClass = env->FindClass( "android/app/NativeActivity" );
          jmethodID getCacheDir = env->GetMethodID( activityClass, "getCacheDir", "()Ljava/io/File;" );
          jobject cache_dir = env->CallObjectMethod( app->activity->clazz, getCacheDir );
      
          jclass fileClass = env->FindClass( "java/io/File" );
          jmethodID getPath = env->GetMethodID( fileClass, "getPath", "()Ljava/lang/String;" );
          jstring path_string = (jstring)env->CallObjectMethod( cache_dir, getPath );
      
          const char *path_chars = env->GetStringUTFChars( path_string, NULL );
          std::string temp_folder( path_chars );
      
          env->ReleaseStringUTFChars( path_string, path_chars );
          app->activity->vm->DetachCurrentThread();
          return temp_folder;
      }
      

      【讨论】:

        【解决方案5】:
        1. 使用 ContentProvider 在应用程序启动时获取缓存目录的路径。
        2. 使用与 POSIX 的 tmpfile 相同的签名实现 tmpfile 函数。
        3. 使用先前获得的缓存目录从 tmpfile 函数调用 mkstemp

        把它打包成.aar,这样就可以通过gradle来消费了。

        https://github.com/ViliusSutkus89/tmpfile-Android

        【讨论】:

          猜你喜欢
          • 2011-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多