2011-09-29 53 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; 
}