[android] jni high level binding refactor
This commit is contained in:
committed by
Ivo van Dongen
parent
7d9018093a
commit
465c949153
@@ -30,6 +30,8 @@ public class Marker extends Annotation {
|
||||
private LatLng position;
|
||||
private String snippet;
|
||||
private Icon icon;
|
||||
//Redundantly stored for JNI access
|
||||
private String iconId;
|
||||
private String title;
|
||||
|
||||
private InfoWindow infoWindow;
|
||||
@@ -51,24 +53,19 @@ public class Marker extends Annotation {
|
||||
* @param baseMarkerOptions The builder used to construct the Marker.
|
||||
*/
|
||||
public Marker(BaseMarkerOptions baseMarkerOptions) {
|
||||
position = baseMarkerOptions.position;
|
||||
snippet = baseMarkerOptions.snippet;
|
||||
icon = baseMarkerOptions.icon;
|
||||
title = baseMarkerOptions.title;
|
||||
this(baseMarkerOptions.position, baseMarkerOptions.icon, baseMarkerOptions.title, baseMarkerOptions.snippet);
|
||||
}
|
||||
|
||||
Marker(BaseMarkerViewOptions baseMarkerViewOptions) {
|
||||
position = baseMarkerViewOptions.position;
|
||||
snippet = baseMarkerViewOptions.snippet;
|
||||
icon = baseMarkerViewOptions.icon;
|
||||
title = baseMarkerViewOptions.title;
|
||||
this(baseMarkerViewOptions.position, baseMarkerViewOptions.icon,
|
||||
baseMarkerViewOptions.title, baseMarkerViewOptions.snippet);
|
||||
}
|
||||
|
||||
Marker(LatLng position, Icon icon, String title, String snippet) {
|
||||
this.position = position;
|
||||
this.icon = icon;
|
||||
this.title = title;
|
||||
this.snippet = snippet;
|
||||
setIcon(icon);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +145,7 @@ public class Marker extends Annotation {
|
||||
*/
|
||||
public void setIcon(@Nullable Icon icon) {
|
||||
this.icon = icon;
|
||||
this.iconId = icon != null ? icon.getId() : null;
|
||||
MapboxMap map = getMapboxMap();
|
||||
if (map != null) {
|
||||
map.updateMarker(this);
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -203,8 +202,6 @@ public class MapView extends FrameLayout {
|
||||
*/
|
||||
@UiThread
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
nativeMapView.setAccessToken(Mapbox.getAccessToken());
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
MapboxTelemetry.getInstance().pushEvent(MapboxEvent.buildMapLoadEvent());
|
||||
} else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
|
||||
@@ -409,11 +406,6 @@ public class MapView extends FrameLayout {
|
||||
return;
|
||||
}
|
||||
|
||||
// stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242
|
||||
if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
|
||||
nativeMapView.setAccessToken(Mapbox.getAccessToken());
|
||||
}
|
||||
|
||||
nativeMapView.setStyleUrl(url);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.annotations.Annotation;
|
||||
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
|
||||
import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
|
||||
@@ -866,10 +865,6 @@ public final class MapboxMap {
|
||||
private void setStyleUrl(@NonNull MapboxMapOptions options) {
|
||||
String style = options.getStyle();
|
||||
if (!TextUtils.isEmpty(style)) {
|
||||
// stopgap for https://github.com/mapbox/mapbox-gl-native/issues/6242
|
||||
if (TextUtils.isEmpty(nativeMapView.getAccessToken())) {
|
||||
nativeMapView.setAccessToken(Mapbox.getAccessToken());
|
||||
}
|
||||
setStyleUrl(style);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,11 @@
|
||||
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 com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.constants.MapboxConstants;
|
||||
import com.mapbox.mapboxsdk.storage.Resource;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -30,11 +25,13 @@ public class OfflineManager {
|
||||
System.loadLibrary("mapbox-gl");
|
||||
}
|
||||
|
||||
// Default database name
|
||||
private static final String DATABASE_NAME = "mbgl-offline.db";
|
||||
|
||||
// Holds the pointer to JNI DefaultFileSource
|
||||
private long mDefaultFileSourcePtr = 0;
|
||||
// Native peer pointer
|
||||
private long nativePtr;
|
||||
|
||||
// Reference to the file source to keep it alive for the
|
||||
// lifetime of this object
|
||||
private final FileSource fileSource;
|
||||
|
||||
// Makes sure callbacks come back to the main thread
|
||||
private Handler handler;
|
||||
@@ -82,94 +79,17 @@ public class OfflineManager {
|
||||
void onError(String error);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback allows implementors to transform URLs before they are requested
|
||||
* from the internet. This can be used add or remove custom parameters, or reroute
|
||||
* certain requests to other servers or endpoints.
|
||||
*/
|
||||
public interface ResourceTransformCallback {
|
||||
/**
|
||||
* Called whenever a URL needs to be transformed.
|
||||
*
|
||||
* @param kind The kind of URL to be transformed.
|
||||
* @param offlineRegions The original URL to be transformed.
|
||||
* @return A URL that will now be downloaded.
|
||||
*/
|
||||
String onURL(@Resource.Kind int kind, String url);
|
||||
}
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
* Constructor
|
||||
*/
|
||||
private OfflineManager(Context context) {
|
||||
// Get a pointer to the DefaultFileSource instance
|
||||
String cachePath = getDatabasePath(context) + File.separator + DATABASE_NAME;
|
||||
String apkPath = context.getPackageCodePath();
|
||||
mDefaultFileSourcePtr = sharedDefaultFileSource(cachePath, apkPath);
|
||||
setAccessToken(mDefaultFileSourcePtr, Mapbox.getAccessToken());
|
||||
this.fileSource = FileSource.getInstance(context);
|
||||
initialize(fileSource);
|
||||
|
||||
// Delete any existing previous ambient cache database
|
||||
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 exception) {
|
||||
Timber.e("Failed to read the package metadata: ", exception);
|
||||
} catch (Exception exception) {
|
||||
Timber.e("Failed to read the storage key: ", exception);
|
||||
}
|
||||
|
||||
String databasePath = null;
|
||||
if (setStorageExternal && isExternalStorageReadable()) {
|
||||
try {
|
||||
// Try getting the external storage path
|
||||
databasePath = context.getExternalFilesDir(null).getAbsolutePath();
|
||||
} catch (NullPointerException exception) {
|
||||
Timber.e("Failed to obtain the external storage path: ", exception);
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
|
||||
* </p>
|
||||
*
|
||||
* @return true if external storage is readable
|
||||
*/
|
||||
public static boolean isExternalStorageReadable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Timber.w("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() {
|
||||
@@ -215,7 +135,8 @@ public class OfflineManager {
|
||||
* @param callback the callback to be invoked
|
||||
*/
|
||||
public void listOfflineRegions(@NonNull final ListOfflineRegionsCallback callback) {
|
||||
listOfflineRegions(mDefaultFileSourcePtr, new ListOfflineRegionsCallback() {
|
||||
listOfflineRegions(fileSource, new ListOfflineRegionsCallback() {
|
||||
|
||||
@Override
|
||||
public void onList(final OfflineRegion[] offlineRegions) {
|
||||
getHandler().post(new Runnable() {
|
||||
@@ -259,7 +180,8 @@ public class OfflineManager {
|
||||
@NonNull byte[] metadata,
|
||||
@NonNull final CreateOfflineRegionCallback callback) {
|
||||
|
||||
createOfflineRegion(mDefaultFileSourcePtr, definition, metadata, new CreateOfflineRegionCallback() {
|
||||
createOfflineRegion(fileSource, definition, metadata, new CreateOfflineRegionCallback() {
|
||||
|
||||
@Override
|
||||
public void onCreate(final OfflineRegion offlineRegion) {
|
||||
getHandler().post(new Runnable() {
|
||||
@@ -282,48 +204,20 @@ public class OfflineManager {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a callback for transforming URLs requested from the internet
|
||||
* <p>
|
||||
* The callback will be executed on the main thread once for every requested URL.
|
||||
* </p>
|
||||
*
|
||||
* @param callback the callback to be invoked
|
||||
*/
|
||||
public void setResourceTransform(@NonNull final ResourceTransformCallback callback) {
|
||||
setResourceTransform(mDefaultFileSourcePtr, callback);
|
||||
}
|
||||
|
||||
/*
|
||||
* Changing or bypassing this limit without permission from Mapbox is prohibited
|
||||
* by the Mapbox Terms of Service.
|
||||
*/
|
||||
public void setOfflineMapboxTileCountLimit(long limit) {
|
||||
setOfflineMapboxTileCountLimit(mDefaultFileSourcePtr, limit);
|
||||
}
|
||||
public native void setOfflineMapboxTileCountLimit(long limit);
|
||||
|
||||
private native void initialize(FileSource fileSource);
|
||||
|
||||
/*
|
||||
* Native methods
|
||||
*/
|
||||
private native long sharedDefaultFileSource(
|
||||
String cachePath, String assetRoot);
|
||||
@Override
|
||||
protected native void finalize() throws Throwable;
|
||||
|
||||
private native void setAccessToken(long defaultFileSourcePtr, String accessToken);
|
||||
private native void listOfflineRegions(FileSource fileSource, ListOfflineRegionsCallback callback);
|
||||
|
||||
private native String getAccessToken(long defaultFileSourcePtr);
|
||||
|
||||
private native void listOfflineRegions(
|
||||
long defaultFileSourcePtr, ListOfflineRegionsCallback callback);
|
||||
|
||||
private native void createOfflineRegion(
|
||||
long defaultFileSourcePtr, OfflineRegionDefinition definition,
|
||||
byte[] metadata, CreateOfflineRegionCallback callback);
|
||||
|
||||
private native void setResourceTransform(
|
||||
long defaultFileSourcePtr, ResourceTransformCallback callback);
|
||||
|
||||
private native void setOfflineMapboxTileCountLimit(
|
||||
long defaultFileSourcePtr, long limit);
|
||||
private native void createOfflineRegion(FileSource fileSource, OfflineRegionDefinition definition,
|
||||
byte[] metadata, CreateOfflineRegionCallback callback);
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.os.Looper;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import timber.log.Timber;
|
||||
import com.mapbox.mapboxsdk.storage.FileSource;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -25,22 +25,25 @@ public class OfflineRegion {
|
||||
System.loadLibrary("mapbox-gl");
|
||||
}
|
||||
|
||||
// Parent OfflineManager
|
||||
private OfflineManager offlineManager;
|
||||
|
||||
// Members
|
||||
private long mId = 0;
|
||||
private OfflineRegionDefinition mDefinition = null;
|
||||
|
||||
// Holds the pointer to JNI OfflineRegion
|
||||
private long nativePtr;
|
||||
|
||||
// Holds a reference to the FileSource to keep it alive
|
||||
private FileSource fileSource;
|
||||
|
||||
//Region id
|
||||
private long id;
|
||||
|
||||
private OfflineRegionDefinition definition;
|
||||
|
||||
/**
|
||||
* Arbitrary binary region metadata. The contents are opaque to the SDK implementation;
|
||||
* it just stores and retrieves a byte[]. Check the `OfflineActivity` in the TestApp
|
||||
* for a sample implementation that uses JSON to store an offline region name.
|
||||
*/
|
||||
private byte[] mMetadata = null;
|
||||
|
||||
// Holds the pointer to JNI OfflineRegion
|
||||
private long mOfflineRegionPtr = 0;
|
||||
private byte[] metadata;
|
||||
|
||||
// Makes sure callbacks come back to the main thread
|
||||
private Handler handler;
|
||||
@@ -197,19 +200,22 @@ public class OfflineRegion {
|
||||
if (state == STATE_ACTIVE) {
|
||||
return true;
|
||||
}
|
||||
if (isDeliveringInactiveMessages()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return isDeliveringInactiveMessages();
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* For JNI use only, to create a new offline region, use
|
||||
* {@link OfflineManager#createOfflineRegion} instead.
|
||||
*/
|
||||
|
||||
private OfflineRegion() {
|
||||
// For JNI use only, to create a new offline region, use
|
||||
// OfflineManager.createOfflineRegion() instead.
|
||||
private OfflineRegion(long offlineRegionPtr, FileSource fileSource, long id,
|
||||
OfflineRegionDefinition definition, byte[] metadata) {
|
||||
this.fileSource = fileSource;
|
||||
this.id = id;
|
||||
this.definition = definition;
|
||||
this.metadata = metadata;
|
||||
initialize(offlineRegionPtr, fileSource);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -217,15 +223,15 @@ public class OfflineRegion {
|
||||
*/
|
||||
|
||||
public long getID() {
|
||||
return mId;
|
||||
return id;
|
||||
}
|
||||
|
||||
public OfflineRegionDefinition getDefinition() {
|
||||
return mDefinition;
|
||||
return definition;
|
||||
}
|
||||
|
||||
public byte[] getMetadata() {
|
||||
return mMetadata;
|
||||
return metadata;
|
||||
}
|
||||
|
||||
private Handler getHandler() {
|
||||
@@ -383,7 +389,7 @@ public class OfflineRegion {
|
||||
getHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMetadata = metadata;
|
||||
OfflineRegion.this.metadata = metadata;
|
||||
callback.onUpdate(metadata);
|
||||
}
|
||||
});
|
||||
@@ -401,33 +407,18 @@ public class OfflineRegion {
|
||||
});
|
||||
}
|
||||
|
||||
private native void initialize(long offlineRegionPtr, FileSource fileSource);
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
try {
|
||||
super.finalize();
|
||||
destroyOfflineRegion();
|
||||
} catch (Throwable throwable) {
|
||||
Timber.e("Failed to finalize OfflineRegion: " + throwable.getMessage());
|
||||
}
|
||||
}
|
||||
protected native void finalize();
|
||||
|
||||
/*
|
||||
* Native methods
|
||||
*/
|
||||
private native void setOfflineRegionObserver(OfflineRegionObserver callback);
|
||||
|
||||
private native void destroyOfflineRegion();
|
||||
private native void setOfflineRegionDownloadState(@DownloadState int offlineRegionDownloadState);
|
||||
|
||||
private native void setOfflineRegionObserver(
|
||||
OfflineRegionObserver observerCallback);
|
||||
private native void getOfflineRegionStatus(OfflineRegionStatusCallback callback);
|
||||
|
||||
private native void setOfflineRegionDownloadState(
|
||||
@DownloadState int offlineRegionDownloadState);
|
||||
|
||||
private native void getOfflineRegionStatus(
|
||||
OfflineRegionStatusCallback statusCallback);
|
||||
|
||||
private native void deleteOfflineRegion(
|
||||
OfflineRegionDeleteCallback deleteCallback);
|
||||
private native void deleteOfflineRegion(OfflineRegionDeleteCallback callback);
|
||||
|
||||
private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback);
|
||||
|
||||
|
||||
@@ -25,25 +25,23 @@ public class OfflineRegionError {
|
||||
public static final String REASON_OTHER = "REASON_OTHER";
|
||||
|
||||
@ErrorReason
|
||||
private String reason;
|
||||
private final String reason;
|
||||
|
||||
/**
|
||||
* /* An error message from the request handler, e.g. a server message or a system message
|
||||
* /* informing the user about the reason for the failure.
|
||||
*/
|
||||
private String message;
|
||||
private final String message;
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
// Constructors
|
||||
|
||||
private OfflineRegionError() {
|
||||
private OfflineRegionError(String reason, String message) {
|
||||
// For JNI use only
|
||||
this.reason = reason;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
// Getters
|
||||
|
||||
@ErrorReason
|
||||
public String getReason() {
|
||||
|
||||
@@ -56,24 +56,29 @@ public class OfflineRegionStatus {
|
||||
|
||||
/*
|
||||
* Use setObserver(OfflineRegionObserver observer) to obtain a OfflineRegionStatus object.
|
||||
*
|
||||
* For JNI use only
|
||||
*/
|
||||
|
||||
private OfflineRegionStatus() {
|
||||
// For JNI use only
|
||||
private OfflineRegionStatus(int downloadState, long completedResourceCount,
|
||||
long completedResourceSize, long completedTileCount,
|
||||
long completedTileSize, long requiredResourceCount,
|
||||
boolean requiredResourceCountIsPrecise) {
|
||||
this.downloadState = downloadState;
|
||||
this.completedResourceCount = completedResourceCount;
|
||||
this.completedResourceSize = completedResourceSize;
|
||||
this.completedTileCount = completedTileCount;
|
||||
this.completedTileSize = completedTileSize;
|
||||
this.requiredResourceCount = requiredResourceCount;
|
||||
this.requiredResourceCountIsPrecise = requiredResourceCountIsPrecise;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Is the region complete?
|
||||
*/
|
||||
|
||||
public boolean isComplete() {
|
||||
return (completedResourceCount == requiredResourceCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Getters
|
||||
*/
|
||||
|
||||
@OfflineRegion.DownloadState
|
||||
public int getDownloadState() {
|
||||
return downloadState;
|
||||
|
||||
@@ -21,16 +21,18 @@ public class OfflineTilePyramidRegionDefinition implements OfflineRegionDefiniti
|
||||
private double maxZoom;
|
||||
private float pixelRatio;
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param styleURL the style
|
||||
* @param bounds the bounds
|
||||
* @param minZoom min zoom
|
||||
* @param maxZoom max zoom
|
||||
* @param pixelRatio pixel ratio of the device
|
||||
*/
|
||||
|
||||
private OfflineTilePyramidRegionDefinition() {
|
||||
// For JNI use only
|
||||
}
|
||||
|
||||
public OfflineTilePyramidRegionDefinition(
|
||||
String styleURL, LatLngBounds bounds, double minZoom, double maxZoom, float pixelRatio) {
|
||||
// Note: Also used in JNI
|
||||
this.styleURL = styleURL;
|
||||
this.bounds = bounds;
|
||||
this.minZoom = minZoom;
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
package com.mapbox.mapboxsdk.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.constants.MapboxConstants;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
/**
|
||||
* Holds a central reference to the core's DefaultFileSource for as long as
|
||||
* there are active mapviews / offline managers
|
||||
*/
|
||||
public class FileSource {
|
||||
|
||||
/**
|
||||
* This callback allows implementors to transform URLs before they are requested
|
||||
* from the internet. This can be used add or remove custom parameters, or reroute
|
||||
* certain requests to other servers or endpoints.
|
||||
*/
|
||||
public interface ResourceTransformCallback {
|
||||
|
||||
/**
|
||||
* Called whenever a URL needs to be transformed.
|
||||
*
|
||||
* @param kind The kind of URL to be transformed.
|
||||
* @return A URL that will now be downloaded.
|
||||
*/
|
||||
String onURL(@Resource.Kind int kind, String url);
|
||||
|
||||
}
|
||||
|
||||
// Use weak reference to avoid blocking GC on this reference.
|
||||
// Should only block when mapview / Offline manager instances
|
||||
// are alive
|
||||
private static WeakReference<FileSource> INSTANCE;
|
||||
|
||||
public static synchronized FileSource getInstance(Context context) {
|
||||
if (INSTANCE == null || INSTANCE.get() == null) {
|
||||
String cachePath = getCachePath(context);
|
||||
String apkPath = context.getPackageCodePath();
|
||||
INSTANCE = new WeakReference<>(new FileSource(cachePath, apkPath));
|
||||
}
|
||||
|
||||
return INSTANCE.get();
|
||||
}
|
||||
|
||||
public static String getCachePath(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 exception) {
|
||||
Timber.e("Failed to read the package metadata: ", exception);
|
||||
} catch (Exception exception) {
|
||||
Timber.e("Failed to read the storage key: ", exception);
|
||||
}
|
||||
|
||||
String cachePath = null;
|
||||
if (setStorageExternal && isExternalStorageReadable()) {
|
||||
try {
|
||||
// Try getting the external storage path
|
||||
cachePath = context.getExternalFilesDir(null).getAbsolutePath();
|
||||
} catch (NullPointerException exception) {
|
||||
Timber.e("Failed to obtain the external storage path: ", exception);
|
||||
}
|
||||
}
|
||||
|
||||
if (cachePath == null) {
|
||||
// Default to internal storage
|
||||
cachePath = context.getFilesDir().getAbsolutePath();
|
||||
}
|
||||
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* Code from https://developer.android.com/guide/topics/data/data-storage.html#filesExternal
|
||||
* </p>
|
||||
*
|
||||
* @return true if external storage is readable
|
||||
*/
|
||||
public static boolean isExternalStorageReadable() {
|
||||
String state = Environment.getExternalStorageState();
|
||||
if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Timber.w("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 long nativePtr;
|
||||
|
||||
private FileSource(String cachePath, String apkPath) {
|
||||
initialize(Mapbox.getAccessToken(), cachePath, apkPath);
|
||||
}
|
||||
|
||||
public native void setAccessToken(@NonNull String accessToken);
|
||||
|
||||
public native String getAccessToken();
|
||||
|
||||
public native void setApiBaseUrl(String baseUrl);
|
||||
|
||||
/**
|
||||
* Sets a callback for transforming URLs requested from the internet
|
||||
* <p>
|
||||
* The callback will be executed on the main thread once for every requested URL.
|
||||
* </p>
|
||||
*
|
||||
* @param callback the callback to be invoked
|
||||
*/
|
||||
public native void setResourceTransform(@NonNull final ResourceTransformCallback callback);
|
||||
|
||||
private native void initialize(String accessToken, String cachePath, String apkPath);
|
||||
|
||||
@Override
|
||||
protected native void finalize() throws Throwable;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user