diff --git a/meson.build b/meson.build index 4976aa31..b56ae6e8 100644 --- a/meson.build +++ b/meson.build @@ -89,6 +89,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ 'src/api-impl-jni/audio/android_media_AudioTrack.c', 'src/api-impl-jni/audio/android_media_SoundPool.c', 'src/api-impl-jni/content/android_content_ClipboardManager.c', + 'src/api-impl-jni/content/android_content_ContentResolver.c', 'src/api-impl-jni/content/android_content_Context.c', 'src/api-impl-jni/content/android_content_res_XmlBlock.c', 'src/api-impl-jni/database/android_database_SQLiteCommon.c', diff --git a/src/api-impl-jni/content/android_content_ContentResolver.c b/src/api-impl-jni/content/android_content_ContentResolver.c new file mode 100644 index 00000000..e15f9d89 --- /dev/null +++ b/src/api-impl-jni/content/android_content_ContentResolver.c @@ -0,0 +1,42 @@ +#include +#include + +#include "../defines.h" +#include "../generated_headers/android_content_ContentResolver.h" + +JNIEXPORT void JNICALL Java_android_content_ContentResolver_native_1query_1file_1info(JNIEnv *env, jclass clazz, jstring path_jstr, jobjectArray attributes, jobjectArray results) +{ + const char *path = (*env)->GetStringUTFChars(env, path_jstr, NULL); + GFile *file = g_file_new_for_path(path); + GString *attrs = g_string_new(""); + for (int i = 0; i < (*env)->GetArrayLength(env, attributes); i++,g_string_append(attrs, ",")) { + const char *attr = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, attributes, i), NULL); + if (!strcmp(attr, "_display_name")) { + g_string_append(attrs, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME); + } else if (!strcmp(attr, "mime_type")) { + g_string_append(attrs, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); + } + (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, attributes, i), attr); + } + GError *error = NULL; + GFileInfo *file_info = g_file_query_info(file, attrs->str, G_FILE_QUERY_INFO_NONE, NULL, &error); + g_string_free(attrs, TRUE); + if (error) { + g_error_free(error); + (*env)->ReleaseStringUTFChars(env, path_jstr, path); + return; + } + for (int i = 0; i < (*env)->GetArrayLength(env, attributes); i++) { + const char *attr = (*env)->GetStringUTFChars(env, (*env)->GetObjectArrayElement(env, attributes, i), NULL); + if (!strcmp(attr, "_display_name")) { + jstring name = _JSTRING(g_file_info_get_attribute_string(file_info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)); + (*env)->SetObjectArrayElement(env, results, i, name); + } else if (!strcmp(attr, "mime_type")) { + jstring mime_type = _JSTRING(g_content_type_get_mime_type(g_file_info_get_content_type(file_info))); + (*env)->SetObjectArrayElement(env, results, i, mime_type); + } + (*env)->ReleaseStringUTFChars(env, (*env)->GetObjectArrayElement(env, attributes, i), attr); + } + g_object_unref(file_info); + (*env)->ReleaseStringUTFChars(env, path_jstr, path); +} diff --git a/src/api-impl-jni/generated_headers/android_content_ContentResolver.h b/src/api-impl-jni/generated_headers/android_content_ContentResolver.h new file mode 100644 index 00000000..afc58351 --- /dev/null +++ b/src/api-impl-jni/generated_headers/android_content_ContentResolver.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class android_content_ContentResolver */ + +#ifndef _Included_android_content_ContentResolver +#define _Included_android_content_ContentResolver +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: android_content_ContentResolver + * Method: native_query_file_info + * Signature: (Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_android_content_ContentResolver_native_1query_1file_1info + (JNIEnv *, jclass, jstring, jobjectArray, jobjectArray); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/api-impl/android/content/ContentResolver.java b/src/api-impl/android/content/ContentResolver.java index 8df1782a..4732a580 100644 --- a/src/api-impl/android/content/ContentResolver.java +++ b/src/api-impl/android/content/ContentResolver.java @@ -6,6 +6,7 @@ import java.io.FileNotFoundException; import android.accounts.Account; import android.database.ContentObserver; import android.database.Cursor; +import android.database.MatrixCursor; import android.net.Uri; import android.os.Bundle; import android.os.CancellationSignal; @@ -40,10 +41,17 @@ public class ContentResolver { public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { ContentProvider provider = ContentProvider.providers.get(uri.getAuthority()); - if (provider != null) + if (provider != null) { return provider.query(uri, projection, selection, selectionArgs, sortOrder); - else + } else if ("file".equals(uri.getScheme())) { + MatrixCursor cursor = new MatrixCursor(projection); + Object[] row = new Object[projection.length]; + native_query_file_info(uri.getPath(), projection, row); + cursor.addRow(row); + return cursor; + } else { return null; + } } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, CancellationSignal cancellationSignal) { @@ -94,4 +102,6 @@ public class ContentResolver { public static boolean isSyncActive(Account account, String authority) { return false; } + + private static native void native_query_file_info(String path, String[] attributes, Object[] result); }