From 734b217cda0603cb9ea8303b5d719616e2f18155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Paczos?= Date: Tue, 19 Feb 2019 13:23:49 +0100 Subject: [android] when changing the resource path, recreate database instead of the whole FileSource --- .../mapbox/mapboxsdk/offline/OfflineManager.java | 23 ++++------- .../com/mapbox/mapboxsdk/storage/FileSource.java | 44 ++++++++++++---------- .../offline/ChangeResourcesCachePathActivity.kt | 37 +++++++++++++----- platform/android/src/file_source.cpp | 12 +++++- platform/android/src/file_source.hpp | 3 ++ 5 files changed, 72 insertions(+), 47 deletions(-) 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 0d85be18a5..01ac098d16 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 @@ -8,7 +8,6 @@ import android.os.Looper; import android.support.annotation.Keep; import android.support.annotation.NonNull; -import android.support.annotation.RestrictTo; import com.mapbox.mapboxsdk.LibraryLoader; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.R; @@ -134,14 +133,6 @@ public class OfflineManager { deleteAmbientDatabase(this.context); } - /** - * Clears the current instance of the offline manager. - */ - @RestrictTo(RestrictTo.Scope.LIBRARY) - public static void clear() { - instance = null; - } - private void deleteAmbientDatabase(final Context context) { final String path = FileSource.getInternalCachePath(context) + File.separator + "mbgl-cache.db"; FileUtils.deleteFile(path); @@ -461,17 +452,17 @@ public class OfflineManager { * resource were requested in the process of map rendering. * Use this method to pre-warm the cache with resources you know * will be requested. - * + *

* This call is asynchronous: the data may not be immediately available * for in-progress requests, although subsequent requests should have * access to the cached data. * - * @param url The URL of the resource to insert - * @param data Response data to store for this resource. Data is expected to be uncompressed; - * internally, the cache will compress data as necessary. - * @param modified Optional "modified" response header, in seconds since 1970, or 0 if not set - * @param expires Optional "expires" response header, in seconds since 1970, or 0 if not set - * @param etag Optional "entity tag" response header + * @param url The URL of the resource to insert + * @param data Response data to store for this resource. Data is expected to be uncompressed; + * internally, the cache will compress data as necessary. + * @param modified Optional "modified" response header, in seconds since 1970, or 0 if not set + * @param expires Optional "expires" response header, in seconds since 1970, or 0 if not set + * @param etag Optional "entity tag" response header * @param mustRevalidate Indicates whether response can be used after it's stale */ @Keep diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java index 8df527657c..75763aa828 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java @@ -13,11 +13,11 @@ import android.support.annotation.Keep; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; + import com.mapbox.mapboxsdk.MapStrictMode; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.log.Logger; -import com.mapbox.mapboxsdk.offline.OfflineManager; import com.mapbox.mapboxsdk.utils.ThreadUtils; import java.io.File; @@ -117,7 +117,7 @@ public class FileSource { // Reset stored cache path SharedPreferences.Editor editor = - context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit(); + context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit(); editor.remove(MAPBOX_SHARED_PREFERENCE_RESOURCES_CACHE_PATH).apply(); } @@ -148,11 +148,11 @@ public class FileSource { try { // Try getting a custom value from the app Manifest ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), - PackageManager.GET_META_DATA); + PackageManager.GET_META_DATA); if (appInfo.metaData != null) { isExternalStorageConfiguration = appInfo.metaData.getBoolean( - MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL, - MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL + MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL, + MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL ); } } catch (PackageManager.NameNotFoundException exception) { @@ -182,8 +182,8 @@ public class FileSource { } Logger.w(TAG, "External storage was requested but it isn't readable. For API level < 18" - + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE" - + " permissions in your app Manifest (defaulting to internal storage)."); + + " make sure you've requested READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE" + + " permissions in your app Manifest (defaulting to internal storage)."); return false; } @@ -212,9 +212,9 @@ public class FileSource { @NonNull @Override protected String[] doInBackground(Context... contexts) { - return new String[]{ - getCachePath(contexts[0]), - contexts[0].getCacheDir().getAbsolutePath() + return new String[] { + getCachePath(contexts[0]), + contexts[0].getCacheDir().getAbsolutePath() }; } @@ -297,7 +297,7 @@ public class FileSource { message = null; final SharedPreferences.Editor editor = - context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit(); + context.getSharedPreferences(MAPBOX_SHARED_PREFERENCES, Context.MODE_PRIVATE).edit(); if (!editor.putString(MAPBOX_SHARED_PREFERENCE_RESOURCES_CACHE_PATH, path).commit()) { Logger.w(TAG, "Cannot store cache path in shared preferences."); } @@ -305,8 +305,15 @@ public class FileSource { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { - setResourcesCachePath(context, path); - callback.onSuccess(path); + if (getInstance(context).isActivated()) { + final String activatedMessage = "Cannot set path, file source is activated!"; + Logger.w(TAG, activatedMessage); + callback.onError(activatedMessage); + editor.remove(MAPBOX_SHARED_PREFERENCE_RESOURCES_CACHE_PATH).apply(); + } else { + setResourcesCachePath(context, path); + callback.onSuccess(path); + } } }); } @@ -332,8 +339,8 @@ public class FileSource { private static void setResourcesCachePath(@NonNull Context context, @NonNull String path) { resourcesCachePathLoaderLock.lock(); resourcesCachePath = path; - reinitializeOfflineManager(context); resourcesCachePathLoaderLock.unlock(); + getInstance(context).setResourceCachePath(path); } private static boolean isPathWritable(String path) { @@ -343,12 +350,6 @@ public class FileSource { return new File(path).canWrite(); } - private static void reinitializeOfflineManager(@NonNull Context context) { - final FileSource fileSource = FileSource.getInstance(context); - fileSource.initialize(Mapbox.getAccessToken(), resourcesCachePath, context.getResources().getAssets()); - OfflineManager.clear(); - } - private static void lockPathLoaders() { internalCachePathLoaderLock.lock(); resourcesCachePathLoaderLock.lock(); @@ -396,6 +397,9 @@ public class FileSource { @Keep public native void setResourceTransform(final ResourceTransformCallback callback); + @Keep + private native void setResourceCachePath(String path); + @Keep private native void initialize(String accessToken, String cachePath, AssetManager assetManager); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/ChangeResourcesCachePathActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/ChangeResourcesCachePathActivity.kt index 2c429e829d..f2f4eb26c3 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/ChangeResourcesCachePathActivity.kt +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/ChangeResourcesCachePathActivity.kt @@ -12,27 +12,36 @@ import android.widget.AdapterView import android.widget.BaseAdapter import android.widget.TextView import android.widget.Toast +import com.mapbox.mapboxsdk.log.Logger +import com.mapbox.mapboxsdk.offline.OfflineManager +import com.mapbox.mapboxsdk.offline.OfflineRegion import com.mapbox.mapboxsdk.storage.FileSource import com.mapbox.mapboxsdk.testapp.R import kotlinx.android.synthetic.main.activity_change_resources_cache_path.* import java.io.File class ChangeResourcesCachePathActivity : AppCompatActivity(), - AdapterView.OnItemClickListener, - FileSource.SetResourcesCachePathCallback { + AdapterView.OnItemClickListener, + FileSource.SetResourcesCachePathCallback { + + companion object { + private const val TAG = "Mbgl-ChangeResourcesCachePathActivity" + } lateinit var adapter: PathAdapter + private lateinit var offlineManager: OfflineManager + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_change_resources_cache_path) - Thread(Runnable { - adapter = PathAdapter(this, obtainFilesPaths(this)) - listView.adapter = adapter - listView.emptyView = empty - listView.onItemClickListener = this - }).start() + adapter = PathAdapter(this, obtainFilesPaths(this)) + listView.adapter = adapter + listView.emptyView = empty + listView.onItemClickListener = this + + offlineManager = OfflineManager.getInstance(this) } override fun onStart() { @@ -55,6 +64,16 @@ class ChangeResourcesCachePathActivity : AppCompatActivity(), override fun onSuccess(path: String?) { listView.onItemClickListener = this Toast.makeText(this, "New path: $path", Toast.LENGTH_LONG).show() + + offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback { + override fun onList(offlineRegions: Array?) { + Logger.i(TAG, "Number of saved offline regions in the new path: ${offlineRegions?.size.toString()}") + } + + override fun onError(error: String?) { + Logger.e(TAG, error) + } + }) } private fun obtainFilesPaths(context: Context): List { @@ -71,7 +90,7 @@ class ChangeResourcesCachePathActivity : AppCompatActivity(), private fun obtainExternalFilesPathsLegacy(context: Context): List { val postFix = - "${File.separator}Android${File.separator}data${File.separator}${context.packageName}${File.separator}files" + "${File.separator}Android${File.separator}data${File.separator}${context.packageName}${File.separator}files" val paths = ArrayList() val externalStorage = System.getenv("EXTERNAL_STORAGE") val secondaryStorage = System.getenv("SECONDARY_STORAGE") diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index daddd0b9cd..4cfb545b84 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -19,11 +19,12 @@ FileSource::FileSource(jni::JNIEnv& _env, const jni::String& accessToken, const jni::String& _cachePath, const jni::Object& assetManager) { - mapbox::sqlite::setTempPath(jni::Make(_env, _cachePath)); + std::string path = jni::Make(_env, _cachePath); + mapbox::sqlite::setTempPath(path); // Create a core default file source fileSource = std::make_unique( - jni::Make(_env, _cachePath) + "/mbgl-offline.db", + path + DATABASE_FILE, std::make_unique(_env, assetManager)); // Set access token @@ -69,6 +70,12 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, const jni::Object(env, path); + mapbox::sqlite::setTempPath(newPath); + fileSource->setResourceCachePath(newPath + DATABASE_FILE); +} + void FileSource::resume(jni::JNIEnv&) { if (!activationCounter) { activationCounter = optional(1) ; @@ -129,6 +136,7 @@ void FileSource::registerNative(jni::JNIEnv& env) { METHOD(&FileSource::setAccessToken, "setAccessToken"), METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"), METHOD(&FileSource::setResourceTransform, "setResourceTransform"), + METHOD(&FileSource::setResourceCachePath, "setResourceCachePath"), METHOD(&FileSource::resume, "activate"), METHOD(&FileSource::pause, "deactivate"), METHOD(&FileSource::isResumed, "isActivated") diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index 572ac647b7..575702120e 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -39,6 +39,8 @@ public: void setResourceTransform(jni::JNIEnv&, const jni::Object&); + void setResourceCachePath(jni::JNIEnv&, const jni::String&); + void resume(jni::JNIEnv&); void pause(jni::JNIEnv&); @@ -52,6 +54,7 @@ public: static void registerNative(jni::JNIEnv&); private: + const std::string DATABASE_FILE = "/mbgl-offline.db"; optional activationCounter; std::unique_ptr> resourceTransform; std::unique_ptr fileSource; -- cgit v1.2.1