Creating temporary files in Android with NDK

大兔子大兔子 提交于 2019-11-26 16:34:04

问题


I am currently working on a C-based, NDK-based, Android application. This application needs to create temporary files. On a regular Linux system, I would use tmpfile to ensure that these files are properly created in a temporary directory and cleaned-up at process end.

However, my investigations on various Android devices seem to indicate that

  • tmpfile always fails;
  • there is no /tmp directory;
  • directory /data/local/tmp isn't present on all variants of Android;
  • there is no TEMP environment variable set;
  • mkstemp doesn't work any better than tmpfile.

Now, I'm sure that I could hack something together, but seeing that the SDK offers context.getCacheDir and File.createTempFile for Java applications, I hope that there is an equivalent at C-level.

Does anyone know of a good reliable and cross-Android method for creating a temporary file?


回答1:


The best way we've found is to call Context.getCacheDir on startup, get its path with getAbsolutePath, then call a JNI function to store that path in a global. Any function that wants to create a temporary file simply appends a suitable temporary file name to that path.

If you really want to fetch it from JNI another alternative would be to pass in a Context to a JNI function and use a bunch of GetMethodID / CallObjectMethod stuff to call back into Java to getCacheDir, but the former approach is a lot simpler.

Unfortunately, there does not appear to be a more elegant solution at the moment.




回答2:


Below is the GetMethodID / CallObjectMethod procedure that Ertebolle refers to. It is necessary if you are working with a pure native app (such as built by Visual Studio 2015) and cannot use java code.

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;
}



回答3:


As far as I know there is no global /tmp in android, you should use the cache dir. Use getCacheDir() to get the "tmp" dir.

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




回答4:


mkstemp is available in the NDK under stdlib.h




回答5:


  1. Obtain path to cache directory on application's startup using a ContentProvider.
  2. Implement tmpfile function with the same signature as POSIX's tmpfile.
  3. Call mkstemp from your tmpfile function using the previously obtained cache directory

Packaged it as .aar, so it could be consumed through gradle.

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



来源:https://stackoverflow.com/questions/7595324/creating-temporary-files-in-android-with-ndk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!