[android] - add binding integration for cache management API
This commit is contained in:
@@ -4,11 +4,10 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.AnyThread;
|
||||
import android.support.annotation.Keep;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import com.mapbox.mapboxsdk.LibraryLoader;
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.R;
|
||||
@@ -54,7 +53,7 @@ public class OfflineManager {
|
||||
private final FileSource fileSource;
|
||||
|
||||
// Makes sure callbacks come back to the main thread
|
||||
private Handler handler;
|
||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
// This object is implemented as a singleton
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
@@ -157,15 +156,6 @@ public class OfflineManager {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
private Handler getHandler() {
|
||||
if (handler == null) {
|
||||
handler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all regions in the offline database.
|
||||
* <p>
|
||||
@@ -181,7 +171,7 @@ public class OfflineManager {
|
||||
|
||||
@Override
|
||||
public void onList(final OfflineRegion[] offlineRegions) {
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
@@ -192,7 +182,7 @@ public class OfflineManager {
|
||||
|
||||
@Override
|
||||
public void onError(final String error) {
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
@@ -234,7 +224,7 @@ public class OfflineManager {
|
||||
public void run() {
|
||||
String errorMessage = null;
|
||||
if (src.canWrite()) {
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// path writable, merge and update schema in place if necessary
|
||||
@@ -246,7 +236,7 @@ public class OfflineManager {
|
||||
final File dst = new File(FileSource.getInternalCachePath(context), src.getName());
|
||||
try {
|
||||
copyTempDatabaseFile(src, dst);
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// merge and update schema using the copy
|
||||
@@ -264,7 +254,7 @@ public class OfflineManager {
|
||||
|
||||
if (errorMessage != null) {
|
||||
final String finalErrorMessage = errorMessage;
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onError(finalErrorMessage);
|
||||
@@ -275,6 +265,219 @@ public class OfflineManager {
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete existing database and re-initialize.
|
||||
* <p>
|
||||
* When the operation is complete or encounters an error, the given callback will be
|
||||
* executed on the database thread; it is the responsibility of the SDK bindings
|
||||
* to re-execute a user-provided callback on the main thread.
|
||||
* </p>
|
||||
*
|
||||
* @param callback the callback to be invoked when the database was reset or when the operation erred.
|
||||
*/
|
||||
public void resetDatabase(@Nullable final FileSourceCallback callback) {
|
||||
fileSource.activate();
|
||||
nativeResetDatabase(new FileSourceCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull final String message) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onError(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces revalidation of the ambient cache.
|
||||
* <p>
|
||||
* Forces Mapbox GL Native to revalidate resources stored in the ambient
|
||||
* cache with the tile server before using them, making sure they
|
||||
* are the latest version. This is more efficient than cleaning the
|
||||
* cache because if the resource is considered valid after the server
|
||||
* lookup, it will not get downloaded again.
|
||||
* <p>
|
||||
* Resources overlapping with offline regions will not be affected
|
||||
* by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param callback the callback to be invoked when the ambient cache was invalidated or when the operation erred.
|
||||
*/
|
||||
public void invalidateAmbientCache(@Nullable final FileSourceCallback callback) {
|
||||
fileSource.activate();
|
||||
nativeInvalidateAmbientCache(new FileSourceCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull final String message) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onError(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase resources from the ambient cache, freeing storage space.
|
||||
* <p>
|
||||
* Erases the ambient cache, freeing resources. This operation can be
|
||||
* potentially slow because it will trigger a VACUUM on SQLite,
|
||||
* forcing the database to move pages on the filesystem.
|
||||
* </p>
|
||||
* <p>
|
||||
* Resources overlapping with offline regions will not be affected
|
||||
* by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param callback the callback to be invoked when the ambient cache was cleared or when the operation erred.
|
||||
*/
|
||||
public void clearAmbientCache(@Nullable final FileSourceCallback callback) {
|
||||
fileSource.activate();
|
||||
nativeClearAmbientCache(new FileSourceCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull final String message) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onError(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum size in bytes for the ambient cache.
|
||||
* <p>
|
||||
* This call is potentially expensive because it will try
|
||||
* to trim the data in case the database is larger than the
|
||||
* size defined. The size of offline regions are not affected
|
||||
* by this settings, but the ambient cache will always try
|
||||
* to not exceed the maximum size defined, taking into account
|
||||
* the current size for the offline regions.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that if you use the SDK's offline functionality, your ability to set the ambient cache size will be limited.
|
||||
* Space that offline regions take up detract from the space available for ambient caching, and the ambient cache
|
||||
* size does not block offline downloads. For example: if the maximum cache size is set to 50 MB and 40 MB are
|
||||
* already used by offline regions, the ambient cache size will effectively be 10 MB.
|
||||
* </p>
|
||||
* <p>
|
||||
* Setting the size to 0 will disable the cache if there is no
|
||||
* offline region on the database.
|
||||
* </p>
|
||||
* <[
|
||||
* <p>
|
||||
* This method should always be called at the start of an app, before setting the style and loading a map.
|
||||
* Otherwise, the map will instantiate with the default cache size of 50 MB.
|
||||
* </p>
|
||||
*
|
||||
* @param size the maximum size of the ambient cache
|
||||
* @param callback the callback to be invoked when the the maximum size has been set or when the operation erred.
|
||||
*/
|
||||
public void setMaximumAmbientCacheSize(long size, @Nullable final FileSourceCallback callback) {
|
||||
fileSource.activate();
|
||||
nativeSetMaximumAmbientCacheSize(size, new FileSourceCallback() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onSuccess();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull final String message) {
|
||||
fileSource.activate();
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onError(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback receives an asynchronous response indicating if an operation has succeeded or failed.
|
||||
*/
|
||||
@Keep
|
||||
public interface FileSourceCallback {
|
||||
|
||||
/**
|
||||
* Receives the success of an operation
|
||||
*/
|
||||
void onSuccess();
|
||||
|
||||
/**
|
||||
* Receives an error message if an operation was not successful
|
||||
*
|
||||
* @param message the error message
|
||||
*/
|
||||
void onError(@NonNull String message);
|
||||
|
||||
}
|
||||
|
||||
private static void copyTempDatabaseFile(@NonNull File sourceFile, File destFile) throws IOException {
|
||||
if (!destFile.exists() && !destFile.createNewFile()) {
|
||||
throw new IOException("Unable to copy database file for merge.");
|
||||
@@ -308,7 +511,7 @@ public class OfflineManager {
|
||||
if (isTemporaryFile) {
|
||||
file.delete();
|
||||
}
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
@@ -322,7 +525,7 @@ public class OfflineManager {
|
||||
if (isTemporaryFile) {
|
||||
file.delete();
|
||||
}
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
@@ -365,7 +568,7 @@ public class OfflineManager {
|
||||
|
||||
@Override
|
||||
public void onCreate(final OfflineRegion offlineRegion) {
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConnectivityReceiver.instance(context).deactivate();
|
||||
@@ -377,7 +580,7 @@ public class OfflineManager {
|
||||
|
||||
@Override
|
||||
public void onError(final String error) {
|
||||
getHandler().post(new Runnable() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConnectivityReceiver.instance(context).deactivate();
|
||||
@@ -431,6 +634,18 @@ public class OfflineManager {
|
||||
@Keep
|
||||
private native void mergeOfflineRegions(FileSource fileSource, String path, MergeOfflineRegionsCallback callback);
|
||||
|
||||
@Keep
|
||||
private native void nativeResetDatabase(@Nullable FileSourceCallback callback);
|
||||
|
||||
@Keep
|
||||
private native void nativeInvalidateAmbientCache(@Nullable FileSourceCallback callback);
|
||||
|
||||
@Keep
|
||||
private native void nativeClearAmbientCache(@Nullable FileSourceCallback callback);
|
||||
|
||||
@Keep
|
||||
private native void nativeSetMaximumAmbientCacheSize(long size, @Nullable FileSourceCallback callback);
|
||||
|
||||
/**
|
||||
* Insert the provided resource into the ambient cache
|
||||
* This method mimics the caching that would take place if the equivalent
|
||||
|
||||
@@ -7,7 +7,6 @@ import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Keep;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.mapbox.mapboxsdk.LibraryLoader;
|
||||
import com.mapbox.mapboxsdk.Mapbox;
|
||||
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
|
||||
@@ -147,6 +146,25 @@ public class OfflineRegion {
|
||||
void onError(String error);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback receives an asynchronous response containing a notification when
|
||||
* an offline region has been invalidated, or a {@link String} error message otherwise.
|
||||
*/
|
||||
@Keep
|
||||
public interface OfflineRegionInvalidateCallback {
|
||||
/**
|
||||
* Receives the invalidate notification
|
||||
*/
|
||||
void onInvalidate();
|
||||
|
||||
/**
|
||||
* Receives the error message
|
||||
*
|
||||
* @param error the error message
|
||||
*/
|
||||
void onError(String error);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback receives an asynchronous response containing the newly update
|
||||
* OfflineMetadata in the database, or an error message otherwise.
|
||||
@@ -337,14 +355,14 @@ public class OfflineRegion {
|
||||
* @param callback the callback to invoked.
|
||||
*/
|
||||
public void getStatus(@NonNull final OfflineRegionStatusCallback callback) {
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).activate();
|
||||
fileSource.activate();
|
||||
getOfflineRegionStatus(new OfflineRegionStatusCallback() {
|
||||
@Override
|
||||
public void onStatus(final OfflineRegionStatus status) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
|
||||
fileSource.deactivate();
|
||||
callback.onStatus(status);
|
||||
}
|
||||
});
|
||||
@@ -355,7 +373,7 @@ public class OfflineRegion {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
|
||||
fileSource.deactivate();
|
||||
callback.onError(error);
|
||||
}
|
||||
});
|
||||
@@ -383,14 +401,14 @@ public class OfflineRegion {
|
||||
public void delete(@NonNull final OfflineRegionDeleteCallback callback) {
|
||||
if (!isDeleted) {
|
||||
isDeleted = true;
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).activate();
|
||||
fileSource.activate();
|
||||
deleteOfflineRegion(new OfflineRegionDeleteCallback() {
|
||||
@Override
|
||||
public void onDelete() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
|
||||
fileSource.deactivate();
|
||||
callback.onDelete();
|
||||
OfflineRegion.this.finalize();
|
||||
}
|
||||
@@ -403,7 +421,7 @@ public class OfflineRegion {
|
||||
@Override
|
||||
public void run() {
|
||||
isDeleted = false;
|
||||
FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
|
||||
fileSource.deactivate();
|
||||
callback.onError(error);
|
||||
}
|
||||
});
|
||||
@@ -412,6 +430,46 @@ public class OfflineRegion {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate all the tiles from an offline region forcing Mapbox GL to revalidate
|
||||
* the tiles with the server before using. This is more efficient than deleting the
|
||||
* offline region and downloading it again because if the data on the cache matches
|
||||
* the server, no new data gets transmitted.
|
||||
*
|
||||
* @param callback the callback to be invoked
|
||||
*/
|
||||
public void invalidate(@Nullable final OfflineRegionInvalidateCallback callback) {
|
||||
fileSource.activate();
|
||||
invalidateOfflineRegion(new OfflineRegionInvalidateCallback() {
|
||||
|
||||
@Override
|
||||
public void onInvalidate() {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onInvalidate();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull final String message) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileSource.deactivate();
|
||||
if (callback != null) {
|
||||
callback.onError(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an offline region metadata from the database.
|
||||
* <p>
|
||||
@@ -469,4 +527,7 @@ public class OfflineRegion {
|
||||
@Keep
|
||||
private native void updateOfflineRegionMetadata(byte[] metadata, OfflineRegionUpdateMetadataCallback callback);
|
||||
|
||||
@Keep
|
||||
private native void invalidateOfflineRegion(OfflineRegionInvalidateCallback callback);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user