Commit fd6a25a7 authored by Thomas Guillem's avatar Thomas Guillem
Browse files

android: fix config_GetUserDir for generic dirs

Call android.os.Environment.getExternalStoragePublicDirectory() from JNI to get
the path to a valid directory.
parent af873cf8
......@@ -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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment