[android] Introduce a getDatabasePath() method that enables switching storage paths

Fixes #5589
This commit is contained in:
Antonio Zugaldia
2016-07-15 09:58:31 -04:00
parent 244700e560
commit 5c037f4745
4 changed files with 79 additions and 2 deletions

View File

@@ -30,6 +30,16 @@ public class MapboxConstants {
*/
public static final String KEY_META_DATA_STAGING_ACCESS_TOKEN = "com.mapbox.TestEventsAccessToken";
/**
* Key used to switch storage to external in AndroidManifest.xml
*/
public final static String KEY_META_DATA_SET_STORAGE_EXTERNAL = "com.mapbox.SetStorageExternal";
/**
* Default value for KEY_META_DATA_SET_STORAGE_EXTERNAL (default is internal storage)
*/
public final static boolean DEFAULT_SET_STORAGE_EXTERNAL = false;
/**
* Default animation time
*/

View File

@@ -15,6 +15,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.layers.CustomLayer;
import com.mapbox.mapboxsdk.offline.OfflineManager;
import java.util.List;
@@ -51,7 +52,7 @@ final class NativeMapView {
public NativeMapView(MapView mapView) {
Context context = mapView.getContext();
String dataPath = context.getFilesDir().getAbsolutePath();
String dataPath = OfflineManager.getDatabasePath(context);
// With the availability of offline, we're unifying the ambient (cache) and the offline
// databases to be in the same folder, outside cache, to avoid automatic deletion from

View File

@@ -1,11 +1,17 @@
package com.mapbox.mapboxsdk.offline;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.util.Log;
import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import java.io.File;
/**
@@ -88,7 +94,7 @@ public class OfflineManager {
private OfflineManager(Context context) {
// Get a pointer to the DefaultFileSource instance
String assetRoot = context.getFilesDir().getAbsolutePath();
String assetRoot = getDatabasePath(context);
String cachePath = assetRoot + File.separator + DATABASE_NAME;
mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE);
@@ -100,6 +106,61 @@ public class OfflineManager {
deleteAmbientDatabase(context);
}
public static String getDatabasePath(Context context) {
// Default value
boolean setStorageExternal = MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL;
try {
// Try getting a custom value from the app Manifest
ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(
context.getPackageName(), PackageManager.GET_META_DATA);
setStorageExternal = appInfo.metaData.getBoolean(
MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL,
MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL);
} catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Failed to read the package metadata: " + e.getMessage());
} catch (Exception e) {
Log.e(LOG_TAG, "Failed to read the storage key: " + e.getMessage());
}
String databasePath = null;
if (setStorageExternal && isExternalStorageReadable()) {
try {
// Try getting the external storage path
databasePath = context.getExternalFilesDir(null).getAbsolutePath();
} catch (NullPointerException e) {
Log.e(LOG_TAG, "Failed to obtain the external storage path: " + e.getMessage());
}
}
if (databasePath == null) {
// Default to internal storage
databasePath = context.getFilesDir().getAbsolutePath();
}
return databasePath;
}
/**
* Checks if external storage is available to at least read. In order for this to work, make
* sure you include <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
* (or WRITE_EXTERNAL_STORAGE) for API level < 18 in your app Manifest.
*
* Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
*/
public static boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
Log.w(LOG_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).");
return false;
}
private void deleteAmbientDatabase(final Context context) {
// Delete the file in a separate thread to avoid affecting the UI
new Thread(new Runnable() {