From 22c2c8897496233a9f7f9c318451a28839f37499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Mon, 24 Sep 2018 16:04:07 +0200 Subject: [PATCH] [android] check external database's read/write permissions asynchronously --- .../mapboxsdk/offline/OfflineManager.java | 39 ++++-- .../com/mapbox/mapboxsdk/utils/FileUtils.java | 121 ++++++++++++++++++ 2 files changed, 147 insertions(+), 13 deletions(-) create mode 100644 platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/FileUtils.java diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index fbbdf087b0b..cb9260b3cd2 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -15,6 +15,7 @@ import com.mapbox.mapboxsdk.log.Logger; import com.mapbox.mapboxsdk.net.ConnectivityReceiver; import com.mapbox.mapboxsdk.storage.FileSource; +import com.mapbox.mapboxsdk.utils.FileUtils; import java.io.File; import java.io.FileInputStream; @@ -235,20 +236,32 @@ public void run() { */ public void mergeOfflineRegions(@NonNull String path, @NonNull final MergeOfflineRegionsCallback callback) { File src = new File(path); - if (!src.canRead()) { - // path not readable, abort - callback.onError("Secondary database needs to be located in a readable path."); - return; - } + new FileUtils.CheckFileReadPermissionTask(new FileUtils.OnCheckFileReadPermissionListener() { + @Override + public void onReadPermissionGranted() { + new FileUtils.CheckFileWritePermissionTask(new FileUtils.OnCheckFileWritePermissionListener() { + @Override + public void onWritePermissionGranted() { + // path writable, merge and update schema in place if necessary + mergeOfflineDatabaseFiles(src, callback, false); + } - if (src.canWrite()) { - // path writable, merge and update schema in place if necessary - mergeOfflineDatabaseFiles(src, callback, false); - } else { - // path not writable, copy the the file to temp directory, then merge and update schema on a copy if necessary - File dst = new File(FileSource.getInternalCachePath(context), src.getName()); - new CopyTempDatabaseFileTask(this, callback).execute(src, dst); - } + @Override + public void onError() { + // path not writable, copy the the file to temp directory, then merge and update schema on a copy if + // necessary + File dst = new File(FileSource.getInternalCachePath(context), src.getName()); + new CopyTempDatabaseFileTask(OfflineManager.this, callback).execute(src, dst); + } + }).execute(src); + } + + @Override + public void onError() { + // path not readable, abort + callback.onError("Secondary database needs to be located in a readable path."); + } + }).execute(src); } private static final class CopyTempDatabaseFileTask extends AsyncTask { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/FileUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/FileUtils.java new file mode 100644 index 00000000000..b7d09cda2a3 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/FileUtils.java @@ -0,0 +1,121 @@ +package com.mapbox.mapboxsdk.utils; + +import android.os.AsyncTask; + +import java.io.File; +import java.lang.ref.WeakReference; + +public class FileUtils { + + /** + * Task checking whether app's process can read a file. + */ + public static class CheckFileReadPermissionTask extends AsyncTask { + private final WeakReference listenerWeakReference; + + public CheckFileReadPermissionTask(OnCheckFileReadPermissionListener listener) { + this.listenerWeakReference = new WeakReference<>(listener); + } + + @Override + protected Boolean doInBackground(File... files) { + try { + return files[0].canRead(); + } catch (Exception ex) { + return false; + } + } + + @Override + protected void onCancelled() { + OnCheckFileReadPermissionListener listener = listenerWeakReference.get(); + if (listener != null) { + listener.onError(); + } + } + + @Override + protected void onPostExecute(Boolean result) { + OnCheckFileReadPermissionListener listener = listenerWeakReference.get(); + if (listener != null) { + if (result) { + listener.onReadPermissionGranted(); + } else { + listener.onError(); + } + } + } + } + + /** + * Interface definition for a callback invoked when checking file's read permissions. + */ + public interface OnCheckFileReadPermissionListener { + + /** + * Invoked when app's process has a permission to read a file. + */ + void onReadPermissionGranted(); + + /** + * Invoked when app's process doesn't have a permission to read a file or an error occurs. + */ + void onError(); + } + + /** + * Task checking whether app's process can write to a file. + */ + public static class CheckFileWritePermissionTask extends AsyncTask { + private final WeakReference listenerWeakReference; + + public CheckFileWritePermissionTask(OnCheckFileWritePermissionListener listener) { + this.listenerWeakReference = new WeakReference<>(listener); + } + + @Override + protected Boolean doInBackground(File... files) { + try { + return files[0].canWrite(); + } catch (Exception ex) { + return false; + } + } + + @Override + protected void onCancelled() { + OnCheckFileWritePermissionListener listener = listenerWeakReference.get(); + if (listener != null) { + listener.onError(); + } + } + + @Override + protected void onPostExecute(Boolean result) { + OnCheckFileWritePermissionListener listener = listenerWeakReference.get(); + if (listener != null) { + if (result) { + listener.onWritePermissionGranted(); + } else { + listener.onError(); + } + } + } + } + + /** + * Interface definition for a callback invoked when checking file's write permissions. + */ + public interface OnCheckFileWritePermissionListener { + + /** + * Invoked when app's process has a permission to write to a file. + */ + void onWritePermissionGranted(); + + /** + * Invoked when app's process doesn't have a permission to write to a file or an error occurs. + */ + void onError(); + } +}