summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobrun Van Nuland <tobrun.van.nuland@gmail.com>2017-07-03 19:47:05 +0200
committerTobrun Van Nuland <tobrun.van.nuland@gmail.com>2017-07-03 19:57:06 +0200
commit431eae0a92c3724b4b0982c0748a4a825c25d2aa (patch)
tree656f08c09d23179b348b6ed9320633430ac33bf5
parentb5fed1172d77bac0ba122c73a9d30739a51e5028 (diff)
downloadqtlocation-mapboxgl-upstream/tvn-rework-surface-creation-destruction.tar.gz
[android] - rework eglDisplay and eglContext construction/destruction. Rework lifecycle events. Postpone map initalisation.upstream/tvn-rework-surface-creation-destruction
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java262
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml7
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/ids.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java127
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java126
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_visibility.xml17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml4
9 files changed, 452 insertions, 139 deletions
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 19cad1d8e0..14f4265b00 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -45,6 +45,9 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import timber.log.Timber;
/**
* <p>
@@ -60,65 +63,81 @@ import java.util.List;
* <strong>Warning:</strong> Please note that you are responsible for getting permission to use the map data,
* and for ensuring your use adheres to the relevant terms of use.
*/
+@UiThread
public class MapView extends FrameLayout {
private NativeMapView nativeMapView;
- private boolean textureMode;
- private boolean destroyed;
- private boolean hasSurface;
+ private Bundle savedInstanceState;
private MapboxMap mapboxMap;
- private MapCallback mapCallback;
+ private MapCallback mapCallback = new MapCallback();
private MapGestureDetector mapGestureDetector;
private MapKeyListener mapKeyListener;
private MapZoomButtonController mapZoomButtonController;
- @UiThread
+ private MapboxMapOptions mapboxMapOptions;
+ private final CopyOnWriteArrayList<OnMapChangedListener> onMapChangedListeners = new CopyOnWriteArrayList<>();
+ private CompassView compassView;
+ private MyLocationView myLocationView;
+ private ImageView attrView;
+
public MapView(@NonNull Context context) {
super(context);
- initialise(context, MapboxMapOptions.createFromAttributes(context, null));
+ initialiseView(context, MapboxMapOptions.createFromAttributes(context, null));
}
- @UiThread
public MapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
- initialise(context, MapboxMapOptions.createFromAttributes(context, attrs));
+ initialiseView(context, MapboxMapOptions.createFromAttributes(context, attrs));
}
- @UiThread
public MapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- initialise(context, MapboxMapOptions.createFromAttributes(context, attrs));
+ initialiseView(context, MapboxMapOptions.createFromAttributes(context, attrs));
}
- @UiThread
public MapView(@NonNull Context context, @Nullable MapboxMapOptions options) {
super(context);
- initialise(context, options == null ? MapboxMapOptions.createFromAttributes(context, null) : options);
+ initialiseView(context, options == null ? MapboxMapOptions.createFromAttributes(context, null) : options);
}
- private void initialise(@NonNull final Context context, @NonNull final MapboxMapOptions options) {
+ private void initialiseView(@NonNull final Context context, @NonNull final MapboxMapOptions options) {
if (isInEditMode()) {
// in IDE, show preview map
LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_preview, this);
return;
}
-
- // determine render surface
- textureMode = options.getTextureMode();
+ mapboxMapOptions = options;
// inflate view
- View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
- CompassView compassView = (CompassView) view.findViewById(R.id.compassView);
- MyLocationView myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
- ImageView attrView = (ImageView) view.findViewById(R.id.attributionView);
+ LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
+ compassView = (CompassView) findViewById(R.id.compassView);
+ myLocationView = (MyLocationView) findViewById(R.id.userLocationView);
+ attrView = (ImageView) findViewById(R.id.attributionView);
// add accessibility support
setContentDescription(context.getString(R.string.mapbox_mapActionDescription));
+ setWillNotDraw(false);
+ }
- // create native Map object
- nativeMapView = new NativeMapView(this);
+ private void initialiseDrawingSurface(boolean textureMode) {
+ if (textureMode) {
+ TextureView textureView = new TextureView(getContext());
+ textureView.setSurfaceTextureListener(new SurfaceTextureListener());
+ addView(textureView, 0);
+ } else {
+ SurfaceView surfaceView = new SurfaceView(getContext());
+ surfaceView.setId(R.id.surfaceView);
+ surfaceView.setContentDescription(null);
+ surfaceView.getHolder().addCallback(new SurfaceCallback());
+ addView(surfaceView, 0);
+ }
+ }
+
+ private void initialiseMap() {
+ Context context = getContext();
+ addOnMapChangedListener(mapCallback);
// callback for focal point invalidation
FocalPointInvalidator focalPoint = new FocalPointInvalidator(compassView);
@@ -134,7 +153,7 @@ public class MapView extends FrameLayout {
// setup components for MapboxMap creation
Projection proj = new Projection(nativeMapView);
- UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, view.findViewById(R.id.logoView));
+ UiSettings uiSettings = new UiSettings(proj, focalPoint, compassView, attrView, findViewById(R.id.logoView));
TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPoint, zoomInvalidator);
MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj, focalPoint);
LongSparseArray<Annotation> annotationsArray = new LongSparseArray<>();
@@ -150,6 +169,7 @@ public class MapView extends FrameLayout {
cameraChangeDispatcher);
mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
registerTouchListener, annotationManager, cameraChangeDispatcher);
+ mapCallback.attachMapboxMap(mapboxMap);
// user input
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings, trackingSettings,
@@ -171,14 +191,17 @@ public class MapView extends FrameLayout {
setFocusableInTouchMode(true);
requestDisallowInterceptTouchEvent(true);
- // allow onDraw invocation
- setWillNotDraw(false);
-
// notify Map object about current connectivity state
nativeMapView.setReachability(ConnectivityReceiver.instance(context).isConnected(context));
- // initialise MapboxMap
- mapboxMap.initialise(context, options);
+ // initialiseView MapboxMap
+ if (savedInstanceState == null) {
+ mapboxMap.initialise(context, mapboxMapOptions);
+ } else {
+ mapboxMap.onRestoreInstanceState(savedInstanceState);
+ }
+
+ mapboxMap.onStart();
}
//
@@ -201,24 +224,7 @@ public class MapView extends FrameLayout {
if (savedInstanceState == null) {
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapLoadEvent());
} else if (savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
- mapboxMap.onRestoreInstanceState(savedInstanceState);
- }
-
- initialiseDrawingSurface(textureMode);
- addOnMapChangedListener(mapCallback = new MapCallback(mapboxMap));
- }
-
- private void initialiseDrawingSurface(boolean textureMode) {
- nativeMapView.initializeDisplay();
- nativeMapView.initializeContext();
- if (textureMode) {
- TextureView textureView = new TextureView(getContext());
- textureView.setSurfaceTextureListener(new SurfaceTextureListener());
- addView(textureView, 0);
- } else {
- SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
- surfaceView.getHolder().addCallback(new SurfaceCallback());
- surfaceView.setVisibility(View.VISIBLE);
+ this.savedInstanceState = savedInstanceState;
}
}
@@ -228,7 +234,6 @@ public class MapView extends FrameLayout {
*
* @param outState Pass in the parent's outState.
*/
-
@UiThread
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
@@ -240,7 +245,6 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onStart() {
- mapboxMap.onStart();
ConnectivityReceiver.instance(getContext()).activate();
}
@@ -265,21 +269,31 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onStop() {
- mapboxMap.onStop();
ConnectivityReceiver.instance(getContext()).deactivate();
}
+ @Override
+ protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+ if (isInEditMode()) {
+ return;
+ }
+ Timber.e("OnVisibilityChanged for %s, isVisible %s, isGone %s, isInvisible %s", changedView.getClass().getSimpleName(), visibility == View.VISIBLE, visibility == View.GONE, View.INVISIBLE);
+ if (visibility == View.VISIBLE && nativeMapView == null) {
+ initialiseDrawingSurface(mapboxMapOptions.getTextureMode());
+ }
+
+ if (mapZoomButtonController != null && nativeMapView != null) {
+ mapZoomButtonController.setVisible(visibility == View.VISIBLE);
+ }
+ }
+
/**
* You must call this method from the parent's {@link Activity#onDestroy()} or {@link Fragment#onDestroy()}.
*/
@UiThread
public void onDestroy() {
- destroyed = true;
- nativeMapView.terminateContext();
- nativeMapView.terminateDisplay();
- nativeMapView.destroySurface();
- nativeMapView.destroy();
- nativeMapView = null;
+
}
@Override
@@ -385,11 +399,9 @@ public class MapView extends FrameLayout {
* @see Style
*/
public void setStyleUrl(@NonNull String url) {
- if (destroyed) {
- return;
+ if (nativeMapView != null) {
+ nativeMapView.setStyleUrl(url);
}
-
- nativeMapView.setStyleUrl(url);
}
//
@@ -409,11 +421,7 @@ public class MapView extends FrameLayout {
return;
}
- if (destroyed) {
- return;
- }
-
- if (!hasSurface) {
+ if (nativeMapView == null) {
return;
}
@@ -422,28 +430,46 @@ public class MapView extends FrameLayout {
@Override
protected void onSizeChanged(int width, int height, int oldw, int oldh) {
- if (destroyed) {
+ if (nativeMapView == null) {
return;
}
- if (!isInEditMode()) {
+ if (!isInEditMode() && nativeMapView != null) {
nativeMapView.resizeView(width, height);
}
}
+ void onMapChange(int rawChange) {
+ for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) {
+ try {
+ onMapChangedListener.onMapChanged(rawChange);
+ } catch (RuntimeException err) {
+ Timber.e("Exception (%s) in MapView.OnMapChangedListener: %s", err.getClass(), err.getMessage());
+ }
+ }
+ }
+
private class SurfaceCallback implements SurfaceHolder.Callback {
private Surface surface;
@Override
public void surfaceCreated(SurfaceHolder holder) {
- nativeMapView.createSurface(surface = holder.getSurface());
- hasSurface = true;
+ Timber.e("onSurfaceCreated");
+ if (nativeMapView == null) {
+ nativeMapView = new NativeMapView(MapView.this);
+ nativeMapView.initializeDisplay();
+ nativeMapView.initializeContext();
+ nativeMapView.createSurface(surface = holder.getSurface());
+ nativeMapView.resizeView(getWidth(), getHeight());
+ initialiseMap();
+ }
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if (destroyed) {
+ Timber.e("onSurfaceChanged");
+ if (nativeMapView == null) {
return;
}
nativeMapView.resizeFramebuffer(width, height);
@@ -451,12 +477,17 @@ public class MapView extends FrameLayout {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
- hasSurface = false;
-
+ Timber.e("onSurfaceDestroyed");
if (nativeMapView != null) {
+ mapboxMap.onStop();
nativeMapView.destroySurface();
+ surface.release();
+ surface = null;
+ nativeMapView.terminateDisplay();
+ nativeMapView.terminateContext();
+ nativeMapView.destroy();
+ nativeMapView = null;
}
- surface.release();
}
}
@@ -469,21 +500,33 @@ public class MapView extends FrameLayout {
// Must do all EGL/GL ES initialization here
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- nativeMapView.createSurface(this.surface = new Surface(surface));
- nativeMapView.resizeFramebuffer(width, height);
- hasSurface = true;
+ Timber.e("onSurfaceCreated");
+ if (nativeMapView == null) {
+ nativeMapView = new NativeMapView(MapView.this);
+ nativeMapView.initializeDisplay();
+ nativeMapView.initializeContext();
+ nativeMapView.createSurface(this.surface = new Surface(surface));
+ nativeMapView.resizeView(width, height);
+ nativeMapView.resizeFramebuffer(width, height);
+ initialiseMap();
+ }
}
// Called when the native surface texture has been destroyed
// Must do all EGL/GL ES destruction here
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- hasSurface = false;
-
+ Timber.e("onSurfaceDestroyed");
if (nativeMapView != null) {
+ mapboxMap.onStop();
nativeMapView.destroySurface();
+ this.surface.release();
+ this.surface = null;
+ nativeMapView.terminateDisplay();
+ nativeMapView.terminateContext();
+ nativeMapView.destroy();
+ nativeMapView = null;
}
- this.surface.release();
return true;
}
@@ -491,7 +534,7 @@ public class MapView extends FrameLayout {
// Must handle window resizing here.
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- if (destroyed) {
+ if (nativeMapView == null) {
return;
}
@@ -502,7 +545,7 @@ public class MapView extends FrameLayout {
// Must sync with UI here
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if (destroyed) {
+ if (nativeMapView == null) {
return;
}
mapboxMap.onUpdateRegionChange();
@@ -523,15 +566,6 @@ public class MapView extends FrameLayout {
}
}
- // Called when view is hidden and shown
- @Override
- protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
- if (isInEditMode() || mapZoomButtonController == null) {
- return;
- }
- mapZoomButtonController.setVisible(visibility == View.VISIBLE);
- }
-
//
// Map events
//
@@ -547,7 +581,7 @@ public class MapView extends FrameLayout {
*/
public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.addOnMapChangedListener(listener);
+ onMapChangedListeners.add(listener);
}
}
@@ -559,7 +593,7 @@ public class MapView extends FrameLayout {
*/
public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
- nativeMapView.removeOnMapChangedListener(listener);
+ onMapChangedListeners.remove(listener);
}
}
@@ -570,13 +604,7 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void getMapAsync(final OnMapReadyCallback callback) {
- if (!mapCallback.isInitialLoad() && callback != null) {
- callback.onMapReady(mapboxMap);
- } else {
- if (callback != null) {
- mapCallback.addOnMapReadyCallback(callback);
- }
- }
+ mapCallback.addOnMapReadyCallback(callback);
}
MapboxMap getMapboxMap() {
@@ -876,12 +904,6 @@ public class MapView extends FrameLayout {
this.transform = transform;
}
- // Not used
- @Override
- public void onVisibilityChanged(boolean visible) {
- // Ignore
- }
-
// Called when user pushes a zoom button on the ZoomButtonController
@Override
public void onZoom(boolean zoomIn) {
@@ -898,6 +920,11 @@ public class MapView extends FrameLayout {
transform.zoom(zoomIn, centerPoint);
}
}
+
+ @Override
+ public void onVisibilityChanged(boolean visible) {
+
+ }
}
private class CameraZoomInvalidator implements TrackingSettings.CameraZoomInvalidator {
@@ -923,26 +950,29 @@ public class MapView extends FrameLayout {
private static class MapCallback implements OnMapChangedListener {
- private final MapboxMap mapboxMap;
+ private MapboxMap mapboxMap;
private final List<OnMapReadyCallback> onMapReadyCallbackList = new ArrayList<>();
private boolean initialLoad = true;
- MapCallback(MapboxMap mapboxMap) {
+ MapCallback() {
+ }
+
+ void attachMapboxMap(MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
}
@Override
public void onMapChanged(@MapChange int change) {
+ if (mapboxMap == null) {
+ Timber.e("not executing mapchange, mapboxmap is null for change %s", change);
+ return;
+ }
+
if (change == DID_FINISH_LOADING_STYLE && initialLoad) {
initialLoad = false;
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- mapboxMap.onPreMapReady();
- onMapReady();
- mapboxMap.onPostMapReady();
- }
- });
+ mapboxMap.onPreMapReady();
+ onMapReady();
+ mapboxMap.onPostMapReady();
} else if (change == DID_FINISH_RENDERING_FRAME || change == DID_FINISH_RENDERING_FRAME_FULLY_RENDERED) {
mapboxMap.onUpdateFullyRendered();
} else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
@@ -962,10 +992,6 @@ public class MapView extends FrameLayout {
}
}
- boolean isInitialLoad() {
- return initialLoad;
- }
-
void addOnMapReadyCallback(OnMapReadyCallback callback) {
onMapReadyCallbackList.add(callback);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index a88a11d387..4db1c809b6 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -57,9 +57,6 @@ final class NativeMapView {
// Device density
private final float pixelRatio;
- // Listeners for Map change events
- private CopyOnWriteArrayList<MapView.OnMapChangedListener> onMapChangedListeners;
-
// Listener invoked to return a bitmap of the map
private MapboxMap.SnapshotReadyCallback snapshotReadyCallback;
@@ -76,7 +73,6 @@ final class NativeMapView {
fileSource = FileSource.getInstance(context);
pixelRatio = context.getResources().getDisplayMetrics().density;
- onMapChangedListeners = new CopyOnWriteArrayList<>();
this.mapView = mapView;
String programCacheDir = context.getCacheDir().getAbsolutePath();
@@ -887,14 +883,8 @@ final class NativeMapView {
}
protected void onMapChanged(int rawChange) {
- if (onMapChangedListeners != null) {
- for (MapView.OnMapChangedListener onMapChangedListener : onMapChangedListeners) {
- try {
- onMapChangedListener.onMapChanged(rawChange);
- } catch (RuntimeException err) {
- Timber.e("Exception (%s) in MapView.OnMapChangedListener: %s", err.getClass(), err.getMessage());
- }
- }
+ if (mapView != null) {
+ mapView.onMapChange(rawChange);
}
}
@@ -1130,11 +1120,15 @@ final class NativeMapView {
//
void addOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) {
- onMapChangedListeners.add(listener);
+ if (mapView != null) {
+ mapView.addOnMapChangedListener(listener);
+ }
}
void removeOnMapChangedListener(@NonNull MapView.OnMapChangedListener listener) {
- onMapChangedListeners.remove(listener);
+ if (mapView != null) {
+ mapView.removeOnMapChangedListener(listener);
+ }
}
//
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
index 6d07de7baa..0d0fda7b2e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
@@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <SurfaceView
- android:id="@+id/surfaceView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:contentDescription="@null"
- android:visibility="gone"/>
-
<FrameLayout
android:id="@+id/markerViewContainer"
android:layout_width="match_parent"
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/ids.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..b8d2548032
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="surfaceView" type="id" />
+</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index d57136755f..93ac4101d4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -415,6 +415,28 @@
android:value=".activity.FeatureOverviewActivity"/>
</activity>
<activity
+ android:name=".activity.maplayout.MapChangeActivity"
+ android:description="@string/description_map_change"
+ android:label="@string/activity_map_change">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout"/>
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity"/>
+ </activity>
+ <activity
+ android:name=".activity.maplayout.VisibilityChangeActivity"
+ android:description="@string/description_visibility_map"
+ android:label="@string/activity_map_visibility">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout"/>
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity"/>
+ </activity>
+ <activity
android:name=".activity.style.RuntimeStyleActivity"
android:description="@string/description_runtime_style"
android:label="@string/activity_runtime_style">
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java
new file mode 100644
index 0000000000..27f32939b8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java
@@ -0,0 +1,127 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+import timber.log.Timber;
+
+/**
+ * Test activity showcasing how to listen to map change events.
+ */
+public class MapChangeActivity extends AppCompatActivity {
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_simple);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(int change) {
+ Timber.e("OnMapChange: %s", resolveMapChange(change));
+ }
+ });
+
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(55.754020, 37.620948), 12), 9000);
+ }
+ });
+ }
+
+ private String resolveMapChange(int change) {
+ switch (change) {
+ case MapView.REGION_WILL_CHANGE:
+ return "Region will change";
+ case MapView.REGION_WILL_CHANGE_ANIMATED:
+ return "Region will change animated";
+ case MapView.REGION_IS_CHANGING:
+ return "Region is changing";
+ case MapView.REGION_DID_CHANGE:
+ return "Region did change";
+ case MapView.REGION_DID_CHANGE_ANIMATED:
+ return "Region did change animated";
+ case MapView.WILL_START_LOADING_MAP:
+ return "Will start loading map";
+ case MapView.DID_FINISH_LOADING_MAP:
+ return "Did finish loading map";
+ case MapView.DID_FAIL_LOADING_MAP:
+ return "Did fail loading map";
+ case MapView.WILL_START_RENDERING_FRAME:
+ return "Will start rendering frame";
+ case MapView.DID_FINISH_RENDERING_FRAME:
+ return "Did finish rendering frame";
+ case MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED:
+ return "Did finish rendering frame fully rendered";
+ case MapView.WILL_START_RENDERING_MAP:
+ return "Will start rendering map";
+ case MapView.DID_FINISH_RENDERING_MAP:
+ return "Did finish rendering map";
+ case MapView.DID_FINISH_RENDERING_MAP_FULLY_RENDERED:
+ return "Did finish rendering map fully rendered";
+ case MapView.DID_FINISH_LOADING_STYLE:
+ return "Did finish loading style";
+ case MapView.SOURCE_DID_CHANGE:
+ return "Source did change";
+ default:
+ throw new RuntimeException("Unsupported map type with int value: " + change);
+ }
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mapView.onStop();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java
new file mode 100644
index 0000000000..2d0708f25c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java
@@ -0,0 +1,126 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+/**
+ * Test activity showcasing visibility changes to the mapview.
+ */
+public class VisibilityChangeActivity extends AppCompatActivity {
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private Handler handler = new Handler();
+ private Runnable runnable;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_map_visibility);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(55.754020, 37.620948), 12), 9000);
+ }
+ });
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ handler.post(runnable = new VisibilityRunner(mapView, findViewById(R.id.viewParent), handler));
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ private static class VisibilityRunner implements Runnable {
+
+ private MapView mapView;
+ private View viewParent;
+ private Handler handler;
+ private int counter;
+
+ VisibilityRunner(MapView mapView, View viewParent, Handler handler) {
+ this.mapView = mapView;
+ this.viewParent = viewParent;
+ this.handler = handler;
+ }
+
+ @Override
+ public void run() {
+ if (mapView != null && viewParent != null) {
+ if (counter == 0 || counter % 2 == 0) {
+ viewParent.setVisibility(View.VISIBLE);
+ mapView.setVisibility(View.VISIBLE);
+ } else {
+ if (counter == 1 || counter == 3) {
+ mapView.setVisibility(counter == 1 ? View.GONE : View.INVISIBLE);
+ } else if (counter == 5 || counter == 7) {
+ viewParent.setVisibility(counter == 5 ? View.GONE : View.INVISIBLE);
+ }
+ }
+
+ // update counter
+ if (counter == 7) {
+ counter = 0;
+ } else {
+ counter++;
+ }
+ }
+ handler.postDelayed(this, 1500);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (runnable != null) {
+ handler.removeCallbacks(runnable);
+ runnable = null;
+ }
+ mapView.onStop();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_visibility.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_visibility.xml
new file mode 100644
index 0000000000..c33034181c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_visibility.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/viewParent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context=".activity.maplayout.SimpleMapActivity">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="invisible"/>
+
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index 0dd0b343fb..61c8a4a34f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -53,6 +53,8 @@
<string name="activity_add_sprite">Add Custom Sprite</string>
<string name="activity_navigation_drawer">Android SDK View integration</string>
<string name="activity_simple_map">Simple Map</string>
+ <string name="activity_map_change">Map Change Events</string>
+ <string name="activity_map_visibility">Visibility Map</string>
<string name="activity_map_in_dialog">Dialog with map</string>
<string name="activity_marker_view_rectangle">Marker views in rectangle</string>
<string name="activity_url_transform">Url transform</string>
@@ -109,6 +111,8 @@
<string name="description_query_rendered_features_box_highlight">Hightligh buildings in box</string>
<string name="description_query_source_features">Query source for features</string>
<string name="description_simple_map">Shows a simple map</string>
+ <string name="description_map_change">Logs map change events to Logcat</string>
+ <string name="description_visibility_map">Changes visibility of map and view parent</string>
<string name="description_add_remove_markers">Based on zoom level</string>
<string name="description_style_file">Use a local file as the style</string>
<string name="description_map_in_dialog">Display a map inside a dialog fragment</string>