summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/.gitignore1
-rw-r--r--platform/android/CHANGELOG.md6
-rw-r--r--platform/android/CONTRIBUTING_LINUX.md49
-rw-r--r--platform/android/CONTRIBUTING_OSX.md (renamed from platform/android/INSTALL_OSX.md)2
-rw-r--r--platform/android/DISTRIBUTE.md47
-rw-r--r--platform/android/INSTALL_LINUX.md34
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle6
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java74
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java295
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java42
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java44
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java341
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java352
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java115
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java53
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java180
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java36
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java67
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java489
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java355
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java297
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java96
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java14
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java77
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java145
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java115
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java705
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java146
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java757
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java26
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java97
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java12
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java93
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java90
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/overview.html8
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.pngbin0 -> 1046 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.pngbin0 -> 885 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location.pngbin2783 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_bearing.pngbin5939 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_stale.pngbin2593 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.pngbin0 -> 649 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.pngbin0 -> 555 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location.pngbin2089 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_bearing.pngbin3599 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_stale.pngbin1942 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.pngbin0 -> 1345 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.pngbin0 -> 1096 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location.pngbin3520 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_bearing.pngbin8155 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_stale.pngbin3287 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.pngbin0 -> 1902 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.pngbin0 -> 1586 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location.pngbin5057 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_bearing.pngbin13246 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_stale.pngbin4676 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.pngbin0 -> 3022 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.pngbin0 -> 2456 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location.pngbin5236 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_bearing.pngbin11688 -> 0 bytes
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_stale.pngbin5053 -> 0 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml40
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/README.md2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java28
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CameraActivityTest.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivityTest.java34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivityTest.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivityTest.java34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityScreenTest.java88
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityTest.java257
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivityTest.java34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivityTest.java35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/TiltActivityTest.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BaseTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BaseTest.java)4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BulkMarkerActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DirectionsActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DirectionsActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DynamicMarkerChangeActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivityTest.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/GeocoderActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/GeocoderActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowAdapterActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/LatLngBoundsActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ManualZoomActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapFragmentActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapPaddingActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MaxMinZoomActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivityTest.java)7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MyLocationTrackingModeActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivityTest.java)7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/PolylineActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PolylineActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScreenshotActivityTest.java124
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScrollByActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ScrollByActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/SupportMapFragmentActivityTest.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivityTest.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/DrawerUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/GestureUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java)4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ScreenshotUtil.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java)22
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ViewUtils.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/BaseMainActivityTest.java46
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/CompassViewTest.java48
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleRotateTest.java29
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleZoomTest.java28
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/utils/ViewAssertion.java17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml269
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttfbin0 -> 127488 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttfbin0 -> 126072 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java186
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java150
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java142
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java101
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java685
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java100
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java123
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java136
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java166
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java)17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java307
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java)5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java228
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java124
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java)7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java141
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java)75
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java176
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java)21
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java)9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java)54
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java)11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java)79
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java)9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java)16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivity.java)16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java)24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java106
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java167
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java144
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java131
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java)29
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java)7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java)30
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java136
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java188
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java160
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java)71
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java55
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java178
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java69
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarker.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarkerOptions.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java75
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java104
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/layers/ExampleCustomLayer.java)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/DownloadRegionDialog.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/ListRegionsDialog.java)6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiAccess.java44
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java95
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/TimingLogger.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/rotate_360.xml8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_down.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_up.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_us.pngbin0 -> 418 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_add_a_photo_black_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_blur_on_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_bug_report_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_compare_arrows_black_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_crop_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dns_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dynamic_marker.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_center_focus_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_none_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_find_replace_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_back_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_front_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_gps_fixed_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_adapter.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_concurrent.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_24dp.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_menu_24dp.xml)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_clear_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_map_padding.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_my_location_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_navigation_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_wallpaper_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_widgets_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pin_drop_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_place_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_refresh_24dp.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_mapboxmap.xml)2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_tilt.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_transform_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_trending_up_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/line_divider.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera.xml50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml53
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml36
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_layer.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animate_coordinate.xml)24
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_debug_mode.xml57
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml73
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_fragment.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_padding.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml37
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml32
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapboxmap.xml)23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml38
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polygon.xml (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_tilt.xml)13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml21
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml48
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/dialog_camera_position.xml202
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_double_map.xml7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_main_feature.xml35
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/section_main_layout.xml27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_text_marker.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml221
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_infowindow.xml13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_press_for_marker.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/colors.xml5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/ids.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml163
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java91
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java45
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java210
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java85
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java37
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java15
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java25
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java80
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/StyleInitializerTest.java75
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java138
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java79
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java17
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java299
-rw-r--r--platform/android/README.md18
-rw-r--r--platform/android/bitrise.yml59
-rw-r--r--platform/android/build.gradle7
-rw-r--r--platform/android/gradle/wrapper/gradle-wrapper.properties6
-rw-r--r--platform/android/platform.gyp (renamed from platform/android/mapboxgl-app.gypi)126
-rw-r--r--platform/android/resources/dot-arrow.svg11
-rw-r--r--platform/android/scripts/configure.sh11
-rwxr-xr-xplatform/android/scripts/debug.sh46
-rw-r--r--platform/android/scripts/defaults.mk10
-rwxr-xr-xplatform/android/scripts/install.sh13
-rwxr-xr-xplatform/android/scripts/run.sh56
-rwxr-xr-xplatform/android/scripts/toolchain.sh2
-rw-r--r--platform/android/src/asset_file_source.cpp8
-rw-r--r--platform/android/src/async_task.cpp63
-rw-r--r--platform/android/src/example_custom_layer.cpp6
-rw-r--r--platform/android/src/http_file_source.cpp (renamed from platform/android/src/http_request_android.cpp)100
-rwxr-xr-xplatform/android/src/jni.cpp384
-rw-r--r--platform/android/src/jni.hpp5
-rwxr-xr-xplatform/android/src/native_map_view.cpp182
-rwxr-xr-xplatform/android/src/native_map_view.hpp21
-rw-r--r--platform/android/src/run_loop.cpp213
-rw-r--r--platform/android/src/run_loop_impl.hpp57
-rw-r--r--platform/android/src/timer.cpp78
-rw-r--r--platform/android/tests/docs/UI_TESTS.md8
-rw-r--r--platform/android/tests/docs/UNIT_TESTS.md94
296 files changed, 10839 insertions, 5407 deletions
diff --git a/platform/android/.gitignore b/platform/android/.gitignore
index 57cd31fea2..53e7540178 100644
--- a/platform/android/.gitignore
+++ b/platform/android/.gitignore
@@ -12,7 +12,6 @@ build/
# JNI
MapboxGLAndroidSDK/src/main/jniLibs/
-MapboxGLAndroidSDK/src/main/obj.target/
# Lib assets
MapboxGLAndroidSDK/src/main/assets/
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index 7ba51fd368..f73c5ba198 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -2,6 +2,12 @@
Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started.
+## 4.0.1
+
+Mapbox Android 4.0.1 is a patch release to make this bug fix available sooner.
+
+* MapboxMap.removeAnnotations() doesn't remove markers ([#4553](https://github.com/mapbox/mapbox-gl-native/issues/4553))
+
## 4.0.0
Mapbox Android 4.0.0 contains the following 3 major new features.
diff --git a/platform/android/CONTRIBUTING_LINUX.md b/platform/android/CONTRIBUTING_LINUX.md
new file mode 100644
index 0000000000..875f7a800a
--- /dev/null
+++ b/platform/android/CONTRIBUTING_LINUX.md
@@ -0,0 +1,49 @@
+# Contributing to the Android SDK on Linux
+
+_These instructions were tested on Ubuntu 16.04 LTS (aka Xenial Xerus)._
+
+Install the build dependencies:
+
+```
+$ sudo apt-get install -y android-tools-adb build-essential curl git \
+ lib32stdc++6 lib32z1 openjdk-8-jdk pkg-config python
+```
+
+Install the Android SDK. We recommend doing this by way of [Android command line tools for Linux](http://developer.android.com/sdk/index.html) but you can also achieve same results with the Android Studio package.
+
+Unpack the SDK and make sure you have the proper environment variables set.
+
+```
+$ export PATH=/path/to/android-sdk-linux/tools:$PATH
+$ export ANDROID_HOME=/path/to/android-sdk-linux
+```
+
+Update the Android SDK to the latest version:
+
+```
+$ android update sdk -u
+```
+
+## Setting Mapbox Access Token
+
+_The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/)._
+
+gradle will take the value of the `MAPBOX_ACCESS_TOKEN` environ variable and save it to `platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml` where the app will read it from. Otherwise, you can edit `developer-config.xml` and add the value manually as `mapbox_access_token`.
+
+## Building
+
+Checking out the code:
+
+```
+$ git clone https://github.com/mapbox/mapbox-gl-native.git
+$ cd mapbox-gl-native
+```
+
+Building a debug version will generated a self-signed test application that can be installed on the phone or emulator:
+
+```
+$ BUILDTYPE=Debug make android
+$ adb install -r platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk
+```
+
+The debug version will emit considerable more log information (and run slower). Use simply `make android` to build a release version.
diff --git a/platform/android/INSTALL_OSX.md b/platform/android/CONTRIBUTING_OSX.md
index 00096ebc60..3154ac1087 100644
--- a/platform/android/INSTALL_OSX.md
+++ b/platform/android/CONTRIBUTING_OSX.md
@@ -1,4 +1,4 @@
-# Installing the Mapbox Android SDK on OS X
+# Contributing to the Android SDK on OS X
Install Oracle JDK 7+ and Android Studio:
diff --git a/platform/android/DISTRIBUTE.md b/platform/android/DISTRIBUTE.md
index eb21979347..e7df5650f1 100644
--- a/platform/android/DISTRIBUTE.md
+++ b/platform/android/DISTRIBUTE.md
@@ -1,3 +1,48 @@
# Distributing Mapbox GL Native for Android
-Use the `Makefile` target `make apackage` in order to build JNI libraries for all supported ABI's for eventual distribution of the whole package.
+Depending on your use case, you may want to support all or just a subset of [Android ABIs](http://developer.android.com/ndk/guides/abis.html).
+This can be achieved using the different `Makefile` targets that are available.
+
+##### Build native libraries for all supported ABIs
+
+```sh
+make apackage
+```
+
+This will build native libraries to support following ABIs:
+ - armeabi
+ - armeabi-v7a
+ - arm64-v8a
+ - x86
+ - x86_64
+ - mips
+
+##### Build native libraries for a specific ABI
+
+```sh
+make android-lib-%%
+```
+
+In the command above you'll need to replace `%%` with an ABI key listed below:
+
+| ABI Key | Android ABI |
+|---------|-------------|
+| arm-v5 | armeabi |
+| arm-v7 | armeabi-v7a |
+| arm-v8 | arm64-v8a |
+| x86 | x86 |
+| x86-64 | x86_64 |
+| mips | mips |
+
+For example, to build the arm64-v8a ABI the Makefile target would be:
+
+```sh
+make android-lib-arm-v8
+```
+
+It's also possible to build multiple ABI (without having to build them all) by running the Makefile multiple times. For example to build arm64-v8a and x86_64 in the same project the commands would be:
+
+```sh
+make android-lib-arm-v8
+make android-lib-arm-x86-64
+```
diff --git a/platform/android/INSTALL_LINUX.md b/platform/android/INSTALL_LINUX.md
deleted file mode 100644
index 353d0269d0..0000000000
--- a/platform/android/INSTALL_LINUX.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Developing for Android on Linux
-
-Install a build dependencies:
-
- apt-get install -y make git build-essential automake \
- libtool make cmake pkg-config lib32stdc++6 lib32z1
-
-Install [Oracle JDK 7 (requires license agreement)](http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html)
-
- export JAVA_HOME="/dir/to/jdk1.7.0_71"
-
-Install the Android SDK. We recommend doing this by way of [Android Studio](https://developer.android.com/sdk/installing/studio.html).
-
- export ANDROID_HOME="/dir/to/android-sdk-linux"
-
-In the Android SDK Manager also select and install "Android Support Repository" and "Android Support Library" from "Extras":
-
-![image](https://cloud.githubusercontent.com/assets/98601/9915837/289f398e-5c6e-11e5-9a84-ed4d08d52d1f.png)
-
-## Setting Mapbox Access Token
-
-_The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/)._
-
-gradle will take the value of the `MAPBOX_ACCESS_TOKEN` environ variable and save it to `"MapboxGLAndroidSDKTestApp/src/main/res/values/developer-config.xml` where the app will read it from. Otherwise, you can edit `developer-config.xml` and add the value manually as `mapbox_access_token`.
-
-## Building
-
-Run:
-
- make android
-
-You can then open `android` in Android Studio via "Import project (Eclipse ADT, Gradle, etc.)".
-
-**Next: get your app [running on a hardware Android Device](docs/ANDROID_DEVICE.md) or [simulator](docs/ANDROID_SIMULATOR.md)**
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index cc06995df6..38688a9aca 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -18,15 +18,15 @@ repositories {
}
ext {
- supportLibVersion = '23.1.1'
+ supportLibVersion = '23.4.0'
}
dependencies {
compile "com.android.support:support-annotations:${supportLibVersion}"
compile "com.android.support:support-v4:${supportLibVersion}"
compile "com.android.support:design:${supportLibVersion}"
- compile 'com.squareup.okhttp3:okhttp:3.2.0'
- compile 'com.mapzen.android:lost:1.0.1'
+ compile 'com.squareup.okhttp3:okhttp:3.3.0'
+ compile 'com.mapzen.android:lost:1.1.0'
}
android {
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index 56cb4324fb..c2df63b0bb 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -14,7 +14,7 @@ POM_DEVELOPER_NAME=Mapbox
ANDROID_MIN_SDK=15
ANDROID_BUILD_TARGET_SDK_VERSION=23
-ANDROID_BUILD_TOOLS_VERSION=23.0.2
+ANDROID_BUILD_TOOLS_VERSION=23.0.3
ANDROID_BUILD_SDK_VERSION=23
POM_NAME=Mapbox GL Android SDK
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java
new file mode 100644
index 0000000000..211590653a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/MapboxAccountManager.java
@@ -0,0 +1,74 @@
+package com.mapbox.mapboxsdk;
+
+import android.content.Context;
+import android.text.TextUtils;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
+import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
+
+public class MapboxAccountManager {
+
+ private static MapboxAccountManager mapboxAccountManager = null;
+
+ private final String accessToken;
+ private final Context applicationContext;
+
+ /**
+ * MapboxAccountManager should NOT be instantiated directly.
+ * Use @see MapboxAccountManager#getInstance() instead.
+ * @param applicationContext Context used to get ApplicationContext
+ * @param accessToken Mapbox Access Token
+ */
+ private MapboxAccountManager(Context applicationContext, String accessToken) {
+ super();
+ this.applicationContext = applicationContext.getApplicationContext();
+ this.accessToken = accessToken;
+ }
+
+ /**
+ * Primary entry point to Mapbox for implementing developers.
+ * Must be configured in either Application.onCreate() or Launch Activity.onCreate()
+ *
+ * @param context Context used to get Application Context
+ * @param accessToken Mapbox Access Token. You can get one on the Mapbox Web site.
+ * @return MapboxAccountManager instance for app
+ */
+ public static MapboxAccountManager start(Context context, String accessToken) {
+ if (mapboxAccountManager == null) {
+ mapboxAccountManager = new MapboxAccountManager(context, accessToken);
+ }
+ MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager();
+ eventManager.initialize(mapboxAccountManager.applicationContext, mapboxAccountManager.accessToken);
+ return mapboxAccountManager;
+ }
+
+ /**
+ * Internal Use Only
+ * Get an instance of MapboxAccountManager configured with the app's Access Token
+ *
+ * @return MapboxAccountManager instance for app. May be NULL if not configured yet.
+ */
+ public static MapboxAccountManager getInstance() {
+ return mapboxAccountManager;
+ }
+
+ /**
+ * Access Token for this application
+ * @return Mapbox Access Token
+ */
+ public String getAccessToken() {
+ return accessToken;
+ }
+
+ /**
+ * Runtime validation of Access Token
+ *
+ * @param accessToken Access Token to check
+ * @throws InvalidAccessTokenException
+ */
+ public static void validateAccessToken(String accessToken) throws InvalidAccessTokenException {
+ if (TextUtils.isEmpty(accessToken) || (!accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("pk.") && !accessToken.toLowerCase(MapboxConstants.MAPBOX_LOCALE).startsWith("sk."))) {
+ throw new InvalidAccessTokenException();
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
index 114e809b9e..36d56591c8 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Annotation.java
@@ -22,7 +22,7 @@ public abstract class Annotation implements Comparable<Annotation> {
* Internal C++ id is stored as unsigned int.
*/
private long id = -1; // -1 unless added to a MapView
- private MapboxMap mapboxMap;
+ protected MapboxMap mapboxMap;
protected Annotation() {
}
@@ -75,19 +75,15 @@ public abstract class Annotation implements Comparable<Annotation> {
} else if (id > annotation.getId()) {
return -1;
}
-
- // Equal
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
+ if (o == null || !(o instanceof Annotation)) return false;
Annotation that = (Annotation) o;
-
- return getId() == that.getId();
+ return id == that.getId();
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
index fe8bf67920..fc2022f9e1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerOptions.java
@@ -6,7 +6,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
/**
* Abstract builder class for composing custom Marker objects.
- * <p/>
+ *
* Extending this class requires implementing Parceable interface.
*
* @param <U> Type of the marker to be composed
@@ -43,4 +43,4 @@ public abstract class BaseMarkerOptions<U extends Marker, T extends BaseMarkerOp
public abstract U getMarker();
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
new file mode 100644
index 0000000000..0cd54fc0f0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/BaseMarkerViewOptions.java
@@ -0,0 +1,295 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import android.os.Parcelable;
+import android.support.annotation.AnimatorRes;
+import android.support.annotation.NonNull;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+/**
+ * Abstract builder class for composing custom MarkerView objects.
+ * <p>
+ * Extending this class requires implementing Parceable interface.
+ * </p>
+ *
+ * @param <U> Type of the marker view to be composed
+ * @param <T> Type of the builder to be used for composing
+ */
+public abstract class BaseMarkerViewOptions<U extends MarkerView, T extends BaseMarkerViewOptions<U, T>> implements Parcelable {
+
+ protected LatLng position;
+ protected String snippet;
+ protected String title;
+ protected Icon icon;
+ protected boolean flat;
+ protected float anchorU = 0.5f;
+ protected float anchorV = 1f;
+ protected float infoWindowAnchorU = 0.5f;
+ protected float infoWindowAnchorV = 0.0f;
+ protected int selectAnimRes;
+ protected int deselectAnimRes;
+ protected int rotation;
+ protected boolean visible = true;
+
+ /**
+ * Default constructor
+ */
+ public BaseMarkerViewOptions() {
+ }
+
+ /**
+ * Set the geographical location of the MarkerView.
+ *
+ * @param position the location to position the MarkerView
+ * @return the object for which the method was called
+ */
+ public T position(@NonNull LatLng position) {
+ this.position = position;
+ return getThis();
+ }
+
+ /**
+ * Set the snippet of the MarkerView.
+ *
+ * @param snippet the snippet of the MarkerView
+ * @return the object for which the method was called
+ */
+ public T snippet(String snippet) {
+ this.snippet = snippet;
+ return getThis();
+ }
+
+ /**
+ * Set the title of the MarkerView.
+ *
+ * @param title the title of the MarkerView
+ * @return the object for which the method was called
+ */
+ public T title(String title) {
+ this.title = title;
+ return getThis();
+ }
+
+ /**
+ * Set the icon of the MarkerView.
+ *
+ * @param icon the icon of the MarkerView
+ * @return the object for which the method was called
+ */
+ public T icon(Icon icon) {
+ this.icon = icon;
+ return getThis();
+ }
+
+ /**
+ * Set the flat state of the MarkerView.
+ *
+ * @param flat the flat state of the MarkerView
+ * @return the object for which the method was called
+ */
+ public T flat(boolean flat) {
+ this.flat = flat;
+ return getThis();
+ }
+
+ /**
+ * Set the anchor of the MarkerView.
+ *
+ * @param u the u-value
+ * @param v the v-value
+ * @return the object for which the method was called
+ */
+ public T anchor(float u, float v) {
+ this.anchorU = u;
+ this.anchorV = v;
+ return getThis();
+ }
+
+ /**
+ * Set the InfoWindow anchor of the MarkerView.
+ *
+ * @param u the u-value
+ * @param v the v-values
+ * @return the object for which the method was called
+ */
+ public T infoWindowAnchor(float u, float v) {
+ this.infoWindowAnchorU = u;
+ this.infoWindowAnchorV = v;
+ return getThis();
+ }
+
+ /**
+ * Set the animator resource to be used when an MarkerView is selected.
+ *
+ * @param selectAnimRes the used animator resource
+ * @return the object for which the method was called
+ */
+ public T selectAnimatorResource(@AnimatorRes int selectAnimRes) {
+ this.selectAnimRes = selectAnimRes;
+ return getThis();
+ }
+
+ /**
+ * Set the animator resource to be used when an MarkerView is deselected.
+ *
+ * @param deselectAnimRes the used animator resource
+ * @return the object for which the method was called
+ */
+ public T deselectAnimatorResource(@AnimatorRes int deselectAnimRes) {
+ this.deselectAnimRes = deselectAnimRes;
+ return getThis();
+ }
+
+ /**
+ * Set the rotation of the MarkerView.
+ *
+ * @param rotation the rotation value
+ * @return the object for which the method was called
+ */
+ public T rotation(int rotation) {
+ this.rotation = rotation;
+ return getThis();
+ }
+
+ /**
+ * Set the visibility state of the MarkerView.
+ *
+ * @param visible the visible state
+ * @return the object for which the method was calleds
+ */
+ public T visible(boolean visible) {
+ this.visible = visible;
+ return getThis();
+ }
+
+ /**
+ * Get the geographical location of the MarkerView.
+ *
+ * @return the geographical location
+ */
+ public LatLng getPosition() {
+ return position;
+ }
+
+ /**
+ * Get the snippet of the MarkerView.
+ *
+ * @return the snippet
+ */
+ public String getSnippet() {
+ return snippet;
+ }
+
+ /**
+ * Get the title of the MarkerView.
+ *
+ * @return the title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * Get the icon of the MarkerView.
+ *
+ * @return the icon
+ */
+ public Icon getIcon() {
+ return icon;
+ }
+
+ /**
+ * Get the flat state of the MarkerView.
+ *
+ * @return the flat state
+ */
+ public boolean isFlat() {
+ return flat;
+ }
+
+ /**
+ * Get the u-value of the MarkerView anchor.
+ *
+ * @return the u-value
+ */
+ public float getAnchorU() {
+ return anchorU;
+ }
+
+ /**
+ * Get the v-value of the MarkerView anchor.
+ *
+ * @return the v-value
+ */
+ public float getAnchorV() {
+ return anchorV;
+ }
+
+ /**
+ * Get the u-value of the MarkerView InfoWindow anchor.
+ *
+ * @return the u-value
+ */
+ public float getInfoWindowAnchorU() {
+ return infoWindowAnchorU;
+ }
+
+ /**
+ * Get the v-value of the MarkerView InfoWindow anchor.
+ *
+ * @return the v-value
+ */
+ public float getInfoWindowAnchorV() {
+ return infoWindowAnchorV;
+ }
+
+ /**
+ * Get the animator resource used for selecting the MarkerView.
+ *
+ * @return the animator resource
+ */
+ public int getSelectAnimRes() {
+ return selectAnimRes;
+ }
+
+ /**
+ * Get the animator resource used for deselecting the MarkerView.
+ *
+ * @return the animator resource
+ */
+ public int getDeselectAnimRes() {
+ return deselectAnimRes;
+ }
+
+ /**
+ * Get the rotation of the MarkerView.
+ *
+ * @return the rotation value
+ */
+ public int getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Get the visibility state of the MarkerView.
+ *
+ * @return the visibility state
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Get the instance of the object for which this method was called.
+ *
+ * @return the object for which the this method was called
+ */
+ public abstract T getThis();
+
+ /**
+ * Get the MarkerView.
+ *
+ * @return the MarkerView created from this builder
+ */
+ public abstract U getMarker();
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
index e30b81d4c9..fceeb52713 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Icon.java
@@ -6,9 +6,10 @@ import com.mapbox.mapboxsdk.maps.MapView;
/**
* Icon is the visual representation of a {@link Marker} on a {@link MapView}.
+ *
* @see Marker
*/
-public final class Icon {
+public class Icon {
private Bitmap mBitmap;
private String mId;
@@ -39,8 +40,13 @@ public final class Icon {
@Override
public int hashCode() {
- int result = mBitmap.hashCode();
- result = 31 * result + mId.hashCode();
+ int result = 0;
+ if (mBitmap != null) {
+ result = mBitmap.hashCode();
+ }
+ if (mId != null) {
+ result = 31 * result + mId.hashCode();
+ }
return result;
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
index c1fc9bb0ab..7452ab8fac 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/InfoWindow.java
@@ -30,6 +30,7 @@ public class InfoWindow {
protected WeakReference<View> mView;
private float mMarkerHeightOffset;
+ private float mMarkerWidthOffset;
private float mViewWidthOffset;
private PointF mCoordinates;
private boolean mIsVisible;
@@ -108,9 +109,9 @@ public class InfoWindow {
// Calculate y-offset for update method
mMarkerHeightOffset = -view.getMeasuredHeight() + offsetY;
+ mMarkerWidthOffset = -offsetX;
// Calculate default Android x,y coordinate
-
mCoordinates = mapboxMap.getProjection().toScreenLocation(position);
float x = mCoordinates.x - (view.getMeasuredWidth() / 2) + offsetX;
float y = mCoordinates.y - view.getMeasuredHeight() + offsetY;
@@ -244,7 +245,7 @@ public class InfoWindow {
View view = mView.get();
if (mapboxMap != null && marker != null && view != null) {
mCoordinates = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
- view.setX(mCoordinates.x + mViewWidthOffset);
+ view.setX(mCoordinates.x + mViewWidthOffset - mMarkerWidthOffset);
view.setY(mCoordinates.y + mMarkerHeightOffset);
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
index c2683cbb56..16b219684f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/Marker.java
@@ -4,16 +4,16 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
/**
* Marker is an annotation that shows an icon image at a geographical location.
- * </p>
+ * <p>
* An {@link InfoWindow} can be shown when a Marker is pressed
- * <p/>
+ * </p>
*/
public class Marker extends Annotation {
@@ -21,9 +21,12 @@ public class Marker extends Annotation {
private String snippet;
private Icon icon;
private String title;
- private InfoWindow infoWindow = null;
- private boolean infoWindowShown = false;
+
+ private InfoWindow infoWindow;
+ private boolean infoWindowShown;
+
private int topOffsetPixels;
+ private int rightOffsetPixels;
/**
* Constructor
@@ -39,6 +42,13 @@ public class Marker extends Annotation {
title = baseMarkerOptions.title;
}
+ Marker(BaseMarkerViewOptions baseMarkerViewOptions){
+ position = baseMarkerViewOptions.position;
+ snippet = baseMarkerViewOptions.snippet;
+ icon = baseMarkerViewOptions.icon;
+ title = baseMarkerViewOptions.title;
+ }
+
public LatLng getPosition() {
return position;
}
@@ -130,7 +140,7 @@ public class Marker extends Annotation {
}
private InfoWindow showInfoWindow(InfoWindow iw, MapView mapView) {
- iw.open(mapView, this, getPosition(), 0, topOffsetPixels);
+ iw.open(mapView, this, getPosition(), rightOffsetPixels, topOffsetPixels);
infoWindowShown = true;
return iw;
}
@@ -149,21 +159,11 @@ public class Marker extends Annotation {
this.topOffsetPixels = topOffsetPixels;
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
-
- Marker marker = (Marker) o;
- return !(getPosition() != null ? !getPosition().equals(marker.getPosition()) : marker.getPosition() != null);
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- result = 31 * result + (getPosition() != null ? getPosition().hashCode() : 0);
- return result;
+ /**
+ * Do not use this method. Used internally by the SDK.
+ */
+ public void setRightOffsetPixels(int rightOffsetPixels) {
+ this.rightOffsetPixels = rightOffsetPixels;
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
index a3df23d96f..7ca3687b0d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerOptions.java
@@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.Parcelable;
-import android.support.annotation.Nullable;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -12,9 +11,7 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
* <p>
* Builder for composing {@link com.mapbox.mapboxsdk.annotations.Marker} objects.
* </p>
- * <p/>
* <h3>Example</h3>
- * <p/>
* <pre>
* mMapView.addMarker(new MarkerOptions()
* .title("Intersection")
@@ -24,30 +21,24 @@ import com.mapbox.mapboxsdk.geometry.LatLng;
*/
public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions> implements Parcelable {
- public static final Parcelable.Creator<MarkerOptions> CREATOR
- = new Parcelable.Creator<MarkerOptions>() {
- public MarkerOptions createFromParcel(Parcel in) {
- return new MarkerOptions(in);
- }
+ private Marker marker;
- public MarkerOptions[] newArray(int size) {
- return new MarkerOptions[size];
- }
- };
+ public MarkerOptions() {
+ marker = new Marker();
+ }
- private MarkerOptions(Parcel in) {
+ protected MarkerOptions(Parcel in) {
marker = new Marker();
position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
snippet(in.readString());
-
- if(in.readByte()!=0){
+ title(in.readString());
+ if (in.readByte() != 0) {
// this means we have an icon
String iconId = in.readString();
Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
Icon icon = new Icon(iconId, iconBitmap);
icon(icon);
}
- title(in.readString());
}
@Override
@@ -57,26 +48,20 @@ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions
@Override
public int describeContents() {
- return hashCode();
+ return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(getPosition(), flags);
out.writeString(getSnippet());
+ out.writeString(getTitle());
Icon icon = getIcon();
out.writeByte((byte) (icon != null ? 1 : 0));
if (icon != null) {
out.writeString(getIcon().getId());
out.writeParcelable(getIcon().getBitmap(), flags);
}
- out.writeString(getTitle());
- }
-
- private Marker marker;
-
- public MarkerOptions() {
- marker = new Marker();
}
/**
@@ -108,6 +93,17 @@ public final class MarkerOptions extends BaseMarkerOptions<Marker, MarkerOptions
return icon;
}
+ public static final Parcelable.Creator<MarkerOptions> CREATOR
+ = new Parcelable.Creator<MarkerOptions>() {
+ public MarkerOptions createFromParcel(Parcel in) {
+ return new MarkerOptions(in);
+ }
+
+ public MarkerOptions[] newArray(int size) {
+ return new MarkerOptions[size];
+ }
+ };
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
new file mode 100644
index 0000000000..3e51044643
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerView.java
@@ -0,0 +1,341 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+
+/**
+ * MarkerView is an annotation that shows an View at a geographical location.
+ * <p>
+ * This class uses {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter} to adapt a
+ * MarkerView model to an Android SDK {@link android.view.View} object.
+ * </p>
+ * <p>
+ * An {@link InfoWindow} can be shown when a MarkerView is pressed
+ * </p>
+ */
+public class MarkerView extends Marker {
+
+ private MarkerViewManager markerViewManager;
+
+ private float anchorU;
+ private float anchorV;
+
+ private float offsetX;
+ private float offsetY;
+
+ private float infoWindowAnchorU;
+ private float infoWindowAnchorV;
+
+ private boolean flat;
+ private boolean visible = true;
+
+ private int selectAnimRes;
+ private int deselectAnimRes;
+
+ private float tiltValue;
+ private float rotation;
+ private float alpha = 1;
+
+ /**
+ * Publicly hidden default constructor
+ */
+ MarkerView() {
+ }
+
+ /**
+ * Creates a instance of MarkerView using the builder of MarkerView
+ *
+ * @param baseMarkerViewOptions the builder used to construct the MarkerView
+ */
+ public MarkerView(BaseMarkerViewOptions baseMarkerViewOptions) {
+ super(baseMarkerViewOptions);
+ this.anchorU = baseMarkerViewOptions.getAnchorU();
+ this.anchorV = baseMarkerViewOptions.getAnchorV();
+ this.infoWindowAnchorU = baseMarkerViewOptions.getInfoWindowAnchorU();
+ this.infoWindowAnchorV = baseMarkerViewOptions.getInfoWindowAnchorV();
+ this.flat = baseMarkerViewOptions.isFlat();
+ this.selectAnimRes = baseMarkerViewOptions.getSelectAnimRes();
+ this.deselectAnimRes = baseMarkerViewOptions.getDeselectAnimRes();
+ this.infoWindowAnchorU = baseMarkerViewOptions.infoWindowAnchorU;
+ this.infoWindowAnchorV = baseMarkerViewOptions.infoWindowAnchorV;
+ this.anchorU = baseMarkerViewOptions.anchorU;
+ this.anchorV = baseMarkerViewOptions.anchorV;
+ }
+
+ /**
+ * Specifies the anchor being set on a particular point point of the MarkerView.
+ * <p>
+ * The anchor point is specified in the continuous space [0.0, 1.0] x [0.0, 1.0], where (0, 0)
+ * is the top-left corner of the image, and (1, 1) is the bottom-right corner.
+ * </p>
+ *
+ * @param u u-coordinate of the anchor, as a ratio of the image width (in the range [0, 1])
+ * @param v v-coordinate of the anchor, as a ratio of the image height (in the range [0, 1])
+ */
+ public void setAnchor(float u, float v) {
+ this.anchorU = u;
+ this.anchorV = v;
+ }
+
+ /**
+ * Get the horizontal distance, normalized to [0, 1], of the anchor from the left edge.
+ *
+ * @return the u-value of the anchor
+ */
+ public float getAnchorU() {
+ return anchorU;
+ }
+
+ /**
+ * Get the vertical distance, normalized to [0, 1], of the anchor from the top edge.
+ *
+ * @return the v-value of the anchor
+ */
+ public float getAnchorV() {
+ return anchorV;
+ }
+
+ /**
+ * Internal method to set the horizontal calculated offset.
+ * <p>
+ * These are calculated based on the View bounds and the provided anchor.
+ * </p>
+ *
+ * @param x the x-value of the offset
+ */
+ void setOffsetX(float x) {
+ offsetX = x;
+ }
+
+ /**
+ * Internal method to set the vertical calculated offset.
+ * <p>
+ * These are calculated based on the View bounds and the provided anchor.
+ * </p>
+ *
+ * @param y the y-value of the offset
+ */
+ void setOffsetY(float y) {
+ offsetY = y;
+ }
+
+ /**
+ * Internal method to get the horizontal calculated offset
+ *
+ * @return the calculated horizontal offset
+ */
+ float getOffsetX() {
+ return offsetX;
+ }
+
+ /**
+ * Internal method to get the vertical calculated offset
+ *
+ * @return the calculated vertical offset
+ */
+ float getOffsetY() {
+ return offsetY;
+ }
+
+ /**
+ * Specifies the anchor point of the info window on the View of the MarkerView.
+ * <p>
+ * This is specified in the same coordinate system as the anchor.
+ * </p>
+ * <p>
+ * The default is the top middle of the View.
+ * </p>
+ *
+ * @param u u-coordinate of the info window anchor, as a ratio of the image width (in the range [0, 1])
+ * @param v v-coordinate of the info window anchor, as a ratio of the image height (in the range [0, 1])
+ * @see #setAnchor(float, float) for more details.
+ */
+ public void setInfoWindowAnchor(float u, float v) {
+ this.infoWindowAnchorU = u;
+ this.infoWindowAnchorV = v;
+ }
+
+ /**
+ * Get the horizontal distance, normalized to [0, 1], of the info window anchor from the left edge.
+ *
+ * @return the u value of the InfoWindow anchor.
+ */
+ public float getInfoWindowAnchorU() {
+ return infoWindowAnchorU;
+ }
+
+ /**
+ * Get the vertical distance, normalized to [0, 1], of the info window anchor from the top edge.
+ *
+ * @return the v value of the InfoWindow anchor.
+ */
+ public float getInfoWindowAnchorV() {
+ return infoWindowAnchorV;
+ }
+
+ /**
+ * Get the flat state of a MarkerView.
+ *
+ * @return true is the MarkerView is flat; false is the MarkerView is billboard
+ */
+ public boolean isFlat() {
+ return flat;
+ }
+
+ /**
+ * Sets whether this marker should be flat against the map true or a billboard facing the camera false.
+ *
+ * @param flat the flat state of the MarkerView
+ */
+ public void setFlat(boolean flat) {
+ this.flat = flat;
+ }
+
+ /**
+ * Get the animator resource used to animate to the selected state of a MarkerView.
+ *
+ * @return the animator resource used
+ */
+ public int getSelectAnimRes() {
+ return selectAnimRes;
+ }
+
+ /**
+ * Set the animator resource used to animate to the deselected state of a MarkerView.
+ *
+ * @param selectAnimRes the animator resource used
+ */
+ public void setSelectAnimRes(int selectAnimRes) {
+ this.selectAnimRes = selectAnimRes;
+ }
+
+ /**
+ * Get the animator resource used to animate to the deslected state of a MarkerView.
+ *
+ * @return the animator resource used
+ */
+ public int getDeselectAnimRes() {
+ return deselectAnimRes;
+ }
+
+ /**
+ * Set the animator resource used to animate to the selected state of a MarkerView.
+ *
+ * @param deselectAnimRes the animator resource used
+ */
+ public void setDeselectAnimRes(int deselectAnimRes) {
+ this.deselectAnimRes = deselectAnimRes;
+ }
+
+ /**
+ * Internal method to get the current tilted value of a MarkerView.
+ *
+ * @return the tilted value
+ */
+ float getTilt() {
+ return tiltValue;
+ }
+
+ /**
+ * Internal method to set the current titled value of a MarkerView.
+ *
+ * @param tiltValue the tilted value to set
+ */
+ void setTilt(float tiltValue) {
+ this.tiltValue = tiltValue;
+ }
+
+ /**
+ * Set the visible state of a MarkerView.
+ *
+ * @param visible true will make the MarkerView visible, false will hide the MarkerViews
+ */
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ if (markerViewManager != null) {
+ markerViewManager.animateVisible(this, visible);
+ }
+ }
+
+ /**
+ * Returns the visible state of the MarkerView.
+ *
+ * @return the visible state
+ */
+ public boolean isVisible() {
+ return visible;
+ }
+
+ /**
+ * Set the rotation value of the MarkerView.
+ * <p>
+ * This will result in animating the rotation of the MarkerView using an rotation animator
+ * from current value to the provided parameter value.
+ * </p>
+ *
+ * @param rotation the rotation value to animate to
+ */
+ public void setRotation(float rotation) {
+ this.rotation = rotation;
+ if (markerViewManager != null) {
+ markerViewManager.animateRotation(this, rotation);
+ }
+ }
+
+ /**
+ * Get the rotation value of the MarkerView.
+ *
+ * @return the rotation value
+ */
+ public float getRotation() {
+ return rotation;
+ }
+
+ /**
+ * Get the alpha value of the MarkerView.
+ *
+ * @return the alpha value
+ */
+ public float getAlpha() {
+ return alpha;
+ }
+
+ /**
+ * Set the alpha value of the MarkerView.
+ * <p>
+ * This will result in animating the alpha of the MarkerView using an alpha animator
+ * from current value to the provided parameter value.
+ * </p>
+ *
+ * @param alpha the alpha value to animate to
+ */
+ public void setAlpha(float alpha) {
+ this.alpha = alpha;
+ if (markerViewManager != null) {
+ markerViewManager.animateAlpha(this, alpha);
+ }
+ }
+
+ /**
+ * Set the MapboxMap associated tot the MapView containing the MarkerView.
+ * <p>
+ * This method is used to instantiate the MarkerView and provide an instance of {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}
+ * </p>
+ *
+ * @param mapboxMap the MapboxMap instances
+ */
+ @Override
+ public void setMapboxMap(MapboxMap mapboxMap) {
+ super.setMapboxMap(mapboxMap);
+ markerViewManager = mapboxMap.getMarkerViewManager();
+ }
+
+ /**
+ * Get the String representation of a MarkerView.
+ *
+ * @return the String representation
+ */
+ @Override
+ public String toString() {
+ return "MarkerView [position[" + getPosition() + "]]";
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
new file mode 100644
index 0000000000..d9fc9e62ae
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewManager.java
@@ -0,0 +1,352 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import android.graphics.PointF;
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.util.Pools;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Projection;
+import com.mapbox.mapboxsdk.utils.AnimatorUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interface for interacting with ViewMarkers objects inside of a MapView.
+ * <p>
+ * This class is responsible for managing a {@link MarkerView} item.
+ * </p>
+ */
+public class MarkerViewManager {
+
+ private Map<MarkerView, View> mMarkerViewMap;
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private List<MapboxMap.MarkerViewAdapter> markerViewAdapters;
+ private long mViewMarkerBoundsUpdateTime;
+ private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
+
+ /**
+ * Creates an instance of MarkerViewManager.
+ *
+ * @param mapboxMap the MapboxMap associated with the MarkerViewManager
+ * @param mapView the MapView associated with the MarkerViewManager
+ */
+ public MarkerViewManager(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
+ this.mapboxMap = mapboxMap;
+ this.markerViewAdapters = new ArrayList<>();
+ this.mapView = mapView;
+ mMarkerViewMap = new HashMap<>();
+ }
+
+ /**
+ * Animate a MarkerView to a given rotation.
+ * <p>
+ * The {@link MarkerView} will be rotated from its current rotation to the given rotation.
+ * </p>
+ *
+ * @param marker the MarkerView to rotate
+ * @param rotation the rotation value
+ */
+ public void animateRotation(@NonNull MarkerView marker, float rotation) {
+ View convertView = mMarkerViewMap.get(marker);
+ if (convertView != null) {
+ AnimatorUtils.rotate(convertView, rotation);
+ }
+ }
+
+ /**
+ * Animate a MarkerView to a given alpha value.
+ * <p>
+ * The {@link MarkerView} will be transformed from its current alpha value to the given value.
+ * </p>
+ *
+ * @param marker the MarkerView to change its alpha value
+ * @param alpha the alpha value
+ */
+ public void animateAlpha(@NonNull MarkerView marker, float alpha) {
+ View convertView = mMarkerViewMap.get(marker);
+ if (convertView != null) {
+ AnimatorUtils.alpha(convertView, alpha);
+ }
+ }
+
+ /**
+ * Animate a MarkerVIew to be visible or invisible
+ * <p>
+ * The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}.
+ * </p>
+ *
+ * @param marker the MarkerView to change its visibility
+ * @param visible the flag indicating if MarkerView is visible
+ */
+ public void animateVisible(@NonNull MarkerView marker, boolean visible) {
+ View convertView = mMarkerViewMap.get(marker);
+ if (convertView != null) {
+ convertView.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ /**
+ * Updates the position of MarkerViews currently found in the viewport.
+ * <p>
+ * The collection of {@link MarkerView} will be iterated and each item position will be updated.
+ * If an item is View state is not visible and its related flag is set to visible,
+ * The {@link MarkerView} will be animated to visible using alpha animation.
+ * </p>
+ */
+ public void update() {
+ View convertView;
+ for (MarkerView marker : mMarkerViewMap.keySet()) {
+ convertView = mMarkerViewMap.get(marker);
+ if (convertView != null) {
+ PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
+ int x = (int) (marker.getAnchorU() * convertView.getMeasuredWidth());
+ int y = (int) (marker.getAnchorV() * convertView.getMeasuredHeight());
+
+ marker.setOffsetX(x);
+ marker.setOffsetY(y);
+
+ convertView.setX(point.x - x);
+ convertView.setY(point.y - y);
+
+ if (marker.isVisible() && convertView.getVisibility() == View.GONE) {
+ convertView.animate().cancel();
+ convertView.setAlpha(0);
+ AnimatorUtils.alpha(convertView, 1);
+ }
+ }
+ }
+ }
+
+ /**
+ * Set tilt on every non flat MarkerView currently shown in the Viewport.
+ *
+ * @param tilt the tilt value
+ */
+ public void setTilt(float tilt) {
+ View convertView;
+ for (MarkerView markerView : mMarkerViewMap.keySet()) {
+ if (markerView.isFlat()) {
+ convertView = mMarkerViewMap.get(markerView);
+ if (convertView != null) {
+ markerView.setTilt(tilt);
+ convertView.setRotationX(tilt);
+ }
+ }
+ }
+ }
+
+ /**
+ * Animate a MarkerView to a deselected state.
+ * <p>
+ * The {@link MarkerView#getDeselectAnimRes()} will be called to get the related animation.
+ * If non are provided, no animation will be started.
+ * </p>
+ *
+ * @param marker the MarkerView to deselect
+ */
+ public void deselect(@NonNull MarkerView marker) {
+ final View convertView = mMarkerViewMap.get(marker);
+ if (convertView != null) {
+ int deselectAnimatorRes = marker.getDeselectAnimRes();
+ if (deselectAnimatorRes != 0) {
+ AnimatorUtils.animate(convertView, deselectAnimatorRes);
+ }
+ }
+ }
+
+ /**
+ * Remove a MarkerView from a map.
+ * <p>
+ * The {@link MarkerView} will be removed using an alpha animation and related {@link View}
+ * will be released to the {@link android.support.v4.util.Pools.SimplePool} from the related
+ * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove
+ * the {@link MarkerView} from the underlying collection if needed.
+ * </p>
+ *
+ * @param marker the MarkerView to remove
+ * @param removeFromMap flag indicating if a MarkerView will be removed from the collection.
+ */
+ public void removeMarkerView(MarkerView marker, boolean removeFromMap) {
+ final View viewHolder = mMarkerViewMap.get(marker);
+ if (viewHolder != null && marker != null) {
+ for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass() == marker.getClass()) {
+
+ // get pool of Views associated to an adapter
+ final Pools.SimplePool<View> viewPool = adapter.getViewReusePool();
+
+ // cancel ongoing animations
+ viewHolder.animate().cancel();
+ viewHolder.setAlpha(1);
+ AnimatorUtils.alpha(viewHolder, 0, new AnimatorUtils.OnAnimationEndListener() {
+ @Override
+ public void onAnimationEnd() {
+ viewHolder.setVisibility(View.GONE);
+ viewPool.release(viewHolder);
+ }
+ });
+ }
+ }
+ }
+ if (removeFromMap) {
+ mMarkerViewMap.remove(marker);
+ }
+ }
+
+ /**
+ * Add a MarkerViewAdapter.
+ *
+ * @param markerViewAdapter the MarkerViewAdapter to add
+ */
+ public void addMarkerViewAdapter(@Nullable MapboxMap.MarkerViewAdapter markerViewAdapter) {
+ if (!markerViewAdapters.contains(markerViewAdapter)) {
+ markerViewAdapters.add(markerViewAdapter);
+ invalidateViewMarkersInBounds();
+ }
+ }
+
+ /**
+ * Get all MarkerViewAdapters associated with this MarkerViewManager.
+ *
+ * @return a List of MarkerViewAdapters
+ */
+ public List<MapboxMap.MarkerViewAdapter> getMarkerViewAdapters() {
+ return markerViewAdapters;
+ }
+
+
+ /**
+ * Register a callback to be invoked when this view is clicked.
+ *
+ * @param listener the callback to be invoked
+ */
+ public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) {
+ onMarkerViewClickListener = listener;
+ }
+
+ /**
+ * Schedule that ViewMarkers found in the viewport are invalidated.
+ * <p>
+ * This method is rate limited, and {@link #invalidateViewMarkersInBounds} will only be called
+ * once each 250 ms.
+ * </p>
+ */
+ public void scheduleViewMarkerInvalidation() {
+ if (!markerViewAdapters.isEmpty()) {
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime < mViewMarkerBoundsUpdateTime) {
+ return;
+ }
+ invalidateViewMarkersInBounds();
+ mViewMarkerBoundsUpdateTime = currentTime + 250;
+ }
+ }
+
+ /**
+ * Invalidate the ViewMarkers found in the viewport.
+ * <p>
+ * This method will remove any markers that aren't in the viewport any more and will add new
+ * ones for each found Marker in the changed viewport.
+ * </p>
+ */
+ public void invalidateViewMarkersInBounds() {
+ Projection projection = mapboxMap.getProjection();
+ List<MarkerView> markers = mapView.getMarkerViewsInBounds(projection.getVisibleRegion().latLngBounds);
+ View convertView;
+
+ // remove old markers
+ Iterator<MarkerView> iterator = mMarkerViewMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ MarkerView m = iterator.next();
+ if (!markers.contains(m)) {
+ // remove marker
+ convertView = mMarkerViewMap.get(m);
+ int deselectAnimRes = m.getDeselectAnimRes();
+ if (deselectAnimRes != 0) {
+ AnimatorUtils.animate(convertView, deselectAnimRes, 0);
+ }
+ removeMarkerView(m, false);
+ iterator.remove();
+ }
+ }
+
+ // introduce new markers
+ for (final MarkerView marker : markers) {
+ if (!mMarkerViewMap.containsKey(marker)) {
+ for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
+ if (adapter.getMarkerClass() == marker.getClass()) {
+ convertView = (View) adapter.getViewReusePool().acquire();
+ final View adaptedView = adapter.getView(marker, convertView, mapView);
+ if (adaptedView != null) {
+
+ // tilt
+ adaptedView.setRotationX(marker.getTilt());
+
+ // rotation
+ adaptedView.setRotation(marker.getRotation());
+
+ // alpha
+ adaptedView.setAlpha(marker.getAlpha());
+
+ // visible
+ adaptedView.setVisibility(marker.isVisible() ? View.VISIBLE : View.GONE);
+
+ if (mapboxMap.getSelectedMarkers().contains(marker)) {
+ // if a marker to be shown was selected
+ // replay that animation with duration 0
+ int selectAnimRes = marker.getSelectAnimRes();
+ if (selectAnimRes != 0) {
+ AnimatorUtils.animate(convertView, selectAnimRes, 0);
+ }
+ }
+
+ final int animSelectRes = marker.getSelectAnimRes();
+ adaptedView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(final View v) {
+ boolean clickHandled = false;
+ if (onMarkerViewClickListener != null) {
+ clickHandled = onMarkerViewClickListener.onMarkerClick(marker, v, adapter);
+ }
+
+ if (!clickHandled) {
+ // InfoWindow offset
+ int infoWindowOffsetX = (int) ((adaptedView.getWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX());
+ int infoWindowOffsetY = (int) ((adaptedView.getHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY());
+ marker.setTopOffsetPixels(infoWindowOffsetY);
+ marker.setRightOffsetPixels(infoWindowOffsetX);
+
+ if (animSelectRes != 0) {
+ AnimatorUtils.animate(v, animSelectRes, new AnimatorUtils.OnAnimationEndListener() {
+ @Override
+ public void onAnimationEnd() {
+ mapboxMap.selectMarker(marker);
+ }
+ });
+ } else {
+ mapboxMap.selectMarker(marker);
+ }
+ }
+ }
+ });
+
+ mMarkerViewMap.put(marker, adaptedView);
+ if (convertView == null) {
+ mapView.addView(adaptedView);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
new file mode 100644
index 0000000000..0c9faed355
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/annotations/MarkerViewOptions.java
@@ -0,0 +1,115 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+/**
+ * builder class for composing MarkerView objects.
+ * <p>
+ * Do not extend this class directly but extend BaseMarkerViewOptions instead.
+ * </p>
+ */
+public class MarkerViewOptions extends BaseMarkerViewOptions<MarkerView, MarkerViewOptions> {
+
+ private MarkerView marker;
+
+ public MarkerViewOptions() {
+ marker = new MarkerView();
+ }
+
+ protected MarkerViewOptions(Parcel in) {
+ marker = new MarkerView();
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ selectAnimatorResource(in.readInt());
+ deselectAnimatorResource(in.readInt());
+ rotation(in.readInt());
+ visible(in.readByte() != 0);
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = new Icon(iconId, iconBitmap);
+ icon(icon);
+ }
+ }
+
+ @Override
+ public MarkerViewOptions getThis() {
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeInt(getSelectAnimRes());
+ out.writeInt(getDeselectAnimRes());
+ out.writeInt(getRotation());
+ out.writeByte((byte) (isVisible() ? 1 : 0));
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
+ }
+ }
+
+ @Override
+ public MarkerView getMarker() {
+ marker.setPosition(position);
+ marker.setSnippet(snippet);
+ marker.setTitle(title);
+ marker.setIcon(icon);
+ marker.setFlat(flat);
+ marker.setAnchor(anchorU, anchorV);
+ marker.setInfoWindowAnchor(infoWindowAnchorU, infoWindowAnchorV);
+ marker.setSelectAnimRes(selectAnimRes);
+ marker.setDeselectAnimRes(deselectAnimRes);
+ marker.setRotation(rotation);
+ marker.setVisible(visible);
+ return marker;
+ }
+
+ public static final Parcelable.Creator<MarkerViewOptions> CREATOR
+ = new Parcelable.Creator<MarkerViewOptions>() {
+ public MarkerViewOptions createFromParcel(Parcel in) {
+ return new MarkerViewOptions(in);
+ }
+
+ public MarkerViewOptions[] newArray(int size) {
+ return new MarkerViewOptions[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MarkerViewOptions that = (MarkerViewOptions) o;
+ return marker != null ? marker.equals(that.marker) : that.marker == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return marker != null ? marker.hashCode() : 0;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
index 679a474ae7..f9346e21d6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraPosition.java
@@ -70,7 +70,7 @@ public final class CameraPosition implements Parcelable {
@Override
public int describeContents() {
- return hashCode();
+ return 0;
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
index 763ab8d664..028d077a09 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java
@@ -56,7 +56,6 @@ public final class CameraUpdateFactory {
return newLatLngBounds(bounds, padding, padding, padding, padding);
}
-
/**
* Returns a CameraUpdate that transforms the camera such that the specified latitude/longitude
* bounds are centered on screen at the greatest possible zoom level.
@@ -227,11 +226,18 @@ public final class CameraUpdateFactory {
// Get required objects
Projection projection = mapboxMap.getProjection();
UiSettings uiSettings = mapboxMap.getUiSettings();
- RectF padding = getPadding();
+
+ // calculate correct padding
+ int[] mapPadding = mapboxMap.getPadding();
+ RectF latLngPadding = getPadding();
+ RectF padding = new RectF(latLngPadding.left + mapPadding[0],
+ latLngPadding.top + mapPadding[1],
+ latLngPadding.right + mapPadding[2],
+ latLngPadding.bottom + mapPadding[3]);
// Calculate the bounds of the possibly rotated shape with respect to the viewport
- PointF nePixel = new PointF(-10000, -10000);
- PointF swPixel = new PointF(10000, 10000);
+ PointF nePixel = new PointF(-Float.MAX_VALUE, -Float.MAX_VALUE);
+ PointF swPixel = new PointF(Float.MAX_VALUE, Float.MAX_VALUE);
float viewportHeight = uiSettings.getHeight();
for (LatLng latLng : getBounds().toLatLngs()) {
PointF pixel = projection.toScreenLocation(latLng);
@@ -241,16 +247,20 @@ public final class CameraUpdateFactory {
nePixel.y = Math.max(nePixel.y, viewportHeight - pixel.y);
}
- // Calculate wid=th/height
+ // Calculate width/height
float width = nePixel.x - swPixel.x;
float height = nePixel.y - swPixel.y;
+ double zoom = 0;
+ float minScale = 1;
// Calculate the zoom level
- float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
- float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
- float minScale = scaleX < scaleY ? scaleX : scaleY;
- double zoom = projection.calculateZoom(minScale);
- zoom = MathUtils.clamp(zoom, (float) mapboxMap.getMinZoom(), (float) mapboxMap.getMaxZoom());
+ if (padding != null) {
+ float scaleX = (uiSettings.getWidth() - padding.left - padding.right) / width;
+ float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height;
+ minScale = scaleX < scaleY ? scaleX : scaleY;
+ zoom = projection.calculateZoom(minScale);
+ zoom = MathUtils.clamp(zoom, (float) mapboxMap.getMinZoom(), (float) mapboxMap.getMaxZoom());
+ }
// Calculate the center point
PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale);
@@ -291,13 +301,22 @@ public final class CameraUpdateFactory {
// Convert point to LatLng
LatLng latLng = projection.fromScreenLocation(targetPoint);
- CameraPosition cameraPosition = mapboxMap.getCameraPosition();
- return new CameraPosition.Builder()
- .target(latLng)
- .zoom(cameraPosition.zoom)
- .tilt(cameraPosition.tilt)
- .bearing(cameraPosition.bearing)
- .build();
+ CameraPosition previousPosition = mapboxMap.getCameraPosition();
+ if (latLng != null) {
+ return new CameraPosition.Builder()
+ .target(latLng)
+ .zoom(previousPosition.zoom)
+ .tilt(previousPosition.tilt)
+ .bearing(previousPosition.bearing)
+ .build();
+ } else {
+ return new CameraPosition.Builder(true)
+ .tilt(previousPosition.tilt)
+ .zoom(previousPosition.zoom)
+ .bearing(previousPosition.bearing)
+ .target(previousPosition.target)
+ .build();
+ }
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
index 475489f621..ece992ad54 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk.constants;
+import android.content.Context;
import java.util.Locale;
/**
@@ -14,7 +15,9 @@ public class MapboxConstants {
/**
* Key used to store access token in AndroidManifest.xml
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
*/
+ @Deprecated
public static final String KEY_META_DATA_MANIFEST = "com.mapbox.AccessToken";
/**
@@ -33,6 +36,11 @@ public class MapboxConstants {
public static final int ANIMATION_DURATION = 300;
/**
+ * Default short animation time
+ */
+ public static final int ANIMATION_DURATION_SHORT = 150;
+
+ /**
* The currently supported minimum zoom level.
*/
public static final float MINIMUM_ZOOM = 0.0f;
@@ -71,14 +79,16 @@ public class MapboxConstants {
public static final String STATE_HAS_SAVED_STATE = "savedState";
public static final String STATE_CAMERA_POSITION = "cameraPosition";
public static final String STATE_ZOOM_ENABLED = "zoomEnabled";
+ public static final String STATE_ZOOM_ENABLED_CHANGE = "zoomEnabledChange";
public static final String STATE_SCROLL_ENABLED = "scrollEnabled";
+ public static final String STATE_SCROLL_ENABLED_CHANGE = "scrollEnabledChange";
public static final String STATE_ROTATE_ENABLED = "rotateEnabled";
+ public static final String STATE_ROTATE_ENABLED_CHANGE = "rotateEnabledChange";
public static final String STATE_TILT_ENABLED = "tiltEnabled";
+ public static final String STATE_TILT_ENABLED_CHANGE = "tiltEnabledChange";
public static final String STATE_ZOOM_CONTROLS_ENABLED = "zoomControlsEnabled";
public static final String STATE_DEBUG_ACTIVE = "debugActive";
public static final String STATE_STYLE_URL = "styleUrl";
- public static final String STATE_ACCESS_TOKEN = "accessToken";
- public static final String STATE_DEFAULT_TRANSITION_DURATION = "defaultTransitionDuration";
public static final String STATE_MY_LOCATION_ENABLED = "myLocationEnabled";
public static final String STATE_MY_LOCATION_TRACKING_MODE = "myLocationTracking";
public static final String STATE_MY_BEARING_TRACKING_MODE = "myBearingTracking";
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
index 383a85417c..929df2da77 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
@@ -3,7 +3,7 @@ package com.mapbox.mapboxsdk.constants;
import android.support.annotation.IntDef;
import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.widgets.UserLocationView;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy;
* MyBearingTracking exposes different types bearing tracking modes.
*
* @see MapView#setMyBearingTrackingMode(int)
- * @see UserLocationView#setMyBearingTrackingMode(int)
+ * @see MyLocationView#setMyBearingTrackingMode(int)
*/
public class MyBearingTracking {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
index 9b0ae7285e..b2a49c6454 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
@@ -3,7 +3,7 @@ package com.mapbox.mapboxsdk.constants;
import android.support.annotation.IntDef;
import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.widgets.UserLocationView;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy;
* MyLocationTracking exposes different types of locational tracking modes.
*
* @see MapView#setMyLocationTrackingMode(int)
- * @see UserLocationView#setMyLocationTrackingMode(int)
+ * @see MyLocationView#setMyLocationTrackingMode(int)
*/
public class MyLocationTracking {
@@ -30,7 +30,7 @@ public class MyLocationTracking {
public static final int TRACKING_NONE = 0x00000000;
/**
- * Tracking the location of the user, {@link MapView} will reposition to center of {@link UserLocationView}
+ * Tracking the location of the user, {@link MapView} will reposition to center of {@link MyLocationView}
*/
public static final int TRACKING_FOLLOW = 0x00000004;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
index 31c146b43e..aa24d58656 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/Style.java
@@ -1,11 +1,10 @@
package com.mapbox.mapboxsdk.constants;
import android.support.annotation.StringDef;
-
import com.mapbox.mapboxsdk.maps.MapView;
-
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+
/**
* <p>
* Style provides URLs to several professional styles designed by Mapbox.
@@ -17,10 +16,154 @@ import java.lang.annotation.RetentionPolicy;
public class Style {
/**
+ * Mapbox Streets: A complete basemap, perfect for incorporating your own data.
+ */
+ private static final String MAPBOX_STREETS_BASE = "mapbox://styles/mapbox/streets-v%d";
+ /**
+ * Outdoors: A general-purpose style tailored to outdoor activities.
+ */
+ private static final String OUTDOORS_BASE = "mapbox://styles/mapbox/outdoors-v%d";
+ /**
+ * Light: Subtle light backdrop for data visualizations.
+ */
+ private static final String LIGHT_BASE = "mapbox://styles/mapbox/light-v%d";
+ /**
+ * Dark: Subtle dark backdrop for data visualizations.
+ */
+ private static final String DARK_BASE = "mapbox://styles/mapbox/dark-v%d";
+ /**
+ * Satellite: A beautiful global satellite and aerial imagery layer.
+ */
+ private static final String SATELLITE_BASE = "mapbox://styles/mapbox/satellite-v%d";
+ /**
+ * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels.
+ */
+ private static final String SATELLITE_STREETS_BASE = "mapbox://styles/mapbox/satellite-streets-v%d";
+
+ /**
+ * Satellite Streets: Global satellite and aerial imagery with unobtrusive labels (Version 8).
+ */
+ private static final String SATELLITE_STREETS_V8 = "mapbox://styles/mapbox/satellite-hybrid-v8";
+
+ /**
+ * Get versioned url of Mapbox streets style.
+ * <p>
+ * <ul>
+ * <li>Current default version is 9.</li>
+ * </ul
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getMapboxStreetsUrl(int version) {
+ return String.format(MapboxConstants.MAPBOX_LOCALE, MAPBOX_STREETS_BASE, version);
+ }
+
+ /**
+ * Get versioned url of Outdoors streets style.
+ * <p>
+ * <ul>
+ * <li>Current version is 9.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getOutdoorsStyleUrl(int version) {
+ return String.format(MapboxConstants.MAPBOX_LOCALE, OUTDOORS_BASE, version);
+ }
+
+ /**
+ * Get versioned url of Light style.
+ * <p>
+ * <ul>
+ * <li>Current default version is 9.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getLightStyleUrl(int version) {
+ return String.format(MapboxConstants.MAPBOX_LOCALE, LIGHT_BASE, version);
+ }
+
+ /**
+ * Get versioned url of Dark style.
+ * <p>
+ * <ul>
+ * <li>Current default version is 9.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getDarkStyleUrl(int version) {
+ return String.format(MapboxConstants.MAPBOX_LOCALE, DARK_BASE, version);
+ }
+
+ /**
+ * Get versioned url of Satellite style.
+ * <p>
+ * <ul>
+ * <li>Current version is 9.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getSatelliteStyleUrl(int version) {
+ return String.format(MapboxConstants.MAPBOX_LOCALE, SATELLITE_BASE, version);
+ }
+
+ /**
+ * Get versioned url of Satellite streets style.
+ * <p>
+ * <ul>
+ * <li>Current version is 9.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * More information on the Mapbox styles API can be found on https://www.mapbox.com/api-documentation/#styles
+ * </p>
+ *
+ * @param version the version of the style.
+ * @return uri to load style from
+ */
+ public static String getSatelliteStreetsStyleUrl(int version) {
+ if (version == 8) {
+ return SATELLITE_STREETS_V8;
+ }
+ return String.format(MapboxConstants.MAPBOX_LOCALE, SATELLITE_STREETS_BASE, version);
+ }
+
+ /**
* Indicates the parameter accepts one of the values from {@link Style}.
+ *
+ * @deprecated use dedicated versioned methods in {@link Style} instead.
*/
@StringDef({MAPBOX_STREETS, EMERALD, LIGHT, DARK, SATELLITE, SATELLITE_STREETS})
@Retention(RetentionPolicy.SOURCE)
+ @Deprecated
public @interface StyleUrl {
}
@@ -28,28 +171,49 @@ public class Style {
/**
* Mapbox Streets: A complete basemap, perfect for incorporating your own data.
+ *
+ * @deprecated use {@link #getMapboxStreetsUrl(int)} instead.
*/
- public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v8";
+ @Deprecated
+ public static final String MAPBOX_STREETS = "mapbox://styles/mapbox/streets-v9";
+
/**
* Emerald: A versatile style, with emphasis on road networks and public transit.
+ *
+ * @deprecated this style has been deprecated and will be removed in future versions.
*/
+ @Deprecated
public static final String EMERALD = "mapbox://styles/mapbox/emerald-v8";
+
/**
* Light: Subtle light backdrop for data visualizations.
+ *
+ * @deprecated use {@link #getLightStyleUrl(int)} instead.
*/
- public static final String LIGHT = "mapbox://styles/mapbox/light-v8";
+ @Deprecated
+ public static final String LIGHT = "mapbox://styles/mapbox/light-v9";
+
/**
* Dark: Subtle dark backdrop for data visualizations.
+ *
+ * @deprecated use {@link #getDarkStyleUrl(int)} (int)} instead.
*/
- public static final String DARK = "mapbox://styles/mapbox/dark-v8";
+ @Deprecated
+ public static final String DARK = "mapbox://styles/mapbox/dark-v9";
+
/**
* Satellite: A beautiful global satellite and aerial imagery layer.
+ *
+ * @deprecated use {@link #getSatelliteStyleUrl(int)} instead.
*/
- public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v8";
+ @Deprecated
+ public static final String SATELLITE = "mapbox://styles/mapbox/satellite-v9";
/**
* Satellite Streets: Global satellite and aerial imagery with unobtrusive labels.
+ *
+ * @deprecated use {@link #getSatelliteStreetsStyleUrl(int)} (int)} instead.
*/
- public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-hybrid-v8";
-
+ @Deprecated
+ public static final String SATELLITE_STREETS = "mapbox://styles/mapbox/satellite-streets-v9";
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
index 10ab7a5bbb..5b87e70ef6 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java
@@ -16,12 +16,13 @@ import javax.net.ssl.SSLException;
import okhttp3.Call;
import okhttp3.Callback;
+import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
class HTTPRequest implements Callback {
-
+
private static OkHttpClient mClient = new OkHttpClient();
private final String LOG_TAG = HTTPRequest.class.getName();
@@ -46,6 +47,17 @@ class HTTPRequest implements Callback {
mNativePtr = nativePtr;
try {
+ HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
+ final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
+ if (host.equals("mapbox.com") || host.endsWith(".mapbox.com")) {
+ if (httpUrl.querySize() == 0) {
+ resourceUrl = resourceUrl + "?";
+ } else {
+ resourceUrl = resourceUrl + "&";
+ }
+ resourceUrl = resourceUrl + "events=true";
+ }
+
Request.Builder builder = new Request.Builder().url(resourceUrl).tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE)).addHeader("User-Agent", userAgent);
if (etag.length() > 0) {
builder = builder.addHeader("If-None-Match", etag);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
index 95278ed508..08f18892d2 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/location/LocationServices.java
@@ -14,11 +14,21 @@ import com.mapbox.mapboxsdk.telemetry.TelemetryLocationReceiver;
import com.mapzen.android.lost.api.LocationRequest;
import com.mapzen.android.lost.api.LostApiClient;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages locational updates. Contains methods to register and unregister location listeners.
+ * <p>
+ * <ul>
+ * <li>You can register a {@link LocationListener} with {@link #addLocationListener(LocationListener)} to receive location updates.</li>
+ * <li> You can unregister a {@link LocationListener} with {@link #removeLocationListener(LocationListener)}.</li>
+ * </ul>
+ * <p/>
+ * <p>
+ * Note: If registering a listener in your Activity.onResume() implementation, you should unregister it in Activity.onPause().
+ * (You won't receive location updates when paused, and this will cut down on unnecessary system overhead).
+ * Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.
+ * </p>
*/
public class LocationServices implements com.mapzen.android.lost.api.LocationListener {
@@ -30,7 +40,7 @@ public class LocationServices implements com.mapzen.android.lost.api.LocationLis
private LostApiClient locationClient;
private Location lastLocation;
- private List<LocationListener> locationListeners;
+ private CopyOnWriteArrayList<LocationListener> locationListeners;
private boolean isGPSEnabled;
@@ -42,7 +52,7 @@ public class LocationServices implements com.mapzen.android.lost.api.LocationLis
this.context = context;
// Setup location services
locationClient = new LostApiClient.Builder(context).build();
- locationListeners = new ArrayList<>();
+ locationListeners = new CopyOnWriteArrayList<>();
}
/**
@@ -64,8 +74,7 @@ public class LocationServices implements com.mapzen.android.lost.api.LocationLis
* @param enableGPS true if GPS is to be enabled, false if GPS is to be disabled
*/
public void toggleGPS(boolean enableGPS) {
- if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) &&
- (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
+ if (!areLocationPermissionsGranted()) {
Log.w(TAG, "Location Permissions Not Granted Yet. Try again after requesting.");
return;
}
@@ -123,7 +132,7 @@ public class LocationServices implements com.mapzen.android.lost.api.LocationLis
*/
@Override
public void onLocationChanged(Location location) {
- Log.d(TAG, "onLocationChanged()..." + location);
+// Log.d(TAG, "onLocationChanged()..." + location);
this.lastLocation = location;
// Update Listeners
@@ -166,4 +175,17 @@ public class LocationServices implements com.mapzen.android.lost.api.LocationLis
public boolean removeLocationListener(@NonNull LocationListener locationListener) {
return this.locationListeners.remove(locationListener);
}
+
+ /**
+ * Check status of Location Permissions
+ * @return True if granted to the app, False if not
+ */
+ public boolean areLocationPermissionsGranted() {
+ if ((ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) &&
+ (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
+ Log.w(TAG, "Location Permissions Not Granted Yet. Try again after requesting.");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
index 2fefd805ea..27ecb7520b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java
@@ -1,14 +1,19 @@
package com.mapbox.mapboxsdk.maps;
import android.app.Fragment;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
/**
* Fragment wrapper around a map view.
@@ -44,7 +49,7 @@ public final class MapFragment extends Fragment {
}
/**
- * Creates the fragment view hierachy.
+ * Creates the fragment view hierarchy.
*
* @param inflater Inflater used to inflate content.
* @param container The parent layout for the map fragment.
@@ -54,11 +59,67 @@ public final class MapFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
- MapboxMapOptions options = getArguments().getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
+ MapboxMapOptions options = null;
+
+ // Get bundle
+ Bundle bundle = getArguments();
+ if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) {
+ options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
+ }
+
+ // Assign an AccessToken if needed
+ if (options == null || options.getAccessToken() == null) {
+ String token = null;
+ if (MapboxAccountManager.getInstance() != null) {
+ token = MapboxAccountManager.getInstance().getAccessToken();
+ } else {
+ token = getToken(inflater.getContext());
+ }
+ if (TextUtils.isEmpty(token)) {
+ throw new InvalidAccessTokenException();
+ }
+ if (options == null) {
+ options = new MapboxMapOptions().accessToken(token);
+ } else {
+ options.accessToken(token);
+ }
+ }
return mMap = new MapView(inflater.getContext(), options);
}
/**
+ * <p>
+ * Returns the Mapbox access token set in the app resources.
+ * </p>
+ * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST}
+ * meta-data value. If not found it will then attempt to load the access token from the
+ * {@code res/raw/token.txt} 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.
+ * @see MapboxConstants#KEY_META_DATA_MANIFEST
+ *
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
+ */
+ @Deprecated
+ private String getToken(@NonNull Context context) {
+ try {
+ // read out AndroidManifest
+ PackageManager packageManager = context.getPackageManager();
+ ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
+ String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST);
+ if (token == null || token.isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ return token;
+ } catch (Exception e) {
+ // 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;
+ }
+ }
+
+ /**
* Called when the fragment view hierarchy is created.
*
* @param view The content view of the fragment
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index 38dd4bccb4..b34b947a2a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -10,15 +10,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
+import android.graphics.drawable.ColorDrawable;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -58,12 +58,14 @@ import android.widget.ZoomButtonsController;
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
import com.almeros.android.multitouch.gesturedetectors.ShoveGestureDetector;
import com.almeros.android.multitouch.gesturedetectors.TwoFingerGestureDetector;
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.Icon;
import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.camera.CameraPosition;
@@ -73,15 +75,17 @@ import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.exceptions.IconBitmapChangedException;
-import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
-import com.mapbox.mapboxsdk.exceptions.TelemetryServiceNotConfiguredException;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.layers.CustomLayer;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
-import com.mapbox.mapboxsdk.maps.widgets.UserLocationView;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.telemetry.MapboxEvent;
import com.mapbox.mapboxsdk.telemetry.MapboxEventManager;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -106,19 +110,25 @@ import java.util.concurrent.CopyOnWriteArrayList;
* </p>
* <strong>Warning:</strong> Please note that you are responsible for getting permission to use the map data,
* and for ensuring your use adheres to the relevant terms of use.
- *
- * @see MapView#setAccessToken(String)
*/
public class MapView extends FrameLayout {
private MapboxMap mMapboxMap;
+ private boolean mInitialLoad;
+ private boolean mDestroyed;
+
private List<Icon> mIcons;
+ private int mAverageIconHeight;
+ private int mAverageIconWidth;
private NativeMapView mNativeMapView;
+ private boolean mHasSurface = false;
+
private CompassView mCompassView;
private ImageView mLogoView;
private ImageView mAttributionsView;
- private UserLocationView mUserLocationView;
+ private MyLocationView mMyLocationView;
+ private LocationListener mMyLocationListener;
private CopyOnWriteArrayList<OnMapChangedListener> mOnMapChangedListener;
private ZoomButtonsController mZoomButtonsController;
@@ -140,11 +150,9 @@ public class MapView extends FrameLayout {
private int mContentPaddingRight;
private int mContentPaddingBottom;
- private String mStyleUrl;
+ private StyleInitializer mStyleInitializer;
private List<OnMapReadyCallback> mOnMapReadyCallbackList;
- private boolean mInitialLoad;
- private boolean mDestroyed;
@UiThread
public MapView(@NonNull Context context) {
@@ -176,6 +184,7 @@ public class MapView extends FrameLayout {
mOnMapChangedListener = new CopyOnWriteArrayList<>();
mMapboxMap = new MapboxMap(this);
mIcons = new ArrayList<>();
+ mStyleInitializer = new StyleInitializer(context);
View view = LayoutInflater.from(context).inflate(R.layout.mapview_internal, this);
if (!isInEditMode()) {
@@ -215,8 +224,8 @@ public class MapView extends FrameLayout {
// Connectivity
onConnectivityChanged(isConnected());
- mUserLocationView = (UserLocationView) view.findViewById(R.id.userLocationView);
- mUserLocationView.setMapboxMap(mMapboxMap);
+ mMyLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
+ mMyLocationView.setMapboxMap(mMapboxMap);
mCompassView = (CompassView) view.findViewById(R.id.compassView);
mCompassView.setMapboxMap(mMapboxMap);
@@ -245,24 +254,45 @@ public class MapView extends FrameLayout {
mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
}
- String accessToken = options.getAccessToken();
- if (!TextUtils.isEmpty(accessToken)) {
- mMapboxMap.setAccessToken(accessToken);
+ String accessToken = null;
+ if (MapboxAccountManager.getInstance() != null) {
+ accessToken = MapboxAccountManager.getInstance().getAccessToken();
+ } else {
+ accessToken = options.getAccessToken();
}
String style = options.getStyle();
- if (!TextUtils.isEmpty(style)) {
- mMapboxMap.setStyleUrl(style);
+ if (!TextUtils.isEmpty(accessToken)) {
+ mMapboxMap.setAccessToken(accessToken);
+ if (style != null) {
+ setStyleUrl(style);
+ }
+ } else {
+ mStyleInitializer.setStyle(style, true);
}
+ // MyLocationView
+ MyLocationViewSettings myLocationViewSettings = mMapboxMap.getMyLocationViewSettings();
+ myLocationViewSettings.setForegroundDrawable(options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
+ myLocationViewSettings.setForegroundTintColor(options.getMyLocationForegroundTintColor());
+ myLocationViewSettings.setBackgroundDrawable(options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
+ myLocationViewSettings.setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
+ myLocationViewSettings.setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
+ myLocationViewSettings.setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
mMapboxMap.setMyLocationEnabled(options.getLocationEnabled());
// Enable gestures
UiSettings uiSettings = mMapboxMap.getUiSettings();
uiSettings.setZoomGesturesEnabled(options.getZoomGesturesEnabled());
+ uiSettings.setZoomGestureChangeAllowed(options.getZoomGesturesEnabled());
uiSettings.setScrollGesturesEnabled(options.getScrollGesturesEnabled());
+ uiSettings.setScrollGestureChangeAllowed(options.getScrollGesturesEnabled());
uiSettings.setRotateGesturesEnabled(options.getRotateGesturesEnabled());
+ uiSettings.setRotateGestureChangeAllowed(options.getRotateGesturesEnabled());
uiSettings.setTiltGesturesEnabled(options.getTiltGesturesEnabled());
+ uiSettings.setTiltGestureChangeAllowed(options.getTiltGesturesEnabled());
+
+ // Ui Controls
uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled());
// Zoom
@@ -303,6 +333,10 @@ public class MapView extends FrameLayout {
int seventySixDp = (int) resources.getDimension(R.dimen.seventy_six_dp);
uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp);
}
+
+ int attributionTintColor = options.getAttributionTintColor();
+ uiSettings.setAttributionTintColor(attributionTintColor != -1 ?
+ attributionTintColor : ColorUtils.getPrimaryColor(getContext()));
}
//
@@ -323,7 +357,7 @@ public class MapView extends FrameLayout {
@UiThread
public void onCreate(@Nullable Bundle savedInstanceState) {
// Force a check for an access token
- validateAccessToken(getAccessToken());
+ MapboxAccountManager.validateAccessToken(getAccessToken());
if (savedInstanceState != null && savedInstanceState.getBoolean(MapboxConstants.STATE_HAS_SAVED_STATE)) {
@@ -335,9 +369,13 @@ public class MapView extends FrameLayout {
UiSettings uiSettings = mMapboxMap.getUiSettings();
uiSettings.setZoomGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED));
+ uiSettings.setZoomGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE));
uiSettings.setScrollGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED));
+ uiSettings.setScrollGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE));
uiSettings.setRotateGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED));
+ uiSettings.setRotateGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE));
uiSettings.setTiltGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED));
+ uiSettings.setTiltGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE));
uiSettings.setZoomControlsEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED));
// Compass
@@ -366,9 +404,6 @@ public class MapView extends FrameLayout {
mMapboxMap.setDebugActive(savedInstanceState.getBoolean(MapboxConstants.STATE_DEBUG_ACTIVE));
mMapboxMap.setStyleUrl(savedInstanceState.getString(MapboxConstants.STATE_STYLE_URL));
- setAccessToken(savedInstanceState.getString(MapboxConstants.STATE_ACCESS_TOKEN));
- mNativeMapView.setDefaultTransitionDuration(
- savedInstanceState.getLong(MapboxConstants.STATE_DEFAULT_TRANSITION_DURATION));
// User location
try {
@@ -384,10 +419,8 @@ public class MapView extends FrameLayout {
//noinspection ResourceType
trackingSettings.setMyBearingTrackingMode(savedInstanceState.getInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE));
} else if (savedInstanceState == null) {
- // Force a check for Telemetry
- validateTelemetryServiceConfigured();
-
// Start Telemetry (authorization determined in initial MapboxEventManager constructor)
+ Log.i(MapView.class.getCanonicalName(), "MapView start Telemetry...");
MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager();
eventManager.initialize(getContext(), getAccessToken());
}
@@ -400,21 +433,21 @@ public class MapView extends FrameLayout {
addOnMapChangedListener(new OnMapChangedListener() {
@Override
public void onMapChanged(@MapChange int change) {
- if (change == DID_FINISH_RENDERING_MAP_FULLY_RENDERED) {
+ if (change == WILL_START_RENDERING_MAP && mInitialLoad) {
+ mInitialLoad = false;
reloadIcons();
reloadMarkers();
adjustTopOffsetPixels();
- if (mInitialLoad) {
- mInitialLoad = false;
- if (mOnMapReadyCallbackList.size() > 0) {
- Iterator<OnMapReadyCallback> iterator = mOnMapReadyCallbackList.iterator();
- while (iterator.hasNext()) {
- OnMapReadyCallback callback = iterator.next();
- callback.onMapReady(mMapboxMap);
- iterator.remove();
- }
+ if (mOnMapReadyCallbackList.size() > 0) {
+ Iterator<OnMapReadyCallback> iterator = mOnMapReadyCallbackList.iterator();
+ while (iterator.hasNext()) {
+ OnMapReadyCallback callback = iterator.next();
+ callback.onMapReady(mMapboxMap);
+ iterator.remove();
}
}
+ } else if (change == REGION_IS_CHANGING || change == REGION_DID_CHANGE || change == DID_FINISH_LOADING_MAP) {
+ mMapboxMap.getMarkerViewManager().scheduleViewMarkerInvalidation();
}
}
});
@@ -440,9 +473,7 @@ public class MapView extends FrameLayout {
outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
outState.putParcelable(MapboxConstants.STATE_CAMERA_POSITION, mMapboxMap.getCameraPosition());
outState.putBoolean(MapboxConstants.STATE_DEBUG_ACTIVE, mMapboxMap.isDebugActive());
- outState.putString(MapboxConstants.STATE_STYLE_URL, mStyleUrl);
- outState.putString(MapboxConstants.STATE_ACCESS_TOKEN, mMapboxMap.getAccessToken());
- outState.putLong(MapboxConstants.STATE_DEFAULT_TRANSITION_DURATION, mNativeMapView.getDefaultTransitionDuration());
+ outState.putString(MapboxConstants.STATE_STYLE_URL, mStyleInitializer.getStyle());
outState.putBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED, mMapboxMap.isMyLocationEnabled());
// TrackingSettings
@@ -453,9 +484,13 @@ public class MapView extends FrameLayout {
// UiSettings
UiSettings uiSettings = mMapboxMap.getUiSettings();
outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED, uiSettings.isZoomGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_ZOOM_ENABLED_CHANGE, uiSettings.isZoomGestureChangeAllowed());
outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED, uiSettings.isScrollGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_SCROLL_ENABLED_CHANGE, uiSettings.isScrollGestureChangeAllowed());
outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED, uiSettings.isRotateGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_ROTATE_ENABLED_CHANGE, uiSettings.isRotateGestureChangeAllowed());
outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED, uiSettings.isTiltGesturesEnabled());
+ outState.putBoolean(MapboxConstants.STATE_TILT_ENABLED_CHANGE, uiSettings.isTiltGestureChangeAllowed());
outState.putBoolean(MapboxConstants.STATE_ZOOM_CONTROLS_ENABLED, uiSettings.isZoomControlsEnabled());
// UiSettings - Compass
@@ -505,8 +540,7 @@ public class MapView extends FrameLayout {
getContext().unregisterReceiver(mConnectivityReceiver);
mConnectivityReceiver = null;
- mUserLocationView.onPause();
- mNativeMapView.pause();
+ mMyLocationView.onPause();
}
/**
@@ -518,13 +552,12 @@ public class MapView extends FrameLayout {
mConnectivityReceiver = new ConnectivityReceiver();
getContext().registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
- mNativeMapView.resume();
mNativeMapView.update();
- mUserLocationView.onResume();
+ mMyLocationView.onResume();
- if (mStyleUrl == null) {
+ if (mStyleInitializer.isDefaultStyle()) {
// user has failed to supply a style url
- setStyleUrl(Style.MAPBOX_STREETS);
+ setStyleUrl(mStyleInitializer.getStyle());
}
}
@@ -567,20 +600,18 @@ public class MapView extends FrameLayout {
return mNativeMapView.getPitch();
}
- void setTilt(Double pitch, @Nullable Long duration) {
- long actualDuration = 0;
- if (duration != null) {
- actualDuration = duration;
- }
- mNativeMapView.setPitch(pitch, actualDuration);
+ void setTilt(Double pitch) {
+ mMyLocationView.setTilt(pitch);
+ mNativeMapView.setPitch(pitch, 0);
}
+
//
// Direction
//
double getDirection() {
- if(mDestroyed){
+ if (mDestroyed) {
return 0;
}
@@ -641,6 +672,14 @@ public class MapView extends FrameLayout {
return mContentPaddingBottom;
}
+ int getContentWidth(){
+ return getWidth() - mContentPaddingLeft - mContentPaddingRight;
+ }
+
+ int getContentHeight(){
+ return getHeight() - mContentPaddingBottom - mContentPaddingTop;
+ }
+
//
// Zoom
//
@@ -744,7 +783,7 @@ public class MapView extends FrameLayout {
* <li>{@code asset://...}:
* reads the style from the APK {@code assets/} directory.
* This is used to load a style bundled with your app.</li>
- * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
+ * <li>{@code null}: loads the default {@link Style#getMapboxStreetsUrl(int)} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return immediately before the style finishes loading.
@@ -760,7 +799,7 @@ public class MapView extends FrameLayout {
if (mDestroyed) {
return;
}
- mStyleUrl = url;
+ mStyleInitializer.setStyle(url);
mNativeMapView.setStyleUrl(url);
}
@@ -794,7 +833,7 @@ public class MapView extends FrameLayout {
@UiThread
@NonNull
public String getStyleUrl() {
- return mStyleUrl;
+ return mStyleInitializer.getStyle();
}
//
@@ -803,16 +842,21 @@ public class MapView extends FrameLayout {
/**
* <p>
- * Sets the current Mapbox access token used to load map styles and tiles.
+ * DEPRECATED @see MapboxAccountManager#start(String)
* </p>
* <p>
+ * <p>
+ * Sets the current Mapbox access token used to load map styles and tiles.
+ * <p>
* You must set a valid access token before you call {@link MapView#onCreate(Bundle)}
* or an exception will be thrown.
* </p>
*
* @param accessToken Your public Mapbox access token.
* @see MapView#onCreate(Bundle)
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
*/
+ @Deprecated
@UiThread
public void setAccessToken(@NonNull String accessToken) {
if (mDestroyed) {
@@ -822,15 +866,22 @@ public class MapView extends FrameLayout {
if (!TextUtils.isEmpty(accessToken)) {
accessToken = accessToken.trim();
}
- validateAccessToken(accessToken);
+ MapboxAccountManager.validateAccessToken(accessToken);
mNativeMapView.setAccessToken(accessToken);
}
/**
+ * <p>
+ * DEPRECATED @see MapboxAccountManager#getAccessToken()
+ * </p>
+ * <p/>
* Returns the current Mapbox access token used to load map styles and tiles.
+ * </p>
*
* @return The current Mapbox access token.
+ * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
*/
+ @Deprecated
@UiThread
@Nullable
public String getAccessToken() {
@@ -840,31 +891,6 @@ public class MapView extends FrameLayout {
return mNativeMapView.getAccessToken();
}
- // Checks if the given token is valid
- private void validateAccessToken(String accessToken) {
- if (TextUtils.isEmpty(accessToken) || (!accessToken.startsWith("pk.") && !accessToken.startsWith("sk."))) {
- throw new InvalidAccessTokenException();
- }
- }
-
- // Checks that TelemetryService has been configured by developer
- private void validateTelemetryServiceConfigured() {
- try {
- // Check Implementing app's AndroidManifest.xml
- PackageInfo packageInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), PackageManager.GET_SERVICES);
- if (packageInfo.services != null) {
- for (ServiceInfo service : packageInfo.services) {
- if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) {
- return;
- }
- }
- }
- } catch (Exception e) {
- Log.w(MapboxConstants.TAG, "Error checking for Telemetry Service Config: " + e);
- }
- throw new TelemetryServiceNotConfiguredException();
- }
-
//
// Projection
//
@@ -873,22 +899,17 @@ public class MapView extends FrameLayout {
if (mDestroyed) {
return new LatLng();
}
- float x = point.x;
- float y = point.y;
-
- return mNativeMapView.latLngForPixel(new PointF(x / mScreenDensity, y / mScreenDensity));
+ point.set(point.x / mScreenDensity, point.y / mScreenDensity);
+ return mNativeMapView.latLngForPixel(point);
}
PointF toScreenLocation(@NonNull LatLng location) {
- if (mDestroyed) {
+ if (mDestroyed || location == null) {
return new PointF();
}
- PointF point = mNativeMapView.pixelForLatLng(location);
-
- float x = point.x * mScreenDensity;
- float y = point.y * mScreenDensity;
-
- return new PointF(x, y);
+ PointF pointF = mNativeMapView.pixelForLatLng(location);
+ pointF.set(pointF.x * mScreenDensity, pointF.y * mScreenDensity);
+ return pointF;
}
//
@@ -897,10 +918,24 @@ public class MapView extends FrameLayout {
Icon loadIconForMarker(Marker marker) {
Icon icon = marker.getIcon();
+
+ // calculating average before adding
+ int iconSize = mIcons.size() + 1;
+
+ // TODO replace former if case with anchor implementation,
+ // current workaround for having extra pixels is diving height by 2
if (icon == null) {
icon = IconFactory.getInstance(getContext()).defaultMarker();
+ Bitmap bitmap = icon.getBitmap();
+ mAverageIconHeight = mAverageIconHeight + (bitmap.getHeight() / 2 - mAverageIconHeight) / iconSize;
+ mAverageIconWidth = mAverageIconHeight + (bitmap.getWidth() - mAverageIconHeight) / iconSize;
marker.setIcon(icon);
+ } else {
+ Bitmap bitmap = icon.getBitmap();
+ mAverageIconHeight = mAverageIconHeight + (bitmap.getHeight() - mAverageIconHeight) / iconSize;
+ mAverageIconWidth = mAverageIconHeight + (bitmap.getWidth() - mAverageIconHeight) / iconSize;
}
+
if (!mIcons.contains(icon)) {
mIcons.add(icon);
loadIcon(icon);
@@ -930,7 +965,6 @@ public class MapView extends FrameLayout {
density = DisplayMetrics.DENSITY_DEFAULT;
}
float scale = density / DisplayMetrics.DENSITY_DEFAULT;
-
mNativeMapView.addAnnotationIcon(
id,
bitmap.getWidth(),
@@ -987,6 +1021,9 @@ public class MapView extends FrameLayout {
}
long addMarker(@NonNull Marker marker) {
+ if(mDestroyed){
+ return 0l;
+ }
return mNativeMapView.addMarker(marker);
}
@@ -1039,16 +1076,11 @@ public class MapView extends FrameLayout {
mNativeMapView.removeAnnotations(ids);
}
- private List<Marker> getMarkersInBounds(@NonNull LatLngBounds bbox) {
- if (mDestroyed) {
+ List<Marker> getMarkersInBounds(@NonNull LatLngBounds bbox) {
+ if (mDestroyed || bbox == null) {
return new ArrayList<>();
}
- if (bbox == null) {
- Log.w(MapboxConstants.TAG, "bbox was null, so just returning null");
- return null;
- }
-
// TODO: filter in JNI using C++ parameter to getAnnotationsInBounds
long[] ids = mNativeMapView.getAnnotationsInBounds(bbox);
@@ -1070,10 +1102,35 @@ public class MapView extends FrameLayout {
return new ArrayList<>(annotations);
}
+ public List<MarkerView> getMarkerViewsInBounds(@NonNull LatLngBounds bbox) {
+ if (mDestroyed || bbox == null) {
+ return new ArrayList<>();
+ }
+
+ // TODO: filter in JNI using C++ parameter to getAnnotationsInBounds
+ long[] ids = mNativeMapView.getAnnotationsInBounds(bbox);
+
+ List<Long> idsList = new ArrayList<>(ids.length);
+ for (int i = 0; i < ids.length; i++) {
+ idsList.add(ids[i]);
+ }
+
+ List<MarkerView> annotations = new ArrayList<>(ids.length);
+ List<Annotation> annotationList = mMapboxMap.getAnnotations();
+ int count = annotationList.size();
+ for (int i = 0; i < count; i++) {
+ Annotation annotation = annotationList.get(i);
+ if (annotation instanceof MarkerView && idsList.contains(annotation.getId())) {
+ annotations.add((MarkerView) annotation);
+ }
+ }
+
+ return new ArrayList<>(annotations);
+ }
+
+
int getTopOffsetPixelsForIcon(Icon icon) {
- // This method will dead lock if map paused. Causes a freeze if you add a marker in an
- // activity's onCreate()
- if (mDestroyed || mNativeMapView.isPaused()) {
+ if (mDestroyed) {
return 0;
}
@@ -1086,18 +1143,28 @@ public class MapView extends FrameLayout {
return;
}
- if (left == mContentPaddingLeft && top == mContentPaddingTop && right == mContentPaddingRight && bottom == mContentPaddingBottom) {
- return;
- }
+// if (left == mContentPaddingLeft && top == mContentPaddingTop && right == mContentPaddingRight && bottom == mContentPaddingBottom) {
+// return;
+// }
mContentPaddingLeft = left;
mContentPaddingTop = top;
mContentPaddingRight = right;
mContentPaddingBottom = bottom;
+ int[] userLocationViewPadding = mMapboxMap.getMyLocationViewSettings().getPadding();
+ left += userLocationViewPadding[0];
+ top += userLocationViewPadding[1];
+ right += userLocationViewPadding[2];
+ bottom += userLocationViewPadding[3];
+
mNativeMapView.setContentPadding(top / mScreenDensity, left / mScreenDensity, bottom / mScreenDensity, right / mScreenDensity);
}
+ public void invalidateContentPadding() {
+ setContentPadding(mContentPaddingLeft, mContentPaddingTop, mContentPaddingRight, mContentPaddingBottom);
+ }
+
double getMetersPerPixelAtLatitude(@FloatRange(from = -180, to = 180) double latitude) {
if (mDestroyed) {
return 0;
@@ -1118,7 +1185,7 @@ public class MapView extends FrameLayout {
mNativeMapView.jumpTo(bearing, center, pitch, zoom);
}
- void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
+ void easeTo(double bearing, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
if (mDestroyed) {
return;
}
@@ -1139,7 +1206,7 @@ public class MapView extends FrameLayout {
});
}
- mNativeMapView.easeTo(bearing, center, duration, pitch, zoom);
+ mNativeMapView.easeTo(bearing, center, duration, pitch, zoom, easingInterpolator);
}
void flyTo(double bearing, LatLng center, long duration, double pitch, double zoom, @Nullable final MapboxMap.CancelableCallback cancelableCallback) {
@@ -1220,11 +1287,15 @@ public class MapView extends FrameLayout {
return;
}
- if (mDestroyed || mNativeMapView.isPaused()) {
+ if (mDestroyed) {
+ return;
+ }
+
+ if (!mHasSurface) {
return;
}
- mNativeMapView.renderSync();
+ mNativeMapView.render();
}
@Override
@@ -1250,6 +1321,10 @@ public class MapView extends FrameLayout {
private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
private Surface mSurface;
+ private View mViewHolder;
+
+ private static final int VIEW_MARKERS_POOL_SIZE = 20;
+
// Called when the native surface texture has been created
// Must do all EGL/GL ES initialization here
@@ -1257,12 +1332,15 @@ public class MapView extends FrameLayout {
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mNativeMapView.createSurface(mSurface = new Surface(surface));
mNativeMapView.resizeFramebuffer(width, height);
+ mHasSurface = true;
}
// Called when the native surface texture has been destroyed
// Must do all EGL/GL ES destruction here
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ mHasSurface = false;
+
if (mNativeMapView != null) {
mNativeMapView.destroySurface();
}
@@ -1274,7 +1352,7 @@ public class MapView extends FrameLayout {
// Must handle window resizing here.
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- if(mDestroyed){
+ if (mDestroyed) {
return;
}
@@ -1285,12 +1363,14 @@ public class MapView extends FrameLayout {
// Must sync with UI here
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
- if(mDestroyed){
+ if (mDestroyed) {
return;
}
mCompassView.update(getDirection());
- mUserLocationView.update();
+ mMyLocationView.update();
+ mMapboxMap.getMarkerViewManager().update();
+
for (InfoWindow infoWindow : mMapboxMap.getInfoWindows()) {
infoWindow.update();
}
@@ -1432,7 +1512,8 @@ public class MapView extends FrameLayout {
case MotionEvent.ACTION_POINTER_DOWN:
// Second pointer down
- mTwoTap = event.getPointerCount() == 2;
+ mTwoTap = event.getPointerCount() == 2
+ && mMapboxMap.getUiSettings().isZoomGesturesEnabled();
if (mTwoTap) {
// Confirmed 2nd Finger Down
trackGestureEvent(MapboxEvent.GESTURE_TWO_FINGER_SINGLETAP, event.getX(), event.getY());
@@ -1517,8 +1598,7 @@ public class MapView extends FrameLayout {
zoom(true, e.getX(), e.getY());
} else {
// Zoom in on user location view
- PointF centerPoint = mUserLocationView.getMarkerScreenPoint();
- zoom(true, centerPoint.x, centerPoint.y);
+ zoom(true, mMyLocationView.getCenterX(), mMyLocationView.getCenterY());
}
break;
}
@@ -1540,17 +1620,15 @@ public class MapView extends FrameLayout {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- // Open / Close InfoWindow
- PointF tapPoint = new PointF(e.getX(), e.getY());
-
List<Marker> selectedMarkers = mMapboxMap.getSelectedMarkers();
- final float toleranceSides = 15 * mScreenDensity;
- final float toleranceTop = 20 * mScreenDensity;
- final float toleranceBottom = 5 * mScreenDensity;
-
- RectF tapRect = new RectF(tapPoint.x - toleranceSides, tapPoint.y + toleranceTop,
- tapPoint.x + toleranceSides, tapPoint.y - toleranceBottom);
+ PointF tapPoint = new PointF(e.getX(), e.getY());
+ float toleranceSides = 4 * mScreenDensity;
+ float toleranceTopBottom = 10 * mScreenDensity;
+ RectF tapRect = new RectF(tapPoint.x - mAverageIconWidth / 2 - toleranceSides,
+ tapPoint.y - mAverageIconHeight / 2 - toleranceTopBottom,
+ tapPoint.x + mAverageIconWidth / 2 + toleranceSides,
+ tapPoint.y + mAverageIconHeight / 2 + toleranceTopBottom);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(fromScreenLocation(new PointF(tapRect.left, tapRect.bottom)));
@@ -1585,7 +1663,10 @@ public class MapView extends FrameLayout {
if (annotation instanceof Marker) {
if (annotation.getId() == newSelectedMarkerId) {
if (selectedMarkers.isEmpty() || !selectedMarkers.contains(annotation)) {
- mMapboxMap.selectMarker((Marker) annotation);
+ // only handle click if no marker view is available
+ if (!(annotation instanceof MarkerView)) {
+ mMapboxMap.selectMarker((Marker) annotation);
+ }
}
break;
}
@@ -1625,9 +1706,7 @@ public class MapView extends FrameLayout {
}
// reset tracking modes if gesture occurs
- if (mMapboxMap.getTrackingSettings().isDismissTrackingOnGesture()) {
- resetTrackingModes();
- }
+ resetTrackingModesIfRequired();
// Fling the map
float ease = 0.25f;
@@ -1663,10 +1742,9 @@ public class MapView extends FrameLayout {
return false;
}
- if (mMapboxMap.getTrackingSettings().isDismissTrackingOnGesture()) {
- // reset tracking modes if gesture occurs
- resetTrackingModes();
- }
+ // reset tracking modes if gesture occurs
+ resetTrackingModesIfRequired();
+
// Cancel any animation
mNativeMapView.cancelTransitions();
@@ -1695,10 +1773,8 @@ public class MapView extends FrameLayout {
return false;
}
- if (mMapboxMap.getTrackingSettings().isDismissTrackingOnGesture()) {
- // reset tracking modes if gesture occurs
- resetTrackingModes();
- }
+ // reset tracking modes if gesture occurs
+ resetTrackingModesIfRequired();
mBeginTime = detector.getEventTime();
trackGestureEvent(MapboxEvent.GESTURE_PINCH_START, detector.getFocusX(), detector.getFocusY());
@@ -1758,8 +1834,9 @@ public class MapView extends FrameLayout {
mNativeMapView.scaleBy(detector.getScaleFactor(), (getWidth() / 2) / mScreenDensity, (getHeight() / 2) / mScreenDensity);
} else {
// around user location view
- PointF centerPoint = mUserLocationView.getMarkerScreenPoint();
- mNativeMapView.scaleBy(detector.getScaleFactor(), centerPoint.x / mScreenDensity, centerPoint.y / mScreenDensity);
+ float x = mMyLocationView.getX() + mMyLocationView.getWidth() / 2;
+ float y = mMyLocationView.getY() + mMyLocationView.getHeight() / 2;
+ mNativeMapView.scaleBy(detector.getScaleFactor(), x / mScreenDensity, y / mScreenDensity);
}
}
return true;
@@ -1780,10 +1857,8 @@ public class MapView extends FrameLayout {
return false;
}
- if (mMapboxMap.getTrackingSettings().isDismissTrackingOnGesture()) {
- // reset tracking modes if gesture occurs
- resetTrackingModes();
- }
+ // reset tracking modes if gesture occurs
+ resetTrackingModesIfRequired();
mBeginTime = detector.getEventTime();
trackGestureEvent(MapboxEvent.GESTURE_ROTATION_START, detector.getFocusX(), detector.getFocusY());
@@ -1840,8 +1915,9 @@ public class MapView extends FrameLayout {
detector.getFocusY() / mScreenDensity);
} else {
// around center userlocation
- PointF centerPoint = mUserLocationView.getMarkerScreenPoint();
- mNativeMapView.setBearing(bearing, centerPoint.x / mScreenDensity, centerPoint.y / mScreenDensity);
+ float x = mMyLocationView.getX() + mMyLocationView.getWidth() / 2;
+ float y = mMyLocationView.getY() + mMyLocationView.getHeight() / 2;
+ mNativeMapView.setBearing(bearing, x / mScreenDensity, y / mScreenDensity);
}
return true;
}
@@ -1861,10 +1937,8 @@ public class MapView extends FrameLayout {
return false;
}
- if (mMapboxMap.getTrackingSettings().isDismissTrackingOnGesture()) {
- // reset tracking modes if gesture occurs
- resetTrackingModes();
- }
+ // reset tracking modes if gesture occurs
+ resetTrackingModesIfRequired();
mBeginTime = detector.getEventTime();
trackGestureEvent(MapboxEvent.GESTURE_PITCH_START, detector.getFocusX(), detector.getFocusY());
@@ -1912,14 +1986,14 @@ public class MapView extends FrameLayout {
pitch = Math.max(MapboxConstants.MINIMUM_TILT, Math.min(MapboxConstants.MAXIMUM_TILT, pitch));
// Tilt the map
- setTilt(pitch, null);
+ mMapboxMap.setTilt(pitch);
return true;
}
}
// This class handles input events from the zoom control buttons
-// Zoom controls allow single touch only devices to zoom in and out
+ // Zoom controls allow single touch only devices to zoom in and out
private class OnZoomListener implements ZoomButtonsController.OnZoomListener {
// Not used
@@ -2269,7 +2343,6 @@ public class MapView extends FrameLayout {
* @param listener The callback that's invoked on every frame rendered to the map view.
* @see MapView#removeOnMapChangedListener(OnMapChangedListener)
*/
- @UiThread
public void addOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
mOnMapChangedListener.add(listener);
@@ -2282,7 +2355,6 @@ public class MapView extends FrameLayout {
* @param listener The previously added callback to remove.
* @see MapView#addOnMapChangedListener(OnMapChangedListener)
*/
- @UiThread
public void removeOnMapChangedListener(@Nullable OnMapChangedListener listener) {
if (listener != null) {
mOnMapChangedListener.remove(listener);
@@ -2308,22 +2380,35 @@ public class MapView extends FrameLayout {
//
void setMyLocationEnabled(boolean enabled) {
- mUserLocationView.setEnabled(enabled);
+ mMyLocationView.setEnabled(enabled);
}
Location getMyLocation() {
- return mUserLocationView.getLocation();
+ return mMyLocationView.getLocation();
}
- void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) {
- mUserLocationView.setOnMyLocationChangeListener(listener);
+ void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
+ if (listener != null) {
+ mMyLocationListener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (listener != null) {
+ listener.onMyLocationChange(location);
+ }
+ }
+ };
+ LocationServices.getLocationServices(getContext()).addLocationListener(mMyLocationListener);
+ } else {
+ LocationServices.getLocationServices(getContext()).removeLocationListener(mMyLocationListener);
+ mMyLocationListener = null;
+ }
}
void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && !mMapboxMap.isMyLocationEnabled()) {
mMapboxMap.setMyLocationEnabled(true);
}
- mUserLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
+ mMyLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
MapboxMap.OnMyLocationTrackingModeChangeListener listener = mMapboxMap.getOnMyLocationTrackingModeChangeListener();
if (listener != null) {
listener.onMyLocationTrackingModeChange(myLocationTrackingMode);
@@ -2334,7 +2419,7 @@ public class MapView extends FrameLayout {
if (myBearingTrackingMode != MyBearingTracking.NONE && !mMapboxMap.isMyLocationEnabled()) {
mMapboxMap.setMyLocationEnabled(true);
}
- mUserLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
+ mMyLocationView.setMyBearingTrackingMode(myBearingTrackingMode);
MapboxMap.OnMyBearingTrackingModeChangeListener listener = mMapboxMap.getOnMyBearingTrackingModeChangeListener();
if (listener != null) {
listener.onMyBearingTrackingModeChange(myBearingTrackingMode);
@@ -2346,11 +2431,28 @@ public class MapView extends FrameLayout {
ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
- private void resetTrackingModes() {
+ private void resetTrackingModesIfRequired() {
+ TrackingSettings trackingSettings = mMapboxMap.getTrackingSettings();
+ if (trackingSettings.isDismissLocationTrackingOnGesture()) {
+ resetLocationTrackingMode();
+ }
+ if (trackingSettings.isDismissBearingTrackingOnGesture()) {
+ resetBearingTrackingMode();
+ }
+ }
+
+ private void resetLocationTrackingMode() {
try {
TrackingSettings trackingSettings = mMapboxMap.getTrackingSettings();
trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.NONE);
+ } catch (SecurityException ignore) {
+ // User did not accept location permissions
+ }
+ }
+
+ private void resetBearingTrackingMode() {
+ try {
+ setMyBearingTrackingMode(MyBearingTracking.NONE);
} catch (SecurityException ignore) {
// User did not accept location permissions
}
@@ -2404,6 +2506,13 @@ public class MapView extends FrameLayout {
mAttributionsView.setVisibility(visibility);
}
+ void setAtttibutionTintColor(int tintColor) {
+ ColorUtils.setTintList(mAttributionsView, tintColor);
+ }
+
+ int getAttributionTintColor() {
+ return mMapboxMap.getUiSettings().getAttributionTintColor();
+ }
//
// Custom layer
@@ -2455,6 +2564,26 @@ public class MapView extends FrameLayout {
mMapboxMap = mapboxMap;
}
+ MyLocationView getUserLocationView() {
+ return mMyLocationView;
+ }
+
+ @UiThread
+ void snapshot(@NonNull final MapboxMap.SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
+ TextureView textureView = (TextureView) findViewById(R.id.textureView);
+ final boolean canUseBitmap = bitmap != null && textureView.getWidth() == bitmap.getWidth() && textureView.getHeight() == bitmap.getHeight();
+
+ setDrawingCacheEnabled(true);
+ Bitmap content = Bitmap.createBitmap(getDrawingCache());
+ setDrawingCacheEnabled(false);
+
+ Bitmap output = Bitmap.createBitmap(content.getWidth(), content.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+ canvas.drawBitmap(canUseBitmap ? textureView.getBitmap(bitmap) : textureView.getBitmap(), 0, 0, null);
+ canvas.drawBitmap(content, new Matrix(), null);
+ callback.onSnapshotReady(output);
+ }
+
//
// View utility methods
//
@@ -2494,7 +2623,8 @@ public class MapView extends FrameLayout {
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.AttributionAlertDialogStyle);
builder.setTitle(R.string.attributionsDialogTitle);
builder.setAdapter(new ArrayAdapter<>(context, R.layout.attribution_list_item, items), this);
- builder.show();
+ AlertDialog dialog = builder.show();
+ dialog.getWindow().setBackgroundDrawable(new ColorDrawable(mMapView.getAttributionTintColor()));
}
// Called when someone selects an attribution, 'Improve this map' adds location data to the url
@@ -2570,6 +2700,41 @@ public class MapView extends FrameLayout {
}
/**
+ * Class responsible for managing state of Style loading.
+ */
+ static class StyleInitializer {
+
+ private String mStyle;
+ private boolean mDefaultStyle;
+
+ StyleInitializer(@NonNull Context context) {
+ mStyle = Style.getMapboxStreetsUrl(context.getResources().getInteger(R.integer.style_version));
+ mDefaultStyle = true;
+ }
+
+ void setStyle(@NonNull String style) {
+ setStyle(style, false);
+ }
+
+ void setStyle(@NonNull String style, boolean defaultStyle) {
+ if (style == null) {
+ // don't override default style
+ return;
+ }
+ mStyle = style;
+ mDefaultStyle = defaultStyle;
+ }
+
+ public String getStyle() {
+ return mStyle;
+ }
+
+ boolean isDefaultStyle() {
+ return mDefaultStyle;
+ }
+ }
+
+ /**
* Definition of a map change event.
*
* @see MapView.OnMapChangedListener#onMapChanged(int)
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
index e1a9cd8cdf..fbe6a31f6a 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java
@@ -1,5 +1,7 @@
package com.mapbox.mapboxsdk.maps;
+import android.content.Context;
+import android.graphics.Bitmap;
import android.location.Location;
import android.os.SystemClock;
import android.support.annotation.FloatRange;
@@ -7,16 +9,23 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.util.LongSparseArray;
+import android.support.v4.util.Pools;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import android.view.ViewGroup;
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
import com.mapbox.mapboxsdk.annotations.InfoWindow;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
import com.mapbox.mapboxsdk.annotations.Polyline;
@@ -30,7 +39,10 @@ import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.layers.CustomLayer;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
+import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -49,13 +61,18 @@ public class MapboxMap {
private MapView mMapView;
private UiSettings mUiSettings;
private TrackingSettings mTrackingSettings;
+ private MyLocationViewSettings myLocationViewSettings;
private Projection mProjection;
private CameraPosition mCameraPosition;
private boolean mInvalidCameraPosition;
private LongSparseArray<Annotation> mAnnotations;
+
private List<Marker> mSelectedMarkers;
+ private MarkerViewManager mMarkerViewManager;
+
private List<InfoWindow> mInfoWindows;
private MapboxMap.InfoWindowAdapter mInfoWindowAdapter;
+ private Bitmap mViewMarkerBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
private boolean mMyLocationEnabled;
private boolean mAllowConcurrentMultipleInfoWindows;
@@ -85,6 +102,7 @@ public class MapboxMap {
mAnnotations = new LongSparseArray<>();
mSelectedMarkers = new ArrayList<>();
mInfoWindows = new ArrayList<>();
+ mMarkerViewManager = new MarkerViewManager(this, mapView);
}
//
@@ -186,6 +204,20 @@ public class MapboxMap {
}
//
+ // MyLocationViewSettings
+ //
+
+ /**
+ * Gets the settings of the user location for the map.
+ */
+ public MyLocationViewSettings getMyLocationViewSettings() {
+ if (myLocationViewSettings == null) {
+ myLocationViewSettings = new MyLocationViewSettings(mMapView, mMapView.getUserLocationView());
+ }
+ return myLocationViewSettings;
+ }
+
+ //
// Projection
//
@@ -254,10 +286,12 @@ public class MapboxMap {
}
/**
- * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates.
- * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight.
+ * Gradually move the camera by the default duration, zoom will not be affected unless specified
+ * within {@link CameraUpdate}. If {@link #getCameraPosition()} is called during the animation,
+ * it will return the current location of the camera in flight.
*
* @param update The change that should be applied to the camera.
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update) {
@@ -265,11 +299,14 @@ public class MapboxMap {
}
/**
- * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates.
- * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight.
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. If {@link #getCameraPosition()} is called
+ * during the animation, it will return the current location of the camera in flight.
*
* @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update, int durationMs) {
@@ -277,17 +314,35 @@ public class MapboxMap {
}
/**
- * Ease the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates.
- * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight.
+ * Gradually move the camera by a specified duration in milliseconds, zoom will not be affected
+ * unless specified within {@link CameraUpdate}. A callback can be used to be notified when
+ * easing the camera stops. If {@link #getCameraPosition()} is called during the animation, it
+ * will return the current location of the camera in flight.
*
* @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown.
- * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or ease the camera from within onCancel().
+ * @see {@link CameraUpdateFactory} for a set of camera updates.
*/
@UiThread
public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
+ easeCamera(update, durationMs, true, callback);
+ }
+
+ @UiThread
+ public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator) {
+ easeCamera(update, durationMs, easingInterpolator, null);
+ }
+
+ @UiThread
+ public final void easeCamera(CameraUpdate update, int durationMs, boolean easingInterpolator, final MapboxMap.CancelableCallback callback) {
mCameraPosition = update.getCameraPosition(this);
- mMapView.easeTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, new CancelableCallback() {
+ mMapView.easeTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, easingInterpolator, new CancelableCallback() {
@Override
public void onCancel() {
if (callback != null) {
@@ -307,12 +362,13 @@ public class MapboxMap {
}
/**
- * Animates the movement of the camera from the current position to the position defined in the update.
- * During the animation, a call to getCameraPosition() returns an intermediate location of the camera.
- * <p/>
- * See CameraUpdateFactory for a set of updates.
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last the default amount of time.
+ * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
+ * of the camera in flight.
*
* @param update The change that should be applied to the camera.
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update) {
@@ -320,12 +376,16 @@ public class MapboxMap {
}
/**
- * Animates the movement of the camera from the current position to the position defined in the update and calls an optional callback on completion.
- * See CameraUpdateFactory for a set of updates.
- * During the animation, a call to getCameraPosition() returns an intermediate location of the camera.
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last the default amount of time. A
+ * callback can be used to be notified when animating the camera stops. During the animation, a
+ * call to {@link #getCameraPosition()} returns an intermediate location of the camera in flight.
*
* @param update The change that should be applied to the camera.
- * @param callback The callback to invoke from the main thread when the animation stops. If the animation completes normally, onFinish() is called; otherwise, onCancel() is called. Do not update or animate the camera from within onCancel().
+ * @param callback The callback to invoke from the main thread when the animation stops. If the
+ * animation completes normally, onFinish() is called; otherwise, onCancel() is
+ * called. Do not update or animate the camera from within onCancel().
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) {
@@ -333,11 +393,15 @@ public class MapboxMap {
}
/**
- * Moves the map according to the update with an animation over a specified duration. See CameraUpdateFactory for a set of updates.
- * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight.
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last a specified amount of time
+ * given in milliseconds. During the animation, a call to {@link #getCameraPosition()} returns
+ * an intermediate location of the camera in flight.
*
* @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, int durationMs) {
@@ -345,12 +409,22 @@ public class MapboxMap {
}
/**
- * Moves the map according to the update with an animation over a specified duration, and calls an optional callback on completion. See CameraUpdateFactory for a set of updates.
- * If getCameraPosition() is called during the animation, it will return the current location of the camera in flight.
+ * Animate the camera to a new location defined within {@link CameraUpdate} using a transition
+ * animation that evokes powered flight. The animation will last a specified amount of time
+ * given in milliseconds. A callback can be used to be notified when animating the camera stops.
+ * During the animation, a call to {@link #getCameraPosition()} returns an intermediate location
+ * of the camera in flight.
*
* @param update The change that should be applied to the camera.
- * @param durationMs The duration of the animation in milliseconds. This must be strictly positive, otherwise an IllegalArgumentException will be thrown.
- * @param callback An optional callback to be notified from the main thread when the animation stops. If the animation stops due to its natural completion, the callback will be notified with onFinish(). If the animation stops due to interruption by a later camera movement or a user gesture, onCancel() will be called. The callback should not attempt to move or animate the camera in its cancellation method. If a callback isn't required, leave it as null.
+ * @param durationMs The duration of the animation in milliseconds. This must be strictly
+ * positive, otherwise an IllegalArgumentException will be thrown.
+ * @param callback An optional callback to be notified from the main thread when the animation
+ * stops. If the animation stops due to its natural completion, the callback
+ * will be notified with onFinish(). If the animation stops due to interruption
+ * by a later camera movement or a user gesture, onCancel() will be called.
+ * Do not update or animate the camera from within onCancel(). If a callback
+ * isn't required, leave it as null.
+ * @see {@link CameraUpdateFactory} for a set of updates.
*/
@UiThread
public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) {
@@ -476,7 +550,7 @@ public class MapboxMap {
* <li>{@code asset://...}:
* reads the style from the APK {@code assets/} directory.
* This is used to load a style bundled with your app.</li>
- * <li>{@code null}: loads the default {@link Style#MAPBOX_STREETS} style.</li>
+ * <li>{@code null}: loads the default {@link Style#getMapboxStreetsUrl(int)} style.</li>
* </ul>
* <p>
* This method is asynchronous and will return immediately before the style finishes loading.
@@ -506,8 +580,10 @@ public class MapboxMap {
*
* @param style The bundled style. Accepts one of the values from {@link Style}.
* @see Style
+ * @deprecated use {@link #setStyleUrl(String)} instead with versioned url methods from {@link Style}
*/
@UiThread
+ @Deprecated
public void setStyle(@Style.StyleUrl String style) {
setStyleUrl(style);
}
@@ -532,22 +608,34 @@ public class MapboxMap {
/**
* <p>
+ * DEPRECATED @see MapboxAccountManager#start(String)
+ * </p>
+ * <p>
* Sets the current Mapbox access token used to load map styles and tiles.
* </p>
*
* @param accessToken Your public Mapbox access token.
* @see MapView#setAccessToken(String)
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
*/
+ @Deprecated
@UiThread
public void setAccessToken(@NonNull String accessToken) {
mMapView.setAccessToken(accessToken);
}
/**
+ * <p>
+ * DEPRECATED @see MapboxAccountManager#getAccessToken()
+ * </p>
+ * <p>
* Returns the current Mapbox access token used to load map styles and tiles.
+ * </p>
*
* @return The current Mapbox access token.
+ * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
*/
+ @Deprecated
@UiThread
@Nullable
public String getAccessToken() {
@@ -558,6 +646,12 @@ public class MapboxMap {
// Annotations
//
+ void setTilt(double tilt) {
+ mMarkerViewManager.setTilt((float) tilt);
+ mMapView.setTilt(tilt);
+ }
+
+
/**
* <p>
* Adds a marker to this map.
@@ -597,6 +691,27 @@ public class MapboxMap {
/**
* <p>
+ * Adds a marker to this map.
+ * </p>
+ * The marker's icon is rendered on the map at the location {@code Marker.position}.
+ * If {@code Marker.title} is defined, the map shows an info box with the marker's title and snippet.
+ *
+ * @param markerOptions A marker options object that defines how to render the marker.
+ * @return The {@code Marker} that was added to the map.
+ */
+ @UiThread
+ @NonNull
+ public MarkerView addMarker(@NonNull BaseMarkerViewOptions markerOptions) {
+ MarkerView marker = prepareViewMarker(markerOptions);
+ long id = mMapView.addMarker(marker);
+ marker.setMapboxMap(this);
+ marker.setId(id);
+ mAnnotations.put(id, marker);
+ return marker;
+ }
+
+ /**
+ * <p>
* Adds multiple markers to this map.
* </p>
* The marker's icon is rendered on the map at the location {@code Marker.position}.
@@ -607,11 +722,11 @@ public class MapboxMap {
*/
@UiThread
@NonNull
- public List<Marker> addMarkers(@NonNull List<MarkerOptions> markerOptionsList) {
+ public List<Marker> addMarkers(@NonNull List<? extends BaseMarkerOptions> markerOptionsList) {
int count = markerOptionsList.size();
List<Marker> markers = new ArrayList<>(count);
if (count > 0) {
- MarkerOptions markerOptions;
+ BaseMarkerOptions markerOptions;
Marker marker;
for (int i = 0; i < count; i++) {
markerOptions = markerOptionsList.get(i);
@@ -693,7 +808,7 @@ public class MapboxMap {
Polyline polyline;
List<Polyline> polylines = new ArrayList<>(count);
- if(count>0) {
+ if (count > 0) {
for (PolylineOptions options : polylineOptionsList) {
polyline = options.getPolyline();
if (!polyline.getPoints().isEmpty()) {
@@ -757,7 +872,7 @@ public class MapboxMap {
Polygon polygon;
List<Polygon> polygons = new ArrayList<>(count);
- if(count>0) {
+ if (count > 0) {
for (PolygonOptions polygonOptions : polygonOptionsList) {
polygon = polygonOptions.getPolygon();
if (!polygon.getPoints().isEmpty()) {
@@ -767,8 +882,8 @@ public class MapboxMap {
long[] ids = mMapView.addPolygons(polygons);
- // if unit tests or polygons correcly added to map
- if(ids==null || ids.length==polygons.size()) {
+ // if unit tests or polygons correctly added to map
+ if (ids == null || ids.length == polygons.size()) {
long id = 0;
for (int i = 0; i < polygons.size(); i++) {
polygon = polygons.get(i);
@@ -834,7 +949,11 @@ public class MapboxMap {
@UiThread
public void removeAnnotation(@NonNull Annotation annotation) {
if (annotation instanceof Marker) {
- ((Marker) annotation).hideInfoWindow();
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ }
}
long id = annotation.getId();
mMapView.removeAnnotation(id);
@@ -864,7 +983,11 @@ public class MapboxMap {
for (int i = 0; i < count; i++) {
Annotation annotation = annotationList.get(i);
if (annotation instanceof Marker) {
- ((Marker) annotation).hideInfoWindow();
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ }
}
ids[i] = annotationList.get(i).getId();
}
@@ -886,7 +1009,11 @@ public class MapboxMap {
ids[i] = mAnnotations.keyAt(i);
annotation = mAnnotations.get(ids[i]);
if (annotation instanceof Marker) {
- ((Marker) annotation).hideInfoWindow();
+ Marker marker = (Marker) annotation;
+ marker.hideInfoWindow();
+ if (marker instanceof MarkerView) {
+ mMarkerViewManager.removeMarkerView((MarkerView) marker, true);
+ }
}
}
mMapView.removeAnnotations(ids);
@@ -894,11 +1021,18 @@ public class MapboxMap {
}
/**
+ * Removes all markers, polylines, polygons, overlays, etc from the map.
+ */
+ @UiThread
+ public void clear() {
+ removeAnnotations();
+ }
+
+ /**
* Return a annotation based on its id.
*
* @return An annotation with a matched id, null is returned if no match was found.
*/
- @UiThread
@Nullable
public Annotation getAnnotation(long id) {
return mAnnotations.get(id);
@@ -989,8 +1123,7 @@ public class MapboxMap {
@UiThread
public void selectMarker(@NonNull Marker marker) {
if (marker == null) {
- Log.w(MapboxConstants.TAG, "marker was null, so just" +
- " returning");
+ Log.w(MapboxConstants.TAG, "marker was null, so just returning");
return;
}
@@ -1031,6 +1164,10 @@ public class MapboxMap {
if (marker.isInfoWindowShown()) {
marker.hideInfoWindow();
}
+
+ if (marker instanceof MarkerView) {
+ mMarkerViewManager.deselect((MarkerView) marker);
+ }
}
// Removes all selected markers from the list
@@ -1070,6 +1207,22 @@ public class MapboxMap {
return marker;
}
+ private MarkerView prepareViewMarker(BaseMarkerViewOptions markerViewOptions) {
+ MarkerView marker = markerViewOptions.getMarker();
+ Icon icon = IconFactory.recreate("markerViewSettings", mViewMarkerBitmap);
+ marker.setIcon(icon);
+ return marker;
+ }
+
+ /**
+ * Get the MarkerViewManager associated to the MapView.
+ *
+ * @return the associated MarkerViewManager
+ */
+ public MarkerViewManager getMarkerViewManager() {
+ return mMarkerViewManager;
+ }
+
//
// InfoWindow
//
@@ -1142,6 +1295,7 @@ public class MapboxMap {
* view’s frame. Otherwise, those properties are inset, excluding part of the
* frame from the viewport. For instance, if the only the top edge is inset, the
* map center is effectively shifted downward.
+ * </p>
*
* @param left The left margin in pixels.
* @param top The top margin in pixels.
@@ -1151,8 +1305,6 @@ public class MapboxMap {
public void setPadding(int left, int top, int right, int bottom) {
mMapView.setContentPadding(left, top, right, bottom);
mUiSettings.invalidate();
-
- moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder(mCameraPosition).build()));
}
/**
@@ -1381,8 +1533,10 @@ public class MapboxMap {
*
* @param listener The callback that's invoked when the user clicks on a marker.
* To unset the callback, use null.
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.location.LocationServices#addLocationListener(LocationListener)})}
*/
@UiThread
+ @Deprecated
public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) {
mMapView.setOnMyLocationChangeListener(listener);
}
@@ -1451,6 +1605,14 @@ public class MapboxMap {
return mMapView;
}
+ void setUiSettings(UiSettings uiSettings) {
+ mUiSettings = uiSettings;
+ }
+
+ void setProjection(Projection projection) {
+ mProjection = projection;
+ }
+
//
// Invalidate
//
@@ -1462,6 +1624,27 @@ public class MapboxMap {
mMapView.update();
}
+ /**
+ * Takes a snapshot of the map.
+ *
+ * @param callback Callback method invoked when the snapshot is taken.
+ * @param bitmap A pre-allocated bitmap.
+ */
+ @UiThread
+ public void snapshot(@NonNull SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
+ mMapView.snapshot(callback, bitmap);
+ }
+
+ /**
+ * Takes a snapshot of the map.
+ *
+ * @param callback Callback method invoked when the snapshot is taken.
+ */
+ @UiThread
+ public void snapshot(@NonNull SnapshotReadyCallback callback) {
+ mMapView.snapshot(callback, null);
+ }
+
//
// Interfaces
//
@@ -1624,10 +1807,92 @@ public class MapboxMap {
}
/**
+ * Interface definition for a callback to be invoked when an MarkerView will be shown.
+ *
+ * @param <U> the instance type of MarkerView
+ */
+ public static abstract class MarkerViewAdapter<U extends MarkerView> {
+
+ private Context context;
+ private final Class<U> persistentClass;
+ private final Pools.SimplePool<View> mViewReusePool;
+
+ /**
+ * Create an instance of MarkerViewAdapter.
+ *
+ * @param context the context associated to a MapView
+ */
+ @SuppressWarnings("unchecked")
+ public MarkerViewAdapter(Context context) {
+ this.context = context;
+ persistentClass = (Class<U>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+ mViewReusePool = new Pools.SimplePool<>(20);
+ }
+
+ /**
+ * Called when an MarkerView will be added to the MapView.
+ *
+ * @param marker the model representing the MarkerView
+ * @param convertView the reusable view
+ * @param parent the parent ViewGroup of the convertview
+ * @return the View that is adapted to the contents of MarkerView
+ */
+ @Nullable
+ public abstract View getView(@NonNull U marker, @NonNull View convertView, @NonNull ViewGroup parent);
+
+ /**
+ * Returns the generic type of the used MarkerView.
+ *
+ * @return the generic type
+ */
+ public Class<U> getMarkerClass() {
+ return persistentClass;
+ }
+
+ /**
+ * Returns the pool used to store reusable Views.
+ *
+ * @return the pool associated to this adapter
+ */
+ public Pools.SimplePool<View> getViewReusePool() {
+ return mViewReusePool;
+ }
+
+ /**
+ * Returns the context associated to the hosting MapView.
+ *
+ * @return the context used
+ */
+ public Context getContext() {
+ return context;
+ }
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the user clicks on a MarkerView.
+ *
+ * @see MarkerViewManager#setOnMarkerViewClickListener(OnMarkerViewClickListener)
+ */
+ public interface OnMarkerViewClickListener {
+
+ /**
+ * Called when the user clicks on a MarkerView.
+ *
+ * @param marker the MarkerView associated to the clicked View
+ * @param view the clicked View
+ * @param adapter the adapter used to adapt the MarkerView to the View
+ * @return If true the listener has consumed the event and the info window will not be shown
+ */
+ boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MarkerViewAdapter adapter);
+ }
+
+ /**
* Interface definition for a callback to be invoked when the the My Location view changes location.
*
* @see MapboxMap#setOnMyLocationChangeListener(OnMyLocationChangeListener)
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.location.LocationListener}
*/
+ @Deprecated
public interface OnMyLocationChangeListener {
/**
* Called when the location of the My Location view has changed
@@ -1683,6 +1948,16 @@ public class MapboxMap {
void onFinish();
}
+ /**
+ * Interface definition for a callback to be invoked when the snapshot has been taken.
+ */
+ public interface SnapshotReadyCallback {
+ /**
+ * Invoked when the snapshot has been taken.
+ */
+ void onSnapshotReady(Bitmap snapshot);
+ }
+
private class MapChangeCameraPositionListener implements MapView.OnMapChangedListener {
private static final long UPDATE_RATE_MS = 400;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
index 6b7a0db8bd..17593129e7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java
@@ -2,16 +2,22 @@ package com.mapbox.mapboxsdk.maps;
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.Gravity;
-
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.utils.ColorUtils;
+import java.util.Arrays;
/**
* Defines configuration MapboxMapMapOptions for a MapboxMap. These options can be used when adding a
@@ -40,6 +46,8 @@ public class MapboxMapOptions implements Parcelable {
private int logoGravity = Gravity.BOTTOM | Gravity.START;
private int logoMargins[];
+ @ColorInt
+ private int attributionTintColor = -1;
private boolean attributionEnabled = true;
private int attributionGravity = Gravity.BOTTOM;
private int attributionMargins[];
@@ -53,9 +61,18 @@ public class MapboxMapOptions implements Parcelable {
private boolean zoomGesturesEnabled = true;
private boolean zoomControlsEnabled = false;
- private boolean locationEnabled;
+ private boolean myLocationEnabled;
+ private Drawable myLocationForegroundDrawable;
+ private Drawable myLocationForegroundBearingDrawable;
+ private Drawable myLocationBackgroundDrawable;
+ private int myLocationForegroundTintColor;
+ private int myLocationBackgroundTintColor;
+ private int[] myLocationBackgroundPadding;
+ private int myLocationAccuracyTintColor;
+ private int myLocationAccuracyAlpha;
private String style;
+ @Deprecated
private String accessToken;
/**
@@ -79,6 +96,7 @@ public class MapboxMapOptions implements Parcelable {
attributionEnabled = in.readByte() != 0;
attributionGravity = in.readInt();
attributionMargins = in.createIntArray();
+ attributionTintColor = in.readInt();
minZoom = in.readFloat();
maxZoom = in.readFloat();
@@ -89,7 +107,15 @@ public class MapboxMapOptions implements Parcelable {
zoomControlsEnabled = in.readByte() != 0;
zoomGesturesEnabled = in.readByte() != 0;
- locationEnabled = in.readByte() != 0;
+ myLocationEnabled = in.readByte() != 0;
+ //myLocationForegroundDrawable;
+ //myLocationForegroundBearingDrawable;
+ //myLocationBackgroundDrawable;
+ myLocationForegroundTintColor = in.readInt();
+ myLocationBackgroundTintColor = in.readInt();
+ myLocationBackgroundPadding = in.createIntArray();
+ myLocationAccuracyAlpha = in.readInt();
+ myLocationAccuracyTintColor = in.readInt();
style = in.readString();
accessToken = in.readString();
@@ -137,6 +163,7 @@ public class MapboxMapOptions implements Parcelable {
, (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_right, DIMENSION_SIXTEEN_DP) * screenDensity)
, (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_bottom, DIMENSION_SIXTEEN_DP) * screenDensity)});
+ mapboxMapOptions.attributionTintColor(typedArray.getColor(R.styleable.MapView_attribution_tint, -1));
mapboxMapOptions.attributionEnabled(typedArray.getBoolean(R.styleable.MapView_attribution_enabled, true));
mapboxMapOptions.attributionGravity(typedArray.getInt(R.styleable.MapView_attribution_gravity, Gravity.BOTTOM));
mapboxMapOptions.attributionMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_left, DIMENSION_SEVENTY_SIX_DP) * screenDensity)
@@ -145,6 +172,32 @@ public class MapboxMapOptions implements Parcelable {
, (int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_bottom, DIMENSION_SEVEN_DP) * screenDensity)});
mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.MapView_my_location_enabled, false));
+ mapboxMapOptions.myLocationForegroundTintColor(typedArray.getColor(R.styleable.MapView_my_location_foreground_tint, Color.TRANSPARENT));
+ mapboxMapOptions.myLocationBackgroundTintColor(typedArray.getColor(R.styleable.MapView_my_location_background_tint, Color.TRANSPARENT));
+
+ Drawable foregroundDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_foreground);
+ if(foregroundDrawable==null){
+ foregroundDrawable = ContextCompat.getDrawable(context,R.drawable.ic_mylocationview_normal);
+ }
+
+ Drawable foregroundBearingDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_foreground_bearing);
+ if(foregroundBearingDrawable==null){
+ foregroundBearingDrawable = ContextCompat.getDrawable(context,R.drawable.ic_mylocationview_bearing);
+ }
+
+ Drawable backgroundDrawable = typedArray.getDrawable(R.styleable.MapView_my_location_background);
+ if(backgroundDrawable==null){
+ backgroundDrawable = ContextCompat.getDrawable(context, R.drawable.ic_mylocationview_background);
+ }
+
+ mapboxMapOptions.myLocationForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
+ mapboxMapOptions.myLocationBackgroundDrawable(backgroundDrawable);
+ mapboxMapOptions.myLocationBackgroundPadding(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_my_location_background_left, 0) * screenDensity)
+ , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_top, 0) * screenDensity)
+ , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_right, 0) * screenDensity)
+ , (int) (typedArray.getDimension(R.styleable.MapView_my_location_background_bottom, 0) * screenDensity)});
+ mapboxMapOptions.myLocationAccuracyAlpha(typedArray.getInt(R.styleable.MapView_my_location_accuracy_alpha, 100));
+ mapboxMapOptions.myLocationAccuracyTint(typedArray.getColor(R.styleable.MapView_my_location_accuracy_tint, ColorUtils.getPrimaryColor(context)));
} finally {
typedArray.recycle();
}
@@ -163,11 +216,15 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * <p>
+ * DEPRECATED @see MapboxAccountManager#start(String)
+ * </p>
* Specifies the accesstoken associated with a map view.
*
* @param accessToken Token to be used to access the service
* @return This
*/
+ @Deprecated
public MapboxMapOptions accessToken(String accessToken) {
this.accessToken = accessToken;
return this;
@@ -317,6 +374,17 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * Specifies the tint color of the attribution for a map view
+ *
+ * @param color integer resembling a color
+ * @return This
+ */
+ public MapboxMapOptions attributionTintColor(@ColorInt int color) {
+ attributionTintColor = color;
+ return this;
+ }
+
+ /**
* Specifies if the rotate gesture is enabled for a map view.
*
* @param enabled True and gesture will be enabled
@@ -378,7 +446,73 @@ public class MapboxMapOptions implements Parcelable {
* @return This
*/
public MapboxMapOptions locationEnabled(boolean locationEnabled) {
- this.locationEnabled = locationEnabled;
+ this.myLocationEnabled = locationEnabled;
+ return this;
+ }
+
+ /**
+ *
+ * @param myLocationForegroundDrawable
+ * @param myLocationBearingDrawable
+ * @return This
+ */
+ public MapboxMapOptions myLocationForegroundDrawables(Drawable myLocationForegroundDrawable, Drawable myLocationBearingDrawable ) {
+ this.myLocationForegroundDrawable = myLocationForegroundDrawable;
+ this.myLocationForegroundBearingDrawable = myLocationBearingDrawable;
+ return this;
+ }
+
+ /**
+ * @param myLocationBackgroundDrawable
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundDrawable(Drawable myLocationBackgroundDrawable) {
+ this.myLocationBackgroundDrawable = myLocationBackgroundDrawable;
+ return this;
+ }
+
+ /**
+ * @param myLocationForegroundTintColor
+ * @return This
+ */
+ public MapboxMapOptions myLocationForegroundTintColor(@ColorInt int myLocationForegroundTintColor) {
+ this.myLocationForegroundTintColor = myLocationForegroundTintColor;
+ return this;
+ }
+
+ /**
+ * @param myLocationBackgroundTintColor
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundTintColor(@ColorInt int myLocationBackgroundTintColor) {
+ this.myLocationBackgroundTintColor = myLocationBackgroundTintColor;
+ return this;
+ }
+
+ /**
+ * @param myLocationBackgroundPadding
+ * @return This
+ */
+ public MapboxMapOptions myLocationBackgroundPadding(int[] myLocationBackgroundPadding) {
+ this.myLocationBackgroundPadding = myLocationBackgroundPadding;
+ return this;
+ }
+
+ /**
+ * @param myLocationAccuracyTintColor
+ * @return This
+ */
+ public MapboxMapOptions myLocationAccuracyTint(@ColorInt int myLocationAccuracyTintColor) {
+ this.myLocationAccuracyTintColor = myLocationAccuracyTintColor;
+ return this;
+ }
+
+ /**
+ * @param alpha
+ * @return This
+ */
+ public MapboxMapOptions myLocationAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
+ this.myLocationAccuracyAlpha = alpha;
return this;
}
@@ -464,10 +598,14 @@ public class MapboxMapOptions implements Parcelable {
}
/**
+ * <p>
+ * DEPRECATED @see MapboxAccountManager#start(String)
+ * </p>
* Get the current configured access token for a map view.
*
* @return Access token to be used.
*/
+ @Deprecated
public String getAccessToken() {
return accessToken;
}
@@ -553,13 +691,74 @@ public class MapboxMapOptions implements Parcelable {
return attributionMargins;
}
+ @ColorInt
+ public int getAttributionTintColor() {
+ return attributionTintColor;
+ }
+
/**
* Get the current configured user location view state for a map view.
*
* @return True and user location will be shown
*/
public boolean getLocationEnabled() {
- return locationEnabled;
+ return myLocationEnabled;
+ }
+
+ /**
+ * @return
+ */
+ public Drawable getMyLocationForegroundDrawable() {
+ return myLocationForegroundDrawable;
+ }
+
+ /**
+ * @return
+ */
+ public Drawable getMyLocationForegroundBearingDrawable() {
+ return myLocationForegroundBearingDrawable;
+ }
+
+ /**
+ * @return
+ */
+ public Drawable getMyLocationBackgroundDrawable() {
+ return myLocationBackgroundDrawable;
+ }
+
+ /**
+ * @return
+ */
+ public int getMyLocationForegroundTintColor() {
+ return myLocationForegroundTintColor;
+ }
+
+ /**
+ * @return
+ */
+ public int getMyLocationBackgroundTintColor() {
+ return myLocationBackgroundTintColor;
+ }
+
+ /**
+ * @return
+ */
+ public int[] getMyLocationBackgroundPadding() {
+ return myLocationBackgroundPadding;
+ }
+
+ /**
+ * @return
+ */
+ public int getMyLocationAccuracyTintColor() {
+ return myLocationAccuracyTintColor;
+ }
+
+ /**
+ * @return
+ */
+ public int getMyLocationAccuracyAlpha() {
+ return myLocationAccuracyAlpha;
}
/**
@@ -603,6 +802,7 @@ public class MapboxMapOptions implements Parcelable {
dest.writeByte((byte) (attributionEnabled ? 1 : 0));
dest.writeInt(attributionGravity);
dest.writeIntArray(attributionMargins);
+ dest.writeInt(attributionTintColor);
dest.writeFloat(minZoom);
dest.writeFloat(maxZoom);
@@ -613,9 +813,94 @@ public class MapboxMapOptions implements Parcelable {
dest.writeByte((byte) (zoomControlsEnabled ? 1 : 0));
dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0));
- dest.writeByte((byte) (locationEnabled ? 1 : 0));
+ dest.writeByte((byte) (myLocationEnabled ? 1 : 0));
+ //myLocationForegroundDrawable;
+ //myLocationForegroundBearingDrawable;
+ //myLocationBackgroundDrawable;
+ dest.writeInt(myLocationForegroundTintColor);
+ dest.writeInt(myLocationBackgroundTintColor);
+ dest.writeIntArray(myLocationBackgroundPadding);
+ dest.writeInt(myLocationAccuracyAlpha);
+ dest.writeInt(myLocationAccuracyTintColor);
dest.writeString(style);
dest.writeString(accessToken);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MapboxMapOptions options = (MapboxMapOptions) o;
+
+ if (debugActive != options.debugActive) return false;
+ if (compassEnabled != options.compassEnabled) return false;
+ if (compassGravity != options.compassGravity) return false;
+ if (logoEnabled != options.logoEnabled) return false;
+ if (logoGravity != options.logoGravity) return false;
+ if (attributionEnabled != options.attributionEnabled) return false;
+ if (attributionGravity != options.attributionGravity) return false;
+ if (Float.compare(options.minZoom, minZoom) != 0) return false;
+ if (Float.compare(options.maxZoom, maxZoom) != 0) return false;
+ if (rotateGesturesEnabled != options.rotateGesturesEnabled) return false;
+ if (scrollGesturesEnabled != options.scrollGesturesEnabled) return false;
+ if (tiltGesturesEnabled != options.tiltGesturesEnabled) return false;
+ if (zoomGesturesEnabled != options.zoomGesturesEnabled) return false;
+ if (zoomControlsEnabled != options.zoomControlsEnabled) return false;
+ if (myLocationEnabled != options.myLocationEnabled) return false;
+ if (myLocationForegroundTintColor != options.myLocationForegroundTintColor) return false;
+ if (myLocationBackgroundTintColor != options.myLocationBackgroundTintColor) return false;
+ if (myLocationAccuracyTintColor != options.myLocationAccuracyTintColor) return false;
+ if (myLocationAccuracyAlpha != options.myLocationAccuracyAlpha) return false;
+ if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null)
+ return false;
+ if (!Arrays.equals(compassMargins, options.compassMargins)) return false;
+ if (!Arrays.equals(logoMargins, options.logoMargins)) return false;
+ if (!Arrays.equals(attributionMargins, options.attributionMargins)) return false;
+ if (myLocationForegroundDrawable != null ? !myLocationForegroundDrawable.equals(options.myLocationForegroundDrawable) : options.myLocationForegroundDrawable != null)
+ return false;
+ if (myLocationForegroundBearingDrawable != null ? !myLocationForegroundBearingDrawable.equals(options.myLocationForegroundBearingDrawable) : options.myLocationForegroundBearingDrawable != null)
+ return false;
+ if (myLocationBackgroundDrawable != null ? !myLocationBackgroundDrawable.equals(options.myLocationBackgroundDrawable) : options.myLocationBackgroundDrawable != null)
+ return false;
+ if (!Arrays.equals(myLocationBackgroundPadding, options.myLocationBackgroundPadding))
+ return false;
+ if (style != null ? !style.equals(options.style) : options.style != null) return false;
+ return accessToken != null ? accessToken.equals(options.accessToken) : options.accessToken == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = cameraPosition != null ? cameraPosition.hashCode() : 0;
+ result = 31 * result + (debugActive ? 1 : 0);
+ result = 31 * result + (compassEnabled ? 1 : 0);
+ result = 31 * result + compassGravity;
+ result = 31 * result + Arrays.hashCode(compassMargins);
+ result = 31 * result + (logoEnabled ? 1 : 0);
+ result = 31 * result + logoGravity;
+ result = 31 * result + Arrays.hashCode(logoMargins);
+ result = 31 * result + (attributionEnabled ? 1 : 0);
+ result = 31 * result + attributionGravity;
+ result = 31 * result + Arrays.hashCode(attributionMargins);
+ result = 31 * result + (minZoom != +0.0f ? Float.floatToIntBits(minZoom) : 0);
+ result = 31 * result + (maxZoom != +0.0f ? Float.floatToIntBits(maxZoom) : 0);
+ result = 31 * result + (rotateGesturesEnabled ? 1 : 0);
+ result = 31 * result + (scrollGesturesEnabled ? 1 : 0);
+ result = 31 * result + (tiltGesturesEnabled ? 1 : 0);
+ result = 31 * result + (zoomGesturesEnabled ? 1 : 0);
+ result = 31 * result + (zoomControlsEnabled ? 1 : 0);
+ result = 31 * result + (myLocationEnabled ? 1 : 0);
+ result = 31 * result + (myLocationForegroundDrawable != null ? myLocationForegroundDrawable.hashCode() : 0);
+ result = 31 * result + (myLocationForegroundBearingDrawable != null ? myLocationForegroundBearingDrawable.hashCode() : 0);
+ result = 31 * result + (myLocationBackgroundDrawable != null ? myLocationBackgroundDrawable.hashCode() : 0);
+ result = 31 * result + myLocationForegroundTintColor;
+ result = 31 * result + myLocationBackgroundTintColor;
+ result = 31 * result + Arrays.hashCode(myLocationBackgroundPadding);
+ result = 31 * result + myLocationAccuracyTintColor;
+ result = 31 * result + myLocationAccuracyAlpha;
+ result = 31 * result + (style != null ? style.hashCode() : 0);
+ result = 31 * result + (accessToken != null ? accessToken.hashCode() : 0);
+ return result;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index c6ac6dc6e2..6c092ee0c8 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -119,24 +119,12 @@ final class NativeMapView {
nativeDestroySurface(mNativeMapViewPtr);
}
- public void pause() {
- nativePause(mNativeMapViewPtr);
- }
-
- public boolean isPaused() {
- return nativeIsPaused(mNativeMapViewPtr);
- }
-
- public void resume() {
- nativeResume(mNativeMapViewPtr);
- }
-
public void update() {
nativeUpdate(mNativeMapViewPtr);
}
- public void renderSync() {
- nativeRenderSync(mNativeMapViewPtr);
+ public void render() {
+ nativeRender(mNativeMapViewPtr);
}
public void resizeView(int width, int height) {
@@ -201,34 +189,12 @@ final class NativeMapView {
return nativeGetClasses(mNativeMapViewPtr);
}
- public void setDefaultTransitionDuration() {
- setDefaultTransitionDuration(0);
- }
-
- public long getDefaultTransitionDuration() {
- return nativeGetDefaultTransitionDuration(mNativeMapViewPtr);
- }
-
- public void setDefaultTransitionDuration(long milliseconds) {
- if (milliseconds < 0) {
- throw new IllegalArgumentException(
- "milliseconds cannot be negative.");
- }
-
- nativeSetDefaultTransitionDuration(mNativeMapViewPtr,
- milliseconds);
- }
-
public void setStyleUrl(String url) {
nativeSetStyleUrl(mNativeMapViewPtr, url);
}
public void setStyleJson(String newStyleJson) {
- setStyleJson(newStyleJson, "");
- }
-
- public void setStyleJson(String newStyleJson, String base) {
- nativeSetStyleJson(mNativeMapViewPtr, newStyleJson, base);
+ nativeSetStyleJson(mNativeMapViewPtr, newStyleJson);
}
public String getStyleJson() {
@@ -377,27 +343,30 @@ final class NativeMapView {
}
public long addMarker(Marker marker) {
- return nativeAddMarker(mNativeMapViewPtr, marker);
+ Marker[] markers = { marker };
+ return nativeAddMarkers(mNativeMapViewPtr, markers)[0];
}
public long[] addMarkers(List<Marker> markers) {
- return nativeAddMarkers(mNativeMapViewPtr, markers);
+ return nativeAddMarkers(mNativeMapViewPtr, markers.toArray(new Marker[markers.size()]));
}
public long addPolyline(Polyline polyline) {
- return nativeAddPolyline(mNativeMapViewPtr, polyline);
+ Polyline[] polylines = { polyline };
+ return nativeAddPolylines(mNativeMapViewPtr, polylines)[0];
}
public long[] addPolylines(List<Polyline> polylines) {
- return nativeAddPolylines(mNativeMapViewPtr, polylines);
+ return nativeAddPolylines(mNativeMapViewPtr, polylines.toArray(new Polyline[polylines.size()]));
}
public long addPolygon(Polygon polygon) {
- return nativeAddPolygon(mNativeMapViewPtr, polygon);
+ Polygon[] polygons = { polygon };
+ return nativeAddPolygons(mNativeMapViewPtr, polygons)[0];
}
- public long[] addPolygons(List<Polygon> polygon) {
- return nativeAddPolygons(mNativeMapViewPtr, polygon);
+ public long[] addPolygons(List<Polygon> polygons) {
+ return nativeAddPolygons(mNativeMapViewPtr, polygons.toArray(new Polygon[polygons.size()]));
}
public void updateMarker(Marker marker) {
@@ -405,7 +374,8 @@ final class NativeMapView {
}
public void removeAnnotation(long id) {
- nativeRemoveAnnotation(mNativeMapViewPtr, id);
+ long[] ids = { id };
+ removeAnnotations(ids);
}
public void removeAnnotations(long[] ids) {
@@ -476,8 +446,8 @@ final class NativeMapView {
nativeJumpTo(mNativeMapViewPtr, angle, center, pitch, zoom);
}
- public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom) {
- nativeEaseTo(mNativeMapViewPtr, angle, center, duration, pitch, zoom);
+ public void easeTo(double angle, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator) {
+ nativeEaseTo(mNativeMapViewPtr, angle, center, duration, pitch, zoom, easingInterpolator);
}
public void flyTo(double angle, LatLng center, long duration, double pitch, double zoom) {
@@ -533,15 +503,9 @@ final class NativeMapView {
private native void nativeDestroySurface(long nativeMapViewPtr);
- private native void nativePause(long nativeMapViewPtr);
-
- private native boolean nativeIsPaused(long nativeMapViewPtr);
-
- private native void nativeResume(long nativeMapViewPtr);
-
private native void nativeUpdate(long nativeMapViewPtr);
- private native void nativeRenderSync(long nativeMapViewPtr);
+ private native void nativeRender(long nativeMapViewPtr);
private native void nativeViewResize(long nativeMapViewPtr, int width, int height);
@@ -558,15 +522,9 @@ final class NativeMapView {
private native List<String> nativeGetClasses(long nativeMapViewPtr);
- private native void nativeSetDefaultTransitionDuration(
- long nativeMapViewPtr, long duration);
-
- private native long nativeGetDefaultTransitionDuration(long nativeMapViewPtr);
-
private native void nativeSetStyleUrl(long nativeMapViewPtr, String url);
- private native void nativeSetStyleJson(long nativeMapViewPtr,
- String newStyleJson, String base);
+ private native void nativeSetStyleJson(long nativeMapViewPtr, String newStyleJson);
private native String nativeGetStyleJson(long nativeMapViewPtr);
@@ -630,21 +588,13 @@ final class NativeMapView {
private native void nativeResetNorth(long nativeMapViewPtr);
- private native long nativeAddMarker(long nativeMapViewPtr, Marker marker);
-
private native void nativeUpdateMarker(long nativeMapViewPtr, Marker marker);
- private native long[] nativeAddMarkers(long nativeMapViewPtr, List<Marker> markers);
-
- private native long nativeAddPolyline(long nativeMapViewPtr, Polyline polyline);
-
- private native long[] nativeAddPolylines(long mNativeMapViewPtr, List<Polyline> polygon);
-
- private native long nativeAddPolygon(long mNativeMapViewPtr, Polygon polygon);
+ private native long[] nativeAddMarkers(long nativeMapViewPtr, Marker[] markers);
- private native long[] nativeAddPolygons(long mNativeMapViewPtr, List<Polygon> polygon);
+ private native long[] nativeAddPolylines(long mNativeMapViewPtr, Polyline[] polylines);
- private native void nativeRemoveAnnotation(long nativeMapViewPtr, long id);
+ private native long[] nativeAddPolygons(long mNativeMapViewPtr, Polygon[] polygons);
private native void nativeRemoveAnnotations(long nativeMapViewPtr, long[] id);
@@ -682,7 +632,7 @@ final class NativeMapView {
private native void nativeJumpTo(long nativeMapViewPtr, double angle, LatLng center, double pitch, double zoom);
- private native void nativeEaseTo(long nativeMapViewPtr, double angle, LatLng center, long duration, double pitch, double zoom);
+ private native void nativeEaseTo(long nativeMapViewPtr, double angle, LatLng center, long duration, double pitch, double zoom, boolean easingInterpolator);
private native void nativeFlyTo(long nativeMapViewPtr, double angle, LatLng center, long duration, double pitch, double zoom);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
index 9482b1a2f7..d37c3a02ea 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java
@@ -57,13 +57,15 @@ public class Projection {
public VisibleRegion getVisibleRegion() {
LatLngBounds.Builder builder = new LatLngBounds.Builder();
- int viewportWidth = mMapView.getWidth();
- int viewportHeight = mMapView.getHeight();
+ float left = mMapView.getContentPaddingLeft();
+ float right = mMapView.getWidth() - mMapView.getContentPaddingRight();
+ float top = mMapView.getContentPaddingTop();
+ float bottom = mMapView.getHeight() - mMapView.getContentPaddingBottom();
- LatLng topLeft = fromScreenLocation(new PointF(0, 0));
- LatLng topRight = fromScreenLocation(new PointF(viewportWidth, 0));
- LatLng bottomRight = fromScreenLocation(new PointF(viewportWidth, viewportHeight));
- LatLng bottomLeft = fromScreenLocation(new PointF(0, viewportHeight));
+ LatLng topLeft = fromScreenLocation(new PointF(left, top));
+ LatLng topRight = fromScreenLocation(new PointF(right, top));
+ LatLng bottomRight = fromScreenLocation(new PointF(right, bottom));
+ LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom));
builder.include(topLeft)
.include(topRight)
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
index ffdb57de8c..3d96727758 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java
@@ -1,14 +1,19 @@
package com.mapbox.mapboxsdk.maps;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.InvalidAccessTokenException;
/**
* Support Fragment wrapper around a map view.
@@ -32,6 +37,15 @@ public class SupportMapFragment extends Fragment {
/**
* Creates a MapFragment instance
*
+ * @return MapFragment created
+ */
+ public static SupportMapFragment newInstance() {
+ return new SupportMapFragment();
+ }
+
+ /**
+ * Creates a MapFragment instance
+ *
* @param mapboxMapOptions The configuration options to be used.
* @return MapFragment created.
*/
@@ -44,7 +58,7 @@ public class SupportMapFragment extends Fragment {
}
/**
- * Creates the fragment view hierachy.
+ * Creates the fragment view hierarchy.
*
* @param inflater Inflater used to inflate content.
* @param container The parent layout for the map fragment.
@@ -54,11 +68,66 @@ public class SupportMapFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
- MapboxMapOptions options = getArguments().getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
+ MapboxMapOptions options = null;
+
+ // Get bundle
+ Bundle bundle = getArguments();
+ if (bundle != null && bundle.containsKey(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS)) {
+ options = bundle.getParcelable(MapboxConstants.FRAG_ARG_MAPBOXMAPOPTIONS);
+ }
+
+ // Assign an AccessToken if needed
+ if (options == null || options.getAccessToken() == null) {
+ String token = null;
+ if (MapboxAccountManager.getInstance() != null) {
+ token = MapboxAccountManager.getInstance().getAccessToken();
+ } else {
+ token = getToken(inflater.getContext());
+ }
+ if (TextUtils.isEmpty(token)) {
+ throw new InvalidAccessTokenException();
+ }
+ if (options == null) {
+ options = new MapboxMapOptions().accessToken(token);
+ } else {
+ options.accessToken(token);
+ }
+ }
return mMap = new MapView(inflater.getContext(), options);
}
/**
+ * <p>
+ * Returns the Mapbox access token set in the app resources.
+ * </p>
+ * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST}
+ * meta-data value. If not found it will then attempt to load the access token from the
+ * {@code res/raw/token.txt} 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.
+ * @see MapboxConstants#KEY_META_DATA_MANIFEST
+ * @deprecated As of release 4.1.0, replaced by {@link com.mapbox.mapboxsdk.MapboxAccountManager#start(Context, String)}
+ */
+ @Deprecated
+ private String getToken(@NonNull Context context) {
+ try {
+ // read out AndroidManifest
+ PackageManager packageManager = context.getPackageManager();
+ ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
+ String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST);
+ if (token == null || token.isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ return token;
+ } catch (Exception e) {
+ // 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;
+ }
+ }
+
+ /**
* Called when the fragment view hierarchy is created.
*
* @param view The content view of the fragment
@@ -142,4 +211,4 @@ public class SupportMapFragment extends Fragment {
public void getMapAsync(@NonNull final OnMapReadyCallback onMapReadyCallback) {
mOnMapReadyCallback = onMapReadyCallback;
}
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
index 90147929e9..30492bc421 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
@@ -5,7 +5,7 @@ import android.support.annotation.UiThread;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
-import com.mapbox.mapboxsdk.maps.widgets.UserLocationView;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
/**
* Settings for the user location and bearing tracking of a MapboxMap.
@@ -14,13 +14,14 @@ public class TrackingSettings {
private MapView mapView;
private UiSettings uiSettings;
- private boolean dismissTrackingOnGesture = true;
+ private boolean dismissLocationTrackingOnGesture = true;
+ private boolean dismissBearingTrackingOnGesture = true;
@MyLocationTracking.Mode
- private int mMyLocationTrackingMode;
+ private int myLocationTrackingMode;
@MyBearingTracking.Mode
- private int mMyBearingTrackingMode;
+ private int myBearingTrackingMode;
TrackingSettings(@NonNull MapView mapView, UiSettings uiSettings) {
this.mapView = mapView;
@@ -42,9 +43,9 @@ public class TrackingSettings {
*/
@UiThread
public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- mMyLocationTrackingMode = myLocationTrackingMode;
+ this.myLocationTrackingMode = myLocationTrackingMode;
mapView.setMyLocationTrackingMode(myLocationTrackingMode);
- validateGesturesForTrackingModes();
+ validateGesturesForLocationTrackingMode();
}
/**
@@ -57,7 +58,7 @@ public class TrackingSettings {
@UiThread
@MyLocationTracking.Mode
public int getMyLocationTrackingMode() {
- return mMyLocationTrackingMode;
+ return myLocationTrackingMode;
}
/**
@@ -66,7 +67,7 @@ public class TrackingSettings {
* </p>
* Shows the direction the user is heading.
* <p>
- * When location tracking is disabled the direction of {@link UserLocationView} is rotated
+ * When location tracking is disabled the direction of {@link MyLocationView} is rotated
* When location tracking is enabled the {@link MapView} is rotated based on bearing value.
* </p>
* See {@link MyBearingTracking} for different values.
@@ -77,8 +78,9 @@ public class TrackingSettings {
*/
@UiThread
public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- mMyBearingTrackingMode = myBearingTrackingMode;
+ this.myBearingTrackingMode = myBearingTrackingMode;
mapView.setMyBearingTrackingMode(myBearingTrackingMode);
+ validateGesturesForBearingTrackingMode();
}
/**
@@ -89,52 +91,137 @@ public class TrackingSettings {
* @see MyBearingTracking
*/
@UiThread
- @MyLocationTracking.Mode
+ @MyBearingTracking.Mode
public int getMyBearingTrackingMode() {
- return mMyBearingTrackingMode;
+ return myBearingTrackingMode;
}
/**
* Returns if the tracking modes will be dismissed when a gesture occurs.
*
* @return True to indicate the tracking modes will be dismissed.
- */
+ * @deprecated use @link #isAllDismissTrackingOnGestureinstead
+ */
+ @Deprecated
public boolean isDismissTrackingOnGesture() {
- return dismissTrackingOnGesture;
+ return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
+ }
+
+ /**
+ * Returns if all tracking modes will be dismissed when a gesture occurs.
+ *
+ * @return True to indicate that location and bearing tracking will be dismissed.
+ */
+ public boolean isAllDismissTrackingOnGesture() {
+ return dismissLocationTrackingOnGesture && dismissBearingTrackingOnGesture;
}
/**
* Set the dismissal of the tracking modes if a gesture occurs.
*
* @param dismissTrackingOnGesture True to dismiss the tracking modes.
+ * @deprecated use @link #setDismissAllTrackingOnGesture instead
*/
+ @Deprecated
public void setDismissTrackingOnGesture(boolean dismissTrackingOnGesture) {
- this.dismissTrackingOnGesture = dismissTrackingOnGesture;
- validateGesturesForTrackingModes();
+ setDismissAllTrackingOnGesture(dismissTrackingOnGesture);
+ }
+
+ /**
+ * Set the dismissal of the tracking modes if a gesture occurs.
+ *
+ * @param dismissTrackingOnGesture True to dismiss all the tracking modes.
+ */
+ public void setDismissAllTrackingOnGesture(boolean dismissTrackingOnGesture) {
+ dismissLocationTrackingOnGesture = dismissTrackingOnGesture;
+ dismissBearingTrackingOnGesture = dismissTrackingOnGesture;
+ validateAllGesturesForTrackingModes();
+ }
+
+ /**
+ * Set the dismissal of the tracking modes if a gesture occurs.
+ *
+ * @param dismissLocationTrackingOnGesture True to dismiss the location tracking mode.
+ */
+ public void setDismissLocationTrackingOnGesture(boolean dismissLocationTrackingOnGesture) {
+ this.dismissLocationTrackingOnGesture = dismissLocationTrackingOnGesture;
+ validateGesturesForLocationTrackingMode();
+ }
+
+ /**
+ * Returns if the location tracking will be disabled when a gesture occurs
+ *
+ * @return True if location tracking will be disabled.
+ */
+ public boolean isDismissLocationTrackingOnGesture() {
+ return dismissLocationTrackingOnGesture;
+ }
+
+ /**
+ * Set the dismissal of the bearing tracking modes if a gesture occurs.
+ *
+ * @param dismissBearingTrackingOnGesture True to dimsiss the bearinf tracking mode
+ */
+ public void setDismissBearingTrackingOnGesture(boolean dismissBearingTrackingOnGesture) {
+ this.dismissBearingTrackingOnGesture = dismissBearingTrackingOnGesture;
+ validateGesturesForBearingTrackingMode();
}
- private void validateGesturesForTrackingModes() {
- if (!dismissTrackingOnGesture) {
- int myLocationTrackingMode = getMyLocationTrackingMode();
- int myBearingTrackingMode = getMyBearingTrackingMode();
+ /**
+ * Returns if bearing will disabled when a gesture occurs
+ *
+ * @return True if bearing tracking will be disabled
+ */
+ public boolean isDismissBearingTrackingOnGesture() {
+ return dismissBearingTrackingOnGesture;
+ }
- // Enable/disable gestures based on tracking mode
+ /**
+ * Returns if location tracking is disabled
+ *
+ * @return True if location tracking is disabled.
+ */
+ public boolean isLocationTrackingDisabled() {
+ return myLocationTrackingMode == MyLocationTracking.TRACKING_NONE;
+ }
+
+ /**
+ * Retyrns uf bearing tracking is disabled
+ *
+ * @return True if bearing tracking will be disabled.
+ */
+ public boolean isBearingTrackingDisabled() {
+ return myBearingTrackingMode == MyBearingTracking.NONE;
+ }
+
+ private void validateAllGesturesForTrackingModes() {
+ validateGesturesForBearingTrackingMode();
+ validateGesturesForLocationTrackingMode();
+ }
+
+ private void validateGesturesForLocationTrackingMode() {
+ int myLocationTrackingMode = getMyLocationTrackingMode();
+ if (!dismissLocationTrackingOnGesture) {
if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
uiSettings.setScrollGesturesEnabled(true);
- uiSettings.setRotateGesturesEnabled(true);
} else {
uiSettings.setScrollGesturesEnabled(false);
- uiSettings.setRotateGesturesEnabled((myBearingTrackingMode == MyBearingTracking.NONE));
}
+ } else {
+ uiSettings.setScrollGesturesEnabled(true);
}
}
- /**
- * Return if location tracking is disabled
- *
- * @return True if location tracking is disabled.
- */
- public boolean isLocationTrackingDisabled() {
- return mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE;
+ private void validateGesturesForBearingTrackingMode() {
+ int myBearingTrackingMode = getMyBearingTrackingMode();
+ if (!dismissBearingTrackingOnGesture) {
+ if (myBearingTrackingMode == MyBearingTracking.NONE) {
+ uiSettings.setRotateGesturesEnabled(true);
+ } else {
+ uiSettings.setRotateGesturesEnabled(false);
+ }
+ } else {
+ uiSettings.setRotateGesturesEnabled(true);
+ }
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
index f87ddb4ca1..3cd9efb13e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java
@@ -1,13 +1,12 @@
package com.mapbox.mapboxsdk.maps;
-import android.support.annotation.FloatRange;
+import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
-import android.util.Log;
import android.view.Gravity;
import android.view.View;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
/**
* Settings for the user interface of a MapboxMap. To obtain this interface, call getUiSettings().
@@ -20,11 +19,19 @@ public class UiSettings {
private ViewSettings logoSettings;
private ViewSettings attributionSettings;
- private boolean rotateGesturesEnabled;
- private boolean tiltGesturesEnabled;
- private boolean zoomGesturesEnabled;
+ private boolean rotateGesturesEnabled = true;
+ private boolean rotateGestureChangeAllowed = true;
+
+ private boolean tiltGesturesEnabled = true;
+ private boolean tiltGestureChangeAllowed = true;
+
+ private boolean zoomGesturesEnabled = true;
+ private boolean zoomGestureChangeAllowed = true;
+
+ private boolean scrollGesturesEnabled = true;
+ private boolean scrollGestureChangeAllowed = true;
+
private boolean zoomControlsEnabled;
- private boolean scrollGesturesEnabled;
UiSettings(@NonNull MapView mapView) {
this.mapView = mapView;
@@ -232,11 +239,11 @@ public class UiSettings {
/**
* <p>
- * Enables or disables the Mapbox logo.
+ * Enables or disables the attribution.
* </p>
- * By default, the compass is enabled.
+ * By default, the attribution is enabled.
*
- * @param enabled True to enable the logo; false to disable the logo.
+ * @param enabled True to enable the attribution; false to disable the attribution.
*/
public void setAttributionEnabled(boolean enabled) {
attributionSettings.setEnabled(enabled);
@@ -244,9 +251,9 @@ public class UiSettings {
}
/**
- * Returns whether the logo is enabled.
+ * Returns whether the attribution is enabled.
*
- * @return True if the logo is enabled; false if the logo is disabled.
+ * @return True if the attribution is enabled; false if the attribution is disabled.
*/
public boolean isAttributionEnabled() {
return attributionSettings.isEnabled();
@@ -254,10 +261,9 @@ public class UiSettings {
/**
* <p>
- * Sets the gravity of the logo view. Use this to change the corner of the map view that the
- * Mapbox logo is displayed in.
+ * Sets the gravity of the attribution.
* </p>
- * By default, the logo is in the bottom left corner.
+ * By default, the attribution is in the bottom left corner next to the Mapbox logo.
*
* @param gravity One of the values from {@link Gravity}.
* @see Gravity
@@ -277,8 +283,7 @@ public class UiSettings {
}
/**
- * Sets the margins of the logo view. Use this to change the distance of the Mapbox logo from the
- * map view edge.
+ * Sets the margins of the attribution view.
*
* @param left The left margin in pixels.
* @param top The top margin in pixels.
@@ -291,7 +296,29 @@ public class UiSettings {
}
/**
- * Returns the left side margin of the logo
+ * <p>
+ * Sets the tint of the attribution view. Use this to change the color of the attribution.
+ * </p>
+ * By default, the logo is tinted with the primary color of your theme.
+ *
+ * @param tintColor Color to tint the attribution.
+ */
+ public void setAttributionTintColor(@ColorInt int tintColor) {
+ attributionSettings.setTintColor(tintColor);
+ mapView.setAtttibutionTintColor(tintColor);
+ }
+
+ /**
+ * Returns the tint color value of the attribution view.
+ *
+ * @return The tint color
+ */
+ public int getAttributionTintColor() {
+ return attributionSettings.getTintColor();
+ }
+
+ /**
+ * Returns the left side margin of the attribution view.
*
* @return The left margin in pixels
*/
@@ -300,7 +327,7 @@ public class UiSettings {
}
/**
- * Returns the top side margin of the logo
+ * Returns the top side margin of the attribution view.
*
* @return The top margin in pixels
*/
@@ -309,7 +336,7 @@ public class UiSettings {
}
/**
- * Returns the right side margin of the logo
+ * Returns the right side margin of the attribution view.
*
* @return The right margin in pixels
*/
@@ -339,7 +366,9 @@ public class UiSettings {
* @param rotateGesturesEnabled If true, rotating is enabled.
*/
public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
- this.rotateGesturesEnabled = rotateGesturesEnabled;
+ if (rotateGestureChangeAllowed) {
+ this.rotateGesturesEnabled = rotateGesturesEnabled;
+ }
}
/**
@@ -351,6 +380,14 @@ public class UiSettings {
return rotateGesturesEnabled;
}
+ void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) {
+ this.rotateGestureChangeAllowed = rotateGestureChangeAllowed;
+ }
+
+ boolean isRotateGestureChangeAllowed() {
+ return rotateGestureChangeAllowed;
+ }
+
/**
* <p>
* Changes whether the user may tilt the map.
@@ -364,7 +401,9 @@ public class UiSettings {
* @param tiltGesturesEnabled If true, tilting is enabled.
*/
public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
- this.tiltGesturesEnabled = tiltGesturesEnabled;
+ if (tiltGestureChangeAllowed) {
+ this.tiltGesturesEnabled = tiltGesturesEnabled;
+ }
}
/**
@@ -376,6 +415,14 @@ public class UiSettings {
return tiltGesturesEnabled;
}
+ void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) {
+ this.tiltGestureChangeAllowed = tiltGestureChangeAllowed;
+ }
+
+ boolean isTiltGestureChangeAllowed() {
+ return tiltGestureChangeAllowed;
+ }
+
/**
* <p>
* Changes whether the user may zoom the map.
@@ -389,7 +436,9 @@ public class UiSettings {
* @param zoomGesturesEnabled If true, zooming is enabled.
*/
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
- this.zoomGesturesEnabled = zoomGesturesEnabled;
+ if (zoomGestureChangeAllowed) {
+ this.zoomGesturesEnabled = zoomGesturesEnabled;
+ }
}
/**
@@ -401,6 +450,14 @@ public class UiSettings {
return zoomGesturesEnabled;
}
+ void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) {
+ this.zoomGestureChangeAllowed = zoomGestureChangeAllowed;
+ }
+
+ boolean isZoomGestureChangeAllowed() {
+ return zoomGestureChangeAllowed;
+ }
+
/**
* <p>
* Sets whether the zoom controls are enabled.
@@ -439,7 +496,9 @@ public class UiSettings {
* @param scrollGesturesEnabled If true, scrolling is enabled.
*/
public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
- this.scrollGesturesEnabled = scrollGesturesEnabled;
+ if (scrollGestureChangeAllowed) {
+ this.scrollGesturesEnabled = scrollGesturesEnabled;
+ }
}
/**
@@ -451,6 +510,14 @@ public class UiSettings {
return scrollGesturesEnabled;
}
+ void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) {
+ this.scrollGestureChangeAllowed = scrollGestureChangeAllowed;
+ }
+
+ boolean isScrollGestureChangeAllowed() {
+ return scrollGestureChangeAllowed;
+ }
+
/**
* <p>
* Sets the preference for whether all gestures should be enabled or disabled.
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
index 0726b7bbbf..f08a1bdeb4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ViewSettings.java
@@ -8,6 +8,7 @@ class ViewSettings {
private boolean enabled;
private int gravity;
private int[]margins;
+ private int tintColor;
public ViewSettings() {
margins = new int[4];
@@ -36,4 +37,12 @@ class ViewSettings {
public void setMargins(int[] margins) {
this.margins = margins;
}
+
+ public int getTintColor() {
+ return tintColor;
+ }
+
+ public void setTintColor(int tintColor) {
+ this.tintColor = tintColor;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
new file mode 100644
index 0000000000..aed4e87c07
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
@@ -0,0 +1,705 @@
+package com.mapbox.mapboxsdk.maps.widgets;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.location.Location;
+import android.os.SystemClock;
+import android.support.annotation.ColorInt;
+import android.support.annotation.FloatRange;
+import android.support.annotation.IntRange;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.R;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.MyBearingTracking;
+import com.mapbox.mapboxsdk.constants.MyLocationTracking;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.Projection;
+import com.mapbox.mapboxsdk.maps.UiSettings;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * UI element overlaid on a map to show the user's location.
+ */
+public class MyLocationView extends View {
+
+ private MyLocationBehavior myLocationBehavior;
+ private MapboxMap mapboxMap;
+ private Projection projection;
+ private int maxSize;
+ private int[] contentPadding = new int[4];
+
+ private Location location;
+ private LatLng latLng;
+ private LatLng interpolatedLocation;
+ private LatLng previousLocation;
+ private long locationUpdateTimestamp;
+
+ private float gpsDirection;
+ private float previousDirection;
+
+ private float accuracy = 0;
+ private Paint accuracyPaint = new Paint();
+
+ private ValueAnimator locationChangeAnimator;
+ private ValueAnimator accuracyAnimator;
+ private ObjectAnimator directionAnimator;
+
+ private Drawable foregroundDrawable;
+ private Drawable foregroundBearingDrawable;
+ private Drawable backgroundDrawable;
+
+ private int foregroundTintColor;
+ private int backgroundTintColor;
+
+ private Rect foregroundBounds;
+ private Rect backgroundBounds;
+
+ private int backgroundOffsetLeft;
+ private int backgroundOffsetTop;
+ private int backgroundOffsetRight;
+ private int backgroundOffsetBottom;
+
+ @MyLocationTracking.Mode
+ private int myLocationTrackingMode;
+
+ @MyBearingTracking.Mode
+ private int myBearingTrackingMode;
+
+ private GpsLocationListener userLocationListener;
+ private CompassListener compassListener;
+
+ public MyLocationView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public MyLocationView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public MyLocationView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ private void init(Context context) {
+ setEnabled(false);
+ myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE);
+ compassListener = new CompassListener(context);
+ maxSize = (int) context.getResources().getDimension(R.dimen.my_locationview_size);
+ }
+
+ public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) {
+ if (defaultDrawable == null || bearingDrawable == null) {
+ return;
+ }
+ if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth() || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) {
+ throw new RuntimeException("The dimensions from location and bearing drawables should be match");
+ }
+
+ foregroundDrawable = defaultDrawable;
+ foregroundBearingDrawable = bearingDrawable;
+ setForegroundDrawableTint(foregroundTintColor);
+
+ invalidateBounds();
+ }
+
+ public final void setForegroundDrawableTint(@ColorInt int color) {
+ if (color != Color.TRANSPARENT) {
+ foregroundTintColor = color;
+ if (foregroundDrawable != null) {
+ foregroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ }
+ if (foregroundBearingDrawable != null) {
+ foregroundBearingDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ }
+ }
+ invalidate();
+ }
+
+ public final void setShadowDrawable(Drawable drawable) {
+ setShadowDrawable(drawable, 0, 0, 0, 0);
+ }
+
+ public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) {
+ if (drawable != null) {
+ backgroundDrawable = drawable;
+ }
+
+ backgroundOffsetLeft = left;
+ backgroundOffsetTop = top;
+ backgroundOffsetRight = right;
+ backgroundOffsetBottom = bottom;
+
+ setShadowDrawableTint(backgroundTintColor);
+
+ invalidateBounds();
+ }
+
+ public final void setShadowDrawableTint(@ColorInt int color) {
+ if (color != Color.TRANSPARENT) {
+ backgroundTintColor = color;
+ if (backgroundDrawable == null) {
+ return;
+ }
+ backgroundDrawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
+ }
+ invalidate();
+ }
+
+ public final void setAccuracyTint(@ColorInt int color) {
+ int alpha = accuracyPaint.getAlpha();
+ accuracyPaint.setColor(color);
+ accuracyPaint.setAlpha(alpha);
+ invalidate();
+ }
+
+ public final void setAccuracyAlpha(@IntRange(from = 0, to = 255) int alpha) {
+ accuracyPaint.setAlpha(alpha);
+ invalidate();
+ }
+
+ private void invalidateBounds() {
+ if (backgroundDrawable == null || foregroundDrawable == null || foregroundBearingDrawable == null) {
+ return;
+ }
+
+ int backgroundWidth = backgroundDrawable.getIntrinsicWidth();
+ int backgroundHeight = backgroundDrawable.getIntrinsicHeight();
+
+ int foregroundWidth = foregroundDrawable.getIntrinsicWidth();
+ int foregroundHeight = foregroundDrawable.getIntrinsicHeight();
+
+ int horizontalOffset = backgroundOffsetLeft - backgroundOffsetRight;
+ int verticalOffset = backgroundOffsetTop - backgroundOffsetBottom;
+
+ int accuracyWidth = 2 * maxSize;
+
+ backgroundBounds = new Rect(accuracyWidth - (backgroundWidth / 2) + horizontalOffset, accuracyWidth + verticalOffset - (backgroundWidth / 2), accuracyWidth + (backgroundWidth / 2) + horizontalOffset, accuracyWidth + (backgroundHeight / 2) + verticalOffset);
+ foregroundBounds = new Rect(accuracyWidth - (foregroundWidth / 2), accuracyWidth - (foregroundHeight / 2), accuracyWidth + (foregroundWidth / 2), accuracyWidth + (foregroundHeight / 2));
+
+ // invoke a new measure
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null) {
+ // Not ready yet
+ return;
+ }
+
+ // Draw circle
+ float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
+ float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel;
+ float maxRadius = getWidth() / 2;
+ canvas.drawCircle(foregroundBounds.centerX(), foregroundBounds.centerY(), accuracyPixels <= maxRadius ? accuracyPixels : maxRadius, accuracyPaint);
+
+ // Draw shadow
+ if (backgroundDrawable != null) {
+ backgroundDrawable.draw(canvas);
+ }
+
+ // Draw foreground
+ if (myBearingTrackingMode == MyBearingTracking.NONE) {
+ if (foregroundDrawable != null) {
+ foregroundDrawable.draw(canvas);
+ }
+ } else if (foregroundBearingDrawable != null && foregroundBounds != null) {
+ foregroundBearingDrawable.draw(canvas);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ if (foregroundDrawable != null && foregroundBounds != null) {
+ foregroundDrawable.setBounds(foregroundBounds);
+ }
+
+ if (foregroundBearingDrawable != null && foregroundBounds != null) {
+ foregroundBearingDrawable.setBounds(foregroundBounds);
+ }
+
+ if (backgroundDrawable != null && backgroundBounds != null) {
+ backgroundDrawable.setBounds(backgroundBounds);
+ }
+
+ setMeasuredDimension(4 * maxSize, 4 * maxSize);
+ }
+
+ public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) {
+ setRotationX((float) tilt);
+ }
+
+ void updateOnNextFrame() {
+ mapboxMap.invalidate();
+ }
+
+ public void onPause() {
+ compassListener.onPause();
+ toggleGps(false);
+ }
+
+ public void onResume() {
+ if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ compassListener.onResume();
+ }
+ if (isEnabled()) {
+ toggleGps(true);
+ }
+ }
+
+ public void update() {
+ if (isEnabled()) {
+ myLocationBehavior.invalidate();
+ } else {
+ setVisibility(View.INVISIBLE);
+ }
+ }
+
+ public void setMapboxMap(MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ this.projection = mapboxMap.getProjection();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
+ toggleGps(enabled);
+ }
+
+ /**
+ * Enabled / Disable GPS location updates along with updating the UI
+ *
+ * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
+ */
+ private void toggleGps(boolean enableGps) {
+ LocationServices locationServices = LocationServices.getLocationServices(getContext());
+ if (enableGps) {
+ // Set an initial location if one available
+ Location lastLocation = locationServices.getLastLocation();
+
+ if (lastLocation != null) {
+ setLocation(lastLocation);
+ }
+
+ if (userLocationListener == null) {
+ userLocationListener = new GpsLocationListener(this);
+ }
+
+ locationServices.addLocationListener(userLocationListener);
+ } else {
+ // Disable location and user dot
+ location = null;
+ locationServices.removeLocationListener(userLocationListener);
+ }
+
+ locationServices.toggleGPS(enableGps);
+ }
+
+ public Location getLocation() {
+ return location;
+ }
+
+ public void setLocation(Location location) {
+ if (location == null) {
+ this.location = null;
+ return;
+ }
+
+ this.location = location;
+ myLocationBehavior.updateLatLng(location);
+ }
+
+ public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
+ this.myBearingTrackingMode = myBearingTrackingMode;
+ if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ compassListener.onResume();
+ } else {
+ compassListener.onPause();
+ if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
+ // always face north
+ gpsDirection = 0;
+ setCompass(gpsDirection);
+ }
+ }
+ invalidate();
+ update();
+ }
+
+ public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
+ this.myLocationTrackingMode = myLocationTrackingMode;
+
+ MyLocationBehaviorFactory factory = new MyLocationBehaviorFactory();
+ myLocationBehavior = factory.getBehavioralModel(myLocationTrackingMode);
+
+ if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && location != null) {
+ // center map directly if we have a location fix
+ myLocationBehavior.updateLatLng(location);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(location)));
+ }
+ invalidate();
+ update();
+ }
+
+ private void setCompass(float bearing) {
+ float oldDir = previousDirection;
+ if (directionAnimator != null) {
+ oldDir = (Float) directionAnimator.getAnimatedValue();
+ directionAnimator.end();
+ directionAnimator = null;
+ }
+
+ float newDir = bearing;
+ float diff = oldDir - newDir;
+ if (diff > 180.0f) {
+ newDir += 360.0f;
+ } else if (diff < -180.0f) {
+ newDir -= 360.f;
+ }
+ previousDirection = newDir;
+
+ directionAnimator = ObjectAnimator.ofFloat(this, View.ROTATION, oldDir, newDir);
+ directionAnimator.setDuration(1000);
+ directionAnimator.start();
+ }
+
+ public float getCenterX() {
+ return getX() + getMeasuredWidth() / 2;
+ }
+
+ public float getCenterY() {
+ return getY() + getMeasuredHeight() / 2;
+ }
+
+ public void setContentPadding(int[] padding) {
+ contentPadding = padding;
+ }
+
+ private static class GpsLocationListener implements LocationListener {
+
+ private WeakReference<MyLocationView> mUserLocationView;
+
+ public GpsLocationListener(MyLocationView myLocationView) {
+ mUserLocationView = new WeakReference<>(myLocationView);
+ }
+
+ /**
+ * Callback method for receiving location updates from LocationServices.
+ *
+ * @param location The new Location data
+ */
+ @Override
+ public void onLocationChanged(Location location) {
+ MyLocationView locationView = mUserLocationView.get();
+ if (locationView != null) {
+ locationView.setLocation(location);
+ }
+ }
+ }
+
+ private class CompassListener implements SensorEventListener {
+
+ private SensorManager mSensorManager;
+ private Sensor mAccelerometer;
+ private Sensor mMagnetometer;
+ private boolean paused;
+
+ private float mCurrentDegree = 0f;
+
+ private float[] mOrientation = new float[3];
+ private float[] mGData = new float[3];
+ private float[] mMData = new float[3];
+ private float[] mR = new float[16];
+ private float[] mI = new float[16];
+
+ // Controls the sensor updateLatLng rate in milliseconds
+ private static final int UPDATE_RATE_MS = 500;
+
+ // Compass data
+ private long mCompassUpdateNextTimestamp = 0;
+
+ public CompassListener(Context context) {
+ mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+ mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
+ }
+
+ public void onResume() {
+ paused = false;
+ mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
+ mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
+ }
+
+ public void onPause() {
+ paused = true;
+ mSensorManager.unregisterListener(this, mAccelerometer);
+ mSensorManager.unregisterListener(this, mMagnetometer);
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (paused) {
+ return;
+ }
+
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime < mCompassUpdateNextTimestamp) {
+ return;
+ }
+
+ int type = event.sensor.getType();
+ float[] data;
+ if (type == Sensor.TYPE_ACCELEROMETER) {
+ data = mGData;
+ } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
+ data = mMData;
+ } else {
+ // we should not be here.
+ return;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ data[i] = event.values[i];
+ }
+
+ SensorManager.getRotationMatrix(mR, mI, mGData, mMData);
+ SensorManager.getOrientation(mR, mOrientation);
+ setCompass((int) (mOrientation[0] * 180.0f / Math.PI));
+ mCompassUpdateNextTimestamp = currentTime + UPDATE_RATE_MS;
+ }
+
+ public float getCurrentDegree() {
+ return mCurrentDegree;
+ }
+
+ public boolean isPaused() {
+ return paused;
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ }
+
+ private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
+
+ private MyLocationBehavior behavior;
+ private double fromLat;
+ private double fromLng;
+ private double toLat;
+ private double toLng;
+
+ private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) {
+ behavior = myLocationBehavior;
+ fromLat = from.getLatitude();
+ fromLng = from.getLongitude();
+ toLat = to.getLatitude();
+ toLng = to.getLongitude();
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ float frac = animation.getAnimatedFraction();
+ double latitude = fromLat + (toLat - fromLat) * frac;
+ double longitude = fromLng + (toLng - fromLng) * frac;
+ behavior.updateLatLng(latitude, longitude);
+ updateOnNextFrame();
+ }
+ }
+
+ private class MyLocationBehaviorFactory {
+
+ public MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) {
+ if (mode == MyLocationTracking.TRACKING_NONE) {
+ return new MyLocationShowBehavior();
+ } else {
+ return new MyLocationTrackingBehavior();
+ }
+ }
+ }
+
+ private abstract class MyLocationBehavior {
+
+ abstract void updateLatLng(@NonNull Location location);
+
+ public void updateLatLng(double lat, double lon) {
+ if (latLng != null) {
+ latLng.setLatitude(lat);
+ latLng.setLongitude(lon);
+ }
+ }
+
+ protected void updateAccuracy(@NonNull Location location) {
+ if (accuracyAnimator != null && accuracyAnimator.isRunning()) {
+ // use current accuracy as a starting point
+ accuracy = (Float) accuracyAnimator.getAnimatedValue();
+ accuracyAnimator.end();
+ }
+
+ accuracyAnimator = ValueAnimator.ofFloat(accuracy * 10, location.getAccuracy() * 10);
+ accuracyAnimator.setDuration(750);
+ accuracyAnimator.start();
+ accuracy = location.getAccuracy();
+ }
+
+ abstract void invalidate();
+ }
+
+ private class MyLocationTrackingBehavior extends MyLocationBehavior {
+
+ @Override
+ void updateLatLng(@NonNull Location location) {
+ if (latLng == null) {
+ // first location fix
+ latLng = new LatLng(location);
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ }
+
+ // updateLatLng timestamp
+ long previousUpdateTimeStamp = locationUpdateTimestamp;
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+
+ // calculate animation duration
+ long locationUpdateDuration;
+ if (previousUpdateTimeStamp == 0) {
+ locationUpdateDuration = 0;
+ } else {
+ locationUpdateDuration = locationUpdateTimestamp - previousUpdateTimeStamp;
+ }
+
+ // calculate interpolated location
+ previousLocation = latLng;
+ latLng = new LatLng(location);
+ interpolatedLocation = new LatLng((latLng.getLatitude() + previousLocation.getLatitude()) / 2, (latLng.getLongitude() + previousLocation.getLongitude()) / 2);
+
+ // build new camera
+ CameraPosition.Builder builder = new CameraPosition.Builder().target(interpolatedLocation);
+
+ // add direction
+ if (myBearingTrackingMode == MyBearingTracking.GPS) {
+ if (location.hasBearing()) {
+ builder.bearing(location.getBearing());
+ }
+ gpsDirection = 0;
+ setCompass(gpsDirection);
+ } else if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
+ if (!compassListener.isPaused()) {
+ builder.bearing(compassListener.getCurrentDegree());
+ setCompass(0);
+ }
+ }
+
+ // accuracy
+ updateAccuracy(location);
+
+ // ease to new camera position with a linear interpolator
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), (int) locationUpdateDuration, false /*linear interpolator*/);
+ }
+
+ @Override
+ void invalidate() {
+ int[] mapPadding = mapboxMap.getPadding();
+ UiSettings uiSettings = mapboxMap.getUiSettings();
+ setX((uiSettings.getWidth() - getWidth() + mapPadding[0] - mapPadding[2]) / 2 + (contentPadding[0] - contentPadding[2]) / 2);
+ setY((uiSettings.getHeight() - getHeight() - mapPadding[3] + mapPadding[1]) / 2 + (contentPadding[1] - contentPadding[3]) / 2);
+ MyLocationView.this.invalidate();
+ }
+ }
+
+ private class MyLocationShowBehavior extends MyLocationBehavior {
+
+ @Override
+ void updateLatLng(@NonNull final Location location) {
+ if (latLng == null) {
+ // first location update
+ latLng = new LatLng(location);
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ }
+
+ // update LatLng location
+ previousLocation = latLng;
+ latLng = new LatLng(location);
+
+ // update LatLng direction
+ if (location.hasBearing()) {
+ gpsDirection = clamp(location.getBearing() - (float) mapboxMap.getCameraPosition().bearing);
+ setCompass(gpsDirection);
+ }
+
+ // update LatLng accuracy
+ updateAccuracy(location);
+
+ // calculate updateLatLng time + add some extra offset to improve animation
+ long previousUpdateTimeStamp = locationUpdateTimestamp;
+ locationUpdateTimestamp = SystemClock.elapsedRealtime();
+ long locationUpdateDuration = (long) ((locationUpdateTimestamp - previousUpdateTimeStamp) * 1.1);
+
+ // calculate interpolated entity
+ interpolatedLocation = new LatLng((latLng.getLatitude() + previousLocation.getLatitude()) / 2, (latLng.getLongitude() + previousLocation.getLongitude()) / 2);
+
+ // animate changes
+ if (locationChangeAnimator != null) {
+ locationChangeAnimator.end();
+ locationChangeAnimator = null;
+ }
+
+ locationChangeAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+ locationChangeAnimator.setDuration((long) (locationUpdateDuration * 1.2));
+ locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this,
+ previousLocation, interpolatedLocation
+ ));
+ locationChangeAnimator.start();
+
+ // use interpolated location as current location
+ latLng = interpolatedLocation;
+ }
+
+ private float clamp(float direction) {
+ float diff = previousDirection - direction;
+ if (diff > 180.0f) {
+ direction += 360.0f;
+ } else if (diff < -180.0f) {
+ direction -= 360.f;
+ }
+ previousDirection = direction;
+ return direction;
+ }
+
+ @Override
+ void invalidate() {
+ PointF screenLocation = projection.toScreenLocation(latLng);
+ if (screenLocation != null) {
+ setX((screenLocation.x - getWidth() / 2));
+ setY((screenLocation.y - getHeight() / 2));
+ }
+ MyLocationView.this.invalidate();
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
new file mode 100644
index 0000000000..9ae96ebf7b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
@@ -0,0 +1,146 @@
+package com.mapbox.mapboxsdk.maps.widgets;
+
+import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.IntRange;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+
+public class MyLocationViewSettings {
+
+ private MapView mapView;
+ private MyLocationView myLocationView;
+
+ //
+ // State
+ //
+
+ private boolean enabled;
+
+ //
+ // Foreground
+ //
+
+ private Drawable foregroundDrawable;
+ private Drawable foregroundBearingDrawable;
+
+ @ColorInt
+ private int foregroundTintColor;
+
+ //
+ // Background
+ //
+
+ private Drawable backgroundDrawable;
+ private int[] backgroundOffset = new int[4];
+
+ @ColorInt
+ private int backgroundTintColor;
+
+ //
+ // Accuracy
+ //
+
+ private int accuracyAlpha;
+
+ @ColorInt
+ private int accuracyTintColor;
+
+ //
+ // Padding
+ //
+
+ private int[] padding = new int[4];
+
+ public MyLocationViewSettings(MapView mapView, MyLocationView myLocationView) {
+ this.mapView = mapView;
+ this.myLocationView = myLocationView;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ myLocationView.setEnabled(enabled);
+ }
+
+ public void setForegroundDrawable(Drawable foregroundDrawable, Drawable foregroundBearingDrawable) {
+ this.foregroundDrawable = foregroundDrawable;
+ this.foregroundBearingDrawable = foregroundBearingDrawable;
+ myLocationView.setForegroundDrawables(foregroundDrawable, foregroundBearingDrawable);
+ }
+
+ public Drawable getForegroundDrawable() {
+ return foregroundDrawable;
+ }
+
+ public Drawable getForegroundBearingDrawable() {
+ return foregroundBearingDrawable;
+ }
+
+ public void setForegroundTintColor(@ColorInt int foregroundTintColor) {
+ this.foregroundTintColor = foregroundTintColor;
+ myLocationView.setForegroundDrawableTint(foregroundTintColor);
+ }
+
+ public int getForegroundTintColor() {
+ return foregroundTintColor;
+ }
+
+ public void setBackgroundDrawable(Drawable backgroundDrawable, int[] padding) {
+ this.backgroundDrawable = backgroundDrawable;
+ this.backgroundOffset = padding;
+ if (padding != null && padding.length == 4) {
+ myLocationView.setShadowDrawable(backgroundDrawable, padding[0], padding[1], padding[2], padding[3]);
+ } else {
+ myLocationView.setShadowDrawable(backgroundDrawable);
+ }
+ }
+
+ public Drawable getBackgroundDrawable() {
+ return backgroundDrawable;
+ }
+
+ public void setBackgroundTintColor(@ColorInt int backgroundTintColor) {
+ this.backgroundTintColor = backgroundTintColor;
+ myLocationView.setShadowDrawableTint(backgroundTintColor);
+ }
+
+ public int getBackgroundTintColor() {
+ return backgroundTintColor;
+ }
+
+ public int[] getBackgroundOffset() {
+ return backgroundOffset;
+ }
+
+ public void setPadding(int left, int top, int right, int bottom) {
+ padding = new int[]{left, top, right, bottom};
+ myLocationView.setContentPadding(padding);
+ mapView.invalidateContentPadding();
+ }
+
+ public int[] getPadding() {
+ return padding;
+ }
+
+ public int getAccuracyAlpha() {
+ return accuracyAlpha;
+ }
+
+ public void setAccuracyAlpha(@IntRange(from = 0, to = 255) int arruracyAlpha) {
+ this.accuracyAlpha = arruracyAlpha;
+ myLocationView.setAccuracyAlpha(arruracyAlpha);
+ }
+
+ public int getAccuracyTintColor() {
+ return accuracyTintColor;
+ }
+
+ public void setAccuracyTintColor(@ColorInt int accuracyTintColor) {
+ this.accuracyTintColor = accuracyTintColor;
+ myLocationView.setAccuracyTint(accuracyTintColor);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java
deleted file mode 100644
index 36e48488fa..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java
+++ /dev/null
@@ -1,757 +0,0 @@
-package com.mapbox.mapboxsdk.maps.widgets;
-
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.location.Location;
-import android.os.Build;
-import android.os.SystemClock;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.mapbox.mapboxsdk.R;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MyBearingTracking;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.location.LocationListener;
-import com.mapbox.mapboxsdk.location.LocationServices;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.Projection;
-
-import java.lang.ref.WeakReference;
-
-/**
- * UI element overlaid on a map to show the user's location.
- */
-public final class UserLocationView extends View {
-
- private MapboxMap mMapboxMap;
- private Projection mProjection;
-
- private boolean mShowMarker;
- private boolean mShowDirection;
- private boolean mShowAccuracy;
- private boolean mStaleMarker;
-
- private PointF mMarkerScreenPoint;
- private Matrix mMarkerScreenMatrix;
-
- private Paint mAccuracyPaintFill;
- private Paint mAccuracyPaintStroke;
- private Path mAccuracyPath;
- private RectF mAccuracyBounds;
-
- private Drawable mUserLocationDrawable;
- private RectF mUserLocationDrawableBoundsF;
- private Rect mUserLocationDrawableBounds;
-
- private Drawable mUserLocationBearingDrawable;
- private RectF mUserLocationBearingDrawableBoundsF;
- private Rect mUserLocationBearingDrawableBounds;
-
- private Drawable mUserLocationStaleDrawable;
- private RectF mUserLocationStaleDrawableBoundsF;
- private Rect mUserLocationStaleDrawableBounds;
-
- private Rect mDirtyRect;
- private RectF mDirtyRectF;
-
- private LatLng mMarkerCoordinate;
- private ValueAnimator mMarkerCoordinateAnimator;
- private float mGpsMarkerDirection;
- private float mCompassMarkerDirection;
- private ObjectAnimator mMarkerDirectionAnimator;
- private float mMarkerAccuracy;
- private ObjectAnimator mMarkerAccuracyAnimator;
-
- private LatLng mCurrentMapViewCoordinate;
- private double mCurrentBearing;
- private boolean mPaused = false;
- private Location mUserLocation;
- private UserLocationListener mUserLocationListener;
-
- private MapboxMap.OnMyLocationChangeListener mOnMyLocationChangeListener;
-
- @MyLocationTracking.Mode
- private int mMyLocationTrackingMode;
-
- @MyBearingTracking.Mode
- private int mMyBearingTrackingMode;
-
- // Compass data
- private MyBearingListener mBearingChangeListener;
-
- public UserLocationView(Context context) {
- super(context);
- initialize(context);
- }
-
- public UserLocationView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initialize(context);
- }
-
- public UserLocationView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initialize(context);
- }
-
- private void initialize(Context context) {
- // View configuration
- setEnabled(false);
- setWillNotDraw(false);
-
- // Layout params
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
- setLayoutParams(lp);
-
- // Setup sensors
- mBearingChangeListener = new MyBearingListener(context);
-
- // Setup the custom paint
- Resources resources = context.getResources();
- int accuracyColor = ContextCompat.getColor(context,R.color.my_location_ring);
-
- float density = resources.getDisplayMetrics().density;
- mMarkerCoordinate = new LatLng(0.0, 0.0);
- mMarkerScreenPoint = new PointF();
- mMarkerScreenMatrix = new Matrix();
-
- mAccuracyPaintFill = new Paint();
- mAccuracyPaintFill.setAntiAlias(true);
- mAccuracyPaintFill.setStyle(Paint.Style.FILL);
- mAccuracyPaintFill.setColor(accuracyColor);
- mAccuracyPaintFill.setAlpha((int) (255 * 0.25f));
-
- mAccuracyPaintStroke = new Paint();
- mAccuracyPaintStroke.setAntiAlias(true);
- mAccuracyPaintStroke.setStyle(Paint.Style.STROKE);
- mAccuracyPaintStroke.setStrokeWidth(0.5f * density);
- mAccuracyPaintStroke.setColor(accuracyColor);
- mAccuracyPaintStroke.setAlpha((int) (255 * 0.5f));
-
- mAccuracyPath = new Path();
- mAccuracyBounds = new RectF();
-
- mUserLocationDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location);
- mUserLocationDrawableBounds = new Rect(
- -mUserLocationDrawable.getIntrinsicWidth() / 2,
- -mUserLocationDrawable.getIntrinsicHeight() / 2,
- mUserLocationDrawable.getIntrinsicWidth() / 2,
- mUserLocationDrawable.getIntrinsicHeight() / 2);
- mUserLocationDrawableBoundsF = new RectF(
- -mUserLocationDrawable.getIntrinsicWidth() / 2,
- -mUserLocationDrawable.getIntrinsicHeight() / 2,
- mUserLocationDrawable.getIntrinsicWidth() / 2,
- mUserLocationDrawable.getIntrinsicHeight() / 2);
- mUserLocationDrawable.setBounds(mUserLocationDrawableBounds);
-
- mUserLocationBearingDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location_bearing);
- mUserLocationBearingDrawableBounds = new Rect(
- -mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
- -mUserLocationBearingDrawable.getIntrinsicHeight() / 2,
- mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
- mUserLocationBearingDrawable.getIntrinsicHeight() / 2);
- mUserLocationBearingDrawableBoundsF = new RectF(
- -mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
- -mUserLocationBearingDrawable.getIntrinsicHeight() / 2,
- mUserLocationBearingDrawable.getIntrinsicWidth() / 2,
- mUserLocationBearingDrawable.getIntrinsicHeight() / 2);
- mUserLocationBearingDrawable.setBounds(mUserLocationBearingDrawableBounds);
-
- mUserLocationStaleDrawable = ContextCompat.getDrawable(getContext(), R.drawable.my_location_stale);
- mUserLocationStaleDrawableBounds = new Rect(
- -mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
- -mUserLocationStaleDrawable.getIntrinsicHeight() / 2,
- mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
- mUserLocationStaleDrawable.getIntrinsicHeight() / 2);
- mUserLocationStaleDrawableBoundsF = new RectF(
- -mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
- -mUserLocationStaleDrawable.getIntrinsicHeight() / 2,
- mUserLocationStaleDrawable.getIntrinsicWidth() / 2,
- mUserLocationStaleDrawable.getIntrinsicHeight() / 2);
- mUserLocationStaleDrawable.setBounds(mUserLocationStaleDrawableBounds);
- }
-
- public void setMapboxMap(MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
- mProjection = mapboxMap.getProjection();
- }
-
- @Override
- public void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (!mShowMarker) {
- return;
- }
-
- canvas.concat(mMarkerScreenMatrix);
-
- Drawable dotDrawable = mShowDirection ? mUserLocationBearingDrawable : mUserLocationDrawable;
- dotDrawable = mStaleMarker ? mUserLocationStaleDrawable : dotDrawable;
- // IMPORTANT also update in update()
- RectF dotBounds = mShowDirection ? mUserLocationBearingDrawableBoundsF : mUserLocationDrawableBoundsF;
- dotBounds = mStaleMarker ? mUserLocationStaleDrawableBoundsF : dotBounds;
-
- boolean willDraw = true;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN || !canvas.isHardwareAccelerated()) {
- willDraw = mShowAccuracy && !mStaleMarker && !canvas.quickReject(mAccuracyPath, Canvas.EdgeType.AA);
- }
- willDraw |= !canvas.quickReject(dotBounds, Canvas.EdgeType.AA);
-
- if (willDraw) {
- if (mShowAccuracy && !mStaleMarker) {
- canvas.drawPath(mAccuracyPath, mAccuracyPaintFill);
- canvas.drawPath(mAccuracyPath, mAccuracyPaintStroke);
- }
- dotDrawable.draw(canvas);
- }
- }
-
- public void setMyLocationTrackingMode(@MyLocationTracking.Mode int myLocationTrackingMode) {
- mMyLocationTrackingMode = myLocationTrackingMode;
-
- if (myLocationTrackingMode != MyLocationTracking.TRACKING_NONE && mUserLocation != null) {
- // center map directly if we have a location fix
- mMarkerCoordinate = new LatLng(mUserLocation.getLatitude(), mUserLocation.getLongitude());
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(mUserLocation)));
-
- // center view directly
- mMarkerScreenMatrix.reset();
- mMarkerScreenPoint = getMarkerScreenPoint();
- mMarkerScreenMatrix.setTranslate(mMarkerScreenPoint.x, mMarkerScreenPoint.y);
- }
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled);
- setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- toggleGps(enabled);
- }
-
- public void update() {
- if (isEnabled() && mShowMarker) {
- setVisibility(View.VISIBLE);
-
- mStaleMarker = isStale(mUserLocation);
-
- // compute new marker position
- // TODO add JNI method that takes existing pointf
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- mMarkerScreenPoint = getMarkerScreenPoint();
- mMarkerScreenMatrix.reset();
- mMarkerScreenMatrix.setTranslate(
- mMarkerScreenPoint.x,
- mMarkerScreenPoint.y);
-
- } else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- double bearing;
- if (mShowDirection) {
- bearing = mMyBearingTrackingMode == MyBearingTracking.COMPASS ? mBearingChangeListener.getCompassBearing() : mUserLocation.getBearing();
- } else {
- bearing = mMapboxMap.getCameraPosition().bearing;
- }
-
- if (mCurrentMapViewCoordinate == null) {
- mCurrentMapViewCoordinate = mMapboxMap.getCameraPosition().target;
- }
-
- // only update if there is an actual change
- if ((!mCurrentMapViewCoordinate.equals(mMarkerCoordinate)) || (!(mCurrentBearing == bearing))) {
- CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(mMarkerCoordinate)
- .bearing(bearing)
- .build();
- mMapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 300, null);
- mMarkerScreenMatrix.reset();
- mMarkerScreenPoint = getMarkerScreenPoint();
- mMarkerScreenMatrix.setTranslate(mMarkerScreenPoint.x, mMarkerScreenPoint.y);
-
- // set values for next check for actual change
- mCurrentMapViewCoordinate = mMarkerCoordinate;
- mCurrentBearing = bearing;
- }
- }
-
- // rotate so arrow in points to bearing
- if (mShowDirection) {
- if (mMyBearingTrackingMode == MyBearingTracking.COMPASS && mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- mMarkerScreenMatrix.preRotate((float)(mCompassMarkerDirection + mMapboxMap.getCameraPosition().bearing));
- } else if (mMyBearingTrackingMode == MyBearingTracking.GPS) {
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- mMarkerScreenMatrix.preRotate((float)(mGpsMarkerDirection + mMapboxMap.getCameraPosition().bearing));
- } else {
- mMarkerScreenMatrix.preRotate(mGpsMarkerDirection);
- }
- }
- }
-
- // adjust accuracy circle
- if (mShowAccuracy && !mStaleMarker) {
- mAccuracyPath.reset();
- mAccuracyPath.addCircle(0.0f, 0.0f,
- (float) (mMarkerAccuracy / mMapboxMap.getProjection().getMetersPerPixelAtLatitude(
- mMarkerCoordinate.getLatitude())),
- Path.Direction.CW);
-
- mAccuracyPath.computeBounds(mAccuracyBounds, false);
- mAccuracyBounds.inset(-1.0f, -1.0f);
- }
-
- // invalidate changed pixels
- if (mDirtyRect == null) {
- mDirtyRect = new Rect();
- mDirtyRectF = new RectF();
- } else {
- // the old marker location
- invalidate(mDirtyRect);
- }
-
- RectF dotBounds = mShowDirection ? mUserLocationBearingDrawableBoundsF : mUserLocationDrawableBoundsF;
- dotBounds = mStaleMarker ? mUserLocationStaleDrawableBoundsF : dotBounds;
- RectF largerBounds = mShowAccuracy && !mStaleMarker && mAccuracyBounds.contains(dotBounds)
- ? mAccuracyBounds : dotBounds;
- mMarkerScreenMatrix.mapRect(mDirtyRectF, largerBounds);
- mDirtyRectF.roundOut(mDirtyRect);
- invalidate(mDirtyRect); // the new marker location
- } else {
- setVisibility(View.INVISIBLE);
- }
- }
-
- public Location getLocation() {
- return mUserLocation;
- }
-
- /**
- * Enabled / Disable GPS location updates along with updating the UI
- *
- * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
- */
- private void toggleGps(boolean enableGps) {
-
- LocationServices locationServices = LocationServices.getLocationServices(getContext());
-
- if (enableGps) {
- // Set an initial location if one available
- Location lastLocation = locationServices.getLastLocation();
- if (lastLocation != null) {
- setLocation(lastLocation);
- }
-
- if (mUserLocationListener == null) {
- mUserLocationListener = new UserLocationListener(this);
- }
-
- // Register for Location Updates
- locationServices.addLocationListener(mUserLocationListener);
- } else {
- // Disable location and user dot
- setLocation(null);
-
- // Deregister for Location Updates
- locationServices.removeLocationListener(mUserLocationListener);
- }
-
- locationServices.toggleGPS(enableGps);
- }
-
- public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- mMyBearingTrackingMode = myBearingTrackingMode;
-
- if (myBearingTrackingMode == MyBearingTracking.COMPASS) {
- mShowAccuracy = false;
- mShowDirection = true;
- mBearingChangeListener.onResume();
- } else {
- mBearingChangeListener.onPause();
- if (myBearingTrackingMode == MyBearingTracking.GPS) {
- mShowDirection = (mUserLocation != null) && mUserLocation.hasBearing();
- } else {
- mShowDirection = false;
- }
- }
- update();
- }
-
- private class MyBearingListener implements SensorEventListener {
-
- private SensorManager mSensorManager;
- private Sensor mAccelerometer;
- private Sensor mMagnetometer;
- private float[] mLastAccelerometer = new float[3];
- private float[] mLastMagnetometer = new float[3];
- private boolean mLastAccelerometerSet = false;
- private boolean mLastMagnetometerSet = false;
- private float[] mR = new float[9];
- private float[] mOrientation = new float[3];
- private float mCurrentDegree = 0f;
-
- // Controls the sensor update rate in milliseconds
- private static final int UPDATE_RATE_MS = 300;
-
- // Compass data
- private float mCompassBearing;
- private long mCompassUpdateNextTimestamp = 0;
-
- public MyBearingListener(Context context) {
- mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
- mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
- }
-
- public void onResume() {
- mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME);
- mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME);
- }
-
- public void onPause() {
- mSensorManager.unregisterListener(this, mAccelerometer);
- mSensorManager.unregisterListener(this, mMagnetometer);
- }
-
- public float getCompassBearing() {
- return mCurrentDegree;
- }
-
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (mPaused) {
- return;
- }
-
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime < mCompassUpdateNextTimestamp) {
- return;
- }
-
- if (event.sensor == mAccelerometer) {
- System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
- mLastAccelerometerSet = true;
- } else if (event.sensor == mMagnetometer) {
- System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
- mLastMagnetometerSet = true;
- }
-
- if (mLastAccelerometerSet && mLastMagnetometerSet) {
- SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
- SensorManager.getOrientation(mR, mOrientation);
- float azimuthInRadians = mOrientation[0];
-
- mCompassBearing = (float) (Math.toDegrees(azimuthInRadians) + 360) % 360;
- if (mCompassBearing < 0) {
- // only allow positive degrees
- mCompassBearing += 360;
- }
-
- if (mCompassBearing > mCurrentDegree + 15 || mCompassBearing < mCurrentDegree - 15) {
- mCurrentDegree = mCompassBearing;
- setCompass(mCurrentDegree);
- }
- }
- mCompassUpdateNextTimestamp = currentTime + UPDATE_RATE_MS;
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // TODO add accuracy to the equiation
- }
- }
-
- private static class UserLocationListener implements LocationListener {
-
- private WeakReference<UserLocationView> mUserLocationView;
-
- public UserLocationListener(UserLocationView userLocationView) {
- mUserLocationView = new WeakReference<>(userLocationView);
- }
-
-
- /**
- * Callback method for receiving location updates from LocationServices.
- *
- * @param location The new Location data
- */
- @Override
- public void onLocationChanged(Location location) {
- UserLocationView locationView = mUserLocationView.get();
- if (locationView != null && !locationView.isPaused()) {
- locationView.setLocation(location);
- }
- }
- }
-
- private boolean isStale(Location location) {
- if (location != null && mMyBearingTrackingMode != MyBearingTracking.COMPASS) {
- long ageInNanos;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- ageInNanos = SystemClock.elapsedRealtimeNanos() -
- location.getElapsedRealtimeNanos();
- } else {
- ageInNanos = (System.currentTimeMillis() - location.getTime()) * 1000 * 1000;
- }
- final long oneMinuteInNanos = 60L * 1000 * 1000 * 1000;
- return ageInNanos > oneMinuteInNanos;
- } else {
- return false;
- }
- }
-
- // Handles location updates from GPS
- private void setLocation(Location location) {
- // if null we should hide the marker
- if (location == null) {
- mShowMarker = false;
- mShowDirection = false;
- mShowAccuracy = false;
-
- cancelAnimations();
-
- mUserLocation = null;
- return;
- }
-
- if (mMarkerCoordinateAnimator != null) {
- mMarkerCoordinateAnimator.end();
- mMarkerCoordinateAnimator = null;
- }
-
- if (mMarkerDirectionAnimator != null) {
- mMarkerDirectionAnimator.end();
- mMarkerDirectionAnimator = null;
- }
-
- if (mMarkerAccuracyAnimator != null) {
- mMarkerAccuracyAnimator.end();
- mMarkerAccuracyAnimator = null;
- }
-
- mShowMarker = true;
-
- LatLng previousCoordinate;
- if (mUserLocation == null) {
- previousCoordinate = new LatLng(location);
- } else {
- previousCoordinate = new LatLng(mUserLocation);
- }
-
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- // moving marker above map
- mMarkerCoordinateAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
- mMarkerCoordinateAnimator.setDuration(1000);
- mMarkerCoordinateAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(
- previousCoordinate, new LatLng(location)
- ));
- mMarkerCoordinateAnimator.start();
- mMarkerCoordinate = new LatLng(location);
- } else {
- // moving map under the tracker
- mMarkerCoordinate = new LatLng(location);
- }
-
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE && mMyBearingTrackingMode == MyBearingTracking.GPS) {
- // show GPS direction
- mShowDirection = location.hasBearing();
- if (mShowDirection) {
- if (mUserLocation != null && mUserLocation.hasBearing()) {
- mGpsMarkerDirection = mUserLocation.getBearing();
- }
- float oldDir = mGpsMarkerDirection;
- float newDir = location.getBearing();
- float diff = oldDir - newDir;
- if (diff > 180.0f) {
- newDir += 360.0f;
- } else if (diff < -180.0f) {
- newDir -= 360.f;
- }
- mMarkerDirectionAnimator = ObjectAnimator.ofFloat(this, "direction", oldDir, newDir);
- mMarkerDirectionAnimator.setDuration(1000);
- mMarkerDirectionAnimator.start();
- }
- } else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW && mMyBearingTrackingMode == MyBearingTracking.GPS) {
- // always show north & rotate map below
- mShowDirection = true;
- mGpsMarkerDirection = 0;
- }
-
- mShowAccuracy = location.hasAccuracy();
- if (mShowAccuracy) {
- if (mUserLocation != null && mUserLocation.hasAccuracy()) {
- mMarkerAccuracy = mUserLocation.getAccuracy();
- }
- mMarkerAccuracyAnimator = ObjectAnimator.ofFloat(this, "accuracy", location.getAccuracy());
- mMarkerAccuracyAnimator.setDuration(1000);
- mMarkerAccuracyAnimator.start();
- }
-
- mUserLocation = location;
- updateOnNextFrame();
-
- if (mOnMyLocationChangeListener != null) {
- mOnMyLocationChangeListener.onMyLocationChange(location);
- }
- }
-
- // handles compass sensor updates
- private void setCompass(float bearing) {
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- // animate marker
- mShowDirection = true;
- float oldDir = mCompassMarkerDirection;
- float newDir = bearing;
- float diff = oldDir - newDir;
- if (diff > 180.0f) {
- newDir += 360.0f;
- } else if (diff < -180.0f) {
- newDir -= 360.f;
- }
- mMarkerDirectionAnimator = ObjectAnimator.ofFloat(this, "direction", oldDir, newDir);
- mMarkerDirectionAnimator.setDuration(1000);
- mMarkerDirectionAnimator.start();
- mCompassMarkerDirection = bearing;
-
- } else if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- cancelAnimations();
- if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
- // always show north & change map direction
- mShowDirection = true;
- mGpsMarkerDirection = 0;
- mCompassMarkerDirection = 0;
- update();
- }
- }
- }
-
- void updateOnNextFrame() {
- mMapboxMap.invalidate();
- }
-
- public void onPause() {
- mPaused = true;
- mBearingChangeListener.onPause();
- cancelAnimations();
- toggleGps(false);
- }
-
- public void onResume() {
- mPaused = false;
- if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
- mBearingChangeListener.onResume();
- }
- if (isEnabled()) {
- toggleGps(true);
- }
- }
-
- public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener listener) {
- mOnMyLocationChangeListener = listener;
- }
-
- // public for animator only
- public float getDirection() {
- if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
- return mCompassMarkerDirection;
- }
- return mGpsMarkerDirection;
- }
-
- // public for animator only
- public void setDirection(float direction) {
- if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) {
- mCompassMarkerDirection = direction % 360.0f;
- } else {
- mGpsMarkerDirection = direction % 360.0f;
- }
- updateOnNextFrame();
- }
-
- // public for animator only
- public float getAccuracy() {
- return mMarkerAccuracy;
- }
-
- // public for animator only
- public void setAccuracy(float accuracy) {
- mMarkerAccuracy = accuracy;
- updateOnNextFrame();
- }
-
- private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
-
- private double mFromLat;
- private double mFromLng;
- private double mToLat;
- private double mToLng;
-
- private MarkerCoordinateAnimatorListener(LatLng from, LatLng to) {
- mFromLat = from.getLatitude();
- mFromLng = from.getLongitude();
- mToLat = to.getLatitude();
- mToLng = to.getLongitude();
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- float frac = animation.getAnimatedFraction();
- double latitude = mFromLat + (mToLat - mFromLat) * frac;
- double longitude = mFromLng + (mToLng - mFromLng) * frac;
- mMarkerCoordinate.setLatitude(latitude);
- mMarkerCoordinate.setLongitude(longitude);
- updateOnNextFrame();
- }
- }
-
- public void cancelAnimations() {
- if (mMarkerCoordinateAnimator != null) {
- mMarkerCoordinateAnimator.cancel();
- mMarkerCoordinateAnimator = null;
- }
-
- if (mMarkerDirectionAnimator != null) {
- mMarkerDirectionAnimator.cancel();
- mMarkerDirectionAnimator = null;
- }
-
- if (mMarkerAccuracyAnimator != null) {
- mMarkerAccuracyAnimator.cancel();
- mMarkerAccuracyAnimator = null;
- }
- }
-
- public boolean isPaused() {
- return mPaused;
- }
-
- public PointF getMarkerScreenPoint() {
- if (mMyLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- mMarkerScreenPoint = mProjection.toScreenLocation(mMarkerCoordinate);
- } else {
- int[] contentPadding = mMapboxMap.getPadding();
- mMarkerScreenPoint = new PointF(((getMeasuredWidth() + contentPadding[0] - contentPadding[2]) / 2)
- , ((getMeasuredHeight() - contentPadding[3] + contentPadding[1]) / 2));
- }
- return mMarkerScreenPoint;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
index 85b3d619b8..e81c366dba 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java
@@ -5,7 +5,7 @@ import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.util.Log;
-
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import java.io.File;
/**
@@ -92,6 +92,10 @@ public class OfflineManager {
String cachePath = assetRoot + File.separator + DATABASE_NAME;
mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE);
+ if (MapboxAccountManager.getInstance() != null) {
+ setAccessToken(mDefaultFileSourcePtr, MapboxAccountManager.getInstance().getAccessToken());
+ }
+
// Delete any existing previous ambient cache database
deleteAmbientDatabase(context);
}
@@ -123,13 +127,24 @@ public class OfflineManager {
return instance;
}
- /*
+ /**
* Access token getter/setter
+ * @param accessToken
+ *
+ * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#start(Context, String)} ()}
*/
+ @Deprecated
public void setAccessToken(String accessToken) {
setAccessToken(mDefaultFileSourcePtr, accessToken);
}
+ /**
+ * Get Access Token
+ * @return Access Token
+ *
+ * @deprecated As of release 4.1.0, replaced by {@link MapboxAccountManager#getAccessToken()}
+ */
+ @Deprecated
public String getAccessToken() {
return getAccessToken(mDefaultFileSourcePtr);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
index e65a20f18e..48609a13bb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegionStatus.java
@@ -13,17 +13,29 @@ public class OfflineRegionStatus {
@OfflineRegion.DownloadState private int downloadState = OfflineRegion.STATE_INACTIVE;
/**
- * The number of resources that have been fully downloaded and are ready for
- * offline access.
+ * The number of resources (inclusive of tiles) that have been fully downloaded
+ * and are ready for offline access.
*/
private long completedResourceCount = 0;
/**
- * The cumulative size, in bytes, of all resources that have been fully downloaded.
+ * The cumulative size, in bytes, of all resources (inclusive of tiles) that have
+ * been fully downloaded.
*/
private long completedResourceSize = 0;
/**
+ * The number of tiles that have been fully downloaded and are ready for
+ * offline access.
+ */
+ private long completedTileCount = 0;
+
+ /**
+ * The cumulative size, in bytes, of all tiles that have been fully downloaded.
+ */
+ private long completedTileSize = 0;
+
+ /**
* The number of resources that are known to be required for this region. See the
* documentation for `requiredResourceCountIsPrecise` for an important caveat
* about this number.
@@ -73,6 +85,14 @@ public class OfflineRegionStatus {
return completedResourceSize;
}
+ public long getCompletedTileCount() {
+ return completedTileCount;
+ }
+
+ public long getCompletedTileSize() {
+ return completedTileSize;
+ }
+
public long getRequiredResourceCount() {
return requiredResourceCount;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
index 736247bbac..b386ed6549 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java
@@ -8,6 +8,7 @@ import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.location.Location;
import android.net.ConnectivityManager;
@@ -17,6 +18,7 @@ import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Build;
+import android.os.Handler;
import android.support.annotation.NonNull;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -26,6 +28,7 @@ import android.view.WindowManager;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.constants.GeoConstants;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.exceptions.TelemetryServiceNotConfiguredException;
import com.mapbox.mapboxsdk.location.LocationServices;
import com.mapbox.mapboxsdk.utils.MathUtils;
import org.json.JSONArray;
@@ -36,7 +39,6 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
-import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
@@ -47,6 +49,7 @@ import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
+import okhttp3.internal.Util;
/**
* Singleton control center for managing Telemetry Data.
@@ -58,11 +61,12 @@ public class MapboxEventManager {
private static MapboxEventManager mapboxEventManager = null;
+ private boolean initialized = false;
private boolean telemetryEnabled;
private final Vector<Hashtable<String, Object>> events = new Vector<>();
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
- private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
+ private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", MapboxConstants.MAPBOX_LOCALE);
private Context context = null;
private String accessToken = null;
@@ -81,7 +85,7 @@ public class MapboxEventManager {
private long mapboxSessionIdLastSet = 0;
private static long hourInMillis = 1000 * 60 * 60;
private static long flushDelayInitialInMillis = 1000 * 10; // 10 Seconds
- private static long flushDelayInMillis = 1000 * 60 * 2; // 2 Minutes
+ private static long flushDelayInMillis = 1000 * 60 * 3; // 3 Minutes
private static final int SESSION_ID_ROTATION_HOURS = 24;
private static MessageDigest messageDigest = null;
@@ -97,16 +101,26 @@ public class MapboxEventManager {
/**
* Internal setup of MapboxEventsManager. It needs to be called once before @link MapboxEventManager#getMapboxEventManager
- * <p/>
+ *
* This allows for a cleaner getMapboxEventManager() that doesn't require context and accessToken
*
* @param context The context associated with MapView
* @param accessToken The accessToken to load MapView
*/
public void initialize(@NonNull Context context, @NonNull String accessToken) {
+
+ Log.i(TAG, "Telemetry initialize() called...");
+
+ if (initialized) {
+ Log.i(TAG, "Mapbox Telemetry has already been initialized.");
+ return;
+ }
+
this.context = context.getApplicationContext();
this.accessToken = accessToken;
+ validateTelemetryServiceConfigured();
+
// Setup Message Digest
try {
messageDigest = MessageDigest.getInstance("SHA-1");
@@ -114,9 +128,13 @@ public class MapboxEventManager {
Log.w(TAG, "Error getting Encryption Algorithm: " + e);
}
+ // Create Initial Session Id
+ rotateSessionId();
+
SharedPreferences prefs = context.getSharedPreferences(MapboxConstants.MAPBOX_SHARED_PREFERENCES_FILE, Context.MODE_PRIVATE);
// Determine if Telemetry Should Be Enabled
+ Log.i(TAG, "Right before Telemetry set enabled in initialized()");
setTelemetryEnabled(prefs.getBoolean(MapboxConstants.MAPBOX_SHARED_PREFERENCE_KEY_TELEMETRY_ENABLED, true));
// Load / Create Vendor Id
@@ -132,9 +150,6 @@ public class MapboxEventManager {
editor.commit();
}
- // Create Initial Session Id
- rotateSessionId();
-
// Get DisplayMetrics Setup
displayMetrics = new DisplayMetrics();
((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
@@ -160,6 +175,8 @@ public class MapboxEventManager {
// Build User Agent
if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appName) && !TextUtils.isEmpty(versionName)) {
userAgent = appName + "/" + versionName + "/" + versionCode + " " + userAgent;
+ // Ensure that only ASCII characters are sent
+ userAgent = Util.toHumanReadableAscii(userAgent);
}
} catch (Exception e) {
@@ -169,6 +186,8 @@ public class MapboxEventManager {
// Register for battery updates
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
batteryStatus = context.registerReceiver(null, iFilter);
+
+ initialized = true;
}
/**
@@ -183,6 +202,24 @@ public class MapboxEventManager {
return mapboxEventManager;
}
+ // Checks that TelemetryService has been configured by developer
+ private void validateTelemetryServiceConfigured() {
+ try {
+ // Check Implementing app's AndroidManifest.xml
+ PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SERVICES);
+ if (packageInfo.services != null) {
+ for (ServiceInfo service : packageInfo.services) {
+ if (TextUtils.equals("com.mapbox.mapboxsdk.telemetry.TelemetryService", service.name)) {
+ return;
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.w(MapboxConstants.TAG, "Error checking for Telemetry Service Config: " + e);
+ }
+ throw new TelemetryServiceNotConfiguredException();
+ }
+
public static String generateCreateDate() {
return dateFormat.format(new Date());
}
@@ -196,6 +233,7 @@ public class MapboxEventManager {
* @param telemetryEnabled True to start telemetry, false to stop it
*/
public void setTelemetryEnabled(boolean telemetryEnabled) {
+ Log.i(TAG, "setTelemetryEnabled(); this.telemetryEnabled = " + this.telemetryEnabled + "; telemetryEnabled = " + telemetryEnabled);
if (this.telemetryEnabled == telemetryEnabled) {
Log.d(TAG, "No need to start / stop telemetry as it's already in that state.");
return;
@@ -207,8 +245,33 @@ public class MapboxEventManager {
context.startService(new Intent(context, TelemetryService.class));
// Make sure Ambient Mode is started at a minimum
- if (LocationServices.getLocationServices(context).isGPSEnabled()) {
- LocationServices.getLocationServices(context).toggleGPS(false);
+ if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) {
+ Log.i(TAG, "Permissions are good, see if GPS is enabled and if not then setup Ambient.");
+ if (LocationServices.getLocationServices(context).isGPSEnabled()) {
+ LocationServices.getLocationServices(context).toggleGPS(false);
+ }
+ } else {
+ // Start timer that checks for Permissions
+ Log.i(TAG, "Permissions are not good. Need to do some looping to check on stuff.");
+
+ final Handler permsHandler = new Handler();
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ if (LocationServices.getLocationServices(context).areLocationPermissionsGranted()) {
+ Log.i(TAG, "Permissions finally granted, so starting Ambient if GPS isn't already enabled");
+ // Start Ambient
+ if (LocationServices.getLocationServices(context).isGPSEnabled()) {
+ LocationServices.getLocationServices(context).toggleGPS(false);
+ }
+ } else {
+ // Restart Handler
+ Log.i(TAG, "Permissions not granted yet... let's try again in 30 seconds");
+ permsHandler.postDelayed(this, 1000 * 30);
+ }
+ }
+ };
+ permsHandler.postDelayed(runnable, 1000 * 10);
}
// Manage Timer Flush
@@ -381,7 +444,7 @@ public class MapboxEventManager {
*/
private void rotateSessionId() {
long now = System.currentTimeMillis();
- if (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis)) {
+ if ((TextUtils.isEmpty(mapboxSessionId)) || (now - mapboxSessionIdLastSet > (SESSION_ID_ROTATION_HOURS * hourInMillis))) {
mapboxSessionId = UUID.randomUUID().toString();
mapboxSessionIdLastSet = System.currentTimeMillis();
}
@@ -524,7 +587,7 @@ public class MapboxEventManager {
@Override
protected Void doInBackground(Void... voids) {
- if (events.size() < 1) {
+ if (events.isEmpty()) {
Log.d(TAG, "No events in the queue to send so returning.");
return null;
}
@@ -533,7 +596,10 @@ public class MapboxEventManager {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo == null || !networkInfo.isConnected()) {
- Log.w(TAG, "Not connected to network, so returning without attempting to send events");
+ Log.w(TAG, "Not connected to network, so empty events cache and return without attempting to send events");
+ // Make sure that events don't pile up when Offline
+ // and thus impact available memory over time.
+ events.removeAllElements();
return null;
}
@@ -642,12 +708,13 @@ public class MapboxEventManager {
Response response = client.newCall(request).execute();
Log.d(TAG, "response code = " + response.code() + " for events " + events.size());
- // Reset Events
- // ============
- events.removeAllElements();
} catch (Exception e) {
Log.e(TAG, "FlushTheEventsTask borked: " + e);
e.printStackTrace();
+ } finally {
+ // Reset Events
+ // ============
+ events.removeAllElements();
}
return null;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
index a35a87eb09..c18da41e4b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java
@@ -37,7 +37,7 @@ public class TelemetryLocationReceiver extends BroadcastReceiver {
* 10 seconds that the system allows before considering the receiver to
* be blocked and a candidate to be killed). You cannot launch a popup dialog
* in your implementation of onReceive().
- * <p/>
+ *
* <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
* then the object is no longer alive after returning from this
* function.</b> This means you should not perform any operations that
@@ -47,7 +47,7 @@ public class TelemetryLocationReceiver extends BroadcastReceiver {
* {@link Context#bindService(Intent, ServiceConnection, int)}. If you wish
* to interact with a service that is already running, you can use
* {@link #peekService}.
- * <p/>
+ *
* <p>The Intent filters used in {@link Context#registerReceiver}
* and in application manifests are <em>not</em> guaranteed to be exclusive. They
* are hints to the operating system about how to find suitable recipients. It is
@@ -63,7 +63,7 @@ public class TelemetryLocationReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Location location = (Location)intent.getExtras().get(LocationManager.KEY_LOCATION_CHANGED);
if (location != null) {
- Log.d(TAG, "location received = " + location);
+// Log.d(TAG, "location received = " + location);
MapboxEventManager.getMapboxEventManager().addLocationEvent(location);
} else {
Log.d(TAG, "location NOT received");
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
index 0db75c92f4..008f355f29 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java
@@ -25,7 +25,7 @@ public class TelemetryService extends Service {
* {@link IBinder} is usually for a complex interface
* that has been <a href="{@docRoot}guide/components/aidl.html">described using
* aidl</a>.
- * <p/>
+ *
* <p><em>Note that unlike other application components, calls on to the
* IBinder interface returned here may not happen on the main thread
* of the process</em>. More information about the main thread can be found in
@@ -93,19 +93,17 @@ public class TelemetryService extends Service {
* Called by the system every time a client explicitly starts the service by calling
* {@link Context#startService}, providing the arguments it supplied and a
* unique integer token representing the start request. Do not call this method directly.
- * <p/>
+ *
* <p>For backwards compatibility, the default implementation calls
* {@link #onStart} and returns either {@link #START_STICKY}
* or {@link #START_STICKY_COMPATIBILITY}.
- * <p/>
+ * </p>
* <p>If you need your application to run on platform versions prior to API
* level 5, you can use the following model to handle the older {@link #onStart}
* callback in that case. The <code>handleCommand</code> method is implemented by
* you as appropriate:
- * <p/>
- * {@sample development/samples/ApiDemos/src/com/example/android/apis/app/ForegroundService.java
- * start_compatibility}
- * <p/>
+ * </p>
+ *
* <p class="caution">Note that the system calls this on your
* service's main thread. A service's main thread is the same
* thread where UI operations take place for Activities running in the
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
new file mode 100644
index 0000000000..495393c258
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/AnimatorUtils.java
@@ -0,0 +1,93 @@
+package com.mapbox.mapboxsdk.utils;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.support.annotation.AnimatorRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+public class AnimatorUtils {
+
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, @Nullable OnAnimationEndListener listener) {
+ animate(view, animatorRes, -1, listener);
+ }
+
+ public static void animate(final View view, @AnimatorRes int animatorRes, int duration, @Nullable final OnAnimationEndListener listener) {
+ if (view == null) {
+ return;
+ }
+
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes);
+ if (duration != -1) {
+ animator.setDuration(duration);
+ }
+
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ if (listener != null) {
+ listener.onAnimationEnd();
+ }
+ }
+ });
+ animator.setTarget(view);
+ animator.start();
+ }
+
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) {
+ animate(view, animatorRes, -1);
+ }
+
+ public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) {
+ animate(view, animatorRes, duration, null);
+ }
+
+ public static void rotate(@NonNull final View view, float rotation) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ rotateAnimator.start();
+ }
+
+ public static void alpha(@NonNull final View convertView, float alpha, @Nullable final OnAnimationEndListener listener) {
+ convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha);
+ rotateAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ convertView.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ convertView.setLayerType(View.LAYER_TYPE_NONE, null);
+ if (listener != null) {
+ listener.onAnimationEnd();
+ }
+ }
+ });
+ rotateAnimator.start();
+ }
+
+ public static void alpha(@NonNull final View convertView, float alpha) {
+ alpha(convertView, alpha, null);
+ }
+
+ public interface OnAnimationEndListener {
+ void onAnimationEnd();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
new file mode 100644
index 0000000000..a0de07c5f1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java
@@ -0,0 +1,90 @@
+package com.mapbox.mapboxsdk.utils;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
+import android.support.v4.graphics.drawable.DrawableCompat;
+import android.util.TypedValue;
+import android.widget.ImageView;
+
+import com.mapbox.mapboxsdk.R;
+
+public class ColorUtils {
+
+ /**
+ * Returns a color integer associated as primary color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The primary color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getPrimaryColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
+ return typedValue.data;
+ }
+
+ /**
+ * Returns a color integer associated as primary dark color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The primary dark color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getPrimaryDarkColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorPrimaryDark, typedValue, true);
+ return typedValue.data;
+ }
+
+ /**
+ * Returns a color integer associated as accent color from a theme based on a {@link Context}.
+ *
+ * @param context The context used to style the color attributes.
+ * @return The accent color value of current theme in the form 0xAARRGGBB.
+ */
+ @ColorInt
+ public static int getAccentColor(@NonNull Context context) {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ theme.resolveAttribute(R.attr.colorAccent, typedValue, true);
+ return typedValue.data;
+ }
+
+ /**
+ * Returns a color state list associated with a theme based on a {@link Context}
+ *
+ * @param color The color used for tinting.
+ * @return A ColorStateList object containing the primary color of a theme
+ */
+ @NonNull
+ public static ColorStateList getSelector(@ColorInt int color) {
+ return new ColorStateList(
+ new int[][]{
+ new int[]{android.R.attr.state_pressed},
+ new int[]{}
+ },
+ new int[]{
+ color,
+ color
+ }
+ );
+ }
+
+ /**
+ * Set a color tint list to the {@link Drawable} of an {@link ImageView}.
+ *
+ * @param imageView The view to set the default tint list.
+ * @param tintColor The color to tint.
+ */
+ public static void setTintList(@NonNull ImageView imageView, @ColorInt int tintColor) {
+ Drawable originalDrawable = imageView.getDrawable();
+ Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable);
+ DrawableCompat.setTintList(wrappedDrawable, getSelector(tintColor));
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
index 922fb11868..a92999c0d5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java
@@ -27,7 +27,7 @@ public class MathUtils {
/**
* Constrains value to the given range (including min, excluding max) via modular arithmetic.
*
- * Same formula as used in Core GL (math.hpp)
+ * Same formula as used in Core GL (wrap.hpp)
* std::fmod((std::fmod((value - min), d) + d), d) + min;
*
* @param value Value to wrap
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/overview.html b/platform/android/MapboxGLAndroidSDK/src/main/java/overview.html
index 951b8d8e75..f218b3ccf9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/overview.html
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/overview.html
@@ -1,9 +1,11 @@
<html>
<body>
+<p>
An open source OpenGL-based vector map solution for Android with full styling capabilities.
-<p/>
+</p>
+<p>
For more information, check out <a href="https://www.mapbox.com/android-sdk/">our online overview</a>.
-<p/>
+</p>
<!--TODO: Need an Android image-->
<!--<img src="https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/ios/screenshot.png"/>-->
<!--<h2>Changelog</h2>
@@ -14,4 +16,4 @@ Initial preview release.
<h3>0.1.0</h3>
<p>Initial beta release.</p>-->
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png
new file mode 100755
index 0000000000..c93fa4781a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png
new file mode 100755
index 0000000000..120b7dd612
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/ic_mylocationview_normal.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location.png
deleted file mode 100755
index 1ae8d541af..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_bearing.png
deleted file mode 100755
index 8ecaffa2e8..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_bearing.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_stale.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_stale.png
deleted file mode 100755
index 0d599c01fa..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-hdpi/my_location_stale.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png
new file mode 100755
index 0000000000..0d7d89a8b4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png
new file mode 100755
index 0000000000..831ef1acf4
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/ic_mylocationview_normal.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location.png
deleted file mode 100755
index 542cd25e22..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_bearing.png
deleted file mode 100755
index 429f03f648..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_bearing.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_stale.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_stale.png
deleted file mode 100755
index 6613c41153..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-mdpi/my_location_stale.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png
new file mode 100755
index 0000000000..1056d617e9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png
new file mode 100755
index 0000000000..37b1f7adbf
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/ic_mylocationview_normal.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location.png
deleted file mode 100755
index ca1f1fe630..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_bearing.png
deleted file mode 100755
index 1b88f9f489..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_bearing.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_stale.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_stale.png
deleted file mode 100755
index 7af3789ff0..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xhdpi/my_location_stale.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png
new file mode 100755
index 0000000000..1ff2590606
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png
new file mode 100755
index 0000000000..520b85eff7
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/ic_mylocationview_normal.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location.png
deleted file mode 100755
index 6f175df168..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_bearing.png
deleted file mode 100755
index f4bb454a06..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_bearing.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_stale.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_stale.png
deleted file mode 100755
index f1d2f2eca0..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxhdpi/my_location_stale.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png
new file mode 100755
index 0000000000..671c33a08e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_bearing.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png
new file mode 100755
index 0000000000..f9f4265d2a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/ic_mylocationview_normal.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location.png
deleted file mode 100755
index d43541ac3c..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_bearing.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_bearing.png
deleted file mode 100755
index a8cccbb3e2..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_bearing.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_stale.png b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_stale.png
deleted file mode 100755
index 33e952391f..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable-xxxhdpi/my_location_stale.png
+++ /dev/null
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml
new file mode 100644
index 0000000000..e1df60788e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/drawable/ic_mylocationview_background.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+
+ <solid android:color="@color/white" />
+
+ <size
+ android:width="@dimen/my_locationview_outer_circle"
+ android:height="@dimen/my_locationview_outer_circle" />
+</shape> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml
index 04b7033282..9799487f12 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapview_internal.xml
@@ -29,7 +29,7 @@
android:src="@drawable/ic_info_outline_24dp_selector"
android:background="@drawable/bg_default_selector"/>
- <com.mapbox.mapboxsdk.maps.widgets.UserLocationView
+ <com.mapbox.mapboxsdk.maps.widgets.MyLocationView
android:id="@+id/userLocationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index a6e1f044c8..66ddd251a5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -1,23 +1,47 @@
<resources>
<!-- these are public -->
<declare-styleable name="MapView">
+
+ <!--Configuration-->
+ <attr name="access_token" format="string" />
+ <attr name="style_url" format="string" />
+
+ <!--Camera-->
<attr name="center_longitude" format="float" />
<attr name="center_latitude" format="float" />
<attr name="zoom" format="float" />
- <attr name="zoom_max" format="float" />
- <attr name="zoom_min" format="float" />
<attr name="direction" format="float" />
<attr name="tilt" format="float" />
+
+ <!--Zoom-->
+ <attr name="zoom_max" format="float" />
+ <attr name="zoom_min" format="float" />
+
+ <!--Gestures-->
<attr name="zoom_enabled" format="boolean" />
<attr name="scroll_enabled" format="boolean" />
<attr name="rotate_enabled" format="boolean" />
<attr name="tilt_enabled" format="boolean" />
- <attr name="zoom_controls_enabled" format="boolean" />
<attr name="debug_active" format="boolean" />
- <attr name="style_url" format="string" />
- <attr name="access_token" format="string" />
- <attr name="style_classes" format="string" />
+
+ <!--UI-Controls-->
+ <attr name="zoom_controls_enabled" format="boolean" />
+
+ <!--MyLocation-->
<attr name="my_location_enabled" format="boolean" />
+ <attr name="my_location_foreground" format="reference" />
+ <attr name="my_location_foreground_bearing" format="reference" />
+ <attr name="my_location_foreground_tint" format="color" />
+ <attr name="my_location_background" format="reference" />
+ <attr name="my_location_background_tint" format="color" />
+ <attr name="my_location_background_left" format="dimension" />
+ <attr name="my_location_background_top" format="dimension" />
+ <attr name="my_location_background_right" format="dimension" />
+ <attr name="my_location_background_bottom" format="dimension" />
+ <attr name="my_location_accuracy_tint" format="color" />
+ <attr name="my_location_accuracy_alpha" format="integer" />
+
+ <!--Compass-->
<attr name="compass_enabled" format="boolean" />
<attr name="compass_gravity">
<flag name="top" value="0x30" />
@@ -39,6 +63,8 @@
<attr name="compass_margin_top" format="dimension" />
<attr name="compass_margin_right" format="dimension" />
<attr name="compass_margin_bottom" format="dimension" />
+
+ <!--Logo-->
<attr name="logo_gravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
@@ -61,6 +87,7 @@
<attr name="logo_margin_bottom" format="dimension" />
<attr name="logo_enabled" format="boolean" />
+ <!--Attribution-->
<attr name="attribution_gravity">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
@@ -82,5 +109,6 @@
<attr name="attribution_margin_right" format="dimension" />
<attr name="attribution_margin_bottom" format="dimension" />
<attr name="attribution_enabled" format="boolean" />
+ <attr name="attribution_tint" format="color" />
</declare-styleable>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
index 97d29c7d45..63f739c30c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/colors.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <color name="white">#FFFFFF</color>
+ <color name="white">#F9F9F9</color>
<color name="black">#000000</color>
<color name="gray">#7D7F80</color>
<color name="gray_light">#EEEEEE</color>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
index 5167ecf936..d6cca7090f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/dimens.xml
@@ -9,4 +9,6 @@
<dimen name="ten_dp">10dp</dimen>
<dimen name="sixteen_dp">16dp</dimen>
<dimen name="seventy_six_dp">76dp</dimen>
+ <dimen name="my_locationview_size">64dp</dimen>
+ <dimen name="my_locationview_outer_circle">18dp</dimen>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml
new file mode 100644
index 0000000000..3727365659
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/integers.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="style_version">9</integer>
+</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
index 1f3cd8c4e3..becbcce0b0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/strings.xml
@@ -11,10 +11,11 @@
<string name="infoWindowAddress">Address</string>
<!-- these are public -->
- <string name="style_mapbox_streets">mapbox://styles/mapbox/streets-v8</string>
+ <!-- {@deprecated Use Style.getXStyleUrl(int version) instead.} -->
+ <string name="style_mapbox_streets">mapbox://styles/mapbox/streets-v9</string>
<string name="style_emerald">mapbox://styles/mapbox/emerald-v8</string>
- <string name="style_light">mapbox://styles/mapbox/light-v8</string>
- <string name="style_dark">mapbox://styles/mapbox/dark-v8</string>
- <string name="style_satellite">mapbox://styles/mapbox/satellite-v8</string>
- <string name="style_satellite_streets">mapbox://styles/mapbox/satellite-hybrid-v8</string>
+ <string name="style_light">mapbox://styles/mapbox/light-v9</string>
+ <string name="style_dark">mapbox://styles/mapbox/dark-v9</string>
+ <string name="style_satellite">mapbox://styles/mapbox/satellite-v9</string>
+ <string name="style_satellite_streets">mapbox://styles/mapbox/satellite-hybrid-v9</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
index 9ad12f76ad..a46f58ae80 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
@@ -4,7 +4,6 @@
<!-- these are public -->
<style name="AttributionAlertDialogStyle" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:textColorPrimary">@android:color/white</item>
- <item name="android:background">@color/mapbox_blue</item>
</style>
</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/README.md b/platform/android/MapboxGLAndroidSDKTestApp/README.md
index 646f29c4b4..0acb509b3e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/README.md
+++ b/platform/android/MapboxGLAndroidSDKTestApp/README.md
@@ -42,7 +42,7 @@ Then:
On Step 2, you can also separate by commas different classes: `com.mapbox.mapboxgl.testapp.MainActivityTest,com.mapbox.mapboxgl.testapp.MainActivityScreenTest`
-If you have no tests for your app, or want to test some random user behaviour,
+If you have no tests for your app, or want to test some random user behavior,
you can just choose "Built-in: Fuzz" in step 2.
### Running pure JUnit tests
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 76dd07b7d6..5c6265c725 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -22,19 +22,19 @@ gradle.projectsEvaluated {
}
ext {
- supportLibVersion = '23.1.1'
+ supportLibVersion = '23.4.0'
}
android {
compileSdkVersion 23
- buildToolsVersion "23.0.2"
+ buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.mapbox.mapboxsdk.testapp"
minSdkVersion 15
targetSdkVersion 23
- versionCode 8
- versionName "4.0.0"
+ versionCode 9
+ versionName "4.1.0"
// Specify AndroidJUnitRunner as the default test instrumentation runner
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -63,7 +63,7 @@ android {
}
buildTypes {
- debug{
+ debug {
// run code coverage reports
testCoverageEnabled = true
}
@@ -84,19 +84,20 @@ dependencies {
compile "com.android.support:support-v4:${supportLibVersion}"
compile "com.android.support:appcompat-v7:${supportLibVersion}"
compile "com.android.support:design:${supportLibVersion}"
+ compile "com.android.support:recyclerview-v7:${supportLibVersion}"
// Leak Canary
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
// Directions SDK
- compile ('com.mapbox.mapboxsdk:mapbox-android-directions:1.0.0@aar'){
- transitive=true
+ compile('com.mapbox.mapboxsdk:mapbox-android-directions:1.0.0@aar') {
+ transitive = true
}
// Geocoder SDK
- compile ('com.mapbox.mapboxsdk:mapbox-android-geocoder:1.0.0@aar'){
- transitive=true
+ compile('com.mapbox.mapboxsdk:mapbox-android-geocoder:1.0.0@aar') {
+ transitive = true
}
// Testing dependencies
@@ -106,6 +107,7 @@ dependencies {
androidTestCompile 'com.android.support.test:runner:0.4.1'
androidTestCompile 'com.android.support.test:rules:0.4.1'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
+ androidTestCompile 'com.jayway.android.robotium:robotium-solo:5.5.4'
}
checkstyle {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
index 255a724744..fbeca9f23b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDKTestApp/proguard-rules.pro
@@ -3,4 +3,6 @@
-dontwarn com.squareup.**
-dontwarn com.retrofit.**
-dontwarn java.lang.**
--dontwarn org.codehaus.** \ No newline at end of file
+-dontwarn org.codehaus.**
+-keep class com.google.**
+-dontwarn com.google.**
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java
new file mode 100644
index 0000000000..d41c692509
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapUtils.java
@@ -0,0 +1,28 @@
+package com.mapbox.mapboxsdk.maps;
+
+/**
+ * Utility class to fetch a MapboxMap instance by bypassing package visibility
+ */
+public class MapboxMapUtils {
+
+ /**
+ * Get the MapboxMap instance linked to passed MapView
+ *
+ * @param mapView
+ * @return
+ */
+ public static MapboxMap getMapboxMap(MapView mapView) {
+ return mapView.getMapboxMap();
+ }
+
+ /**
+ * Set the direction of the user
+ *
+ * @param mapView
+ * @param direction
+ */
+ public static void setDirection(MapView mapView, double direction) {
+ mapView.setDirection(direction);
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CameraActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CameraActivityTest.java
deleted file mode 100644
index 1f176af879..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CameraActivityTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.Activity;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on CameraActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class CameraActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<CameraActivity> mActivityRule = new ActivityTestRule<>(CameraActivity.class);
-
- private Activity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.cameraMapView);
- }
-}
-
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivityTest.java
deleted file mode 100644
index 68633547ed..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivityTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.Activity;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on CameraActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class CoordinateChangeActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<CoordinateChangeActivity> mActivityRule = new ActivityTestRule<>(CoordinateChangeActivity.class);
-
- private Activity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.mapView);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivityTest.java
deleted file mode 100644
index db014b69ac..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivityTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.Activity;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on DoubleMapActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class DoubleMapActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<DoubleMapActivity> mActivityRule = new ActivityTestRule<>(DoubleMapActivity.class);
-
- private Activity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.mapView);
- checkViewIsDisplayed(R.id.mini_map);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivityTest.java
deleted file mode 100644
index e507c6cd61..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivityTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.Activity;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on InfoWindowConcurrentActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class InfoWindowConcurrentActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<InfoWindowConcurrentActivity> mActivityRule = new ActivityTestRule<>(InfoWindowConcurrentActivity.class);
-
- private Activity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.infoWindowConcurrentMapView);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityScreenTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityScreenTest.java
deleted file mode 100644
index 7c56f4c874..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityScreenTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import com.mapbox.mapboxsdk.testapp.utils.DrawerUtils;
-import com.mapbox.mapboxsdk.testapp.utils.GestureUtils;
-import com.mapbox.mapboxsdk.testapp.utils.ScreenshotUtil;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.doubleClick;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-
-/**
- * Tests on MainActivity with screenshots
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class MainActivityScreenTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
- MainActivity.class);
-
- private MainActivity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.mainMapView);
- }
-
- @Test
- public void testStyleEmerald() {
- DrawerUtils.openDrawer();
- DrawerUtils.clickItem(R.string.styleEmerald);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- takeNamedScreenshot(mActivity, "testEmeraldStyle");
- }
-
- @Test
- public void testStyleStreets() {
- DrawerUtils.openDrawer();
- DrawerUtils.clickItem(R.string.styleMapboxStreets);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- takeNamedScreenshot(mActivity, "testStreetsStyle");
- }
-
- @Test
- public void testStyleDark() {
- DrawerUtils.openDrawer();
- DrawerUtils.clickItem(R.string.styleDark);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- takeNamedScreenshot(mActivity, "testDarkStyle");
- }
-
- @Test
- public void testStyleLight() {
- DrawerUtils.openDrawer();
- DrawerUtils.clickItem(R.string.styleLight);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- takeNamedScreenshot(mActivity, "testLightStyle");
- }
-
- @Test
- public void testStyleSatellite() {
- DrawerUtils.openDrawer();
- DrawerUtils.clickItem(R.string.styleSatellite);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- GestureUtils.doubleClickGesture(R.id.mainMapView);
- takeNamedScreenshot(mActivity, "testSatelliteStyle");
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityTest.java
deleted file mode 100644
index b9d00de089..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MainActivityTest.java
+++ /dev/null
@@ -1,257 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.action.ViewActions.doubleClick;
-import static android.support.test.espresso.action.ViewActions.longClick;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-import static org.hamcrest.Matchers.not;
-
-/**
- * Tests on MainActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class MainActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
- MainActivity.class);
-
- private MainActivity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- /*
- * Note that we need to keep the `test` prefix if we want to be able to run these
- * tests on AWS Device Farm, annotations are not enough:
- * https://github.com/awslabs/aws-device-farm-sample-app-for-android/issues/5#issuecomment-138258444
- */
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.mainMapView);
- }
-
- /*
- * Check UI ids are visible
- */
-
- @Test
- public void testDrawerLayoutIsDisplayed() {
- onView(withId(R.id.drawer_layout))
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testToolbarIsDisplayed() {
- onView(withId(R.id.toolbar))
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testContentFrameIsDisplayed() {
- onView(withId(R.id.content_frame))
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testViewFpsIsDisplayed() {
- // By default, R.id.view_fps is not displayed
- onView(withId(R.id.view_fps))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testLocationFABIsDisplayed() {
- onView(withId(R.id.locationFAB))
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testNavViewIsNotDisplayed() {
- // By default, nav_view not displayed
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewIsDisplayed() {
- // However, it's displayed when we click the home icon
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withId(R.id.nav_view))
- .check(matches(isDisplayed()));
- }
-
- /*
- * Some more tests on the map view (clicks, gestures)
- */
-
- @Test
- public void testClickMap() {
- onView(withId(R.id.mainMapView))
- .perform(click())
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testDoubleClickMap() {
- onView(withId(R.id.mainMapView))
- .perform(doubleClick())
- .check(matches(isDisplayed()));
- }
-
- @Test
- public void testLongClickMap() {
- onView(withId(R.id.mainMapView))
- .perform(longClick())
- .check(matches(isDisplayed()));
- }
-
- /*
- * Test the main drawer options
- */
-
- @Test
- public void testNavViewActionDebug() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.action_debug))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewActionPointAnnotations() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.action_point_annotations))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewActionCompass() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.action_compass))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewStyleMapboxStreets() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.styleMapboxStreets))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewStyleEmerald() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.styleEmerald))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewStyleLight() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.styleLight))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewStyleDark() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.styleDark))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- @Test
- public void testNavViewStyleSatellite() {
- onView(withContentDescription(HOME_BUTTON_STRING))
- .perform(click());
- onView(withText(R.string.styleSatellite))
- .perform(click());
-
- // Clicking the item closes the drawer
- onView(withId(R.id.nav_view))
- .check(matches(not(isDisplayed())));
- }
-
- /*
- * We can also check the map inner elements are visible
- */
-
- @Test
- public void testMapIconContentDescription() {
- // Mapbox logo
- onView(withContentDescription(mActivity.getResources()
- .getString(R.string.mapboxIconContentDescription)))
- .check(matches(isDisplayed()));
- }
-
-// @Test
-// public void testMapCompassContentDescription() {
-// //FIXME this is currently broken hence compass view is only being showed when rotating the map
-// // Map compass
-//// onView(withContentDescription(mActivity.getResources()
-//// .getString(R.string.compassContentDescription)))
-//// .check(matches(isDisplayed()));
-// }
-
- @Test
- public void testMapAttributionsIconContentDescription() {
- // Attribution icon
- onView(withContentDescription(mActivity.getResources()
- .getString(R.string.attributionsIconContentDescription)))
- .check(matches(isDisplayed()));
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivityTest.java
deleted file mode 100644
index eaa1584a3f..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivityTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.Activity;
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on MapboxMapActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class MapboxMapActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<MapboxMapActivity> mActivityRule = new ActivityTestRule<>(MapboxMapActivity.class);
-
- private Activity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.mapView);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivityTest.java
deleted file mode 100644
index ccb8354fc5..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivityTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.support.test.rule.ActivityTestRule;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.suitebuilder.annotation.LargeTest;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests on PressForMarkerActivity
- */
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class PressForMarkerActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<PressForMarkerActivity> mActivityRule = new ActivityTestRule<>(
- PressForMarkerActivity.class);
-
- private PressForMarkerActivity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- // we are adding mapview on the fly.. just validating if we have a toolbar
- checkViewIsDisplayed(R.id.secondToolBar);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/TiltActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/TiltActivityTest.java
deleted file mode 100644
index a38af03a61..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/TiltActivityTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.support.test.rule.ActivityTestRule;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class TiltActivityTest extends BaseTest {
-
- @Rule
- public ActivityTestRule<TiltActivity> mActivityRule = new ActivityTestRule<>(
- TiltActivity.class);
-
- private TiltActivity mActivity = null;
-
- @Before
- public void setActivity() {
- mActivity = mActivityRule.getActivity();
- }
-
- @Test
- public void testSanity() {
- checkViewIsDisplayed(R.id.tiltMapView);
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BaseTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BaseTest.java
index e432d5f576..e9292332d5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BaseTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BaseTest.java
@@ -1,8 +1,8 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
-import com.mapbox.mapboxsdk.testapp.utils.ScreenshotUtil;
+import com.mapbox.mapboxsdk.testapp.espresso.utils.ScreenshotUtil;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BulkMarkerActivityTest.java
index d66ae8f514..b85fe41243 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/BulkMarkerActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.BulkMarkerActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DirectionsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DirectionsActivityTest.java
index 3ce8d00aa0..a84345b14d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DirectionsActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DirectionsActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.directions.DirectionsActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DynamicMarkerChangeActivityTest.java
index b6feb8f1be..700da5e3bc 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/DynamicMarkerChangeActivityTest.java
@@ -1,10 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
-import com.mapbox.mapboxsdk.testapp.utils.ViewUtils;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.DynamicMarkerChangeActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.espresso.utils.ViewUtils;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/GeocoderActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/GeocoderActivityTest.java
index c1ca7413c2..9bd7a49b9c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/GeocoderActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/GeocoderActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.geocoding.GeocoderActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowActivityTest.java
index 9fb99fe262..feb0bb1a02 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowAdapterActivityTest.java
index 51bd163fc1..0c62387e36 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/InfoWindowAdapterActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowAdapterActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/LatLngBoundsActivityTest.java
index 057979aeb8..39e7e4766e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/LatLngBoundsActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.camera.LatLngBoundsActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ManualZoomActivityTest.java
index 8ce8498d64..5c88bd371a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ManualZoomActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.camera.ManualZoomActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapFragmentActivityTest.java
index e65860f4b2..d7522b2d7f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapFragmentActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.fragment.MapFragmentActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapPaddingActivityTest.java
index c252077856..fe6c4eb487 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MapPaddingActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.maplayout.MapPaddingActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MaxMinZoomActivityTest.java
index e93a7675f0..48152286e9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MaxMinZoomActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.camera.MaxMinZoomActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -29,6 +32,6 @@ public class MaxMinZoomActivityTest extends BaseTest {
@Test
public void testSanity() {
- checkViewIsDisplayed(R.id.manualZoomMapView);
+ checkViewIsDisplayed(R.id.mapView);
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MyLocationTrackingModeActivityTest.java
index b21cd070a6..ceda7cff2c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/MyLocationTrackingModeActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.userlocation.MyLocationTrackingModeActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -30,4 +33,4 @@ public class MyLocationTrackingModeActivityTest extends BaseTest {
public void testSanity() {
checkViewIsDisplayed(R.id.mapView);
}
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PolylineActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/PolylineActivityTest.java
index 653921497e..425d803952 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/PolylineActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/PolylineActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PolylineActivity;
+import com.mapbox.mapboxsdk.testapp.R;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScreenshotActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScreenshotActivityTest.java
new file mode 100644
index 0000000000..60649ad4ae
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScreenshotActivityTest.java
@@ -0,0 +1,124 @@
+package com.mapbox.mapboxsdk.testapp.espresso;
+
+import android.app.Activity;
+import android.support.test.espresso.Espresso;
+import android.support.test.espresso.IdlingPolicies;
+import android.support.test.espresso.IdlingResource;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.text.format.DateUtils;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.LatLngBoundsActivity;
+import com.mapbox.mapboxsdk.testapp.espresso.utils.ScreenshotUtil;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class
+ScreenshotActivityTest {
+
+ @Rule
+ public ActivityTestRule<LatLngBoundsActivity> mActivityRule = new ActivityTestRule<>(LatLngBoundsActivity.class);
+
+ private Activity mActivity = null;
+
+ @Before
+ public void setActivity() {
+ mActivity = mActivityRule.getActivity();
+
+ // Make sure Espresso does not time out
+ IdlingPolicies.setMasterPolicyTimeout(60, TimeUnit.SECONDS);
+ IdlingPolicies.setIdlingResourceTimeout(26, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testScreenshot() {
+ waitFor(DateUtils.SECOND_IN_MILLIS * 5, mActivity);
+ }
+
+ private static void waitFor(long waitingTime, Activity a) {
+ // Start
+ onView(withId(R.id.mapView)).perform(click());
+
+ // Make sure Espresso does not time out
+ IdlingPolicies.setMasterPolicyTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
+ IdlingPolicies.setIdlingResourceTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
+
+ // Now we wait
+ IdlingResource idlingResource = new ElapsedTimeIdlingResource(waitingTime);
+ Espresso.registerIdlingResources(idlingResource);
+
+ // Stop and verify
+ onView(withId(R.id.mapView)).perform(click());
+
+ ScreenshotUtil.take(a, "testing");
+
+ // Clean up
+ Espresso.unregisterIdlingResources(idlingResource);
+ }
+
+// @Test
+// public void takeScreenshot() {
+// // Start
+// checkViewIsDisplayed(R.id.mapView);
+//
+//
+// // Now we wait
+// IdlingResource idlingResource = new ElapsedTimeIdlingResource(4);
+// Espresso.registerIdlingResources(idlingResource);
+//
+// // We take a screenshot
+// ScreenshotUtil.take(mActivity, "test");
+//
+// // Clean up
+// Espresso.unregisterIdlingResources(idlingResource);
+// }
+
+// @Test
+// public void testSanity() {
+// checkViewIsDisplayed(R.id.mapView);
+// }
+
+ public static class ElapsedTimeIdlingResource implements IdlingResource {
+ private final long startTime;
+ private final long waitingTime;
+ private ResourceCallback resourceCallback;
+
+ public ElapsedTimeIdlingResource(long waitingTime) {
+ this.startTime = System.currentTimeMillis();
+ this.waitingTime = waitingTime;
+ }
+
+ @Override
+ public String getName() {
+ return ElapsedTimeIdlingResource.class.getName() + ":" + waitingTime;
+ }
+
+ @Override
+ public boolean isIdleNow() {
+ long elapsed = System.currentTimeMillis() - startTime;
+ boolean idle = (elapsed >= waitingTime);
+ if (idle) {
+ resourceCallback.onTransitionToIdle();
+ }
+ return idle;
+ }
+
+ @Override
+ public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
+ this.resourceCallback = resourceCallback;
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ScrollByActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScrollByActivityTest.java
index 05386b089e..c545bc6e04 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/ScrollByActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/ScrollByActivityTest.java
@@ -1,9 +1,12 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.camera.ScrollByActivity;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/SupportMapFragmentActivityTest.java
index 7ae03e0d07..e6c1cadf1e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/SupportMapFragmentActivityTest.java
@@ -1,10 +1,13 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.espresso;
import android.app.Activity;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.fragment.SupportMapFragmentActivity;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/DrawerUtils.java
index 8d8905fdf4..7143fa948f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/DrawerUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/DrawerUtils.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.utils;
+package com.mapbox.mapboxsdk.testapp.espresso.utils;
import android.support.annotation.StringRes;
import android.support.test.espresso.Espresso;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/GestureUtils.java
index 37c18399e4..e2807af5b5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/GestureUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/GestureUtils.java
@@ -1,9 +1,7 @@
-package com.mapbox.mapboxsdk.testapp.utils;
+package com.mapbox.mapboxsdk.testapp.espresso.utils;
import android.support.annotation.IdRes;
-import com.mapbox.mapboxsdk.testapp.R;
-
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.doubleClick;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ScreenshotUtil.java
index d25afec815..fdb06e52d8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ScreenshotUtil.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ScreenshotUtil.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.utils;
+package com.mapbox.mapboxsdk.testapp.espresso.utils;
import android.app.Activity;
import android.graphics.Bitmap;
@@ -43,15 +43,17 @@ public class ScreenshotUtil {
}
// Get a bitmap from the activity root view. When the drawing cache is enabled,
- // the next call to getDrawingCache() will draw the view in a bitmap.
+// // the next call to getDrawingCache() will draw the view in a bitmap.
View rootView = activity.getWindow().getDecorView().getRootView();
- rootView.setDrawingCacheEnabled(true);
- Bitmap bitmap = Bitmap.createBitmap(rootView.getDrawingCache());
- rootView.setDrawingCacheEnabled(false);
+// rootView.setDrawingCacheEnabled(true);r
+// rootView.setDrawingCacheEnabled(false);
+
+ Bitmap bitmap = null;
// Add the SurfaceView bit (see getAllTextureViews() below)
List<TextureView> tilingViews = getAllTextureViews(rootView);
if (tilingViews.size() > 0) {
+ bitmap = Bitmap.createBitmap(tilingViews.get(0).getHeight(),tilingViews.get(0).getWidth(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
for (TextureView TextureView : tilingViews) {
Bitmap b = TextureView.getBitmap(TextureView.getWidth(), TextureView.getHeight());
@@ -59,7 +61,7 @@ public class ScreenshotUtil {
TextureView.getLocationInWindow(location);
int[] location2 = new int[2];
TextureView.getLocationOnScreen(location2);
- canvas.drawBitmap(b, location[0], location[1], null);
+ canvas.drawBitmap(b, 0,0, null);
}
}
@@ -71,7 +73,8 @@ public class ScreenshotUtil {
outputStream = new FileOutputStream(outputFile);
bitmap.compress(DEFAULT_IMAGE_FORMAT, DEFAULT_IMAGE_QUALITY, outputStream);
outputStream.flush();
- } catch (IOException e) {
+ } catch (Exception e) {
+
e.printStackTrace();
} finally {
if (outputStream != null) {
@@ -122,7 +125,10 @@ public class ScreenshotUtil {
}
String externalPath = Environment.getExternalStorageDirectory().toString();
- String path = externalPath + File.separator + SCREENSHOT_FOLDER + File.separator + filename;
+ String path = externalPath + File.separator + SCREENSHOT_FOLDER;
+ File dir = new File(path);
+ dir.mkdirs();
+ path += File.separator + filename;
Log.d(LOG_TAG, "Screenshot path: " + path);
return path;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ViewUtils.java
index 01ee3e9b9f..6611c83545 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/ViewUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/espresso/utils/ViewUtils.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.utils;
+package com.mapbox.mapboxsdk.testapp.espresso.utils;
import android.support.annotation.IdRes;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/BaseMainActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/BaseMainActivityTest.java
new file mode 100644
index 0000000000..0eedca5458
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/BaseMainActivityTest.java
@@ -0,0 +1,46 @@
+package com.mapbox.mapboxsdk.testapp.robotium;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PolygonActivity;
+import com.mapbox.mapboxsdk.testapp.activity.annotation.PolylineActivity;
+import com.mapbox.mapboxsdk.testapp.activity.infowindow.InfoWindowActivity;
+import com.robotium.solo.Solo;
+
+import org.junit.Test;
+
+public abstract class BaseMainActivityTest{
+//
+//} extends ActivityInstrumentationTestCase2<InfoWindowActivity> {
+//
+// protected Solo solo;
+// protected MapView mapView;
+// protected MapboxMap mapboxMap;
+//
+// public BaseMainActivityTest() {
+// super(InfoWindowActivity.class);
+// }
+//
+// @Override
+// public void setUp() throws Exception {
+// solo = new Solo(getInstrumentation(), getActivity());
+// mapView = (MapView) solo.getView(R.id.mapView);
+// mapboxMap = MapboxMapUtils.getMapboxMap(mapView);
+// }
+//
+// @Override
+// public void tearDown() throws Exception {
+// solo.finishOpenedActivities();
+// }
+//
+// @Test
+// public void testSanity() throws Exception {
+// assertNotNull("Should be non null", solo);
+// assertNotNull("Should be non null", mapView);
+// assertNotNull("Should be non null", mapboxMap);
+// }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/CompassViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/CompassViewTest.java
new file mode 100644
index 0000000000..9990d71d67
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/CompassViewTest.java
@@ -0,0 +1,48 @@
+package com.mapbox.mapboxsdk.testapp.robotium;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.widgets.CompassView;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.robotium.utils.ViewAssertion;
+
+import org.junit.Test;
+
+public class CompassViewTest {
+// extends
+//} BaseMainActivityTest {
+//
+// private CompassView compassView;
+//
+// @Override
+// public void setUp() throws Exception {
+// super.setUp();
+// compassView = (CompassView) solo.getView(R.id.compassView);
+// }
+//
+//// @Test
+//// public void testCompass() {
+//// setCameraDirection(0);
+//// solo.sleep(200);
+//// ViewAssertion.isInvisible(compassView);
+//// }
+//
+// @Test
+// public void testCompassClick() throws Exception {
+// setCameraDirection(20);
+// solo.sleep(200);
+// ViewAssertion.isVisible(compassView);
+// solo.clickOnView(compassView);
+// solo.sleep(200);
+// ViewAssertion.isVisible(compassView);
+// }
+//
+// private void setCameraDirection(float bearing) {
+// mapboxMap.setCameraPosition(new CameraPosition.Builder()
+// .target(new LatLng(0, 0))
+// .tilt(0)
+// .zoom(15)
+// .bearing(bearing)
+// .build());
+// }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleRotateTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleRotateTest.java
new file mode 100644
index 0000000000..8d1feed6ff
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleRotateTest.java
@@ -0,0 +1,29 @@
+package com.mapbox.mapboxsdk.testapp.robotium;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.MapboxMapUtils;
+
+import org.junit.Test;
+
+public class SimpleRotateTest {
+// extends
+//} BaseMainActivityTest {
+//
+// @Override
+// public void setUp() throws Exception {
+// super.setUp();
+// }
+//
+// @Test
+// public void testRotate() {
+// mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(47.376271, 8.539116), 15));
+// double rotation = 0;
+// for (int i = 0; i < 180; i++) {
+// rotation += 1;
+// MapboxMapUtils.setDirection(mapView, rotation);
+// solo.sleep(100);
+// }
+// }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleZoomTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleZoomTest.java
new file mode 100644
index 0000000000..bc8e9caac0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/SimpleZoomTest.java
@@ -0,0 +1,28 @@
+package com.mapbox.mapboxsdk.testapp.robotium;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+import org.junit.Test;
+
+public class SimpleZoomTest {
+// extends
+//} BaseMainActivityTest {
+//
+// @Override
+// public void setUp() throws Exception {
+// super.setUp();
+// }
+//
+// @Test
+// public void testZoomIn() {
+// float currentZoomlevel = MapboxConstants.MINIMUM_ZOOM;
+// while (currentZoomlevel < MapboxConstants.MAXIMUM_ZOOM - 5) {
+// mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(47.376271, 8.539116),currentZoomlevel));
+// currentZoomlevel++;
+// solo.sleep(1400);
+// }
+// }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/utils/ViewAssertion.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/utils/ViewAssertion.java
new file mode 100644
index 0000000000..74410cce50
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/robotium/utils/ViewAssertion.java
@@ -0,0 +1,17 @@
+package com.mapbox.mapboxsdk.testapp.robotium.utils;
+
+import android.view.View;
+
+import static junit.framework.Assert.assertEquals;
+
+public class ViewAssertion {
+
+ public static void isVisible(View view) {
+ assertEquals(view.getClass().getSimpleName() + " should be visible", view.getVisibility(), View.VISIBLE);
+ }
+
+ public static void isInvisible(View view) {
+ assertEquals(view.getClass().getSimpleName() + " should be visible", view.getVisibility(), View.INVISIBLE);
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 0d2b78acf8..7268b7d551 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:name=".MapboxApplication"
@@ -16,93 +17,252 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
- android:name=".MainActivity"
+ android:name=".activity.FeatureOverviewActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
<activity
- android:name=".MapboxMapActivity"
- android:label="@string/action_mapboxmap" />
+ android:name=".activity.infowindow.InfoWindowActivity"
+ android:description="@string/description_info_window"
+ android:label="@string/activity_info_window">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_infowindow" />
+ </activity>
<activity
- android:name=".LatLngBoundsActivity"
- android:label="@string/activity_visible_coordinate_bounds" />
+ android:name=".activity.infowindow.InfoWindowAdapterActivity"
+ android:description="@string/description_info_window_adapter"
+ android:label="@string/activity_infowindow_adapter">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_infowindow" />
+ </activity>
<activity
- android:name=".InfoWindowAdapterActivity"
- android:label="@string/activity_infowindow_adapter" />
+ android:name=".activity.annotation.BulkMarkerActivity"
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:description="@string/description_add_bulk_markers"
+ android:label="@string/activity_add_bulk_markers">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
<activity
- android:name=".InfoWindowActivity"
- android:label="@string/activity_info_window" />
+ android:name=".activity.annotation.AnimatedMarkerActivity"
+ android:description="@string/description_animated_marker"
+ android:label="@string/activity_animated_marker">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
<activity
- android:name=".InfoWindowConcurrentActivity"
- android:label="@string/activity_info_window_concurrent" />
+ android:name=".activity.annotation.DynamicMarkerChangeActivity"
+ android:description="@string/description_dynamic_marker"
+ android:label="@string/activity_dynamic_marker">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
+ <activity android:name=".activity.annotation.PressForMarkerActivity"
+ android:description="@string/description_press_for_marker"
+ android:label="@string/activity_press_for_marker">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
<activity
- android:name=".BulkMarkerActivity"
- android:configChanges="orientation|keyboardHidden|screenSize"
- android:label="@string/activity_add_bulk_markers" />
+ android:name=".activity.camera.CameraAnimationTypeActivity"
+ android:description="@string/description_camera_animation_types"
+ android:label="@string/activity_camera_animation_types">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".CameraActivity"
- android:label="@string/activity_camera" />
+ android:name=".activity.camera.CameraPositionActivity"
+ android:description="@string/description_cameraposition"
+ android:label="@string/activity_camera_position">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".TiltActivity"
- android:label="@string/activity_tilt" />
+ android:name=".activity.camera.LatLngBoundsActivity"
+ android:description="@string/description_visible_bounds"
+ android:screenOrientation="portrait"
+ android:label="@string/activity_visible_coordinate_bounds">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".MapFragmentActivity"
- android:label="@string/activity_map_fragment" />
+ android:name=".activity.fragment.MapFragmentActivity"
+ android:description="@string/description_map_fragment"
+ android:label="@string/activity_map_fragment">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_fragment" />
+ </activity>
<activity
- android:name=".SupportMapFragmentActivity"
- android:label="@string/activity_map_fragment_suport" />
+ android:name=".activity.fragment.SupportMapFragmentActivity"
+ android:description="@string/description_map_fragment_support"
+ android:label="@string/activity_map_fragment_suport">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_fragment" />
+ </activity>
<activity
- android:name=".PressForMarkerActivity"
- android:label="@string/activity_press_for_marker" />
+ android:name=".activity.camera.ManualZoomActivity"
+ android:description="@string/description_camera_zoom"
+ android:label="@string/activity_camera_zoom">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".ManualZoomActivity"
- android:label="@string/action_manual_zoom" />
+ android:name=".activity.camera.MaxMinZoomActivity"
+ android:description="@string/description_minmax_zoom"
+ android:label="@string/activity_minmax_zoom">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".MaxMinZoomActivity"
- android:label="@string/action_minmax_zoom" />
+ android:name=".activity.customlayer.CustomLayerActivity"
+ android:description="@string/description_custom_layer"
+ android:label="@string/activity_custom_layer">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_custom_layer" />
+ </activity>
<activity
- android:name=".MyLocationTrackingModeActivity"
- android:label="@string/activity_user_tracking_mode" />
+ android:name=".activity.userlocation.MyLocationTrackingModeActivity"
+ android:description="@string/description_user_location_tracking"
+ android:label="@string/activity_user_tracking_mode">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_userlocation" />
+ </activity>
<activity
- android:name=".PolylineActivity"
- android:label="@string/activity_polyline" />
+ android:name=".activity.userlocation.MyLocationDrawableActivity"
+ android:description="@string/description_user_location_customization"
+ android:label="@string/activity_user_tracking_customization">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_userlocation" />
+ </activity>
<activity
- android:name=".CoordinateChangeActivity"
- android:label="@string/activity_animate_coordinate_change" />
+ android:name=".activity.userlocation.MyLocationTintActivity"
+ android:description="@string/description_user_location_dot_color"
+ android:label="@string/activity_user_dot_color">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_userlocation" />
+ </activity>
<activity
- android:name=".DirectionsActivity"
- android:label="@string/activity_directions" />
+ android:name=".activity.userlocation.MyLocationToggleActivity"
+ android:description="@string/description_user_location_toggle"
+ android:label="@string/activity_user_location_toggle">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_userlocation" />
+ </activity>
<activity
- android:name=".GeocoderActivity"
- android:label="@string/activity_geocoder" />
+ android:name=".activity.annotation.PolygonActivity"
+ android:description="@string/description_polygon"
+ android:label="@string/activity_polygon">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
+
<activity
- android:name=".DoubleMapActivity"
- android:label="@string/activity_double_map" />
+ android:name=".activity.annotation.PolylineActivity"
+ android:description="@string/description_polyline"
+ android:label="@string/activity_polyline">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
+ <activity
+ android:name=".activity.directions.DirectionsActivity"
+ android:description="@string/description_directions"
+ android:label="@string/activity_directions">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_directions" />
+ </activity>
<activity
- android:name=".ScrollByActivity"
- android:label="@string/activity_scroll_by" />
+ android:name=".activity.geocoding.GeocoderActivity"
+ android:description="@string/description_geocoder"
+ android:label="@string/activity_geocoder">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_geocoding" />
+ </activity>
<activity
- android:name=".DynamicMarkerChangeActivity"
- android:label="@string/activity_dynamic_marker" />
+ android:name=".activity.camera.ScrollByActivity"
+ android:description="@string/description_scroll_by"
+ android:label="@string/activity_scroll_by">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
+ </activity>
<activity
- android:name=".MapPaddingActivity"
+ android:name=".activity.maplayout.MapPaddingActivity"
+ android:description="@string/description_map_padding"
android:label="@string/activity_map_padding"
- android:screenOrientation="portrait" />
+ android:screenOrientation="portrait">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout" />
+ </activity>
+ <activity
+ android:name=".activity.maplayout.DebugModeActivity"
+ android:description="@string/description_debug_mode"
+ android:label="@string/activity_debug_mode">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout" />
+ </activity>
<activity
- android:name=".OfflineActivity"
- android:label="@string/activity_offline" />
+ android:name=".activity.offline.OfflineActivity"
+ android:description="@string/description_offline"
+ android:label="@string/activity_offline">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_offline" />
+ </activity>
+ <activity
+ android:name=".activity.imagegenerator.SnapshotActivity"
+ android:description="@string/description_snapshot"
+ android:label="@string/activity_snapshot">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_imagegenerator" />
+ </activity>
<activity
- android:name=".AnimatedMarkerActivity"
- android:label="@string/title_activity_animated_marker" />
+ android:name=".activity.maplayout.DoubleMapActivity"
+ android:description="@string/description_doublemap"
+ android:label="@string/activity_double_map">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_maplayout" />
+ </activity>
- <!-- Configuration Settings -->
- <meta-data
- android:name="com.mapbox.AccessToken"
- android:value="" />
+ <activity
+ android:name=".activity.annotation.MarkerViewActivity"
+ android:description="@string/description_view_marker"
+ android:label="@string/activity_view_marker">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_annotation" />
+ </activity>
+ <!-- Configuration Settings -->
<meta-data
android:name="com.mapbox.TestEventsServer"
android:value="https://cloudfront-staging.tilestream.net" />
@@ -112,7 +272,6 @@
<service android:name="com.mapbox.mapboxsdk.telemetry.TelemetryService" />
-
</application>
</manifest>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttf b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttf
new file mode 100644
index 0000000000..a3c1a1f170
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Medium.ttf
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttf b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttf
new file mode 100644
index 0000000000..0e58508a64
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/assets/Roboto-Regular.ttf
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java
deleted file mode 100644
index 9381992bb4..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
-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.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-import org.json.JSONException;
-
-import java.io.IOException;
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-public class BulkMarkerActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
-
- private MapboxMap mMapboxMap;
- private MapView mMapView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_marker_bulk);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayShowTitleEnabled(false);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(38.87031, -77.00897))
- .zoom(10)
- .build()
- ));
-
- ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(actionBar.getThemedContext(), R.array.bulk_marker_list, android.R.layout.simple_spinner_item);
- spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
- Spinner spinner = (Spinner) findViewById(R.id.spinner);
- spinner.setAdapter(spinnerAdapter);
- spinner.setOnItemSelectedListener(BulkMarkerActivity.this);
- }
- });
-
- }
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- int markersAmount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
- new LoadBulkMarkerTask(this, mMapboxMap, markersAmount).execute();
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // nothing selected, nothing to do!
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- private static class LoadBulkMarkerTask extends AsyncTask<Void, Integer, List<MarkerOptions>> {
-
- private static final String TAG = "LoadBulkMarkerTask";
- private MapboxMap mMapboxMap;
- private Context mAppContext;
- private ProgressDialog mProgressDialog;
- private int mAmount;
-
- public LoadBulkMarkerTask(Context context, MapboxMap mapboxMap, int amount) {
- mMapboxMap = mapboxMap;
- mapboxMap.removeAnnotations();
- mProgressDialog = ProgressDialog.show(context, "Loading", "Fetching markers", false);
- mAppContext = context.getApplicationContext();
- mAmount = amount;
- }
-
- @Override
- protected List<MarkerOptions> doInBackground(Void... params) {
- List<MarkerOptions> markerOptions = new ArrayList<>(mAmount);
- try {
- DecimalFormat formatter = new DecimalFormat("#.#####");
- String json = GeoParseUtil.loadStringFromAssets(mAppContext, "points.geojson");
- List<LatLng> locations = GeoParseUtil.parseGeoJSONCoordinates(json);
-
- if (locations.size() < mAmount) {
- mAmount = locations.size();
- }
-
- LatLng location;
- for (int i = 0; i < mAmount; i++) {
- location = locations.get(i);
- markerOptions.add(new MarkerOptions()
- .position(location)
- .title("Marker")
- .snippet(formatter.format(location.getLatitude()) + ", " + formatter.format(location.getLongitude())));
- }
-
- } catch (IOException | JSONException e) {
- Log.e(TAG, "Could not add markers,", e);
- }
- return markerOptions;
- }
-
- @Override
- protected void onProgressUpdate(Integer... values) {
- super.onProgressUpdate(values);
- }
-
- @Override
- protected void onPostExecute(List<MarkerOptions> markerOptions) {
- super.onPostExecute(markerOptions);
- mMapboxMap.addMarkers(markerOptions);
- mProgressDialog.hide();
- }
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java
deleted file mode 100644
index d857d665bd..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-import android.widget.Toast;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-import java.text.DecimalFormat;
-
-public class InfoWindowActivity extends AppCompatActivity {
-
- private MapView mMapView;
- private Marker mCustomMarker;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- mapboxMap.addMarker(new MarkerOptions()
- .title("Intersection")
- .snippet("H St NW with 15th St NW")
- .position(new LatLng(38.9002073, -77.03364419)));
-
- Marker marker = mapboxMap.addMarker(new MarkerOptions()
- .title("White House")
- .snippet("The official residence and principal workplace of the President of the United States, located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every U.S. president since John Adams in 1800.")
- .position(new LatLng(38.897705003219784, -77.03655168667463)));
-
- // open InfoWindow at startup!
- mapboxMap.selectMarker(marker);
-
- mapboxMap.addMarker(new MarkerOptions().title("Intersection")
- .snippet("E St NW with 17th St NW")
- .position(new LatLng(38.8954236, -77.0394623)));
-
- mapboxMap.setOnInfoWindowCloseListener(new MapboxMap.OnInfoWindowCloseListener() {
- @Override
- public void onInfoWindowClose(Marker marker) {
- Toast.makeText(getApplicationContext(), "OnClose: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- }
- });
-
- final DecimalFormat formatter = new DecimalFormat("#.#####");
- mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- // Remove previous added marker
- if (mCustomMarker != null) {
- mapboxMap.removeAnnotation(mCustomMarker);
- mCustomMarker = null;
- }
-
- // Add marker on long click location with default marker image
- mCustomMarker = mapboxMap.addMarker(new MarkerOptions()
- .title("Custom Marker")
- .snippet(formatter.format(point.getLatitude()) + ", " + formatter.format(point.getLongitude()))
- .position(point));
- }
- });
-
-
- mapboxMap.setOnInfoWindowClickListener(new MapboxMap.OnInfoWindowClickListener() {
- @Override
- public boolean onInfoWindowClick(@NonNull Marker marker) {
- Toast.makeText(getApplicationContext(), "OnClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- // return false to close the info window
- // return true to leave the info window open
- return false;
- }
- });
-
- mapboxMap.setOnInfoWindowLongClickListener(new MapboxMap.OnInfoWindowLongClickListener() {
- @Override
- public void onInfoWindowLongClick(Marker marker) {
- Toast.makeText(getApplicationContext(), "OnLongClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
- }
- });
-
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java
deleted file mode 100644
index 56aa965025..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.TextView;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.annotations.Icon;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.IconFactory;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.annotations.CityStateMarker;
-import com.mapbox.mapboxsdk.testapp.annotations.CityStateMarkerOptions;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-public class InfoWindowAdapterActivity extends AppCompatActivity {
-
- private MapView mMapView;
- private IconFactory mIconFactory;
- private Drawable mIconDrawable;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow_adapter);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
-
- mIconFactory = IconFactory.getInstance(this);
- mIconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
-
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- // add markers
- mapboxMap.addMarker(generateCityStateMarker("Andorra", 42.505777, 1.52529, "#F44336"));
- mapboxMap.addMarker(generateCityStateMarker("Luxembourg", 49.815273, 6.129583, "#3F51B5"));
- mapboxMap.addMarker(generateCityStateMarker("Monaco", 43.738418, 7.424616, "#673AB7"));
- mapboxMap.addMarker(generateCityStateMarker("Vatican City", 41.902916, 12.453389, "#009688"));
- mapboxMap.addMarker(generateCityStateMarker("San Marino", 43.942360, 12.457777, "#795548"));
- mapboxMap.addMarker(generateCityStateMarker("Liechtenstein", 47.166000, 9.555373, "#FF5722"));
-
- // add custom window adapter
- mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
-
- private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
-
- @Override
- public View getInfoWindow(@NonNull Marker marker) {
- TextView textView = new TextView(InfoWindowAdapterActivity.this);
- textView.setText(marker.getTitle());
- textView.setTextColor(Color.WHITE);
-
- if(marker instanceof CityStateMarker){
- CityStateMarker cityStateMarker = (CityStateMarker)marker;
- textView.setBackgroundColor(Color.parseColor(cityStateMarker.getInfoWindowBackgroundColor()));
- }
-
- textView.setPadding(tenDp, tenDp, tenDp, tenDp);
- return textView;
- }
- });
- }
- });
- }
-
- private CityStateMarkerOptions generateCityStateMarker(String title, double lat, double lng, String color) {
- CityStateMarkerOptions marker = new CityStateMarkerOptions();
- marker.title(title);
- marker.position(new LatLng(lat, lng));
- marker.infoWindowBackground(color);
-
- mIconDrawable.setColorFilter(Color.parseColor(color), PorterDuff.Mode.SRC_IN);
- Icon icon = mIconFactory.fromDrawable(mIconDrawable);
- marker.icon(icon);
- return marker;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java
deleted file mode 100644
index 6fa5be3ce6..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java
+++ /dev/null
@@ -1,101 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-
-import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-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.utils.ApiAccess;
-
-public class InfoWindowConcurrentActivity extends AppCompatActivity {
-
- private MapView mMapView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_infowindow_concurrent);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.infoWindowConcurrentMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(true);
-
- mapboxMap.addMarker(new MarkerOptions()
- .title("Intersection")
- .snippet("H St NW with 15th St NW")
- .position(new LatLng(38.9002073, -77.03364419)));
-
- mapboxMap.addMarker(new MarkerOptions()
- .title("White House")
- .snippet("The official residence and principal workplace of the President of the United States, located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every U.S. president since John Adams in 1800.")
- .position(new LatLng(38.897705003219784, -77.03655168667463)));
-
- mapboxMap.addMarker(new MarkerOptions().title("Intersection")
- .snippet("E St NW with 17th St NW")
- .position(new LatLng(38.8954236, -77.0394623)));
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java
deleted file mode 100644
index 17bf767264..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java
+++ /dev/null
@@ -1,685 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.Manifest;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.graphics.Color;
-import android.location.Location;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.design.widget.CoordinatorLayout;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.NavigationView;
-import android.support.design.widget.Snackbar;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.view.GravityCompat;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.util.Log;
-import android.view.MenuItem;
-import android.view.View;
-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.annotations.PolygonOptions;
-import com.mapbox.mapboxsdk.annotations.PolylineOptions;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.constants.MyBearingTracking;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
-import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.layers.CustomLayer;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.layers.ExampleCustomLayer;
-import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MainActivity extends AppCompatActivity {
-
- private static final String TAG = "MainActivity";
-
- //
- // Static members
- //
-
- // Used for saving instance state
- private static final String STATE_IS_ANNOTATIONS_ON = "isAnnotationsOn";
- private static final String STATE_SELECTED_STYLE = "selectedStyle";
- private static final String STATE_MARKER_LIST = "markerList";
-
- // Used for permissions requests
- private static final int PERMISSIONS_LOCATION = 0;
- private static final int PERMISSIONS_TRACKING_MODE_ACTIVITY = 1;
-
- // Used for info window
- private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
-
- //
- // Instance members
- //
-
- // Used for the UI
- private DrawerLayout mDrawerLayout;
- private MapView mMapView;
- private MapboxMap mMapboxMap;
- private TextView mFpsTextView;
- private int mSelectedStyle = R.id.actionStyleMapboxStreets;
- private NavigationView mNavigationView;
- private CoordinatorLayout mCoordinatorLayout;
- private boolean mIsShowingCustomLayer;
-
- // Used for GPS
- private FloatingActionButton mLocationFAB;
-
- // Used for Annotations
- private boolean mIsAnnotationsOn = false;
- private ArrayList<MarkerOptions> mMarkerList = new ArrayList<>();
-
- //
- // Lifecycle events
- //
-
- // Called when activity is created
- @Override
- protected void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // Load the layout
- setContentView(R.layout.activity_main);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- final ActionBar ab = getSupportActionBar();
- if (ab != null) {
- ab.setHomeAsUpIndicator(R.drawable.ic_menu_24dp);
- ab.setDisplayHomeAsUpEnabled(true);
- }
-
- mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-
- mNavigationView = (NavigationView) findViewById(R.id.nav_view);
- if (mNavigationView != null) {
- setupDrawerContent(mNavigationView);
- }
-
- mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout);
-
- mFpsTextView = (TextView) findViewById(R.id.view_fps);
- mFpsTextView.setText("");
-
- mLocationFAB = (FloatingActionButton) findViewById(R.id.locationFAB);
- mLocationFAB.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // Toggle GPS position updates
- if (mMapboxMap != null) {
- toggleGps(!mMapboxMap.isMyLocationEnabled());
- }
- }
- });
-
- mMapView = (MapView) findViewById(R.id.mainMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- changeMapStyle(mSelectedStyle);
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
-
- mMapboxMap.setOnFpsChangedListener(new MyOnFpsChangedListener());
-
- // add location listener to MapboxMap
- mapboxMap.setOnMyLocationChangeListener(new MapboxMap.OnMyLocationChangeListener() {
- @Override
- public void onMyLocationChange(@Nullable Location location) {
- String desc = "Loc Chg: ";
- boolean noInfo = true;
- if (location.hasSpeed()) {
- desc += String.format("Spd = %.1f km/h ", location.getSpeed() * 3.6f);
- noInfo = false;
- }
- if (location.hasAltitude()) {
- desc += String.format("Alt = %.0f m ", location.getAltitude());
- noInfo = false;
- }
- if (noInfo) {
- desc += "No extra info";
- }
- Snackbar.make(mCoordinatorLayout, desc, Snackbar.LENGTH_SHORT).show();
- }
- });
-
- // Set default UI state
- mNavigationView.getMenu().findItem(R.id.action_compass).setChecked(mapboxMap.getUiSettings().isCompassEnabled());
- mNavigationView.getMenu().findItem(R.id.action_debug).setChecked(mapboxMap.isDebugActive());
- mNavigationView.getMenu().findItem(R.id.action_markers).setChecked(mIsAnnotationsOn);
- toggleGps(mapboxMap.isMyLocationEnabled());
-
- // Listeners
- mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- MarkerOptions marker = new MarkerOptions()
- .position(point)
- .title("Dropped Pin")
- .snippet(LAT_LON_FORMATTER.format(point.getLatitude()) + ", " +
- LAT_LON_FORMATTER.format(point.getLongitude()))
- .icon(null);
-
- mMarkerList.add(marker);
- mapboxMap.addMarker(marker);
- }
- });
-
- // Restore saved state
- if (savedInstanceState != null) {
- mIsAnnotationsOn = savedInstanceState.getBoolean(STATE_IS_ANNOTATIONS_ON);
- mSelectedStyle = savedInstanceState.getInt(STATE_SELECTED_STYLE);
- mMarkerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
- mapboxMap.addMarkers(mMarkerList);
- }
-
- mMapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
- @Override
- public boolean onMarkerClick(@NonNull Marker marker) {
- Snackbar.make(mCoordinatorLayout, "Marker Click Listener for " + marker.getTitle(), Snackbar.LENGTH_SHORT).show();
- return false;
- }
- });
-
- mMapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
- @Override
- public void onMapClick(@NonNull LatLng point) {
- String location = LAT_LON_FORMATTER.format(point.getLatitude()) + ", " +
- LAT_LON_FORMATTER.format(point.getLongitude());
- Snackbar.make(mCoordinatorLayout, "Map Click Listener " + location, Snackbar.LENGTH_SHORT).show();
- }
- });
-
- mMapboxMap.setOnInfoWindowClickListener(new MapboxMap.OnInfoWindowClickListener() {
- @Override
- public boolean onInfoWindowClick(@NonNull Marker marker) {
- Snackbar.make(mCoordinatorLayout, "InfoWindow Click Listener for " + marker.getTitle(), Snackbar.LENGTH_SHORT).show();
- marker.hideInfoWindow();
- return true;
- }
- });
-
-
- mMapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
- @Override
- public void onCameraChange(CameraPosition position) {
- Log.v(TAG, "OnCameraChange : " + position);
- }
- });
-
- }
- });
- }
-
- @Override
- protected void onStart() {
- super.onStart();
-
- // We need to recheck permissions in case user revoked them via settings app
- if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) ||
- (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- toggleGps(false);
- }
- }
-
- // Called when our app comes into the foreground
- @Override
- public void onResume() {
- super.onResume();
-
- mMapView.onResume();
- }
-
- // Called when our app goes into the background
- @Override
- public void onPause() {
- super.onPause();
-
- mMapView.onPause();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- mMapView.onDestroy();
- }
-
- // Called when we need to save instance state
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
-
- mMapView.onSaveInstanceState(outState);
- outState.putBoolean(STATE_IS_ANNOTATIONS_ON, mIsAnnotationsOn);
- outState.putInt(STATE_SELECTED_STYLE, mSelectedStyle);
- outState.putParcelableArrayList(STATE_MARKER_LIST, mMarkerList);
- }
-
- // Called when the system is running low on memory
- @Override
- public void onLowMemory() {
- super.onLowMemory();
-
- mMapView.onLowMemory();
- }
-
- //
- // Other events
- //
-
- // Called when pressing action bar items
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- mDrawerLayout.openDrawer(GravityCompat.START);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
- switch (requestCode) {
- case PERMISSIONS_LOCATION:
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- toggleGps(true);
- }
- break;
-
- case PERMISSIONS_TRACKING_MODE_ACTIVITY:
- if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- startActivity(new Intent(getApplicationContext(), MyLocationTrackingModeActivity.class));
- }
- break;
- }
- }
-
- private void setupDrawerContent(NavigationView navigationView) {
- navigationView.setNavigationItemSelectedListener(
- new NavigationView.OnNavigationItemSelectedListener() {
- @Override
- public boolean onNavigationItemSelected(MenuItem menuItem) {
- mDrawerLayout.closeDrawers();
-
- // Respond To Selection
- switch (menuItem.getItemId()) {
-
- case R.id.action_debug:
- // Cycle map debug options
- mMapboxMap.cycleDebugOptions();
- toggleFpsCounter(mMapboxMap.isDebugActive());
- return true;
-
- case R.id.action_markers:
- // Toggle markers
- toggleAnnotations(!mIsAnnotationsOn);
- return true;
-
- case R.id.action_compass:
- // Toggle compass
- UiSettings uiSettings = mMapboxMap.getUiSettings();
- uiSettings.setCompassEnabled(!uiSettings.isCompassEnabled());
- return true;
-
- case R.id.action_mapboxmap:
- startActivity(new Intent(getApplicationContext(), MapboxMapActivity.class));
- return true;
-
- case R.id.action_info_window_adapter:
- startActivity(new Intent(getApplicationContext(), InfoWindowAdapterActivity.class));
- return true;
-
- case R.id.action_camera:
- startActivity(new Intent(getApplicationContext(), CameraActivity.class));
- return true;
-
- case R.id.action_tilt:
- startActivity(new Intent(getApplicationContext(), TiltActivity.class));
- return true;
-
- case R.id.action_map_fragment:
- startActivity(new Intent(getApplicationContext(), MapFragmentActivity.class));
- return true;
-
- case R.id.action_support_map_fragment:
- startActivity(new Intent(getApplicationContext(), SupportMapFragmentActivity.class));
- return true;
-
- case R.id.action_press_for_marker:
- startActivity(new Intent(getApplicationContext(), PressForMarkerActivity.class));
- return true;
-
- case R.id.action_manual_zoom:
- startActivity(new Intent(getApplicationContext(), ManualZoomActivity.class));
- return true;
-
- case R.id.action_minmax_zoom:
- startActivity(new Intent(getApplicationContext(), MaxMinZoomActivity.class));
- return true;
-
- case R.id.action_coordinate_change:
- startActivity(new Intent(getApplicationContext(), CoordinateChangeActivity.class));
- return true;
-
- case R.id.action_bulk_markers:
- startActivity(new Intent(getApplicationContext(), BulkMarkerActivity.class));
- return true;
-
- case R.id.action_info_window:
- startActivity(new Intent(getApplicationContext(), InfoWindowActivity.class));
- return true;
-
- case R.id.action_info_window_concurrent:
- startActivity(new Intent(getApplicationContext(), InfoWindowConcurrentActivity.class));
- return true;
-
- case R.id.action_visible_bounds:
- startActivity(new Intent(getApplicationContext(), LatLngBoundsActivity.class));
- return true;
-
- case R.id.action_user_tracking_mode:
- if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) ||
- (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(MainActivity.this,
- new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
- PERMISSIONS_TRACKING_MODE_ACTIVITY);
- } else {
- startActivity(new Intent(getApplicationContext(), MyLocationTrackingModeActivity.class));
- }
- return true;
-
- case R.id.action_polyline:
- startActivity(new Intent(getApplicationContext(), PolylineActivity.class));
- return true;
-
- case R.id.action_custom_layer:
- if (mIsShowingCustomLayer) {
- removeCustomLayer();
- } else {
- addCustomLayer();
- }
- return true;
-
- case R.id.action_directions:
- startActivity(new Intent(getApplicationContext(), DirectionsActivity.class));
- return true;
-
- case R.id.action_double_mapview:
- if ((ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) ||
- (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(MainActivity.this,
- new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
- PERMISSIONS_TRACKING_MODE_ACTIVITY);
- } else {
- startActivity(new Intent(getApplicationContext(), DoubleMapActivity.class));
- }
- return true;
-
- case R.id.action_geocoder:
- startActivity(new Intent(getApplicationContext(), GeocoderActivity.class));
- return true;
-
- case R.id.action_scroll_by:
- startActivity(new Intent(getApplicationContext(), ScrollByActivity.class));
- return true;
-
- case R.id.action_dynamic_marker:
- startActivity(new Intent(getApplicationContext(), DynamicMarkerChangeActivity.class));
- return true;
-
- case R.id.action_map_padding:
- startActivity(new Intent(getApplicationContext(), MapPaddingActivity.class));
- return true;
-
- case R.id.action_offline:
- startActivity(new Intent(getApplicationContext(), OfflineActivity.class));
- return true;
-
- case R.id.action_animated_marker:
- startActivity(new Intent(getApplicationContext(), AnimatedMarkerActivity.class));
- return true;
-
- default:
- return changeMapStyle(menuItem.getItemId());
- }
- }
- });
- }
-
- private void toggleFpsCounter(boolean enableFps) {
- // Show the FPS counter
- if (enableFps) {
- mFpsTextView.setVisibility(View.VISIBLE);
- mFpsTextView.setText(getResources().getString(R.string.label_fps));
- } else {
- mFpsTextView.setVisibility(View.INVISIBLE);
- }
- }
-
- private boolean changeMapStyle(int id) {
- switch (id) {
- case R.id.actionStyleMapboxStreets:
- mMapView.setStyleUrl(Style.MAPBOX_STREETS);
- mSelectedStyle = id;
- return true;
-
- case R.id.actionStyleEmerald:
- mMapView.setStyleUrl(Style.EMERALD);
- mSelectedStyle = id;
- return true;
-
- case R.id.actionStyleLight:
- mMapView.setStyleUrl(Style.LIGHT);
- mSelectedStyle = id;
- return true;
-
- case R.id.actionStyleDark:
- mMapView.setStyleUrl(Style.DARK);
- mSelectedStyle = id;
- return true;
-
- case R.id.actionStyleSatellite:
- mMapView.setStyleUrl(Style.SATELLITE);
- mSelectedStyle = id;
- return true;
-
- case R.id.actionStyleSatelliteStreets:
- mMapView.setStyleUrl(Style.SATELLITE_STREETS);
- mSelectedStyle = id;
- return true;
-
- default:
- return false;
- }
- }
-
- /**
- * Enabled / Disable GPS location updates along with updating the UI
- *
- * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
- */
- private void toggleGps(boolean enableGps) {
- if (enableGps) {
- if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) ||
- (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED)) {
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
- PERMISSIONS_LOCATION);
- } else {
- mMapboxMap.setOnMyLocationChangeListener(new MapboxMap.OnMyLocationChangeListener() {
- @Override
- public void onMyLocationChange(@Nullable Location location) {
- if (location != null) {
- mMapboxMap.setCameraPosition(new CameraPosition.Builder()
- .target(new LatLng(location))
- .zoom(16)
- .bearing(0)
- .tilt(0)
- .build());
- mMapboxMap.setOnMyLocationChangeListener(null);
- }
- }
- });
- mMapboxMap.setMyLocationEnabled(true);
-
- TrackingSettings trackingSettings = mMapboxMap.getTrackingSettings();
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
-
- mLocationFAB.setColorFilter(ContextCompat.getColor(this, R.color.primary));
- }
- } else {
- if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
- == PackageManager.PERMISSION_GRANTED) ||
- (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
- == PackageManager.PERMISSION_GRANTED)) {
- mMapboxMap.setMyLocationEnabled(false);
- }
- mLocationFAB.setColorFilter(Color.TRANSPARENT);
- }
- }
-
- /**
- * Enable / Disable Annotations.
- *
- * @param enableAnnotations True to display, False to hide
- */
- private void toggleAnnotations(boolean enableAnnotations) {
- if (enableAnnotations) {
- if (!mIsAnnotationsOn) {
- mIsAnnotationsOn = true;
- addMarkers();
- addPolyline();
- addPolygon();
- mMapboxMap.setCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(38.11727, -122.22839))
- .zoom(7)
- .bearing(0)
- .tilt(0)
- .build());
- }
- } else {
- if (mIsAnnotationsOn) {
- mIsAnnotationsOn = false;
- removeAnnotations();
- }
- }
- }
-
- private void addMarkers() {
- List<MarkerOptions> markerOptionsList = new ArrayList<>();
-
- final MarkerOptions backLot = generateMarker("Back Lot", "The back lot behind my house", null, 38.649441, -121.369064);
- markerOptionsList.add(backLot);
-
- final Icon dogIcon = IconFactory.getInstance(this).fromAsset("dog-park-24.png");
- final MarkerOptions cheeseRoom = generateMarker("Cheese Room", "The only air conditioned room on the property", dogIcon, 38.531577, -122.010646);
- markerOptionsList.add(cheeseRoom);
-
- mMapboxMap.addMarkers(markerOptionsList);
- }
-
- private MarkerOptions generateMarker(String title, String snippet, Icon icon, double lat, double lng) {
- return new MarkerOptions()
- .position(new LatLng(lat, lng))
- .title(title)
- .icon(icon)
- .snippet(snippet);
- }
-
- private void addPolyline() {
- try {
- String geojsonStr = GeoParseUtil.loadStringFromAssets(this, "small_line.geojson");
- List<LatLng> latLngs = GeoParseUtil.parseGeoJSONCoordinates(geojsonStr);
- mMapboxMap.addPolyline(new PolylineOptions()
- .add(latLngs.toArray(new LatLng[latLngs.size()]))
- .width(2)
- .color(Color.RED));
- } catch (Exception e) {
- Log.e(TAG, "Error adding Polyline: " + e);
- e.printStackTrace();
- }
- }
-
- private void addPolygon() {
- try {
- String geojsonStr = GeoParseUtil.loadStringFromAssets(this, "small_poly.geojson");
- List<LatLng> latLngs = GeoParseUtil.parseGeoJSONCoordinates(geojsonStr);
- List<PolygonOptions> polygonOptions = new ArrayList<>();
- polygonOptions.add(new PolygonOptions()
- .add(latLngs.toArray(new LatLng[latLngs.size()]))
- .strokeColor(Color.MAGENTA)
- .fillColor(Color.BLUE).alpha(0.5f));
- mMapboxMap.addPolygons(polygonOptions).get(0);
- } catch (Exception e) {
- Log.e(TAG, "Error adding Polygon: " + e);
- e.printStackTrace();
- }
- }
-
- private void removeAnnotations() {
- mMarkerList.clear();
- mMapboxMap.removeAnnotations();
- }
-
- private void addCustomLayer() {
- mIsShowingCustomLayer = true;
- mMapboxMap.addCustomLayer(
- new CustomLayer("custom",
- ExampleCustomLayer.createContext(),
- ExampleCustomLayer.InitializeFunction,
- ExampleCustomLayer.RenderFunction,
- ExampleCustomLayer.DeinitializeFunction),
- null);
- }
-
- private void removeCustomLayer() {
- mIsShowingCustomLayer = false;
- mMapboxMap.removeCustomLayer("custom");
- }
-
- // Called when FPS changes
- private class MyOnFpsChangedListener implements MapboxMap.OnFpsChangedListener {
-
- @Override
- public void onFpsChanged(double fps) {
- mFpsTextView.setText(getResources().getString(R.string.label_fps) + String.format(" %4.2f", fps));
- }
- }
-
-}
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 4b1305daed..33c75db4d0 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
@@ -3,6 +3,7 @@ package com.mapbox.mapboxsdk.testapp;
import android.app.Application;
import android.os.StrictMode;
+import com.mapbox.mapboxsdk.MapboxAccountManager;
import com.squareup.leakcanary.LeakCanary;
public class MapboxApplication extends Application {
@@ -10,6 +11,7 @@ public class MapboxApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
+ MapboxAccountManager.start(getApplicationContext(), getString(R.string.mapbox_access_token));
LeakCanary.install(this);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java
deleted file mode 100644
index b397d5d688..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.design.widget.Snackbar;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-public class MapboxMapActivity extends AppCompatActivity {
-
- private MapView mMapView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_mapboxmap);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyle(Style.SATELLITE_STREETS);
- mMapView.onCreate(savedInstanceState);
-
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
- new CameraPosition.Builder()
- .target(new LatLng(43.876550, -103.454791))
- .zoom(14)
- .build()));
- }
- });
-
- Snackbar.make(findViewById(android.R.id.content),
- "Demo MapboxMap API",
- Snackbar.LENGTH_INDEFINITE).show();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java
deleted file mode 100644
index f167e1e5e6..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.graphics.Point;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.Menu;
-import android.view.MenuItem;
-
-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.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-
-public class MaxMinZoomActivity extends AppCompatActivity {
-
- private MapboxMap mMapboxMap;
- private MapView mMapView;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_maxmin_zoom);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- mMapView = (MapView) findViewById(R.id.manualZoomMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyle(Style.SATELLITE_STREETS);
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
- mMapboxMap.setMinZoom(3);
- mMapboxMap.setMaxZoom(5);
-
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(-1.063510, 32.895425)));
- }
- });
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_zoom, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- onBackPressed();
- return true;
-
- case R.id.action_zoom_in:
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomIn());
- return true;
-
- case R.id.action_zoom_out:
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomOut());
- return true;
-
- case R.id.action_zoom_by:
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2));
- return true;
- case R.id.action_zoom_to:
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomTo(2));
- return true;
-
- case R.id.action_zoom_to_point:
- mMapboxMap.animateCamera(CameraUpdateFactory.zoomBy(12, new Point(100, 100)));
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java
deleted file mode 100644
index de78de62fb..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.mapbox.mapboxsdk.testapp;
-
-import android.graphics.PointF;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
-import android.view.MenuItem;
-import android.view.ViewGroup;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
-
-import java.text.DecimalFormat;
-import java.util.ArrayList;
-
-public class PressForMarkerActivity extends AppCompatActivity implements MapboxMap.OnMapLongClickListener {
-
- private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
- private static final String STATE_MARKER_LIST = "markerList";
-
- private MapView mMapView;
- private MapboxMap mMapboxMap;
- private ArrayList<MarkerOptions> mMarkerList;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_press_for_marker);
-
- Toolbar toolbar = (Toolbar) findViewById(R.id.secondToolBar);
- setSupportActionBar(toolbar);
-
- ActionBar actionBar = getSupportActionBar();
- if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setDisplayShowHomeEnabled(true);
- }
-
- // Adding MapView programmatically
- mMapView = new MapView(this);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyle(Style.EMERALD);
- mMapView.onCreate(savedInstanceState);
- ((ViewGroup) findViewById(R.id.activity_container)).addView(mMapView);
-
- if (savedInstanceState != null) {
- mMarkerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
- }else{
- mMarkerList = new ArrayList<>();
- }
-
- mMapView.getMapAsync(new OnMapReadyCallback() {
- @Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
-
- // set camera
- mapboxMap.setCameraPosition(new CameraPosition.Builder()
- .target(new LatLng(45.1855569, 5.7215506))
- .zoom(11)
- .build());
-
- // add markers
- mapboxMap.addMarkers(mMarkerList);
-
- // set map long click listeners
- mapboxMap.setOnMapLongClickListener(PressForMarkerActivity.this);
- }
- });
- }
-
- @Override
- public void onMapLongClick(@NonNull LatLng point) {
- PointF pixel = mMapboxMap.getProjection().toScreenLocation(point);
- String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", " + LAT_LON_FORMATTER.format(point.getLongitude());
- String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
-
- MarkerOptions marker = new MarkerOptions()
- .position(point)
- .title(title)
- .snippet(snippet);
-
- mMarkerList.add(marker);
- mMapboxMap.addMarker(marker);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMapView.onResume();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
- outState.putParcelableArrayList(STATE_MARKER_LIST, mMarkerList);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
- }
-
- @Override
- public void onLowMemory() {
- super.onLowMemory();
- mMapView.onLowMemory();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-}
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
new file mode 100644
index 0000000000..9d514b2870
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java
@@ -0,0 +1,166 @@
+package com.mapbox.mapboxsdk.testapp.activity;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.StringRes;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.adapter.FeatureAdapter;
+import com.mapbox.mapboxsdk.testapp.adapter.FeatureSectionAdapter;
+import com.mapbox.mapboxsdk.testapp.model.activity.Feature;
+import com.mapbox.mapboxsdk.testapp.utils.ItemClickSupport;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class FeatureOverviewActivity extends AppCompatActivity {
+
+ private static final String KEY_STATE_FEATURES = "featureList";
+
+ private RecyclerView recyclerView;
+ private FeatureSectionAdapter sectionAdapter;
+ private List<Feature> features;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ toolbar.setTitle(getString(R.string.app_name));
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setElevation(getResources().getDimension(R.dimen.toolbar_shadow));
+ }
+
+ recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+ recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
+ recyclerView.setHasFixedSize(true);
+
+ ItemClickSupport.addTo(recyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
+ @Override
+ public void onItemClicked(RecyclerView recyclerView, int position, View v) {
+ if (!sectionAdapter.isSectionHeaderPosition(position)) {
+ Intent intent = new Intent();
+ int realPosition = sectionAdapter.getConvertedPosition(position);
+ intent.setComponent(new ComponentName(getPackageName(), features.get(realPosition).getName()));
+ startActivity(intent);
+ }
+ }
+ });
+
+ if (savedInstanceState == null) {
+ loadFeatures();
+ } else {
+ features = savedInstanceState.getParcelableArrayList(KEY_STATE_FEATURES);
+ onFeaturesLoaded(features);
+ }
+ }
+
+ private void loadFeatures() {
+ try {
+ new LoadFeatureTask().execute(getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(MapboxConstants.TAG, "Could not resolve package info", e);
+ }
+ }
+
+ private void onFeaturesLoaded(List<Feature> featuresList) {
+ features = featuresList;
+
+ List<FeatureSectionAdapter.Section> sections = new ArrayList<>();
+ String currentCat = "";
+ for (int i = 0; i < features.size(); i++) {
+ String category = features.get(i).getCategory();
+ if (!currentCat.equals(category)) {
+ sections.add(new FeatureSectionAdapter.Section(i, category));
+ currentCat = category;
+ }
+ }
+
+ FeatureSectionAdapter.Section[] dummy = new FeatureSectionAdapter.Section[sections.size()];
+ sectionAdapter = new FeatureSectionAdapter(this, R.layout.section_main_layout, R.id.section_text, new FeatureAdapter(features));
+ sectionAdapter.setSections(sections.toArray(dummy));
+ recyclerView.setAdapter(sectionAdapter);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelableArrayList(KEY_STATE_FEATURES, (ArrayList<Feature>) features);
+ }
+
+ private class LoadFeatureTask extends AsyncTask<PackageInfo, Void, List<Feature>> {
+
+ @Override
+ protected List<Feature> doInBackground(PackageInfo... params) {
+ List<Feature> features = new ArrayList<>();
+ PackageInfo app = params[0];
+
+ String packageName = getApplicationContext().getPackageName();
+ String metaDataKey = getString(R.string.category);
+ for (ActivityInfo info : app.activities) {
+ if (info.name.startsWith(packageName) && !info.name.equals(FeatureOverviewActivity.class.getName())) {
+ String label = getString(info.labelRes);
+ String description = resolveString(info.descriptionRes);
+ String category = resolveMetaData(info.metaData, metaDataKey);
+ features.add(new Feature(info.name, label, description, category));
+ }
+ }
+
+ if (!features.isEmpty()) {
+ Comparator<Feature> comparator = new Comparator<Feature>() {
+ @Override
+ public int compare(Feature lhs, Feature rhs) {
+ return lhs.getCategory().compareToIgnoreCase(rhs.getCategory());
+ }
+ };
+ Collections.sort(features, comparator);
+ }
+
+ return features;
+ }
+
+ private String resolveMetaData(Bundle bundle, String key) {
+ String category = null;
+ if (bundle != null) {
+ category = bundle.getString(key);
+ }
+ return category;
+ }
+
+ private String resolveString(@StringRes int stringRes){
+ try{
+ return getString(stringRes);
+ }catch (Resources.NotFoundException e){
+ return "-";
+ }
+ }
+
+ @Override
+ protected void onPostExecute(List<Feature> features) {
+ super.onPostExecute(features);
+ onFeaturesLoaded(features);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
index 27cd7f175c..1e15c9ea36 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedMarkerActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
@@ -13,12 +13,11 @@ import android.view.animation.AccelerateDecelerateInterpolator;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
-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.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
public class AnimatedMarkerActivity extends AppCompatActivity {
@@ -39,8 +38,6 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
}
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyleUrl(Style.LIGHT);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -76,11 +73,9 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
-
case android.R.id.home:
onBackPressed();
return true;
-
default:
return super.onOptionsItemSelected(item);
}
@@ -117,10 +112,14 @@ public class AnimatedMarkerActivity extends AppCompatActivity {
}
private class LatLngEvaluator implements TypeEvaluator<LatLng> {
+
+ private LatLng mLatLng = new LatLng();
+
@Override
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
- return new LatLng(startValue.getLatitude() + (endValue.getLatitude() - startValue.getLatitude()) * fraction,
- startValue.getLongitude() + (endValue.getLongitude() - startValue.getLongitude()) * fraction);
+ mLatLng.setLatitude(startValue.getLatitude() + (endValue.getLatitude() - startValue.getLatitude()) * fraction);
+ mLatLng.setLongitude(startValue.getLongitude() + (endValue.getLongitude() - startValue.getLongitude()) * fraction);
+ return mLatLng;
}
}
}
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
new file mode 100644
index 0000000000..7a2241a84c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java
@@ -0,0 +1,307 @@
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+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.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
+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.GeoParseUtil;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class BulkMarkerActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
+
+ private MapboxMap mMapboxMap;
+ private MapView mMapView;
+ private boolean mCustomMarkerView;
+ private List<LatLng> mLocations;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_bulk);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mMapView = (MapView) findViewById(R.id.mapView);
+ mMapView.onCreate(savedInstanceState);
+ mMapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ mMapboxMap = mapboxMap;
+
+ if (actionBar != null) {
+ ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter.createFromResource(actionBar.getThemedContext(), R.array.bulk_marker_list, android.R.layout.simple_spinner_item);
+ spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ spinner.setAdapter(spinnerAdapter);
+ spinner.setOnItemSelectedListener(BulkMarkerActivity.this);
+ }
+ }
+ });
+
+ final View fab = findViewById(R.id.fab);
+ if (fab != null) {
+ fab.setOnClickListener(new FabClickListener());
+ }
+ }
+
+ public static class TextAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
+
+ private LayoutInflater inflater;
+
+ public TextAdapter(@NonNull Context context) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ }
+
+ @Nullable
+ @Override
+ public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
+ viewHolder.title = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.title.setText(marker.getTitle());
+ return convertView;
+ }
+
+ private static class ViewHolder {
+ TextView title;
+ }
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]);
+ if (mLocations == null) {
+ new LoadLocationTask(this, amount).execute();
+ } else {
+ showMarkers(amount);
+ }
+ }
+
+
+ private void onLatLngListLoaded(List<LatLng> latLngs, int amount) {
+ mLocations = latLngs;
+ showMarkers(amount);
+ }
+
+ private void showMarkers(int amount) {
+ mMapboxMap.clear();
+
+ if (mLocations.size() < amount) {
+ amount = mLocations.size();
+ }
+
+ if (mCustomMarkerView) {
+ showNativeMarkers(amount);
+ } else {
+ showGlMarkers(amount);
+ }
+ }
+
+ private void showNativeMarkers(int amount) {
+ DecimalFormat formatter = new DecimalFormat("#.#####");
+ Random random = new Random();
+ int randomIndex;
+
+ for (int i = 0; i < amount; i++) {
+ randomIndex = random.nextInt(mLocations.size());
+ LatLng latLng = mLocations.get(randomIndex);
+ mMapboxMap.addMarker(new MarkerViewOptions()
+ .position(latLng)
+ .title(String.valueOf(i))
+ .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
+ }
+ }
+
+ private void showGlMarkers(int amount) {
+ List<MarkerOptions> markerOptionsList = new ArrayList<>();
+ DecimalFormat formatter = new DecimalFormat("#.#####");
+ Random random = new Random();
+ int randomIndex;
+
+ for (int i = 0; i < amount; i++) {
+ randomIndex = random.nextInt(mLocations.size());
+ LatLng latLng = mLocations.get(randomIndex);
+ markerOptionsList.add(new MarkerOptions()
+ .position(latLng)
+ .title(String.valueOf(i))
+ .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude())));
+ }
+
+ mMapboxMap.addMarkers(markerOptionsList);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // nothing selected, nothing to do!
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mMapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mMapView.onPause();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mMapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mMapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mMapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private class FabClickListener implements View.OnClickListener {
+ @Override
+ public void onClick(final View v) {
+ if (mMapboxMap != null) {
+ mCustomMarkerView = true;
+
+ // remove fab
+ v.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ v.setVisibility(View.GONE);
+ }
+ }).start();
+
+ // reload markers
+ Spinner spinner = (Spinner) findViewById(R.id.spinner);
+ if (spinner != null) {
+ int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[spinner.getSelectedItemPosition()]);
+ showMarkers(amount);
+ }
+
+ // add adapter
+ mMapboxMap.getMarkerViewManager().addMarkerViewAdapter(new TextAdapter(BulkMarkerActivity.this));
+
+ mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ public void onMapChanged(@MapView.MapChange int change) {
+ if (change == MapView.REGION_IS_CHANGING || change == MapView.REGION_DID_CHANGE) {
+ if (!mMapboxMap.getMarkerViewManager().getMarkerViewAdapters().isEmpty()) {
+ TextView viewCountView = (TextView) findViewById(R.id.countView);
+ viewCountView.setText("ViewCache size " + (mMapView.getChildCount() - 5));
+ }
+ }
+ }
+ });
+
+ mMapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(new MapboxMap.OnMarkerViewClickListener() {
+ @Override
+ public boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
+ Toast.makeText(BulkMarkerActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ });
+ }
+ }
+ }
+
+ private static class LoadLocationTask extends AsyncTask<Void, Integer, List<LatLng>> {
+
+ private static final String TAG = "LoadLocationTask";
+ private BulkMarkerActivity mActivity;
+ private ProgressDialog mProgressDialog;
+ private int mAmount;
+
+ public LoadLocationTask(BulkMarkerActivity activity, int amount) {
+ mAmount = amount;
+ mActivity = activity;
+ mProgressDialog = ProgressDialog.show(activity, "Loading", "Fetching markers", false);
+ }
+
+ @Override
+ protected List<LatLng> doInBackground(Void... params) {
+ try {
+ String json = GeoParseUtil.loadStringFromAssets(mActivity.getApplicationContext(), "points.geojson");
+ return GeoParseUtil.parseGeoJSONCoordinates(json);
+ } catch (IOException | JSONException e) {
+ Log.e(TAG, "Could not add markers,", e);
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(List<LatLng> locations) {
+ super.onPostExecute(locations);
+ mActivity.onLatLngListLoaded(locations, mAmount);
+ mProgressDialog.hide();
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
index a665a085ef..fcddf8ca54 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/DynamicMarkerChangeActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -18,7 +18,7 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
public class DynamicMarkerChangeActivity extends AppCompatActivity {
@@ -48,7 +48,6 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity {
mMapView = (MapView) findViewById(R.id.mapView);
mMapView.setTag(false);
- mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
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
new file mode 100644
index 0000000000..65a5afa602
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java
@@ -0,0 +1,228 @@
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
+
+import android.content.Context;
+import android.graphics.Point;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+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.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
+import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
+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.model.annotations.CountryMarkerOptions;
+import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerView;
+import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerViewOptions;
+
+public class MarkerViewActivity extends AppCompatActivity {
+
+ private MapboxMap mMapboxMap;
+ private MapView mMapView;
+
+ private final static LatLng[] LAT_LNGS = new LatLng[]{
+ new LatLng(38.907327, -77.041293),
+ new LatLng(38.909698, -77.029642),
+ new LatLng(38.907227, -77.036530),
+ new LatLng(38.905607, -77.031916),
+ new LatLng(38.897424, -77.036508),
+ new LatLng(38.897642, -77.041980),
+ new LatLng(38.889876, -77.008849),
+ new LatLng(38.889441, -77.050134)
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_marker_view);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ final TextView viewCountView = (TextView) findViewById(R.id.countView);
+ mMapView = (MapView) findViewById(R.id.mapView);
+ mMapView.onCreate(savedInstanceState);
+ mMapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ mMapboxMap = mapboxMap;
+
+ // add text markers
+ for (int i = 0; i < LAT_LNGS.length; i++) {
+ mMapboxMap.addMarker(new MarkerViewOptions()
+ .position(LAT_LNGS[i])
+ .title(String.valueOf(i))
+ .selectAnimatorResource(R.animator.scale_up)
+ .deselectAnimatorResource(R.animator.scale_down)
+ );
+ }
+
+ // add flag marker
+ CountryMarkerViewOptions options = new CountryMarkerViewOptions();
+ options.title("United States");
+ options.abbrevName("us");
+ options.flagRes(R.drawable.ic_us);
+ options.position(new LatLng(38.899774, -77.023237));
+ options.selectAnimatorResource(R.animator.rotate_360);
+ options.deselectAnimatorResource(R.animator.rotate_360);
+ options.flat(true);
+ mapboxMap.addMarker(options);
+
+ // default GL marker
+ mMapboxMap.addMarker(new CountryMarkerOptions()
+ .title("United States")
+ .position(new LatLng(38.902580, -77.050102))
+ );
+
+ // set adapters
+ final MarkerViewManager markerViewManager = mapboxMap.getMarkerViewManager();
+ markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this));
+ markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this));
+
+ mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
+ @Override
+ 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 " + (mMapView.getChildCount() - 5));
+ }
+ }
+ }
+ });
+
+ mMapboxMap.getMarkerViewManager().setOnMarkerViewClickListener(new MapboxMap.OnMarkerViewClickListener() {
+ @Override
+ public boolean onMarkerClick(@NonNull Marker marker, @NonNull View view, @NonNull MapboxMap.MarkerViewAdapter adapter) {
+ Toast.makeText(MarkerViewActivity.this, "Hello " + marker.getId(), Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ });
+ }
+ });
+ }
+
+ private static class TextAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> {
+
+ private LayoutInflater inflater;
+
+ public TextAdapter(@NonNull Context context) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ }
+
+ @Nullable
+ @Override
+ public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_text_marker, parent, false);
+ viewHolder.title = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.title.setText(marker.getTitle());
+ return convertView;
+ }
+
+ private static class ViewHolder {
+ TextView title;
+ }
+ }
+
+ private static class CountryAdapter extends MapboxMap.MarkerViewAdapter<CountryMarkerView> {
+
+ private LayoutInflater inflater;
+
+ public CountryAdapter(@NonNull Context context) {
+ super(context);
+ this.inflater = LayoutInflater.from(context);
+ }
+
+ @Nullable
+ @Override
+ public View getView(@NonNull CountryMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) {
+ ViewHolder viewHolder;
+ if (convertView == null) {
+ viewHolder = new ViewHolder();
+ convertView = inflater.inflate(R.layout.view_custom_marker, parent, false);
+ viewHolder.flag = (ImageView) convertView.findViewById(R.id.imageView);
+ viewHolder.abbrev = (TextView) convertView.findViewById(R.id.textView);
+ convertView.setTag(viewHolder);
+ } else {
+ viewHolder = (ViewHolder) convertView.getTag();
+ }
+ viewHolder.flag.setImageResource(marker.getFlagRes());
+ viewHolder.abbrev.setText(marker.getAbbrevName());
+ return convertView;
+ }
+
+ private static class ViewHolder {
+ ImageView flag;
+ TextView abbrev;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mMapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mMapView.onPause();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mMapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mMapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mMapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
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
new file mode 100644
index 0000000000..f08d65163b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolygonActivity.java
@@ -0,0 +1,124 @@
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
+
+import android.graphics.Color;
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.ViewGroup;
+
+import com.mapbox.mapboxsdk.annotations.PolygonOptions;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+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.testapp.model.constants.AppConstant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PolygonActivity extends AppCompatActivity {
+
+ private MapView mapView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_polygon);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ // configure inital map state
+ MapboxMapOptions options = new MapboxMapOptions()
+ .attributionTintColor(Color.RED)
+ .accessToken(getString(R.string.mapbox_access_token))
+ .styleUrl(Style.getMapboxStreetsUrl(AppConstant.STYLE_VERSION))
+ .camera(new CameraPosition.Builder()
+ .target(new LatLng(45.520486, -122.673541))
+ .zoom(12)
+ .tilt(40)
+ .build());
+
+ // create map
+ mapView = new MapView(this, options);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ List<LatLng> polygon = new ArrayList<>();
+ polygon.add(new LatLng(45.522585, -122.685699));
+ polygon.add(new LatLng(45.534611, -122.708873));
+ polygon.add(new LatLng(45.530883, -122.678833));
+ polygon.add(new LatLng(45.547115, -122.667503));
+ polygon.add(new LatLng(45.530643, -122.660121));
+ polygon.add(new LatLng(45.533529, -122.636260));
+ polygon.add(new LatLng(45.521743, -122.659091));
+ polygon.add(new LatLng(45.510677, -122.648792));
+ polygon.add(new LatLng(45.515008, -122.664070));
+ polygon.add(new LatLng(45.502496, -122.669048));
+ polygon.add(new LatLng(45.515369, -122.678489));
+ polygon.add(new LatLng(45.506346, -122.702007));
+ polygon.add(new LatLng(45.522585, -122.685699));
+ mapboxMap.addPolygon(new PolygonOptions()
+ .addAll(polygon)
+ .fillColor(Color.parseColor("#3bb2d0")));
+ }
+ });
+
+ // add to layout
+ ((ViewGroup) findViewById(R.id.container)).addView(mapView);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
index 997009d434..9eb4bc1741 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PolylineActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
import android.graphics.Color;
import android.os.Bundle;
@@ -16,7 +16,7 @@ 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.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import java.util.ArrayList;
import java.util.Collections;
@@ -58,7 +58,6 @@ public class PolylineActivity extends AppCompatActivity {
}
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -159,7 +158,7 @@ public class PolylineActivity extends AppCompatActivity {
case R.id.action_id_remove:
// test to remove all annotations
mPolylineOptions.clear();
- mMapboxMap.removeAnnotations();
+ mMapboxMap.clear();
return true;
case android.R.id.home:
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java
new file mode 100644
index 0000000000..88008d64fb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/PressForMarkerActivity.java
@@ -0,0 +1,141 @@
+package com.mapbox.mapboxsdk.testapp.activity.annotation;
+
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+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.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+
+public class PressForMarkerActivity extends AppCompatActivity {
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private ArrayList<MarkerOptions> mMarkerList = new ArrayList<>();
+
+ private static final DecimalFormat LAT_LON_FORMATTER = new DecimalFormat("#.#####");
+
+ private static String STATE_MARKER_LIST = "markerList";
+
+ @Override
+ protected void onCreate(@Nullable final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_press_for_marker);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.pressForMarkerMapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(final MapboxMap map) {
+ mapboxMap = map;
+ mapboxMap.setStyleUrl(Style.getOutdoorsStyleUrl(9));
+ resetMap();
+
+ mapboxMap.setOnMapLongClickListener(new MapboxMap.OnMapLongClickListener() {
+ @Override
+ public void onMapLongClick(@NonNull LatLng point) {
+ final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
+
+ String title = LAT_LON_FORMATTER.format(point.getLatitude()) + ", " + LAT_LON_FORMATTER.format(point.getLongitude());
+ String snippet = "X = " + (int) pixel.x + ", Y = " + (int) pixel.y;
+
+ MarkerOptions marker = new MarkerOptions()
+ .position(point)
+ .title(title)
+ .snippet(snippet);
+
+ mMarkerList.add(marker);
+ mapboxMap.addMarker(marker);
+ }
+ });
+
+ if (savedInstanceState != null) {
+ mMarkerList = savedInstanceState.getParcelableArrayList(STATE_MARKER_LIST);
+ mapboxMap.addMarkers(mMarkerList);
+ }
+ }
+ });
+ }
+
+ private void resetMap() {
+ if (mapboxMap == null) {
+ return;
+ }
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(45.1855569, 5.7215506), 11));
+ mapboxMap.removeAnnotations();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_press_for_marker, menu);
+ return true;
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+
+ mapView.onSaveInstanceState(outState);
+ outState.putParcelableArrayList(STATE_MARKER_LIST, mMarkerList);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mapView.onLowMemory();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ case R.id.menuItemReset:
+ resetMap();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
index 3f7703954b..44758cd146 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimationTypeActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -16,19 +16,23 @@ import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
-public class CameraActivity extends AppCompatActivity {
+public class CameraAnimationTypeActivity extends AppCompatActivity {
private static final String TAG = "CameraActivity";
- private MapView mMapView;
+ private MapView mapView;
+
+ private boolean cameraState;
+ private static final LatLng LAT_LNG_LONDON_EYE = new LatLng(51.50325, -0.11968);
+ private static final LatLng LAT_LNG_TOWER_BRIDGE = new LatLng(51.50550, -0.07520);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_camera);
+ setContentView(R.layout.activity_camera_animation_types);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -39,13 +43,13 @@ public class CameraActivity extends AppCompatActivity {
actionBar.setDisplayShowHomeEnabled(true);
}
- mMapView = (MapView) findViewById(R.id.cameraMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- // set a style
+ mapboxMap.getUiSettings().setAttributionEnabled(false);
+ mapboxMap.getUiSettings().setLogoEnabled(false);
mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition position) {
@@ -58,9 +62,10 @@ public class CameraActivity extends AppCompatActivity {
@Override
public void onClick(View view) {
CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(new LatLng(44.50128, -88.06216)) // Sets the center of the map to Lambeau Field
- .zoom(14) // Sets the zoom
- .tilt(30) // Sets the tilt of the camera to 30 degrees
+ .target(getNextLatLng())
+ .zoom(14)
+ .tilt(30)
+ .tilt(0)
.build();
mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
@@ -72,26 +77,27 @@ public class CameraActivity extends AppCompatActivity {
@Override
public void onClick(View view) {
CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(new LatLng(48.21874, 11.62465)) // Sets the center of the map to Allianz Arena
- .zoom(16) // Sets the zoom
- .bearing(180) // Sets the orientation of the camera to south
- .build(); // Creates a CameraPosition from the builder
+ .target(getNextLatLng())
+ .zoom(15)
+ .bearing(180)
+ .tilt(30)
+ .build();
MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
@Override
public void onCancel() {
Log.i(TAG, "Duration onCancel Callback called.");
- Toast.makeText(CameraActivity.this, "Ease onCancel Callback called.", Toast.LENGTH_LONG).show();
+ Toast.makeText(CameraAnimationTypeActivity.this, "Ease onCancel Callback called.", Toast.LENGTH_LONG).show();
}
@Override
public void onFinish() {
Log.i(TAG, "Duration onFinish Callback called.");
- Toast.makeText(CameraActivity.this, "Ease onFinish Callback called.", Toast.LENGTH_LONG).show();
+ Toast.makeText(CameraAnimationTypeActivity.this, "Ease onFinish Callback called.", Toast.LENGTH_LONG).show();
}
};
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 25000, callback);
+ mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
}
});
@@ -100,60 +106,65 @@ public class CameraActivity extends AppCompatActivity {
@Override
public void onClick(View view) {
CameraPosition cameraPosition = new CameraPosition.Builder()
- .target(new LatLng(-22.91214, -43.23012)) // Sets the center of the map to Maracanã
- .bearing(270) // Sets the orientation of the camera to west
- .tilt(20) // Sets the tilt of the camera to 30 degrees
- .build(); // Creates a CameraPosition from the builder
+ .target(getNextLatLng())
+ .bearing(270)
+ .tilt(20)
+ .build();
MapboxMap.CancelableCallback callback = new MapboxMap.CancelableCallback() {
@Override
public void onCancel() {
Log.i(TAG, "Duration onCancel Callback called.");
- Toast.makeText(CameraActivity.this, "Duration onCancel Callback called.", Toast.LENGTH_LONG).show();
+ Toast.makeText(CameraAnimationTypeActivity.this, "Duration onCancel Callback called.", Toast.LENGTH_LONG).show();
}
@Override
public void onFinish() {
Log.i(TAG, "Duration onFinish Callback called.");
- Toast.makeText(CameraActivity.this, "Duration onFinish Callback called.", Toast.LENGTH_LONG).show();
+ Toast.makeText(CameraAnimationTypeActivity.this, "Duration onFinish Callback called.", Toast.LENGTH_LONG).show();
}
};
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 25000, callback);
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 7500, callback);
}
});
}
});
}
+ private LatLng getNextLatLng() {
+ cameraState = !cameraState;
+ return cameraState ? LAT_LNG_TOWER_BRIDGE : LAT_LNG_LONDON_EYE;
+ }
+
@Override
public void onResume() {
super.onResume();
- mMapView.onResume();
+ mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
- mMapView.onPause();
+ mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
- mMapView.onDestroy();
+ mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
- mMapView.onLowMemory();
+ mapView.onLowMemory();
}
@Override
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
new file mode 100644
index 0000000000..220bef197b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
@@ -0,0 +1,176 @@
+package com.mapbox.mapboxsdk.testapp.activity.camera;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.annotation.IdRes;
+import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+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;
+
+public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback {
+
+ private MapView mapView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera_position);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ // add a listener to FAB
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Context context = v.getContext();
+ final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context, com.mapbox.mapboxsdk.R.style.AttributionAlertDialogStyle);
+ builder.setTitle(R.string.dialog_camera_position);
+ builder.setView(onInflateDialogContent(dialogContent));
+ builder.setPositiveButton("Animate", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ double latitude = Double.parseDouble(((TextView) dialogContent.findViewById(R.id.value_lat)).getText().toString());
+ double longitude = Double.parseDouble(((TextView) dialogContent.findViewById(R.id.value_lon)).getText().toString());
+ double zoom = Double.parseDouble(((TextView) dialogContent.findViewById(R.id.value_zoom)).getText().toString());
+ double bearing = Double.parseDouble(((TextView) dialogContent.findViewById(R.id.value_bearing)).getText().toString());
+ double tilt = Double.parseDouble(((TextView) dialogContent.findViewById(R.id.value_tilt)).getText().toString());
+
+ CameraPosition cameraPosition = new CameraPosition.Builder()
+ .target(new LatLng(latitude, longitude))
+ .zoom(zoom)
+ .bearing(bearing)
+ .tilt(tilt)
+ .build();
+
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000);
+ Log.v(MapboxConstants.TAG, cameraPosition.toString());
+ }
+ });
+ builder.setNegativeButton("Cancel", null);
+ builder.setCancelable(false);
+ builder.show();
+ }
+ });
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mapView.onDestroy();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private View onInflateDialogContent(View view) {
+ linkTextView(view, R.id.value_lat, R.id.seekbar_lat, new LatLngChangeListener(), 180 + 38);
+ linkTextView(view, R.id.value_lon, R.id.seekbar_lon, new LatLngChangeListener(), 180 - 77);
+ linkTextView(view, R.id.value_zoom, R.id.seekbar_zoom, new ValueChangeListener(), 6);
+ linkTextView(view, R.id.value_bearing, R.id.seekbar_bearing, new ValueChangeListener(), 90);
+ linkTextView(view, R.id.value_tilt, R.id.seekbar_tilt, new ValueChangeListener(), 40);
+ return view;
+ }
+
+ private void linkTextView(View view, @IdRes int textViewRes, @IdRes int seekBarRes, ValueChangeListener listener, int defaultValue) {
+ final TextView value = (TextView) view.findViewById(textViewRes);
+ SeekBar seekBar = (SeekBar) view.findViewById(seekBarRes);
+ listener.setLinkedValueView(value);
+ seekBar.setOnSeekBarChangeListener(listener);
+ seekBar.setProgress(defaultValue);
+ }
+
+ private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
+
+ protected TextView textView;
+
+ public void setLinkedValueView(TextView textView) {
+ this.textView = textView;
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ textView.setText(String.valueOf(progress));
+ }
+ }
+
+ private class LatLngChangeListener extends ValueChangeListener {
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ super.onProgressChanged(seekBar, progress - 180, fromUser);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java
index 24c6e7eb28..b9a438b7d5 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/LatLngBoundsActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -17,8 +17,9 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
public class LatLngBoundsActivity extends AppCompatActivity {
@@ -42,13 +43,11 @@ public class LatLngBoundsActivity extends AppCompatActivity {
}
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyle(Style.DARK);
+ mMapView.setStyleUrl(Style.getDarkStyleUrl(AppConstant.STYLE_VERSION));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull final MapboxMap mapboxMap) {
- mapboxMap.setStyle(Style.DARK);
UiSettings uiSettings = mapboxMap.getUiSettings();
uiSettings.setAllGesturesEnabled(false);
@@ -69,18 +68,18 @@ public class LatLngBoundsActivity extends AppCompatActivity {
.include(LOS_ANGELES)
.build();
- // And padding
- int padding = (int) getResources().getDimension(R.dimen.coordinatebounds_margin);
+ // Add map padding
+ int mapPadding = (int) getResources().getDimension(R.dimen.fab_margin);
+ mapboxMap.setPadding(mapPadding, mapPadding, mapPadding, mapPadding);
- // Move camera to the bounds with padding
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
+ // Move camera to the bounds with added padding
+ int padding = (int) getResources().getDimension(R.dimen.coordinatebounds_margin);
+ mapboxMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
// Call mapboxMap.getProjection().getVisibleRegion().latLngBounds to retrieve the bounds
Log.v(MapboxConstants.TAG, mapboxMap.getProjection().getVisibleRegion().latLngBounds.toString());
}
});
-
-
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
index 5d0d4b1eef..bc3691a2f7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ManualZoomActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.graphics.Point;
import android.os.Bundle;
@@ -15,8 +15,9 @@ import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
public class ManualZoomActivity extends AppCompatActivity {
@@ -38,8 +39,7 @@ public class ManualZoomActivity extends AppCompatActivity {
}
mMapView = (MapView) findViewById(R.id.manualZoomMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyleUrl(Style.SATELLITE_STREETS);
+ mMapView.setStyleUrl(Style.getSatelliteStyleUrl(AppConstant.STYLE_VERSION));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -54,6 +54,7 @@ public class ManualZoomActivity extends AppCompatActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
+// findViewById(R.id.)
getMenuInflater().inflate(R.menu.menu_zoom, menu);
return true;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
index 9ed66e4dc3..e9a9647d45 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/MaxMinZoomActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -7,21 +7,20 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.maps.UiSettings;
+import com.mapbox.mapboxsdk.testapp.R;
-public class TiltActivity extends AppCompatActivity {
+public class MaxMinZoomActivity extends AppCompatActivity {
private MapView mMapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_tilt);
+ setContentView(R.layout.activity_maxmin_zoom);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -32,23 +31,25 @@ public class TiltActivity extends AppCompatActivity {
actionBar.setDisplayShowHomeEnabled(true);
}
- mMapView = (MapView) findViewById(R.id.tiltMapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
+ mMapView = (MapView) findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- // initial position has been set in R.layout.activity_tilt
- CameraPosition tiltedCameraPosition = new CameraPosition.Builder().tilt(45.0f).build();
- mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(tiltedCameraPosition), 10000);
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ mapboxMap.setMinZoom(3);
+ mapboxMap.setMaxZoom(5);
}
});
}
@Override
- public void onPause() {
- super.onPause();
- mMapView.onPause();
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ }
+ return false;
}
@Override
@@ -58,9 +59,9 @@ public class TiltActivity extends AppCompatActivity {
}
@Override
- protected void onDestroy() {
- super.onDestroy();
- mMapView.onDestroy();
+ public void onPause() {
+ super.onPause();
+ mMapView.onPause();
}
@Override
@@ -70,14 +71,15 @@ public class TiltActivity extends AppCompatActivity {
}
@Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
+ protected void onDestroy() {
+ super.onDestroy();
+ mMapView.onDestroy();
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ mMapView.onLowMemory();
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
index 57099e3ad8..729a08758e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/ScrollByActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -13,14 +13,12 @@ import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
-import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
public class ScrollByActivity extends AppCompatActivity {
@@ -52,8 +50,6 @@ public class ScrollByActivity extends AppCompatActivity {
mMapView = (MapView) findViewById(R.id.mapView);
mMapView.setTag(true);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyleUrl(Style.MAPBOX_STREETS);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -62,9 +58,6 @@ public class ScrollByActivity extends AppCompatActivity {
uiSettings.setLogoEnabled(false);
uiSettings.setAttributionEnabled(false);
- LatLng grenada = new LatLng(37.176546, -3.599007);
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(grenada, 16));
-
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(ScrollByActivity.this, R.color.primary));
fab.setOnClickListener(new View.OnClickListener() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
index f6b3095a00..98c86d4313 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java
@@ -1,7 +1,6 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.customlayer;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
@@ -9,95 +8,106 @@ import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.view.View;
-
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.layers.CustomLayer;
+import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.customlayer.ExampleCustomLayer;
+
+public class CustomLayerActivity extends AppCompatActivity {
-public class CoordinateChangeActivity extends AppCompatActivity {
+ private MapboxMap mapboxMap;
+ private MapView mapView;
- private MapView mMapView;
- private MapboxMap mMapboxMap;
+ private boolean isShowingCustomLayer = false;
+ private FloatingActionButton fab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_animate_coordinate);
+ setContentView(R.layout.activity_custom_layer);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- ActionBar actionBar = getSupportActionBar();
+ final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
}
- mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setTag(true);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.onCreate(savedInstanceState);
- mMapView.getMapAsync(new OnMapReadyCallback() {
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
@Override
- public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mMapboxMap = mapboxMap;
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(getNextLatLng(), 16));
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(39.91448, -243.60947), 10));
- UiSettings uiSettings = mapboxMap.getUiSettings();
- uiSettings.setCompassEnabled(false);
}
});
- FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(this, R.color.primary));
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (mMapboxMap != null) {
- mMapboxMap.animateCamera(CameraUpdateFactory.newLatLng(getNextLatLng()));
+ if (mapboxMap != null) {
+ swapCustomLayer();
}
}
});
}
- private LatLng getNextLatLng() {
- boolean first = (boolean) mMapView.getTag();
- mMapView.setTag(!first);
- return first ? new LatLng(38.87000, -77.00800) : new LatLng(38.87031, -77.00897);
+ private void swapCustomLayer() {
+
+ if (isShowingCustomLayer) {
+ mapboxMap.removeCustomLayer("custom");
+ fab.setImageResource(R.drawable.ic_layers_24dp);
+ } else {
+ mapboxMap.addCustomLayer(new CustomLayer("custom",
+ ExampleCustomLayer.createContext(),
+ ExampleCustomLayer.InitializeFunction,
+ ExampleCustomLayer.RenderFunction,
+ ExampleCustomLayer.DeinitializeFunction), null);
+ fab.setImageResource(R.drawable.ic_layers_clear_24dp);
+ }
+
+ isShowingCustomLayer = !isShowingCustomLayer;
}
@Override
public void onResume() {
super.onResume();
- mMapView.onResume();
+ mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
- mMapView.onPause();
+ mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- mMapView.onSaveInstanceState(outState);
+ mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
- mMapView.onDestroy();
+ mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
- mMapView.onLowMemory();
+ mapView.onLowMemory();
}
@Override
@@ -110,5 +120,4 @@ public class CoordinateChangeActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
}
-
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java
index 0292ce2061..d5f248f89d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/directions/DirectionsActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.directions;
import android.graphics.Color;
import android.os.Bundle;
@@ -21,7 +21,7 @@ import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
import java.util.List;
@@ -52,7 +52,6 @@ public class DirectionsActivity extends AppCompatActivity {
}
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -96,7 +95,7 @@ public class DirectionsActivity extends AppCompatActivity {
private void getRoute(Waypoint origin, Waypoint destination) {
MapboxDirections md = new MapboxDirections.Builder()
- .setAccessToken(ApiAccess.getToken(this))
+ .setAccessToken(getString(R.string.mapbox_access_token))
.setOrigin(origin)
.setDestination(destination)
.setProfile(DirectionsCriteria.PROFILE_WALKING)
@@ -181,4 +180,4 @@ public class DirectionsActivity extends AppCompatActivity {
}
}
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
index 74516a2e48..5987855aac 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/MapFragmentActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
@@ -16,7 +16,8 @@ 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.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
public class MapFragmentActivity extends AppCompatActivity {
@@ -39,8 +40,7 @@ public class MapFragmentActivity extends AppCompatActivity {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
MapboxMapOptions options = new MapboxMapOptions();
- options.accessToken(ApiAccess.getToken(this));
- options.styleUrl(Style.SATELLITE_STREETS);
+ options.styleUrl(Style.getOutdoorsStyleUrl(AppConstant.STYLE_VERSION));
options.scrollGesturesEnabled(false);
options.zoomGesturesEnabled(false);
@@ -52,11 +52,13 @@ public class MapFragmentActivity extends AppCompatActivity {
// options.attributionEnabled(false);
// options.logoEnabled(false);
+ LatLng dc = new LatLng(38.90252, -77.02291);
+
options.minZoom(9);
options.maxZoom(11);
options.camera(new CameraPosition.Builder()
- .target(new LatLng(48.861431, 2.334166))
- .zoom(9)
+ .target(dc)
+ .zoom(11)
.build());
mapFragment = MapFragment.newInstance(options);
@@ -70,7 +72,7 @@ public class MapFragmentActivity extends AppCompatActivity {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2), 3500);
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
index efd4f52890..bb391fc93d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/SupportMapFragmentActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/fragment/SupportMapFragmentActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.fragment;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -16,7 +16,8 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
public class SupportMapFragmentActivity extends AppCompatActivity {
@@ -39,8 +40,7 @@ public class SupportMapFragmentActivity extends AppCompatActivity {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
MapboxMapOptions options = new MapboxMapOptions();
- options.accessToken(ApiAccess.getToken(this));
- options.styleUrl(Style.SATELLITE_STREETS);
+ options.styleUrl(Style.getSatelliteStreetsStyleUrl(AppConstant.STYLE_VERSION));
options.scrollGesturesEnabled(false);
options.zoomGesturesEnabled(false);
@@ -52,11 +52,13 @@ public class SupportMapFragmentActivity extends AppCompatActivity {
options.attributionEnabled(false);
options.logoEnabled(false);
+ LatLng dc = new LatLng(38.90252, -77.02291);
+
options.minZoom(9);
options.maxZoom(11);
options.camera(new CameraPosition.Builder()
- .target(new LatLng(48.861431, 2.334166))
- .zoom(9)
+ .target(dc)
+ .zoom(11)
.build());
mapFragment = SupportMapFragment.newInstance(options);
@@ -70,7 +72,7 @@ public class SupportMapFragmentActivity extends AppCompatActivity {
mapFragment.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
- mapboxMap.animateCamera(CameraUpdateFactory.zoomBy(2), 3500);
+ mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().tilt(45.0).build()), 10000);
}
});
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java
index 6185151471..fc03066a4e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/geocoding/GeocoderActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.geocoding;
import android.graphics.PointF;
import android.os.AsyncTask;
@@ -19,15 +19,15 @@ import com.mapbox.geocoder.GeocoderCriteria;
import com.mapbox.geocoder.MapboxGeocoder;
import com.mapbox.geocoder.service.models.GeocoderFeature;
import com.mapbox.geocoder.service.models.GeocoderResponse;
-import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Projection;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
import java.util.List;
@@ -38,7 +38,6 @@ import retrofit.Retrofit;
public class GeocoderActivity extends AppCompatActivity {
private static final String LOG_TAG = "GeocoderActivity";
- private static final LatLng DC_DUPONT_CIRCLE = new LatLng(38.90962, -77.04341);
private MapView mapView;
private TextView textView;
@@ -58,11 +57,10 @@ public class GeocoderActivity extends AppCompatActivity {
}
textView = (TextView) findViewById(R.id.message);
- setMessage("Tap the map to trigger the geocoder.");
+ setMessage(getString(R.string.geocoder_instructions));
mapView = (MapView) findViewById(R.id.mapView);
- mapView.setAccessToken(ApiAccess.getToken(this));
- mapView.setStyle(Style.MAPBOX_STREETS);
+ mapView.setStyleUrl(Style.getMapboxStreetsUrl(AppConstant.STYLE_VERSION));
mapView.onCreate(savedInstanceState);
final ImageView dropPinView = new ImageView(this);
@@ -78,16 +76,6 @@ public class GeocoderActivity extends AppCompatActivity {
final int width = mapView.getMeasuredWidth();
final int height = mapView.getMeasuredHeight();
- // Camera position
- mapboxMap.setCameraPosition(
- new CameraPosition.Builder()
- .target(DC_DUPONT_CIRCLE)
- .zoom(15)
- .bearing(0)
- .tilt(0)
- .build()
- );
-
// Click listener
mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
@Override
@@ -141,7 +129,7 @@ public class GeocoderActivity extends AppCompatActivity {
@Override
protected Void doInBackground(Void... params) {
MapboxGeocoder client = new MapboxGeocoder.Builder()
- .setAccessToken(ApiAccess.getToken(GeocoderActivity.this))
+ .setAccessToken(getString(R.string.mapbox_access_token))
.setCoordinates(point.getLongitude(), point.getLatitude())
.setType(GeocoderCriteria.TYPE_POI)
.build();
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
new file mode 100644
index 0000000000..93ebdcd157
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java
@@ -0,0 +1,106 @@
+package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
+
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class SnapshotActivity extends AppCompatActivity {
+
+ private MapView mapView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_snapshot);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull final MapboxMap mapboxMap) {
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setColorFilter(ContextCompat.getColor(SnapshotActivity.this, R.color.primary));
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final long startTime = System.nanoTime();
+ mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
+ @Override
+ public void onSnapshotReady(Bitmap snapshot) {
+ long endTime = System.nanoTime();
+ long duration = (long) ((endTime - startTime) / 1e6);
+ ImageView snapshotView = (ImageView) findViewById(R.id.imageView);
+ snapshotView.setImageBitmap(snapshot);
+ Toast.makeText(SnapshotActivity.this, String.format("Snapshot taken in %d ms", duration), Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java
new file mode 100644
index 0000000000..7ac3c59667
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowActivity.java
@@ -0,0 +1,167 @@
+package com.mapbox.mapboxsdk.testapp.activity.infowindow;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.maps.MapView;
+
+import java.text.DecimalFormat;
+
+public class InfoWindowActivity extends AppCompatActivity implements OnMapReadyCallback, MapboxMap.OnInfoWindowCloseListener, MapboxMap.OnMapLongClickListener, MapboxMap.OnInfoWindowClickListener, MapboxMap.OnInfoWindowLongClickListener {
+
+ private MapboxMap mapboxMap;
+ private MapView mapView;
+ private Marker customMarker;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_infowindow);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(this);
+ }
+
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ this.mapboxMap = mapboxMap;
+ addMarkers();
+ addInfoWindowListeners();
+ }
+
+ private void addMarkers() {
+ mapboxMap.addMarker(new MarkerOptions()
+ .title("Intersection")
+ .snippet("H St NW with 15th St NW")
+ .position(new LatLng(38.9002073, -77.03364419)));
+
+ mapboxMap.addMarker(new MarkerOptions().title("Intersection")
+ .snippet("E St NW with 17th St NW")
+ .position(new LatLng(38.8954236, -77.0394623)));
+
+ Marker marker = mapboxMap.addMarker(new MarkerOptions()
+ .title("White House")
+ .snippet("The official residence and principal workplace of the President of the United States, located at 1600 Pennsylvania Avenue NW in Washington, D.C. It has been the residence of every U.S. president since John Adams in 1800.")
+ .position(new LatLng(38.897705003219784, -77.03655168667463)));
+
+ // open InfoWindow at startup
+ mapboxMap.selectMarker(marker);
+ }
+
+ private void addInfoWindowListeners() {
+ mapboxMap.setOnInfoWindowCloseListener(this);
+ mapboxMap.setOnMapLongClickListener(this);
+ mapboxMap.setOnInfoWindowClickListener(this);
+ mapboxMap.setOnInfoWindowLongClickListener(this);
+ }
+
+ private void toggleConcurrentInfoWindow(boolean allowConcurrentInfoWindow) {
+ mapboxMap.deselectMarkers();
+ mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(allowConcurrentInfoWindow);
+ }
+
+ @Override
+ public boolean onInfoWindowClick(@NonNull Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ // returning true will leave the info window open
+ return false;
+ }
+
+ @Override
+ public void onInfoWindowClose(Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnClose: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onInfoWindowLongClick(Marker marker) {
+ Toast.makeText(getApplicationContext(), "OnLongClick: " + marker.getTitle(), Toast.LENGTH_LONG).show();
+ }
+
+ @Override
+ public void onMapLongClick(@NonNull LatLng point) {
+ if (customMarker != null) {
+ // Remove previous added marker
+ mapboxMap.removeAnnotation(customMarker);
+ customMarker = null;
+ }
+
+ // Add marker on long click location with default marker image
+ customMarker = mapboxMap.addMarker(new MarkerOptions()
+ .title("Custom Marker")
+ .snippet(new DecimalFormat("#.#####").format(point.getLatitude()) + ", " + new DecimalFormat("#.#####").format(point.getLongitude()))
+ .position(point));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_infowindow, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_toggle_concurrent_infowindow:
+ toggleConcurrentInfoWindow(!item.isChecked());
+ item.setChecked(!item.isChecked());
+ return true;
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
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
new file mode 100644
index 0000000000..2c74702253
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/infowindow/InfoWindowAdapterActivity.java
@@ -0,0 +1,144 @@
+package com.mapbox.mapboxsdk.testapp.activity.infowindow;
+
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarker;
+import com.mapbox.mapboxsdk.testapp.model.annotations.CityStateMarkerOptions;
+import com.mapbox.mapboxsdk.maps.MapView;
+
+public class InfoWindowAdapterActivity extends AppCompatActivity {
+
+ private MapView mapView;
+ private IconFactory iconFactory;
+ private Drawable iconDrawable;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_infowindow_adapter);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ iconFactory = IconFactory.getInstance(this);
+ iconDrawable = ContextCompat.getDrawable(this, R.drawable.ic_location_city_24dp);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ addMarkers(mapboxMap);
+ addCustomInfoWindowAdapter(mapboxMap);
+ }
+ });
+ }
+
+ private void addMarkers(MapboxMap mapboxMap){
+ mapboxMap.addMarker(generateCityStateMarker("Andorra", 42.505777, 1.52529, "#F44336"));
+ mapboxMap.addMarker(generateCityStateMarker("Luxembourg", 49.815273, 6.129583, "#3F51B5"));
+ mapboxMap.addMarker(generateCityStateMarker("Monaco", 43.738418, 7.424616, "#673AB7"));
+ mapboxMap.addMarker(generateCityStateMarker("Vatican City", 41.902916, 12.453389, "#009688"));
+ mapboxMap.addMarker(generateCityStateMarker("San Marino", 43.942360, 12.457777, "#795548"));
+ mapboxMap.addMarker(generateCityStateMarker("Liechtenstein", 47.166000, 9.555373, "#FF5722"));
+ }
+
+ private CityStateMarkerOptions generateCityStateMarker(String title, double lat, double lng, String color) {
+ CityStateMarkerOptions marker = new CityStateMarkerOptions();
+ marker.title(title);
+ marker.position(new LatLng(lat, lng));
+ marker.infoWindowBackground(color);
+
+ iconDrawable.setColorFilter(Color.parseColor(color), PorterDuff.Mode.SRC_IN);
+ Icon icon = iconFactory.fromDrawable(iconDrawable);
+ marker.icon(icon);
+ return marker;
+ }
+
+ private void addCustomInfoWindowAdapter(MapboxMap mapboxMap){
+ mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() {
+
+ private int tenDp = (int) getResources().getDimension(R.dimen.attr_margin);
+
+ @Override
+ public View getInfoWindow(@NonNull Marker marker) {
+ TextView textView = new TextView(InfoWindowAdapterActivity.this);
+ textView.setText(marker.getTitle());
+ textView.setTextColor(Color.WHITE);
+
+ if (marker instanceof CityStateMarker) {
+ CityStateMarker cityStateMarker = (CityStateMarker) marker;
+ textView.setBackgroundColor(Color.parseColor(cityStateMarker.getInfoWindowBackgroundColor()));
+ }
+
+ textView.setPadding(tenDp, tenDp, tenDp, tenDp);
+ return textView;
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
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
new file mode 100644
index 0000000000..f5835ab7bd
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DebugModeActivity.java
@@ -0,0 +1,131 @@
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+
+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.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
+
+public class DebugModeActivity extends AppCompatActivity {
+
+ private static final String TAG = "DebugModeActivity";
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+
+ private int currentStyleIndex = 0;
+
+ private static final String[] STYLES = new String[]{
+ Style.getMapboxStreetsUrl(AppConstant.STYLE_VERSION),
+ Style.getOutdoorsStyleUrl(AppConstant.STYLE_VERSION),
+ Style.getLightStyleUrl(AppConstant.STYLE_VERSION),
+ Style.getDarkStyleUrl(AppConstant.STYLE_VERSION),
+ Style.getSatelliteStyleUrl(AppConstant.STYLE_VERSION),
+ Style.getSatelliteStreetsStyleUrl(AppConstant.STYLE_VERSION)
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_debug_mode);
+
+ final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.setTag(true);
+ mapView.setStyleUrl(STYLES[currentStyleIndex]);
+ mapView.onCreate(savedInstanceState);
+
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(@NonNull MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ FloatingActionButton fabDebug = (FloatingActionButton) findViewById(R.id.fabDebug);
+ fabDebug.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mapboxMap != null) {
+ Log.d(TAG, "Debug FAB: isDebug Active? " + mapboxMap.isDebugActive());
+ mapboxMap.cycleDebugOptions();
+ }
+ }
+ });
+
+ FloatingActionButton fabStyles = (FloatingActionButton) findViewById(R.id.fabStyles);
+ fabStyles.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mapboxMap != null) {
+ currentStyleIndex++;
+ if (currentStyleIndex == STYLES.length) {
+ currentStyleIndex = 0;
+ }
+ mapboxMap.setStyleUrl(STYLES[currentStyleIndex]);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java
index b4dd6bd2c4..288817d670 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java
@@ -1,5 +1,6 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
+import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
@@ -15,16 +16,18 @@ import android.view.ViewGroup;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
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.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.maps.UiSettings;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
public class DoubleMapActivity extends AppCompatActivity {
private static final String TAG_FRAGMENT = "map";
- private DoubleMapFragment mMapFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -40,12 +43,13 @@ public class DoubleMapActivity extends AppCompatActivity {
actionBar.setDisplayShowHomeEnabled(true);
}
+ Fragment mapFragment;
if (savedInstanceState == null) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
- transaction.add(R.id.fragment_container, mMapFragment = new DoubleMapFragment(), TAG_FRAGMENT);
+ transaction.add(R.id.fragment_container, mapFragment = new DoubleMapFragment(), TAG_FRAGMENT);
transaction.commit();
} else {
- mMapFragment = (DoubleMapFragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
+ mapFragment = (DoubleMapFragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
}
}
@@ -65,11 +69,12 @@ public class DoubleMapActivity extends AppCompatActivity {
// MapView large
mMapView = (MapView) view.findViewById(R.id.mapView);
- mMapView.setStyleUrl(Style.DARK);
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ mapboxMap.setStyleUrl(Style.getDarkStyleUrl(AppConstant.STYLE_VERSION));
+
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(18));
try {
TrackingSettings settings = mapboxMap.getTrackingSettings();
@@ -83,11 +88,11 @@ public class DoubleMapActivity extends AppCompatActivity {
// MapView mini
mMapViewMini = (MapView) view.findViewById(R.id.mini_map);
- mMapViewMini.setStyle(Style.LIGHT);
mMapViewMini.onCreate(savedInstanceState);
mMapViewMini.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
+ mapboxMap.setStyleUrl(Style.getLightStyleUrl(AppConstant.STYLE_VERSION));
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4));
UiSettings uiSettings = mapboxMap.getUiSettings();
@@ -99,10 +104,18 @@ public class DoubleMapActivity extends AppCompatActivity {
try {
TrackingSettings settings = mapboxMap.getTrackingSettings();
settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- }catch (SecurityException e){
+ } catch (SecurityException e) {
// permission is handled in MainActivity
getActivity().finish();
}
+
+ mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
+ @Override
+ public void onMapClick(@NonNull LatLng point) {
+ // test if we can open 2 activities after each other
+ startActivity(new Intent(mMapViewMini.getContext(), DoubleMapActivity.class));
+ }
+ });
}
});
}
@@ -153,4 +166,4 @@ public class DoubleMapActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
index c5e25f48d0..62762f7116 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.maplayout;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -17,7 +17,7 @@ import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
+import com.mapbox.mapboxsdk.testapp.R;
public class MapPaddingActivity extends AppCompatActivity {
@@ -40,7 +40,6 @@ public class MapPaddingActivity extends AppCompatActivity {
mMapView = (MapView) findViewById(R.id.mapView);
mMapView.setTag(true);
- mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@@ -103,7 +102,7 @@ public class MapPaddingActivity extends AppCompatActivity {
trackingSettings.setDismissTrackingOnGesture(false);
trackingSettings.setMyLocationTrackingMode(enable ? MyLocationTracking.TRACKING_FOLLOW : MyLocationTracking.TRACKING_NONE);
} catch (SecurityException e) {
- // permission not granted is handled in MainActivity
+ // permission not granted is handled in FeatureOverviewActivity
finish();
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
index c6fae95d7a..fde46b1cab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.offline;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -12,7 +12,6 @@ import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Toast;
-
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.Style;
@@ -26,16 +25,15 @@ import com.mapbox.mapboxsdk.offline.OfflineRegion;
import com.mapbox.mapboxsdk.offline.OfflineRegionError;
import com.mapbox.mapboxsdk.offline.OfflineRegionStatus;
import com.mapbox.mapboxsdk.offline.OfflineTilePyramidRegionDefinition;
-import com.mapbox.mapboxsdk.testapp.offline.DownloadRegionDialog;
-import com.mapbox.mapboxsdk.testapp.offline.ListRegionsDialog;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
+import com.mapbox.mapboxsdk.testapp.model.other.OfflineDownloadRegionDialog;
+import com.mapbox.mapboxsdk.testapp.model.other.OfflineListRegionsDialog;
import org.json.JSONObject;
-
import java.util.ArrayList;
public class OfflineActivity extends AppCompatActivity
- implements DownloadRegionDialog.DownloadRegionDialogListener {
+ implements OfflineDownloadRegionDialog.DownloadRegionDialogListener {
private final static String LOG_TAG = "OfflineActivity";
@@ -76,8 +74,7 @@ public class OfflineActivity extends AppCompatActivity
// Set up map
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
- mMapView.setStyle(Style.MAPBOX_STREETS);
+ mMapView.setStyleUrl(Style.getMapboxStreetsUrl(AppConstant.STYLE_VERSION));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
@@ -118,7 +115,6 @@ public class OfflineActivity extends AppCompatActivity
// Set up the OfflineManager
mOfflineManager = OfflineManager.getInstance(this);
- mOfflineManager.setAccessToken(ApiAccess.getToken(this));
}
@Override
@@ -170,8 +166,8 @@ public class OfflineActivity extends AppCompatActivity
Log.d(LOG_TAG, "handleDownloadRegion");
// Show dialog
- DownloadRegionDialog downloadRegionDialog = new DownloadRegionDialog();
- downloadRegionDialog.show(getSupportFragmentManager(), "download");
+ OfflineDownloadRegionDialog offlineDownloadRegionDialog = new OfflineDownloadRegionDialog();
+ offlineDownloadRegionDialog.show(getSupportFragmentManager(), "download");
}
private void handleListRegions() {
@@ -195,12 +191,12 @@ public class OfflineActivity extends AppCompatActivity
// Create args
Bundle args = new Bundle();
- args.putStringArrayList(ListRegionsDialog.ITEMS, offlineRegionsNames);
+ args.putStringArrayList(OfflineListRegionsDialog.ITEMS, offlineRegionsNames);
// Show dialog
- ListRegionsDialog listRegionsDialog = new ListRegionsDialog();
- listRegionsDialog.setArguments(args);
- listRegionsDialog.show(getSupportFragmentManager(), "list");
+ OfflineListRegionsDialog offlineListRegionsDialog = new OfflineListRegionsDialog();
+ offlineListRegionsDialog.setArguments(args);
+ offlineListRegionsDialog.show(getSupportFragmentManager(), "list");
}
@Override
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
new file mode 100644
index 0000000000..a4a283907e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
@@ -0,0 +1,136 @@
+package com.mapbox.mapboxsdk.testapp.activity.userlocation;
+
+import android.graphics.Color;
+import android.location.Location;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.constants.Style;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
+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.testapp.model.constants.AppConstant;
+
+public class MyLocationDrawableActivity extends AppCompatActivity implements LocationListener {
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private Location location;
+ private boolean firstRun;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_customization);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ findViewById(R.id.progress).setVisibility(View.GONE);
+ location = LocationServices.getLocationServices(this).getLastLocation();
+
+ MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
+ mapboxMapOptions.accessToken(getString(R.string.mapbox_access_token));
+ mapboxMapOptions.styleUrl(Style.getMapboxStreetsUrl(AppConstant.STYLE_VERSION));
+ mapboxMapOptions.locationEnabled(true);
+ mapboxMapOptions.camera(new CameraPosition.Builder()
+ .target(location != null ? new LatLng(location) : new LatLng(0, 0))
+ .zoom(11)
+ .tilt(25)
+ .build());
+
+ mapboxMapOptions.myLocationForegroundDrawables(ContextCompat.getDrawable(this, R.drawable.ic_chelsea),
+ ContextCompat.getDrawable(this, R.drawable.ic_chelsea));
+ mapboxMapOptions.myLocationBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_arsenal));
+ mapboxMapOptions.myLocationForegroundTintColor(Color.GREEN);
+ mapboxMapOptions.myLocationBackgroundTintColor(Color.YELLOW);
+ mapboxMapOptions.myLocationBackgroundPadding(new int[]{0, 0,
+ (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding),
+ (int) getResources().getDimension(R.dimen.locationview_background_drawable_padding)});
+
+ mapboxMapOptions.myLocationAccuracyTint(Color.RED);
+ mapboxMapOptions.myLocationAccuracyAlpha(155);
+
+ mapView = new MapView(this, mapboxMapOptions);
+ ViewGroup parent = (ViewGroup) findViewById(R.id.container);
+ parent.addView(mapView);
+
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ LocationServices.getLocationServices(this).addLocationListener(this);
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ if (mapboxMap != null && firstRun) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 10));
+ firstRun = false;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
new file mode 100644
index 0000000000..f665b88f60
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
@@ -0,0 +1,188 @@
+package com.mapbox.mapboxsdk.testapp.activity.userlocation;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.os.Bundle;
+import android.support.annotation.IdRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.location.LocationListener;
+import com.mapbox.mapboxsdk.location.LocationServices;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class MyLocationTintActivity extends AppCompatActivity implements LocationListener {
+
+ private MapView mapView;
+ private MapboxMap map;
+ private boolean firstRun;
+
+ private static final int PERMISSIONS_LOCATION = 0;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_dot_color);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ map = mapboxMap;
+ toggleGps(!mapboxMap.isMyLocationEnabled());
+
+ final MyLocationViewSettings myLocationViewSettings = mapboxMap.getMyLocationViewSettings();
+
+ // handle default button clicks
+ ViewUtils.attachClickListener(MyLocationTintActivity.this, R.id.default_user_dot_coloring_button,new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.my_location_ring));
+ myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
+ }
+ });
+
+ // handle tint user dot button clicks
+ ViewUtils.attachClickListener(MyLocationTintActivity.this, R.id.tint_user_dot_button,new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
+ myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_green));
+ }
+ });
+
+ // handle tint accuracy ring button clicks
+ ViewUtils.attachClickListener(MyLocationTintActivity.this, R.id.user_accuracy_ring_tint_button,new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ myLocationViewSettings.setAccuracyTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
+ myLocationViewSettings.setForegroundTintColor(ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
+ }
+ });
+ }
+ });
+
+ LocationServices.getLocationServices(this).addLocationListener(this);
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ if (map != null && firstRun) {
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15));
+ firstRun = false;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
+ }
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ map.setMyLocationEnabled(true);
+ if (map.getMyLocation() != null) {
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(map.getMyLocation().getLatitude(), map.getMyLocation().getLongitude()), 15));
+ }
+ } else {
+ map.setMyLocationEnabled(false);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+ switch (requestCode) {
+ case PERMISSIONS_LOCATION: {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
+ }
+ }
+ }
+
+ private static class ViewUtils {
+
+ public static void attachClickListener(@NonNull Activity activity, @IdRes int buttonId, @Nullable View.OnClickListener clickListener) {
+ View view = activity.findViewById(buttonId);
+ if(view!=null){
+ view.setOnClickListener(clickListener);
+ }
+ }
+ }
+}
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
new file mode 100644
index 0000000000..b92bb5937c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java
@@ -0,0 +1,160 @@
+package com.mapbox.mapboxsdk.testapp.activity.userlocation;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.UiThread;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.view.View;
+import com.mapbox.mapboxsdk.camera.CameraPosition;
+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.OnMapReadyCallback;
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class MyLocationToggleActivity extends AppCompatActivity {
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private FloatingActionButton locationToggleFAB;
+
+ private static final int PERMISSIONS_LOCATION = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my_location_toggle);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap map) {
+ mapboxMap = map;
+ }
+ });
+
+ locationToggleFAB = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
+ locationToggleFAB.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mapboxMap != null) {
+ toggleGps(!mapboxMap.isMyLocationEnabled());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mapView.onPause();
+ }
+
+ @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();
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ onBackPressed();
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @UiThread
+ public void toggleGps(boolean enableGps) {
+ if (enableGps) {
+ if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
+ } else {
+ enableLocation(true);
+ }
+ } else {
+ enableLocation(false);
+ }
+ }
+
+ private void enableLocation(boolean enabled) {
+ if (enabled) {
+ mapboxMap.setOnMyLocationChangeListener(new MapboxMap.OnMyLocationChangeListener() {
+ @Override
+ public void onMyLocationChange(@Nullable Location location) {
+ if (location != null) {
+ mapboxMap.setCameraPosition(new CameraPosition.Builder()
+ .target(new LatLng(location))
+ .zoom(16)
+ .bearing(0)
+ .tilt(0)
+ .build());
+ mapboxMap.setOnMyLocationChangeListener(null);
+ }
+ }
+ });
+ locationToggleFAB.setImageResource(R.drawable.ic_location_disabled_24dp);
+ } else {
+ locationToggleFAB.setImageResource(R.drawable.ic_my_location_24dp);
+ }
+
+ mapboxMap.setMyLocationEnabled(enabled);
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
+ switch (requestCode) {
+ case PERMISSIONS_LOCATION: {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ enableLocation(true);
+ }
+ }
+ }
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
index 5a349c396f..fcd61e70b4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp;
+package com.mapbox.mapboxsdk.testapp.activity.userlocation;
import android.location.Location;
import android.os.Bundle;
@@ -8,22 +8,24 @@ import android.support.design.widget.Snackbar;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
+import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;
-
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.MyBearingTracking;
import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.location.LocationServices;
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.testapp.utils.ApiAccess;
-import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationTrackingModeActivity extends AppCompatActivity implements MapboxMap.OnMyLocationChangeListener, AdapterView.OnItemSelectedListener {
@@ -48,13 +50,16 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
}
mMapView = (MapView) findViewById(R.id.mapView);
- mMapView.setAccessToken(ApiAccess.getToken(this));
mMapView.onCreate(savedInstanceState);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mMapboxMap = mapboxMap;
+ // disable dismissal when a gesture occurs
+ mMapboxMap.getTrackingSettings().setDismissLocationTrackingOnGesture(false);
+ mMapboxMap.getTrackingSettings().setDismissBearingTrackingOnGesture(false);
+
mapboxMap.setOnMyLocationChangeListener(MyLocationTrackingModeActivity.this);
ArrayAdapter<CharSequence> locationTrackingAdapter = ArrayAdapter.createFromResource(actionBar.getThemedContext(), R.array.user_tracking_mode, android.R.layout.simple_spinner_item);
@@ -69,15 +74,6 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
mBearingSpinner.setAdapter(bearingTrackingAdapter);
mBearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- try {
- mapboxMap.setMyLocationEnabled(true);
- } catch (SecurityException e) {
- //should not occur, permission was checked in MainActivity
- Toast.makeText(MyLocationTrackingModeActivity.this,
- "Location permission is not available", Toast.LENGTH_SHORT).show();
- finish();
- }
-
mapboxMap.setOnMyLocationTrackingModeChangeListener(new MapboxMap.OnMyLocationTrackingModeChangeListener() {
@Override
public void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode) {
@@ -99,18 +95,29 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
}
}
});
+
+
+ mLocation = LocationServices.getLocationServices(MyLocationTrackingModeActivity.this).getLastLocation();
+ if(mLocation!=null){
+ setInitialPosition(new LatLng(mLocation));
+ }
}
});
}
+ private void setInitialPosition(LatLng latLng){
+ mMapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14));
+ mMapboxMap.setMyLocationEnabled(true);
+ mLocationSpinner.setEnabled(true);
+ mBearingSpinner.setEnabled(true);
+ }
+
@Override
public void onMyLocationChange(@Nullable Location location) {
if (location != null) {
if (mLocation == null) {
// initial location to reposition map
- mMapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 14));
- mLocationSpinner.setEnabled(true);
- mBearingSpinner.setEnabled(true);
+ setInitialPosition(new LatLng(location));
}
mLocation = location;
showSnackBar();
@@ -121,13 +128,17 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
String desc = "Loc Chg: ";
boolean noInfo = true;
if (mLocation.hasSpeed()) {
- desc += String.format("Spd = %.1f km/h ", mLocation.getSpeed() * 3.6f);
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Spd = %.1f km/h ", mLocation.getSpeed() * 3.6f);
noInfo = false;
}
if (mLocation.hasAltitude()) {
- desc += String.format("Alt = %.0f m ", mLocation.getAltitude());
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Alt = %.0f m ", mLocation.getAltitude());
noInfo = false;
}
+ if (mLocation.hasAccuracy()) {
+ desc += String.format(MapboxConstants.MAPBOX_LOCALE, "Acc = %.0f m", mLocation.getAccuracy());
+ }
+
if (noInfo) {
desc += "No extra info";
}
@@ -200,14 +211,32 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_tracking, menu);
+ return true;
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem item) {
+ boolean state;
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
+ case R.id.action_toggle_dismissible_tracking:
+ state = !item.isChecked();
+ mMapboxMap.getTrackingSettings().setDismissLocationTrackingOnGesture(state);
+ Toast.makeText(this, "Dismiss tracking mode on gesture = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
+ return true;
+ case R.id.action_toggle_dismissible_bearing:
+ state = !item.isChecked();
+ mMapboxMap.getTrackingSettings().setDismissBearingTrackingOnGesture(state);
+ Toast.makeText(this, "Dismiss bearing mode on gesture = " + state, Toast.LENGTH_SHORT).show();
+ item.setChecked(state);
default:
return super.onOptionsItemSelected(item);
}
}
-} \ No newline at end of file
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java
new file mode 100644
index 0000000000..fac7e34ce1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureAdapter.java
@@ -0,0 +1,55 @@
+package com.mapbox.mapboxsdk.testapp.adapter;
+
+import android.graphics.Typeface;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.activity.Feature;
+import com.mapbox.mapboxsdk.testapp.utils.FontCache;
+
+import java.util.List;
+
+public class FeatureAdapter extends RecyclerView.Adapter<FeatureAdapter.ViewHolder> {
+
+ private List<Feature> features;
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+
+ public TextView labelView;
+ public TextView descriptionView;
+
+ public ViewHolder(View v) {
+ super(v);
+ Typeface typeface = FontCache.get("Roboto-Regular.ttf",v.getContext());
+ labelView = (TextView) v.findViewById(R.id.nameView);
+ labelView.setTypeface(typeface);
+ descriptionView = (TextView) v.findViewById(R.id.descriptionView);
+ descriptionView.setTypeface(typeface);
+ }
+ }
+
+ public FeatureAdapter(List<Feature> features) {
+ this.features = features;
+ }
+
+ @Override
+ public FeatureAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main_feature, parent, false);
+ return new ViewHolder(v);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ holder.labelView.setText(features.get(position).getLabel());
+ holder.descriptionView.setText(features.get(position).getDescription());
+ }
+
+ @Override
+ public int getItemCount() {
+ return features.size();
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
new file mode 100644
index 0000000000..d86e06ea6d
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/adapter/FeatureSectionAdapter.java
@@ -0,0 +1,178 @@
+package com.mapbox.mapboxsdk.testapp.adapter;
+
+import android.content.Context;
+import android.support.annotation.IdRes;
+import android.support.annotation.LayoutRes;
+import android.support.annotation.NonNull;
+import android.support.v7.widget.RecyclerView;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.mapbox.mapboxsdk.testapp.utils.FontCache;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+public class FeatureSectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
+
+ private static final int SECTION_TYPE = 0;
+
+ private final Context context;
+ private final SparseArray<Section> sections;
+ private final RecyclerView.Adapter adapter;
+
+ @LayoutRes
+ private final int sectionRes;
+
+ @IdRes
+ private final int textRes;
+
+ private boolean valid = true;
+
+ public FeatureSectionAdapter(Context ctx, int sectionResourceId, int textResourceId, RecyclerView.Adapter baseAdapter) {
+ context = ctx;
+ sectionRes = sectionResourceId;
+ textRes = textResourceId;
+ adapter = baseAdapter;
+ sections = new SparseArray<>();
+ adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
+ @Override
+ public void onChanged() {
+ valid = adapter.getItemCount() > 0;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onItemRangeChanged(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeChanged(positionStart, itemCount);
+ }
+
+ @Override
+ public void onItemRangeInserted(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeInserted(positionStart, itemCount);
+ }
+
+ @Override
+ public void onItemRangeRemoved(int positionStart, int itemCount) {
+ valid = adapter.getItemCount() > 0;
+ notifyItemRangeRemoved(positionStart, itemCount);
+ }
+ });
+ }
+
+
+ public static class SectionViewHolder extends RecyclerView.ViewHolder {
+
+ public TextView title;
+
+ public SectionViewHolder(@NonNull View view, @IdRes int textRes) {
+ super(view);
+ title = (TextView) view.findViewById(textRes);
+ title.setTypeface(FontCache.get("Roboto-Medium.ttf", view.getContext()));
+ }
+ }
+
+ @Override
+ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
+ if (typeView == SECTION_TYPE) {
+ final View view = LayoutInflater.from(context).inflate(sectionRes, parent, false);
+ return new SectionViewHolder(view, textRes);
+ } else {
+ return adapter.onCreateViewHolder(parent, typeView - 1);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
+ if (isSectionHeaderPosition(position)) {
+ ((SectionViewHolder) sectionViewHolder).title.setText(sections.get(position).title);
+ } else {
+ adapter.onBindViewHolder(sectionViewHolder, getConvertedPosition(position));
+ }
+
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return isSectionHeaderPosition(position)
+ ? SECTION_TYPE
+ : adapter.getItemViewType(getConvertedPosition(position)) + 1;
+ }
+
+
+ public static class Section {
+ int firstPosition;
+ int sectionedPosition;
+ CharSequence title;
+
+ public Section(int firstPosition, CharSequence title) {
+ this.firstPosition = firstPosition;
+ this.title = title;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+ }
+
+
+ public void setSections(Section[] sections) {
+ this.sections.clear();
+
+ Arrays.sort(sections, new Comparator<Section>() {
+ @Override
+ public int compare(Section o, Section o1) {
+ return (o.firstPosition == o1.firstPosition)
+ ? 0
+ : ((o.firstPosition < o1.firstPosition) ? -1 : 1);
+ }
+ });
+
+ int offset = 0;
+ for (Section section : sections) {
+ section.sectionedPosition = section.firstPosition + offset;
+ this.sections.append(section.sectionedPosition, section);
+ ++offset;
+ }
+
+ notifyDataSetChanged();
+ }
+
+ public int getConvertedPosition(int sectionedPosition) {
+ if (isSectionHeaderPosition(sectionedPosition)) {
+ return RecyclerView.NO_POSITION;
+ }
+
+ int offset = 0;
+ for (int i = 0; i < sections.size(); i++) {
+ if (sections.valueAt(i).sectionedPosition > sectionedPosition) {
+ break;
+ }
+ --offset;
+ }
+ return sectionedPosition + offset;
+ }
+
+ public boolean isSectionHeaderPosition(int position) {
+ return sections.get(position) != null;
+ }
+
+
+ @Override
+ public long getItemId(int position) {
+ return isSectionHeaderPosition(position)
+ ? Integer.MAX_VALUE - sections.indexOfKey(position)
+ : adapter.getItemId(getConvertedPosition(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return (valid ? adapter.getItemCount() + sections.size() : 0);
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java
new file mode 100644
index 0000000000..66c51a1a13
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java
@@ -0,0 +1,69 @@
+package com.mapbox.mapboxsdk.testapp.model.activity;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class Feature implements Parcelable{
+
+ private String name;
+ private String label;
+ private String description;
+ private String category;
+
+ public Feature(String name, String label, String description, String category) {
+ this.name = name;
+ this.label = label;
+ this.description = description;
+ this.category = category;
+ }
+
+ private Feature(Parcel in) {
+ name = in.readString();
+ label = in.readString();
+ description = in.readString();
+ category = in.readString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getSimpleName() {
+ String[] split = name.split("\\.");
+ return split[split.length - 1];
+ }
+
+ public String getLabel() {
+ return label != null ? label : getSimpleName();
+ }
+
+ public String getDescription() {
+ return description != null ? description : "-";
+ }
+
+ public String getCategory() {
+ return category;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(name);
+ out.writeString(label);
+ out.writeString(description);
+ out.writeString(category);
+ }
+
+ public static final Parcelable.Creator<Feature> CREATOR
+ = new Parcelable.Creator<Feature>() {
+ public Feature createFromParcel(Parcel in) {
+ return new Feature(in);
+ }
+
+ public Feature[] newArray(int size) {
+ return new Feature[size];
+ }
+ };
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarker.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java
index 1ec5aa9c76..e0141586e4 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarker.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarker.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.annotations;
+package com.mapbox.mapboxsdk.testapp.model.annotations;
import com.mapbox.mapboxsdk.annotations.Marker;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarkerOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java
index 379a9210e5..a716518c22 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/annotations/CityStateMarkerOptions.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CityStateMarkerOptions.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.annotations;
+package com.mapbox.mapboxsdk.testapp.model.annotations;
import android.graphics.Bitmap;
import android.os.Parcel;
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java
new file mode 100644
index 0000000000..7503b48df3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarker.java
@@ -0,0 +1,24 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Marker;
+
+public class CountryMarker extends Marker {
+
+ private String abbrevName;
+ private int flagRes;
+
+ public CountryMarker(BaseMarkerOptions baseMarkerOptions, String abbrevName, int iconRes) {
+ super(baseMarkerOptions);
+ this.abbrevName = abbrevName;
+ this.flagRes = iconRes;
+ }
+
+ public String getAbbrevName() {
+ return abbrevName;
+ }
+
+ public int getFlagRes() {
+ return flagRes;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java
new file mode 100644
index 0000000000..ac1ff25bf2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerOptions.java
@@ -0,0 +1,75 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+public class CountryMarkerOptions extends BaseMarkerOptions<CountryMarker, CountryMarkerOptions> {
+
+ private String abbrevName;
+ private int flagRes;
+
+ public CountryMarkerOptions abbrevName(String name) {
+ abbrevName = name;
+ return getThis();
+ }
+
+ public CountryMarkerOptions flagRes(int imageRes) {
+ flagRes = imageRes;
+ return getThis();
+ }
+
+ public CountryMarkerOptions() {
+ }
+
+ private CountryMarkerOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
+ title(in.readString());
+ }
+
+ @Override
+ public CountryMarkerOptions getThis() {
+ return this;
+ }
+
+ @Override
+ public CountryMarker getMarker() {
+ return new CountryMarker(this, abbrevName, flagRes);
+ }
+
+ public static final Parcelable.Creator<CountryMarkerOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerOptions>() {
+ public CountryMarkerOptions createFromParcel(Parcel in) {
+ return new CountryMarkerOptions(in);
+ }
+
+ public CountryMarkerOptions[] newArray(int size) {
+ return new CountryMarkerOptions[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(position, flags);
+ out.writeString(snippet);
+ out.writeString(icon.getId());
+ out.writeParcelable(icon.getBitmap(), flags);
+ out.writeString(title);
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java
new file mode 100644
index 0000000000..64f0565026
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerView.java
@@ -0,0 +1,24 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+
+public class CountryMarkerView extends MarkerView {
+
+ private String abbrevName;
+ private int flagRes;
+
+ public CountryMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String abbrevName, int flagRes) {
+ super(baseMarkerViewOptions);
+ this.abbrevName = abbrevName;
+ this.flagRes = flagRes;
+ }
+
+ public String getAbbrevName() {
+ return abbrevName;
+ }
+
+ public int getFlagRes() {
+ return flagRes;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
new file mode 100644
index 0000000000..c4ef4a8d13
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java
@@ -0,0 +1,104 @@
+package com.mapbox.mapboxsdk.testapp.model.annotations;
+
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions;
+import com.mapbox.mapboxsdk.annotations.Icon;
+import com.mapbox.mapboxsdk.annotations.IconFactory;
+import com.mapbox.mapboxsdk.annotations.MarkerView;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+public class CountryMarkerViewOptions extends BaseMarkerViewOptions<CountryMarkerView, CountryMarkerViewOptions> {
+
+ private String abbrevName;
+ private int flagRes;
+
+ public CountryMarkerViewOptions() {
+ }
+
+ protected CountryMarkerViewOptions(Parcel in) {
+ position((LatLng) in.readParcelable(LatLng.class.getClassLoader()));
+ snippet(in.readString());
+ title(in.readString());
+ flat(in.readByte() != 0);
+ anchor(in.readFloat(), in.readFloat());
+ infoWindowAnchor(in.readFloat(), in.readFloat());
+ selectAnimatorResource(in.readInt());
+ deselectAnimatorResource(in.readInt());
+ rotation(in.readInt());
+ if (in.readByte() != 0) {
+ // this means we have an icon
+ String iconId = in.readString();
+ Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader());
+ Icon icon = IconFactory.recreate(iconId, iconBitmap);
+ icon(icon);
+ }
+ abbrevName(in.readString());
+ flagRes(in.readInt());
+ }
+
+ @Override
+ public CountryMarkerViewOptions getThis() {
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(getPosition(), flags);
+ out.writeString(getSnippet());
+ out.writeString(getTitle());
+ out.writeByte((byte) (isFlat() ? 1 : 0));
+ out.writeFloat(getAnchorU());
+ out.writeFloat(getAnchorV());
+ out.writeFloat(getInfoWindowAnchorU());
+ out.writeFloat(getInfoWindowAnchorV());
+ out.writeInt(getSelectAnimRes());
+ out.writeInt(getDeselectAnimRes());
+ out.writeInt(getRotation());
+ Icon icon = getIcon();
+ out.writeByte((byte) (icon != null ? 1 : 0));
+ if (icon != null) {
+ out.writeString(getIcon().getId());
+ out.writeParcelable(getIcon().getBitmap(), flags);
+ }
+ out.writeString(abbrevName);
+ out.writeInt(flagRes);
+ }
+
+ @Override
+ public CountryMarkerView getMarker() {
+ return new CountryMarkerView(this, abbrevName, flagRes);
+ }
+
+ public CountryMarkerViewOptions abbrevName(String abbrevName) {
+ this.abbrevName = abbrevName;
+ return getThis();
+ }
+
+ public CountryMarkerViewOptions flagRes(int flagRes) {
+ this.flagRes = flagRes;
+ return getThis();
+ }
+
+ public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR
+ = new Parcelable.Creator<CountryMarkerViewOptions>() {
+ public CountryMarkerViewOptions createFromParcel(Parcel in) {
+ return new CountryMarkerViewOptions(in);
+ }
+
+ public CountryMarkerViewOptions[] newArray(int size) {
+ return new CountryMarkerViewOptions[size];
+ }
+ };
+
+
+} \ No newline at end of file
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
new file mode 100644
index 0000000000..60ed6168cb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/constants/AppConstant.java
@@ -0,0 +1,6 @@
+package com.mapbox.mapboxsdk.testapp.model.constants;
+
+public class AppConstant {
+
+ public final static int STYLE_VERSION = 9;
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/layers/ExampleCustomLayer.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java
index 3a97c26595..2901060459 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/layers/ExampleCustomLayer.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.layers;
+package com.mapbox.mapboxsdk.testapp.model.customlayer;
public class ExampleCustomLayer {
static {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/DownloadRegionDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
index 81b681cc50..3c2d1cab5e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/DownloadRegionDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineDownloadRegionDialog.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.offline;
+package com.mapbox.mapboxsdk.testapp.model.other;
import android.app.Activity;
import android.app.Dialog;
@@ -15,9 +15,9 @@ import com.mapbox.mapboxsdk.testapp.R;
/**
* Created by antonio on 2/17/16.
*/
-public class DownloadRegionDialog extends DialogFragment {
+public class OfflineDownloadRegionDialog extends DialogFragment {
- private final static String LOG_TAG = "DownloadRegionDialog";
+ private final static String LOG_TAG = "OfflineDownloadRegionDialog";
public interface DownloadRegionDialogListener {
void onDownloadRegionDialogPositiveClick(String regionName);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/ListRegionsDialog.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
index 50df71ad00..e00465a9b1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/offline/ListRegionsDialog.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/other/OfflineListRegionsDialog.java
@@ -1,4 +1,4 @@
-package com.mapbox.mapboxsdk.testapp.offline;
+package com.mapbox.mapboxsdk.testapp.model.other;
import android.app.Dialog;
import android.content.DialogInterface;
@@ -15,9 +15,9 @@ import java.util.ArrayList;
/**
* Created by antonio on 2/17/16.
*/
-public class ListRegionsDialog extends DialogFragment {
+public class OfflineListRegionsDialog extends DialogFragment {
- private final static String LOG_TAG = "ListRegionsDialog";
+ private final static String LOG_TAG = "OfflineListRegionsDialog";
public final static String ITEMS = "ITEMS";
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiAccess.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiAccess.java
deleted file mode 100644
index 20ca2913e2..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ApiAccess.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.utils;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-
-/**
- * {@code ApiAccess} provides a method to load the Mapbox access token.
- */
-public final class ApiAccess {
-
- /**
- * <p>
- * Returns the Mapbox access token set in the app resources.
- * </p>
- * It will first search the application manifest for a {@link MapboxConstants#KEY_META_DATA_MANIFEST}
- * meta-data value. If not found it will then attempt to load the access token from the
- * {@code res/raw/token.txt} 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.
- * @see MapboxConstants#KEY_META_DATA_MANIFEST
- */
- public static String getToken(@NonNull Context context) {
- try {
- // read out AndroidManifest
- PackageManager packageManager = context.getPackageManager();
- ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
- String token = appInfo.metaData.getString(MapboxConstants.KEY_META_DATA_MANIFEST);
- if (token == null || token.isEmpty()) {
- throw new IllegalArgumentException();
- }
- return token;
- } catch (Exception e) {
- // 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/utils/FontCache.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
new file mode 100644
index 0000000000..46552fb7ae
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/FontCache.java
@@ -0,0 +1,27 @@
+package com.mapbox.mapboxsdk.testapp.utils;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.util.Log;
+
+import com.mapbox.mapboxsdk.constants.MapboxConstants;
+
+import java.util.Hashtable;
+
+public class FontCache {
+
+ private static Hashtable<String, Typeface> fontCache = new Hashtable<>();
+
+ public static Typeface get(String name, Context context) {
+ Typeface tf = fontCache.get(name);
+ if (tf == null) {
+ try {
+ tf = Typeface.createFromAsset(context.getAssets(), name);
+ fontCache.put(name, tf);
+ } catch (Exception e) {
+ Log.e(MapboxConstants.TAG, "Font not found");
+ }
+ }
+ return tf;
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java
new file mode 100644
index 0000000000..51e09f3593
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ItemClickSupport.java
@@ -0,0 +1,95 @@
+package com.mapbox.mapboxsdk.testapp.utils;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.mapbox.mapboxsdk.testapp.R;
+
+public class ItemClickSupport {
+ private final RecyclerView mRecyclerView;
+ private OnItemClickListener mOnItemClickListener;
+ private OnItemLongClickListener mOnItemLongClickListener;
+ private View.OnClickListener mOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mOnItemClickListener != null) {
+ RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
+ mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
+ }
+ }
+ };
+ private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (mOnItemLongClickListener != null) {
+ RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
+ return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
+ }
+ return false;
+ }
+ };
+ private RecyclerView.OnChildAttachStateChangeListener mAttachListener
+ = new RecyclerView.OnChildAttachStateChangeListener() {
+ @Override
+ public void onChildViewAttachedToWindow(View view) {
+ if (mOnItemClickListener != null) {
+ view.setOnClickListener(mOnClickListener);
+ }
+ if (mOnItemLongClickListener != null) {
+ view.setOnLongClickListener(mOnLongClickListener);
+ }
+ }
+
+ @Override
+ public void onChildViewDetachedFromWindow(View view) {
+
+ }
+ };
+
+ private ItemClickSupport(RecyclerView recyclerView) {
+ mRecyclerView = recyclerView;
+ mRecyclerView.setTag(R.id.item_click_support, this);
+ mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
+ }
+
+ public static ItemClickSupport addTo(RecyclerView view) {
+ ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
+ if (support == null) {
+ support = new ItemClickSupport(view);
+ }
+ return support;
+ }
+
+ public static ItemClickSupport removeFrom(RecyclerView view) {
+ ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
+ if (support != null) {
+ support.detach(view);
+ }
+ return support;
+ }
+
+ public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
+ mOnItemClickListener = listener;
+ return this;
+ }
+
+ public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
+ mOnItemLongClickListener = listener;
+ return this;
+ }
+
+ private void detach(RecyclerView view) {
+ view.removeOnChildAttachStateChangeListener(mAttachListener);
+ view.setTag(R.id.item_click_support, null);
+ }
+
+ public interface OnItemClickListener {
+
+ void onItemClicked(RecyclerView recyclerView, int position, View v);
+ }
+
+ public interface OnItemLongClickListener {
+
+ boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
+ }
+} \ No newline at end of file
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 6789b401eb..544e737780 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
@@ -23,7 +23,7 @@ import android.util.Log;
/**
* A utility class to help log timings splits throughout a method call.
* Typical usage is:
- * <p/>
+ *
* <pre>
* TimingLogger timings = new TimingLogger(TAG, "methodA");
* // ... do some work A ...
@@ -34,9 +34,9 @@ import android.util.Log;
* timings.addSplit("work C");
* timings.dumpToLog();
* </pre>
- * <p/>
+ *
* <p>The dumpToLog call would add the following to the log:</p>
- * <p/>
+ *
* <pre>
* D/TAG ( 3459): methodA: begin
* D/TAG ( 3459): methodA: 9 ms, work A
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/rotate_360.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/rotate_360.xml
new file mode 100644
index 0000000000..e3569966d2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/rotate_360.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="rotation"
+ android:valueFrom="0"
+ android:valueTo="360"
+ android:valueType="floatType"/>
+</set> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_down.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_down.xml
new file mode 100644
index 0000000000..d1067b09c2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_down.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="scaleX"
+ android:duration="300"
+ android:valueTo="1"/>
+ <objectAnimator
+ android:propertyName="scaleY"
+ android:duration="300"
+ android:valueTo="1"/>
+</set> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_up.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_up.xml
new file mode 100644
index 0000000000..b43ed05513
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/animator/scale_up.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+ <objectAnimator
+ android:propertyName="scaleX"
+ android:duration="300"
+ android:valueTo="2"/>
+ <objectAnimator
+ android:propertyName="scaleY"
+ android:duration="300"
+ android:valueTo="2"/>
+</set> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_us.png b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_us.png
new file mode 100644
index 0000000000..d09e068fe9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxhdpi/ic_us.png
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_add_a_photo_black_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_add_a_photo_black_24dp.xml
new file mode 100644
index 0000000000..3d2ba42f3e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_add_a_photo_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M3,4L3,1h2v3h3v2L5,6v3L3,9L3,6L0,6L0,4h3zM6,10L6,7h3L9,4h7l1.83,2L21,6c1.1,0 2,0.9 2,2v12c0,1.1 -0.9,2 -2,2L5,22c-1.1,0 -2,-0.9 -2,-2L3,10h3zM13,19c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5 -5,2.24 -5,5 2.24,5 5,5zM9.8,14c0,1.77 1.43,3.2 3.2,3.2s3.2,-1.43 3.2,-3.2 -1.43,-3.2 -3.2,-3.2 -3.2,1.43 -3.2,3.2z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_blur_on_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_blur_on_24dp.xml
deleted file mode 100644
index b032703e38..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_blur_on_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M6,13c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,-8c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm-3,0.5c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5 0.5,-0.22 0.5,-0.5 -0.22,-0.5 -0.5,-0.5zM6,5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm15,5.5c0.28,0 0.5,-0.22 0.5,-0.5s-0.22,-0.5 -0.5,-0.5 -0.5,0.22 -0.5,0.5 0.22,0.5 0.5,0.5zM14,7c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1 -1,0.45 -1,1 0.45,1 1,1zm0,-3.5c0.28,0 0.5,-0.22 0.5,-0.5s-0.22,-0.5 -0.5,-0.5 -0.5,0.22 -0.5,0.5 0.22,0.5 0.5,0.5zm-11,10c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5 0.5,-0.22 0.5,-0.5 -0.22,-0.5 -0.5,-0.5zm7,7c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5 0.5,-0.22 0.5,-0.5 -0.22,-0.5 -0.5,-0.5zm0,-17c0.28,0 0.5,-0.22 0.5,-0.5s-0.22,-0.5 -0.5,-0.5 -0.5,0.22 -0.5,0.5 0.22,0.5 0.5,0.5zM10,7c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1 -1,0.45 -1,1 0.45,1 1,1zm0,5.5c-0.83,0 -1.5,0.67 -1.5,1.5s0.67,1.5 1.5,1.5 1.5,-0.67 1.5,-1.5 -0.67,-1.5 -1.5,-1.5zm8,0.5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,-8c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,-4c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm3,8.5c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5 0.5,-0.22 0.5,-0.5 -0.22,-0.5 -0.5,-0.5zM14,17c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm0,3.5c-0.28,0 -0.5,0.22 -0.5,0.5s0.22,0.5 0.5,0.5 0.5,-0.22 0.5,-0.5 -0.22,-0.5 -0.5,-0.5zm-4,-12c-0.83,0 -1.5,0.67 -1.5,1.5s0.67,1.5 1.5,1.5 1.5,-0.67 1.5,-1.5 -0.67,-1.5 -1.5,-1.5zm0,8.5c-0.55,0 -1,0.45 -1,1s0.45,1 1,1 1,-0.45 1,-1 -0.45,-1 -1,-1zm4,-4.5c-0.83,0 -1.5,0.67 -1.5,1.5s0.67,1.5 1.5,1.5 1.5,-0.67 1.5,-1.5 -0.67,-1.5 -1.5,-1.5zm0,-4c-0.83,0 -1.5,0.67 -1.5,1.5s0.67,1.5 1.5,1.5 1.5,-0.67 1.5,-1.5 -0.67,-1.5 -1.5,-1.5z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_bug_report_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_bug_report_24dp.xml
deleted file mode 100644
index 909e11f923..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_bug_report_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M20,8h-2.81c-0.45,-0.78 -1.07,-1.45 -1.82,-1.96L17,4.41 15.59,3l-2.17,2.17C12.96,5.06 12.49,5 12,5c-0.49,0 -0.96,0.06 -1.41,0.17L8.41,3 7,4.41l1.62,1.63C7.88,6.55 7.26,7.22 6.81,8H4v2h2.09c-0.05,0.33 -0.09,0.66 -0.09,1v1H4v2h2v1c0,0.34 0.04,0.67 0.09,1H4v2h2.81c1.04,1.79 2.97,3 5.19,3s4.15,-1.21 5.19,-3H20v-2h-2.09c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1H20V8zm-6,8h-4v-2h4v2zm0,-4h-4v-2h4v2z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_compare_arrows_black_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_compare_arrows_black_24dp.xml
deleted file mode 100644
index 23417034d6..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_compare_arrows_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3zM14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_crop_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_crop_24dp.xml
deleted file mode 100644
index 4f72bed69c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_crop_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M17,15h2V7c0,-1.1 -0.9,-2 -2,-2H9v2h8v8zM7,17V1H5v4H1v2h4v10c0,1.1 0.9,2 2,2h10v4h2v-4h4v-2H7z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions.xml
deleted file mode 100644
index 2c474849a4..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_directions.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M21.71,11.29l-9,-9c-0.39,-0.39 -1.02,-0.39 -1.41,0l-9,9c-0.39,0.39 -0.39,1.02 0,1.41l9,9c0.39,0.39 1.02,0.39 1.41,0l9,-9c0.39,-0.38 0.39,-1.01 0,-1.41zM14,14.5V12h-4v3H8v-4c0,-0.55 0.45,-1 1,-1h5V7.5l3.5,3.5 -3.5,3.5z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dns_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dns_24dp.xml
deleted file mode 100644
index 5b7b1bce6a..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dns_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M20,13H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-6c0,-0.55 -0.45,-1 -1,-1zM7,19c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM20,3H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1zM7,9c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dynamic_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dynamic_marker.xml
deleted file mode 100644
index e16f6b317d..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_dynamic_marker.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M7,7h10v3l4,-4 -4,-4v3H5v6h2V7zm10,10H7v-3l-4,4 4,4v-3h12v-6h-2v4zm-4,-2V9h-1l-2,1v1h1.5v4H13z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_center_focus_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_center_focus_24dp.xml
deleted file mode 100644
index 455c18f3d1..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_center_focus_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M5,15H3v4c0,1.1 0.9,2 2,2h4v-2H5v-4zM5,5h4V3H5c-1.1,0 -2,0.9 -2,2v4h2V5zm14,-2h-4v2h4v4h2V5c0,-1.1 -0.9,-2 -2,-2zm0,16h-4v2h4c1.1,0 2,-0.9 2,-2v-4h-2v4zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_none_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_none_24dp.xml
deleted file mode 100644
index 9b16b15571..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_filter_none_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M3,5H1v16c0,1.1 0.9,2 2,2h16v-2H3V5zm18,-4H7c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-2 -2,-2zm0,16H7V3h14v14z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_find_replace_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_find_replace_24dp.xml
deleted file mode 100644
index 26bb56ca5a..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_find_replace_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M11,6c1.38,0 2.63,0.56 3.54,1.46L12,10h6V4l-2.05,2.05C14.68,4.78 12.93,4 11,4c-3.53,0 -6.43,2.61 -6.92,6H6.1c0.46,-2.28 2.48,-4 4.9,-4zm5.64,9.14c0.66,-0.9 1.12,-1.97 1.28,-3.14H15.9c-0.46,2.28 -2.48,4 -4.9,4 -1.38,0 -2.63,-0.56 -3.54,-1.46L10,12H4v6l2.05,-2.05C7.32,17.22 9.07,18 11,18c1.55,0 2.98,-0.51 4.14,-1.36L20,21.49 21.49,20l-4.85,-4.86z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_back_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_back_24dp.xml
deleted file mode 100644
index da636f975c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_back_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M9,7H7v2h2V7zm0,4H7v2h2v-2zm0,-8c-1.11,0 -2,0.9 -2,2h2V3zm4,12h-2v2h2v-2zm6,-12v2h2c0,-1.1 -0.9,-2 -2,-2zm-6,0h-2v2h2V3zM9,17v-2H7c0,1.1 0.89,2 2,2zm10,-4h2v-2h-2v2zm0,-4h2V7h-2v2zm0,8c1.1,0 2,-0.9 2,-2h-2v2zM5,7H3v12c0,1.1 0.89,2 2,2h12v-2H5V7zm10,-2h2V3h-2v2zm0,12h2v-2h-2v2z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_front_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_front_24dp.xml
deleted file mode 100644
index 7d78638595..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_flip_to_front_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M3,13h2v-2H3v2zm0,4h2v-2H3v2zm2,4v-2H3c0,1.1 0.89,2 2,2zM3,9h2V7H3v2zm12,12h2v-2h-2v2zm4,-18H9c-1.11,0 -2,0.9 -2,2v10c0,1.1 0.89,2 2,2h10c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2zm0,12H9V5h10v10zm-8,6h2v-2h-2v2zm-4,0h2v-2H7v2z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_gps_fixed_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_gps_fixed_24dp.xml
deleted file mode 100644
index a8fa0207e6..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_gps_fixed_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#000000"
- android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zm8.94,3c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94V1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11H1v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94V23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94H23v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_adapter.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_adapter.xml
deleted file mode 100644
index 0d4c724aa9..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_adapter.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_concurrent.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_concurrent.xml
deleted file mode 100644
index 9b16b15571..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_infowindow_concurrent.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M3,5H1v16c0,1.1 0.9,2 2,2h16v-2H3V5zm18,-4H7c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-2 -2,-2zm0,16H7V3h14v14z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_menu_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_24dp.xml
index 8c16289f27..944b526c5c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_menu_24dp.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_24dp.xml
@@ -5,5 +5,5 @@
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
- android:pathData="M3,18h18v-2H3v2zm0,-5h18v-2H3v2zm0,-7v2h18V6H3z"/>
+ android:pathData="M11.99,18.54l-7.37,-5.73L3,14.07l9,7 9,-7 -1.63,-1.27 -7.38,5.74zM12,16l7.36,-5.73L21,9l-9,-7 -9,7 1.63,1.27L12,16z"/>
</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_clear_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_clear_24dp.xml
new file mode 100644
index 0000000000..249f57fc65
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_layers_clear_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M19.81,14.99l1.19,-0.92 -1.43,-1.43 -1.19,0.92 1.43,1.43zM19.36,10.27L21,9l-9,-7 -2.91,2.27 7.87,7.88 2.4,-1.88zM3.27,1L2,2.27l4.22,4.22L3,9l1.63,1.27L12,16l2.1,-1.63 1.43,1.43L12,18.54l-7.37,-5.73L3,14.07l9,7 4.95,-3.85L20.73,21 22,19.73 3.27,1z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location.xml
deleted file mode 100644
index 027a644721..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zm0,9.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled_24dp.xml
new file mode 100644
index 0000000000..4fedff778b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_map_padding.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_map_padding.xml
deleted file mode 100644
index 60b75a5493..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_map_padding.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_my_location_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_my_location_24dp.xml
new file mode 100644
index 0000000000..eb979016bf
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_my_location_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_navigation_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_navigation_24dp.xml
deleted file mode 100644
index 6ab15dc6b3..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_navigation_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M12,2L4.5,20.29l0.71,0.71L12,18l6.79,3 0.71,-0.71z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_wallpaper_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_wallpaper_24dp.xml
deleted file mode 100644
index 1b885337da..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_wallpaper_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M4,4h7V2H4c-1.1,0 -2,0.9 -2,2v7h2V4zm6,9l-4,5h12l-3,-4 -2.03,2.71L10,13zm7,-4.5c0,-0.83 -0.67,-1.5 -1.5,-1.5S14,7.67 14,8.5s0.67,1.5 1.5,1.5S17,9.33 17,8.5zM20,2h-7v2h7v7h2V4c0,-1.1 -0.9,-2 -2,-2zm0,18h-7v2h7c1.1,0 2,-0.9 2,-2v-7h-2v7zM4,13H2v7c0,1.1 0.9,2 2,2h7v-2H4v-7z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_widgets_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_widgets_24dp.xml
deleted file mode 100644
index 9329bfc677..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_now_widgets_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M13,13v8h8v-8h-8zM3,21h8v-8H3v8zM3,3v8h8V3H3zm13.66,-1.31L11,7.34 16.66,13l5.66,-5.66 -5.66,-5.65z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pin_drop_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pin_drop_24dp.xml
deleted file mode 100644
index 47aff99532..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pin_drop_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M18,8c0,-3.31 -2.69,-6 -6,-6S6,4.69 6,8c0,4.5 6,11 6,11s6,-6.5 6,-11zm-8,0c0,-1.1 0.9,-2 2,-2s2,0.9 2,2 -0.89,2 -2,2c-1.1,0 -2,-0.9 -2,-2zM5,20v2h14v-2H5z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_place_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_place_24dp.xml
deleted file mode 100644
index e778c37c4c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_place_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zm0,9.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_mapboxmap.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_refresh_24dp.xml
index 3482fa9dbc..20cd9a07d8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_mapboxmap.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_refresh_24dp.xml
@@ -5,5 +5,5 @@
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFF"
- android:pathData="M12,11.55C9.64,9.35 6.48,8 3,8v11c3.48,0 6.64,1.35 9,3.55 2.36,-2.19 5.52,-3.55 9,-3.55V8c-3.48,0 -6.64,1.35 -9,3.55zM12,8c1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3 1.34,3 3,3z"/>
+ android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_tilt.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_tilt.xml
deleted file mode 100644
index d5c67efbb7..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_tilt.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M7.77,6.76L6.23,5.48 0.82,12l5.41,6.52 1.54,-1.28L3.42,12l4.35,-5.24zM7,13h2v-2H7v2zm10,-2h-2v2h2v-2zm-6,2h2v-2h-2v2zm6.77,-7.52l-1.54,1.28L20.58,12l-4.35,5.24 1.54,1.28L23.18,12l-5.41,-6.52z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_transform_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_transform_24dp.xml
deleted file mode 100644
index b8448abb14..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_transform_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M22,18v-2H8V4h2L7,1 4,4h2v2H2v2h4v8c0,1.1 0.9,2 2,2h8v2h-2l3,3 3,-3h-2v-2h4zM10,8h6v6h2V8c0,-1.1 -0.9,-2 -2,-2h-6v2z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_trending_up_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_trending_up_24dp.xml
deleted file mode 100644
index 830f3036f2..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_trending_up_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0">
- <path
- android:fillColor="#FFFFFF"
- android:pathData="M16,6l2.29,2.29 -4.88,4.88 -4,-4L2,16.59 3.41,18l6,-6 4,4 6.3,-6.29L22,12V6z" />
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/line_divider.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/line_divider.xml
new file mode 100644
index 0000000000..2dc6b4a008
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/line_divider.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <size
+ android:width="1dp"
+ android:height="1dp" />
+
+ <solid android:color="@android:color/darker_gray" />
+
+</shape> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
index 6a09109ea8..8c025d999c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animated_marker.xml
@@ -2,6 +2,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
@@ -15,6 +16,7 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ app:style_url="@string/style_light"
android:layout_below="@id/toolbar" />
-</RelativeLayout> \ No newline at end of file
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera.xml
deleted file mode 100644
index 0b318d781b..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
-
- <com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/cameraMapView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@+id/toolbar"/>
-
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/button_camera_move"
- android:id="@+id/cameraMoveButton"
- android:layout_margin="@dimen/fab_margin"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:background="@color/white"/>
-
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/button_camera_ease"
- android:id="@+id/cameraEaseButton"
- android:layout_alignTop="@+id/cameraMoveButton"
- android:layout_centerHorizontal="true"
- android:background="@color/white"/>
-
- <Button
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/button_camera_animate"
- android:id="@+id/cameraAnimateButton"
- android:layout_alignBottom="@+id/cameraEaseButton"
- android:layout_alignParentRight="true"
- android:layout_marginRight="@dimen/fab_margin"
- android:background="@color/white"/>
-
-</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml
new file mode 100644
index 0000000000..5a5fb5f604
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animation_types.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@+id/toolbar"
+ app:center_latitude="51.50325"
+ app:center_longitude="-0.11968"
+ app:zoom="15" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:orientation="horizontal"
+ android:weightSum="3">
+
+ <Button
+ android:id="@+id/cameraMoveButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_camera_move" />
+
+ <Button
+ android:id="@+id/cameraEaseButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_camera_ease" />
+
+ <Button
+ android:id="@+id/cameraAnimateButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_camera_animate" />
+
+ </LinearLayout>
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml
new file mode 100644
index 0000000000..2e08f79e95
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_position.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <android.support.design.widget.CoordinatorLayout
+ android:id="@+id/coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:style_url="@string/style_mapbox_streets" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_input_24dp"
+ app:backgroundTint="@android:color/white" />
+
+ </android.support.design.widget.CoordinatorLayout>
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animate_coordinate.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_layer.xml
index 73592448b2..2b52f7d8fd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_animate_coordinate.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_layer.xml
@@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
+
+ </android.support.v7.widget.Toolbar>
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_below="@+id/toolbar">
+ >
<android.support.design.widget.CoordinatorLayout
android:id="@+id/coordinator_layout"
@@ -33,13 +36,12 @@
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
- android:src="@drawable/ic_animate_coordinates"
- app:backgroundTint="@color/white" />
+ android:src="@drawable/ic_layers_24dp"
+ app:backgroundTint="@android:color/white"
+ />
</android.support.design.widget.CoordinatorLayout>
</FrameLayout>
-</RelativeLayout>
-
-
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_debug_mode.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_debug_mode.xml
new file mode 100644
index 0000000000..36adfbc6e9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_debug_mode.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
+
+ </android.support.v7.widget.Toolbar>
+
+ <FrameLayout
+ android:id="@+id/content_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <android.support.design.widget.CoordinatorLayout
+ android:id="@+id/coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@+id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fabDebug"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_marginBottom="82dp"
+ android:layout_marginRight="@dimen/fab_margin"
+ android:src="@drawable/ic_refresh_24dp"
+ app:backgroundTint="@color/accent"
+ app:layout_anchorGravity="top" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fabStyles"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_layers_24dp"
+ app:backgroundTint="@color/primary" />
+
+ </android.support.design.widget.CoordinatorLayout>
+
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
index d93a6d1eb5..cce6883541 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_geocoder.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -15,7 +16,10 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_weight="5" />
+ android:layout_weight="5"
+ app:center_latitude="38.90962"
+ app:center_longitude="-77.04341"
+ app:zoom="15" />
<TextView
android:id="@+id/message"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml
index 0b539daac3..41956385f9 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_main.xml
@@ -1,69 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-
-<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:id="@+id/drawer_layout"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:orientation="vertical">
- <RelativeLayout
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
-
- <FrameLayout
- android:id="@+id/content_frame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@+id/toolbar">
-
- <android.support.design.widget.CoordinatorLayout
- android:id="@+id/coordinator_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/mainMapView"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <TextView
- android:id="@+id/view_fps"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="10dp"
- android:text="@string/label_fps"
- android:textAppearance="?android:attr/textAppearanceLarge" />
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
-
- <android.support.design.widget.FloatingActionButton
- android:id="@+id/locationFAB"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end|bottom"
- android:layout_margin="@dimen/fab_margin"
- android:src="@drawable/ic_gps_fixed_24dp"
- app:backgroundTint="@color/white" />
-
- </android.support.design.widget.CoordinatorLayout>
-
- </FrameLayout>
-
- </RelativeLayout>
-
- <android.support.design.widget.NavigationView
- android:id="@+id/nav_view"
- android:layout_width="wrap_content"
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/recyclerView"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="start"
- android:fitsSystemWindows="true"
- app:menu="@menu/menu_drawer" />
+ android:scrollbars="vertical" />
-</android.support.v4.widget.DrawerLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
index 873e5d18a1..6a90a8eafb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_manual_zoom.xml
@@ -11,6 +11,8 @@
android:background="@color/primary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+
<com.mapbox.mapboxsdk.maps.MapView
android:layout_below="@id/toolbar"
android:id="@+id/manualZoomMapView"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_fragment.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_fragment.xml
index ce516f6a1b..a421f21ede 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_fragment.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_fragment.xml
@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- tools:context="com.mapbox.mapboxsdk.testapp.MapFragmentActivity">
+ tools:context=".activity.fragment.MapFragmentActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_padding.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_padding.xml
index aa3c50d65c..f0e635f29c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_padding.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_map_padding.xml
@@ -40,8 +40,6 @@
android:layout_width="@dimen/map_padding_right"
android:layout_height="match_parent"
android:layout_gravity="end"
- android:layout_marginLeft="@dimen/map_padding_left"
- android:layout_marginStart="@dimen/map_padding_left"
android:alpha="0.5"
android:layout_marginTop="?attr/actionBarSize"
android:background="@color/mapbox_blue" />
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
index ce108ba129..90cb1a90b3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_bulk.xml
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+ android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
+ android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
@@ -20,12 +19,32 @@
</android.support.v7.widget.Toolbar>
<com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/mapView"
+ android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:center_latitude="38.897705003219784"
- app:center_longitude="-77.03655168667463"
+ app:center_latitude="38.87031"
+ android:layout_below="@id/toolbar"
+ app:center_longitude="-77.00897"
app:style_url="@string/style_mapbox_streets"
- app:zoom="15" />
+ app:zoom="10" />
-</LinearLayout>
+ <TextView
+ android:id="@+id/countView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/toolbar"
+ android:padding="16dp"
+ android:textSize="20sp"/>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_animate_coordinates" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml
new file mode 100644
index 0000000000..5d285958f1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_marker_view.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@id/toolbar"
+ app:center_latitude="38.907192"
+ app:center_longitude="-77.036871"
+ app:style_url="@string/style_mapbox_streets"
+ app:zoom="12" />
+
+ <TextView
+ android:id="@+id/countView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/toolbar"
+ android:padding="16dp"
+ android:textSize="20sp" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
index 873e5d18a1..611766acb1 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_maxmin_zoom.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
@@ -12,9 +13,13 @@
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<com.mapbox.mapboxsdk.maps.MapView
- android:layout_below="@id/toolbar"
- android:id="@+id/manualZoomMapView"
+ android:id="@+id/mapView"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_below="@id/toolbar"
+ app:center_latitude="-1.063510"
+ app:center_longitude=" 32.895425"
+ app:style_url="@string/style_satellite_streets"
+ app:zoom="4" />
</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapboxmap.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml
index eccd3ea8eb..75218423fb 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_mapboxmap.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml
@@ -1,24 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
+ android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
- <com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/mapView"
+ <FrameLayout
+ android:id="@id/progress"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:style_url="@string/style_mapbox_streets"
- app:center_latitude="38.897705003219784"
- app:center_longitude="-77.03655168667463"
- app:zoom="15" />
+ android:layout_height="match_parent">
+
+ <android.support.v4.widget.ContentLoadingProgressBar
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center" />
+
+ </FrameLayout>
+
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
new file mode 100644
index 0000000000..af755c72a1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_below="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:orientation="horizontal"
+ android:weightSum="3">
+
+ <Button
+ android:id="@+id/default_user_dot_coloring_button"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_user_dot_default" />
+
+ <Button
+ android:id="@+id/tint_user_dot_button"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_user_dot_tint" />
+
+ <Button
+ android:id="@+id/user_accuracy_ring_tint_button"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/button_user_accuracy_ring_tint" />
+
+ </LinearLayout>
+
+</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml
new file mode 100644
index 0000000000..e8204117a3
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:mapbox="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <android.support.design.widget.CoordinatorLayout
+ android:id="@id/coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fabLocationToggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_my_location_24dp"
+ tools:backgroundTint="@color/primary" />
+
+ </android.support.design.widget.CoordinatorLayout>
+
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
index 699fa4be6b..19c30dbb8d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
@@ -42,7 +42,9 @@
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ app:my_location_foreground_tint="@color/primary"
+ app:my_location_accuracy_tint="@color/primary"
app:style_url="@string/style_mapbox_streets"
app:zoom="15" />
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_tilt.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polygon.xml
index eae320c750..1c60deb328 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_tilt.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polygon.xml
@@ -1,24 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
- android:id="@+id/toolbar"
+ android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
- <com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/tiltMapView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:center_latitude="38.90252"
- app:center_longitude="-77.02291"
- app:style_url="@string/style_mapbox_streets"
- app:zoom="11" />
-
</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
index 7875fc2021..8ff9f82b09 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_polyline.xml
@@ -19,6 +19,7 @@
android:layout_below="@+id/toolbar"
app:center_latitude="47.798202"
app:center_longitude="7.573781"
+ app:attribution_tint="@android:color/holo_green_dark"
app:style_url="@string/style_mapbox_streets"
app:zoom="4" />
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
index 39ff128c69..9378900dc3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_press_for_marker.xml
@@ -1,15 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/activity_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<android.support.v7.widget.Toolbar
- android:id="@+id/secondToolBar"
+ android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
-</LinearLayout>
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@+id/pressForMarkerMapView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/toolbar"/>
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
index 17e0f35729..eb0d0a2245 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_scroll_by.xml
@@ -79,6 +79,10 @@
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
+ app:center_latitude="37.176546"
+ app:center_longitude="-3.599007"
+ app:style_url="@string/style_emerald"
+ app:zoom="15"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml
new file mode 100644
index 0000000000..b9701b53e0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_snapshot.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?attr/actionBarSize"
+ android:background="@color/primary"
+ android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_below="@+id/toolbar"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/imageView"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:background="@color/primary" />
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ app:style_url="@string/style_emerald" />
+
+ </LinearLayout>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_margin="@dimen/fab_margin"
+ android:src="@drawable/ic_add_a_photo_black_24dp"
+ app:backgroundTint="@android:color/white" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/dialog_camera_position.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/dialog_camera_position.xml
new file mode 100644
index 0000000000..c1ffa7d203
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/dialog_camera_position.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/text_lat"
+ android:layout_width="72dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="4dp"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:text="Latitude"
+ android:textColor="@android:color/white" />
+
+ <SeekBar
+ android:id="@+id/seekbar_lat"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_toLeftOf="@+id/value_lat"
+ android:layout_toRightOf="@id/text_lat"
+ android:max="360" />
+
+ <TextView
+ android:id="@id/value_lat"
+ android:layout_width="48dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="4dp"
+ android:layout_marginStart="4dp"
+ android:gravity="center"
+ android:text="-180"
+ android:textColor="@android:color/white" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp">
+
+ <TextView
+ android:id="@+id/text_lon"
+ android:layout_width="72dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="4dp"
+ android:textColor="@android:color/white"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:text="Longitude" />
+
+ <SeekBar
+ android:id="@+id/seekbar_lon"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_toLeftOf="@+id/value_lon"
+ android:layout_toRightOf="@id/text_lon"
+ android:max="360" />
+
+ <TextView
+ android:id="@id/value_lon"
+ android:layout_width="48dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:textColor="@android:color/white"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="4dp"
+ android:layout_marginStart="4dp"
+ android:gravity="center"
+ android:text="-180" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp">
+
+ <TextView
+ android:id="@+id/text_zoom"
+ android:layout_width="72dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="4dp"
+ android:textColor="@android:color/white"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:text="Zoom" />
+
+ <SeekBar
+ android:id="@+id/seekbar_zoom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_toLeftOf="@+id/value_zoom"
+ android:layout_toRightOf="@id/text_zoom"
+ android:max="18" />
+
+ <TextView
+ android:id="@id/value_zoom"
+ android:layout_width="48dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="4dp"
+ android:textColor="@android:color/white"
+ android:layout_marginStart="4dp"
+ android:gravity="center"
+ android:text="18" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp">
+
+ <TextView
+ android:id="@+id/text_bearing"
+ android:textColor="@android:color/white"
+ android:layout_width="72dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="4dp"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:text="Bearing" />
+
+ <SeekBar
+ android:id="@+id/seekbar_bearing"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_toLeftOf="@+id/value_bearing"
+ android:layout_toRightOf="@id/text_bearing"
+ android:max="360" />
+
+ <TextView
+ android:id="@id/value_bearing"
+ android:layout_width="48dp"
+ android:textColor="@android:color/white"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="4dp"
+ android:layout_marginStart="4dp"
+ android:gravity="center"
+ android:text="0" />
+
+ </RelativeLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp">
+
+ <TextView
+ android:id="@+id/text_tilt"
+ android:layout_width="72dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="4dp"
+ android:textColor="@android:color/white"
+ android:layout_marginRight="4dp"
+ android:gravity="center"
+ android:text="Tilt" />
+
+ <SeekBar
+ android:id="@+id/seekbar_tilt"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:layout_marginRight="4dp"
+ android:layout_toLeftOf="@+id/value_tilt"
+ android:layout_toRightOf="@id/text_tilt"
+ android:max="60" />
+
+ <TextView
+ android:id="@id/value_tilt"
+ android:layout_width="48dp"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:textColor="@android:color/white"
+ android:layout_marginLeft="4dp"
+ android:layout_marginStart="4dp"
+ android:gravity="center"
+ android:text="0" />
+
+ </RelativeLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_double_map.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_double_map.xml
index 88788fc429..db50720257 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_double_map.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/fragment_double_map.xml
@@ -7,8 +7,7 @@
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- mapbox:access_token="@string/mapbox_access_token" />
+ android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/map_card"
@@ -22,6 +21,6 @@
android:id="@+id/mini_map"
android:layout_width="100dp"
android:layout_height="100dp"
- mapbox:access_token="@string/mapbox_access_token" />
+ />
</FrameLayout>
-</RelativeLayout> \ No newline at end of file
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_main_feature.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_main_feature.xml
new file mode 100644
index 0000000000..93af094e3f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_main_feature.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="72dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingStart="16dp"
+ android:paddingTop="16dp">
+
+ <TextView
+ android:id="@+id/nameView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:text="Dummy headline"
+ android:layout_marginRight="16dp"
+ android:layout_marginEnd="16dp"
+ android:singleLine="true"
+ android:textColor="@android:color/black"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/descriptionView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:alpha="0.56"
+ android:layout_marginRight="16dp"
+ android:layout_marginEnd="16dp"
+ android:singleLine="true"
+ android:text="Description is dummy dummy"
+ android:textColor="@android:color/black"
+ android:textSize="14sp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/section_main_layout.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/section_main_layout.xml
new file mode 100644
index 0000000000..8978d4e3eb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/section_main_layout.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="48dp">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="0.25dp"
+ android:alpha="0.56"
+ android:background="@drawable/line_divider" />
+
+ <TextView
+ android:id="@+id/section_text"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginEnd="16dp"
+ android:alpha="0.54"
+ android:background="@android:color/transparent"
+ android:singleLine="true"
+ android:textColor="@android:color/black"
+ android:textSize="14sp" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml
new file mode 100644
index 0000000000..08caf1df66
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_custom_marker.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@id/imageView"
+ android:layout_width="64dp"
+ android:layout_height="64dp"/>
+
+ <TextView
+ android:id="@id/textView"
+ android:layout_width="wrap_content"
+ android:textColor="@android:color/white"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:layout_centerInParent="true" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_text_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_text_marker.xml
new file mode 100644
index 0000000000..8a3508691a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/view_text_marker.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@color/mapbox_green">
+
+ <TextView
+ android:id="@id/textView"
+ android:layout_width="wrap_content"
+ android:textColor="@android:color/white"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:padding="4dp"
+ android:layout_centerInParent="true" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml
deleted file mode 100644
index d04996dc95..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_drawer.xml
+++ /dev/null
@@ -1,221 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item
- android:id="@+id/mainActivityMenu"
- android:title="@string/navdrawer_menu_title_mainactivity_controls">
- <menu>
- <group>
- <item
- android:id="@+id/action_debug"
- android:icon="@drawable/ic_bug_report_24dp"
- android:title="@string/action_debug" />
-
- <item
- android:id="@+id/action_markers"
- android:icon="@drawable/ic_place_24dp"
- android:title="@string/action_point_annotations" />
-
- <item
- android:id="@+id/action_compass"
- android:icon="@drawable/ic_navigation_24dp"
- android:title="@string/action_compass" />
-
- <item
- android:id="@+id/action_custom_layer"
- android:icon="@drawable/ic_now_wallpaper_24dp"
- android:title="@string/action_custom_layer" />
-
- </group>
- </menu>
- </item>
-
- <group android:id="@+id/stylesSeparator" />
-
- <item
- android:id="@+id/mainActivityStylesMenue"
- android:title="@string/navdrawer_menu_title_mainactivity_styles">
- <menu>
- <group android:id="@+id/stylesGroup">
- <item
- android:id="@+id/actionStyleMapboxStreets"
- android:title="@string/styleMapboxStreets" />
-
- <item
- android:id="@+id/actionStyleEmerald"
- android:title="@string/styleEmerald" />
-
- <item
- android:id="@+id/actionStyleLight"
- android:title="@string/styleLight" />
-
- <item
- android:id="@+id/actionStyleDark"
- android:title="@string/styleDark" />
-
- <item
- android:id="@+id/actionStyleSatellite"
- android:title="@string/styleSatellite" />
-
- <item
- android:id="@+id/actionStyleSatelliteStreets"
- android:title="@string/styleSatelliteStreets" />
-
- </group>
- </menu>
- </item>
-
- <group android:id="@+id/testsSeparator" />
-
- <item
- android:id="@+id/testsMenu"
- android:title="@string/navdrawer_menu_title_individual_tests">
- <menu>
-
- <item
- android:id="@+id/action_offline"
- android:checkable="false"
- android:icon="@drawable/ic_airplanemode_active_black_24dp"
- android:title="@string/action_offline" />
-
- <item
- android:id="@+id/action_mapboxmap"
- android:checkable="false"
- android:icon="@drawable/ic_mapboxmap"
- android:title="@string/action_mapboxmap" />
-
- <item
- android:id="@+id/action_tilt"
- android:checkable="false"
- android:icon="@drawable/ic_tilt"
- android:title="@string/action_tilt" />
-
- <item
- android:id="@+id/action_camera"
- android:checkable="false"
- android:icon="@drawable/ic_transform_24dp"
- android:title="@string/action_camera" />
-
- <item
- android:id="@+id/action_map_fragment"
- android:checkable="false"
- android:icon="@drawable/ic_now_widgets_24dp"
- android:title="@string/action_map_fragment" />
-
- <item
- android:id="@+id/action_support_map_fragment"
- android:checkable="false"
- android:icon="@drawable/ic_now_widgets_24dp"
- android:title="@string/action_map_fragment_support" />
-
- <item
- android:id="@+id/action_info_window"
- android:checkable="false"
- android:icon="@drawable/ic_flip_to_front_24dp"
- android:title="@string/action_info_window" />
-
- <item
- android:id="@+id/action_info_window_concurrent"
- android:checkable="false"
- android:icon="@drawable/ic_flip_to_back_24dp"
- android:title="@string/action_info_window_concurrent" />
-
- <item
- android:id="@+id/action_info_window_adapter"
- android:checkable="false"
- android:icon="@drawable/ic_infowindow_adapter"
- android:title="@string/action_info_window_adapter" />
-
- <item
- android:id="@+id/action_press_for_marker"
- android:checkable="false"
- android:icon="@drawable/ic_pin_drop_24dp"
- android:title="@string/action_press_for_marker" />
-
- <item
- android:id="@+id/action_manual_zoom"
- android:checkable="false"
- android:icon="@drawable/ic_filter_center_focus_24dp"
- android:title="@string/action_manual_zoom" />
-
- <item
- android:id="@+id/action_minmax_zoom"
- android:checkable="false"
- android:icon="@drawable/ic_find_replace_24dp"
- android:title="@string/action_minmax_zoom" />
-
- <item
- android:id="@+id/action_coordinate_change"
- android:checkable="false"
- android:icon="@drawable/ic_animate_coordinates"
- android:title="@string/action_animate_coordinate_change" />
-
- <item
- android:id="@+id/action_visible_bounds"
- android:checkable="false"
- android:icon="@drawable/ic_crop_24dp"
- android:title="@string/action_visible_bounds" />
-
- <item
- android:id="@+id/action_bulk_markers"
- android:checkable="false"
- android:icon="@drawable/ic_blur_on_24dp"
- android:title="@string/action_add_bulk_markers" />
-
- <item
- android:id="@+id/action_user_tracking_mode"
- android:checkable="false"
- android:icon="@drawable/ic_gps_fixed_24dp"
- android:title="@string/activity_user_tracking_mode" />
-
- <item
- android:id="@+id/action_polyline"
- android:checkable="false"
- android:icon="@drawable/ic_trending_up_24dp"
- android:title="@string/activity_polyline" />
-
- <item
- android:id="@+id/action_directions"
- android:checkable="false"
- android:icon="@drawable/ic_directions"
- android:title="@string/activity_directions" />
-
- <item
- android:id="@+id/action_double_mapview"
- android:checkable="false"
- android:icon="@drawable/ic_dns_24dp"
- android:title="@string/action_double_mapview" />
-
- <item
- android:id="@+id/action_geocoder"
- android:checkable="false"
- android:icon="@drawable/ic_directions"
- android:title="@string/activity_geocoder" />
-
- <item
- android:id="@+id/action_scroll_by"
- android:checkable="false"
- android:icon="@drawable/ic_input_24dp"
- android:title="@string/activity_scroll_by" />
-
- <item
- android:id="@+id/action_dynamic_marker"
- android:checkable="false"
- android:icon="@drawable/ic_dynamic_marker"
- android:title="@string/action_dynamic_marker" />
-
- <item
- android:id="@+id/action_map_padding"
- android:checkable="false"
- android:icon="@drawable/ic_map_padding"
- android:title="@string/action_map_padding" />
-
- <item
- android:id="@+id/action_animated_marker"
- android:checkable="false"
- android:icon="@drawable/ic_compare_arrows_black_24dp"
- android:title="@string/action_animated_marker" />
-
- </menu>
- </item>
-</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_infowindow.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_infowindow.xml
new file mode 100644
index 0000000000..583b760d7c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_infowindow.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <group android:checkableBehavior="all">
+ <item
+ android:title="@string/menuitem_title_concurrent_infowindow"
+ android:id="@+id/action_toggle_concurrent_infowindow"
+ app:showAsAction="never"
+ android:checkable="true"/>
+ </group>
+
+</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_press_for_marker.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_press_for_marker.xml
new file mode 100644
index 0000000000..0b3a8e797e
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_press_for_marker.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item
+ android:id="@+id/menuItemReset"
+ android:title="@string/menuitem_title_reset"
+ app:showAsAction="always"
+ />
+</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml
new file mode 100644
index 0000000000..dc2add474c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <group android:checkableBehavior="all">
+ <item
+ android:id="@+id/action_toggle_dismissible_tracking"
+ android:checkable="true"
+ android:checked="false"
+ android:title="@string/menuitem_title_tracking_mode_dismiss_on_gesture"
+ app:showAsAction="never" />
+ <item
+ android:id="@+id/action_toggle_dismissible_bearing"
+ android:checkable="true"
+ android:checked="false"
+ android:title="@string/menuitem_title_bearing_mode_dismiss_on_gesture"
+ app:showAsAction="never" />
+ </group>
+
+</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/colors.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/colors.xml
index ac3b4fc30d..891ab8d7a8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/colors.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/colors.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary">#1E8CAB</color>
- <color name="primaryDark">#166B83</color>
+ <color name="primary_dark">#166B83</color>
<color name="accent">#E55E5E</color>
- <color name="white">#FFFFFF</color>
+ <color name="white">#F9F9F9</color>
+ <color name="mapbox_green">#56B881</color>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
index aeda60d478..98ec90c6fd 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
@@ -6,4 +6,7 @@
<dimen name="map_padding_left">96dp</dimen>
<dimen name="map_padding_bottom">256dp</dimen>
<dimen name="map_padding_right">32dp</dimen>
+ <dimen name="toolbar_shadow">4dp</dimen>
+ <dimen name="locationview_background_drawable_padding">2dp</dimen>
+ <dimen name="locationview_padding_top">350dp</dimen>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/ids.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..120bf49fca
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/ids.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="mapView" type="id" />
+ <item name="fab" type="id" />
+ <item name="progress" type="id" />
+ <item name="imageView" type="id" />
+ <item name="textView" type="id" />
+ <item name="toolbar" type="id" />
+ <item name="container" type="id" />
+ <item name="item_click_support" type="id" />
+</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
index bd3d6390ee..a84035aa58 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/strings.xml
@@ -1,68 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="app_name">Mapbox GL</string>
+ <string name="app_name">Mapbox Android SDK TestApp</string>
<!-- Test Activities -->
- <string name="activity_mapboxmap">MapboxMap</string>
- <string name="activity_tilt">Map Tilt</string>
- <string name="activity_infowindow_adapter">InfoWindow Adapter</string>
- <string name="activity_map_fragment_suport">Support Map Fragment Activity</string>
- <string name="activity_map_fragment">Map Fragment Activity</string>
- <string name="activity_press_for_marker">Press For Marker Activity</string>
- <string name="activity_marker_in_bulk">Add Bulk Markers Activity</string>
- <string name="activity_manual_zoom">Manual Zoom Activity</string>
- <string name="activity_info_window">InfoWindow Activity</string>
- <string name="activity_info_window_concurrent">InfoWindow Activity (Concurrent)</string>
- <string name="activity_visible_coordinate_bounds">Visible Coordinate Bounds</string>
- <string name="activity_user_tracking_mode">User tracking mode</string>
+ <string name="activity_mapboxmap">MapboxMap Activity</string>
+
+ <!-- Fragment -->
+ <string name="activity_map_fragment_suport">Support Map Fragment</string>
+ <string name="activity_map_fragment">Map Fragment</string>
+
+ <!-- Annotations -->
<string name="activity_add_bulk_markers">Add Markers In Bulk</string>
- <string name="activity_camera">Camera</string>
- <string name="activity_polyline">Polyline Activity</string>
- <string name="activity_animate_coordinate_change">Animate Coordinate Change</string>
- <string name="activity_custom_layer">Custom Layer</string>
- <string name="activity_directions">Directions Activity</string>
- <string name="activity_geocoder">Geocoder Activity</string>
+ <string name="activity_animated_marker">Animated Marker (experimental)</string>
+ <string name="activity_dynamic_marker">Dynamic Marker</string>
+ <string name="activity_polyline">Polyline</string>
+ <string name="activity_polygon">Polygon</string>
+ <string name="activity_press_for_marker">Press Map For Marker</string>
+ <string name="activity_view_marker">View Marker API</string>
+
+ <!-- InfoWindow-->
+ <string name="activity_info_window">Standard InfoWindow example</string>
+ <string name="activity_infowindow_adapter">Custom InfoWindow Adapter</string>
+
+ <!-- Camera -->
+ <string name="activity_camera_animation_types">Animation Types</string>
+ <string name="activity_camera_zoom">Zoom Methods</string>
+ <string name="activity_visible_coordinate_bounds">LatLngBounds Method</string>
+ <string name="activity_camera_position">CameraPosition Method</string>
+ <string name="activity_scroll_by">Scroll By Method</string>
+
+ <!-- API -->
+ <string name="activity_directions">Directions</string>
+ <string name="activity_geocoder">Geocoder</string>
+
+ <!-- Other -->
<string name="activity_double_map">Double Map Activity</string>
- <string name="activity_scroll_by">Scroll By Activity</string>
- <string name="activity_dynamic_marker">Dynamic Marker Activity</string>
- <string name="activity_map_padding">Map Padding Activity</string>
- <string name="activity_offline">Offline Map Activity</string>
-
- <string name="navdrawer_menu_title_mainactivity_controls">Main Activity Controls</string>
- <string name="navdrawer_menu_title_mainactivity_styles">Main Activity Styles</string>
- <string name="navdrawer_menu_title_individual_tests">Individual Tests</string>
- <string name="action_gps">Toggle GPS location</string>
- <string name="action_user_location_tracking">User location tracking</string>
- <string name="action_compass">Toggle compass</string>
- <string name="action_custom_layer">Custom Layer</string>
- <string name="action_debug">Cycle map debug options</string>
- <string name="action_point_annotations">Toggle point annotations</string>
- <string name="action_mapboxmap">MapboxMap</string>
- <string name="action_info_window_adapter">InfoWindow Adapter</string>
- <string name="action_tilt">Tilt</string>
- <string name="action_map_fragment">MapFragment</string>
- <string name="action_map_fragment_support">SupportMapFragment</string>
- <string name="action_press_for_marker">Press For Marker</string>
- <string name="action_manual_zoom">Manual Zoom</string>
- <string name="action_minmax_zoom">Min/Max Zoom</string>
- <string name="action_info_window">InfoWindow</string>
- <string name="action_animate_coordinate_change">Animate Coordinate Change</string>
- <string name="action_info_window_concurrent">InfoWindow (Concurrent)</string>
- <string name="action_add_bulk_markers">Add Markers in bulk</string>
- <string name="action_camera">Camera</string>
- <string name="action_visible_bounds">Set Visible Bounds</string>
+ <string name="activity_snapshot">Snapshot Activity</string>
+ <string name="activity_user_tracking_mode">User tracking mode</string>
+ <string name="activity_user_tracking_customization">User location customization</string>
+ <string name="activity_user_dot_color">User location tint color</string>
+ <string name="activity_user_location_toggle">User location toggle</string>
+ <string name="activity_custom_layer">Custom Layer</string>
+ <string name="activity_map_padding">Map Padding</string>
+ <string name="activity_debug_mode">Debug Mode</string>
+ <string name="activity_offline">Offline Map</string>
+ <string name="activity_minmax_zoom">Min/Max Zoom</string>
+
+ <!-- Description -->
+ <string name="description_user_location_tracking">Tracks the location of the user</string>
+ <string name="description_user_location_customization">Customize the location of the user</string>
+ <string name="description_user_location_dot_color">Customize the user location color</string>
+ <string name="description_user_location_toggle">Toggle location of the user on and off</string>
+ <string name="description_custom_layer">Overlay a custom native layer on the map</string>
+ <string name="description_info_window_adapter">Learn how to create a custom InfoWindow</string>
+ <string name="description_cameraposition">CameraPosition capabilities</string>
+ <string name="description_map_fragment">Showcase MapFragment</string>
+ <string name="description_map_fragment_support">Showcase SupportMapFragment</string>
+ <string name="description_press_for_marker">Add marker to map on long press</string>
+ <string name="description_camera_zoom">Different types of zoom methods</string>
+ <string name="description_minmax_zoom">Configure a max and min zoomlevel</string>
+ <string name="description_info_window">Learn how to handle the InfoWindow</string>
+ <string name="description_info_window_concurrent">InfoWindow example with multiple open</string>
+ <string name="description_add_bulk_markers">Add Markers In Bulk to a Map</string>
+ <string name="description_camera_animation_types">Showcase the different animation types</string>
+ <string name="description_visible_bounds">Center the camera around a bounds</string>
+ <string name="description_dynamic_marker">Update position and icon</string>
+ <string name="description_map_padding">Map Padding example</string>
+ <string name="description_debug_mode">Debug Mode</string>
+ <string name="description_offline">Offline Map example</string>
+ <string name="description_animated_marker">Animate the position change of a Marker</string>
+ <string name="description_polyline">Add a polyline to a map</string>
+ <string name="description_polygon">Add a polygon to a map</string>
+ <string name="description_directions">Example with Directions API</string>
+ <string name="description_geocoder">Example with Geocoder API</string>
+ <string name="description_scroll_by">Scroll with pixels in x,y direction</string>
+ <string name="description_snapshot">Example to make a snapshot of the map</string>
+ <string name="description_doublemap">2 maps in a view hierarchy</string>
+ <string name="description_view_marker">Use an Android SDK View as marker</string>
+
+ <string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>r
+ <string name="menuitem_title_tracking_mode_dismiss_on_gesture">Dismiss location tracking on gesture</string>
+ <string name="menuitem_title_bearing_mode_dismiss_on_gesture">Dismiss bearing tracking on gesture</string>
+ <string name="menuitem_title_reset">Reset</string>
+
+ <string name="category">category</string>
+ <string name="category_annotation">Annotation</string>
+ <string name="category_camera">Camera</string>
+ <string name="category_custom_layer">Custom Layer</string>
+ <string name="category_directions">Directions</string>
+ <string name="category_fragment">Fragment</string>
+ <string name="category_geocoding">Geocoding</string>
+ <string name="category_imagegenerator">Image Generator</string>
+ <string name="category_infowindow">InfoWindow</string>
+ <string name="category_maplayout">Map Layout</string>
+ <string name="category_offline">Offline</string>
+ <string name="category_userlocation">User Location</string>
+
<string name="action_visible_bounds_explanation">Center map around 2 markers</string>
<string name="action_remove_polylines">Remove polylines</string>
- <string name="action_double_mapview">Double MapView</string>
- <string name="action_dynamic_marker">Dynamic Marker</string>
- <string name="action_map_padding">Map Padding</string>
- <string name="action_offline">Offline Map</string>
- <string name="action_animated_marker">Animated Marker</string>
<string name="button_camera_move">Move</string>
<string name="button_camera_ease">Ease</string>
<string name="button_camera_animate">Animate</string>
+ <string name="button_make_snapshot">Snapshot</string>
+ <string name="button_user_dot_default">Default</string>
+ <string name="button_user_dot_tint">Tint dot</string>
+ <string name="button_user_accuracy_ring_tint">Tint ring</string>
<string name="label_fps">FPS:</string>
@@ -86,14 +130,14 @@
</string-array>
<string-array name="user_tracking_mode">
- <item>Disable tracking</item>
- <item>Follow tracking mode</item>
+ <item>Disabled</item>
+ <item>Follow tracking</item>
</string-array>
<string-array name="user_bearing_mode">
- <item>Disable bearing</item>
- <item>GPS mode</item>
- <item>Compass mode</item>
+ <item>Disabled</item>
+ <item>GPS bearing</item>
+ <item>Compass bearing</item>
<!--<item>Combined mode</item>-->
</string-array>
@@ -103,6 +147,9 @@
<string name="scrollby_y_value">Y: %1$d</string>
<string name="button_download_region">Download region</string>
<string name="button_list_regions">List regions</string>
- <string name="title_activity_animated_marker">AnimatedMarkerActivity</string>
+
+ <string name="dialog_camera_position">Animate to new position</string>
+
+ <string name="geocoder_instructions">Tap Map To Geocode Where Black Marker Is Currently Located</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
index e781e337d6..d01b9d313f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/styles.xml
@@ -5,9 +5,9 @@
<style name="AppBaseTheme" parent="@style/Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/primary</item>
- <item name="colorPrimaryDark">@color/primaryDark</item>
+ <item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
- <item name="android:windowBackground">@android:color/white</item>
+ <item name="android:windowBackground">@color/white</item>
</style>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java
new file mode 100644
index 0000000000..76658c242f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/AnnotationTest.java
@@ -0,0 +1,91 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class AnnotationTest {
+
+ @InjectMocks
+ private MapboxMap mapboxMap = mock(MapboxMap.class);
+ private Annotation annotation;
+ private Annotation compare = new Annotation() {
+ @Override
+ public long getId() {
+ return 1;
+ }
+ };
+
+ @Before
+ public void beforeTest() {
+ annotation = new Annotation() {
+ // empty child
+ };
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("markerOptions should not be null", annotation);
+ }
+
+ @Test
+ public void testRemove() {
+ annotation.setId(1);
+ annotation.setMapboxMap(mapboxMap);
+ annotation.remove();
+ verify(mapboxMap, times(1)).removeAnnotation(annotation);
+ }
+
+ @Test
+ public void testRemoveUnboundMapboxMap() {
+ annotation.setId(1);
+ annotation.remove();
+ verify(mapboxMap, times(0)).removeAnnotation(annotation);
+ }
+
+ @Test
+ public void testCompareToEqual() {
+ annotation.setId(1);
+ assertEquals("conparable equal", 0, annotation.compareTo(compare));
+ }
+
+ @Test
+ public void testCompareToHigher() {
+ annotation.setId(3);
+ assertEquals("conparable higher", -1, annotation.compareTo(compare));
+ }
+
+ @Test
+ public void testCompareTolower() {
+ annotation.setId(0);
+ assertEquals("conparable lower", 1, annotation.compareTo(compare));
+ }
+
+ @Test
+ public void testEquals() {
+ Annotation holder = null;
+ assertFalse(annotation.equals(holder));
+ holder = annotation;
+ assertTrue(annotation.equals(holder));
+ assertFalse(annotation.equals(new Object()));
+ }
+
+ @Test
+ public void testHashcode() {
+ int id = 1;
+ annotation.setId(id);
+ assertSame("hashcode should match", annotation.hashCode(), id);
+ }
+
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
index cc38ca40b8..a55672e86b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java
@@ -1,17 +1,17 @@
package com.mapbox.mapboxsdk.annotations;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
+import android.os.Parcelable;
-import com.mapbox.mapboxsdk.annotations.Marker;
-import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
public class MarkerTest {
@@ -70,8 +70,8 @@ public class MarkerTest {
@Test
public void testHashCode() {
- Marker marker = new MarkerOptions().position(new LatLng(10, 12)).getMarker();
- assertEquals("hash code should match", marker.hashCode(), -1946419200);
+ Marker marker = new MarkerOptions().getMarker();
+ assertEquals("hash code should match", marker.hashCode(), 0);
}
@Test
@@ -88,6 +88,35 @@ public class MarkerTest {
}
@Test
+ public void testEqualityDifferentLocation() {
+ MarkerOptions marker = new MarkerOptions().position(new LatLng(0, 0));
+ MarkerOptions other = new MarkerOptions().position(new LatLng(1, 0));
+ assertNotEquals("Should not match", other, marker);
+ }
+
+
+ @Test
+ public void testEqualityDifferentSnippet() {
+ MarkerOptions marker = new MarkerOptions().snippet("s");
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
+ public void testEqualityDifferentIcon() {
+ MarkerOptions marker = new MarkerOptions().icon(mock(Icon.class));
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
+ public void testEqualityDifferentTitle() {
+ MarkerOptions marker = new MarkerOptions().title("t");
+ MarkerOptions other = new MarkerOptions();
+ assertNotEquals("Should not match", other, marker);
+ }
+
+ @Test
public void testEqualsItself() {
MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(0, 0));
Marker marker = markerOptions.getMarker();
@@ -116,4 +145,10 @@ public class MarkerTest {
assertEquals(marker.toString(), "Marker [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
}
+ @Test
+ public void testParcelable() {
+ MarkerOptions markerOptions = new MarkerOptions().position(new LatLng()).title("t").snippet("s");
+ Parcelable parcelable = MockParcel.obtain(markerOptions);
+ assertEquals("Parcel should match original object", parcelable, markerOptions);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
new file mode 100644
index 0000000000..ed8e4ff323
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java
@@ -0,0 +1,210 @@
+package com.mapbox.mapboxsdk.annotations;
+
+import android.graphics.Bitmap;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.utils.MockParcel;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class MarkerViewTest {
+
+ @Test
+ public void testSanity() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions();
+ assertNotNull("markerOptions should not be null", markerOptions);
+ }
+
+ @Test
+ public void testMarker() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions();
+ assertNotNull("marker should not be null", markerOptions.getMarker());
+ }
+
+ @Test
+ public void testPosition() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ assertEquals(markerOptions.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testSnippet() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().snippet("Mapbox");
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getSnippet(), "Mapbox");
+ }
+
+ @Test
+ public void testTitle() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().title("Mapbox");
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals(marker.getTitle(), "Mapbox");
+ assertEquals(markerOptions.getTitle(), "Mapbox");
+ }
+
+ @Test
+ public void testIcon() {
+ Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_4444);
+ Icon icon = IconFactory.recreate("test", bitmap);
+ MarkerViewOptions markerOptions = new MarkerViewOptions().icon(icon);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("Icon should match", icon, marker.getIcon());
+ assertEquals("Icon should match", icon, markerOptions.getIcon());
+ }
+
+ @Test
+ public void testFlat() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().flat(true);
+ MarkerView marker = markerOptions.getMarker();
+ assertTrue("flat should be true", marker.isFlat());
+ }
+
+ @Test
+ public void testFlatDefault() {
+ assertFalse("default value of flat should be false", new MarkerViewOptions().getMarker().isFlat());
+ }
+
+ @Test
+ public void testAnchor() {
+ float anchorU = 1;
+ float anchorV = 1;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().anchor(anchorU, anchorV);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("anchorU should match ", anchorU, marker.getAnchorU(), 0);
+ assertEquals("anchorU should match ", anchorV, marker.getAnchorV(), 0);
+ }
+
+ @Test
+ public void testAnchorDefault() {
+ MarkerView marker = new MarkerViewOptions().getMarker();
+ assertEquals("anchorU should match ", 0.5, marker.getAnchorU(), 0);
+ assertEquals("anchorU should match ", 1, marker.getAnchorV(), 0);
+ }
+
+ @Test
+ public void testInfoWindowAnchor() {
+ float anchorU = 1;
+ float anchorV = 1;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().infoWindowAnchor(anchorU, anchorV);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorU(), 0);
+ assertEquals("anchorU should match ", 1, marker.getInfoWindowAnchorV(), 0);
+ }
+
+ @Test
+ public void testInfoWindowAnchorDefault() {
+ MarkerView marker = new MarkerViewOptions().getMarker();
+ assertEquals("anchorU should match ", 0.5, marker.getInfoWindowAnchorU(), 0);
+ assertEquals("anchorU should match ", 0, marker.getInfoWindowAnchorV(), 0);
+ }
+
+ @Test
+ public void testSelectAnimRes() {
+ int animatorRes = R.animator.rotate_360;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().selectAnimatorResource(animatorRes);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("select animator resource should match ", animatorRes, marker.getSelectAnimRes(), 0);
+ }
+
+ @Test
+ public void testDeselectAnimRes() {
+ int animatorRes = R.animator.rotate_360;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().deselectAnimatorResource(animatorRes);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("deselect animator resource should match ", animatorRes, marker.getDeselectAnimRes(), 0);
+ }
+
+ @Test
+ public void testRotation() {
+ int rotation = 90;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(rotation);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("rotation should match ", rotation, marker.getRotation(), 0);
+ }
+
+ @Test
+ public void testVisible() {
+ boolean visible = false;
+ MarkerViewOptions markerOptions = new MarkerViewOptions().visible(visible);
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("visible should match ", visible, marker.isVisible());
+ }
+
+ @Test
+ public void testVisibleDefault() {
+ assertTrue(new MarkerViewOptions().getMarker().isVisible());
+ }
+
+ @Test
+ public void testBuilder() {
+ MarkerView marker = new MarkerViewOptions().title("title").snippet("snippet").position(new LatLng(10, 12)).getMarker();
+ assertEquals(marker.getSnippet(), "snippet");
+
+ assertEquals(marker.getPosition(), new LatLng(10, 12));
+ }
+
+ @Test
+ public void testHashCode() {
+ MarkerView marker = new MarkerViewOptions().getMarker();
+ assertEquals("hash code should match", marker.hashCode(), 0);
+ }
+
+ @Test
+ public void testHashCodeBuilder() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(10, 12));
+ assertEquals("hash code should match", markerOptions.hashCode(), 0);
+ }
+
+ @Test
+ public void testEquals() {
+ MarkerView markerOne = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ MarkerView markerTwo = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testEqualsItself() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerView marker = markerOptions.getMarker();
+ assertEquals("MarkerView should match", marker, marker);
+ assertEquals("MarkerViewOptions should match", markerOptions, markerOptions);
+ }
+
+ @Test
+ public void testNotEquals() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerView marker = markerOptions.getMarker();
+ assertNotEquals("MarkerViewOptions should match", markerOptions, new Object());
+ assertNotEquals("MarkerView should match", marker, new Object());
+ }
+
+ @Test
+ public void testEqualityBuilder() {
+ MarkerViewOptions markerOne = new MarkerViewOptions().position(new LatLng(0, 0));
+ MarkerViewOptions markerTwo = new MarkerViewOptions().position(new LatLng(0, 0));
+ assertEquals(markerOne, markerTwo);
+ }
+
+ @Test
+ public void testToString() {
+ MarkerView marker = new MarkerViewOptions().position(new LatLng(0, 0)).getMarker();
+ assertEquals(marker.toString(), "MarkerView [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]");
+ }
+
+ @Test
+ public void testParcelable() {
+ MarkerViewOptions markerOptions = new MarkerViewOptions().position(new LatLng()).title("t").snippet("s");
+ Parcelable parcelable = MockParcel.obtain(markerOptions);
+ assertEquals("Parcel should match original object", parcelable, markerOptions);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
index 222007df79..a8cca4c3c8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java
@@ -1,17 +1,28 @@
package com.mapbox.mapboxsdk.camera;
+import android.content.res.TypedArray;
+import android.os.Parcelable;
+
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.MathConstants;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.utils.MathUtils;
+import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class CameraPositionTest {
+ private static final double DELTA = 1e-15;
+
@Test
public void testSanity() {
LatLng latLng = new LatLng(1, 2);
@@ -20,6 +31,55 @@ public class CameraPositionTest {
}
@Test
+ public void testDefaultTypedArrayBuilder() {
+ TypedArray typedArray = null;
+ CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
+ assertEquals("bearing should match", -1, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", null, cameraPosition.target);
+ assertEquals("tilt should match", -1, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", -1, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
+ public void testTypedArrayBuilder() {
+ float bearing = 180;
+ float zoom = 12;
+ float latitude = 10;
+ float longitude = 11;
+ float tilt = 44;
+
+ TypedArray typedArray = mock(TypedArray.class);
+ when(typedArray.getFloat(R.styleable.MapView_direction, 0.0f)).thenReturn(bearing);
+ when(typedArray.getFloat(R.styleable.MapView_center_latitude, 0.0f)).thenReturn(latitude);
+ when(typedArray.getFloat(R.styleable.MapView_center_longitude, 0.0f)).thenReturn(longitude);
+ when(typedArray.getFloat(R.styleable.MapView_zoom, 0.0f)).thenReturn(zoom);
+ when(typedArray.getFloat(R.styleable.MapView_tilt, 0.0f)).thenReturn(tilt);
+ doNothing().when(typedArray).recycle();
+
+ CameraPosition cameraPosition = new CameraPosition.Builder(typedArray).build();
+ assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
+ assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
+ public void testJniBuilder() {
+ double bearing = 180;
+ double zoom = 12;
+ double latitude = 10;
+ double longitude = 11;
+ double tilt = 44;
+
+ double[] cameraVars = new double[]{latitude, longitude, bearing, tilt, zoom};
+ CameraPosition cameraPosition = new CameraPosition.Builder(cameraVars).build();
+ assertEquals("bearing should match", bearing, cameraPosition.bearing, DELTA);
+ assertEquals("latlng should match", new LatLng(latitude, longitude), cameraPosition.target);
+ assertEquals("tilt should match", tilt, cameraPosition.tilt, DELTA);
+ assertEquals("zoom should match", zoom, cameraPosition.zoom, DELTA);
+ }
+
+ @Test
public void testToString() {
LatLng latLng = new LatLng(1, 2);
CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
@@ -74,4 +134,29 @@ public class CameraPositionTest {
(CameraUpdateFactory.ZoomUpdate) CameraUpdateFactory.zoomTo(zoomLevel));
assertEquals("zoom should match", zoomLevel, builder.build().zoom, 0);
}
+
+ @Test
+ public void testEquals() {
+ LatLng latLng = new LatLng(1, 2);
+ CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5);
+ CameraPosition cameraPositionBearing = new CameraPosition(latLng, 3, 4, 9);
+ CameraPosition cameraPositionTilt = new CameraPosition(latLng, 3, 9, 5);
+ CameraPosition cameraPositionZoom = new CameraPosition(latLng, 9, 4, 5);
+ CameraPosition cameraPositionTarget = new CameraPosition(new LatLng(), 3, 4, 5);
+
+ assertEquals("cameraPosition should match itself", cameraPosition, cameraPosition);
+ assertNotEquals("cameraPosition should not match null", null, cameraPosition);
+ assertNotEquals("cameraPosition should not match object", new Object(), cameraPosition);
+ assertNotEquals("cameraPosition should not match for bearing", cameraPositionBearing, cameraPosition);
+ assertNotEquals("cameraPosition should not match for tilt", cameraPositionTilt, cameraPosition);
+ assertNotEquals("cameraPosition should not match for zoom", cameraPositionZoom, cameraPosition);
+ assertNotEquals("cameraPosition should not match for target", cameraPositionTarget, cameraPosition);
+ }
+
+ @Test
+ public void testParcelable() {
+ CameraPosition object = new CameraPosition(new LatLng(1, 2), 3, 4, 5);
+ Parcelable parcelable = MockParcel.obtain(object);
+ assertEquals("Parcel should match original object", parcelable, object);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java
new file mode 100644
index 0000000000..078b4184ca
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/constants/StyleVersionTest.java
@@ -0,0 +1,20 @@
+package com.mapbox.mapboxsdk.constants;
+
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
+
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+public class StyleVersionTest {
+
+ private static final double DELTA = 1e-15;
+
+ @Test
+ public void testSanity() {
+ assertEquals("Style version should match, when upgrading, verify that integers.xml is updated",
+ AppConstant.STYLE_VERSION,
+ 9,
+ DELTA);
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
index f9cdf29b81..b667940a6f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
@@ -1,6 +1,9 @@
package com.mapbox.mapboxsdk.geometry;
+import android.os.Parcelable;
+
import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException;
+import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Before;
import org.junit.Test;
@@ -168,5 +171,13 @@ public class LatLngBoundsTest {
.build());
}
-
-}
+ @Test
+ public void testParcelable() {
+ LatLngBounds latLngBounds = new LatLngBounds.Builder()
+ .include(new LatLng(10, 10))
+ .include(new LatLng(9, 8))
+ .build();
+ Parcelable parcel = MockParcel.obtain(latLngBounds);
+ assertEquals("Parcel should match original object", parcel, latLngBounds);
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
index 7bf164166c..e184097a43 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngSpanTest.java
@@ -1,6 +1,8 @@
package com.mapbox.mapboxsdk.geometry;
-import com.mapbox.mapboxsdk.geometry.LatLngSpan;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
@@ -54,4 +56,10 @@ public class LatLngSpanTest {
assertEquals("latitude in constructor", latLngSpan.getLongitudeSpan(), longitude, DELTA);
}
+ @Test
+ public void testParcelable() {
+ LatLngSpan object = new LatLngSpan(1, 2);
+ Parcelable parcel = MockParcel.obtain(object);
+ assertEquals("parcel should match initial object", object, parcel);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
index e13efb9708..de5dbc5e09 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java
@@ -1,18 +1,16 @@
package com.mapbox.mapboxsdk.geometry;
import android.location.Location;
-import android.os.Parcel;
-import com.mapbox.mapboxsdk.geometry.LatLng;
+import android.os.Parcelable;
+
import com.mapbox.mapboxsdk.utils.MockParcel;
+
import org.junit.Test;
-import java.util.Objects;
-import static org.junit.Assert.assertArrayEquals;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -164,7 +162,7 @@ public class LatLngTest {
@Test
public void testEqualsItself() {
- LatLng latLng = new LatLng(1,2,3);
+ LatLng latLng = new LatLng(1, 2, 3);
assertEquals("LatLng should match", latLng, latLng);
}
@@ -176,28 +174,9 @@ public class LatLngTest {
@Test
public void testParcelable() {
- LatLng latLng = new LatLng(1, 2, 3);
- Parcel parcel = MockParcel.obtain();
- latLng.writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- LatLng parceledLatLng = LatLng.CREATOR.createFromParcel(parcel);
- assertEquals("parcel should match initial object", latLng, parceledLatLng);
- }
-
- @Test
- public void testParcelableArray() {
- LatLng[] latLngs = new LatLng[]{new LatLng(1, 2, 3), new LatLng(1, 2)};
- Parcel parcel = MockParcel.obtain();
- parcel.writeParcelableArray(latLngs, 0);
- parcel.setDataPosition(0);
- LatLng[] parceledLatLngs = (LatLng[]) parcel.readParcelableArray(LatLng.class.getClassLoader());
- assertArrayEquals("parcel should match initial object", latLngs, parceledLatLngs);
- }
-
- @Test
- public void testDescribeContents() {
- LatLng latLng = new LatLng(1.2, 3.4);
- assertEquals("contents should be 0", 0, latLng.describeContents(), DELTA);
+ LatLng latLng = new LatLng(45.0, -185.0);
+ Parcelable parcel = MockParcel.obtain(latLng);
+ assertEquals("parcel should match initial object", latLng, parcel);
}
@Test
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
index bd40221706..5525684601 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/ProjectedMetersTest.java
@@ -1,5 +1,9 @@
package com.mapbox.mapboxsdk.geometry;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.utils.MockParcel;
+
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -48,8 +52,15 @@ public class ProjectedMetersTest {
}
@Test
- public void testToString(){
+ public void testToString() {
+ ProjectedMeters meters = new ProjectedMeters(1, 1);
+ assertEquals("toString should match", "ProjectedMeters [northing=1.0, easting=1.0]", meters.toString());
+ }
+
+ @Test
+ public void testParcelable() {
ProjectedMeters meters = new ProjectedMeters(1, 1);
- assertEquals("toString should match","ProjectedMeters [northing=1.0, easting=1.0]",meters.toString());
+ Parcelable parcel = MockParcel.obtain(meters);
+ assertEquals("parcel should match initial object", meters, parcel);
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
index 0682d0878e..cad268c2ba 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java
@@ -1,5 +1,9 @@
package com.mapbox.mapboxsdk.geometry;
+import android.os.Parcelable;
+
+import com.mapbox.mapboxsdk.utils.MockParcel;
+
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -81,4 +85,10 @@ public class VisibleRegionTest {
, region.toString());
}
+ @Test
+ public void testParcelable() {
+ VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS);
+ Parcelable parcel = MockParcel.obtain(region);
+ assertEquals("parcel should match initial object", region, parcel);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
index 589084d17c..dbde9a4420 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
@@ -1,11 +1,13 @@
package com.mapbox.mapboxsdk.maps;
+import android.graphics.Color;
import android.view.Gravity;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.utils.MockParcel;
import org.junit.Test;
@@ -71,6 +73,12 @@ public class MapboxMapOptionsTest {
}
@Test
+ public void testAttributionTintColor() {
+ assertEquals(-1, new MapboxMapOptions().getAttributionTintColor());
+ assertEquals(Color.RED, new MapboxMapOptions().attributionTintColor(Color.RED).getAttributionTintColor());
+ }
+
+ @Test
public void testAttributionEnabled() {
assertTrue(new MapboxMapOptions().attributionEnabled(true).getAttributionEnabled());
assertFalse(new MapboxMapOptions().attributionEnabled(false).getAttributionEnabled());
@@ -161,6 +169,23 @@ public class MapboxMapOptionsTest {
}
@Test
+ public void testMyLocationForegroundTint() {
+ assertEquals(Color.BLUE, new MapboxMapOptions().myLocationForegroundTintColor(Color.BLUE).getMyLocationForegroundTintColor());
+ }
+
+ @Test
+ public void testMyLocationBackgroundTint() {
+ assertEquals(Color.BLUE, new MapboxMapOptions().myLocationBackgroundTintColor(Color.BLUE).getMyLocationBackgroundTintColor());
+ }
+
+ @Test
+ public void testParceable() {
+ MapboxMapOptions options = new MapboxMapOptions().camera(new CameraPosition.Builder().build()).styleUrl("s").accessToken("a").debugActive(true).compassMargins(new int[]{0, 1, 2, 3});
+ MapboxMapOptions parceled = (MapboxMapOptions) MockParcel.obtain(options);
+ assertEquals(options, parceled);
+ }
+
+ @Test
public void testAccessToken() {
assertNull(new MapboxMapOptions().getAccessToken());
assertEquals("test", new MapboxMapOptions().accessToken("test").getAccessToken());
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
index 1705f44fa4..b69ba4e3f8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -2,7 +2,9 @@ package com.mapbox.mapboxsdk.maps;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.PointF;
+import com.mapbox.mapboxsdk.annotations.BaseMarkerOptions;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.annotations.Polygon;
@@ -12,6 +14,7 @@ import com.mapbox.mapboxsdk.annotations.PolylineOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import org.junit.Before;
import org.junit.Test;
@@ -26,6 +29,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -197,7 +201,7 @@ public class MapboxMapTest {
CameraPosition position = new CameraPosition.Builder().bearing(1).tilt(2).zoom(3).target(new LatLng(4, 5)).build();
mMapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(position));
mMapboxMap.setPadding(0, 0, 0, 0);
- verify(mOnCameraChangeListener, times(2)).onCameraChange(position);
+ verify(mOnCameraChangeListener, times(1)).onCameraChange(position);
}
//
@@ -372,6 +376,58 @@ public class MapboxMapTest {
}
//
+ // Camera - LatLngBounds
+ //
+ @Test
+ public void testLatLngBounds() {
+ LatLng la = new LatLng(34.053940, -118.242622);
+ LatLng ny = new LatLng(40.712730, -74.005953);
+ LatLng centroid = new LatLng(
+ (la.getLatitude() + ny.getLatitude()) / 2,
+ (la.getLongitude() + ny.getLongitude()) / 2);
+
+ Projection projection = mock(Projection.class);
+ when(projection.toScreenLocation(la)).thenReturn(new PointF(20, 20));
+ when(projection.toScreenLocation(ny)).thenReturn(new PointF(100, 100));
+ when(projection.fromScreenLocation(any(PointF.class))).thenReturn(centroid);
+
+ UiSettings uiSettings = mock(UiSettings.class);
+ when(uiSettings.getHeight()).thenReturn(1000f);
+
+ mMapboxMap.setProjection(projection);
+ mMapboxMap.setUiSettings(uiSettings);
+
+ LatLngBounds bounds = new LatLngBounds.Builder().include(la).include(ny).build();
+ mMapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 1));
+
+ assertEquals("LatLng should be same", centroid, mMapboxMap.getCameraPosition().target);
+ }
+
+
+ //
+ // CameraPositionUpdate - NPX target
+ //
+ @Test
+ public void testCamerePositionUpdateNullTarget() {
+ LatLng latLng = new LatLng(1, 1);
+ mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
+ mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(null));
+ assertEquals("LatLng should be same", latLng, mMapboxMap.getCameraPosition().target);
+ }
+
+ //
+ // Camera - ScrollBy
+ //
+ @Test
+ public void testScrollBy() {
+ LatLng latLng = new LatLng(1, 1);
+ mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
+ mMapboxMap.moveCamera(CameraUpdateFactory.scrollBy(0, 0));
+ assertEquals("LatLng should be same", latLng, mMapboxMap.getCameraPosition().target);
+ mMapboxMap.moveCamera(CameraUpdateFactory.scrollBy(12, 12));
+ }
+
+ //
// Camera - Zoom
//
@@ -523,7 +579,7 @@ public class MapboxMapTest {
@Test
public void testAddMarkers() {
- List<MarkerOptions> markerList = new ArrayList<>();
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
MarkerOptions markerOptions1 = new MarkerOptions().title("a");
MarkerOptions markerOptions2 = new MarkerOptions().title("b");
markerList.add(markerOptions1);
@@ -536,14 +592,14 @@ public class MapboxMapTest {
@Test
public void testAddMarkersEmpty() {
- List<MarkerOptions> markerList = new ArrayList<>();
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
mMapboxMap.addMarkers(markerList);
assertEquals("Markers size should be 0", 0, mMapboxMap.getMarkers().size());
}
@Test
public void testAddMarkersSingleMarker() {
- List<MarkerOptions> markerList = new ArrayList<>();
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
MarkerOptions markerOptions = new MarkerOptions().title("a");
markerList.add(markerOptions);
mMapboxMap.addMarkers(markerList);
@@ -686,7 +742,7 @@ public class MapboxMapTest {
@Test
public void testRemoveAnnotations() {
- List<MarkerOptions> markerList = new ArrayList<>();
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
MarkerOptions markerOptions1 = new MarkerOptions().title("a");
MarkerOptions markerOptions2 = new MarkerOptions().title("b");
markerList.add(markerOptions1);
@@ -697,8 +753,20 @@ public class MapboxMapTest {
}
@Test
+ public void testClear() {
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
+ MarkerOptions markerOptions1 = new MarkerOptions().title("a");
+ MarkerOptions markerOptions2 = new MarkerOptions().title("b");
+ markerList.add(markerOptions1);
+ markerList.add(markerOptions2);
+ mMapboxMap.addMarkers(markerList);
+ mMapboxMap.clear();
+ assertTrue("Annotations should be empty", mMapboxMap.getAnnotations().isEmpty());
+ }
+
+ @Test
public void testRemoveAnnotationsByList() {
- List<MarkerOptions> markerList = new ArrayList<>();
+ List<BaseMarkerOptions> markerList = new ArrayList<>();
MarkerOptions markerOptions1 = new MarkerOptions().title("a");
MarkerOptions markerOptions2 = new MarkerOptions().title("b");
markerList.add(markerOptions1);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/StyleInitializerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/StyleInitializerTest.java
new file mode 100644
index 0000000000..71d61a3d4b
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/StyleInitializerTest.java
@@ -0,0 +1,75 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.model.constants.AppConstant;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class StyleInitializerTest {
+
+ @InjectMocks
+ Context context = mock(Context.class);
+
+ @InjectMocks
+ Resources resources = mock(Resources.class);
+
+ MapView.StyleInitializer initializer;
+
+ @Before
+ public void beforeTest() {
+ MockitoAnnotations.initMocks(this);
+ when(context.getResources()).thenReturn(resources);
+ when(resources.getInteger(R.integer.style_version)).thenReturn(AppConstant.STYLE_VERSION);
+ initializer = new MapView.StyleInitializer(context);
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("initializer should not be null", initializer);
+ }
+
+ @Test
+ public void testDefaultStyle() {
+ assertTrue(initializer.isDefaultStyle());
+ assertEquals(String.format(Locale.US, "mapbox://styles/mapbox/streets-v%d", AppConstant.STYLE_VERSION), "mapbox://styles/mapbox/streets-v9");
+ }
+
+ @Test
+ public void testUpdateStyle() {
+ String customStyle = "test";
+ initializer.setStyle(customStyle);
+ assertFalse(initializer.isDefaultStyle());
+ assertEquals(customStyle, initializer.getStyle());
+ }
+
+ @Test
+ public void testUpdateStyleNull() {
+ String customStyle = null;
+ initializer.setStyle(customStyle);
+ assertTrue(initializer.isDefaultStyle());
+ assertEquals(String.format(Locale.US, "mapbox://styles/mapbox/streets-v%d", AppConstant.STYLE_VERSION), "mapbox://styles/mapbox/streets-v9");
+ }
+
+ @Test
+ public void testOverrideDefaultStyle() {
+ String customStyle = "test";
+ initializer.setStyle(customStyle, true);
+ assertTrue(initializer.isDefaultStyle());
+ assertEquals(customStyle, initializer.getStyle());
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
index 4af44a3f49..300ed1d73a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.maps;
import android.view.Gravity;
+import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
@@ -9,42 +10,45 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class UiSettingsTest {
@InjectMocks
MapView mMapView = mock(MapView.class);
+ UiSettings uiSettings;
+
+ @Before
+ public void beforeTest() {
+ uiSettings = new UiSettings(mMapView);
+ }
+
@Test
public void testSanity() {
- UiSettings uiSettings = new UiSettings(mMapView);
assertNotNull("uiSettings should not be null", uiSettings);
}
@Test
public void testCompassEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setCompassEnabled(true);
assertEquals("Compass should be enabled", true, uiSettings.isCompassEnabled());
}
@Test
public void testCompassDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setCompassEnabled(false);
assertEquals("Compass should be disabled", false, uiSettings.isCompassEnabled());
}
@Test
public void testCompassGravity() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setCompassGravity(Gravity.LEFT);
assertEquals("Compass gravity should be same", Gravity.LEFT, uiSettings.getCompassGravity());
}
@Test
public void testCompassMargins() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setCompassMargins(1, 2, 3, 4);
assertTrue("Compass margin left should be same", uiSettings.getCompassMarginLeft() == 1);
assertTrue("Compass margin top should be same", uiSettings.getCompassMarginTop() == 2);
@@ -54,28 +58,24 @@ public class UiSettingsTest {
@Test
public void testLogoEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setLogoEnabled(true);
assertEquals("Logo should be enabled", true, uiSettings.isLogoEnabled());
}
@Test
public void testLogoDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setLogoEnabled(false);
assertEquals("Logo should be disabled", false, uiSettings.isLogoEnabled());
}
@Test
public void testLogoGravity() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setLogoGravity(Gravity.RIGHT);
assertEquals("Logo gravity should be same", Gravity.RIGHT, uiSettings.getLogoGravity());
}
@Test
public void testLogoMargins() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setLogoMargins(1, 2, 3, 4);
assertTrue("Compass margin left should be same", uiSettings.getLogoMarginLeft() == 1);
assertTrue("Compass margin top should be same", uiSettings.getLogoMarginTop() == 2);
@@ -85,28 +85,24 @@ public class UiSettingsTest {
@Test
public void testAttributionEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAttributionEnabled(true);
assertEquals("Attribution should be enabled", true, uiSettings.isAttributionEnabled());
}
@Test
public void testAttributionDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAttributionEnabled(false);
assertEquals("Attribution should be disabled", false, uiSettings.isLogoEnabled());
}
@Test
public void testAttributionGravity() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAttributionGravity(Gravity.RIGHT);
assertEquals("Attribution gravity should be same", Gravity.RIGHT, uiSettings.getAttributionGravity());
}
@Test
public void testAttributionMargins() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAttributionMargins(1, 2, 3, 4);
assertTrue("Attribution margin left should be same", uiSettings.getAttributionMarginLeft() == 1);
assertTrue("Attribution margin top should be same", uiSettings.getAttributionMarginTop() == 2);
@@ -116,77 +112,158 @@ public class UiSettingsTest {
@Test
public void testRotateGesturesEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setRotateGesturesEnabled(true);
assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
}
@Test
public void testRotateGesturesDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setRotateGesturesEnabled(false);
assertEquals("Rotate gesture should be disabled", false, uiSettings.isRotateGesturesEnabled());
}
@Test
+ public void testRotateGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isRotateGestureChangeAllowed());
+ uiSettings.setRotateGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isRotateGestureChangeAllowed());
+ }
+
+ @Test
+ public void testRotateGestureChangeAllowed() {
+ uiSettings.setRotateGesturesEnabled(false);
+ assertEquals("Rotate gesture should be false", false, uiSettings.isRotateGesturesEnabled());
+ uiSettings.setRotateGesturesEnabled(true);
+ assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
+ public void testRotateGestureChangeDisallowed() {
+ assertEquals("Rotate gesture should be true", true, uiSettings.isRotateGesturesEnabled());
+ uiSettings.setRotateGestureChangeAllowed(false);
+ uiSettings.setRotateGesturesEnabled(false);
+ assertEquals("Rotate gesture change should be ignored", true, uiSettings.isRotateGesturesEnabled());
+ }
+
+ @Test
public void testTiltGesturesEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setTiltGesturesEnabled(true);
assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
}
@Test
public void testTiltGesturesDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setTiltGesturesEnabled(false);
assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
}
@Test
+ public void testTiltGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isTiltGestureChangeAllowed());
+ uiSettings.setTiltGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isTiltGestureChangeAllowed());
+ }
+
+ @Test
+ public void testTiltGestureChangeAllowed() {
+ uiSettings.setTiltGesturesEnabled(false);
+ assertEquals("Tilt gesture should be false", false, uiSettings.isTiltGesturesEnabled());
+ uiSettings.setTiltGesturesEnabled(true);
+ assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
+ public void testTiltGestureChangeDisallowed() {
+ assertEquals("Tilt gesture should be true", true, uiSettings.isTiltGesturesEnabled());
+ uiSettings.setTiltGestureChangeAllowed(false);
+ uiSettings.setTiltGesturesEnabled(false);
+ assertEquals("Tilt gesture change should be ignored", true, uiSettings.isTiltGesturesEnabled());
+ }
+
+ @Test
public void testZoomGesturesEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setZoomGesturesEnabled(true);
assertEquals("Zoom gesture should be enabled", true, uiSettings.isZoomGesturesEnabled());
}
@Test
public void testZoomGesturesDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setZoomGesturesEnabled(false);
assertEquals("Zoom gesture should be disabled", false, uiSettings.isZoomGesturesEnabled());
}
@Test
+ public void testZoomGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isZoomGestureChangeAllowed());
+ uiSettings.setZoomGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isZoomGestureChangeAllowed());
+ }
+
+ @Test
+ public void testZoomGestureChangeAllowed() {
+ uiSettings.setZoomGesturesEnabled(false);
+ assertEquals("Zoom gesture should be false", false, uiSettings.isZoomGesturesEnabled());
+ uiSettings.setZoomGesturesEnabled(true);
+ assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
+ public void testZoomGestureChangeDisallowed() {
+ assertEquals("Zoom gesture should be true", true, uiSettings.isZoomGesturesEnabled());
+ uiSettings.setZoomGestureChangeAllowed(false);
+ uiSettings.setZoomGesturesEnabled(false);
+ assertEquals("Zooom gesture change should be ignored", true, uiSettings.isZoomGesturesEnabled());
+ }
+
+ @Test
public void testZoomControlsEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setZoomControlsEnabled(true);
assertEquals("Zoom controls should be enabled", true, uiSettings.isZoomControlsEnabled());
}
@Test
public void testZoomControlsDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setZoomControlsEnabled(false);
assertEquals("Zoom controls should be disabled", false, uiSettings.isZoomControlsEnabled());
}
@Test
public void testScrollGesturesEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setScrollGesturesEnabled(true);
assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
}
@Test
public void testScrollGesturesDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setScrollGesturesEnabled(false);
assertEquals("Scroll gesture should be disabled", false, uiSettings.isScrollGesturesEnabled());
}
@Test
+ public void testScrollGestureChange() {
+ assertEquals("Default state should be true", true, uiSettings.isScrollGestureChangeAllowed());
+ uiSettings.setScrollGestureChangeAllowed(false);
+ assertEquals("State should have been changed", false, uiSettings.isScrollGestureChangeAllowed());
+ }
+
+ @Test
+ public void testScrollGestureChangeAllowed() {
+ uiSettings.setScrollGesturesEnabled(false);
+ assertEquals("Scroll gesture should be false", false, uiSettings.isScrollGesturesEnabled());
+ uiSettings.setScrollGesturesEnabled(true);
+ assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
+ public void testScrollGestureChangeDisallowed() {
+ assertEquals("Scroll gesture should be true", true, uiSettings.isScrollGesturesEnabled());
+ uiSettings.setScrollGestureChangeAllowed(false);
+ uiSettings.setScrollGesturesEnabled(false);
+ assertEquals("Scroll gesture change should be ignored", true, uiSettings.isScrollGesturesEnabled());
+ }
+
+ @Test
public void testAllGesturesEnabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAllGesturesEnabled(true);
assertEquals("Rotate gesture should be enabled", true, uiSettings.isRotateGesturesEnabled());
assertEquals("Tilt gesture should be enabled", true, uiSettings.isTiltGesturesEnabled());
@@ -196,7 +273,6 @@ public class UiSettingsTest {
@Test
public void testAllGesturesDisabled() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.setAllGesturesEnabled(false);
assertEquals("Rotate gesture should be enabled", false, uiSettings.isRotateGesturesEnabled());
assertEquals("Tilt gesture should be disabled", false, uiSettings.isTiltGesturesEnabled());
@@ -206,8 +282,18 @@ public class UiSettingsTest {
@Test
public void testInvalidate() {
- UiSettings uiSettings = new UiSettings(mMapView);
uiSettings.invalidate();
}
+ @Test
+ public void testHeight() {
+ when(mMapView.getMeasuredHeight()).thenReturn(1);
+ assertEquals("height should be same as mocked instance", 1, uiSettings.getHeight(), 0);
+ }
+
+ @Test
+ public void testWidth() {
+ when(mMapView.getMeasuredWidth()).thenReturn(1);
+ assertEquals("width should be same as mocked instance", 1, uiSettings.getWidth(), 0);
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
new file mode 100644
index 0000000000..a03eb6acae
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
@@ -0,0 +1,79 @@
+package com.mapbox.mapboxsdk.maps.widgets;
+
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InjectMocks;
+
+import java.util.Arrays;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class MyLocationViewSettingsTest {
+
+ @InjectMocks
+ MapView mMapView = mock(MapView.class);
+
+ @InjectMocks
+ MyLocationView myLocationView = mock(MyLocationView.class);
+
+ MyLocationViewSettings locationViewSettings;
+
+ @Before
+ public void beforeTest() {
+ locationViewSettings = new MyLocationViewSettings(mMapView, myLocationView);
+ }
+
+ @Test
+ public void testSanity() {
+ assertNotNull("should not be null", locationViewSettings);
+ }
+
+ @Test
+ public void testForegroundDrawables() {
+ Drawable foregroundDrawable = mock(Drawable.class);
+ Drawable foregroundBearingDrawable = mock(Drawable.class);
+ locationViewSettings.setForegroundDrawable(foregroundDrawable, foregroundBearingDrawable);
+ assertEquals("foreground should match", foregroundDrawable, locationViewSettings.getForegroundDrawable());
+ assertEquals("foreground bearing should match", foregroundBearingDrawable, locationViewSettings.getForegroundBearingDrawable());
+ }
+
+ @Test
+ public void testBackgroundDrawable() {
+ Drawable backgroundDrawable = mock(Drawable.class);
+ int[] offset = new int[]{1, 2, 3, 4};
+ locationViewSettings.setBackgroundDrawable(backgroundDrawable, offset);
+ assertEquals("foreground should match", backgroundDrawable, locationViewSettings.getBackgroundDrawable());
+ assertTrue("offsets should match", Arrays.equals(offset, locationViewSettings.getBackgroundOffset()));
+ }
+
+ @Test
+ public void testForegroundTint() {
+ int color = Color.RED;
+ locationViewSettings.setForegroundTintColor(Color.RED);
+ assertEquals("color should match", color, locationViewSettings.getForegroundTintColor());
+ }
+
+ @Test
+ public void testBackgroundTint() {
+ int color = Color.RED;
+ locationViewSettings.setBackgroundTintColor(Color.RED);
+ assertEquals("color should match", color, locationViewSettings.getBackgroundTintColor());
+ }
+
+ @Test
+ public void testEnabled() {
+ assertFalse("initial state should be false", locationViewSettings.isEnabled());
+ locationViewSettings.setEnabled(true);
+ assertTrue("state should be true", locationViewSettings.isEnabled());
+ }
+
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
new file mode 100644
index 0000000000..8be0d2c663
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
@@ -0,0 +1,17 @@
+package com.mapbox.mapboxsdk.telemetry;
+
+import org.junit.Test;
+import okhttp3.internal.Util;
+import static junit.framework.Assert.assertEquals;
+
+public class HttpTransportTest {
+
+ @Test
+ public void testNonAsciiUserAgent() {
+
+ final String swedishUserAgent = "Sveriges Fjäll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
+ final String asciiVersion = "Sveriges Fj?ll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
+
+ assertEquals("asciiVersion and swedishUserAgent should match", asciiVersion, Util.toHumanReadableAscii(swedishUserAgent));
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
index 9badde848e..aa0a4edd13 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/utils/MockParcel.java
@@ -1,17 +1,24 @@
package com.mapbox.mapboxsdk.utils;
import android.os.Parcel;
-
-import com.mapbox.mapboxsdk.geometry.LatLng;
+import android.os.Parcelable;
+import android.support.annotation.NonNull;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertArrayEquals;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyByte;
import static org.mockito.Matchers.anyDouble;
+import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
@@ -22,97 +29,227 @@ import static org.mockito.Mockito.when;
public class MockParcel {
- public static Parcel obtain() {
- return new MockParcel().getMockedParcel();
+ public static Parcelable obtain(@NonNull Parcelable object) {
+ return obtain(object, 0);
}
- Parcel mockedParcel;
- int position;
- List<Object> objects;
+ public static Parcelable obtain(@NonNull Parcelable object, int describeContentsValue) {
+ testDescribeContents(object, describeContentsValue);
+ testParcelableArray(object);
+ return testParcelable(object);
+ }
- public Parcel getMockedParcel() {
- return mockedParcel;
+ public static Parcelable testParcelable(@NonNull Parcelable object) {
+ Parcel parcel = ParcelMocker.obtain(object);
+ object.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ try {
+ Field field = object.getClass().getDeclaredField("CREATOR");
+ field.setAccessible(true);
+ Class<?> creatorClass = field.getType();
+ Object fieldValue = field.get(object);
+ Method myMethod = creatorClass.getDeclaredMethod("createFromParcel", Parcel.class);
+ return (Parcelable) myMethod.invoke(fieldValue, parcel);
+ } catch (Exception e) {
+ return null;
+ }
}
- public MockParcel() {
- mockedParcel = mock(Parcel.class);
- objects = new ArrayList<>();
- setupMock();
+ public static void testParcelableArray(@NonNull Parcelable object) {
+ Parcelable[] objects = new Parcelable[]{object};
+ Parcel parcel = ParcelMocker.obtain(objects);
+ parcel.writeParcelableArray(objects, 0);
+ parcel.setDataPosition(0);
+ Parcelable[] parcelableArray = parcel.readParcelableArray(object.getClass().getClassLoader());
+ assertArrayEquals("parcel should match initial object", objects, parcelableArray);
}
- private void setupMock() {
- setupWrites();
- setupReads();
- setupOthers();
+ public static void testDescribeContents(@NonNull Parcelable object, int describeContentsValue) {
+ if (describeContentsValue == 0) {
+ assertEquals("\nExpecting a describeContents() value of 0 for a " + object.getClass().getSimpleName() + " instance." +
+ "\nYou can provide a different value for describeContentValue through the obtain method.",
+ 0,
+ object.describeContents());
+ } else {
+ assertEquals("Expecting a describeContents() value of " + describeContentsValue,
+ describeContentsValue,
+ object.describeContents());
+ }
}
- private void setupWrites() {
- Answer<Void> writeValueAnswer = new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Object parameter = invocation.getArguments()[0];
- objects.add(parameter);
- return null;
- }
- };
- Answer<Void> writeArrayAnswer = new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Object[] parameters = (Object[]) invocation.getArguments()[0];
- objects.add(parameters.length);
- for (Object o : parameters) {
- objects.add(o);
- }
- return null;
- }
- };
+ private static class ParcelMocker {
- doAnswer(writeValueAnswer).when(mockedParcel).writeLong(anyLong());
- doAnswer(writeValueAnswer).when(mockedParcel).writeString(anyString());
- doAnswer(writeValueAnswer).when(mockedParcel).writeDouble(anyDouble());
- doAnswer(writeArrayAnswer).when(mockedParcel).writeParcelableArray(any(LatLng[].class), eq(0));
- }
+ public static Parcel obtain(@NonNull Parcelable target) {
+ Parcel parcel = new ParcelMocker(target).getMockedParcel();
+ target.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ return parcel;
+ }
- private void setupReads() {
- when(mockedParcel.readLong()).thenAnswer(new Answer<Long>() {
- @Override
- public Long answer(InvocationOnMock invocation) throws Throwable {
- return (Long) objects.get(position++);
- }
- });
- when(mockedParcel.readString()).thenAnswer(new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- return (String) objects.get(position++);
+ public static Parcel obtain(@NonNull Parcelable[] targets) {
+ if (targets.length == 0) {
+ throw new IllegalArgumentException("The passed argument may not be empty");
}
- });
- when(mockedParcel.readDouble()).thenAnswer(new Answer<Double>() {
- @Override
- public Double answer(InvocationOnMock invocation) throws Throwable {
- return (Double) objects.get(position++);
- }
- });
- when(mockedParcel.readParcelableArray(LatLng.class.getClassLoader())).thenAnswer(new Answer<LatLng[]>() {
- @Override
- public LatLng[] answer(InvocationOnMock invocation) throws Throwable {
- int size = (Integer) objects.get(position++);
- LatLng[] latLngs = LatLng.CREATOR.newArray(size);
- for (int i = 0; i < size; i++) {
- latLngs[i] = (LatLng) objects.get(position++);
+ Parcel parcel = new ParcelMocker(targets[0]).getMockedParcel();
+ parcel.writeParcelableArray(targets, 0);
+ parcel.setDataPosition(0);
+ return parcel;
+ }
+
+ private List<Object> objects;
+ private Object object;
+ private Parcel mockedParcel;
+ private int position;
+
+ private ParcelMocker(Object o) {
+ this.object = o;
+ mockedParcel = mock(Parcel.class);
+ objects = new ArrayList<>();
+ setupMock();
+ }
+
+ private Parcel getMockedParcel() {
+ return mockedParcel;
+ }
+
+ private void setupMock() {
+ setupWrites();
+ setupReads();
+ setupOthers();
+ }
+
+ private void setupWrites() {
+ Answer<Void> writeValueAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object parameter = invocation.getArguments()[0];
+ objects.add(parameter);
+ return null;
}
- return latLngs;
- }
- });
- }
-
- private void setupOthers() {
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- position = ((Integer) invocation.getArguments()[0]);
- return null;
- }
- }).when(mockedParcel).setDataPosition(anyInt());
+ };
+ Answer<Void> writeArrayAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Object[] parameters = (Object[]) invocation.getArguments()[0];
+ objects.add(parameters.length);
+ for (Object o : parameters) {
+ objects.add(o);
+ }
+ return null;
+ }
+ };
+ Answer<Void> writeIntArrayAnswer = new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ int[] parameters = (int[]) invocation.getArguments()[0];
+ if (parameters != null) {
+ objects.add(parameters.length);
+ for (Object o : parameters) {
+ objects.add(o);
+ }
+ } else {
+ objects.add(-1);
+ }
+ return null;
+ }
+ };
+ doAnswer(writeValueAnswer).when(mockedParcel).writeByte(anyByte());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeLong(anyLong());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeString(anyString());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeInt(anyInt());
+ doAnswer(writeIntArrayAnswer).when(mockedParcel).writeIntArray(any(int[].class));
+ doAnswer(writeValueAnswer).when(mockedParcel).writeDouble(anyDouble());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeFloat(anyFloat());
+ doAnswer(writeValueAnswer).when(mockedParcel).writeParcelable(any(Parcelable.class), eq(0));
+ doAnswer(writeArrayAnswer).when(mockedParcel).writeParcelableArray(any(Parcelable[].class), eq(0));
+ }
+
+ private void setupReads() {
+ when(mockedParcel.readInt()).then(new Answer<Integer>() {
+ @Override
+ public Integer answer(InvocationOnMock invocation) throws Throwable {
+ return (Integer) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readByte()).thenAnswer(new Answer<Byte>() {
+ @Override
+ public Byte answer(InvocationOnMock invocation) throws Throwable {
+ return (Byte) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readLong()).thenAnswer(new Answer<Long>() {
+ @Override
+ public Long answer(InvocationOnMock invocation) throws Throwable {
+ return (Long) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readString()).thenAnswer(new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ return (String) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readDouble()).thenAnswer(new Answer<Double>() {
+ @Override
+ public Double answer(InvocationOnMock invocation) throws Throwable {
+ return (Double) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readFloat()).thenAnswer(new Answer<Float>() {
+ @Override
+ public Float answer(InvocationOnMock invocation) throws Throwable {
+ return (Float) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readParcelable(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Parcelable>() {
+ @Override
+ public Parcelable answer(InvocationOnMock invocation) throws Throwable {
+ return (Parcelable) objects.get(position++);
+ }
+ });
+ when(mockedParcel.readParcelableArray(Parcelable.class.getClassLoader())).thenAnswer(new Answer<Object[]>() {
+ @Override
+ public Object[] answer(InvocationOnMock invocation) throws Throwable {
+ int size = (Integer) objects.get(position++);
+ Field field = object.getClass().getDeclaredField("CREATOR");
+ field.setAccessible(true);
+ Class<?> creatorClass = field.getType();
+ Object fieldValue = field.get(object);
+ Method myMethod = creatorClass.getDeclaredMethod("newArray", int.class);
+ Object[] array = (Object[]) myMethod.invoke(fieldValue, size);
+ for (int i = 0; i < size; i++) {
+ array[i] = objects.get(position++);
+ }
+ return array;
+ }
+ });
+ when(mockedParcel.createIntArray()).then(new Answer<int[]>() {
+ @Override
+ public int[] answer(InvocationOnMock invocation) throws Throwable {
+ int size = (Integer) objects.get(position++);
+ if (size == -1) {
+ return null;
+ }
+
+ int[] array = new int[size];
+ for (int i = 0; i < size; i++) {
+ array[i] = (Integer) objects.get(position++);
+ }
+
+ return array;
+ }
+ });
+ }
+
+ private void setupOthers() {
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ position = ((Integer) invocation.getArguments()[0]);
+ return null;
+ }
+ }).when(mockedParcel).setDataPosition(anyInt());
+ }
}
-
}
diff --git a/platform/android/README.md b/platform/android/README.md
index 135eb87a93..895cf84688 100644
--- a/platform/android/README.md
+++ b/platform/android/README.md
@@ -4,14 +4,20 @@
A library based on [Mapbox GL Native](../../README.md) for embedding interactive map views with scalable, customizable vector maps into Java applications on Android devices.
-This repository is for day-to-day development of the SDK. Building the SDK yourself requires [a number of dependencies and steps](../../INSTALL.md) that are unnecessary for developing production applications. For production applications, please consider installing an official, prebuilt release instead; see the [Mapbox Android SDK website](https://www.mapbox.com/android-sdk/) for installation instructions.
+**To install and use the Mapbox Android SDK in an application, see the [Mapbox Android SDK website](https://www.mapbox.com/android-sdk/).**
-## Installing the SDK
+[![](https://www.mapbox.com/android-sdk/images/splash.jpg)](https://www.mapbox.com/android-sdk/)
-* [Installing the Mapbox Android SDK on Linux](INSTALL_LINUX.md)
-* [Installing the Mapbox Android SDK on OS X](INSTALL_OSX.md)
+## Contributing to the SDK
-## Setting up the Android emulator
+**These instructions are for developers interested in making code-level contributions to the SDK itself. If you instead want to use the SDK in your app, see above.**
+
+Building the SDK yourself requires [a number of dependencies and steps](../../INSTALL.md) that are unnecessary for developing production applications.
+
+* [Contributing on Linux](CONTRIBUTING_LINUX.md)
+* [Contributing on OS X](CONTRIBUTING_OSX.md)
+
+### Setting up the Android emulator
The Mapbox Android SDK requires Android 4.0.3+ (API level 15+).
@@ -35,7 +41,7 @@ In Android Studio, create an x86 AVD (Android Virtual Device):
Now when you run or debug the Android project you will see a window "Choose Device". Select your new AVD from drop down under "Launch emulator". If you select "Use same device for future launches" Android Studio will remember the selection and not ask again.
-## Running Mapbox GL Native on a hardware Android device
+### Running Mapbox GL Native on a hardware Android device
The Mapbox Android SDK requires Android 4.0.3+ (API level 15+).
diff --git a/platform/android/bitrise.yml b/platform/android/bitrise.yml
index 9a7dce6f85..3c06a04675 100644
--- a/platform/android/bitrise.yml
+++ b/platform/android/bitrise.yml
@@ -24,29 +24,17 @@ workflows:
envman add --key SKIPCI --value false
fi
- script:
- title: Install Linux Dependencies
- inputs:
- - content: |-
- #!/bin/bash
-
- apt-get install -y pkg-config
- - script:
- title: Build Android SDK For arm
- inputs:
- - content: |-
- #!/bin/bash
-
- make android -j4
- - is_debug: 'yes'
- - script:
- title: Run Unit Tests
+ title: Build
+ run_if: '{{enveq "SKIPCI" "false"}}'
inputs:
- content: |-
#!/bin/bash
-
- cd platform/android
- ./gradlew testReleaseUnitTest --continue
- - is_debug: 'yes'
+ set -eu -o pipefail
+ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
+ sudo apt-get install -y pkg-config nodejs
+ export BUILDTYPE=Release
+ make android
+ make test-android
- slack:
title: Post to Slack
run_if: '{{enveq "SKIPCI" "false"}}'
@@ -68,47 +56,26 @@ workflows:
scheduled:
steps:
- script:
- title: Install Linux Dependencies
+ title: Build
inputs:
- content: |-
#!/bin/bash
+ set -eu -o pipefail
- apt-get install -y pkg-config python-pip python-dev build-essential
+ curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
+ apt-get install -y pkg-config python-pip python-dev build-essential nodejs
pip install awscli
- - script:
- title: Fetch GPG Secring For SDK Signing
- inputs:
- - content: |-
- #!/bin/bash
aws s3 cp s3://mapbox/android/signing-credentials/secring.gpg platform/android/MapboxGLAndroidSDK/secring.gpg
- opts:
- is_expand: true
- - script:
- title: Inject Signing And Publishing Credentials
- inputs:
- - content: |-
- #!/bin/bash
echo "NEXUS_USERNAME=$PUBLISH_NEXUS_USERNAME
NEXUS_PASSWORD=$PUBLISH_NEXUS_PASSWORD
signing.keyId=$SIGNING_KEYID
signing.password=$SIGNING_PASSWORD
signing.secretKeyRingFile=secring.gpg" >> platform/android/MapboxGLAndroidSDK/gradle.properties
- opts:
- is_expand: true
- - script:
- title: Build Mapbox Android SDK For All ABI
- inputs:
- - content: |-
- #!/bin/bash
+ export BUILDTYPE=Release
make apackage -j4
- - script:
- title: Publish To Maven Central
- inputs:
- - content: |-
- #!/bin/bash
cd platform/android
./gradlew uploadArchives
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index f3a1cc06ba..23aef9d1e6 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -4,10 +4,11 @@
buildscript {
repositories {
jcenter()
+ maven { url 'https://jitpack.io' }
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.5.0'
- classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
+ classpath 'com.android.tools.build:gradle:2.1.0'
+ classpath 'com.github.JakeWharton:sdk-manager-plugin:220bf7a88a7072df3ed16dc8466fb144f2817070'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
@@ -22,5 +23,5 @@ allprojects {
}
task wrapper(type: Wrapper) {
- gradleVersion = '2.10'
+ gradleVersion = '2.12'
}
diff --git a/platform/android/gradle/wrapper/gradle-wrapper.properties b/platform/android/gradle/wrapper/gradle-wrapper.properties
index b4ada9d74b..a630852d20 100644
--- a/platform/android/gradle/wrapper/gradle-wrapper.properties
+++ b/platform/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,7 @@
-#Fri Jan 15 17:23:43 CET 2016
+#Thu Apr 07 14:21:05 CDT 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
-distributionSha256Sum=66406247f745fc6f05ab382d3f8d3e120c339f34ef54b86f6dc5f6efc18fbb13
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.12-bin.zip
+distributionSha256Sum=e77064981906cd0476ff1e0de3e6fef747bd18e140960f1915cca8ff6c33ab5c
diff --git a/platform/android/mapboxgl-app.gypi b/platform/android/platform.gyp
index 5e0e653a6f..964492a21e 100644
--- a/platform/android/mapboxgl-app.gypi
+++ b/platform/android/platform.gyp
@@ -1,70 +1,88 @@
{
+ 'variables': {
+ 'loop_lib': 'android',
+ 'headless_lib': 'none',
+ 'coverage': 0,
+ },
'includes': [
- '../../gyp/common.gypi',
+ '../../mbgl.gypi',
],
'targets': [
- { 'target_name': 'android-lib',
+ {
+ 'target_name': 'platform-lib',
'product_name': 'mapbox-gl',
'type': 'shared_library',
'hard_dependency': 1,
-
'dependencies': [
- 'mbgl.gyp:core',
- 'mbgl.gyp:platform-<(platform_lib)',
- 'mbgl.gyp:http-<(http_lib)',
- 'mbgl.gyp:asset-<(asset_lib)',
+ 'core',
],
'include_dirs': [
- '../src',
+ '../default',
+ '../../include',
+ '../../src', # TODO: eliminate
],
'sources': [
- './src/native_map_view.cpp',
- './src/jni.cpp',
- './src/attach_env.cpp',
+ 'src/native_map_view.cpp',
+ 'src/jni.cpp',
+ 'src/attach_env.cpp',
+ 'src/log_android.cpp',
+ 'src/http_file_source.cpp',
+ 'src/asset_file_source.cpp',
+ '../default/thread.cpp',
+ '../default/string_stdlib.cpp',
+ '../default/image.cpp',
+ '../default/png_reader.cpp',
+ '../default/jpeg_reader.cpp',
+ '../default/default_file_source.cpp',
+ '../default/online_file_source.cpp',
+ '../default/mbgl/storage/offline.hpp',
+ '../default/mbgl/storage/offline.cpp',
+ '../default/mbgl/storage/offline_database.hpp',
+ '../default/mbgl/storage/offline_database.cpp',
+ '../default/mbgl/storage/offline_download.hpp',
+ '../default/mbgl/storage/offline_download.cpp',
+ '../default/sqlite3.hpp',
+ '../default/sqlite3.cpp',
],
'cflags_cc': [
'<@(boost_cflags)',
- '<@(variant_cflags)',
+ '<@(rapidjson_cflags)',
+ '<@(nunicode_cflags)',
+ '<@(sqlite_cflags)',
'<@(jni.hpp_cflags)',
+ '<@(libzip_cflags)',
+ '<@(libpng_cflags)',
+ '<@(libjpeg-turbo_cflags)',
],
- 'libraries': [
- '<@(libpng_static_libs)',
- '<@(libjpeg-turbo_static_libs)',
- '<@(sqlite_static_libs)',
- '<@(libuv_static_libs)',
- '<@(nunicode_static_libs)',
- '<@(libzip_static_libs)',
- ],
- 'variables': {
- 'ldflags': [
+
+ 'link_settings': {
+ 'libraries': [
'-llog',
'-landroid',
'-lEGL',
'-lGLESv2',
'-lstdc++',
'-latomic',
- '<@(libpng_ldflags)',
- '<@(libjpeg-turbo_ldflags)',
+ '<@(nunicode_static_libs)',
+ '<@(nunicode_ldflags)',
+ '<@(sqlite_static_libs)',
'<@(sqlite_ldflags)',
+ '<@(zlib_static_libs)',
'<@(zlib_ldflags)',
+ '<@(libzip_static_libs)',
'<@(libzip_ldflags)',
+ '<@(libpng_static_libs)',
+ '<@(libpng_ldflags)',
+ '<@(libjpeg-turbo_static_libs)',
+ '<@(libjpeg-turbo_ldflags)',
],
},
- 'conditions': [
- ['OS == "mac"', {
- 'xcode_settings': {
- 'OTHER_LDFLAGS': [ '<@(ldflags)' ],
- }
- }, {
- 'libraries': [ '<@(ldflags)' ],
- }]
- ],
},
-
- { 'target_name': 'example-custom-layer-lib',
+ {
+ 'target_name': 'example-custom-layer-lib',
'product_name': 'example-custom-layer',
'type': 'shared_library',
'hard_dependency': 1,
@@ -77,8 +95,8 @@
'../../include',
],
- 'variables': {
- 'ldflags': [
+ 'link_settings': {
+ 'libraries': [
'-llog',
'-landroid',
'-lEGL',
@@ -87,24 +105,14 @@
'-latomic',
],
},
-
- 'conditions': [
- ['OS == "mac"', {
- 'xcode_settings': {
- 'OTHER_LDFLAGS': [ '<@(ldflags)' ],
- }
- }, {
- 'libraries': [ '<@(ldflags)' ],
- }]
- ],
},
-
- { 'target_name': 'androidapp',
+ {
+ 'target_name': 'all',
'type': 'none',
'hard_dependency': 1,
'dependencies': [
- 'android-lib',
+ 'platform-lib',
'example-custom-layer-lib',
],
@@ -116,17 +124,11 @@
{
'files': [
'../../common/ca-bundle.crt',
- '../../platform/default/resources/api_mapbox_com-digicert.der',
- '../../platform/default/resources/api_mapbox_com-geotrust.der',
- '../../platform/default/resources/star_tilestream_net.der',
+ '../default/resources/api_mapbox_com-digicert.der',
+ '../default/resources/api_mapbox_com-geotrust.der',
+ '../default/resources/star_tilestream_net.der',
],
- 'destination': '<(pwd)/../platform/android/MapboxGLAndroidSDK/src/main/assets'
- },
- {
- 'files': [
- '<(PRODUCT_DIR)/obj.target'
- ],
- 'destination': '<(pwd)/../platform/android/MapboxGLAndroidSDK/src/main'
+ 'destination': '<(DEPTH)/platform/android/MapboxGLAndroidSDK/src/main/assets'
},
],
@@ -134,13 +136,13 @@
{
'action_name': 'Strip mapbox library',
'inputs': [ '<(PRODUCT_DIR)/lib.target/libmapbox-gl.so' ],
- 'outputs': [ '<(pwd)/../platform/android/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ],
+ 'outputs': [ '<(DEPTH)/platform/android/MapboxGLAndroidSDK/src/main/jniLibs/$(JNIDIR)/libmapbox-gl.so' ],
'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ]
},
{
'action_name': 'Strip example custom layer library',
'inputs': [ '<(PRODUCT_DIR)/lib.target/libexample-custom-layer.so' ],
- 'outputs': [ '<(pwd)/../platform/android/MapboxGLAndroidSDKTestApp/src/main/jniLibs/$(JNIDIR)/libexample-custom-layer.so' ],
+ 'outputs': [ '<(DEPTH)/platform/android//MapboxGLAndroidSDKTestApp/src/main/jniLibs/$(JNIDIR)/libexample-custom-layer.so' ],
'action': [ '$(STRIP)', '<@(_inputs)', '-o', '<@(_outputs)' ]
}
],
diff --git a/platform/android/resources/dot-arrow.svg b/platform/android/resources/dot-arrow.svg
new file mode 100644
index 0000000000..4c2841a54b
--- /dev/null
+++ b/platform/android/resources/dot-arrow.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 139.6 219" enable-background="new 0 0 139.6 219" xml:space="preserve">
+<g id="XMLID_11_">
+ <path fill="#39ADCC" d="M66.5,1.3c1.1-1.8,3.7-1.8,4.8,0l9.8,17L94.8,42c-12.9-3.4-41.7-2.9-52,0.5l13.9-24.2L66.5,1.3z"/>
+</g>
+<g id="XMLID_7_">
+ <circle id="XMLID_10_" fill="#39ADCC" cx="69.8" cy="149.2" r="69.8"/>
+</g>
+</svg>
diff --git a/platform/android/scripts/configure.sh b/platform/android/scripts/configure.sh
index 81bdf19e98..2bbc134597 100644
--- a/platform/android/scripts/configure.sh
+++ b/platform/android/scripts/configure.sh
@@ -1,16 +1,19 @@
#!/usr/bin/env bash
-BOOST_VERSION=1.59.0
+UNIQUE_RESOURCE_VERSION=dev
+PROTOZERO_VERSION=1.3.0
+BOOST_VERSION=1.60.0
LIBPNG_VERSION=1.6.20
LIBJPEG_TURBO_VERSION=1.4.2
SQLITE_VERSION=3.9.1
-LIBUV_VERSION=1.7.5
ZLIB_VERSION=system
NUNICODE_VERSION=1.6
LIBZIP_VERSION=0.11.2
-GEOJSONVT_VERSION=3.1.0
-VARIANT_VERSION=1.0
+GEOMETRY_VERSION=0.5.0
+GEOJSONVT_VERSION=4.1.2
+VARIANT_VERSION=1.1.0
RAPIDJSON_VERSION=1.0.2
JNI_HPP_VERSION=2.0.0
+EARCUT_VERSION=0.11
export MASON_ANDROID_ABI=${MASON_PLATFORM_VERSION}
diff --git a/platform/android/scripts/debug.sh b/platform/android/scripts/debug.sh
new file mode 100755
index 0000000000..ade9ab2d6f
--- /dev/null
+++ b/platform/android/scripts/debug.sh
@@ -0,0 +1,46 @@
+#!/usr/bin/env bash
+
+set -e
+set -o pipefail
+
+# Automation of https://github.com/mapbox/mapbox-gl-native/wiki/Android-debugging-with-remote-GDB
+
+export MASON_DIR="`pwd`/.mason"
+export PATH="${MASON_DIR}:${PATH}"
+
+export MASON_ANDROID_ABI=x86
+export MASON_ANDROID_ARCH=x86
+export MASON_ANDROID_PLATFORM=9
+export MASON_NDK_PACKAGE_VERSION=${MASON_ANDROID_ARCH}-${MASON_ANDROID_PLATFORM}-r10e
+
+if [[ $1 == '--prepare' ]]; then
+ mkdir -p ~/.android/debugging/{vendor,system}_lib
+ adb pull /system/lib ~/.android/debugging/system_lib
+ adb pull /vendor/lib ~/.android/debugging/vendor_lib
+ adb pull /system/bin/app_process ~/.android/debugging
+ adb pull /system/bin/app_process32 ~/.android/debugging
+ adb pull /system/bin/linker ~/.android/debugging
+
+ if [[ ${MASON_ANDROID_ABI} == 'x86_64' || ${MASON_ANDROID_ABI} == 'mips64' ]]; then
+ adb pull /system/bin/app_process64 ~/.android/debugging
+ adb pull /system/bin/linker64 ~/.android/debugging
+ fi
+
+ cp `mason prefix android-ndk ${MASON_NDK_PACKAGE_VERSION}`/prebuilt/android-${MASON_ANDROID_ABI}/gdbserver/gdbserver \
+ platform/android/MapboxGLAndroidSDK/src/main/jniLibs/${MASON_ANDROID_ABI}/gdbserver.so
+fi
+
+adb install -rtdg platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug.apk
+adb shell am start -n "com.mapbox.mapboxsdk.testapp/com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity" \
+ -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
+
+adb forward tcp:5039 tcp:5039
+adb shell run-as com.mapbox.mapboxsdk.testapp '/data/data/com.mapbox.mapboxsdk.testapp/lib/gdbserver.so \
+ --attach :5039 `pgrep com.mapbox.mapboxsdk.testapp`' &
+
+export MASON_PLATFORM=android
+export PATH=`mason env PATH`
+`mason env MASON_ANDROID_TOOLCHAIN`-gdb \
+ -ex "target remote :5039" \
+ -ex "set solib-search-path ~/.android/debugging:~/.android/debugging/system_lib:~/.android/debugging/vendor_lib:~/.android/debugging/vendor_lib/egl:./build/android-${MASON_ANDROID_ABI}/Debug/lib.target/"
+
diff --git a/platform/android/scripts/defaults.mk b/platform/android/scripts/defaults.mk
deleted file mode 100644
index 5f049aae48..0000000000
--- a/platform/android/scripts/defaults.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-HEADLESS ?= none
-PLATFORM ?= android
-ASSET ?= zip
-HTTP ?= android
-
-GYP_FLAVOR_SUFFIX=-android
-
-HOST_VERSION ?= arm-v7
-
-ENV = $(shell MASON_ANDROID_ABI=$(HOST_VERSION) ./platform/android/scripts/toolchain.sh)
diff --git a/platform/android/scripts/install.sh b/platform/android/scripts/install.sh
deleted file mode 100755
index e99c3dc75e..0000000000
--- a/platform/android/scripts/install.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-mapbox_time "checkout_mason" \
-git submodule update --init .mason
-
-export MASON_PLATFORM=android
-export MASON_ANDROID_ABI=${ANDROID_ABI}
-
-mapbox_time "android_toolchain" \
-./platform/android/scripts/toolchain.sh
diff --git a/platform/android/scripts/run.sh b/platform/android/scripts/run.sh
deleted file mode 100755
index 9e87298fe9..0000000000
--- a/platform/android/scripts/run.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-set -o pipefail
-
-# Add Mason to PATH
-export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason"
-export MASON_PLATFORM=android
-export MASON_ANDROID_ABI=${ANDROID_ABI}
-
-################################################################################
-# Build
-################################################################################
-
-mkdir -p ./platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw
-echo "${MAPBOX_ACCESS_TOKEN}" > ./platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/token.txt
-
-mapbox_time "compile_library" \
-make android-lib HOST_VERSION=${ANDROID_ABI} -j${JOBS} BUILDTYPE=${BUILDTYPE}
-
-mapbox_time "build_apk" \
-make android HOST_VERSION=${ANDROID_ABI} -j${JOBS} BUILDTYPE=${BUILDTYPE}
-
-################################################################################
-# Deploy
-################################################################################
-
-if [ ! -z "${AWS_ACCESS_KEY_ID}" ] && [ ! -z "${AWS_SECRET_ACCESS_KEY}" ] ; then
- # Install and add awscli to PATH for uploading the results
- mapbox_time "install_awscli" \
- pip install --user awscli
- export PATH="`python -m site --user-base`/bin:${PATH}"
-
- mapbox_time_start "deploy_results"
- echo "Deploying results..."
-
- S3_PREFIX=s3://mapbox/mapbox-gl-native/android/build/${TRAVIS_JOB_NUMBER}
- APK_OUTPUTS=./platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk
- JNILIB=`mason env JNIDIR`
-
- # ARM64 does not build APK for now
- if [ ${JNIDIR} != "arm64-v8a" ] ; then
- # Upload either the debug or the release build
- if [ ${BUILDTYPE} == "Debug" ] ; then
- aws s3 cp \
- ${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-${JNILIB}-debug.apk \
- ${S3_PREFIX}/MapboxGLAndroidSDKTestApp-debug.apk
- elif [ ${BUILDTYPE} == "Release" ] ; then
- aws s3 cp \
- ${APK_OUTPUTS}/MapboxGLAndroidSDKTestApp-${JNILIB}-release-unsigned.apk \
- ${S3_PREFIX}/MapboxGLAndroidSDKTestApp-release-unsigned.apk
- fi
- fi
-
- mapbox_time_finish
-fi
diff --git a/platform/android/scripts/toolchain.sh b/platform/android/scripts/toolchain.sh
index 67cd0aa476..6eb6a229fe 100755
--- a/platform/android/scripts/toolchain.sh
+++ b/platform/android/scripts/toolchain.sh
@@ -4,7 +4,7 @@ set -e
set -o pipefail
export MASON_PLATFORM=android
-export MASON_ANDROID_ABI=${MASON_ANDROID_ABI:-arm-v7}
+export MASON_ANDROID_ABI=${1:-arm-v7}
export PATH="`pwd`/.mason:${PATH}"
export MASON_DIR="`pwd`/.mason"
diff --git a/platform/android/src/asset_file_source.cpp b/platform/android/src/asset_file_source.cpp
index d2aab30a52..2babe7db41 100644
--- a/platform/android/src/asset_file_source.cpp
+++ b/platform/android/src/asset_file_source.cpp
@@ -35,7 +35,7 @@ struct ZipFileHolder {
namespace mbgl {
-class AssetFileRequest : public FileRequest {
+class AssetFileRequest : public AsyncRequest {
public:
AssetFileRequest(std::unique_ptr<WorkRequest> workRequest_)
: workRequest(std::move(workRequest_)) {
@@ -100,14 +100,14 @@ private:
AssetFileSource::AssetFileSource(const std::string& root)
: thread(std::make_unique<util::Thread<Impl>>(
- util::ThreadContext{"AssetFileSource", util::ThreadType::Worker, util::ThreadPriority::Regular},
+ util::ThreadContext{"AssetFileSource"},
root)) {
}
AssetFileSource::~AssetFileSource() = default;
-std::unique_ptr<FileRequest> AssetFileSource::request(const Resource& resource, Callback callback) {
- return std::make_unique<AssetFileRequest>(thread->invokeWithCallback(&Impl::request, callback, resource.url));
+std::unique_ptr<AsyncRequest> AssetFileSource::request(const Resource& resource, Callback callback) {
+ return thread->invokeWithCallback(&Impl::request, callback, resource.url);
}
}
diff --git a/platform/android/src/async_task.cpp b/platform/android/src/async_task.cpp
new file mode 100644
index 0000000000..6a9263baff
--- /dev/null
+++ b/platform/android/src/async_task.cpp
@@ -0,0 +1,63 @@
+#include "run_loop_impl.hpp"
+
+#include <mbgl/util/async_task.hpp>
+#include <mbgl/util/atomic.hpp>
+#include <mbgl/util/run_loop.hpp>
+
+#include <functional>
+
+namespace mbgl {
+namespace util {
+
+class AsyncTask::Impl : public RunLoop::Impl::Runnable {
+public:
+ Impl(std::function<void()>&& fn)
+ : queued(true), task(std::move(fn)) {
+ loop->initRunnable(this);
+ }
+
+ ~Impl() {
+ loop->removeRunnable(this);
+ }
+
+ void maySend() {
+ if (queued) {
+ queued = false;
+ loop->addRunnable(this);
+ }
+ }
+
+ TimePoint dueTime() const override {
+ return due;
+ }
+
+ void runTask() override {
+ loop->removeRunnable(this);
+ queued = true;
+ task();
+ }
+
+private:
+ // Always expired, run immediately.
+ const TimePoint due = Clock::now();
+
+ RunLoop::Impl* loop = reinterpret_cast<RunLoop::Impl*>(RunLoop::getLoopHandle());
+
+ // TODO: Use std::atomic_flag if we ever drop
+ // support for ARMv5
+ util::Atomic<bool> queued;
+ std::function<void()> task;
+};
+
+AsyncTask::AsyncTask(std::function<void()>&& fn)
+ : impl(std::make_unique<Impl>(std::move(fn))) {
+}
+
+AsyncTask::~AsyncTask() = default;
+
+void AsyncTask::send() {
+ impl->maySend();
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/android/src/example_custom_layer.cpp b/platform/android/src/example_custom_layer.cpp
index 439f9aff1a..516a8f2cd5 100644
--- a/platform/android/src/example_custom_layer.cpp
+++ b/platform/android/src/example_custom_layer.cpp
@@ -1,7 +1,7 @@
#include <jni.h>
#include <GLES2/gl2.h>
-#include <mbgl/style/types.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
static const GLchar * fragmentShaderSource = "void main() { gl_FragColor = vec4(0, 1, 0, 1); }";
@@ -64,7 +64,7 @@ void nativeInitialize(void *context) {
reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
}
-void nativeRender(void *context, const mbgl::CustomLayerRenderParameters& /*parameters*/) {
+void nativeRender(void *context, const mbgl::style::CustomLayerRenderParameters& /*parameters*/) {
reinterpret_cast<ExampleCustomLayer*>(context)->render();
}
@@ -76,7 +76,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
JNIEnv *env = nullptr;
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
- jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/layers/ExampleCustomLayer");
+ jclass customLayerClass = env->FindClass("com/mapbox/mapboxsdk/testapp/model/customlayer/ExampleCustomLayer");
JNINativeMethod methods[] = {
{"createContext", "()J", reinterpret_cast<void *>(&nativeCreateContext)}
diff --git a/platform/android/src/http_request_android.cpp b/platform/android/src/http_file_source.cpp
index 1e0039cdf8..97ccdb14b4 100644
--- a/platform/android/src/http_request_android.cpp
+++ b/platform/android/src/http_file_source.cpp
@@ -1,5 +1,4 @@
-#include <mbgl/storage/http_context_base.hpp>
-#include <mbgl/storage/http_request_base.hpp>
+#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/platform/log.hpp>
@@ -7,26 +6,24 @@
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/string.hpp>
+#include <mbgl/util/http_header.hpp>
#include <jni/jni.hpp>
#include "attach_env.hpp"
namespace mbgl {
-namespace android {
-class HTTPContext : public HTTPContextBase {
+class HTTPFileSource::Impl {
public:
- HTTPRequestBase* createRequest(const Resource&, HTTPRequestBase::Callback) final;
- UniqueEnv env { android::AttachEnv() };
+ android::UniqueEnv env { android::AttachEnv() };
};
-class HTTPRequest : public HTTPRequestBase {
+class HTTPRequest : public AsyncRequest {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/http/HTTPRequest"; };
- HTTPRequest(jni::JNIEnv&, const Resource&, Callback);
-
- void cancel() final;
+ HTTPRequest(jni::JNIEnv&, const Resource&, FileSource::Callback);
+ ~HTTPRequest();
void onFailure(jni::JNIEnv&, int type, jni::String message);
void onResponse(jni::JNIEnv&, int code,
@@ -38,12 +35,16 @@ public:
jni::UniqueObject<HTTPRequest> javaRequest;
private:
- void finish();
+ Resource resource;
+ FileSource::Callback callback;
+ Response response;
- std::unique_ptr<Response> response;
- const std::shared_ptr<const Response> existingResponse;
-
- util::AsyncTask async;
+ util::AsyncTask async { [this] {
+ // Calling `callback` may result in deleting `this`. Copy data to temporaries first.
+ auto callback_ = callback;
+ auto response_ = response;
+ callback_(response_);
+ } };
static const int connectionError = 0;
static const int temporaryError = 1;
@@ -52,6 +53,8 @@ private:
jni::Class<HTTPRequest> HTTPRequest::javaClass;
+namespace android {
+
void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
HTTPRequest::javaClass = *jni::Class<HTTPRequest>::Find(env).NewGlobalRef(env).release();
@@ -62,15 +65,11 @@ void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
}
-// -------------------------------------------------------------------------------------------------
-
-HTTPRequestBase* HTTPContext::createRequest(const Resource& resource, HTTPRequestBase::Callback callback) {
- return new HTTPRequest(*env, resource, callback);
-}
+} // namespace android
-HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, Callback callback_)
- : HTTPRequestBase(resource_, callback_),
- async([this] { finish(); }) {
+HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, FileSource::Callback callback_)
+ : resource(resource_),
+ callback(callback_) {
std::string etagStr;
std::string modifiedStr;
@@ -93,63 +92,53 @@ HTTPRequest::HTTPRequest(jni::JNIEnv& env, const Resource& resource_, Callback c
jni::Make<jni::String>(env, modifiedStr)).NewGlobalRef(env);
}
-void HTTPRequest::cancel() {
- UniqueEnv env = android::AttachEnv();
+HTTPRequest::~HTTPRequest() {
+ android::UniqueEnv env = android::AttachEnv();
static auto cancel = javaClass.GetMethod<void ()>(*env, "cancel");
javaRequest->Call(*env, cancel);
-
- delete this;
-}
-
-void HTTPRequest::finish() {
- assert(response);
- notify(*response);
-
- delete this;
}
void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
jni::String etag, jni::String modified, jni::String cacheControl,
jni::String expires, jni::Array<jni::jbyte> body) {
- response = std::make_unique<Response>();
using Error = Response::Error;
if (etag) {
- response->etag = jni::Make<std::string>(env, etag);
+ response.etag = jni::Make<std::string>(env, etag);
}
if (modified) {
- response->modified = util::parseTimePoint(jni::Make<std::string>(env, modified).c_str());
+ response.modified = util::parseTimestamp(jni::Make<std::string>(env, modified).c_str());
}
if (cacheControl) {
- response->expires = parseCacheControl(jni::Make<std::string>(env, cacheControl).c_str());
+ response.expires = http::CacheControl::parse(jni::Make<std::string>(env, cacheControl).c_str()).toTimePoint();
}
if (expires) {
- response->expires = util::parseTimePoint(jni::Make<std::string>(env, expires).c_str());
+ response.expires = util::parseTimestamp(jni::Make<std::string>(env, expires).c_str());
}
if (code == 200) {
if (body) {
auto data = std::make_shared<std::string>(body.Length(env), char());
jni::GetArrayRegion(env, *body, 0, data->size(), reinterpret_cast<jbyte*>(&(*data)[0]));
- response->data = data;
+ response.data = data;
} else {
- response->data = std::make_shared<std::string>();
+ response.data = std::make_shared<std::string>();
}
} else if (code == 204 || (code == 404 && resource.kind == Resource::Kind::Tile)) {
- response->noContent = true;
+ response.noContent = true;
} else if (code == 304) {
- response->notModified = true;
+ response.notModified = true;
} else if (code == 404) {
- response->error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
+ response.error = std::make_unique<Error>(Error::Reason::NotFound, "HTTP status code 404");
} else if (code >= 500 && code < 600) {
- response->error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + std::to_string(code));
+ response.error = std::make_unique<Error>(Error::Reason::Server, std::string{ "HTTP status code " } + std::to_string(code));
} else {
- response->error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + std::to_string(code));
+ response.error = std::make_unique<Error>(Error::Reason::Other, std::string{ "HTTP status code " } + std::to_string(code));
}
async.send();
@@ -158,30 +147,33 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code,
void HTTPRequest::onFailure(jni::JNIEnv& env, int type, jni::String message) {
std::string messageStr = jni::Make<std::string>(env, message);
- response = std::make_unique<Response>();
using Error = Response::Error;
switch (type) {
case connectionError:
- response->error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
+ response.error = std::make_unique<Error>(Error::Reason::Connection, messageStr);
break;
case temporaryError:
- response->error = std::make_unique<Error>(Error::Reason::Server, messageStr);
+ response.error = std::make_unique<Error>(Error::Reason::Server, messageStr);
break;
default:
- response->error = std::make_unique<Error>(Error::Reason::Other, messageStr);
+ response.error = std::make_unique<Error>(Error::Reason::Other, messageStr);
}
async.send();
}
-} // namespace android
+HTTPFileSource::HTTPFileSource()
+ : impl(std::make_unique<Impl>()) {
+}
+
+HTTPFileSource::~HTTPFileSource() = default;
-std::unique_ptr<HTTPContextBase> HTTPContextBase::createContext() {
- return std::make_unique<android::HTTPContext>();
+std::unique_ptr<AsyncRequest> HTTPFileSource::request(const Resource& resource, Callback callback) {
+ return std::make_unique<HTTPRequest>(*impl->env, resource, callback);
}
-uint32_t HTTPContextBase::maximumConcurrentRequests() {
+uint32_t HTTPFileSource::maximumConcurrentRequests() {
return 20;
}
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 237fbb99da..e79689d7ad 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -13,14 +13,15 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
-#include <mbgl/annotation/point_annotation.hpp>
-#include <mbgl/annotation/shape_annotation.hpp>
+#include <mbgl/annotation/annotation.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/platform/event.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/string.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <jni/jni.hpp>
@@ -139,6 +140,8 @@ jni::jmethodID* offlineRegionStatusConstructorId = nullptr;
jni::jfieldID* offlineRegionStatusDownloadStateId = nullptr;
jni::jfieldID* offlineRegionStatusCompletedResourceCountId = nullptr;
jni::jfieldID* offlineRegionStatusCompletedResourceSizeId = nullptr;
+jni::jfieldID* offlineRegionStatusCompletedTileCountId = nullptr;
+jni::jfieldID* offlineRegionStatusCompletedTileSizeId = nullptr;
jni::jfieldID* offlineRegionStatusRequiredResourceCountId = nullptr;
jni::jfieldID* offlineRegionStatusRequiredResourceCountIsPreciseId = nullptr;
@@ -168,12 +171,12 @@ bool attach_jni_thread(JavaVM* vm, JNIEnv** env, std::string threadName) {
if (ret != JNI_OK) {
if (ret != JNI_EDETACHED) {
mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
- throw new std::runtime_error("GetEnv() failed");
+ throw std::runtime_error("GetEnv() failed");
} else {
ret = vm->AttachCurrentThread(env, &args);
if (ret != JNI_OK) {
mbgl::Log::Error(mbgl::Event::JNI, "AttachCurrentThread() failed with %i", ret);
- throw new std::runtime_error("AttachCurrentThread() failed");
+ throw std::runtime_error("AttachCurrentThread() failed");
}
detach = true;
}
@@ -190,7 +193,7 @@ void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach) {
jint ret;
if ((ret = vm->DetachCurrentThread()) != JNI_OK) {
mbgl::Log::Error(mbgl::Event::JNI, "DetachCurrentThread() failed with %i", ret);
- throw new std::runtime_error("DetachCurrentThread() failed");
+ throw std::runtime_error("DetachCurrentThread() failed");
}
}
*env = nullptr;
@@ -245,64 +248,6 @@ jni::jarray<jlong>* std_vector_uint_to_jobject(JNIEnv *env, std::vector<uint32_t
return &jarray;
}
-mbgl::AnnotationSegment annotation_segment_from_latlng_jlist(JNIEnv *env, jni::jobject* jlist) {
- mbgl::AnnotationSegment segment;
-
- NullCheck(*env, jlist);
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
-
- NullCheck(*env, jarray);
- std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- segment.reserve(len);
-
- for (std::size_t i = 0; i < len; i++) {
- jni::jobject* latLng = reinterpret_cast<jni::jobject*>(jni::GetObjectArrayElement(*env, *jarray, i));
- NullCheck(*env, latLng);
-
- jdouble latitude = jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId);
- jdouble longitude = jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId);
-
- segment.push_back(mbgl::LatLng(latitude, longitude));
- jni::DeleteLocalRef(*env, latLng);
- }
-
- jni::DeleteLocalRef(*env, jarray);
- jarray = nullptr;
-
- return segment;
-}
-
-std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> annotation_std_pair_from_polygon_jobject(JNIEnv *env, jni::jobject* polygon) {
- jfloat alpha = jni::GetField<jfloat>(*env, polygon, *polygonAlphaId);
- jint fillColor = jni::GetField<jint>(*env, polygon, *polygonFillColorId);
- jint strokeColor = jni::GetField<jint>(*env, polygon, *polygonStrokeColorId);
-
- int rF = (fillColor >> 16) & 0xFF;
- int gF = (fillColor >> 8) & 0xFF;
- int bF = (fillColor) & 0xFF;
- int aF = (fillColor >> 24) & 0xFF;
-
- int rS = (strokeColor >> 16) & 0xFF;
- int gS = (strokeColor >> 8) & 0xFF;
- int bS = (strokeColor) & 0xFF;
- int aS = (strokeColor >> 24) & 0xFF;
-
- mbgl::ShapeAnnotation::Properties shapeProperties;
- mbgl::FillAnnotationProperties fillProperties;
- fillProperties.opacity = alpha;
- fillProperties.outlineColor = {{ static_cast<float>(rS) / 255.0f, static_cast<float>(gS) / 255.0f, static_cast<float>(bS) / 255.0f, static_cast<float>(aS) / 255.0f }};
- fillProperties.color = {{ static_cast<float>(rF) / 255.0f, static_cast<float>(gF) / 255.0f, static_cast<float>(bF) / 255.0f, static_cast<float>(aF) / 255.0f }};
- shapeProperties.set<mbgl::FillAnnotationProperties>(fillProperties);
-
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
- mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
- jni::DeleteLocalRef(*env, points);
-
- return std::make_pair(segment, shapeProperties);
-}
-
static std::vector<uint8_t> metadata_from_java(JNIEnv* env, jni::jarray<jbyte>& j) {
mbgl::Log::Debug(mbgl::Event::JNI, "metadata_from_java");
std::size_t length = jni::GetArrayLength(*env, j);
@@ -404,27 +349,6 @@ void nativeDestroySurface(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr
nativeMapView->destroySurface();
}
-void nativePause(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativePause");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->pause();
-}
-
-jboolean nativeIsPaused(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeIsPaused");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().isPaused();
-}
-
-void nativeResume(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeResume");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->resume();
-}
-
void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate");
assert(nativeMapViewPtr != 0);
@@ -432,11 +356,11 @@ void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
nativeMapView->getMap().update(mbgl::Update::Repaint);
}
-void nativeRenderSync(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRenderSync");
+void nativeRender(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRender");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().renderSync();
+ nativeMapView->render();
}
void nativeViewResize(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jint width, jint height) {
@@ -496,22 +420,6 @@ jni::jobject* nativeGetClasses(JNIEnv *env, jni::jobject* obj, jlong nativeMapVi
return std_vector_string_to_jobject(env, nativeMapView->getMap().getClasses());
}
-void nativeSetDefaultTransitionDuration(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
- jlong duration) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetDefaultTransitionDuration");
- assert(nativeMapViewPtr != 0);
- assert(duration >= 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setDefaultTransitionDuration(mbgl::Milliseconds(duration));
-}
-
-jlong nativeGetDefaultTransitionDuration(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetDefaultTransitionDuration");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return std::chrono::duration_cast<mbgl::Milliseconds>(nativeMapView->getMap().getDefaultTransitionDuration()).count();
-}
-
void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* url) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleURL");
assert(nativeMapViewPtr != 0);
@@ -519,13 +427,11 @@ void nativeSetStyleUrl(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, j
nativeMapView->getMap().setStyleURL(std_string_from_jstring(env, url));
}
-void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
- jni::jstring* newStyleJson, jni::jstring* base) {
+void nativeSetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* newStyleJson) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeSetStyleJSON");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson),
- std_string_from_jstring(env, base));
+ nativeMapView->getMap().setStyleJSON(std_string_from_jstring(env, newStyleJson));
}
jni::jstring* nativeGetStyleJson(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
@@ -754,24 +660,6 @@ void nativeResetNorth(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
nativeMapView->getMap().resetNorth();
}
-jlong nativeAddMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* marker) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarker");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- jni::jobject* position = jni::GetField<jni::jobject*>(*env, marker, *markerPositionId);
- jni::jobject* icon = jni::GetField<jni::jobject*>(*env, marker, *markerIconId);
-
- jni::jstring* jid = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, icon, *iconIdId));
- std::string id = std_string_from_jstring(env, jid);
-
- jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
- jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
-
- // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
- return nativeMapView->getMap().addPointAnnotation(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), id));
-}
-
void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* marker) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdateMarker");
assert(nativeMapViewPtr != 0);
@@ -791,184 +679,133 @@ void nativeUpdateMarker(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr,
jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
- // Because Java only has int, not unsigned int, we need to bump the annotation id up to a long.
- nativeMapView->getMap().updatePointAnnotation(markerId, mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), iconId));
+ nativeMapView->getMap().updateAnnotation(markerId, mbgl::SymbolAnnotation {
+ mbgl::Point<double>(longitude, latitude),
+ iconId
+ });
}
-jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* jlist) {
+jni::jarray<jlong>* nativeAddMarkers(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddMarkers");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- std::vector<mbgl::PointAnnotation> markers;
-
- NullCheck(*env, jlist);
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
-
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
- markers.reserve(len);
+ std::vector<mbgl::AnnotationID> ids;
+ ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* marker = jni::GetObjectArrayElement(*env, *jarray, i);
jni::jobject* position = jni::GetField<jni::jobject*>(*env, marker, *markerPositionId);
jni::jobject* icon = jni::GetField<jni::jobject*>(*env, marker, *markerIconId);
- jni::DeleteLocalRef(*env, marker);
-
jni::jstring* jid = reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, icon, *iconIdId));
- jni::DeleteLocalRef(*env, icon);
-
- std::string id = std_string_from_jstring(env, jid);
- jni::DeleteLocalRef(*env, jid);
jdouble latitude = jni::GetField<jdouble>(*env, position, *latLngLatitudeId);
jdouble longitude = jni::GetField<jdouble>(*env, position, *latLngLongitudeId);
- jni::DeleteLocalRef(*env, position);
- markers.emplace_back(mbgl::PointAnnotation(mbgl::LatLng(latitude, longitude), id));
- }
+ ids.push_back(nativeMapView->getMap().addAnnotation(mbgl::SymbolAnnotation {
+ mbgl::Point<double>(longitude, latitude),
+ std_string_from_jstring(env, jid)
+ }));
- jni::DeleteLocalRef(*env, jarray);
+ jni::DeleteLocalRef(*env, position);
+ jni::DeleteLocalRef(*env, jid);
+ jni::DeleteLocalRef(*env, icon);
+ jni::DeleteLocalRef(*env, marker);
+ }
- std::vector<uint32_t> pointAnnotationIDs = nativeMapView->getMap().addPointAnnotations(markers);
- return std_vector_uint_to_jobject(env, pointAnnotationIDs);
+ return std_vector_uint_to_jobject(env, ids);
}
+static mbgl::Color toColor(jint color) {
+ float r = (color >> 16) & 0xFF;
+ float g = (color >> 8) & 0xFF;
+ float b = (color) & 0xFF;
+ float a = (color >> 24) & 0xFF;
+ return {{ r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f }};
+}
-jlong nativeAddPolyline(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* polyline) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolyline");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- jfloat alpha = jni::GetField<jfloat>(*env, polyline, *polylineAlphaId);
- jint color = jni::GetField<jint>(*env, polyline, *polylineColorId);
-
- int r = (color >> 16) & 0xFF;
- int g = (color >> 8) & 0xFF;
- int b = (color) & 0xFF;
- int a = (color >> 24) & 0xFF;
+template <class Geometry>
+Geometry toGeometry(JNIEnv *env, jni::jobject* jlist) {
+ NullCheck(*env, jlist);
+ jni::jarray<jni::jobject>* jarray =
+ reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
+ NullCheck(*env, jarray);
- jfloat width = jni::GetField<jfloat>(*env, polyline, *polylineWidthId);
+ Geometry geometry;
+ geometry.reserve(jni::GetArrayLength(*env, *jarray));
- mbgl::ShapeAnnotation::Properties shapeProperties;
- mbgl::LineAnnotationProperties lineProperties;
- lineProperties.opacity = alpha;
- lineProperties.color = {{ static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f, static_cast<float>(a) / 255.0f }};
- lineProperties.width = width;
- shapeProperties.set<mbgl::LineAnnotationProperties>(lineProperties);
+ for (std::size_t i = 0; i < geometry.size(); i++) {
+ jni::jobject* latLng = reinterpret_cast<jni::jobject*>(jni::GetObjectArrayElement(*env, *jarray, i));
+ NullCheck(*env, latLng);
- jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
- mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
+ geometry.push_back(mbgl::Point<double>(
+ jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId),
+ jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId)));
- std::vector<mbgl::ShapeAnnotation> shapes;
- shapes.emplace_back(mbgl::AnnotationSegments { segment }, shapeProperties);
+ jni::DeleteLocalRef(*env, latLng);
+ }
- std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
- uint32_t id = shapeAnnotationIDs.at(0);
+ jni::DeleteLocalRef(*env, jarray);
+ jni::DeleteLocalRef(*env, jlist);
- return id;
+ return geometry;
}
-jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* jlist) {
+jni::jarray<jlong>* nativeAddPolylines(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolylines");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- std::vector<mbgl::ShapeAnnotation> shapes;
-
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
-
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
- shapes.reserve(len);
+ std::vector<mbgl::AnnotationID> ids;
+ ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* polyline = jni::GetObjectArrayElement(*env, *jarray, i);
-
- jfloat alpha = jni::GetField<jfloat>(*env, polyline, *polylineAlphaId);
- jint color = jni::GetField<jint>(*env, polyline, *polylineColorId);
-
- int r = (color >> 16) & 0xFF;
- int g = (color >> 8) & 0xFF;
- int b = (color) & 0xFF;
- int a = (color >> 24) & 0xFF;
-
- jfloat width = jni::GetField<jfloat>(*env, polyline, *polylineWidthId);
-
- mbgl::ShapeAnnotation::Properties shapeProperties;
- mbgl::LineAnnotationProperties lineProperties;
- lineProperties.opacity = alpha;
- lineProperties.color = {{ static_cast<float>(r) / 255.0f, static_cast<float>(g) / 255.0f, static_cast<float>(b) / 255.0f, static_cast<float>(a) / 255.0f }};
- lineProperties.width = width;
- shapeProperties.set<mbgl::LineAnnotationProperties>(lineProperties);
-
jni::jobject* points = jni::GetField<jni::jobject*>(*env, polyline, *polylinePointsId);
- mbgl::AnnotationSegment segment = annotation_segment_from_latlng_jlist(env, points);
- shapes.emplace_back(mbgl::AnnotationSegments { segment }, shapeProperties);
+ mbgl::LineAnnotation annotation { toGeometry<mbgl::LineString<double>>(env, points) };
+ annotation.opacity = jni::GetField<jfloat>(*env, polyline, *polylineAlphaId);
+ annotation.color = toColor(jni::GetField<jint>(*env, polyline, *polylineColorId));
+ annotation.width = jni::GetField<jfloat>(*env, polyline, *polylineWidthId);
+ ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
jni::DeleteLocalRef(*env, polyline);
}
- jni::DeleteLocalRef(*env, jarray);
-
- std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
- return std_vector_uint_to_jobject(env, shapeAnnotationIDs);
+ return std_vector_uint_to_jobject(env, ids);
}
-jlong nativeAddPolygon(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* polygon) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygon");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
-
- std::vector<mbgl::ShapeAnnotation> shapes;
- std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
-
- shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second);
-
- std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
- uint32_t id = shapeAnnotationIDs.at(0);
- return id;
-}
-
-jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* jlist) {
+jni::jarray<jlong>* nativeAddPolygons(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jni::jobject>* jarray) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddPolygons");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- std::vector<mbgl::ShapeAnnotation> shapes;
-
- jni::jarray<jni::jobject>* jarray =
- reinterpret_cast<jni::jarray<jni::jobject>*>(jni::CallMethod<jni::jobject*>(*env, jlist, *listToArrayId));
-
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
- shapes.reserve(len);
+
+ std::vector<mbgl::AnnotationID> ids;
+ ids.reserve(len);
for (std::size_t i = 0; i < len; i++) {
jni::jobject* polygon = jni::GetObjectArrayElement(*env, *jarray, i);
+ jni::jobject* points = jni::GetField<jni::jobject*>(*env, polygon, *polygonPointsId);
- std::pair<mbgl::AnnotationSegment, mbgl::ShapeAnnotation::Properties> segment = annotation_std_pair_from_polygon_jobject(env, polygon);
- shapes.emplace_back(mbgl::AnnotationSegments { segment.first }, segment.second);
+ mbgl::FillAnnotation annotation { mbgl::Polygon<double> { toGeometry<mbgl::LinearRing<double>>(env, points) } };
+ annotation.opacity = jni::GetField<jfloat>(*env, polygon, *polygonAlphaId);
+ annotation.outlineColor = toColor(jni::GetField<jint>(*env, polygon, *polygonStrokeColorId));
+ annotation.color = toColor(jni::GetField<jint>(*env, polygon, *polygonFillColorId));
+ ids.push_back(nativeMapView->getMap().addAnnotation(annotation));
jni::DeleteLocalRef(*env, polygon);
}
- jni::DeleteLocalRef(*env, jarray);
-
- std::vector<uint32_t> shapeAnnotationIDs = nativeMapView->getMap().addShapeAnnotations(shapes);
- return std_vector_uint_to_jobject(env, shapeAnnotationIDs);
-}
-
-void nativeRemoveAnnotation(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong annotationId) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveAnnotation");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().removeAnnotation(static_cast<uint32_t>(annotationId));
+ return std_vector_uint_to_jobject(env, ids);
}
void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jarray<jlong>* jarray) {
@@ -978,20 +815,14 @@ void nativeRemoveAnnotations(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
NullCheck(*env, jarray);
std::size_t len = jni::GetArrayLength(*env, *jarray);
-
- std::vector<uint32_t> ids;
- ids.reserve(len);
-
auto elements = jni::GetArrayElements(*env, *jarray);
jlong* jids = std::get<0>(elements).get();
for (std::size_t i = 0; i < len; i++) {
if(jids[i] == -1L)
continue;
- ids.push_back(static_cast<uint32_t>(jids[i]));
+ nativeMapView->getMap().removeAnnotation(jids[i]);
}
-
- nativeMapView->getMap().removeAnnotations(ids);
}
jni::jarray<jlong>* nativeGetAnnotationsInBounds(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jobject* latLngBounds_) {
@@ -1052,17 +883,17 @@ void nativeSetVisibleCoordinateBounds(JNIEnv *env, jni::jobject* obj, jlong nati
std::size_t count = jni::GetArrayLength(*env, *coordinates);
mbgl::EdgeInsets mbglInsets = {top, left, bottom, right};
- mbgl::AnnotationSegment segment;
- segment.reserve(count);
+ std::vector<mbgl::LatLng> latLngs;
+ latLngs.reserve(count);
for (std::size_t i = 0; i < count; i++) {
jni::jobject* latLng = jni::GetObjectArrayElement(*env, *coordinates, i);
jdouble latitude = jni::GetField<jdouble>(*env, latLng, *latLngLatitudeId);
jdouble longitude = jni::GetField<jdouble>(*env, latLng, *latLngLongitudeId);
- segment.push_back(mbgl::LatLng(latitude, longitude));
+ latLngs.push_back(mbgl::LatLng(latitude, longitude));
}
- mbgl::CameraOptions cameraOptions = nativeMapView->getMap().cameraForLatLngs(segment, mbglInsets);
+ mbgl::CameraOptions cameraOptions = nativeMapView->getMap().cameraForLatLngs(latLngs, mbglInsets);
if (direction >= 0) {
// convert from degrees to radians
cameraOptions.angle = (-direction * M_PI) / 180;
@@ -1211,7 +1042,7 @@ void nativeJumpTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
nativeMapView->getMap().jumpTo(options);
}
-void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jni::jobject* centerLatLng, jlong duration, jdouble pitch, jdouble zoom) {
+void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jni::jobject* centerLatLng, jlong duration, jdouble pitch, jdouble zoom, jboolean easing) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeEaseTo");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
@@ -1234,6 +1065,11 @@ void nativeEaseTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdoubl
mbgl::AnimationOptions animationOptions;
animationOptions.duration.emplace(mbgl::Duration(duration));
+ if (!easing) {
+ // add a linear interpolator instead of easing
+ animationOptions.easing = mbgl::util::UnitBezier(0, 0, 1, 1);
+ }
+
nativeMapView->getMap().easeTo(cameraOptions, animationOptions);
}
@@ -1244,7 +1080,6 @@ void nativeSetContentPadding(JNIEnv *env, jni::jobject* obj,long nativeMapViewPt
nativeMapView->setInsets({top, left, bottom, right});
}
-
void nativeFlyTo(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jdouble angle, jni::jobject* centerLatLng, jlong duration, jdouble pitch, jdouble zoom) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeFlyTo");
assert(nativeMapViewPtr != 0);
@@ -1275,20 +1110,20 @@ void nativeAddCustomLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddCustomLayer");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().addCustomLayer(
+ nativeMapView->getMap().addLayer(std::make_unique<mbgl::style::CustomLayer>(
std_string_from_jstring(env, reinterpret_cast<jni::jstring*>(jni::GetField<jni::jobject*>(*env, customLayer, *customLayerIdId))),
- reinterpret_cast<mbgl::CustomLayerInitializeFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerInitializeFunctionId)),
- reinterpret_cast<mbgl::CustomLayerRenderFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerRenderFunctionId)),
- reinterpret_cast<mbgl::CustomLayerDeinitializeFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerDeinitializeFunctionId)),
- reinterpret_cast<void*>(jni::GetField<jlong>(*env, customLayer, *customLayerContextId)),
- before ? std_string_from_jstring(env, before).c_str() : nullptr);
+ reinterpret_cast<mbgl::style::CustomLayerInitializeFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerInitializeFunctionId)),
+ reinterpret_cast<mbgl::style::CustomLayerRenderFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerRenderFunctionId)),
+ reinterpret_cast<mbgl::style::CustomLayerDeinitializeFunction>(jni::GetField<jlong>(*env, customLayer, *customLayerDeinitializeFunctionId)),
+ reinterpret_cast<void*>(jni::GetField<jlong>(*env, customLayer, *customLayerContextId))),
+ before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>());
}
void nativeRemoveCustomLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveCustomLayer");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().removeCustomLayer(std_string_from_jstring(env, id));
+ nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id));
}
// Offline calls begin
@@ -1542,11 +1377,17 @@ void setOfflineRegionObserver(JNIEnv *env, jni::jobject* offlineRegion_, jni::jo
break;
}
+ // Create a new local reference frame (capacity 1 for the NewObject allocation below)
+ // to avoid a local reference table overflow (#4706)
+ jni::UniqueLocalFrame frame = jni::PushLocalFrame(*env2, 1);
+
// Stats object
jni::jobject* jstatus = &jni::NewObject(*env2, *offlineRegionStatusClass, *offlineRegionStatusConstructorId);
jni::SetField<jint>(*env2, jstatus, *offlineRegionStatusDownloadStateId, downloadState);
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceCountId, status.completedResourceCount);
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedResourceSizeId, status.completedResourceSize);
+ jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedTileCountId, status.completedTileCount);
+ jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusCompletedTileSizeId, status.completedTileSize);
jni::SetField<jlong>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountId, status.requiredResourceCount);
jni::SetField<jboolean>(*env2, jstatus, *offlineRegionStatusRequiredResourceCountIsPreciseId, status.requiredResourceCountIsPrecise);
jni::CallMethod<void>(*env2, observerCallback.get(), *offlineRegionObserveronStatusChangedId, jstatus);
@@ -1738,6 +1579,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
+ static mbgl::util::RunLoop mainRunLoop;
+
mbgl::android::RegisterNativeHTTPRequest(env);
latLngClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLng");
@@ -1831,11 +1674,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeTerminateContext, "(J)V"),
MAKE_NATIVE_METHOD(nativeCreateSurface, "(JLandroid/view/Surface;)V"),
MAKE_NATIVE_METHOD(nativeDestroySurface, "(J)V"),
- MAKE_NATIVE_METHOD(nativePause, "(J)V"),
- MAKE_NATIVE_METHOD(nativeIsPaused, "(J)Z"),
- MAKE_NATIVE_METHOD(nativeResume, "(J)V"),
MAKE_NATIVE_METHOD(nativeUpdate, "(J)V"),
- MAKE_NATIVE_METHOD(nativeRenderSync, "(J)V"),
+ MAKE_NATIVE_METHOD(nativeRender, "(J)V"),
MAKE_NATIVE_METHOD(nativeViewResize, "(JII)V"),
MAKE_NATIVE_METHOD(nativeFramebufferResize, "(JII)V"),
MAKE_NATIVE_METHOD(nativeAddClass, "(JLjava/lang/String;)V"),
@@ -1843,10 +1683,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeHasClass, "(JLjava/lang/String;)Z"),
MAKE_NATIVE_METHOD(nativeSetClasses, "(JLjava/util/List;)V"),
MAKE_NATIVE_METHOD(nativeGetClasses, "(J)Ljava/util/List;"),
- MAKE_NATIVE_METHOD(nativeSetDefaultTransitionDuration, "(JJ)V"),
- MAKE_NATIVE_METHOD(nativeGetDefaultTransitionDuration, "(J)J"),
MAKE_NATIVE_METHOD(nativeSetStyleUrl, "(JLjava/lang/String;)V"),
- MAKE_NATIVE_METHOD(nativeSetStyleJson, "(JLjava/lang/String;Ljava/lang/String;)V"),
+ MAKE_NATIVE_METHOD(nativeSetStyleJson, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeGetStyleJson, "(J)Ljava/lang/String;"),
MAKE_NATIVE_METHOD(nativeSetAccessToken, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeGetAccessToken, "(J)Ljava/lang/String;"),
@@ -1874,14 +1712,10 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeSetBearingXY, "(JDDD)V"),
MAKE_NATIVE_METHOD(nativeGetBearing, "(J)D"),
MAKE_NATIVE_METHOD(nativeResetNorth, "(J)V"),
- MAKE_NATIVE_METHOD(nativeAddMarker, "(JLcom/mapbox/mapboxsdk/annotations/Marker;)J"),
- MAKE_NATIVE_METHOD(nativeAddMarkers, "(JLjava/util/List;)[J"),
- MAKE_NATIVE_METHOD(nativeAddPolyline, "(JLcom/mapbox/mapboxsdk/annotations/Polyline;)J"),
- MAKE_NATIVE_METHOD(nativeAddPolylines, "(JLjava/util/List;)[J"),
- MAKE_NATIVE_METHOD(nativeAddPolygon, "(JLcom/mapbox/mapboxsdk/annotations/Polygon;)J"),
- MAKE_NATIVE_METHOD(nativeAddPolygons, "(JLjava/util/List;)[J"),
+ MAKE_NATIVE_METHOD(nativeAddMarkers, "(J[Lcom/mapbox/mapboxsdk/annotations/Marker;)[J"),
+ MAKE_NATIVE_METHOD(nativeAddPolylines, "(J[Lcom/mapbox/mapboxsdk/annotations/Polyline;)[J"),
+ MAKE_NATIVE_METHOD(nativeAddPolygons, "(J[Lcom/mapbox/mapboxsdk/annotations/Polygon;)[J"),
MAKE_NATIVE_METHOD(nativeUpdateMarker, "(JLcom/mapbox/mapboxsdk/annotations/Marker;)V"),
- MAKE_NATIVE_METHOD(nativeRemoveAnnotation, "(JJ)V"),
MAKE_NATIVE_METHOD(nativeRemoveAnnotations, "(J[J)V"),
MAKE_NATIVE_METHOD(nativeGetAnnotationsInBounds, "(JLcom/mapbox/mapboxsdk/geometry/LatLngBounds;)[J"),
MAKE_NATIVE_METHOD(nativeAddAnnotationIcon, "(JLjava/lang/String;IIF[B)V"),
@@ -1899,7 +1733,7 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeLatLngForPixel, "(JLandroid/graphics/PointF;)Lcom/mapbox/mapboxsdk/geometry/LatLng;"),
MAKE_NATIVE_METHOD(nativeGetTopOffsetPixelsForAnnotationSymbol, "(JLjava/lang/String;)D"),
MAKE_NATIVE_METHOD(nativeJumpTo, "(JDLcom/mapbox/mapboxsdk/geometry/LatLng;DD)V"),
- MAKE_NATIVE_METHOD(nativeEaseTo, "(JDLcom/mapbox/mapboxsdk/geometry/LatLng;JDD)V"),
+ MAKE_NATIVE_METHOD(nativeEaseTo, "(JDLcom/mapbox/mapboxsdk/geometry/LatLng;JDDZ)V"),
MAKE_NATIVE_METHOD(nativeFlyTo, "(JDLcom/mapbox/mapboxsdk/geometry/LatLng;JDD)V"),
MAKE_NATIVE_METHOD(nativeAddCustomLayer, "(JLcom/mapbox/mapboxsdk/layers/CustomLayer;Ljava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeRemoveCustomLayer, "(JLjava/lang/String;)V"),
@@ -1982,6 +1816,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
offlineRegionStatusDownloadStateId = &jni::GetFieldID(env, *offlineRegionStatusClass, "downloadState", "I");
offlineRegionStatusCompletedResourceCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedResourceCount", "J");
offlineRegionStatusCompletedResourceSizeId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedResourceSize", "J");
+ offlineRegionStatusCompletedTileCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedTileCount", "J");
+ offlineRegionStatusCompletedTileSizeId = &jni::GetFieldID(env, *offlineRegionStatusClass, "completedTileSize", "J");
offlineRegionStatusRequiredResourceCountId = &jni::GetFieldID(env, *offlineRegionStatusClass, "requiredResourceCount", "J");
offlineRegionStatusRequiredResourceCountIsPreciseId = &jni::GetFieldID(env, *offlineRegionStatusClass, "requiredResourceCountIsPrecise", "Z");
diff --git a/platform/android/src/jni.hpp b/platform/android/src/jni.hpp
index c2f1f5481b..57f84f0ccc 100644
--- a/platform/android/src/jni.hpp
+++ b/platform/android/src/jni.hpp
@@ -1,5 +1,4 @@
-#ifndef MBGL_ANDROID_JNI
-#define MBGL_ANDROID_JNI
+#pragma once
#include <string>
@@ -26,5 +25,3 @@ extern void detach_jni_thread(JavaVM* vm, JNIEnv** env, bool detach);
}
}
-
-#endif
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 58883b2313..0b849976eb 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -26,7 +26,7 @@ void log_egl_string(EGLDisplay display, EGLint name, const char *label) {
if (str == nullptr) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglQueryString(%d) returned error %d", name,
eglGetError());
- throw new std::runtime_error("eglQueryString() failed");
+ throw std::runtime_error("eglQueryString() failed");
} else {
char buf[513];
for (int len = std::strlen(str), pos = 0; len > 0; len -= 512, pos += 512) {
@@ -42,7 +42,7 @@ void log_gl_string(GLenum name, const char *label) {
if (str == nullptr) {
mbgl::Log::Error(mbgl::Event::OpenGL, "glGetString(%d) returned error %d", name,
glGetError());
- throw new std::runtime_error("glGetString() failed");
+ throw std::runtime_error("glGetString() failed");
} else {
char buf[513];
for (int len = std::strlen(reinterpret_cast<const char *>(str)), pos = 0; len > 0;
@@ -54,14 +54,15 @@ void log_gl_string(GLenum name, const char *label) {
}
}
-NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
+NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
: mbgl::View(*this),
+ env(env_),
pixelRatio(pixelRatio_),
availableProcessors(availableProcessors_),
totalMemory(totalMemory_) {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::NativeMapView");
- assert(env != nullptr);
+ assert(env_ != nullptr);
assert(obj_ != nullptr);
if (env->GetJavaVM(&vm) < 0) {
@@ -90,8 +91,6 @@ NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_, int a
size_t cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5f;
map->setSourceTileCacheSize(cacheSize);
-
- map->pause();
}
NativeMapView::~NativeMapView() {
@@ -106,16 +105,10 @@ NativeMapView::~NativeMapView() {
map.reset();
fileSource.reset();
- jint ret;
- JNIEnv *env = nullptr;
- ret = vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
- if (ret == JNI_OK) {
- env->DeleteWeakGlobalRef(obj);
- } else {
- mbgl::Log::Error(mbgl::Event::JNI, "GetEnv() failed with %i", ret);
- throw new std::runtime_error("GetEnv() failed");
- }
+ env->DeleteWeakGlobalRef(obj);
+
obj = nullptr;
+ env = nullptr;
vm = nullptr;
}
@@ -134,20 +127,23 @@ std::array<uint16_t, 2> NativeMapView::getFramebufferSize() const {
void NativeMapView::activate() {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::activate");
- assert(vm != nullptr);
+ oldDisplay = eglGetCurrentDisplay();
+ oldReadSurface = eglGetCurrentSurface(EGL_READ);
+ oldDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ oldContext = eglGetCurrentContext();
- renderDetach = attach_jni_thread(vm, &renderEnv, "Map Thread");
+ assert(vm != nullptr);
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE) && (context != EGL_NO_CONTEXT)) {
if (!eglMakeCurrent(display, surface, surface, context)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglMakeCurrent() returned error %d",
eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
+ throw std::runtime_error("eglMakeCurrent() failed");
}
if (!eglSwapInterval(display, 0)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapInterval() returned error %d", eglGetError());
- throw new std::runtime_error("eglSwapInterval() failed");
+ throw std::runtime_error("eglSwapInterval() failed");
}
} else {
mbgl::Log::Info(mbgl::Event::Android, "Not activating as we are not ready");
@@ -159,17 +155,21 @@ void NativeMapView::deactivate() {
assert(vm != nullptr);
- if (display != EGL_NO_DISPLAY) {
+ if (oldContext != context && oldContext != EGL_NO_CONTEXT) {
+ if (!eglMakeCurrent(oldDisplay, oldDrawSurface, oldReadSurface, oldContext)) {
+ mbgl::Log::Error(mbgl::Event::OpenGL, "eglMakeCurrent() returned error %d",
+ eglGetError());
+ throw std::runtime_error("eglMakeCurrent() failed");
+ }
+ } else if (display != EGL_NO_DISPLAY) {
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglMakeCurrent(EGL_NO_CONTEXT) returned error %d",
eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
+ throw std::runtime_error("eglMakeCurrent() failed");
}
} else {
mbgl::Log::Info(mbgl::Event::Android, "Not deactivating as we are not ready");
}
-
- detach_jni_thread(vm, &renderEnv, renderDetach);
}
void NativeMapView::invalidate() {
@@ -178,48 +178,35 @@ void NativeMapView::invalidate() {
assert(vm != nullptr);
assert(obj != nullptr);
- JNIEnv *env = nullptr;
- bool detach = attach_jni_thread(vm, &env, "NativeMapView::invalidate()");
-
env->CallVoidMethod(obj, onInvalidateId);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
}
-
- detach_jni_thread(vm, &env, detach);
}
-void NativeMapView::beforeRender() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::beforeRender()");
+void NativeMapView::render() {
+ activate();
if(sizeChanged){
sizeChanged = false;
glViewport(0, 0, fbWidth, fbHeight);
}
-}
-void NativeMapView::afterRender() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::afterRender()");
-
- assert(vm != nullptr);
- assert(obj != nullptr);
+ map->render();
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
if (!eglSwapBuffers(display, surface)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapBuffers() returned error %d",
eglGetError());
- throw new std::runtime_error("eglSwapBuffers() failed");
+ throw std::runtime_error("eglSwapBuffers() failed");
}
updateFps();
} else {
mbgl::Log::Info(mbgl::Event::Android, "Not swapping as we are not ready");
}
-}
-void NativeMapView::notify() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::notify()");
- // noop
+ deactivate();
}
mbgl::Map &NativeMapView::getMap() { return *map; }
@@ -243,18 +230,18 @@ void NativeMapView::initializeDisplay() {
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglGetDisplay() returned error %d", eglGetError());
- throw new std::runtime_error("eglGetDisplay() failed");
+ throw std::runtime_error("eglGetDisplay() failed");
}
EGLint major, minor;
if (!eglInitialize(display, &major, &minor)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglInitialize() returned error %d", eglGetError());
- throw new std::runtime_error("eglInitialize() failed");
+ throw std::runtime_error("eglInitialize() failed");
}
if ((major <= 1) && (minor < 3)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "EGL version is too low, need 1.3, got %d.%d", major,
minor);
- throw new std::runtime_error("EGL version is too low");
+ throw std::runtime_error("EGL version is too low");
}
log_egl_string(display, EGL_VENDOR, "Vendor");
@@ -282,29 +269,29 @@ void NativeMapView::initializeDisplay() {
if (!eglChooseConfig(display, configAttribs, nullptr, 0, &numConfigs)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglChooseConfig(NULL) returned error %d",
eglGetError());
- throw new std::runtime_error("eglChooseConfig() failed");
+ throw std::runtime_error("eglChooseConfig() failed");
}
if (numConfigs < 1) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglChooseConfig() returned no configs.");
- throw new std::runtime_error("eglChooseConfig() failed");
+ throw std::runtime_error("eglChooseConfig() failed");
}
const auto configs = std::make_unique<EGLConfig[]>(numConfigs);
if (!eglChooseConfig(display, configAttribs, configs.get(), numConfigs, &numConfigs)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglChooseConfig() returned error %d", eglGetError());
- throw new std::runtime_error("eglChooseConfig() failed");
+ throw std::runtime_error("eglChooseConfig() failed");
}
config = chooseConfig(configs.get(), numConfigs);
if (config == nullptr) {
mbgl::Log::Error(mbgl::Event::OpenGL, "No config chosen");
- throw new std::runtime_error("No config chosen");
+ throw std::runtime_error("No config chosen");
}
if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglGetConfigAttrib() returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
mbgl::Log::Info(mbgl::Event::OpenGL, "Chosen window format is %d", format);
}
@@ -318,7 +305,7 @@ void NativeMapView::terminateDisplay() {
if (!eglDestroySurface(display, surface)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglDestroySurface() returned error %d",
eglGetError());
- throw new std::runtime_error("eglDestroySurface() failed");
+ throw std::runtime_error("eglDestroySurface() failed");
}
surface = EGL_NO_SURFACE;
}
@@ -326,13 +313,13 @@ void NativeMapView::terminateDisplay() {
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglMakeCurrent(EGL_NO_CONTEXT) returned error %d", eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
+ throw std::runtime_error("eglMakeCurrent() failed");
}
if (!eglTerminate(display)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglTerminate() returned error %d",
eglGetError());
- throw new std::runtime_error("eglTerminate() failed");
+ throw std::runtime_error("eglTerminate() failed");
}
}
@@ -353,7 +340,7 @@ void NativeMapView::initializeContext() {
if (context == EGL_NO_CONTEXT) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglCreateContext() returned error %d",
eglGetError());
- throw new std::runtime_error("eglCreateContext() failed");
+ throw std::runtime_error("eglCreateContext() failed");
}
}
@@ -364,14 +351,14 @@ void NativeMapView::terminateContext() {
if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglMakeCurrent(EGL_NO_CONTEXT) returned error %d", eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
+ throw std::runtime_error("eglMakeCurrent() failed");
}
if (context != EGL_NO_CONTEXT) {
if (!eglDestroyContext(display, context)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglDestroyContext() returned error %d",
eglGetError());
- throw new std::runtime_error("eglDestroyContext() failed");
+ throw std::runtime_error("eglDestroyContext() failed");
}
}
}
@@ -398,21 +385,18 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
if (surface == EGL_NO_SURFACE) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglCreateWindowSurface() returned error %d",
eglGetError());
- throw new std::runtime_error("eglCreateWindowSurface() failed");
+ throw std::runtime_error("eglCreateWindowSurface() failed");
}
if (!firstTime) {
firstTime = true;
- EGLDisplay oldDisplay = eglGetCurrentDisplay();
- EGLSurface oldReadSurface = eglGetCurrentSurface(EGL_READ);
- EGLSurface oldDrawSurface = eglGetCurrentSurface(EGL_DRAW);
- EGLContext oldContext = eglGetCurrentContext();
+ activate();
if (!eglMakeCurrent(display, surface, surface, context)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglMakeCurrent() returned error %d",
eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
+ throw std::runtime_error("eglMakeCurrent() failed");
}
log_gl_string(GL_VENDOR, "Vendor");
@@ -429,35 +413,18 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
});
- if (oldDisplay == EGL_NO_DISPLAY) {
- oldDisplay = display;
- }
-
- if (!eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
- mbgl::Log::Error(mbgl::Event::OpenGL,"eglMakeCurrent(EGL_NO_CONTEXT) returned error %d", eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
- }
-
- if (!eglMakeCurrent(oldDisplay, oldDrawSurface, oldReadSurface, oldContext)) {
- mbgl::Log::Error(mbgl::Event::OpenGL,
- "eglMakeCurrent(EGL_NO_CONTEXT) returned error %d", eglGetError());
- throw new std::runtime_error("eglMakeCurrent() failed");
- }
+ deactivate();
}
-
- resume();
}
void NativeMapView::destroySurface() {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::destroySurface");
- pause();
-
if (surface != EGL_NO_SURFACE) {
if (!eglDestroySurface(display, surface)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglDestroySurface() returned error %d",
eglGetError());
- throw new std::runtime_error("eglDestroySurface() failed");
+ throw std::runtime_error("eglDestroySurface() failed");
}
}
@@ -518,77 +485,77 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_CONFIG_CAVEAT) returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_CONFORMANT, &conformant)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_CONFORMANT) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_BUFFER_SIZE, &bits)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_BUFFER_SIZE) returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &red)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_RED_SIZE) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &green)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_GREEN_SIZE) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blue)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_BLUE_SIZE) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alpha)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_ALPHA_SIZE) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_ALPHA_MASK_SIZE, &alphaMask)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_ALPHA_MASK_SIZE) returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_DEPTH_SIZE, &depth)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_DEPTH_SIZE) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_STENCIL_SIZE, &stencil)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_STENCIL_SIZE) returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_SAMPLE_BUFFERS, &sampleBuffers)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_SAMPLE_BUFFERS) returned error %d",
eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
if (!eglGetConfigAttrib(display, configs[i], EGL_SAMPLES, &samples)) {
mbgl::Log::Error(mbgl::Event::OpenGL,
"eglGetConfigAttrib(EGL_SAMPLES) returned error %d", eglGetError());
- throw new std::runtime_error("eglGetConfigAttrib() failed");
+ throw std::runtime_error("eglGetConfigAttrib() failed");
}
mbgl::Log::Info(mbgl::Event::OpenGL, "...Caveat: %d", caveat);
@@ -669,42 +636,16 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi
return configId;
}
-void NativeMapView::pause() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::pause");
-
- if ((display != EGL_NO_DISPLAY) && (context != EGL_NO_CONTEXT)) {
- map->pause();
- }
-}
-
-void NativeMapView::resume() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::resume");
-
- assert(display != EGL_NO_DISPLAY);
- assert(context != EGL_NO_CONTEXT);
-
- if (surface != EGL_NO_SURFACE) {
- map->resume();
- } else {
- mbgl::Log::Debug(mbgl::Event::Android, "Not resuming because we are not ready");
- }
-}
-
void NativeMapView::notifyMapChange(mbgl::MapChange change) {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::notifyMapChange()");
assert(vm != nullptr);
assert(obj != nullptr);
- JNIEnv *env = nullptr;
- bool detach = attach_jni_thread(vm, &env, "NativeMapView::notifyMapChange()");
-
env->CallVoidMethod(obj, onMapChangedId, change);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
}
-
- detach_jni_thread(vm, &env, detach);
}
void NativeMapView::enableFps(bool enable) {
@@ -738,15 +679,10 @@ void NativeMapView::updateFps() {
assert(vm != nullptr);
assert(obj != nullptr);
- JNIEnv *env = nullptr;
- bool detach = attach_jni_thread(vm, &env, "NativeMapView::updateFps()");
-
env->CallVoidMethod(obj, onFpsChangedId, fps);
if (env->ExceptionCheck()) {
env->ExceptionDescribe();
}
-
- detach_jni_thread(vm, &env, detach);
}
void NativeMapView::resizeView(int w, int h) {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 5926f781ae..40cb012b0b 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -1,5 +1,4 @@
-#ifndef MBGL_ANDROID_NATIVE_MAP_VIEW
-#define MBGL_ANDROID_NATIVE_MAP_VIEW
+#pragma once
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
@@ -24,10 +23,7 @@ public:
std::array<uint16_t, 2> getFramebufferSize() const override;
void activate() override;
void deactivate() override;
- void notify() override;
void invalidate() override;
- void beforeRender() override;
- void afterRender() override;
void notifyMapChange(mbgl::MapChange) override;
@@ -43,8 +39,7 @@ public:
void createSurface(ANativeWindow *window);
void destroySurface();
- void resume();
- void pause();
+ void render();
void enableFps(bool enable);
void updateFps();
@@ -61,9 +56,16 @@ private:
private:
JavaVM *vm = nullptr;
+ JNIEnv *env = nullptr;
jweak obj = nullptr;
ANativeWindow *window = nullptr;
+
+ EGLDisplay oldDisplay = EGL_NO_DISPLAY;
+ EGLSurface oldReadSurface = EGL_NO_SURFACE;
+ EGLSurface oldDrawSurface = EGL_NO_SURFACE;
+ EGLContext oldContext = EGL_NO_CONTEXT;
+
EGLDisplay display = EGL_NO_DISPLAY;
EGLSurface surface = EGL_NO_SURFACE;
EGLContext context = EGL_NO_CONTEXT;
@@ -88,9 +90,6 @@ private:
int availableProcessors = 0;
size_t totalMemory = 0;
- jboolean renderDetach = false;
- JNIEnv *renderEnv = nullptr;
-
// Ensure these are initialised last
std::unique_ptr<mbgl::DefaultFileSource> fileSource;
std::unique_ptr<mbgl::Map> map;
@@ -98,5 +97,3 @@ private:
};
}
}
-
-#endif
diff --git a/platform/android/src/run_loop.cpp b/platform/android/src/run_loop.cpp
new file mode 100644
index 0000000000..7a28a6139c
--- /dev/null
+++ b/platform/android/src/run_loop.cpp
@@ -0,0 +1,213 @@
+#include "run_loop_impl.hpp"
+
+#include <mbgl/util/thread_context.hpp>
+#include <mbgl/util/thread_local.hpp>
+
+#include <android/looper.h>
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <stdexcept>
+#include <vector>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#define PIPE_OUT 0
+#define PIPE_IN 1
+
+namespace {
+
+using namespace mbgl::util;
+static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>;
+
+int looperCallbackNew(int fd, int, void* data) {
+ int buffer[1];
+ while (read(fd, buffer, sizeof(buffer)) > 0) {}
+
+ auto loop = reinterpret_cast<ALooper*>(data);
+ ALooper_wake(loop);
+
+ return 1;
+}
+
+int looperCallbackDefault(int fd, int, void* data) {
+ int buffer[1];
+ while (read(fd, buffer, sizeof(buffer)) > 0) {}
+
+ auto runLoop = reinterpret_cast<RunLoop*>(data);
+ runLoop->runOnce();
+
+ return 1;
+}
+
+} // namespace
+
+namespace mbgl {
+namespace util {
+
+RunLoop::Impl::Impl(RunLoop* runLoop, RunLoop::Type type) {
+ using namespace mbgl::android;
+ detach = attach_jni_thread(theJVM, &env, "");
+
+ loop = ALooper_prepare(0);
+ assert(loop);
+
+ ALooper_acquire(loop);
+
+ if (pipe(fds)) {
+ throw std::runtime_error("Failed to create pipe.");
+ }
+
+ if (fcntl(fds[PIPE_OUT], F_SETFL, O_NONBLOCK)) {
+ throw std::runtime_error("Failed to set pipe read end non-blocking.");
+ }
+
+ int ret = 0;
+
+ switch (type) {
+ case Type::New:
+ ret = ALooper_addFd(loop, fds[PIPE_OUT], ALOOPER_POLL_CALLBACK,
+ ALOOPER_EVENT_INPUT, looperCallbackNew, loop);
+ break;
+ case Type::Default:
+ ret = ALooper_addFd(loop, fds[PIPE_OUT], ALOOPER_POLL_CALLBACK,
+ ALOOPER_EVENT_INPUT, looperCallbackDefault, runLoop);
+ break;
+ }
+
+ if (ret != 1) {
+ throw std::runtime_error("Failed to add file descriptor to Looper.");
+ }
+}
+
+RunLoop::Impl::~Impl() {
+ if (ALooper_removeFd(loop, fds[PIPE_OUT]) != 1) {
+ throw std::runtime_error("Failed to remove file descriptor from Looper.");
+ }
+
+ if (close(fds[PIPE_IN]) || close(fds[PIPE_OUT])) {
+ throw std::runtime_error("Failed to close file descriptor.");
+ }
+
+ ALooper_release(loop);
+
+ using namespace mbgl::android;
+ detach_jni_thread(theJVM, &env, detach);
+}
+
+void RunLoop::Impl::wake() {
+ if (write(fds[PIPE_IN], "\n", 1) == -1) {
+ throw std::runtime_error("Failed to write to file descriptor.");
+ }
+}
+
+void RunLoop::Impl::addRunnable(Runnable* runnable) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ if (runnable->iter == runnables.end()) {
+ auto iter = runnables.insert(runnables.end(), runnable);
+ runnable->iter = std::move(iter);
+ }
+
+ wake();
+}
+
+void RunLoop::Impl::removeRunnable(Runnable* runnable) {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ if (runnable->iter != runnables.end()) {
+ runnables.erase(runnable->iter);
+ runnable->iter = runnables.end();
+ }
+}
+
+void RunLoop::Impl::initRunnable(Runnable* runnable) {
+ runnable->iter = runnables.end();
+}
+
+Milliseconds RunLoop::Impl::processRunnables() {
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+
+ auto now = Clock::now();
+ auto nextDue = TimePoint::max();
+
+ // O(N) but in the render thread where we get tons
+ // of messages, the size of the list is usually 1~2.
+ for (auto iter = runnables.begin(); iter != runnables.end();) {
+ Runnable* runnable = *(iter++);
+
+ auto const dueTime = runnable->dueTime();
+ if (dueTime <= now) {
+ runnable->runTask();
+ } else {
+ nextDue = std::min(nextDue, dueTime);
+ }
+ }
+
+ if (runnables.empty() || nextDue == TimePoint::max()) {
+ return Milliseconds(-1);
+ } else {
+ return std::chrono::duration_cast<Milliseconds>(nextDue - now);
+ }
+}
+
+RunLoop* RunLoop::Get() {
+ return current.get();
+}
+
+RunLoop::RunLoop(Type type) : impl(std::make_unique<Impl>(this, type)) {
+ current.set(this);
+}
+
+RunLoop::~RunLoop() {
+ current.set(nullptr);
+}
+
+LOOP_HANDLE RunLoop::getLoopHandle() {
+ return current.get()->impl.get();
+}
+
+void RunLoop::push(std::shared_ptr<WorkTask> task) {
+ withMutex([&] { queue.push(std::move(task)); });
+ impl->wake();
+}
+
+void RunLoop::run() {
+ MBGL_VERIFY_THREAD(tid);
+
+ impl->running = true;
+
+ int outFd, outEvents;
+ char *outData = nullptr;
+
+ while (impl->running) {
+ process();
+ auto timeout = impl->processRunnables().count();
+ ALooper_pollAll(timeout, &outFd, &outEvents, reinterpret_cast<void**>(&outData));
+ }
+}
+
+void RunLoop::runOnce() {
+ MBGL_VERIFY_THREAD(tid);
+
+ process();
+ impl->processRunnables();
+}
+
+void RunLoop::stop() {
+ impl->running = false;
+ impl->wake();
+}
+
+void RunLoop::addWatch(int, Event, std::function<void(int, Event)>&&) {
+ throw std::runtime_error("Not implemented.");
+}
+
+void RunLoop::removeWatch(int) {
+ throw std::runtime_error("Not implemented.");
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/android/src/run_loop_impl.hpp b/platform/android/src/run_loop_impl.hpp
new file mode 100644
index 0000000000..d855728b60
--- /dev/null
+++ b/platform/android/src/run_loop_impl.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "jni.hpp"
+
+#include <mbgl/util/atomic.hpp>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/run_loop.hpp>
+
+#include <list>
+#include <memory>
+#include <mutex>
+
+struct ALooper;
+
+namespace mbgl {
+namespace util {
+
+class RunLoop::Impl {
+public:
+ class Runnable {
+ public:
+ virtual ~Runnable() = default;
+
+ virtual void runTask() = 0;
+ virtual TimePoint dueTime() const = 0;
+
+ std::list<Runnable*>::iterator iter;
+ };
+
+ Impl(RunLoop*, RunLoop::Type);
+ ~Impl();
+
+ void wake();
+
+ void addRunnable(Runnable*);
+ void removeRunnable(Runnable*);
+ void initRunnable(Runnable*);
+
+ Milliseconds processRunnables();
+
+private:
+ friend RunLoop;
+
+ int fds[2];
+
+ JNIEnv *env = nullptr;
+ bool detach = false;
+
+ ALooper* loop = nullptr;
+ util::Atomic<bool> running;
+
+ std::recursive_mutex mtx;
+ std::list<Runnable*> runnables;
+};
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/android/src/timer.cpp b/platform/android/src/timer.cpp
new file mode 100644
index 0000000000..741005df23
--- /dev/null
+++ b/platform/android/src/timer.cpp
@@ -0,0 +1,78 @@
+#include "run_loop_impl.hpp"
+
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/timer.hpp>
+
+#include <functional>
+
+namespace mbgl {
+namespace util {
+
+class Timer::Impl : public RunLoop::Impl::Runnable {
+public:
+ Impl() {
+ loop->initRunnable(this);
+ }
+
+ ~Impl() {
+ stop();
+ }
+
+ void start(Duration timeout, Duration repeat_, std::function<void ()>&& task_) {
+ stop();
+
+ repeat = repeat_;
+ task = std::move(task_);
+ due = Clock::now() + timeout;
+
+ loop->addRunnable(this);
+ }
+
+ void stop() {
+ task = nullptr;
+ loop->removeRunnable(this);
+ }
+
+ void reschedule() {
+ if (repeat != Duration::zero()) {
+ due = Clock::now() + repeat;
+ loop->addRunnable(this);
+ } else {
+ stop();
+ }
+ }
+
+ TimePoint dueTime() const override {
+ return due;
+ }
+
+ void runTask() override {
+ task();
+ reschedule();
+ }
+
+private:
+ TimePoint due;
+ Duration repeat;
+
+ RunLoop::Impl* loop = reinterpret_cast<RunLoop::Impl*>(RunLoop::getLoopHandle());
+
+ std::function<void()> task;
+};
+
+Timer::Timer()
+ : impl(std::make_unique<Impl>()) {
+}
+
+Timer::~Timer() = default;
+
+void Timer::start(Duration timeout, Duration repeat, std::function<void()>&& cb) {
+ impl->start(timeout, repeat, std::move(cb));
+}
+
+void Timer::stop() {
+ impl->stop();
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/android/tests/docs/UI_TESTS.md b/platform/android/tests/docs/UI_TESTS.md
index 35032bf5a9..4d7addea0d 100644
--- a/platform/android/tests/docs/UI_TESTS.md
+++ b/platform/android/tests/docs/UI_TESTS.md
@@ -31,15 +31,15 @@ $ ./gradlew cC -p MapboxGLAndroidSDKTestApp
Then:
* Go to your AWS Console and choose Device Farm.
* Create a new project, e.g. `MapboxGLAndroidSDKTestApp`
-* On step 1, upload the APK in `mapbox-gl-native/android/java/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-unaligned.apk`
-* On step 2, choose Instrumentation, test filter is `com.mapbox.mapboxgl.testapp.MainActivityTest` and upload the APK in `mapbox-gl-native/android/java/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest-unaligned.apk`
+* On step 1, upload the APK in `mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-unaligned.apk`
+* On step 2, choose Instrumentation, test filter is `com.mapbox.mapboxgl.testapp.MainActivityTest` and upload the APK in `mapbox-gl-native/platform/android/MapboxGLAndroidSDKTestApp/build/outputs/apk/MapboxGLAndroidSDKTestApp-debug-androidTest-unaligned.apk`
* On step 3, choose a device pool. E.g. Top Devices
* On step 4, customize your device state (if needed)
* Finally, confirm the configuration and run the tests.
On Step 2, you can also separate by commas different classes: `com.mapbox.mapboxgl.testapp.MainActivityTest,com.mapbox.mapboxgl.testapp.MainActivityScreenTest`
-If you have no tests for your app, or want to test some random user behaviour,
+If you have no tests for your app, or want to test some random user behavior,
you can just choose "Built-in: Fuzz" in step 2.
### Code coverage
@@ -59,7 +59,7 @@ You can generate JaCoCo reports from espresso tests by
- running the gradle task `createMockDebugCoverageReport` when executing tests.
## Running Espresso test automatically on AWS Device Farm
-To automatically execute Espresso tests as part of our CI build, we have created a Python [script](https://github.com/mapbox/mapbox-gl-native/blob/aws-devicelab/android/scripts/devicefarm.py).
+To automatically execute Espresso tests as part of our CI build, we have created a Python script called [`devicefarm.py`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/tests/scripts/devicefarm.py).
This script is responsible for:
- uploading an APK + test APK
diff --git a/platform/android/tests/docs/UNIT_TESTS.md b/platform/android/tests/docs/UNIT_TESTS.md
index 15850b8b12..e32a36ef78 100644
--- a/platform/android/tests/docs/UNIT_TESTS.md
+++ b/platform/android/tests/docs/UNIT_TESTS.md
@@ -1,36 +1,80 @@
# Unit tests
-Our Unit tests are based on JUnit and are located under `/src/test/java/`.
-We are using plain JUnit to test classes that aren't calling the Android API,
+**Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation.**
+
+Our Unit tests are based on JUnit and are located under `/src/test/java/`.
+We are using plain JUnit to test classes that aren't calling the Android API,
or are using Android's JUnit extensions to stub/mock Android components.
-## Running Unit tests locally
-To run Unit tests locally you switch to the Unit Tests build variant, then right click the corresponding test class or method and select "Run ...".
+## Writing unit tests
+Unit tests for an Android project are located in the `test` folder:
-You can also have a run configuration:
-* Click on Run -> Edit Configurations...
-* Click on "Junit Tests"
-* Give a name to the configuration, e.g. `JUnit tests`
-* As "Test Kind", choose "All in directory"
-* As folder, choose the following folder: `mapbox-gl-native/platforms/android/java/MapboxGLAndroidSDKTestApp/src/test/java`
-* Click OK to save the new configuration
+<img width="348" alt="screen shot 2016-03-16 at 17 24 31" src="https://cloud.githubusercontent.com/assets/2151639/13829301/9ea62418-eb9c-11e5-8ab3-9d6c6bed80a3.png">
-You can also run the tests from the command line with:
+To add a test, right click the corresponding package and select create new `Java class`. Name the class appropriately by ending it with `Test` and start adding test methods by applying the `@Test` annotation:
+
+```java
+package com.mapbox.mapboxsdk.annotations;
+
+import org.junit.Test;
+
+public class AwesomeSauceTest {
+
+ @Test
+ public void simpleTest(){
+
+ }
+
+}
```
-$ ./gradlew test --continue -p MapboxGLAndroidSDKTestApp
+
+you can add methods that are executed before and after each test:
+
+```java
+package com.mapbox.mapboxsdk.annotations;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class AwesomeSauceTest {
+
+ @Before
+ public void beforeEachTest(){
+
+ }
+
+ @Test
+ public void simpleTest(){
+
+ }
+
+ @After
+ public void afterEachTest(){
+
+ }
+
+}
```
-### Code Coverage
-Showing code coverage directly in the IDE.
-- Switch your Build Variant to the Unit Tests artifact
-- Right click a unit test and select `Run test with coverage`
-- Select `Add to active suites` //this will create a run configuration
-- Edit the run configuration to include/exclude packages in the `Code coverage`-tab.
+## Running unit tests
+You can run a test locally by right clicking and selecting run:
+
+<img width="322" alt="screen shot 2016-03-16 at 17 46 09" src="https://cloud.githubusercontent.com/assets/2151639/13829762/0877af18-eb9f-11e5-87df-6dfb3be64beb.png">
+
+If you like, you can also run with test coverage enabled. This will show you the following dialog:
+
+<img width="465" alt="screen shot 2016-03-16 at 17 58 34" src="https://cloud.githubusercontent.com/assets/2151639/13830064/d097aeca-eba0-11e5-94bd-e38fd1079937.png">
+
+You can also run the tests from the command line with:
+```
+$ ./gradlew test --continue -p MapboxGLAndroidSDKTestApp
+```
## Running Unit tests on CI
-The Unit tests are executed as part of the build process on our CI and are
-automatically run for each new commit pushed to this repo. If a Unit tests
+The Unit tests are executed as part of the build process on our CI and are
+automatically run for each new commit pushed to this repo. If a Unit tests
fails, this will fail and stop the build.
You can find this gradle command in our [buildscript](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/bitrise.yml#L48):
@@ -38,3 +82,11 @@ You can find this gradle command in our [buildscript](https://github.com/mapbox/
```
$ ./gradlew testReleaseUnitTest --continue
```
+
+
+## Code Coverage
+Showing code coverage directly in the IDE.
+- Switch your Build Variant to the Unit Tests artifact
+- Right click a unit test and select `Run test with coverage`
+- Select `Add to active suites` //this will create a run configuration
+- Edit the run configuration to include/exclude packages in the `Code coverage`-tab.