2011-09-29 161 views
18

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

然而,我在各种Android设备的研究似乎表明,

  • tmpfile总是失败;
  • 目录中没有/tmp;
  • 目录/data/local/tmp没有出现在Android的所有变体上;
  • 环境变量集没有TEMP;
  • mkstemp不能比tmpfile好。

现在,我敢肯定,我可以砍的东西在一起,但看到,对于Java应用程序的SDK提供context.getCacheDirFile.createTempFile,我希望有在C级等同。

有谁知道一个很好的可靠和跨Android方法来创建临时文件吗?

回答

9

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

如果你真的想从JNI取它的另一个替代方案是在Context传递给JNI的功能和使用一堆GetMethodID/CallObjectMethod东西放回Java调用到getCacheDir,但前者的做法是很多简单。

遗憾的是,似乎没有要在此刻更优雅的解决方案。

+2

可以使用'libcore'来调用'setenv()',参见http://stackoverflow.com/a/22315463/192373。这可能是显示缓存目录到本机的名称更优雅的方式。 –

0

mkstemp下stdlib.h中

+0

这是否帮助?我认为mkstemp使用一个包含完整路径到temp目录的'template'。 –

2

下面是Ertebolle指的GetMethodID/CallObjectMethod过程是在NDK可用。如果您正在使用纯原生应用程序(如由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; 
}