diff options
Diffstat (limited to 'platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk')
55 files changed, 2047 insertions, 732 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java index e344343627..fba33bb380 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java @@ -2,8 +2,10 @@ package com.mapbox.mapboxsdk.testapp; import android.app.Application; import android.os.StrictMode; +import android.text.TextUtils; import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.testapp.utils.TokenUtils; import com.squareup.leakcanary.LeakCanary; import timber.log.Timber; @@ -18,6 +20,12 @@ import static timber.log.Timber.DebugTree; */ public class MapboxApplication extends Application { + private static final String DEFAULT_MAPBOX_ACCESS_TOKEN = "YOUR_MAPBOX_ACCESS_TOKEN_GOES_HERE"; + private static final String ACCESS_TOKEN_NOT_SET_MESSAGE = "In order to run the Test App you need to set a valid " + + "access token. During development, you can set the MAPBOX_ACCESS_TOKEN environment variable for the SDK to " + + "automatically include it in the Test App. Otherwise, you can manually include it in the " + + "res/values/developer-config.xml file in the MapboxGLAndroidSDKTestApp folder."; + @Override public void onCreate() { super.onCreate(); @@ -43,7 +51,12 @@ public class MapboxApplication extends Application { .penaltyDeath() .build()); - Mapbox.getInstance(getApplicationContext(), getString(R.string.mapbox_access_token)); + String mapboxAccessToken = TokenUtils.getMapboxAccessToken(getApplicationContext()); + if (TextUtils.isEmpty(mapboxAccessToken) || mapboxAccessToken.equals(DEFAULT_MAPBOX_ACCESS_TOKEN)) { + Timber.e(ACCESS_TOKEN_NOT_SET_MESSAGE); + } + + Mapbox.getInstance(getApplicationContext(), mapboxAccessToken); } private void initializeLogger() { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java index f8617366a0..3f20f19f5d 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java @@ -92,7 +92,7 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA)); } catch (PackageManager.NameNotFoundException exception) { - Timber.e("Could not resolve package info", exception); + Timber.e(exception, "Could not resolve package info"); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java deleted file mode 100644 index 27958c3d0c..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AddRemoveMarkerActivity.java +++ /dev/null @@ -1,188 +0,0 @@ -package com.mapbox.mapboxsdk.testapp.activity.annotation; - -import android.annotation.SuppressLint; -import android.graphics.Bitmap; -import android.graphics.Color; -import android.os.Bundle; -import android.support.annotation.DrawableRes; -import android.support.v7.app.AppCompatActivity; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import com.mapbox.mapboxsdk.annotations.Icon; -import com.mapbox.mapboxsdk.annotations.IconFactory; -import com.mapbox.mapboxsdk.annotations.Marker; -import com.mapbox.mapboxsdk.annotations.MarkerOptions; -import com.mapbox.mapboxsdk.camera.CameraPosition; -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 com.mapbox.mapboxsdk.testapp.utils.ViewToBitmapUtil; - -import timber.log.Timber; - -/** - * Test activity showcasing updating a Marker image when changing zoom levels - */ -public class AddRemoveMarkerActivity extends AppCompatActivity { - - public static final double THRESHOLD = 5.0; - - private MapView mapView; - private MapboxMap mapboxMap; - private double lastZoom; - private boolean isShowingHighThresholdMarker; - private boolean isShowingLowThresholdMarker; - - private MarkerOptions lowThresholdMarker; - private MarkerOptions highThresholdMarker; - private Marker activeMarker; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_add_remove_marker); - - View lowThresholdView = generateView("Low", R.drawable.ic_circle); - Bitmap lowThresholdBitmap = ViewToBitmapUtil.convertToBitmap(lowThresholdView); - Icon lowThresholdIcon = IconFactory.getInstance(this).fromBitmap(lowThresholdBitmap); - - lowThresholdMarker = new MarkerOptions() - .icon(lowThresholdIcon) - .position(new LatLng(0.1, 0)); - - View highThesholdView = generateView("High", R.drawable.ic_circle); - Bitmap highThresholdBitmap = ViewToBitmapUtil.convertToBitmap(highThesholdView); - Icon highThresholdIcon = IconFactory.getInstance(this).fromBitmap(highThresholdBitmap); - - highThresholdMarker = new MarkerOptions() - .icon(highThresholdIcon) - .position(new LatLng(0.1, 0)); - - mapView = (MapView) findViewById(R.id.mapView); - mapView.onCreate(savedInstanceState); - mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(MapboxMap mapboxMap) { - AddRemoveMarkerActivity.this.mapboxMap = mapboxMap; - updateZoom(mapboxMap.getCameraPosition().zoom); - mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.9f)); - mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() { - @Override - public void onCameraChange(CameraPosition position) { - updateZoom(position.zoom); - } - }); - } - }); - } - - @SuppressLint("InflateParams") - private View generateView(String text, @DrawableRes int drawableRes) { - View view = LayoutInflater.from(this).inflate(R.layout.view_custom_marker, null); - TextView textView = (TextView) view.findViewById(R.id.textView); - textView.setText(text); - textView.setTextColor(Color.WHITE); - ImageView imageView = (ImageView) view.findViewById(R.id.imageView); - imageView.setImageResource(drawableRes); - return view; - } - - private void updateZoom(double zoom) { - if (lastZoom == zoom) { - return; - } - - lastZoom = zoom; - if (zoom > THRESHOLD) { - showHighThresholdMarker(); - } else { - showLowThresholdMarker(); - } - } - - private void showLowThresholdMarker() { - if (isShowingLowThresholdMarker) { - return; - } - - isShowingLowThresholdMarker = true; - isShowingHighThresholdMarker = false; - - if (activeMarker != null) { - Timber.d("Remove marker with " + activeMarker.getId()); - mapboxMap.removeMarker(activeMarker); - } else { - Timber.e("active marker is null"); - } - - activeMarker = mapboxMap.addMarker(lowThresholdMarker); - Timber.d("showLowThresholdMarker() " + activeMarker.getId()); - } - - private void showHighThresholdMarker() { - if (isShowingHighThresholdMarker) { - return; - } - - isShowingLowThresholdMarker = false; - isShowingHighThresholdMarker = true; - - if (activeMarker != null) { - Timber.d("Remove marker with " + activeMarker.getId()); - mapboxMap.removeMarker(activeMarker); - } else { - Timber.e("active marker is null"); - } - - activeMarker = mapboxMap.addMarker(highThresholdMarker); - Timber.d("showHighThresholdMarker() " + activeMarker.getId()); - } - - @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 - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mapView.onSaveInstanceState(outState); - } - - @Override - public void onLowMemory() { - super.onLowMemory(); - mapView.onLowMemory(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mapView.onDestroy(); - } -} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java index 8b238e49a8..50adeb2d74 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java @@ -274,7 +274,7 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView String json = GeoParseUtil.loadStringFromAssets(activity.getApplicationContext(), "points.geojson"); return GeoParseUtil.parseGeoJsonCoordinates(json); } catch (IOException | JSONException exception) { - Timber.e("Could not add markers,", exception); + Timber.e(exception, "Could not add markers"); return null; } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java index f2f82865d1..61ece0a94f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java @@ -36,6 +36,7 @@ import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerViewOptions; import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerView; import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerViewOptions; +import java.util.Locale; import java.util.Random; /** @@ -150,7 +151,11 @@ public class MarkerViewActivity extends AppCompatActivity { public void onMapChanged(@MapView.MapChange int change) { if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) { if (!markerViewManager.getMarkerViewAdapters().isEmpty() && viewCountView != null) { - viewCountView.setText("ViewCache size " + markerViewContainer.getChildCount()); + viewCountView.setText(String.format( + Locale.getDefault(), + getString(R.string.viewcache_size), + markerViewContainer.getChildCount()) + ); } } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java index 266db3fdd1..848eab9a3c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewsInRectangleActivity.java @@ -19,6 +19,9 @@ import java.util.List; import timber.log.Timber; +/** + * Test activity showcasing counting MarkerViews in a rectangle. + */ public class MarkerViewsInRectangleActivity extends AppCompatActivity implements OnMapReadyCallback, View.OnClickListener { @@ -53,7 +56,7 @@ public class MarkerViewsInRectangleActivity extends AppCompatActivity implements int top = selectionBox.getTop() - mapView.getTop(); int left = selectionBox.getLeft() - mapView.getLeft(); RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight()); - Timber.i(String.format("Querying box %s", box)); + Timber.i("Querying box %s", box); List<MarkerView> markers = mapboxMap.getMarkerViewsInRect(box); // Show count diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java index fecfe2a842..49c9663672 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java @@ -57,8 +57,6 @@ public class PolygonActivity extends AppCompatActivity implements OnMapReadyCall // configure inital map state MapboxMapOptions options = new MapboxMapOptions() .attributionTintColor(RED_COLOR) - // deprecated feature! - .textureMode(true) .compassFadesWhenFacingNorth(false) .styleUrl(Style.MAPBOX_STREETS) .camera(new CameraPosition.Builder() diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java new file mode 100644 index 0000000000..cc44ac9715 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java @@ -0,0 +1,174 @@ +package com.mapbox.mapboxsdk.testapp.activity.camera; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.TypeEvaluator; +import android.animation.ValueAnimator; +import android.os.Bundle; +import android.support.v4.view.animation.FastOutLinearInInterpolator; +import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.view.animation.AnticipateOvershootInterpolator; + +import com.mapbox.mapboxsdk.camera.CameraPosition; +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 using Android SDK animators to animate camera position changes. + */ +public class CameraAnimatorActivity extends AppCompatActivity implements OnMapReadyCallback { + + private static final double ANIMATION_DELAY_FACTOR = 1.5; + + private MapView mapView; + private MapboxMap mapboxMap; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_camera_animator); + + mapView = (MapView) findViewById(R.id.mapView); + if (mapView != null) { + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(this); + } + } + + @Override + public void onMapReady(final MapboxMap map) { + mapboxMap = map; + findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + view.setVisibility(View.GONE); + createAnimator(mapboxMap.getCameraPosition()).start(); + } + }); + } + + private Animator createAnimator(CameraPosition currentPosition) { + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(createLatLngAnimator(currentPosition.target)); + animatorSet.play(createZoomAnimator(currentPosition.zoom)); + animatorSet.play(createBearingAnimator(currentPosition.bearing)); + animatorSet.play(createTiltAnimator(currentPosition.tilt)); + return animatorSet; + } + + private Animator createLatLngAnimator(LatLng currentPosition) { + LatLng target = new LatLng(37.789992, -122.402214); + ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, target); + latLngAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR)); + latLngAnimator.setInterpolator(new FastOutSlowInInterpolator()); + latLngAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mapboxMap.setLatLng((LatLng) animation.getAnimatedValue()); + } + }); + return latLngAnimator; + } + + private Animator createZoomAnimator(double currentZoom) { + ValueAnimator zoomAnimator = ValueAnimator.ofFloat((float) currentZoom, 14.5f); + zoomAnimator.setDuration((long) (2200 * ANIMATION_DELAY_FACTOR)); + zoomAnimator.setStartDelay((long) (600 * ANIMATION_DELAY_FACTOR)); + zoomAnimator.setInterpolator(new AnticipateOvershootInterpolator()); + zoomAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mapboxMap.setZoom((Float) animation.getAnimatedValue()); + } + }); + return zoomAnimator; + } + + private Animator createBearingAnimator(double currentBearing) { + ValueAnimator bearingAnimator = ValueAnimator.ofFloat((float) currentBearing, 135); + bearingAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR)); + bearingAnimator.setStartDelay((long) (1000 * ANIMATION_DELAY_FACTOR)); + bearingAnimator.setInterpolator(new FastOutLinearInInterpolator()); + bearingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mapboxMap.setBearing((Float) animation.getAnimatedValue()); + } + }); + return bearingAnimator; + } + + private Animator createTiltAnimator(double currentTilt) { + ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, 60); + tiltAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR)); + tiltAnimator.setStartDelay((long) (1500 * ANIMATION_DELAY_FACTOR)); + tiltAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mapboxMap.setTilt((Float) animation.getAnimatedValue()); + } + }); + return tiltAnimator; + } + + private static class LatLngEvaluator implements TypeEvaluator<LatLng> { + + private final LatLng latLng = new LatLng(); + + @Override + public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) { + latLng.setLatitude(startValue.getLatitude() + + ((endValue.getLatitude() - startValue.getLatitude()) * fraction)); + latLng.setLongitude(startValue.getLongitude() + + ((endValue.getLongitude() - startValue.getLongitude()) * fraction)); + return latLng; + } + } + + @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 + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java index 10464b087a..2820bdbd53 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java @@ -1,5 +1,6 @@ package com.mapbox.mapboxsdk.testapp.activity.camera; +import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -24,6 +25,9 @@ import com.mapbox.mapboxsdk.testapp.R; import timber.log.Timber; +/** + * Test activity showcasing how to listen to camera change events. + */ public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback { private MapView mapView; @@ -83,6 +87,7 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe fab = (FloatingActionButton) findViewById(R.id.fab); fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary)); fab.setOnClickListener(new View.OnClickListener() { + @SuppressLint("InflateParams") @Override public void onClick(View view) { Context context = view.getContext(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java index d81538f323..e3a9551b8e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java @@ -1,75 +1,122 @@ package com.mapbox.mapboxsdk.testapp.activity.camera; import android.os.Bundle; -import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.design.widget.BottomSheetBehavior; import android.support.v7.app.AppCompatActivity; +import android.view.View; import com.mapbox.mapboxsdk.annotations.MarkerOptions; -import com.mapbox.mapboxsdk.camera.CameraUpdate; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; 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 com.mapbox.mapboxsdk.testapp.view.LockableBottomSheetBehavior; + +import java.util.ArrayList; +import java.util.List; /** * Test activity showcasing using the LatLngBounds camera API. - * <p> - * This activity opens the map at zoom level 0 and animates into a bounds set by Los Angeles and New York - * with some additional padding and an animation duration of 1500 ms. - * </p> */ -public class LatLngBoundsActivity extends AppCompatActivity implements OnMapReadyCallback { - - private static final LatLng LOS_ANGELES = new LatLng(34.053940, -118.242622); - private static final LatLng NEW_YORK = new LatLng(40.712730, -74.005953); - - private final LatLng CHINA_BOTTOM_LEFT = new LatLng(15.68169, 73.499857); - private final LatLng CHINA_TOP_RIGHT = new LatLng(53.560711, 134.77281); +public class LatLngBoundsActivity extends AppCompatActivity implements View.OnClickListener { + + private static final List<LatLng> LOCATIONS = new ArrayList<LatLng>() { + { + add(new LatLng(37.806866, -122.422502)); + add(new LatLng(37.812905, -122.477605)); + add(new LatLng(37.826944, -122.423188)); + add(new LatLng(37.752676, -122.447736)); + add(new LatLng(37.769305, -122.479322)); + add(new LatLng(37.749834, -122.417867)); + add(new LatLng(37.756149, -122.405679)); + add(new LatLng(37.751403, -122.387397)); + add(new LatLng(37.793064, -122.391517)); + add(new LatLng(37.769122, -122.427394)); + } + }; + private static final LatLngBounds BOUNDS = new LatLngBounds.Builder().includes(LOCATIONS).build(); + private static final int ANIMATION_DURATION_LONG = 450; + private static final int ANIMATION_DURATION_SHORT = 250; + private static final int BOUNDS_PADDING_DIVIDER_SMALL = 3; + private static final int BOUNDS_PADDING_DIVIDER_LARGE = 9; private MapView mapView; private MapboxMap mapboxMap; + private View bottomSheet; + private LockableBottomSheetBehavior bottomSheetBehavior; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_visible_bounds); - + setContentView(R.layout.activity_latlngbounds); mapView = (MapView) findViewById(R.id.mapView); - mapView.setStyleUrl(Style.DARK); mapView.onCreate(savedInstanceState); - mapView.getMapAsync(this); + mapView.getMapAsync(new OnMapReadyCallback() { + @Override + public void onMapReady(final MapboxMap map) { + mapboxMap = map; + initMap(); + } + }); + } + + private void initMap() { + addMarkers(); + initFab(); + initBottomSheet(); + moveToBounds(bottomSheet.getMeasuredHeight(), BOUNDS_PADDING_DIVIDER_SMALL, 0); + } + + private void addMarkers() { + for (LatLng location : LOCATIONS) { + mapboxMap.addMarker(new MarkerOptions().position(location)); + } + } + + private void initFab() { + findViewById(R.id.fab).setOnClickListener(this); } @Override - public void onMapReady(final MapboxMap map) { - mapboxMap = map; - moveToBounds(new LatLngBounds.Builder().include(NEW_YORK).include(LOS_ANGELES).build(), new int[] {0, 0, 0, 0}); - new Handler().postDelayed(new Runnable() { + public void onClick(View v) { + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN); + v.animate().alpha(0.0f).setDuration(ANIMATION_DURATION_SHORT); + } + + private void initBottomSheet() { + bottomSheet = findViewById(R.id.bottom_sheet); + bottomSheetBehavior = (LockableBottomSheetBehavior) BottomSheetBehavior.from(bottomSheet); + bottomSheetBehavior.setLocked(true); + bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { + @Override + public void onStateChanged(@NonNull View bottomSheet, int newState) { + if (newState == BottomSheetBehavior.STATE_SETTLING) { + moveToBounds(0, BOUNDS_PADDING_DIVIDER_LARGE, ANIMATION_DURATION_LONG); + } + } + @Override - public void run() { - moveToBounds(new LatLngBounds.Builder().include(CHINA_BOTTOM_LEFT).include(CHINA_TOP_RIGHT).build(), - new int[] {100, 100, 100, 100 }); + public void onSlide(@NonNull View bottomSheet, float slideOffset) { + } - }, 5000); + }); } - private void moveToBounds(LatLngBounds latLngBounds, int[] padding) { - mapboxMap.clear(); - mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getNorthEast())); - mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getSouthEast())); - mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getSouthWest())); - mapboxMap.addMarker(new MarkerOptions().position(latLngBounds.getNorthWest())); - CameraUpdate update = - CameraUpdateFactory.newLatLngBounds(latLngBounds, - padding[0], - padding[1], - padding[2], - padding[3]); - mapboxMap.moveCamera(update); + private void moveToBounds(int verticalOffset, int boundsPaddingDivider, int duration) { + int paddingHorizontal = mapView.getMeasuredWidth() / boundsPaddingDivider; + int paddingVertical = (mapView.getMeasuredHeight() - verticalOffset) / boundsPaddingDivider; + mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds( + BOUNDS, + paddingHorizontal, + paddingVertical, + paddingHorizontal, + paddingVertical + verticalOffset), + duration + ); } @Override @@ -97,9 +144,9 @@ public class LatLngBoundsActivity extends AppCompatActivity implements OnMapRead } @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mapView.onSaveInstanceState(outState); + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); } @Override @@ -109,8 +156,8 @@ public class LatLngBoundsActivity extends AppCompatActivity implements OnMapRead } @Override - public void onLowMemory() { - super.onLowMemory(); - mapView.onLowMemory(); + 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/camera/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java index 014743df96..53a5800f26 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java @@ -13,6 +13,9 @@ import com.mapbox.mapboxsdk.testapp.R; import timber.log.Timber; +/** + * Test activity showcasing using maximum and minimum zoom levels to restrict camera movement. + */ public class MaxMinZoomActivity extends AppCompatActivity implements OnMapReadyCallback { private MapView mapView; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java index dde22db2db..1b49e9e3d6 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java @@ -69,6 +69,7 @@ public class CustomLayerActivity extends AppCompatActivity { ExampleCustomLayer.createContext(), ExampleCustomLayer.InitializeFunction, ExampleCustomLayer.RenderFunction, + ExampleCustomLayer.ContextLostFunction, // Optional ExampleCustomLayer.DeinitializeFunction); mapboxMap.addLayerBelow(customLayer, "building"); fab.setImageResource(R.drawable.ic_layers_clear); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java index 9c031ad32a..20174daeaa 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxCountActivity.java @@ -48,7 +48,7 @@ public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity { int top = selectionBox.getTop() - mapView.getTop(); int left = selectionBox.getLeft() - mapView.getLeft(); RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight()); - Timber.i(String.format("Querying box %s", box)); + Timber.i("Querying box %s", box); List<Feature> features = mapboxMap.queryRenderedFeatures(box); // Show count @@ -66,22 +66,21 @@ public class QueryRenderedFeaturesBoxCountActivity extends AppCompatActivity { } private void debugOutput(List<Feature> features) { - Timber.i(String.format("Got %s features", features.size())); + Timber.i("Got %s features", features.size()); for (Feature feature : features) { if (feature != null) { - Timber.i(String.format("Got feature %s with %s properties and Geometry %s", + Timber.i("Got feature %s with %s properties and Geometry %s", feature.getId(), feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>", - feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>") + feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>" ); if (feature.getProperties() != null) { for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) { - Timber.i(String.format("Prop %s - %s", entry.getKey(), entry.getValue())); + Timber.i("Prop %s - %s", entry.getKey(), entry.getValue()); } } } else { - // TODO Question: Why not formatting here?? - Timber.i("Got NULL feature %s"); + Timber.i("Got 0 features"); } } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java index 1d15efef84..480e48437a 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java @@ -46,6 +46,15 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity @Override public void onMapReady(final MapboxMap mapboxMap) { QueryRenderedFeaturesBoxHighlightActivity.this.mapboxMap = mapboxMap; + + // Add layer / source + final GeoJsonSource source = new GeoJsonSource("highlighted-shapes-source"); + mapboxMap.addSource(source); + mapboxMap.addLayer( + new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source") + .withProperties(fillColor(Color.RED)) + ); + selectionBox.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { @@ -53,7 +62,7 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity int top = selectionBox.getTop() - mapView.getTop(); int left = selectionBox.getLeft() - mapView.getLeft(); RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight()); - Timber.i(String.format("Querying box %s for buildings", box)); + Timber.i("Querying box %s for buildings", box); List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building"); // Show count @@ -62,17 +71,8 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity String.format("%s features in box", features.size()), Toast.LENGTH_SHORT).show(); - // remove layer / source if already added - mapboxMap.removeSource("highlighted-shapes-source"); - mapboxMap.removeLayer("highlighted-shapes-layer"); - - // Add layer / source - mapboxMap.addSource( - new GeoJsonSource("highlighted-shapes-source", - FeatureCollection.fromFeatures(features)) - ); - mapboxMap.addLayer(new FillLayer("highlighted-shapes-layer", "highlighted-shapes-source") - .withProperties(fillColor(Color.RED))); + // Update source data + source.setGeoJson(FeatureCollection.fromFeatures(features)); } }); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java index 8c2f3a8fb5..220137d07d 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxSymbolCountActivity.java @@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.testapp.activity.feature; import android.graphics.BitmapFactory; import android.graphics.RectF; import android.os.Bundle; -import android.support.annotation.RawRes; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Toast; @@ -14,15 +13,10 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.style.layers.SymbolLayer; import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils; import com.mapbox.services.commons.geojson.Feature; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; import java.util.List; import timber.log.Timber; @@ -57,9 +51,10 @@ public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivi // Add a symbol layer (also works with annotations) try { - mapboxMap.addSource(new GeoJsonSource("symbols-source", readRawResource(R.raw.test_points_utrecht))); + mapboxMap.addSource(new GeoJsonSource("symbols-source", ResourceUtils.readRawResource( + QueryRenderedFeaturesBoxSymbolCountActivity.this, R.raw.test_points_utrecht))); } catch (IOException ioException) { - Timber.e("Could not load geojson: " + ioException.getMessage()); + Timber.e(ioException, "Could not load geojson"); return; } mapboxMap.addImage( @@ -76,7 +71,7 @@ public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivi int top = selectionBox.getTop() - mapView.getTop(); int left = selectionBox.getLeft() - mapView.getLeft(); RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight()); - Timber.i(String.format("Querying box %s", box)); + Timber.i("Querying box %s", box); List<Feature> features = mapboxMap.queryRenderedFeatures(box, "symbols-layer"); // Show count @@ -94,23 +89,6 @@ public class QueryRenderedFeaturesBoxSymbolCountActivity extends AppCompatActivi }); } - private String readRawResource(@RawRes int rawResource) throws IOException { - InputStream is = getResources().openRawResource(rawResource); - Writer writer = new StringWriter(); - char[] buffer = new char[1024]; - try { - Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - int numRead; - while ((numRead = reader.read(buffer)) != -1) { - writer.write(buffer, 0, numRead); - } - } finally { - is.close(); - } - - return writer.toString(); - } - public MapboxMap getMapboxMap() { return mapboxMap; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java index 8b83db3069..1bd6a34b7c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesPropertiesActivity.java @@ -59,9 +59,9 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity { public void onMapClick(@NonNull LatLng point) { // Query final PointF pixel = mapboxMap.getProjection().toScreenLocation(point); - Timber.i(String.format( + Timber.i( "Requesting features for %sx%s (%sx%s adjusted for density)", - pixel.x, pixel.y, pixel.x / density, pixel.y / density) + pixel.x, pixel.y, pixel.x / density, pixel.y / density ); List<Feature> features = mapboxMap.queryRenderedFeatures(pixel); @@ -84,22 +84,21 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity { } private void debugOutput(List<Feature> features) { - Timber.i(String.format("Got %s features", features.size())); + Timber.i("Got %s features", features.size()); for (Feature feature : features) { if (feature != null) { - Timber.i(String.format("Got feature %s with %s properties and Geometry %s", + Timber.i("Got feature %s with %s properties and Geometry %s", feature.getId(), feature.getProperties() != null ? feature.getProperties().entrySet().size() : "<null>", - feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>") + feature.getGeometry() != null ? feature.getGeometry().getClass().getSimpleName() : "<null>" ); if (feature.getProperties() != null) { for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) { - Timber.i(String.format("Prop %s - %s", entry.getKey(), entry.getValue())); + Timber.i("Prop %s - %s", entry.getKey(), entry.getValue()); } } } else { - // TODO Question: Why not formatting here?? - Timber.i("Got NULL feature %s"); + Timber.i("Got NULL feature"); } } } @@ -185,7 +184,7 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity { private final List<Feature> features; - public CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) { + CustomMarker(BaseMarkerOptions baseMarkerOptions, List<Feature> features) { super(baseMarkerOptions); this.features = features; } @@ -201,7 +200,7 @@ public class QueryRenderedFeaturesPropertiesActivity extends AppCompatActivity { return this; } - public CustomMarkerOptions() { + CustomMarkerOptions() { } private CustomMarkerOptions(Parcel in) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java index ee16b251c5..4f828060ee 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java @@ -50,7 +50,7 @@ public class SupportMapFragmentActivity extends AppCompatActivity implements OnM .zoom(11) .build()); - mapFragment = SupportMapFragment.newInstance(); + mapFragment = SupportMapFragment.newInstance(options); transaction.add(R.id.fragment_container, mapFragment, "com.mapbox.map"); transaction.commit(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java index 8025832429..bbdf450505 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/ViewPagerActivity.java @@ -31,11 +31,11 @@ public class ViewPagerActivity extends AppCompatActivity { } } - public static class MapFragmentAdapter extends FragmentPagerAdapter { + static class MapFragmentAdapter extends FragmentPagerAdapter { private static int NUM_ITEMS = 3; - public MapFragmentAdapter(FragmentManager fragmentManager) { + MapFragmentAdapter(FragmentManager fragmentManager) { super(fragmentManager); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java index 2be47b4e25..655012f799 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java @@ -15,6 +15,8 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; +import java.util.Locale; + /** * Test activity showcasing the Snapshot API to create and display a bitmap of the current shown Map. */ @@ -56,7 +58,7 @@ public class SnapshotActivity extends AppCompatActivity implements OnMapReadyCal snapshotView.setImageBitmap(snapshot); Toast.makeText( SnapshotActivity.this, - String.format("Snapshot taken in %d ms", duration), + String.format(Locale.getDefault(), "Snapshot taken in %d ms", duration), Toast.LENGTH_LONG).show(); } }); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java index 18db2ba8a8..7fa4792a38 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/DynamicInfoWindowAdapterActivity.java @@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.testapp.activity.infowindow; import android.graphics.Color; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; @@ -21,16 +20,18 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; import com.mapbox.mapboxsdk.testapp.utils.IconUtils; +import java.util.Locale; + /** * Test activity showcasing how to dynamically update InfoWindow when Using an MapboxMap.InfoWindowAdapter. */ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implements OnMapReadyCallback { + private static final LatLng PARIS = new LatLng(48.864716, 2.349014); + private MapboxMap mapboxMap; private MapView mapView; - private LatLng paris = new LatLng(48.864716, 2.349014); - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -43,7 +44,6 @@ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implemen @Override public void onMapReady(MapboxMap map) { - mapboxMap = map; // Add info window adapter @@ -64,27 +64,32 @@ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implemen double distanceKm = marker.getPosition().distanceTo(point) / 1000; // Get the info window - InfoWindow infoWindow = marker.getInfoWindow(); + final InfoWindow infoWindow = marker.getInfoWindow(); // Get the view from the info window if (infoWindow != null && infoWindow.getView() != null) { // Set the new text on the text view in the info window - ((TextView) infoWindow.getView()).setText(String.format("%.2fkm", distanceKm)); - - // Update the info window position (as the text length changes) - infoWindow.update(); + TextView textView = (TextView) infoWindow.getView(); + textView.setText(String.format(Locale.getDefault(), "%.2fkm", distanceKm)); + textView.post(new Runnable() { + @Override + public void run() { + // Update the info window position (as the text length changes) + infoWindow.update(); + } + }); } } }); // Focus on Paris - mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(paris)); + mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(PARIS)); } private MarkerView addMarker(MapboxMap mapboxMap) { return mapboxMap.addMarker( new MarkerViewOptions() - .position(paris) + .position(PARIS) .icon(IconUtils.drawableToIcon(this, R.drawable.ic_location_city, ResourcesCompat.getColor(getResources(), R.color.mapbox_blue, getTheme())) )); @@ -94,15 +99,13 @@ public class DynamicInfoWindowAdapterActivity extends AppCompatActivity implemen final int padding = (int) getResources().getDimension(R.dimen.attr_margin); mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() { - @Nullable @Override public View getInfoWindow(@NonNull Marker marker) { TextView textView = new TextView(DynamicInfoWindowAdapterActivity.this); textView.setText(marker.getTitle()); textView.setBackgroundColor(Color.WHITE); - textView.setText("Click the map to calculate the distance"); + textView.setText(R.string.action_calculate_distance); textView.setPadding(padding, padding, padding, padding); - return textView; } }); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java index 7026a797d5..22347f8a92 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java @@ -18,6 +18,9 @@ import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarker; import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarkerOptions; import com.mapbox.mapboxsdk.testapp.utils.IconUtils; +/** + * Test activity showcasing using an InfoWindowAdapter to provide a custom InfoWindow content. + */ public class InfoWindowAdapterActivity extends AppCompatActivity { private MapView mapView; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java new file mode 100644 index 0000000000..2c83f6d908 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java @@ -0,0 +1,288 @@ +package com.mapbox.mapboxsdk.testapp.activity.maplayout; + +import android.content.Context; +import android.location.Location; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.BottomSheetBehavior; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.MapboxMapOptions; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.utils.MapFragmentUtils; + +/** + * Test activity showcasing using a bottomView with a MapView and stacking map fragments below. + */ +public class BottomSheetActivity extends AppCompatActivity { + + private static final String TAG_MAIN_FRAGMENT = "com.mapbox.mapboxsdk.fragment.tag.main"; + private static final String TAG_BOTTOM_FRAGMENT = "com.mapbox.mapboxsdk.fragment.tag.bottom"; + + private boolean bottomSheetFragmentAdded; + private int mapViewCounter; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_bottom_sheet); + + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + findViewById(R.id.fabFragment).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + addMapFragment(); + } + }); + + findViewById(R.id.fabBottomSheet).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + toggleBottomSheetMapFragment(); + } + }); + + BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_sheet)); + bottomSheetBehavior.setPeekHeight((int) (64 * getResources().getDisplayMetrics().density)); + bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); + toggleBottomSheetMapFragment(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + if (mapViewCounter > 0) { + mapViewCounter--; + Toast.makeText(this, "Amount of main map fragments: " + mapViewCounter, Toast.LENGTH_SHORT).show(); + } + } + + private void addMapFragment() { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + MainMapFragment mainMapFragment = MainMapFragment.newInstance(mapViewCounter); + if (mapViewCounter == 0) { + fragmentTransaction.add(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT); + } else { + fragmentTransaction.replace(R.id.fragment_container, mainMapFragment, TAG_MAIN_FRAGMENT); + } + fragmentTransaction.addToBackStack(null); + fragmentTransaction.commit(); + mapViewCounter++; + Toast.makeText(this, "Amount of main map fragments: " + mapViewCounter, Toast.LENGTH_SHORT).show(); + } + + private void toggleBottomSheetMapFragment() { + if (!bottomSheetFragmentAdded) { + addBottomSheetMapFragment(); + } else { + removeBottomSheetFragment(); + } + bottomSheetFragmentAdded = !bottomSheetFragmentAdded; + } + + private void addBottomSheetMapFragment() { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.add(R.id.fragment_container_bottom, BottomSheetFragment.newInstance(), TAG_BOTTOM_FRAGMENT); + fragmentTransaction.commit(); + } + + private void removeBottomSheetFragment() { + Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_BOTTOM_FRAGMENT); + if (fragment != null) { + getSupportFragmentManager().beginTransaction().remove(fragment).commit(); + } + } + + public static class MainMapFragment extends Fragment implements OnMapReadyCallback { + + private static final String[] STYLES = new String[] { + Style.MAPBOX_STREETS, + Style.SATELLITE_STREETS, + Style.LIGHT, + Style.DARK, + Style.SATELLITE, + Style.OUTDOORS + }; + + private MapView map; + + public static MainMapFragment newInstance(int mapCounter) { + MainMapFragment mapFragment = new MainMapFragment(); + MapboxMapOptions mapboxMapOptions = new MapboxMapOptions(); + mapboxMapOptions.styleUrl(STYLES[Math.min(Math.max(mapCounter, 0), STYLES.length - 1)]); + mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions)); + return mapFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Context context = inflater.getContext(); + return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments())); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + map.onCreate(savedInstanceState); + map.getMapAsync(this); + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + Location location = mapboxMap.getMyLocation(); + if (location != null) { + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15)); + } + } + + @Override + public void onStart() { + super.onStart(); + map.onStart(); + } + + @Override + public void onResume() { + super.onResume(); + map.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + map.onPause(); + } + + @Override + public void onStop() { + super.onStop(); + map.onStop(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + map.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + map.onLowMemory(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + map.onDestroy(); + } + } + + public static class BottomSheetFragment extends Fragment implements OnMapReadyCallback { + + private MapView map; + + public static BottomSheetFragment newInstance() { + BottomSheetFragment mapFragment = new BottomSheetFragment(); + MapboxMapOptions mapboxMapOptions = new MapboxMapOptions(); + mapboxMapOptions.locationEnabled(true); + mapboxMapOptions.renderSurfaceOnTop(true); + mapboxMapOptions.styleUrl(Style.LIGHT); + mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions)); + return mapFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + Context context = inflater.getContext(); + return map = new MapView(context, MapFragmentUtils.resolveArgs(context, getArguments())); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + map.onCreate(savedInstanceState); + map.getMapAsync(this); + } + + @Override + public void onMapReady(MapboxMap mapboxMap) { + Location location = mapboxMap.getMyLocation(); + if (location != null) { + mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15)); + } + } + + @Override + public void onStart() { + super.onStart(); + map.onStart(); + } + + @Override + public void onResume() { + super.onResume(); + map.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + map.onPause(); + } + + @Override + public void onStop() { + super.onStop(); + map.onStop(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + map.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + map.onLowMemory(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + map.onDestroy(); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java index 18d6fadcb8..6134b4cb7a 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java @@ -1,10 +1,19 @@ package com.mapbox.mapboxsdk.testapp.activity.maplayout; +import android.content.Context; import android.os.Bundle; -import android.support.annotation.NonNull; import android.support.design.widget.FloatingActionButton; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; +import android.view.LayoutInflater; +import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.ListView; import android.widget.TextView; import com.mapbox.mapboxsdk.camera.CameraPosition; @@ -12,18 +21,25 @@ import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.style.layers.Layer; +import com.mapbox.mapboxsdk.style.layers.Property; import com.mapbox.mapboxsdk.testapp.R; +import java.util.List; +import java.util.Locale; + import timber.log.Timber; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility; + /** - * Test Activity showcasing the different debug modes and allows to cycle between the default map styles. + * Test activity showcasing the different debug modes and allows to cycle between the default map styles. */ -public class DebugModeActivity extends AppCompatActivity { +public class DebugModeActivity extends AppCompatActivity implements OnMapReadyCallback { private MapView mapView; private MapboxMap mapboxMap; - + private ActionBarDrawerToggle actionBarDrawerToggle; private int currentStyleIndex = 0; private static final String[] STYLES = new String[] { @@ -32,49 +48,128 @@ public class DebugModeActivity extends AppCompatActivity { Style.LIGHT, Style.DARK, Style.SATELLITE, - Style.SATELLITE_STREETS + Style.SATELLITE_STREETS, + Style.TRAFFIC_DAY, + Style.TRAFFIC_NIGHT }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_debug_mode); + setupToolbar(); + setupMapView(savedInstanceState); + setupDebugChangeView(); + setupStyleChangeView(); + } + + private void setupToolbar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + getSupportActionBar().setHomeButtonEnabled(true); + + DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + actionBarDrawerToggle = new ActionBarDrawerToggle(this, + drawerLayout, + R.string.navigation_drawer_open, + R.string.navigation_drawer_close + ); + actionBarDrawerToggle.setDrawerIndicatorEnabled(true); + actionBarDrawerToggle.syncState(); + } + } + private void setupMapView(Bundle savedInstanceState) { mapView = (MapView) findViewById(R.id.mapView); + mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { + @Override + public void onMapChanged(int change) { + if (change == MapView.DID_FINISH_LOADING_STYLE && mapboxMap != null) { + Timber.v("New style loaded with JSON: %s", mapboxMap.getStyleJson()); + setupNavigationView(mapboxMap.getLayers()); + } + } + }); + mapView.setTag(true); mapView.setStyleUrl(STYLES[currentStyleIndex]); mapView.onCreate(savedInstanceState); + mapView.getMapAsync(this); + } - mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(@NonNull MapboxMap map) { - mapboxMap = map; + @Override + public void onMapReady(MapboxMap map) { + mapboxMap = map; + mapboxMap.getUiSettings().setZoomControlsEnabled(true); - mapboxMap.getUiSettings().setZoomControlsEnabled(true); + setupNavigationView(mapboxMap.getLayers()); + setupZoomView(); + setFpsView(); + } - // show current zoom level on screen - final TextView textView = (TextView) findViewById(R.id.textZoom); - mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() { - @Override - public void onCameraChange(CameraPosition position) { - textView.setText(String.format(getString(R.string.debug_zoom), position.zoom)); - } - }); + private void setFpsView() { + final TextView fpsView = (TextView) findViewById(R.id.fpsView); + mapboxMap.setOnFpsChangedListener(new MapboxMap.OnFpsChangedListener() { + @Override + public void onFpsChanged(double fps) { + fpsView.setText(String.format(Locale.US,"FPS: %4.2f", fps)); } }); + } + + private void setupNavigationView(List<Layer> layerList) { + final LayerListAdapter adapter = new LayerListAdapter(this, layerList); + ListView listView = (ListView) findViewById(R.id.listView); + listView.setAdapter(adapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + Layer clickedLayer = adapter.getItem(position); + toggleLayerVisibility(clickedLayer); + closeNavigationView(); + } + }); + } + private void toggleLayerVisibility(Layer layer) { + boolean isVisible = layer.getVisibility().getValue().equals(Property.VISIBLE); + layer.setProperties( + visibility( + isVisible ? Property.NONE : Property.VISIBLE + ) + ); + } + + private void closeNavigationView() { + DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + drawerLayout.closeDrawers(); + } + + private void setupZoomView() { + final TextView textView = (TextView) findViewById(R.id.textZoom); + mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() { + @Override + public void onCameraChange(CameraPosition position) { + textView.setText(String.format(getString(R.string.debug_zoom), position.zoom)); + } + }); + } + private void setupDebugChangeView() { FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug); fabDebug.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (mapboxMap != null) { - Timber.d("Debug FAB: isDebug Active? " + mapboxMap.isDebugActive()); + Timber.d("Debug FAB: isDebug Active? %s", mapboxMap.isDebugActive()); mapboxMap.cycleDebugOptions(); } } }); + } + private void setupStyleChangeView() { FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles); fabStyles.setOnClickListener(new View.OnClickListener() { @Override @@ -96,6 +191,11 @@ public class DebugModeActivity extends AppCompatActivity { } @Override + public boolean onOptionsItemSelected(MenuItem item) { + return actionBarDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item); + } + + @Override protected void onStart() { super.onStart(); mapView.onStart(); @@ -136,4 +236,58 @@ public class DebugModeActivity extends AppCompatActivity { super.onLowMemory(); mapView.onLowMemory(); } + + private static class LayerListAdapter extends BaseAdapter { + + private LayoutInflater layoutInflater; + private List<Layer> layers; + + LayerListAdapter(Context context, List<Layer> layers) { + this.layoutInflater = LayoutInflater.from(context); + this.layers = layers; + } + + @Override + public int getCount() { + return layers.size(); + } + + @Override + public Layer getItem(int position) { + return layers.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + Layer layer = layers.get(position); + View view = convertView; + if (view == null) { + view = layoutInflater.inflate(android.R.layout.simple_list_item_2, parent, false); + ViewHolder holder = new ViewHolder( + (TextView) view.findViewById(android.R.id.text1), + (TextView) view.findViewById(android.R.id.text2) + ); + view.setTag(holder); + } + ViewHolder holder = (ViewHolder) view.getTag(); + holder.text.setText(layer.getClass().getSimpleName()); + holder.subText.setText(layer.getId()); + return view; + } + + private static class ViewHolder { + final TextView text; + final TextView subText; + + ViewHolder(TextView text, TextView subText) { + this.text = text; + this.subText = subText; + } + } + } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java index 7ec9cb9242..462c0c8025 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java @@ -8,7 +8,6 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; -import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; @@ -23,6 +22,12 @@ import com.mapbox.mapboxsdk.maps.TrackingSettings; import com.mapbox.mapboxsdk.maps.UiSettings; import com.mapbox.mapboxsdk.testapp.R; +/** + * Test activity showcasing having 2 maps on top of each other. + * <p> + * The small map is using the `mapbox_enableZMediaOverlay="true"` configuration + * </p> + */ public class DoubleMapActivity extends AppCompatActivity { private static final String TAG_FRAGMENT = "map"; @@ -45,11 +50,11 @@ public class DoubleMapActivity extends AppCompatActivity { public void setMapboxMap(MapboxMap map) { // we need to set mapboxmap on the parent activity, // for auto-generated ui tests - mapboxMap = map; mapboxMap.setStyleUrl(Style.DARK); mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(18)); try { + mapboxMap.setMyLocationEnabled(true); TrackingSettings settings = mapboxMap.getTrackingSettings(); settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW); } catch (SecurityException securityException) { @@ -58,6 +63,9 @@ public class DoubleMapActivity extends AppCompatActivity { } } + /** + * Custom fragment containing 2 MapViews. + */ public static class DoubleMapFragment extends Fragment { private DoubleMapActivity activity; @@ -107,6 +115,7 @@ public class DoubleMapActivity extends AppCompatActivity { uiSettings.setLogoEnabled(false); try { + mapboxMap.setMyLocationEnabled(true); TrackingSettings settings = mapboxMap.getTrackingSettings(); settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW); } catch (SecurityException securityException) { @@ -123,9 +132,6 @@ public class DoubleMapActivity extends AppCompatActivity { }); } }); - - SurfaceView surfaceViewMini = (SurfaceView) mapViewMini.findViewById(R.id.surfaceView); - surfaceViewMini.setZOrderMediaOverlay(true); } @Override @@ -157,8 +163,8 @@ public class DoubleMapActivity extends AppCompatActivity { } @Override - public void onDestroy() { - super.onDestroy(); + public void onDestroyView() { + super.onDestroyView(); mapView.onDestroy(); mapViewMini.onDestroy(); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LatLngBoundsForCameraActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LatLngBoundsForCameraActivity.java index 9ac87deb0d..24a167e260 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LatLngBoundsForCameraActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/LatLngBoundsForCameraActivity.java @@ -16,7 +16,7 @@ import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; /** - * Test Activity showcasing restricting user gestures to a bounds around Iceland. + * Test activity showcasing restricting user gestures to a bounds around Iceland. */ public class LatLngBoundsForCameraActivity extends AppCompatActivity implements OnMapReadyCallback { 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..32344248bc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapChangeActivity.java @@ -0,0 +1,111 @@ +package com.mapbox.mapboxsdk.testapp.activity.maplayout; + +import android.os.Bundle; +import android.support.v4.util.LongSparseArray; +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); + + final LongSparseArray<String> mapChangeMap = buildMapChangeStringValueSparseArray(); + mapView = (MapView) findViewById(R.id.mapView); + mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { + @Override + public void onMapChanged(int change) { + Timber.e("OnMapChange: %s, %s", change, mapChangeMap.get(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 LongSparseArray<String> buildMapChangeStringValueSparseArray() { + LongSparseArray<String> mapChangeArray = new LongSparseArray<>(); + mapChangeArray.put(MapView.REGION_WILL_CHANGE, "Region will change"); + mapChangeArray.put(MapView.REGION_WILL_CHANGE_ANIMATED, "Region will change animated"); + mapChangeArray.put(MapView.REGION_IS_CHANGING, "Region is changing"); + mapChangeArray.put(MapView.REGION_DID_CHANGE, "Region did change"); + mapChangeArray.put(MapView.REGION_DID_CHANGE_ANIMATED, "Region did change animated"); + mapChangeArray.put(MapView.WILL_START_LOADING_MAP, "Will start loading map"); + mapChangeArray.put(MapView.DID_FINISH_LOADING_MAP, "Did finish loading map"); + mapChangeArray.put(MapView.DID_FAIL_LOADING_MAP, "Did fail loading map"); + mapChangeArray.put(MapView.WILL_START_RENDERING_FRAME, "Will start rendering frame"); + mapChangeArray.put(MapView.DID_FINISH_RENDERING_FRAME, "Did finish rendering frame"); + mapChangeArray.put(MapView.DID_FINISH_RENDERING_FRAME_FULLY_RENDERED, "Did finish rendering frame fully rendered"); + mapChangeArray.put(MapView.WILL_START_RENDERING_MAP, "Will start rendering map"); + mapChangeArray.put(MapView.DID_FINISH_RENDERING_MAP, "Did finish rendering map"); + mapChangeArray.put(MapView.DID_FINISH_RENDERING_MAP_FULLY_RENDERED, "Did finish rendering map fully rendered"); + mapChangeArray.put(MapView.DID_FINISH_LOADING_STYLE, "Did finish loading style"); + mapChangeArray.put(MapView.SOURCE_DID_CHANGE, "Source did change"); + return mapChangeArray; + } + + @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/MapInDialogActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java index 495360a168..f0827c65cc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapInDialogActivity.java @@ -1,6 +1,8 @@ package com.mapbox.mapboxsdk.testapp.activity.maplayout; +import android.app.Dialog; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentManager; @@ -65,6 +67,22 @@ public class MapInDialogActivity extends AppCompatActivity { mapView.onCreate(savedInstanceState); } + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new Dialog(getActivity(), getTheme()) { + boolean destroyed = false; + @Override + public void dismiss() { + if (mapView != null && !destroyed) { + mapView.onDestroy(); + destroyed = true; + } + super.dismiss(); + } + }; + } + @Override public void onStart() { super.onStart(); @@ -90,12 +108,6 @@ public class MapInDialogActivity extends AppCompatActivity { } @Override - public void onDestroy() { - super.onDestroy(); - mapView.onDestroy(); - } - - @Override public void onLowMemory() { super.onLowMemory(); mapView.onLowMemory(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java deleted file mode 100644 index 888482b219..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/NavigationDrawerActivity.java +++ /dev/null @@ -1,252 +0,0 @@ -package com.mapbox.mapboxsdk.testapp.activity.maplayout; - -import android.app.Activity; -import android.app.Fragment; -import android.app.FragmentManager; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.design.widget.Snackbar; -import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.ActionBar; -import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import com.mapbox.mapboxsdk.camera.CameraPosition; -import com.mapbox.mapboxsdk.constants.Style; -import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.maps.MapFragment; -import com.mapbox.mapboxsdk.maps.MapboxMap; -import com.mapbox.mapboxsdk.maps.MapboxMapOptions; -import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; -import com.mapbox.mapboxsdk.testapp.R; - -public class NavigationDrawerActivity extends AppCompatActivity { - - private boolean firstStyle = true; - private MapboxMap mapboxMap; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_navigation_drawer); - - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - NavigationDrawerFragment navigationDrawerFragment; - - getFragmentManager() - .beginTransaction() - .add(R.id.navigation_drawer, navigationDrawerFragment = new NavigationDrawerFragment()) - .commit(); - - navigationDrawerFragment.setUp(this, - R.id.navigation_drawer, - (DrawerLayout) findViewById(R.id.drawer_layout), - getSupportActionBar()); - } - - public void onNavigationDrawerItemSelected(int position) { - // update the main content by replacing fragments - switch (position) { - case 0: - // options - MapboxMapOptions options = new MapboxMapOptions(); - options.styleUrl(firstStyle ? Style.LIGHT : Style.SATELLITE); - options.camera(new CameraPosition.Builder() - .target(new LatLng(39.913271, 116.413891)) - .zoom(12) - .build()); - - // fragment - MapFragment mapFragment = MapFragment.newInstance(options); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction() - .replace(R.id.container, mapFragment) - .commit(); - - // get callback when map is ready - mapFragment.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(MapboxMap map) { - mapboxMap = map; - } - }); - - firstStyle = !firstStyle; - break; - case 1: - Snackbar.make( - findViewById(android.R.id.content), - "Hello from snackbar", - Snackbar.LENGTH_LONG) - .show(); - break; - } - } - - public static class NavigationDrawerFragment extends Fragment { - - private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position"; - private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned"; - - private ActionBarDrawerToggle drawerToggle; - - private DrawerLayout drawerLayout; - private ListView drawerListView; - private View fragmentContainerView; - - private int currentSelectedPosition = 0; - private boolean fromSavedInstanceState; - private boolean userLearnedDrawer; - - public NavigationDrawerFragment() { - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); - userLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false); - - if (savedInstanceState != null) { - currentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION); - fromSavedInstanceState = true; - } - selectItem(currentSelectedPosition); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setHasOptionsMenu(true); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - drawerListView = (ListView) inflater.inflate( - R.layout.drawer_navigation_drawer, container, false); - drawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - selectItem(position); - } - }); - drawerListView.setAdapter(new ArrayAdapter<>( - inflater.getContext(), - android.R.layout.simple_list_item_activated_1, - android.R.id.text1, - new String[] { - "Different style", - "Show snackbar" - })); - drawerListView.setItemChecked(currentSelectedPosition, true); - return drawerListView; - } - - /** - * Users of this fragment must call this method to set up the navigation drawer interactions. - * - * @param fragmentId The android:id of this fragment in its activity's layout. - * @param drawerLayout The DrawerLayout containing this fragment's UI. - */ - public void setUp(Activity activity, int fragmentId, DrawerLayout drawerLayout, ActionBar actionBar) { - fragmentContainerView = activity.findViewById(fragmentId); - this.drawerLayout = drawerLayout; - // drawerLayout.setScrimColor(Color.TRANSPARENT); - - actionBar.setDisplayHomeAsUpEnabled(true); - actionBar.setHomeButtonEnabled(true); - - drawerToggle = new ActionBarDrawerToggle( - activity, - NavigationDrawerFragment.this.drawerLayout, - R.string.navigation_drawer_open, - R.string.navigation_drawer_close - ) { - @Override - public void onDrawerClosed(View drawerView) { - super.onDrawerClosed(drawerView); - if (!isAdded()) { - return; - } - getActivity().invalidateOptionsMenu(); - } - - @Override - public void onDrawerOpened(View drawerView) { - super.onDrawerOpened(drawerView); - if (!isAdded()) { - return; - } - - if (!userLearnedDrawer) { - userLearnedDrawer = true; - SharedPreferences sp = PreferenceManager - .getDefaultSharedPreferences(getActivity()); - sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply(); - } - getActivity().invalidateOptionsMenu(); - } - }; - - if (!userLearnedDrawer && !fromSavedInstanceState) { - this.drawerLayout.openDrawer(fragmentContainerView); - } - this.drawerLayout.post(new Runnable() { - @Override - public void run() { - drawerToggle.syncState(); - } - }); - this.drawerLayout.setDrawerListener(drawerToggle); - } - - private void selectItem(int position) { - currentSelectedPosition = position; - if (drawerListView != null) { - drawerListView.setItemChecked(position, true); - } - if (drawerLayout != null) { - drawerLayout.closeDrawer(fragmentContainerView); - } - - Activity activity = getActivity(); - if (activity != null && activity instanceof NavigationDrawerActivity) { - NavigationDrawerActivity navActivity = (NavigationDrawerActivity) activity; - navActivity.onNavigationDrawerItemSelected(position); - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - drawerToggle.onConfigurationChanged(newConfig); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (drawerToggle.onOptionsItemSelected(item)) { - return true; - } - return super.onOptionsItemSelected(item); - } - } -} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java index badb6718cf..8f8a5af3cc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/SimpleMapActivity.java @@ -1,18 +1,11 @@ package com.mapbox.mapboxsdk.testapp.activity.maplayout; import android.os.Bundle; -import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; -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.maps.Projection; import com.mapbox.mapboxsdk.testapp.R; -import timber.log.Timber; - /** * Test activity showcasing a simple MapView without any MapboxMap interaction. */ @@ -27,19 +20,6 @@ public class SimpleMapActivity extends AppCompatActivity { mapView = (MapView) findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); - mapView.getMapAsync(new OnMapReadyCallback() { - @Override - public void onMapReady(MapboxMap mapboxMap) { - final Projection projection = mapboxMap.getProjection(); - - mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() { - @Override - public void onMapClick(@NonNull LatLng point) { - Timber.e(projection.getVisibleRegion().toString()); - } - }); - } - }); } @Override 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..393abb7cd4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/VisibilityChangeActivity.java @@ -0,0 +1,146 @@ +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 currentStep; + + VisibilityRunner(MapView mapView, View viewParent, Handler handler) { + this.mapView = mapView; + this.viewParent = viewParent; + this.handler = handler; + } + + @Override + public void run() { + if (isViewHiearchyReady()) { + if (isEvenStep()) { + viewParent.setVisibility(View.VISIBLE); + mapView.setVisibility(View.VISIBLE); + } else if (isFirstOrThirdStep()) { + mapView.setVisibility(getVisibilityForStep()); + } else if (isFifthOrSeventhStep()) { + viewParent.setVisibility(getVisibilityForStep()); + } + updateStep(); + } + handler.postDelayed(this, 1500); + } + + private void updateStep() { + if (currentStep == 7) { + currentStep = 0; + } else { + currentStep++; + } + } + + private int getVisibilityForStep() { + return (currentStep == 1 || currentStep == 5) ? View.GONE : View.INVISIBLE; + } + + private boolean isFifthOrSeventhStep() { + return currentStep == 5 || currentStep == 7; + } + + private boolean isFirstOrThirdStep() { + return currentStep == 1 || currentStep == 3; + } + + private boolean isEvenStep() { + return currentStep == 0 || currentStep % 2 == 0; + } + + private boolean isViewHiearchyReady() { + return mapView != null && viewParent != null; + } + } + + @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/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java index 344e9e140a..5bffd4d930 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java @@ -12,7 +12,6 @@ import android.widget.Toast; import com.mapbox.mapboxsdk.Mapbox; import com.mapbox.mapboxsdk.camera.CameraPosition; import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.geometry.LatLngBounds; @@ -75,8 +74,7 @@ public class OfflineActivity extends AppCompatActivity // state of your app. This will override any checks performed via the ConnectivityManager. // Mapbox.getInstance().setConnected(false); Boolean connected = Mapbox.isConnected(); - Timber.d(String.format(MapboxConstants.MAPBOX_LOCALE, - "Mapbox is connected: %b", connected)); + Timber.d("Mapbox is connected: %s", connected); // Set up map mapView = (MapView) findViewById(R.id.mapView); @@ -207,7 +205,7 @@ public class OfflineActivity extends AppCompatActivity @Override public void onError(String error) { - Timber.e("Error: " + error); + Timber.e("Error: %s" , error); } }); } @@ -223,7 +221,7 @@ public class OfflineActivity extends AppCompatActivity } // Start progress bar - Timber.d("Download started: " + regionName); + Timber.d("Download started: %s", regionName); startProgress(); // Definition @@ -241,14 +239,14 @@ public class OfflineActivity extends AppCompatActivity offlineManager.createOfflineRegion(definition, metadata, new OfflineManager.CreateOfflineRegionCallback() { @Override public void onCreate(OfflineRegion offlineRegion) { - Timber.d("Offline region created: " + regionName); + Timber.d("Offline region created: %s" , regionName); OfflineActivity.this.offlineRegion = offlineRegion; launchDownload(); } @Override public void onError(String error) { - Timber.e("Error: " + error); + Timber.e("Error: %s", error); } }); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java new file mode 100644 index 0000000000..6b1cb920fc --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/snapshot/MapSnapshotterActivity.java @@ -0,0 +1,131 @@ +package com.mapbox.mapboxsdk.testapp.activity.snapshot; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.ViewTreeObserver; +import android.widget.GridLayout; +import android.widget.ImageView; + +import com.mapbox.mapboxsdk.camera.CameraPosition; +import com.mapbox.mapboxsdk.constants.Style; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.geometry.LatLngBounds; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.snapshotter.MapSnapshotter; +import com.mapbox.mapboxsdk.testapp.R; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import timber.log.Timber; + +/** + * Test activity showing how to use a the {@link com.mapbox.mapboxsdk.snapshotter.MapSnapshotter} + */ +public class MapSnapshotterActivity extends AppCompatActivity { + + private GridLayout grid; + private List<MapSnapshotter> snapshotters = new ArrayList<>(); + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_map_snapshotter); + + // Find the grid view and start snapshotting as soon + // as the view is measured + grid = (GridLayout) findViewById(R.id.snapshot_grid); + grid.getViewTreeObserver() + .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + //noinspection deprecation + grid.getViewTreeObserver().removeGlobalOnLayoutListener(this); + addSnapshots(); + } + }); + } + + private void addSnapshots() { + Timber.i("Creating snapshotters"); + + for (int row = 0; row < grid.getRowCount(); row++) { + for (int column = 0; column < grid.getColumnCount(); column++) { + startSnapShot(row, column); + } + } + } + + private void startSnapShot(final int row, final int column) { + + // Define the dimensions + MapSnapshotter.Options options = new MapSnapshotter.Options( + grid.getMeasuredWidth() / grid.getColumnCount(), + grid.getMeasuredHeight() / grid.getRowCount() + ) + // Optionally the pixel ratio + .withPixelRatio(1) + + // Optionally the style + .withStyle((column + row) % 2 == 0 ? Style.TRAFFIC_DAY : Style.DARK); + + // Optionally the visible region + if (row % 2 == 0) { + options.withRegion(new LatLngBounds.Builder() + .include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .include(new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .build() + ); + } + + // Optionally the camera options + if (column % 2 == 0) { + options.withCameraPosition(new CameraPosition.Builder() + .target(options.getRegion() != null + ? options.getRegion().getCenter() + : new LatLng(randomInRange(-80, 80), randomInRange(-160, 160))) + .bearing(randomInRange(0, 360)) + .tilt(randomInRange(0, 60)) + .zoom(randomInRange(0, 20)) + .build() + ); + } + + MapSnapshotter snapshotter = new MapSnapshotter(MapSnapshotterActivity.this, options); + + snapshotter.start(new MapboxMap.SnapshotReadyCallback() { + @Override + public void onSnapshotReady(Bitmap snapshot) { + Timber.i("Got the snapshot"); + ImageView imageView = new ImageView(MapSnapshotterActivity.this); + imageView.setImageBitmap(snapshot); + grid.addView( + imageView, + new GridLayout.LayoutParams(GridLayout.spec(row), GridLayout.spec(column)) + ); + } + }); + snapshotters.add(snapshotter); + } + + @Override + public void onPause() { + super.onPause(); + + // Make sure to stop the snapshotters on pause + for (MapSnapshotter snapshotter : snapshotters) { + snapshotter.cancel(); + } + snapshotters.clear(); + } + + private static Random random = new Random(); + + public static float randomInRange(float min, float max) { + return (random.nextFloat() * (max - min)) + min; + } + +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java new file mode 100644 index 0000000000..1beba632b0 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/AnimatedImageSourceActivity.java @@ -0,0 +1,148 @@ +package com.mapbox.mapboxsdk.testapp.activity.style; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.Bundle; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AppCompatActivity; + +import com.mapbox.mapboxsdk.Mapbox; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.mapbox.mapboxsdk.geometry.LatLngQuad; +import com.mapbox.mapboxsdk.maps.MapView; +import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; +import com.mapbox.mapboxsdk.style.layers.RasterLayer; +import com.mapbox.mapboxsdk.style.sources.ImageSource; + +import com.mapbox.mapboxsdk.testapp.R; + +/** + * Test activity showing how to use a series of images to create an animation + * with an ImageSource + * <p> + * GL-native equivalent of https://www.mapbox.com/mapbox-gl-js/example/animate-images/ + * </p> + */ +public class AnimatedImageSourceActivity extends AppCompatActivity implements OnMapReadyCallback { + + private static final String ID_IMAGE_SOURCE = "animated_image_source"; + private static final String ID_IMAGE_LAYER = "animated_image_layer"; + + private MapView mapView; + private MapboxMap mapboxMap; + + private Handler handler; + private Runnable runnable; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_animated_image_source); + + mapView = (MapView) findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(this); + } + + @Override + public void onMapReady(@NonNull final MapboxMap map) { + mapboxMap = map; + + // add source + LatLngQuad quad = new LatLngQuad( + new LatLng(46.437, -80.425), + new LatLng(46.437, -71.516), + new LatLng(37.936, -71.516), + new LatLng(37.936, -80.425)); + mapboxMap.addSource(new ImageSource(ID_IMAGE_SOURCE, quad, R.drawable.southeast_radar_0)); + + // add layer + RasterLayer layer = new RasterLayer(ID_IMAGE_LAYER, ID_IMAGE_SOURCE); + mapboxMap.addLayer(layer); + + // loop refresh geojson + handler = new Handler(); + runnable = new RefreshImageRunnable(mapboxMap, handler); + handler.postDelayed(runnable, 100); + } + + @Override + protected void onStart() { + super.onStart(); + mapView.onStart(); + } + + @Override + public void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + mapView.onPause(); + } + + @Override + protected void onStop() { + super.onStop(); + mapView.onStop(); + handler.removeCallbacks(runnable); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + private static class RefreshImageRunnable implements Runnable { + + private MapboxMap mapboxMap; + private Handler handler; + private Bitmap[] drawables; + private int drawableIndex; + + Bitmap getBitmap(int resourceId) { + Context context = Mapbox.getApplicationContext(); + Drawable drawable = ContextCompat.getDrawable(context, resourceId); + if (drawable instanceof BitmapDrawable) { + BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + return bitmapDrawable.getBitmap(); + } + return null; + } + + RefreshImageRunnable(MapboxMap mapboxMap, Handler handler) { + this.mapboxMap = mapboxMap; + this.handler = handler; + drawables = new Bitmap[4]; + drawables[0] = getBitmap(R.drawable.southeast_radar_0); + drawables[1] = getBitmap(R.drawable.southeast_radar_1); + drawables[2] = getBitmap(R.drawable.southeast_radar_2); + drawables[3] = getBitmap(R.drawable.southeast_radar_3); + drawableIndex = 1; + } + + @Override + public void run() { + ((ImageSource) mapboxMap.getSource(ID_IMAGE_SOURCE)).setImage(drawables[drawableIndex++]); + if (drawableIndex > 3) { + drawableIndex = 0; + } + handler.postDelayed(this, 1000); + } + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java index 2238d1d5fe..f99a1fdb96 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java @@ -74,7 +74,7 @@ public class CircleLayerActivity extends AppCompatActivity implements View.OnCli source = new GeoJsonSource("bus_stop", new URL("https://raw.githubusercontent.com/cheeaun/busrouter-sg/master/data/2/bus-stops.geojson")); } catch (MalformedURLException exception) { - Timber.e("That's not an url... ", exception); + Timber.e(exception, "That's not an url... "); } mapboxMap.addSource(source); } @@ -132,7 +132,7 @@ public class CircleLayerActivity extends AppCompatActivity implements View.OnCli new URL("https://gist.githubusercontent.com/tobrun/7fbc0fe7e9ffea509f7608cda2601d5d/raw/" + "a4b8cc289020f91fa2e1553524820054395e36f5/line.geojson"))); } catch (MalformedURLException malformedUrlException) { - Timber.e("That's not an url... ", malformedUrlException); + Timber.e(malformedUrlException, "That's not an url... "); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java index 3a5b30f71f..571b48daa6 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java @@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.testapp.activity.style; import android.graphics.Color; import android.os.Bundle; -import android.support.annotation.RawRes; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; @@ -18,14 +17,9 @@ import com.mapbox.mapboxsdk.style.layers.FillLayer; import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; import timber.log.Timber; @@ -355,7 +349,7 @@ public class DataDrivenStyleActivity extends AppCompatActivity { // Add a source Source source; try { - source = new GeoJsonSource("amsterdam-parks-source", readRawResource(R.raw.amsterdam)); + source = new GeoJsonSource("amsterdam-parks-source", ResourceUtils.readRawResource(this, R.raw.amsterdam)); mapboxMap.addSource(source); } catch (IOException ioException) { Toast.makeText( @@ -375,21 +369,4 @@ public class DataDrivenStyleActivity extends AppCompatActivity { ) ); } - - private String readRawResource(@RawRes int rawResource) throws IOException { - InputStream is = getResources().openRawResource(rawResource); - Writer writer = new StringWriter(); - char[] buffer = new char[1024]; - try { - Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - int numRead; - while ((numRead = reader.read(buffer)) != -1) { - writer.write(buffer, 0, numRead); - } - } finally { - is.close(); - } - - return writer.toString(); - } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java index 1ff0b0e8e1..24914fcbb2 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionStyleTestActivity.java @@ -1,6 +1,5 @@ package com.mapbox.mapboxsdk.testapp.activity.style; - import android.os.Bundle; import android.support.v7.app.AppCompatActivity; @@ -9,6 +8,9 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; +/** + * Test activity used for instrumentation tests of fill extrusion. + */ public class FillExtrusionStyleTestActivity extends AppCompatActivity { public MapView mapView; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java index 80dfe777cb..a2111bc304 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java @@ -128,7 +128,7 @@ public class GeoJsonClusteringActivity extends AppCompatActivity { ) ); } catch (MalformedURLException malformedUrlException) { - Timber.e("That's not an url... " + malformedUrlException.getMessage()); + Timber.e(malformedUrlException,"That's not an url... "); } // Add unclustered layer diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java index b9f7ebce35..b9f1dfe810 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RealTimeGeoJsonActivity.java @@ -55,7 +55,7 @@ public class RealTimeGeoJsonActivity extends AppCompatActivity implements OnMapR try { mapboxMap.addSource(new GeoJsonSource(ID_GEOJSON_SOURCE, new URL(URL_GEOJSON_SOURCE))); } catch (MalformedURLException malformedUrlException) { - Timber.e("Invalid URL", malformedUrlException); + Timber.e(malformedUrlException, "Invalid URL"); } // add layer diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java index f6754af0f9..adce889007 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java @@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.testapp.activity.style; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.RawRes; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; @@ -32,16 +31,11 @@ import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.mapboxsdk.style.sources.TileSet; import com.mapbox.mapboxsdk.style.sources.VectorSource; import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils; import com.mapbox.services.commons.geojson.Feature; import com.mapbox.services.commons.geojson.FeatureCollection; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -285,7 +279,7 @@ public class RuntimeStyleActivity extends AppCompatActivity { // Add a source Source source; try { - source = new GeoJsonSource("amsterdam-spots", readRawResource(R.raw.amsterdam)); + source = new GeoJsonSource("amsterdam-spots", ResourceUtils.readRawResource(this, R.raw.amsterdam)); } catch (IOException ioException) { Toast.makeText( RuntimeStyleActivity.this, @@ -317,12 +311,12 @@ public class RuntimeStyleActivity extends AppCompatActivity { layer = mapboxMap.getLayerAs("parksLayer"); // And get some properties PropertyValue<Boolean> fillAntialias = layer.getFillAntialias(); - Timber.d("Fill anti alias: " + fillAntialias.getValue()); + Timber.d("Fill anti alias: %s", fillAntialias.getValue()); layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP)); PropertyValue<String> fillTranslateAnchor = layer.getFillTranslateAnchor(); - Timber.d("Fill translate anchor: " + fillTranslateAnchor.getValue()); + Timber.d("Fill translate anchor: %s", fillTranslateAnchor.getValue()); PropertyValue<String> visibility = layer.getVisibility(); - Timber.d("Visibility: " + visibility.getValue()); + Timber.d("Visibility: %s", visibility.getValue()); // Get a good look at it all mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12)); @@ -332,7 +326,7 @@ public class RuntimeStyleActivity extends AppCompatActivity { // Load some data FeatureCollection parks; try { - String json = readRawResource(R.raw.amsterdam); + String json = ResourceUtils.readRawResource(this, R.raw.amsterdam); parks = FeatureCollection.fromJson(json); } catch (IOException ioException) { Toast.makeText( @@ -477,33 +471,16 @@ public class RuntimeStyleActivity extends AppCompatActivity { Function<Float, String> function = (Function<Float, String>) fillColor.getFunction(); if (function != null) { ExponentialStops<Float, String> stops = (ExponentialStops) function.getStops(); - Timber.d("Fill color base: " + stops.getBase()); - Timber.d("Fill color #stops: " + stops.size()); + Timber.d("Fill color base: %s", stops.getBase()); + Timber.d("Fill color #stops: %s", stops.size()); if (function.getStops() != null) { for (Stop<Float, String> stop : stops) { - Timber.d("Fill color #stops: " + stop); + Timber.d("Fill color #stops: %s", stop); } } } } - private String readRawResource(@RawRes int rawResource) throws IOException { - InputStream is = getResources().openRawResource(rawResource); - Writer writer = new StringWriter(); - char[] buffer = new char[1024]; - try { - Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - int numRead; - while ((numRead = reader.read(buffer)) != -1) { - writer.write(buffer, 0, numRead); - } - } finally { - is.close(); - } - - return writer.toString(); - } - private void addCustomTileSource() { // Add a source Source source = new VectorSource("custom-tile-source", new TileSet("2.1.0", "https://vector.mapzen.com/osm/all/{z}/{x}/{y}.mvt?api_key=vector-tiles-LM25tq4")); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java index 6906e90f6e..49015ec1e9 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/StyleFileActivity.java @@ -1,9 +1,9 @@ package com.mapbox.mapboxsdk.testapp.activity.style; +import android.content.Context; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.annotation.RawRes; import android.support.design.widget.FloatingActionButton; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; @@ -14,22 +14,18 @@ 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 com.mapbox.mapboxsdk.testapp.utils.ResourceUtils; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; +import java.lang.ref.WeakReference; import timber.log.Timber; /** - * Test activity showcasing how to use a file:// resource for the style.json + * Test activity showcasing how to use a file:// resource for the style.json and how to use MapboxMap#setStyleJson. */ public class StyleFileActivity extends AppCompatActivity { @@ -48,13 +44,21 @@ public class StyleFileActivity extends AppCompatActivity { public void onMapReady(@NonNull final MapboxMap map) { mapboxMap = map; - FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); + FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_file); fab.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary)); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - Timber.i("Loading style file"); - new CreateStyleFileTask().execute(); + new CreateStyleFileTask(view.getContext(), mapboxMap).execute(); + } + }); + + FloatingActionButton fabStyleJson = (FloatingActionButton) findViewById(R.id.fab_style_json); + fabStyleJson.setColorFilter(ContextCompat.getColor(StyleFileActivity.this, R.color.primary)); + fabStyleJson.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + new LoadStyleFileTask(view.getContext(), mapboxMap).execute(); } }); } @@ -62,44 +66,74 @@ public class StyleFileActivity extends AppCompatActivity { } /** + * Task to read a style file from the raw folder + */ + private static class LoadStyleFileTask extends AsyncTask<Void, Void, String> { + private WeakReference<Context> context; + private WeakReference<MapboxMap> mapboxMap; + + LoadStyleFileTask(Context context, MapboxMap mapboxMap) { + this.context = new WeakReference<>(context); + this.mapboxMap = new WeakReference<>(mapboxMap); + } + + @Override + protected String doInBackground(Void... voids) { + String styleJson = ""; + try { + styleJson = ResourceUtils.readRawResource(context.get(), R.raw.sat_style); + } catch (Exception exception) { + Timber.e(exception, "Can't load local file style"); + } + return styleJson; + } + + @Override + protected void onPostExecute(String json) { + super.onPostExecute(json); + Timber.d("Read json, %s", json); + MapboxMap mapboxMap = this.mapboxMap.get(); + if (mapboxMap != null) { + mapboxMap.setStyleJson(json); + } + } + } + + /** * Task to write a style file to local disk and load it in the map view */ - private class CreateStyleFileTask extends AsyncTask<Void, Integer, Long> { + private static class CreateStyleFileTask extends AsyncTask<Void, Integer, Long> { private File cacheStyleFile; + private WeakReference<Context> context; + private WeakReference<MapboxMap> mapboxMap; + + CreateStyleFileTask(Context context, MapboxMap mapboxMap) { + this.context = new WeakReference<>(context); + this.mapboxMap = new WeakReference<>(mapboxMap); + } @Override protected Long doInBackground(Void... params) { try { cacheStyleFile = File.createTempFile("my-", ".style.json"); cacheStyleFile.createNewFile(); - Timber.i("Writing style file to: " + cacheStyleFile.getAbsolutePath()); - writeToFile(cacheStyleFile, readRawResource(R.raw.local_style)); + Timber.i("Writing style file to: %s", cacheStyleFile.getAbsolutePath()); + Context context = this.context.get(); + if (context != null) { + writeToFile(cacheStyleFile, ResourceUtils.readRawResource(context, R.raw.local_style)); + } } catch (Exception exception) { - Toast.makeText(StyleFileActivity.this, "Could not create style file in cache dir", Toast.LENGTH_SHORT).show(); + Toast.makeText(context.get(), "Could not create style file in cache dir", Toast.LENGTH_SHORT).show(); } return 1L; } protected void onPostExecute(Long result) { // Actual file:// usage - mapboxMap.setStyleUrl("file://" + cacheStyleFile.getAbsolutePath()); - } - - private String readRawResource(@RawRes int rawResource) throws IOException { - InputStream is = getResources().openRawResource(rawResource); - Writer writer = new StringWriter(); - char[] buffer = new char[1024]; - try { - Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - int numRead; - while ((numRead = reader.read(buffer)) != -1) { - writer.write(buffer, 0, numRead); - } - } finally { - is.close(); + MapboxMap mapboxMap = this.mapboxMap.get(); + if (mapboxMap != null) { + mapboxMap.setStyleUrl("file://" + cacheStyleFile.getAbsolutePath()); } - - return writer.toString(); } private void writeToFile(File file, String contents) throws IOException { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java new file mode 100644 index 0000000000..0eaccfef0c --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java @@ -0,0 +1,216 @@ +package com.mapbox.mapboxsdk.testapp.activity.style; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.support.v7.app.AppCompatActivity; +import android.graphics.Color; +import android.graphics.PointF; +import android.os.Bundle; +import android.support.annotation.NonNull; + +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.GsonBuilder; +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.style.layers.SymbolLayer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; +import com.mapbox.mapboxsdk.style.sources.Source; +import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils; +import com.mapbox.services.commons.geojson.Feature; +import com.mapbox.services.commons.geojson.FeatureCollection; +import com.mapbox.services.commons.geojson.Geometry; +import com.mapbox.services.commons.geojson.custom.GeometryDeserializer; +import com.mapbox.services.commons.geojson.custom.PositionDeserializer; +import com.mapbox.services.commons.models.Position; + +import java.io.IOException; + +import java.util.List; + +import timber.log.Timber; + +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage; + +/** + * Test activity showcasing using a symbol generator that generates Bitmaps from Android SDK Views. + */ +public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapReadyCallback { + + private static final String SOURCE_ID = "com.mapbox.mapboxsdk.style.layers.symbol.source.id"; + private static final String LAYER_ID = "com.mapbox.mapboxsdk.style.layers.symbol.layer.id"; + private static final String FEATURE_ID = "brk_name"; + private static final String FEATURE_VALUE = "name_sort"; + + private MapView mapView; + private MapboxMap mapboxMap; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_symbol_generator); + + mapView = (MapView) findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(this); + } + + @Override + public void onMapReady(MapboxMap map) { + mapboxMap = map; + try { + // read local geojson from raw folder + String tinyCountriesJson = ResourceUtils.readRawResource(this, R.raw.tiny_countries); + + // convert geojson to a model + FeatureCollection featureCollection = new GsonBuilder() + .registerTypeAdapter(Geometry.class, new GeometryDeserializer()) + .registerTypeAdapter(Position.class, new PositionDeserializer()) + .create().fromJson(tinyCountriesJson, FeatureCollection.class); + + // add a geojson to the map + Source source = new GeoJsonSource(SOURCE_ID, featureCollection); + mapboxMap.addSource(source); + + // for each feature add a symbolLayer + for (Feature feature : featureCollection.getFeatures()) { + String countryName = feature.getStringProperty(FEATURE_ID); + + // create View + TextView textView = new TextView(this); + textView.setBackgroundColor(getResources().getColor(R.color.blueAccent)); + textView.setPadding(10, 5, 10, 5); + textView.setTextColor(Color.WHITE); + textView.setText(countryName); + + // create bitmap from view + mapboxMap.addImage(countryName, SymbolGenerator.generate(textView)); + } + + // create layer use + mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID) + .withProperties( + iconImage("{" + FEATURE_ID + "}"), // { } is a token notation + iconAllowOverlap(false) + ) + ); + + addSymbolClickListener(); + } catch (IOException exception) { + Timber.e(exception); + } + } + + private void addSymbolClickListener() { + mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() { + @Override + public void onMapClick(@NonNull LatLng point) { + PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point); + List<Feature> features = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID); + if (!features.isEmpty()) { + Feature feature = features.get(0); + Timber.v("Feature was clicked with data: %s", feature.toJson()); + Toast.makeText( + SymbolGeneratorActivity.this, + "hello from: " + feature.getStringProperty(FEATURE_VALUE), + Toast.LENGTH_LONG).show(); + } + } + }); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_generator_symbol, menu); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_action_icon_overlap) { + SymbolLayer layer = mapboxMap.getLayerAs(LAYER_ID); + layer.setProperties(iconAllowOverlap(!layer.getIconAllowOverlap().getValue())); + } + return super.onOptionsItemSelected(item); + } + + @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 onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } + + /** + * Utility class to generate Bitmaps for Symbol. + * <p> + * Bitmaps can be added to the map with {@link com.mapbox.mapboxsdk.maps.MapboxMap#addImage(String, Bitmap)} + * </p> + */ + private static class SymbolGenerator { + + /** + * Generate a Bitmap from an Android SDK View. + * + * @param view the View to be drawn to a Bitmap + * @return the generated bitmap + */ + public static Bitmap generate(@NonNull View view) { + int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + view.measure(measureSpec, measureSpec); + + int measuredWidth = view.getMeasuredWidth(); + int measuredHeight = view.getMeasuredHeight(); + + view.layout(0, 0, measuredWidth, measuredHeight); + Bitmap bitmap = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888); + bitmap.eraseColor(Color.TRANSPARENT); + Canvas canvas = new Canvas(bitmap); + view.draw(canvas); + return bitmap; + } + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java new file mode 100644 index 0000000000..cd741a85b6 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java @@ -0,0 +1,171 @@ +package com.mapbox.mapboxsdk.testapp.activity.style; + +import android.graphics.PointF; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v7.app.AppCompatActivity; + +import com.google.gson.JsonObject; +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.style.layers.SymbolLayer; +import com.mapbox.mapboxsdk.style.sources.GeoJsonSource; +import com.mapbox.mapboxsdk.testapp.R; +import com.mapbox.services.commons.geojson.Feature; +import com.mapbox.services.commons.geojson.FeatureCollection; +import com.mapbox.services.commons.geojson.Point; +import com.mapbox.services.commons.models.Position; + +import java.util.List; + +import timber.log.Timber; + +import static com.mapbox.mapboxsdk.style.functions.Function.property; +import static com.mapbox.mapboxsdk.style.functions.Function.zoom; +import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop; +import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical; +import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize; + +/** + * Test activity showcasing changing the icon with a zoom function and adding selection state to a SymbolLayer. + */ +public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity { + + private static final String LAYER_ID = "symbolLayer"; + private static final String SOURCE_ID = "poiSource"; + private static final String BUS_MAKI_ICON_ID = "bus-11"; + private static final String CAFE_MAKI_ICON_ID = "cafe-11"; + private static final String KEY_PROPERTY_SELECTED = "selected"; + private static final float ZOOM_STOP_MIN_VALUE = 7.0f; + private static final float ZOOM_STOP_MAX_VALUE = 12.0f; + + private MapView mapView; + private MapboxMap mapboxMap; + private GeoJsonSource source; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_zoom_symbol_layer); + + mapView = (MapView) findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + mapView.getMapAsync(new OnMapReadyCallback() { + @Override + public void onMapReady(@NonNull final MapboxMap map) { + mapboxMap = map; + updateSource(false); + addLayer(); + addMapClickListener(); + } + }); + } + + private void updateSource(boolean selected) { + FeatureCollection featureCollection = createFeatureCollection(selected); + if (source != null) { + source.setGeoJson(featureCollection); + } else { + source = new GeoJsonSource(SOURCE_ID, featureCollection); + mapboxMap.addSource(source); + } + } + + private FeatureCollection createFeatureCollection(boolean selected) { + Point point = Point.fromCoordinates(Position.fromCoordinates(-74.016181, 40.701745)); + Feature feature = Feature.fromGeometry(point); + JsonObject properties = new JsonObject(); + properties.addProperty(KEY_PROPERTY_SELECTED, selected); + feature.setProperties(properties); + return FeatureCollection.fromFeatures(new Feature[] {feature}); + } + + private void addLayer() { + SymbolLayer layer = new SymbolLayer(LAYER_ID, SOURCE_ID); + layer.setProperties( + iconImage( + zoom( + interval( + stop(ZOOM_STOP_MIN_VALUE, iconImage(BUS_MAKI_ICON_ID)), + stop(ZOOM_STOP_MAX_VALUE, iconImage(CAFE_MAKI_ICON_ID)) + ) + ) + ), + iconSize( + property( + KEY_PROPERTY_SELECTED, + categorical( + stop(true, iconSize(3.0f)), + stop(false, iconSize(1.0f)) + ) + ) + ), + iconAllowOverlap(true) + ); + mapboxMap.addLayer(layer); + } + + private void addMapClickListener() { + mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() { + @Override + public void onMapClick(@NonNull LatLng point) { + PointF screenPoint = mapboxMap.getProjection().toScreenLocation(point); + List<Feature> featureList = mapboxMap.queryRenderedFeatures(screenPoint, LAYER_ID); + if (!featureList.isEmpty()) { + Feature feature = featureList.get(0); + boolean isSelected = feature.getBooleanProperty(KEY_PROPERTY_SELECTED); + updateSource(!isSelected); + } else { + Timber.e("No features found"); + } + } + }); + } + + @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 onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mapView.onLowMemory(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java index f41e5e38f0..71b8115d2e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java @@ -14,6 +14,9 @@ import com.mapbox.services.android.telemetry.permissions.PermissionsManager; import java.util.List; +/** + * Base class for location aware activities. + */ public abstract class BaseLocationActivity extends AppCompatActivity implements PermissionsListener { private PermissionsManager permissionsManager; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java index b0ea9c608b..e954b73f8d 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java @@ -12,6 +12,9 @@ import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; import com.mapbox.mapboxsdk.testapp.R; +/** + * Test activity showcasing using a custom location engine. + */ public class CustomLocationEngineActivity extends BaseLocationActivity { private MapView mapView; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java index 69e6d64325..9f6f2b2fcd 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java @@ -50,7 +50,7 @@ public class MyLocationDrawableActivity extends BaseLocationActivity implements mapView = new MapView(this, mapboxMapOptions); mapView.setId(R.id.mapView); - ViewGroup parent = (ViewGroup) findViewById(R.id.container); + ViewGroup parent = (ViewGroup) findViewById(android.R.id.content); parent.addView(mapView); mapView.onCreate(savedInstanceState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java index d465d676f7..718c10c7cb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java @@ -11,6 +11,9 @@ import com.mapbox.mapboxsdk.testapp.R; import timber.log.Timber; +/** + * Test activity showcasing toggling the user location on the map. + */ public class MyLocationToggleActivity extends BaseLocationActivity { private MapView mapView; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java deleted file mode 100644 index aaef7f8a51..0000000000 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.mapbox.mapboxsdk.testapp.model.constants; - -public class AppConstant { - - public static final int STYLE_VERSION = 9; -} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java index 8c049d7730..aaad2f04ab 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java @@ -11,5 +11,6 @@ public class ExampleCustomLayer { public static long InitializeFunction; public static long RenderFunction; + public static long ContextLostFunction; public static long DeinitializeFunction; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java index f717daeada..76f07ba526 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java @@ -32,7 +32,7 @@ public class OfflineListRegionsDialog extends DialogFragment { .setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - Timber.d("Selected item: " + which); + Timber.d("Selected item: %s", which); } }) .setPositiveButton("Accept", new DialogInterface.OnClickListener() { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java index 8c6ab3e211..6220dc7e69 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/OfflineUtils.java @@ -29,7 +29,7 @@ public class OfflineUtils { String json = jsonObject.toString(); metadata = json.getBytes(JSON_CHARSET); } catch (Exception exception) { - Timber.e("Failed to encode metadata: " + exception.getMessage()); + Timber.e(exception, "Failed to encode metadata: "); } return metadata; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java new file mode 100644 index 0000000000..f0cca57e10 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java @@ -0,0 +1,36 @@ +package com.mapbox.mapboxsdk.testapp.utils; + +import android.content.Context; +import android.support.annotation.RawRes; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.io.Writer; + +public class ResourceUtils { + + public static String readRawResource(Context context, @RawRes int rawResource) throws IOException { + String json = ""; + if (context != null) { + InputStream is = context.getResources().openRawResource(rawResource); + Writer writer = new StringWriter(); + char[] buffer = new char[1024]; + try { + Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); + int numRead; + while ((numRead = reader.read(buffer)) != -1) { + writer.write(buffer, 0, numRead); + } + } finally { + is.close(); + } + json = writer.toString(); + } + return json; + } +} + diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java index 6f20d6fb0f..235fd8233b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java @@ -146,15 +146,15 @@ public class TimingLogger { if (disabled) { return; } - Timber.d(label + ": begin"); + Timber.d("%s: begin", label); final long first = splits.get(0); long now = first; for (int i = 1; i < splits.size(); i++) { now = splits.get(i); final String splitLabel = splitLabels.get(i); final long prev = splits.get(i - 1); - Timber.d(label + ": " + (now - prev) + " ms, " + splitLabel); + Timber.d("%s: %s ms, %s", label, (now - prev), splitLabel); } - Timber.d(label + ": end, " + (now - first) + " ms"); + Timber.d("%s: end, %s ms", label, (now - first)); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TokenUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TokenUtils.java new file mode 100644 index 0000000000..e08fdb9154 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TokenUtils.java @@ -0,0 +1,37 @@ +package com.mapbox.mapboxsdk.testapp.utils; + + +import android.content.Context; +import android.support.annotation.NonNull; + +import com.mapbox.mapboxsdk.Mapbox; + +public class TokenUtils { + + /** + * <p> + * Returns the Mapbox access token set in the app resources. + * </p> + * It will first search for a token in the Mapbox object. If not found it + * will then attempt to load the access token from the + * {@code res/values/dev.xml} development file. + * + * @param context The {@link Context} of the {@link android.app.Activity} or {@link android.app.Fragment}. + * @return The Mapbox access token or null if not found. + */ + public static String getMapboxAccessToken(@NonNull Context context) { + try { + // Read out AndroidManifest + String token = Mapbox.getAccessToken(); + if (token == null || token.isEmpty()) { + throw new IllegalArgumentException(); + } + return token; + } catch (Exception exception) { + // Use fallback on string resource, used for development + int tokenResId = context.getResources() + .getIdentifier("mapbox_access_token", "string", context.getPackageName()); + return tokenResId != 0 ? context.getString(tokenResId) : null; + } + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/LockableBottomSheetBehavior.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/LockableBottomSheetBehavior.java new file mode 100644 index 0000000000..a69fb48ab4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/LockableBottomSheetBehavior.java @@ -0,0 +1,74 @@ +package com.mapbox.mapboxsdk.testapp.view; + +import android.content.Context; +import android.support.design.widget.BottomSheetBehavior; +import android.support.design.widget.CoordinatorLayout; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +public class LockableBottomSheetBehavior<V extends View> extends BottomSheetBehavior<V> { + + private boolean locked = false; + + public LockableBottomSheetBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public void setLocked(boolean locked) { + this.locked = locked; + } + + @Override + public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { + boolean handled = false; + if (!locked) { + handled = super.onInterceptTouchEvent(parent, child, event); + } + return handled; + } + + @Override + public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { + boolean handled = false; + if (!locked) { + handled = super.onTouchEvent(parent, child, event); + } + return handled; + } + + @Override + public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, + int nestedScrollAxes) { + boolean handled = false; + if (!locked) { + handled = super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes); + } + return handled; + } + + @Override + public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, + int[] consumed) { + if (!locked) { + super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); + } + } + + @Override + public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { + if (!locked) { + super.onStopNestedScroll(coordinatorLayout, child, target); + } + } + + @Override + public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target, float velocityX, + float velocityY) { + boolean handled = false; + if (!locked) { + handled = super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY); + } + return handled; + } +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/MapViewPager.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/MapViewPager.java new file mode 100644 index 0000000000..92c28d7ed4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/view/MapViewPager.java @@ -0,0 +1,20 @@ +package com.mapbox.mapboxsdk.testapp.view; + +import android.content.Context; +import android.support.v4.view.PagerTabStrip; +import android.support.v4.view.ViewPager; +import android.util.AttributeSet; +import android.view.SurfaceView; +import android.view.View; + +public class MapViewPager extends ViewPager { + + public MapViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { + return v instanceof SurfaceView || v instanceof PagerTabStrip || (super.canScroll(v, checkV, dx, x, y)); + } +} |