[vlc-commits] android: fix config_GetUserDir for generic dirs
Thomas Guillem
git at videolan.org
Wed Jul 13 15:43:43 CEST 2016
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Jul 13 15:19:14 2016 +0200| [fd6a25a7258d111e199596e6f3d313edf453ace1] | committer: Thomas Guillem
android: fix config_GetUserDir for generic dirs
Call android.os.Environment.getExternalStoragePublicDirectory() from JNI to get
the path to a valid directory.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fd6a25a7258d111e199596e6f3d313edf453ace1
---
src/android/specific.c | 172 +++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 164 insertions(+), 8 deletions(-)
diff --git a/src/android/specific.c b/src/android/specific.c
index 959dc37..1337157 100644
--- a/src/android/specific.c
+++ b/src/android/specific.c
@@ -33,6 +33,56 @@
#include <jni.h>
static JavaVM *s_jvm = NULL;
+#define GENERIC_DIR_COUNT (VLC_VIDEOS_DIR - VLC_DESKTOP_DIR + 1)
+static char *ppsz_generic_names[GENERIC_DIR_COUNT] = {};
+static struct {
+ struct {
+ jclass clazz;
+ jmethodID getExternalStoragePublicDirectory;
+ } Environment;
+ struct {
+ jmethodID getAbsolutePath;
+ } File;
+} fields = { .Environment.clazz = NULL };
+
+static char *
+get_java_string(JNIEnv *env, jclass clazz, const char *psz_name)
+{
+ jfieldID id = (*env)->GetStaticFieldID(env, clazz, psz_name,
+ "Ljava/lang/String;");
+ if ((*env)->ExceptionCheck(env))
+ return NULL;
+
+ jstring jstr = (*env)->GetStaticObjectField(env, clazz, id);
+
+ const char *psz_str = (*env)->GetStringUTFChars(env, jstr, 0);
+ if (psz_str == NULL)
+ return NULL;
+
+ char *psz_strdup = strdup(psz_str);
+
+ (*env)->ReleaseStringUTFChars(env, jstr, psz_str);
+ (*env)->DeleteLocalRef(env, jstr);
+
+ return psz_strdup;
+}
+
+void
+JNI_OnUnload(JavaVM* vm, void* reserved)
+{
+ (void) reserved;
+
+ for (size_t i = 0; i < GENERIC_DIR_COUNT; ++i)
+ free(ppsz_generic_names[i]);
+
+ if (fields.Environment.clazz)
+ {
+ JNIEnv* env = NULL;
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK)
+ return;
+ (*env)->DeleteGlobalRef(env, fields.Environment.clazz);
+ }
+}
/* This function is called when the libvlcore dynamic library is loaded via the
* java.lang.System.loadLibrary method. Therefore, s_jvm will be already set
@@ -40,16 +90,61 @@ static JavaVM *s_jvm = NULL;
jint
JNI_OnLoad(JavaVM *vm, void *reserved)
{
- (void) reserved;
s_jvm = vm;
+ JNIEnv* env = NULL;
+
+ if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK)
+ return -1;
+
+ jclass clazz = (*env)->FindClass(env, "android/os/Environment");
+ if ((*env)->ExceptionCheck(env))
+ return -1;
+
+ static const char *ppsz_env_names[GENERIC_DIR_COUNT] = {
+ NULL, /* VLC_DESKTOP_DIR */
+ "DIRECTORY_DOWNLOADS", /* VLC_DOWNLOAD_DIR */
+ NULL, /* VLC_TEMPLATES_DIR */
+ NULL, /* VLC_PUBLICSHARE_DIR */
+ "DIRECTORY_DOCUMENTS", /* VLC_DOCUMENTS_DIR */
+ "DIRECTORY_MUSIC", /* VLC_MUSIC_DIR */
+ "DIRECTORY_PICTURES", /* VLC_PICTURES_DIR */
+ "DIRECTORY_MOVIES", /* VLC_VIDEOS_DIR */
+ };
+ for (size_t i = 0; i < GENERIC_DIR_COUNT; ++i)
+ {
+ if (ppsz_env_names[i] != NULL)
+ {
+ ppsz_generic_names[i] = get_java_string(env, clazz,
+ ppsz_env_names[i]);
+ if (!ppsz_generic_names[i])
+ goto error;
+ }
+ }
+
+ fields.Environment.clazz = (*env)->NewGlobalRef(env, clazz);
+ fields.Environment.getExternalStoragePublicDirectory =
+ (*env)->GetStaticMethodID(env, clazz,
+ "getExternalStoragePublicDirectory",
+ "(Ljava/lang/String;)Ljava/io/File;");
+ if ((*env)->ExceptionCheck(env))
+ goto error;
+ (*env)->DeleteLocalRef(env, clazz);
+
+ clazz = (*env)->FindClass(env, "java/io/File");
+ fields.File.getAbsolutePath =
+ (*env)->GetMethodID(env, clazz, "getAbsolutePath",
+ "()Ljava/lang/String;");
+ if ((*env)->ExceptionCheck(env))
+ goto error;
+ (*env)->DeleteLocalRef(env, clazz);
+
return JNI_VERSION_1_2;
-}
-void
-JNI_OnUnload(JavaVM* vm, void* reserved)
-{
- (void) vm;
- (void) reserved;
+error:
+ if (clazz)
+ (*env)->DeleteLocalRef(env, clazz);
+ JNI_OnUnload(vm, reserved);
+ return -1;
}
void
@@ -89,6 +184,62 @@ fallback:
return psz_default_dir != NULL ? strdup(psz_default_dir) : NULL;
}
+static char *config_GetGenericDir(const char *psz_name)
+{
+ JNIEnv *env;
+ bool b_detach;
+ char *psz_ret = NULL;
+
+ if ((*s_jvm)->GetEnv(s_jvm, (void **)&env, JNI_VERSION_1_2) != JNI_OK)
+ {
+ /* attach the thread to the Java VM */
+ JavaVMAttachArgs args;
+
+ args.version = JNI_VERSION_1_2;
+ args.name = "config_GetGenericDir";
+ args.group = NULL;
+
+ if ((*s_jvm)->AttachCurrentThread(s_jvm, &env, &args) != JNI_OK)
+ return NULL;
+ b_detach = true;
+ }
+ else
+ b_detach = false;
+
+ jstring jname= (*env)->NewStringUTF(env, psz_name);
+ if ((*env)->ExceptionCheck(env))
+ {
+ (*env)->ExceptionClear(env);
+ jname = NULL;
+ }
+ if (jname == NULL)
+ goto error;
+
+ jobject jfile = (*env)->CallStaticObjectMethod(env,
+ fields.Environment.clazz,
+ fields.Environment.getExternalStoragePublicDirectory,
+ jname);
+ (*env)->DeleteLocalRef(env, jname);
+ if (jfile == NULL)
+ goto error;
+
+ jstring jpath = (*env)->CallObjectMethod(env, jfile,
+ fields.File.getAbsolutePath);
+ (*env)->DeleteLocalRef(env, jfile);
+
+ const char *psz_path = (*env)->GetStringUTFChars(env, jpath, 0);
+ if (psz_path == NULL)
+ goto error;
+ psz_ret = strdup(psz_path);
+ (*env)->ReleaseStringUTFChars(env, jpath, psz_path);
+ (*env)->DeleteLocalRef(env, jpath);
+
+error:
+ if (b_detach)
+ (*s_jvm)->DetachCurrentThread(s_jvm);
+ return psz_ret;
+}
+
char *config_GetUserDir (vlc_userdir_t type)
{
switch (type)
@@ -112,7 +263,12 @@ char *config_GetUserDir (vlc_userdir_t type)
case VLC_MUSIC_DIR:
case VLC_PICTURES_DIR:
case VLC_VIDEOS_DIR:
- return NULL;
+ {
+ assert(type >= VLC_DESKTOP_DIR && type <= VLC_VIDEOS_DIR);
+ const char *psz_name = ppsz_generic_names[type - VLC_DESKTOP_DIR];
+ if (psz_name != NULL)
+ return config_GetGenericDir(psz_name);
+ }
}
return NULL;
}
More information about the vlc-commits
mailing list