From 3805b84906b7994486c1b13eb49f93b2796a9a11 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 27 Jun 2020 11:04:48 +0200 Subject: [PATCH] Android: Add content provider support to File::Delete --- .../dolphinemu/utils/ContentHandler.java | 16 ++++++++++++++++ .../jni/AndroidCommon/AndroidCommon.cpp | 7 +++++++ .../Android/jni/AndroidCommon/AndroidCommon.h | 1 + Source/Android/jni/AndroidCommon/IDCache.cpp | 8 ++++++++ Source/Android/jni/AndroidCommon/IDCache.h | 1 + Source/Core/Common/FileUtil.cpp | 18 ++++++++++++++++-- 6 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java index a42c464d52..83b9c585c9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java @@ -1,6 +1,8 @@ package org.dolphinemu.dolphinemu.utils; +import android.content.ContentResolver; import android.net.Uri; +import android.provider.DocumentsContract; import org.dolphinemu.dolphinemu.DolphinApplication; @@ -20,4 +22,18 @@ public class ContentHandler return -1; } } + + public static boolean delete(String uri) + { + try + { + ContentResolver resolver = DolphinApplication.getAppContext().getContentResolver(); + return DocumentsContract.deleteDocument(resolver, Uri.parse(uri)); + } + catch (FileNotFoundException e) + { + // Return true because we care about the file not being there, not the actual delete. + return true; + } + } } diff --git a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp index c8312048e9..73405b6d8e 100644 --- a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp +++ b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp @@ -58,3 +58,10 @@ int OpenAndroidContent(const std::string& uri, const std::string& mode) return fd; } + +bool DeleteAndroidContent(const std::string& uri) +{ + JNIEnv* env = IDCache::GetEnvForThread(); + return env->CallStaticBooleanMethod(IDCache::GetContentHandlerClass(), + IDCache::GetContentHandlerDelete(), ToJString(env, uri)); +} diff --git a/Source/Android/jni/AndroidCommon/AndroidCommon.h b/Source/Android/jni/AndroidCommon/AndroidCommon.h index 4940844564..ca8245182d 100644 --- a/Source/Android/jni/AndroidCommon/AndroidCommon.h +++ b/Source/Android/jni/AndroidCommon/AndroidCommon.h @@ -13,3 +13,4 @@ jstring ToJString(JNIEnv* env, const std::string& str); std::vector JStringArrayToVector(JNIEnv* env, jobjectArray array); int OpenAndroidContent(const std::string& uri, const std::string& mode); +bool DeleteAndroidContent(const std::string& uri); diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp index f44b5402f8..b4052c42bf 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.cpp +++ b/Source/Android/jni/AndroidCommon/IDCache.cpp @@ -41,6 +41,7 @@ static jmethodID s_compress_cb_run; static jclass s_content_handler_class; static jmethodID s_content_handler_open_fd; +static jmethodID s_content_handler_delete; namespace IDCache { @@ -187,6 +188,11 @@ jmethodID GetContentHandlerOpenFd() return s_content_handler_open_fd; } +jmethodID GetContentHandlerDelete() +{ + return s_content_handler_delete; +} + } // namespace IDCache #ifdef __cplusplus @@ -259,6 +265,8 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) s_content_handler_class = reinterpret_cast(env->NewGlobalRef(content_handler_class)); s_content_handler_open_fd = env->GetStaticMethodID(s_content_handler_class, "openFd", "(Ljava/lang/String;Ljava/lang/String;)I"); + s_content_handler_delete = + env->GetStaticMethodID(s_content_handler_class, "delete", "(Ljava/lang/String;)Z"); return JNI_VERSION; } diff --git a/Source/Android/jni/AndroidCommon/IDCache.h b/Source/Android/jni/AndroidCommon/IDCache.h index 54dafb5a0d..8fd43ea41d 100644 --- a/Source/Android/jni/AndroidCommon/IDCache.h +++ b/Source/Android/jni/AndroidCommon/IDCache.h @@ -43,5 +43,6 @@ jmethodID GetCompressCallbackRun(); jclass GetContentHandlerClass(); jmethodID GetContentHandlerOpenFd(); +jmethodID GetContentHandlerDelete(); } // namespace IDCache diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index b3efa6b868..3c524ed9d8 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -46,6 +46,11 @@ #include #endif +#ifdef ANDROID +#include "Common/StringUtil.h" +#include "jni/AndroidCommon/AndroidCommon.h" +#endif + #ifndef S_ISDIR #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif @@ -132,10 +137,19 @@ bool Delete(const std::string& filename) { INFO_LOG(COMMON, "Delete: file %s", filename.c_str()); +#ifdef ANDROID + if (StringBeginsWith(filename, "content://")) + { + const bool success = DeleteAndroidContent(filename); + if (!success) + WARN_LOG(COMMON, "Delete failed on %s", filename.c_str()); + return success; + } +#endif + const FileInfo file_info(filename); - // Return true because we care about the file no - // being there, not the actual delete. + // Return true because we care about the file not being there, not the actual delete. if (!file_info.Exists()) { WARN_LOG(COMMON, "Delete: %s does not exist", filename.c_str());