summaryrefslogtreecommitdiff
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/CHANGELOG.md115
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java87
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java88
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java234
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java66
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java96
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MarkerContainer.java9
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java83
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotationContainer.java38
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotations.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java18
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java79
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/ColorUtils.java48
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-bg/strings.xml15
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-hu/strings.xml13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AnnotationManagerTest.java11
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcherTest.java87
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/gradle-spoon.gradle8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java31
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java5
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java183
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java211
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java141
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animator.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_animator.xml20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbols.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml5
-rw-r--r--platform/android/build.gradle2
-rw-r--r--platform/android/config.cmake2
-rw-r--r--platform/android/dependencies.gradle3
-rw-r--r--platform/android/scripts/exclude-activity-gen.json31
-rw-r--r--platform/android/scripts/generate-test-code.js23
-rw-r--r--platform/android/src/android_renderer_frontend.cpp5
-rw-r--r--platform/android/src/android_renderer_frontend.hpp1
-rw-r--r--platform/android/src/file_source.cpp14
-rw-r--r--platform/android/src/file_source.hpp4
-rwxr-xr-xplatform/android/src/jni.cpp1
-rw-r--r--platform/android/src/map/image.cpp44
-rw-r--r--platform/android/src/map/image.hpp26
-rwxr-xr-xplatform/android/src/native_map_view.cpp35
-rwxr-xr-xplatform/android/src/native_map_view.hpp5
60 files changed, 1650 insertions, 458 deletions
diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md
index ff03df2236..b3b41ecbd1 100644
--- a/platform/android/CHANGELOG.md
+++ b/platform/android/CHANGELOG.md
@@ -4,11 +4,110 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
## 5.2.0 - TBA
-* Add support for ImageSource [#9110](https://github.com/mapbox/mapbox-gl-native/pull/9110)
-* Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835))
-* Added `MapboxMap.getCameraForGeometry()` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107))
+## 5.2.0-beta.4 - November 3, 2017
+
+- Revert adding mapbox-android-core dependency (#10354) [#10380](https://github.com/mapbox/mapbox-gl-native/pull/10380)
+- Asynchronous TextureView [#10370](https://github.com/mapbox/mapbox-gl-native/pull/10370)
+- Workaround OkHttp bug on Android O [10366](https://github.com/mapbox/mapbox-gl-native/pull/10366)
+- Revisit logo resize [10553](https://github.com/mapbox/mapbox-gl-native/pull/10353)
+- Logo resize for MapSnapshotter [#10312](https://github.com/mapbox/mapbox-gl-native/pull/10312)
+- Make location provider optional [#10354](https://github.com/mapbox/mapbox-gl-native/pull/10354)
+- Check for positive animation value [#10348](https://github.com/mapbox/mapbox-gl-native/pull/10348)
+- Fix IAE of ease/animate [#10338](https://github.com/mapbox/mapbox-gl-native/pull/10338)
+- Run full test suite on CI [#10333](https://github.com/mapbox/mapbox-gl-native/pull/10333)
+- Make sure camera position gets updated in onFinish() callback after camera.move [#10324](https://github.com/mapbox/mapbox-gl-native/pull/10324)
+- throw IAE in animate() and easeCamera() when duration <= 0 [#10321](https://github.com/mapbox/mapbox-gl-native/pull/10321)
+- Don't save state if map hasn't been initialised [#10320](https://github.com/mapbox/mapbox-gl-native/pull/10320)
+- Make map snapshot optional [#10310](https://github.com/mapbox/mapbox-gl-native/pull/10310)
+- Synchronise locationlastions with Transifex [#10309](https://github.com/mapbox/mapbox-gl-native/pull/10309)
+- MapboxMap#addImages [#10281](https://github.com/mapbox/mapbox-gl-native/pull/10281)
+- Move shape annotation click handling to core [#10267](https://github.com/mapbox/mapbox-gl-native/pull/10267)
+- Map snapshotter additions [#10163](https://github.com/mapbox/mapbox-gl-native/pull/10163)
+- Add velocity to gestures / port animations to SDK animators [#10202](https://github.com/mapbox/mapbox-gl-native/pull/10202)
+- Don't save state if map hasn't been initialised [#10320](https://github.com/mapbox/mapbox-gl-native/pull/10320)
+- android.hardware.location.gps feature should not be required [#10347](https://github.com/mapbox/mapbox-gl-native/pull/10347)
+
+## 5.2.0-beta.3 - October 26, 2017
+
+- Reorganize dependencies [#10268](https://github.com/mapbox/mapbox-gl-native/pull/10268)
+- Blacklist VAO usage on adreno 3xx [#10291](https://github.com/mapbox/mapbox-gl-native/pull/10291)
+- On stop null check [#10259](https://github.com/mapbox/mapbox-gl-native/pull/10259)
+
+## 5.2.0-beta.2 - October 19, 2017
+
+- Wire up MapZoomButtonController with camera change events [#10221](https://github.com/mapbox/mapbox-gl-native/pull/10221)
+- Execute callbacks only when not idle [#10220](https://github.com/mapbox/mapbox-gl-native/pull/10220)
+- Cleanup unused gradle plugins [#10211](https://github.com/mapbox/mapbox-gl-native/pull/10211)
+- add FileSource pause/resume [#9977](https://github.com/mapbox/mapbox-gl-native/pull/9977)
+- add make target for ndk-stack [#10185](https://github.com/mapbox/mapbox-gl-native/pull/10185)
+- Add interpolator examples [#10067](https://github.com/mapbox/mapbox-gl-native/pull/10067)
+- Add an UnsatisfiedLinkError safeguard [#10180](https://github.com/mapbox/mapbox-gl-native/pull/10180)
+- Hold off handling hover events untill map has been created [#10142](https://github.com/mapbox/mapbox-gl-native/pull/10142)
+- Added `MapboxMap.getCameraForGeometry()` to get a camera with zoom level and center coordinate computed to fit a shape [#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)
+- Fine tune gesture zoom & rotation [#10134](https://github.com/mapbox/mapbox-gl-native/pull/10134)
+
+## 5.2.0-beta.1 - October 6, 2017
+
+- Allow multiple listeners for camera events, deprecate old API [#10141](https://github.com/mapbox/mapbox-gl-native/pull/10141)
+- Update symbol layer example with location [#10092](https://github.com/mapbox/mapbox-gl-native/pull/10092)
+- Make OfflineTilePyramidRegionDefinition parceable [#10080](https://github.com/mapbox/mapbox-gl-native/pull/10080)
+- Fix 5.2.0-SNAPSHOT CI build failing [#10079](https://github.com/mapbox/mapbox-gl-native/pull/10079)
+- Deprecate MarkerView [#9782](https://github.com/mapbox/mapbox-gl-native/pull/9782)
+- Hide overlain views on initalisation [#10068](https://github.com/mapbox/mapbox-gl-native/pull/10068)
+- API for platform side animations [#10001](https://github.com/mapbox/mapbox-gl-native/pull/10001)
+- Android asynchronous rendering [#9576](https://github.com/mapbox/mapbox-gl-native/pull/9576)
+- Set error handler when starting snapshotter [#10035](https://github.com/mapbox/mapbox-gl-native/pull/10035)
+- Hook camera events into compass [#10019](https://github.com/mapbox/mapbox-gl-native/pull/10019)
+- Testapp cleanup [#10006](https://github.com/mapbox/mapbox-gl-native/pull/10006)
+- Update zoom function example with selected state [#9987](https://github.com/mapbox/mapbox-gl-native/pull/9987)
+- Add style inspection to debug activity [#9773](https://github.com/mapbox/mapbox-gl-native/pull/9773)
+- Bump external dependencies [#9972](https://github.com/mapbox/mapbox-gl-native/pull/9972)
+- Don't recycle bitmap for icon reuse. [#9966](https://github.com/mapbox/mapbox-gl-native/pull/9966)
+- Android snapshotter [#9748](https://github.com/mapbox/mapbox-gl-native/pull/9748)
+- Revert #9764 [#9851](https://github.com/mapbox/mapbox-gl-native/pull/9851)
+- Update docs replacing Bitrise mentions with CircleCI [#9515](https://github.com/mapbox/mapbox-gl-native/pull/9515)
+- Style image accessor [#9763](https://github.com/mapbox/mapbox-gl-native/pull/9763)
+- Update readme with checkstyle and ndk-stack [#9788](https://github.com/mapbox/mapbox-gl-native/pull/9788)
+- make android-check [#9787](https://github.com/mapbox/mapbox-gl-native/pull/9787)
+- Deprecate MyLocationView in favor of LocationLayer plugin [#9771](https://github.com/mapbox/mapbox-gl-native/pull/9771)
+- Increase firebase timeout for CI testing [#9774](https://github.com/mapbox/mapbox-gl-native/pull/9774)
+- Restore max zoom to 25.5 [#9765](https://github.com/mapbox/mapbox-gl-native/pull/9765)
+- Update example of camera zoom function on a symbol layer. [#9743](https://github.com/mapbox/mapbox-gl-native/pull/9743)
+- Optimise icon management [#9643](https://github.com/mapbox/mapbox-gl-native/pull/9643)
+- Expose setStyleJson and getStyleJson [#9714](https://github.com/mapbox/mapbox-gl-native/pull/9714)
+- update LatLngBounds activity with BottomSheet interaction [#9736](https://github.com/mapbox/mapbox-gl-native/pull/9736)
+- post updating InfoWindow update for InfoWindowAdapter [#9716](https://github.com/mapbox/mapbox-gl-native/pull/9716)
+- Annotate MapboxMap class with UiThread [#9712](https://github.com/mapbox/mapbox-gl-native/pull/9712)
+- Move ZoomButtonController creation to view initalisation [#9587](https://github.com/mapbox/mapbox-gl-native/pull/9587)
+- Solve lint issues, reduce baseline [#9627](https://github.com/mapbox/mapbox-gl-native/pull/9627)
+- Remove wear module from project [#9618](https://github.com/mapbox/mapbox-gl-native/pull/9618)
+- Add zMediaOverlay configuration + bottom sheet integration [#9592](https://github.com/mapbox/mapbox-gl-native/pull/9592)
+- Forward getMapAsync to map for fragment [#9621](https://github.com/mapbox/mapbox-gl-native/pull/9621)
+- Make target for dumping system gfx information [#9616](https://github.com/mapbox/mapbox-gl-native/pull/9616)
+- Make target documentation [#9617](https://github.com/mapbox/mapbox-gl-native/pull/9617)
+- onGlobalLayout hook for map creation [#9607](https://github.com/mapbox/mapbox-gl-native/pull/9607)
+- Custom viewpager for horizontal swiping [#9601](https://github.com/mapbox/mapbox-gl-native/pull/9601)
+- Disable program caching on Adreno 3xx, 4xx, and 5xx GPUs due to known bugs [#9574](https://github.com/mapbox/mapbox-gl-native/pull/9574)
+- Avoid creating InfoWindow iterator if no InfoWindows are shown [#9477](https://github.com/mapbox/mapbox-gl-native/pull/9477)
+- Rewire map initialisation [#9462](https://github.com/mapbox/mapbox-gl-native/pull/9462)
+- Trying to update non-existent polyline fix [#9544](https://github.com/mapbox/mapbox-gl-native/pull/9544)
+- Location accuracy threshold [#9472](https://github.com/mapbox/mapbox-gl-native/pull/9472)
+- Rewire gesture handling and telemetry event push [#9494](https://github.com/mapbox/mapbox-gl-native/pull/9494)
+- run style instrumentation tests on CI [#9353](https://github.com/mapbox/mapbox-gl-native/pull/9353)
+- Fix javadoc comment for public setOfflineMapboxTileCountLimit method [#9454](https://github.com/mapbox/mapbox-gl-native/pull/9454)
+- add Map change & visibility test activities [#9425](https://github.com/mapbox/mapbox-gl-native/pull/9425)
+- build release package once during ci build [#9351](https://github.com/mapbox/mapbox-gl-native/pull/9351)
+- Add support for ImageSource [#9110](https://github.com/mapbox/mapbox-gl-native/pull/9110)
+- Increased the default maximum zoom level from 20 to 22. [#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)
+
+## 5.1.5 - October 31, 2017
+
+* Remove obsolete terminate context/display calls [#10162](https://github.com/mapbox/mapbox-gl-native/pull/10162)
+* Determine need for clip ID based on actual layers/tiles [#10216](https://github.com/mapbox/mapbox-gl-native/pull/10216)
+* Correctly alter sprite URLs [#10217](https://github.com/mapbox/mapbox-gl-native/pull/10217)
+* Russian and Ukrainian localizations [#9945](https://github.com/mapbox/mapbox-gl-native/pull/9945)
-### 5.1.4 - September 25, 2017
+## 5.1.4 - September 25, 2017
* Update translations [#10033](https://github.com/mapbox/mapbox-gl-native/pull/10033) & [#9945](https://github.com/mapbox/mapbox-gl-native/pull/9945)
* Continue rendering tiles despite erros [#10012](https://github.com/mapbox/mapbox-gl-native/pull/10012)
@@ -101,7 +200,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to
* Infinite location animation updates [#9194](https://github.com/mapbox/mapbox-gl-native/pull/9194)
* Invoke callback with valid fling gestures [#9192](https://github.com/mapbox/mapbox-gl-native/pull/9192)
* Keep location tracking after screen rotation [#9187](https://github.com/mapbox/mapbox-gl-native/pull/9187)
-* Update components with camera values when animating [#9174](https://github.com/mapbox/mapbox-gl-native/pull/9174)
+* Update components with camera values when animating [#9174](https://github.com/mapbox/mapbox-gl-native/pull/9174)
* Validate if gestures should execute [#9173](https://github.com/mapbox/mapbox-gl-native/pull/9173)
* Custom location source and LOST integration [#9142](https://github.com/mapbox/mapbox-gl-native/pull/9142)
@@ -503,12 +602,6 @@ Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major
- Satellite Streets Style ([#2739](https://github.com/mapbox/mapbox-gl-native/issues/2739))
- **RESOLVED** Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
-
## 2.1.0 - October 21, 2015
- Initial Android release.
-
-Known issues:
-
-- Black Screen On Ice Cream Sandwich and Jelly Bean devices ([#2802](https://github.com/mapbox/mapbox-gl-native/issues/2802))
- - Resolved in 2.2.0
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 688c632326..f3e9433a0b 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -2,8 +2,7 @@ apply plugin: 'com.android.library'
dependencies {
compile rootProject.ext.dep.supportAnnotations
- compile rootProject.ext.dep.supportV4
- compile rootProject.ext.dep.supportDesign
+ compile rootProject.ext.dep.supportFragmentV4
compile rootProject.ext.dep.timber
compile rootProject.ext.dep.okhttp3
provided(rootProject.ext.dep.lost) {
@@ -21,6 +20,7 @@ dependencies {
// Mapbox Android Services (Telemetry support)
compile(rootProject.ext.dep.mapboxAndroidTelemetry) {
transitive = true
+ exclude group: 'com.android.support'
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
index 231e36e092..b61035a008 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature android:name="android.hardware.wifi" android:required="false" /> <!-- Implied by ACCESS_WIFI_STATE. -->
+ <uses-feature android:name="android.hardware.location.gps" android:required="false"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
index 8a75176ccd..a024f0ab70 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/LibraryLoader.java
@@ -1,5 +1,7 @@
package com.mapbox.mapboxsdk;
+import timber.log.Timber;
+
/**
* Centralises the knowledge about "mapbox-gl" library loading.
*/
@@ -9,7 +11,10 @@ public class LibraryLoader {
* Loads "libmapbox-gl.so" native shared library.
*/
public static void load() {
- System.loadLibrary("mapbox-gl");
+ try {
+ System.loadLibrary("mapbox-gl");
+ } catch (UnsatisfiedLinkError error) {
+ Timber.e(error, "Failed to load native shared library.");
+ }
}
-
}
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 97a9ea94ee..fc448ccf7b 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
@@ -80,12 +80,12 @@ public class MapboxConstants {
/**
* The currently used minimun scale factor to clamp to when a quick zoom gesture occurs
*/
- public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.65f;
+ public static final float MINIMUM_SCALE_FACTOR_CLAMP = 0.00f;
/**
* The currently used maximum scale factor to clamp to when a quick zoom gesture occurs
*/
- public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 1.35f;
+ public static final float MAXIMUM_SCALE_FACTOR_CLAMP = 0.45f;
/**
* Fragment Argument Key for MapboxMapOptions
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 e2626a026b..32aa250997 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
@@ -85,7 +85,14 @@ class HTTPRequest implements Callback {
}
mRequest = builder.build();
mCall = mClient.newCall(mRequest);
- mCall.enqueue(this);
+
+ // TODO remove code block for workaround in #10303
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1) {
+ mCall.enqueue(this);
+ } else {
+ // Calling execute instead of enqueue is a workaround for #10303
+ onResponse(mCall, mCall.execute());
+ }
} catch (Exception exception) {
onFailure(exception);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
index c09c926eb5..9f256c341b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AnnotationManager.java
@@ -21,7 +21,6 @@ import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
-import com.mapbox.services.commons.geojson.Feature;
import java.util.ArrayList;
import java.util.List;
@@ -41,7 +40,6 @@ import timber.log.Timber;
*/
class AnnotationManager {
- private static final String LAYER_ID_SHAPE_ANNOTATIONS = "com.mapbox.annotations.shape.";
private static final long NO_ANNOTATION_ID = -1;
private final MapView mapView;
@@ -50,7 +48,6 @@ class AnnotationManager {
private final MarkerViewManager markerViewManager;
private final LongSparseArray<Annotation> annotationsArray;
private final List<Marker> selectedMarkers = new ArrayList<>();
- private final List<String> shapeAnnotationIds = new ArrayList<>();
private MapboxMap mapboxMap;
private MapboxMap.OnMarkerClickListener onMarkerClickListener;
@@ -58,13 +55,14 @@ class AnnotationManager {
private MapboxMap.OnPolylineClickListener onPolylineClickListener;
private Annotations annotations;
+ private ShapeAnnotations shapeAnnotations;
private Markers markers;
private Polygons polygons;
private Polylines polylines;
AnnotationManager(NativeMapView view, MapView mapView, LongSparseArray<Annotation> annotationsArray,
MarkerViewManager markerViewManager, IconManager iconManager, Annotations annotations,
- Markers markers, Polygons polygons, Polylines polylines) {
+ Markers markers, Polygons polygons, Polylines polylines, ShapeAnnotations shapeAnnotations) {
this.mapView = mapView;
this.annotationsArray = annotationsArray;
this.markerViewManager = markerViewManager;
@@ -73,6 +71,7 @@ class AnnotationManager {
this.markers = markers;
this.polygons = polygons;
this.polylines = polylines;
+ this.shapeAnnotations = shapeAnnotations;
if (view != null) {
// null checking needed for unit tests
view.addOnMapChangedListener(markerViewManager);
@@ -122,9 +121,6 @@ class AnnotationManager {
// do icon cleanup
iconManager.iconCleanup(marker.getIcon());
}
- } else {
- // instanceOf Polygon/Polyline
- shapeAnnotationIds.remove(annotation.getId());
}
annotations.removeBy(annotation);
}
@@ -143,9 +139,6 @@ class AnnotationManager {
} else {
iconManager.iconCleanup(marker.getIcon());
}
- } else {
- // instanceOf Polygon/Polyline
- shapeAnnotationIds.remove(annotation.getId());
}
}
annotations.removeBy(annotationList);
@@ -167,9 +160,6 @@ class AnnotationManager {
} else {
iconManager.iconCleanup(marker.getIcon());
}
- } else {
- // instanceOf Polygon/Polyline
- shapeAnnotationIds.remove(annotation.getId());
}
}
annotations.removeAll();
@@ -227,17 +217,11 @@ class AnnotationManager {
//
Polygon addPolygon(@NonNull PolygonOptions polygonOptions, @NonNull MapboxMap mapboxMap) {
- Polygon polygon = polygons.addBy(polygonOptions, mapboxMap);
- shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polygon.getId());
- return polygon;
+ return polygons.addBy(polygonOptions, mapboxMap);
}
List<Polygon> addPolygons(@NonNull List<PolygonOptions> polygonOptionsList, @NonNull MapboxMap mapboxMap) {
- List<Polygon> polygonList = polygons.addBy(polygonOptionsList, mapboxMap);
- for (Polygon polygon : polygonList) {
- shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polygon.getId());
- }
- return polygonList;
+ return polygons.addBy(polygonOptionsList, mapboxMap);
}
void updatePolygon(Polygon polygon) {
@@ -257,17 +241,11 @@ class AnnotationManager {
//
Polyline addPolyline(@NonNull PolylineOptions polylineOptions, @NonNull MapboxMap mapboxMap) {
- Polyline polyline = polylines.addBy(polylineOptions, mapboxMap);
- shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polyline.getId());
- return polyline;
+ return polylines.addBy(polylineOptions, mapboxMap);
}
List<Polyline> addPolylines(@NonNull List<PolylineOptions> polylineOptionsList, @NonNull MapboxMap mapboxMap) {
- List<Polyline> polylineList = polylines.addBy(polylineOptionsList, mapboxMap);
- for (Polyline polyline : polylineList) {
- shapeAnnotationIds.add(LAYER_ID_SHAPE_ANNOTATIONS + polyline.getId());
- }
- return polylineList;
+ return polylines.addBy(polylineOptionsList, mapboxMap);
}
void updatePolyline(Polyline polyline) {
@@ -397,11 +375,11 @@ class AnnotationManager {
//
boolean onTap(PointF tapPoint) {
- if (!shapeAnnotationIds.isEmpty()) {
- ShapeAnnotationHit shapeAnnotationHit = getShapeAnnotationHitFromTap(tapPoint);
- long shapeAnnotationId = new ShapeAnnotationHitResolver(mapboxMap).execute(shapeAnnotationHit);
- if (shapeAnnotationId != NO_ANNOTATION_ID) {
- handleClickForShapeAnnotation(shapeAnnotationId);
+ ShapeAnnotationHit shapeAnnotationHit = getShapeAnnotationHitFromTap(tapPoint);
+ Annotation annotation = new ShapeAnnotationHitResolver(shapeAnnotations).execute(shapeAnnotationHit);
+ if (annotation != null) {
+ if (handleClickForShapeAnnotation(annotation)) {
+ return true;
}
}
@@ -418,16 +396,18 @@ class AnnotationManager {
tapPoint.x + touchTargetSide,
tapPoint.y + touchTargetSide
);
- return new ShapeAnnotationHit(tapRect, shapeAnnotationIds.toArray(new String[shapeAnnotationIds.size()]));
+ return new ShapeAnnotationHit(tapRect);
}
- private void handleClickForShapeAnnotation(long shapeAnnotationId) {
- Annotation annotation = getAnnotation(shapeAnnotationId);
+ private boolean handleClickForShapeAnnotation(Annotation annotation) {
if (annotation instanceof Polygon && onPolygonClickListener != null) {
onPolygonClickListener.onPolygonClick((Polygon) annotation);
+ return true;
} else if (annotation instanceof Polyline && onPolylineClickListener != null) {
onPolylineClickListener.onPolylineClick((Polyline) annotation);
+ return true;
}
+ return false;
}
private MarkerHit getMarkerHitFromTouchArea(PointF tapPoint) {
@@ -470,28 +450,19 @@ class AnnotationManager {
private static class ShapeAnnotationHitResolver {
- private MapboxMap mapboxMap;
-
- ShapeAnnotationHitResolver(MapboxMap mapboxMap) {
- this.mapboxMap = mapboxMap;
- }
+ private ShapeAnnotations shapeAnnotations;
- public long execute(ShapeAnnotationHit shapeHit) {
- long foundAnnotationId = NO_ANNOTATION_ID;
- List<Feature> features = mapboxMap.queryRenderedFeatures(shapeHit.tapPoint, shapeHit.layerIds);
- if (!features.isEmpty()) {
- foundAnnotationId = getIdFromFeature(features.get(0));
- }
- return foundAnnotationId;
+ ShapeAnnotationHitResolver(ShapeAnnotations shapeAnnotations) {
+ this.shapeAnnotations = shapeAnnotations;
}
- private long getIdFromFeature(Feature feature) {
- try {
- return Long.valueOf(feature.getId());
- } catch (NumberFormatException exception) {
- Timber.e(exception, "Couldn't parse feature id to a long, with id: %s", feature.getId());
- return NO_ANNOTATION_ID;
+ public Annotation execute(ShapeAnnotationHit shapeHit) {
+ Annotation foundAnnotation = null;
+ List<Annotation> annotations = shapeAnnotations.obtainAllIn(shapeHit.tapPoint);
+ if (annotations.size() > 0) {
+ foundAnnotation = annotations.get(0);
}
+ return foundAnnotation;
}
}
@@ -567,11 +538,9 @@ class AnnotationManager {
private static class ShapeAnnotationHit {
private final RectF tapPoint;
- private final String[] layerIds;
- ShapeAnnotationHit(RectF tapRect, String[] layerIds) {
- this.tapPoint = tapRect;
- this.layerIds = layerIds;
+ ShapeAnnotationHit(RectF tapPoint) {
+ this.tapPoint = tapPoint;
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
index 5113a0cc73..9ccff387f5 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
@@ -1,12 +1,12 @@
package com.mapbox.mapboxsdk.maps;
+import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
-import android.support.v7.app.AlertDialog;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
@@ -56,7 +56,7 @@ class AttributionDialogManager implements View.OnClickListener, DialogInterface.
private void showAttributionDialog() {
attributionKeys = attributionMap.keySet().toArray(new String[attributionMap.size()]);
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.mapbox_attributionsDialogTitle);
builder.setAdapter(new ArrayAdapter<>(context, R.layout.mapbox_attribution_list_item, attributionKeys), this);
builder.show();
@@ -77,7 +77,7 @@ class AttributionDialogManager implements View.OnClickListener, DialogInterface.
}
private void showTelemetryDialog() {
- AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.mapbox_AlertDialogStyle);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.mapbox_attributionTelemetryTitle);
builder.setMessage(R.string.mapbox_attributionTelemetryMessage);
builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
index 6f7d7c0080..cf780dcc3f 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcher.java
@@ -1,5 +1,10 @@
package com.mapbox.mapboxsdk.maps;
+import android.support.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraIdleListener;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveCanceledListener;
import static com.mapbox.mapboxsdk.maps.MapboxMap.OnCameraMoveListener;
@@ -10,23 +15,32 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
private boolean idle = true;
+ private final List<OnCameraMoveStartedListener> onCameraMoveStartedListenerList = new ArrayList<>();
+ private final List<OnCameraMoveCanceledListener> onCameraMoveCanceledListenerList = new ArrayList<>();
+ private final List<OnCameraMoveListener> onCameraMoveListenerList = new ArrayList<>();
+ private final List<OnCameraIdleListener> onCameraIdleListenerList = new ArrayList<>();
+
private OnCameraMoveStartedListener onCameraMoveStartedListener;
private OnCameraMoveCanceledListener onCameraMoveCanceledListener;
private OnCameraMoveListener onCameraMoveListener;
private OnCameraIdleListener onCameraIdleListener;
+ @Deprecated
void setOnCameraMoveStartedListener(OnCameraMoveStartedListener onCameraMoveStartedListener) {
this.onCameraMoveStartedListener = onCameraMoveStartedListener;
}
+ @Deprecated
void setOnCameraMoveCanceledListener(OnCameraMoveCanceledListener onCameraMoveCanceledListener) {
this.onCameraMoveCanceledListener = onCameraMoveCanceledListener;
}
+ @Deprecated
void setOnCameraMoveListener(OnCameraMoveListener onCameraMoveListener) {
this.onCameraMoveListener = onCameraMoveListener;
}
+ @Deprecated
void setOnCameraIdleListener(OnCameraIdleListener onCameraIdleListener) {
this.onCameraIdleListener = onCameraIdleListener;
}
@@ -36,34 +50,106 @@ class CameraChangeDispatcher implements MapboxMap.OnCameraMoveStartedListener, M
if (!idle) {
return;
}
-
idle = false;
+
+ // deprecated API
if (onCameraMoveStartedListener != null) {
onCameraMoveStartedListener.onCameraMoveStarted(reason);
}
+
+ // new API
+ if (!onCameraMoveStartedListenerList.isEmpty()) {
+ for (OnCameraMoveStartedListener cameraMoveStartedListener : onCameraMoveStartedListenerList) {
+ cameraMoveStartedListener.onCameraMoveStarted(reason);
+ }
+ }
}
@Override
public void onCameraMove() {
+ // deprecated API
if (onCameraMoveListener != null && !idle) {
onCameraMoveListener.onCameraMove();
}
+
+ // new API
+ if (!onCameraMoveListenerList.isEmpty() && !idle) {
+ for (OnCameraMoveListener cameraMoveListener : onCameraMoveListenerList) {
+ cameraMoveListener.onCameraMove();
+ }
+ }
}
@Override
public void onCameraMoveCanceled() {
+ // deprecated API
if (onCameraMoveCanceledListener != null && !idle) {
onCameraMoveCanceledListener.onCameraMoveCanceled();
}
+
+ // new API
+ if (!onCameraMoveCanceledListenerList.isEmpty() && !idle) {
+ for (OnCameraMoveCanceledListener cameraMoveCanceledListener : onCameraMoveCanceledListenerList) {
+ cameraMoveCanceledListener.onCameraMoveCanceled();
+ }
+ }
}
@Override
public void onCameraIdle() {
if (!idle) {
idle = true;
+ // deprecated API
if (onCameraIdleListener != null) {
onCameraIdleListener.onCameraIdle();
}
+
+ // new API
+ if (!onCameraIdleListenerList.isEmpty()) {
+ for (OnCameraIdleListener cameraIdleListener : onCameraIdleListenerList) {
+ cameraIdleListener.onCameraIdle();
+ }
+ }
+ }
+ }
+
+ void addOnCameraIdleListener(@NonNull OnCameraIdleListener listener) {
+ onCameraIdleListenerList.add(listener);
+ }
+
+ void removeOnCameraIdleListener(@NonNull OnCameraIdleListener listener) {
+ if (onCameraIdleListenerList.contains(listener)) {
+ onCameraIdleListenerList.remove(listener);
+ }
+ }
+
+ void addOnCameraMoveCancelListener(OnCameraMoveCanceledListener listener) {
+ onCameraMoveCanceledListenerList.add(listener);
+ }
+
+ void removeOnCameraMoveCancelListener(OnCameraMoveCanceledListener listener) {
+ if (onCameraMoveCanceledListenerList.contains(listener)) {
+ onCameraMoveCanceledListenerList.remove(listener);
+ }
+ }
+
+ void addOnCameraMoveStartedListener(OnCameraMoveStartedListener listener) {
+ onCameraMoveStartedListenerList.add(listener);
+ }
+
+ void removeOnCameraMoveStartedListener(OnCameraMoveStartedListener listener) {
+ if (onCameraMoveStartedListenerList.contains(listener)) {
+ onCameraMoveStartedListenerList.remove(listener);
+ }
+ }
+
+ void addOnCameraMoveListener(OnCameraMoveListener listener) {
+ onCameraMoveListenerList.add(listener);
+ }
+
+ void removeOnCameraMoveListener(OnCameraMoveListener listener) {
+ if (onCameraMoveListenerList.contains(listener)) {
+ onCameraMoveListenerList.remove(listener);
}
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
index b1d6df2103..80ffa973e7 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/IconManager.java
@@ -143,11 +143,14 @@ class IconManager {
}
void iconCleanup(Icon icon) {
- int refCounter = iconMap.get(icon) - 1;
- if (refCounter == 0) {
- remove(icon);
- } else {
- updateIconRefCounter(icon, refCounter);
+ Integer refCounter = iconMap.get(icon);
+ if (refCounter != null) {
+ refCounter--;
+ if (refCounter == 0) {
+ remove(icon);
+ } else {
+ updateIconRefCounter(icon, refCounter);
+ }
}
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
new file mode 100644
index 0000000000..b2f6cef3b0
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Image.java
@@ -0,0 +1,17 @@
+package com.mapbox.mapboxsdk.maps;
+
+class Image {
+ private final byte[] buffer;
+ private final float pixelRatio;
+ private final String name;
+ private final int width;
+ private final int height;
+
+ public Image(byte[] buffer, float pixelRatio, String name, int width, int height) {
+ this.buffer = buffer;
+ this.pixelRatio = pixelRatio;
+ this.name = name;
+ this.width = width;
+ this.height = height;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
index 2394e52193..4120e164a4 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java
@@ -1,14 +1,19 @@
package com.mapbox.mapboxsdk.maps;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.PointF;
import android.location.Location;
import android.support.annotation.Nullable;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ScaleGestureDetectorCompat;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
+import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import com.almeros.android.multitouch.gesturedetectors.RotateGestureDetector;
@@ -57,8 +62,14 @@ final class MapGestureDetector {
private boolean scaleGestureOccurred;
private boolean recentScaleGestureOccurred;
+ private boolean scaleAnimating;
private long scaleBeginTime;
+ private VelocityTracker velocityTracker;
+ private boolean wasZoomingIn;
+ private boolean wasClockwiseRotating;
+ private boolean rotateGestureOccurred;
+
MapGestureDetector(Context context, Transform transform, Projection projection, UiSettings uiSettings,
TrackingSettings trackingSettings, AnnotationManager annotationManager,
CameraChangeDispatcher cameraChangeDispatcher) {
@@ -153,6 +164,12 @@ final class MapGestureDetector {
// Handle two finger tap
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ if (velocityTracker == null) {
+ velocityTracker = VelocityTracker.obtain();
+ } else {
+ velocityTracker.clear();
+ }
+ velocityTracker.addMovement(event);
// First pointer down, reset scaleGestureOccurred, used to avoid triggering a fling after a scale gesture #7666
recentScaleGestureOccurred = false;
transform.setGestureInProgress(true);
@@ -203,11 +220,23 @@ final class MapGestureDetector {
twoTap = false;
transform.setGestureInProgress(false);
+ if (velocityTracker != null) {
+ velocityTracker.recycle();
+ }
+ velocityTracker = null;
break;
case MotionEvent.ACTION_CANCEL:
twoTap = false;
transform.setGestureInProgress(false);
+ if (velocityTracker != null) {
+ velocityTracker.recycle();
+ }
+ velocityTracker = null;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ velocityTracker.addMovement(event);
+ velocityTracker.computeCurrentVelocity(1000);
break;
}
@@ -430,7 +459,11 @@ final class MapGestureDetector {
*/
private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ private static final int ANIMATION_TIME_MULTIPLIER = 77;
+ private static final double ZOOM_DISTANCE_DIVIDER = 5;
+
private float scaleFactor = 1.0f;
+ private PointF scalePointBegin;
// Called when two fingers first touch the screen
@Override
@@ -440,6 +473,7 @@ final class MapGestureDetector {
}
recentScaleGestureOccurred = true;
+ scalePointBegin = new PointF(detector.getFocusX(), detector.getFocusY());
scaleBeginTime = detector.getEventTime();
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
getLocationFromGesture(detector.getFocusX(), detector.getFocusY()),
@@ -447,15 +481,6 @@ final class MapGestureDetector {
return true;
}
- // Called when fingers leave screen
- @Override
- public void onScaleEnd(ScaleGestureDetector detector) {
- scaleGestureOccurred = false;
- scaleBeginTime = 0;
- scaleFactor = 1.0f;
- cameraChangeDispatcher.onCameraIdle();
- }
-
// Called each time a finger moves
// Called for pinch zooms and quickzooms/quickscales
@Override
@@ -464,6 +489,7 @@ final class MapGestureDetector {
return super.onScale(detector);
}
+ wasZoomingIn = (Math.log(detector.getScaleFactor()) / Math.log(Math.PI / 2)) >= 0;
if (tiltGestureOccurred) {
return false;
}
@@ -478,7 +504,7 @@ final class MapGestureDetector {
// If scale is large enough ignore a tap
scaleFactor *= detector.getScaleFactor();
- if ((scaleFactor > 1.05f) || (scaleFactor < 0.95f)) {
+ if ((scaleFactor > 1.1f) || (scaleFactor < 0.9f)) {
// notify camera change listener
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
scaleGestureOccurred = true;
@@ -497,7 +523,6 @@ final class MapGestureDetector {
// make an assumption here; if the zoom center is specified by the gesture, it's NOT going
// to be in the center of the map. Therefore the zoom will translate the map center, so tracking
// should be disabled.
-
trackingSettings.resetTrackingModesIfRequired(!quickZoom, false, false);
// Scale the map
if (focalPoint != null) {
@@ -506,19 +531,79 @@ final class MapGestureDetector {
} else if (quickZoom) {
cameraChangeDispatcher.onCameraMove();
// clamp scale factors we feed to core #7514
- float scaleFactor = MathUtils.clamp(detector.getScaleFactor(),
+ float scaleFactor = detector.getScaleFactor();
+ // around center map
+ double zoomBy = Math.log(scaleFactor) / Math.log(Math.PI / 2);
+ boolean negative = zoomBy < 0;
+ zoomBy = MathUtils.clamp(Math.abs(zoomBy),
MapboxConstants.MINIMUM_SCALE_FACTOR_CLAMP,
MapboxConstants.MAXIMUM_SCALE_FACTOR_CLAMP);
- // around center map
- transform.zoomBy(Math.log(scaleFactor) / Math.log(Math.PI / 2),
- uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ transform.zoomBy(negative ? -zoomBy : zoomBy, uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
+ recentScaleGestureOccurred = true;
} else {
// around gesture
transform.zoomBy(Math.log(detector.getScaleFactor()) / Math.log(Math.PI / 2),
- detector.getFocusX(), detector.getFocusY());
+ scalePointBegin.x, scalePointBegin.y);
}
return true;
}
+
+ // Called when fingers leave screen
+ @Override
+ public void onScaleEnd(final ScaleGestureDetector detector) {
+ if (rotateGestureOccurred || quickZoom) {
+ reset();
+ return;
+ }
+
+ double velocityXY = Math.abs(velocityTracker.getYVelocity()) + Math.abs(velocityTracker.getXVelocity());
+ if (velocityXY > MapboxConstants.VELOCITY_THRESHOLD_IGNORE_FLING / 2) {
+ scaleAnimating = true;
+ double zoomAddition = calculateScale(velocityXY);
+ double currentZoom = transform.getRawZoom();
+ long animationTime = (long) (Math.log(velocityXY) * ANIMATION_TIME_MULTIPLIER);
+ createScaleAnimator(currentZoom, zoomAddition, animationTime).start();
+ } else if (!scaleAnimating) {
+ reset();
+ }
+ }
+
+ private void reset() {
+ scaleAnimating = false;
+ scaleGestureOccurred = false;
+ scaleBeginTime = 0;
+ scaleFactor = 1.0f;
+ cameraChangeDispatcher.onCameraIdle();
+ }
+
+ private double calculateScale(double velocityXY) {
+ double zoomAddition = (float) (Math.log(velocityXY) / ZOOM_DISTANCE_DIVIDER);
+ if (!wasZoomingIn) {
+ zoomAddition = -zoomAddition;
+ }
+ return zoomAddition;
+ }
+
+ private Animator createScaleAnimator(double currentZoom, double zoomAddition, long animationTime) {
+ ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition));
+ animator.setDuration(animationTime);
+ animator.setInterpolator(new FastOutSlowInInterpolator());
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ transform.setZoom((Float) animation.getAnimatedValue(), scalePointBegin);
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ reset();
+ }
+ });
+ return animator;
+ }
}
/**
@@ -526,11 +611,13 @@ final class MapGestureDetector {
*/
private class RotateGestureListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
- private static final long ROTATE_INVOKE_WAIT_TIME = 1500;
+ private static final float ROTATE_INVOKE_ANGLE = 15.30f;
+ private static final float ROTATE_LIMITATION_ANGLE = 3.35f;
+ private static final float ROTATE_LIMITATION_DURATION = ROTATE_LIMITATION_ANGLE * 1.85f;
private long beginTime = 0;
- private float totalAngle = 0.0f;
private boolean started = false;
+ private boolean animating = false;
// Called when two fingers first touch the screen
@Override
@@ -546,15 +633,6 @@ final class MapGestureDetector {
return true;
}
- // Called when the fingers leave the screen
- @Override
- public void onRotateEnd(RotateGestureDetector detector) {
- // notify camera change listener
- beginTime = 0;
- totalAngle = 0.0f;
- started = false;
- }
-
// Called each time one of the two fingers moves
// Called for rotation
@Override
@@ -563,18 +641,10 @@ final class MapGestureDetector {
return false;
}
- // Ignore short touches in case it is a tap
- // Also ignore small rotate
- long time = detector.getEventTime();
- long interval = time - beginTime;
- if (!started && (interval <= ViewConfiguration.getTapTimeout() || isScaleGestureActive(time))) {
- return false;
- }
-
// If rotate is large enough ignore a tap
// Also is zoom already started, don't rotate
- totalAngle += detector.getRotationDegreesDelta();
- if (totalAngle > 35.0f || totalAngle < -35.0f) {
+ float angle = detector.getRotationDegreesDelta();
+ if (Math.abs(angle) >= ROTATE_INVOKE_ANGLE) {
MapboxTelemetry.getInstance().pushEvent(MapboxEventWrapper.buildMapClickEvent(
getLocationFromGesture(detector.getFocusX(), detector.getFocusY()),
MapboxEvent.GESTURE_ROTATION_START, transform));
@@ -585,13 +655,17 @@ final class MapGestureDetector {
return false;
}
+ wasClockwiseRotating = detector.getRotationDegreesDelta() > 0;
+ if (scaleBeginTime != 0) {
+ rotateGestureOccurred = true;
+ }
+
// rotation constitutes translation of anything except the center of
// rotation, so cancel both location and bearing tracking if required
trackingSettings.resetTrackingModesIfRequired(true, true, false);
- // Get rotate value
- double bearing = transform.getRawBearing();
- bearing += detector.getRotationDegreesDelta();
+ // Calculate map bearing value
+ double bearing = transform.getRawBearing() + angle;
// Rotate the map
if (focalPoint != null) {
@@ -604,11 +678,81 @@ final class MapGestureDetector {
return true;
}
- private boolean isScaleGestureActive(long time) {
- long scaleExecutionTime = time - scaleBeginTime;
- boolean scaleGestureStarted = scaleBeginTime != 0;
- boolean scaleOffsetTimeValid = scaleExecutionTime > ROTATE_INVOKE_WAIT_TIME;
- return (scaleGestureStarted && scaleOffsetTimeValid) || scaleGestureOccurred;
+ // Called when the fingers leave the screen
+ @Override
+ public void onRotateEnd(RotateGestureDetector detector) {
+ long interval = detector.getEventTime() - beginTime;
+ if ((!started && (interval <= ViewConfiguration.getTapTimeout())) || scaleAnimating || interval > 500) {
+ reset();
+ return;
+ }
+
+ double angularVelocity = calculateVelocityVector(detector);
+ if (Math.abs(angularVelocity) > 0.001 && rotateGestureOccurred && !animating) {
+ animateRotateVelocity();
+ } else if (!animating) {
+ reset();
+ }
+ }
+
+ private void reset() {
+ beginTime = 0;
+ started = false;
+ animating = false;
+ rotateGestureOccurred = false;
+ }
+
+ private void animateRotateVelocity() {
+ animating = true;
+ double currentRotation = transform.getRawBearing();
+ double rotateAdditionDegrees = calculateVelocityInDegrees();
+ createAnimator(currentRotation, rotateAdditionDegrees).start();
+ }
+
+ private double calculateVelocityVector(RotateGestureDetector detector) {
+ return ((detector.getFocusX() * velocityTracker.getYVelocity())
+ + (detector.getFocusY() * velocityTracker.getXVelocity()))
+ / (Math.pow(detector.getFocusX(), 2) + Math.pow(detector.getFocusY(), 2));
+ }
+
+ private double calculateVelocityInDegrees() {
+ double angleRadians = Math.atan2(velocityTracker.getXVelocity(), velocityTracker.getYVelocity());
+ double angle = angleRadians / (Math.PI / 180);
+ if (angle <= 0) {
+ angle += 360;
+ }
+
+ // limit the angle
+ angle = angle / ROTATE_LIMITATION_ANGLE;
+
+ // correct direction
+ if (!wasClockwiseRotating) {
+ angle = -angle;
+ }
+
+ return angle;
+ }
+
+ private Animator createAnimator(double currentRotation, double rotateAdditionDegrees) {
+ ValueAnimator animator = ValueAnimator.ofFloat(
+ (float) currentRotation,
+ (float) (currentRotation + rotateAdditionDegrees)
+ );
+ animator.setDuration((long) (Math.abs(rotateAdditionDegrees) * ROTATE_LIMITATION_DURATION));
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ transform.setBearing((Float) animation.getAnimatedValue());
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ reset();
+ }
+ });
+ return animator;
}
}
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 92153f7f0b..c025a119b7 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
@@ -28,13 +28,14 @@ import com.mapbox.mapboxsdk.annotations.Annotation;
import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.constants.Style;
-import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
+import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.textureview.TextureViewMapRenderer;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
+import com.mapbox.mapboxsdk.storage.FileSource;
import com.mapbox.services.android.telemetry.MapboxTelemetry;
import java.lang.annotation.Retention;
@@ -175,8 +176,9 @@ public class MapView extends FrameLayout {
Markers markers = new MarkerContainer(nativeMapView, this, annotationsArray, iconManager, markerViewManager);
Polygons polygons = new PolygonContainer(nativeMapView, annotationsArray);
Polylines polylines = new PolylineContainer(nativeMapView, annotationsArray);
+ ShapeAnnotations shapeAnnotations = new ShapeAnnotationContainer(nativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, annotationsArray,
- markerViewManager, iconManager, annotations, markers, polygons, polylines);
+ markerViewManager, iconManager, annotations, markers, polygons, polylines, shapeAnnotations);
Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings,
cameraChangeDispatcher);
@@ -191,8 +193,10 @@ public class MapView extends FrameLayout {
annotationManager, cameraChangeDispatcher);
mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
+ // overlain zoom buttons
mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this));
- MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform);
+ MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform,
+ cameraChangeDispatcher, getWidth(), getHeight());
mapZoomButtonController.bind(uiSettings, zoomListener);
compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher));
@@ -345,8 +349,10 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onSaveInstanceState(@NonNull Bundle outState) {
- outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
- mapboxMap.onSaveInstanceState(outState);
+ if (mapboxMap != null) {
+ outState.putBoolean(MapboxConstants.STATE_HAS_SAVED_STATE, true);
+ mapboxMap.onSaveInstanceState(outState);
+ }
}
/**
@@ -355,6 +361,7 @@ public class MapView extends FrameLayout {
@UiThread
public void onStart() {
ConnectivityReceiver.instance(getContext()).activate();
+ FileSource.getInstance(getContext()).activate();
if (mapboxMap != null) {
mapboxMap.onStart();
}
@@ -385,8 +392,12 @@ public class MapView extends FrameLayout {
*/
@UiThread
public void onStop() {
- mapboxMap.onStop();
+ if (mapboxMap != null) {
+ // map was destroyed before it was started
+ mapboxMap.onStop();
+ }
ConnectivityReceiver.instance(getContext()).deactivate();
+ FileSource.getInstance(getContext()).deactivate();
}
/**
@@ -406,6 +417,10 @@ public class MapView extends FrameLayout {
@Override
public boolean onTouchEvent(MotionEvent event) {
+ if (!isMapInitialized() || !isZoomButtonControllerInitialized()) {
+ return super.onTouchEvent(event);
+ }
+
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mapZoomButtonController.setVisible(true);
}
@@ -434,11 +449,18 @@ public class MapView extends FrameLayout {
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
+ if (mapGestureDetector == null) {
+ return super.onGenericMotionEvent(event);
+ }
return mapGestureDetector.onGenericMotionEvent(event) || super.onGenericMotionEvent(event);
}
@Override
public boolean onHoverEvent(MotionEvent event) {
+ if (!isZoomButtonControllerInitialized()) {
+ return super.onHoverEvent(event);
+ }
+
switch (event.getActionMasked()) {
case MotionEvent.ACTION_HOVER_ENTER:
case MotionEvent.ACTION_HOVER_MOVE:
@@ -495,7 +517,7 @@ public class MapView extends FrameLayout {
if (destroyed) {
return;
}
- if (nativeMapView == null) {
+ if (!isMapInitialized()) {
mapboxMapOptions.styleUrl(url);
return;
}
@@ -512,7 +534,7 @@ public class MapView extends FrameLayout {
return;
}
- if (!isInEditMode() && nativeMapView != null) {
+ if (!isInEditMode() && isMapInitialized()) {
nativeMapView.resizeView(width, height);
}
}
@@ -526,7 +548,9 @@ public class MapView extends FrameLayout {
@CallSuper
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
- mapZoomButtonController.setVisible(false);
+ if (isZoomButtonControllerInitialized()) {
+ mapZoomButtonController.setVisible(false);
+ }
}
// Called when view is hidden and shown
@@ -536,7 +560,7 @@ public class MapView extends FrameLayout {
return;
}
- if (mapZoomButtonController != null) {
+ if (isZoomButtonControllerInitialized()) {
mapZoomButtonController.setVisible(visibility == View.VISIBLE);
}
}
@@ -598,6 +622,14 @@ public class MapView extends FrameLayout {
}
}
+ private boolean isMapInitialized() {
+ return nativeMapView != null;
+ }
+
+ private boolean isZoomButtonControllerInitialized() {
+ return mapZoomButtonController != null;
+ }
+
MapboxMap getMapboxMap() {
return mapboxMap;
}
@@ -883,16 +915,23 @@ public class MapView extends FrameLayout {
}
}
- private class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
+ private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
private final MapGestureDetector mapGestureDetector;
private final UiSettings uiSettings;
private final Transform transform;
+ private final CameraChangeDispatcher cameraChangeDispatcher;
+ private final float mapWidth;
+ private final float mapHeight;
- MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform) {
+ MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform,
+ CameraChangeDispatcher dispatcher, float mapWidth, float mapHeight) {
this.mapGestureDetector = detector;
this.uiSettings = uiSettings;
this.transform = transform;
+ this.cameraChangeDispatcher = dispatcher;
+ this.mapWidth = mapWidth;
+ this.mapHeight = mapHeight;
}
// Not used
@@ -905,6 +944,7 @@ public class MapView extends FrameLayout {
@Override
public void onZoom(boolean zoomIn) {
if (uiSettings.isZoomGesturesEnabled()) {
+ cameraChangeDispatcher.onCameraMoveStarted(CameraChangeDispatcher.REASON_API_ANIMATION);
onZoom(zoomIn, mapGestureDetector.getFocalPoint());
}
}
@@ -913,7 +953,7 @@ public class MapView extends FrameLayout {
if (focalPoint != null) {
transform.zoom(zoomIn, focalPoint);
} else {
- PointF centerPoint = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
+ PointF centerPoint = new PointF(mapWidth / 2, mapHeight / 2);
transform.zoom(zoomIn, centerPoint);
}
}
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 83b4dc4e84..6bf8342efb 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
@@ -47,6 +47,7 @@ import com.mapbox.services.commons.geojson.Feature;
import com.mapbox.services.commons.geojson.Geometry;
import java.lang.reflect.ParameterizedType;
+import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
@@ -463,6 +464,13 @@ public final class MapboxMap {
}
/**
+ * Adds an images to be used in the map's style
+ */
+ public void addImages(@NonNull HashMap<String, Bitmap> images) {
+ nativeMapView.addImages(images);
+ }
+
+ /**
* Removes an image from the map's style
*
* @param name the name of the image to remove
@@ -709,6 +717,10 @@ public final class MapboxMap {
// MapChange.REGION_DID_CHANGE_ANIMATED is not called for `jumpTo`
// invalidate camera position to provide OnCameraChange event.
invalidateCameraPosition();
+
+ if (callback != null) {
+ callback.onFinish();
+ }
}
});
}
@@ -1753,39 +1765,123 @@ public final class MapboxMap {
* Sets a callback that is invoked when camera movement has ended.
*
* @param listener the listener to notify
+ * @deprecated use {@link #addOnCameraIdleListener(OnCameraIdleListener)}
+ * and {@link #removeOnCameraIdleListener(OnCameraIdleListener)} instead
*/
+ @Deprecated
public void setOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
cameraChangeDispatcher.setOnCameraIdleListener(listener);
}
/**
+ * Adds a callback that is invoked when camera movement has ended.
+ *
+ * @param listener the listener to notify
+ */
+ public void addOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
+ cameraChangeDispatcher.addOnCameraIdleListener(listener);
+ }
+
+ /**
+ * Removes a callback that is invoked when camera movement has ended.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
+ cameraChangeDispatcher.removeOnCameraIdleListener(listener);
+ }
+
+ /**
* Sets a callback that is invoked when camera movement was cancelled.
*
* @param listener the listener to notify
+ * @deprecated use {@link #addOnCameraMoveCancelListener(OnCameraMoveCanceledListener)} and
+ * {@link #removeOnCameraMoveCancelListener(OnCameraMoveCanceledListener)} instead
*/
+ @Deprecated
public void setOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
cameraChangeDispatcher.setOnCameraMoveCanceledListener(listener);
}
/**
+ * Adds a callback that is invoked when camera movement was cancelled.
+ *
+ * @param listener the listener to notify
+ */
+ public void addOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
+ cameraChangeDispatcher.addOnCameraMoveCancelListener(listener);
+ }
+
+ /**
+ * Removes a callback that is invoked when camera movement was cancelled.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
+ cameraChangeDispatcher.removeOnCameraMoveCancelListener(listener);
+ }
+
+ /**
* Sets a callback that is invoked when camera movement has started.
*
* @param listener the listener to notify
+ * @deprecated use {@link #addOnCameraMoveStartedListener(OnCameraMoveStartedListener)} and
+ * {@link #removeOnCameraMoveStartedListener(OnCameraMoveStartedListener)} instead
*/
+ @Deprecated
public void setOnCameraMoveStartedListener(@Nullable OnCameraMoveStartedListener listener) {
cameraChangeDispatcher.setOnCameraMoveStartedListener(listener);
}
/**
+ * Adds a callback that is invoked when camera movement has started.
+ *
+ * @param listener the listener to notify
+ */
+ public void addOnCameraMoveStartedListener(@Nullable OnCameraMoveStartedListener listener) {
+ cameraChangeDispatcher.addOnCameraMoveStartedListener(listener);
+ }
+
+ /**
+ * Removes a callback that is invoked when camera movement has started.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeOnCameraMoveStartedListener(@Nullable OnCameraMoveStartedListener listener) {
+ cameraChangeDispatcher.removeOnCameraMoveStartedListener(listener);
+ }
+
+ /**
* Sets a callback that is invoked when camera position changes.
*
* @param listener the listener to notify
+ * @deprecated use {@link #addOnCameraMoveListener(OnCameraMoveListener)} and
+ * {@link #removeOnCameraMoveListener(OnCameraMoveListener)}instead
*/
+ @Deprecated
public void setOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
cameraChangeDispatcher.setOnCameraMoveListener(listener);
}
/**
+ * Adds a callback that is invoked when camera position changes.
+ *
+ * @param listener the listener to notify
+ */
+ public void addOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
+ cameraChangeDispatcher.addOnCameraMoveListener(listener);
+ }
+
+ /**
+ * Removes a callback that is invoked when camera position changes.
+ *
+ * @param listener the listener to remove
+ */
+ public void removeOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
+ cameraChangeDispatcher.removeOnCameraMoveListener(listener);
+ }
+
+ /**
* Sets a callback that's invoked on every frame rendered to the map view.
*
* @param listener The callback that's invoked on every frame rendered to the map view.
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MarkerContainer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MarkerContainer.java
index 072382ce07..2c2f07a112 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MarkerContainer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MarkerContainer.java
@@ -98,15 +98,8 @@ class MarkerContainer implements Markers {
@NonNull
@Override
public List<Marker> obtainAllIn(@NonNull RectF rectangle) {
- // convert Rectangle to be density depedent
- float pixelRatio = nativeMapView.getPixelRatio();
- RectF rect = new RectF(rectangle.left / pixelRatio,
- rectangle.top / pixelRatio,
- rectangle.right / pixelRatio,
- rectangle.bottom / pixelRatio);
-
+ RectF rect = nativeMapView.getDensityDependantRectangle(rectangle);
long[] ids = nativeMapView.queryPointAnnotations(rect);
-
List<Long> idsList = new ArrayList<>(ids.length);
for (long id : ids) {
idsList.add(id);
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 bd8a54783e..8b6bce69e2 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
@@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
+import android.os.AsyncTask;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -34,7 +35,9 @@ import com.mapbox.services.commons.geojson.Geometry;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import timber.log.Timber;
@@ -468,6 +471,13 @@ final class NativeMapView {
return nativeQueryPointAnnotations(rect);
}
+ public long[] queryShapeAnnotations(RectF rectF) {
+ if (isDestroyedOn("queryShapeAnnotations")) {
+ return new long[] {};
+ }
+ return nativeQueryShapeAnnotations(rectF);
+ }
+
public void addAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels) {
if (isDestroyedOn("addAnnotationIcon")) {
return;
@@ -746,6 +756,7 @@ final class NativeMapView {
if (isDestroyedOn("addImage")) {
return;
}
+
// Check/correct config
if (image.getConfig() != Bitmap.Config.ARGB_8888) {
image = image.copy(Bitmap.Config.ARGB_8888, false);
@@ -762,6 +773,14 @@ final class NativeMapView {
nativeAddImage(name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
}
+ public void addImages(@NonNull HashMap<String, Bitmap> bitmapHashMap) {
+ if (isDestroyedOn("addImages")) {
+ return;
+ }
+ //noinspection unchecked
+ new BitmapImageConversionTask(this).execute(bitmapHashMap);
+ }
+
public void removeImage(String name) {
if (isDestroyedOn("removeImage")) {
return;
@@ -825,6 +844,15 @@ final class NativeMapView {
return pixelRatio;
}
+ RectF getDensityDependantRectangle(final RectF rectangle) {
+ return new RectF(
+ rectangle.left / pixelRatio,
+ rectangle.top / pixelRatio,
+ rectangle.right / pixelRatio,
+ rectangle.bottom / pixelRatio
+ );
+ }
+
//
// Callbacks
//
@@ -927,6 +955,8 @@ final class NativeMapView {
private native long[] nativeQueryPointAnnotations(RectF rect);
+ private native long[] nativeQueryShapeAnnotations(RectF rect);
+
private native void nativeAddAnnotationIcon(String symbol, int width, int height, float scale, byte[] pixels);
private native void nativeRemoveAnnotationIcon(String symbol);
@@ -1006,6 +1036,8 @@ final class NativeMapView {
private native void nativeAddImage(String name, int width, int height, float pixelRatio,
byte[] array);
+ private native void nativeAddImages(Image[] images);
+
private native void nativeRemoveImage(String name);
private native Bitmap nativeGetImage(String name);
@@ -1093,4 +1125,55 @@ final class NativeMapView {
});
}
+
+
+ //
+ // Image conversion
+ //
+
+ private static class BitmapImageConversionTask extends AsyncTask<HashMap<String, Bitmap>, Void, List<Image>> {
+
+ private NativeMapView nativeMapView;
+
+ BitmapImageConversionTask(NativeMapView nativeMapView) {
+ this.nativeMapView = nativeMapView;
+ }
+
+ @Override
+ protected List<Image> doInBackground(HashMap<String, Bitmap>... params) {
+ HashMap<String, Bitmap> bitmapHashMap = params[0];
+
+ List<Image> images = new ArrayList<>();
+ ByteBuffer buffer;
+ String name;
+ Bitmap bitmap;
+
+ for (Map.Entry<String, Bitmap> stringBitmapEntry : bitmapHashMap.entrySet()) {
+ name = stringBitmapEntry.getKey();
+ bitmap = stringBitmapEntry.getValue();
+
+ if (bitmap.getConfig() != Bitmap.Config.ARGB_8888) {
+ bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, false);
+ }
+
+ buffer = ByteBuffer.allocate(bitmap.getByteCount());
+ bitmap.copyPixelsToBuffer(buffer);
+
+ float density = bitmap.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : bitmap.getDensity();
+ float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
+
+ images.add(new Image(buffer.array(), pixelRatio, name, bitmap.getWidth(), bitmap.getHeight()));
+ }
+
+ return images;
+ }
+
+ @Override
+ protected void onPostExecute(List<Image> images) {
+ super.onPostExecute(images);
+ if (nativeMapView != null && !nativeMapView.isDestroyedOn("nativeAddImages")) {
+ nativeMapView.nativeAddImages(images.toArray(new Image[images.size()]));
+ }
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotationContainer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotationContainer.java
new file mode 100644
index 0000000000..6ded2f32fb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotationContainer.java
@@ -0,0 +1,38 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.RectF;
+import android.support.v4.util.LongSparseArray;
+
+import com.mapbox.mapboxsdk.annotations.Annotation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class ShapeAnnotationContainer implements ShapeAnnotations {
+
+ private final NativeMapView nativeMapView;
+ private final LongSparseArray<Annotation> annotations;
+
+ ShapeAnnotationContainer(NativeMapView nativeMapView, LongSparseArray<Annotation> annotations) {
+ this.nativeMapView = nativeMapView;
+ this.annotations = annotations;
+ }
+
+ @Override
+ public List<Annotation> obtainAllIn(RectF rectangle) {
+ RectF rect = nativeMapView.getDensityDependantRectangle(rectangle);
+ long[] annotationIds = nativeMapView.queryShapeAnnotations(rect);
+ return getAnnotationsFromIds(annotationIds);
+ }
+
+ private List<Annotation> getAnnotationsFromIds(long[] annotationIds) {
+ List<Annotation> shapeAnnotations = new ArrayList<>();
+ for (long annotationId : annotationIds) {
+ Annotation annotation = annotations.get(annotationId);
+ if (annotation != null) {
+ shapeAnnotations.add(annotation);
+ }
+ }
+ return shapeAnnotations;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotations.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotations.java
new file mode 100644
index 0000000000..f9b2ca10db
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/ShapeAnnotations.java
@@ -0,0 +1,13 @@
+package com.mapbox.mapboxsdk.maps;
+
+import android.graphics.RectF;
+
+import com.mapbox.mapboxsdk.annotations.Annotation;
+
+import java.util.List;
+
+interface ShapeAnnotations {
+
+ List<Annotation> obtainAllIn(RectF rectF);
+
+}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
index 6f63c2eba8..0366e50627 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java
@@ -98,9 +98,6 @@ final class Transform implements MapView.OnMapChangedListener {
cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
- if (callback != null) {
- callback.onFinish();
- }
cameraChangeDispatcher.onCameraIdle();
}
}
@@ -210,6 +207,10 @@ final class Transform implements MapView.OnMapChangedListener {
return cameraPosition.zoom;
}
+ double getRawZoom() {
+ return mapView.getZoom();
+ }
+
void zoom(boolean zoomIn, @NonNull PointF focalPoint) {
CameraPosition cameraPosition = invalidateCameraPosition();
if (cameraPosition != null) {
@@ -221,6 +222,17 @@ final class Transform implements MapView.OnMapChangedListener {
}
}
+ void zoom(double zoomAddition, @NonNull PointF focalPoint, long duration) {
+ CameraPosition cameraPosition = invalidateCameraPosition();
+ if (cameraPosition != null) {
+ int newZoom = (int) Math.round(cameraPosition.zoom + zoomAddition);
+ setZoom(newZoom, focalPoint, duration);
+ } else {
+ // we are not transforming, notify about being idle
+ cameraChangeDispatcher.onCameraIdle();
+ }
+ }
+
void setZoom(double zoom, @NonNull PointF focalPoint) {
setZoom(zoom, focalPoint, 0);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
index 45f72af1c5..1e604c9bef 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java
@@ -6,10 +6,10 @@ import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
-import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -22,7 +22,7 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
* use {@link com.mapbox.mapboxsdk.maps.UiSettings}.
* </p>
*/
-public final class CompassView extends AppCompatImageView implements Runnable {
+public final class CompassView extends ImageView implements Runnable {
public static final long TIME_WAIT_IDLE = 500;
public static final long TIME_MAP_NORTH_ANIMATION = 150;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
index f210729037..1b9a156352 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java
@@ -300,10 +300,19 @@ public class OfflineRegion {
/**
* Pause or resume downloading of regional resources.
+ * <p>
+ * After a download has been completed, you are required to reset the state of the region to STATE_INACTIVE.
+ * </p>
*
* @param state the download state
*/
public void setDownloadState(@DownloadState int state) {
+ if (state == STATE_ACTIVE) {
+ fileSource.activate();
+ } else {
+ fileSource.deactivate();
+ }
+
this.state = state;
setOfflineRegionDownloadState(state);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
index 5206606c83..5deedc3e63 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
@@ -4,6 +4,7 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
@@ -262,35 +263,59 @@ public class MapSnapshotter {
nativeCancel();
}
- protected void addOverlay(Bitmap original) {
+ /**
+ * Draw an overlay on the map snapshot.
+ *
+ * @param mapSnapshot the map snapshot to draw the overlay on
+ */
+ protected void addOverlay(MapSnapshot mapSnapshot) {
+ Bitmap original = mapSnapshot.getBitmap();
+ Canvas canvas = new Canvas(original);
+ addLogo(canvas, original);
+ }
+
+ /**
+ * Draw a logo on the canvas created from the map snapshot.
+ *
+ * @param canvas the canvas to draw the bitmap on
+ * @param original the map snapshot image
+ */
+ private void addLogo(Canvas canvas, Bitmap original) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float margin = displayMetrics.density * LOGO_MARGIN_DP;
- Canvas canvas = new Canvas(original);
+ Bitmap logo = createScaledLogo(original);
+ canvas.drawBitmap(logo, margin, original.getHeight() - logo.getHeight() - margin, null);
+ }
+
+ /**
+ * Create a scaled logo for a map snapshot.
+ *
+ * @param snapshot the map snapshot where the logo should be placed on
+ * @return the scaled bitmap logo
+ */
+ private Bitmap createScaledLogo(Bitmap snapshot) {
+ Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, null);
+ float scale = calculateLogoScale(snapshot, logo);
+ Matrix matrix = new Matrix();
+ matrix.postScale(scale, scale);
+ return Bitmap.createBitmap(logo, 0, 0, logo.getWidth(), logo.getHeight(), matrix, true);
+ }
- // Decode just the boundaries
- BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
- bitmapOptions.inJustDecodeBounds = true;
- BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, bitmapOptions);
- int srcWidth = bitmapOptions.outWidth;
- int srcHeight = bitmapOptions.outHeight;
-
- // Ratio, preferred dimensions and resulting sample size
- float widthRatio = displayMetrics.widthPixels / original.getWidth();
- float heightRatio = displayMetrics.heightPixels / original.getHeight();
- float prefWidth = srcWidth / widthRatio;
- float prefHeight = srcHeight / heightRatio;
- int sampleSize = MapSnaphotUtil.calculateInSampleSize(bitmapOptions, (int) prefWidth, (int) prefHeight);
-
- // Scale bitmap
- bitmapOptions.inJustDecodeBounds = false;
- bitmapOptions.inScaled = true;
- bitmapOptions.inSampleSize = sampleSize;
- bitmapOptions.inDensity = srcWidth;
- bitmapOptions.inTargetDensity = (int) prefWidth * bitmapOptions.inSampleSize;
- Bitmap logo = BitmapFactory.decodeResource(context.getResources(), R.drawable.mapbox_logo_icon, bitmapOptions);
-
- float scaledHeight = bitmapOptions.outHeight * heightRatio / bitmapOptions.inSampleSize;
- canvas.drawBitmap(logo, margin, original.getHeight() - scaledHeight - margin, null);
+ /**
+ * Calculates the scale of the logo, only allow downscaling.
+ *
+ * @param snapshot the bitmap of the map snapshot
+ * @param logo the bitmap of the mapbox logo
+ * @return the scale value
+ */
+ private float calculateLogoScale(Bitmap snapshot, Bitmap logo) {
+ DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+ float widthRatio = displayMetrics.widthPixels / snapshot.getWidth();
+ float heightRatio = displayMetrics.heightPixels / snapshot.getHeight();
+ float prefWidth = logo.getWidth() / widthRatio;
+ float prefHeight = logo.getHeight() / heightRatio;
+ float calculatedScale = Math.min(prefWidth / logo.getWidth(), prefHeight / logo.getHeight()) * 2;
+ return calculatedScale < 1 ? calculatedScale : 1.0f;
}
/**
@@ -302,7 +327,7 @@ public class MapSnapshotter {
protected void onSnapshotReady(MapSnapshot snapshot) {
if (callback != null) {
if (snapshot.isShowLogo()) {
- addOverlay(snapshot.getBitmap());
+ addOverlay(snapshot);
}
callback.onSnapshotReady(snapshot);
reset();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
index a968cdf192..41dc449b50 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/storage/FileSource.java
@@ -72,7 +72,7 @@ public class FileSource {
MapboxConstants.KEY_META_DATA_SET_STORAGE_EXTERNAL,
MapboxConstants.DEFAULT_SET_STORAGE_EXTERNAL);
} catch (PackageManager.NameNotFoundException exception) {
- Timber.e(exception,"Failed to read the package metadata: ");
+ Timber.e(exception, "Failed to read the package metadata: ");
} catch (Exception exception) {
Timber.e(exception, "Failed to read the storage key: ");
}
@@ -119,17 +119,39 @@ public class FileSource {
}
private long nativePtr;
+ private long activeCounter;
+ private boolean wasPaused;
private FileSource(String cachePath, AssetManager assetManager) {
initialize(Mapbox.getAccessToken(), cachePath, assetManager);
}
+ public void activate() {
+ activeCounter++;
+ if (activeCounter == 1 && wasPaused) {
+ wasPaused = false;
+ resume();
+ }
+ }
+
+ public void deactivate() {
+ activeCounter--;
+ if (activeCounter == 0) {
+ wasPaused = true;
+ pause();
+ }
+ }
+
public native void setAccessToken(@NonNull String accessToken);
public native String getAccessToken();
public native void setApiBaseUrl(String baseUrl);
+ private native void resume();
+
+ private native void pause();
+
/**
* Sets a callback for transforming URLs requested from the internet
* <p>
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
index 14b18b00dc..1c0e439afc 100644
--- 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
@@ -5,6 +5,7 @@ import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.v4.graphics.drawable.DrawableCompat;
@@ -30,10 +31,15 @@ public class ColorUtils {
*/
@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;
+ try {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ int id = context.getResources().getIdentifier("colorPrimary", "attrs", context.getPackageName());
+ theme.resolveAttribute(id, typedValue, true);
+ return typedValue.data;
+ } catch (Exception exception) {
+ return getColorCompat(context, R.color.mapbox_blue);
+ }
}
/**
@@ -44,10 +50,15 @@ public class ColorUtils {
*/
@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;
+ try {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ int id = context.getResources().getIdentifier("colorPrimaryDark", "attrs", context.getPackageName());
+ theme.resolveAttribute(id, typedValue, true);
+ return typedValue.data;
+ } catch (Exception exception) {
+ return getColorCompat(context, R.color.mapbox_blue);
+ }
}
/**
@@ -58,10 +69,15 @@ public class ColorUtils {
*/
@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;
+ try {
+ TypedValue typedValue = new TypedValue();
+ Resources.Theme theme = context.getTheme();
+ int id = context.getResources().getIdentifier("colorAccent", "attrs", context.getPackageName());
+ theme.resolveAttribute(id, typedValue, true);
+ return typedValue.data;
+ } catch (Exception exception) {
+ return getColorCompat(context, R.color.mapbox_gray);
+ }
}
/**
@@ -122,4 +138,12 @@ public class ColorUtils {
throw new ConversionException("Not a valid rgb/rgba value");
}
}
+
+ private static int getColorCompat(Context context, int id) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ return context.getResources().getColor(id, context.getTheme());
+ } else {
+ return context.getResources().getColor(id);
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-bg/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000000..262e94f368
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-bg/strings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mapbox_compassContentDescription">Компас на картата. Активирай, за да насочиш картата на север.</string>
+ <string name="mapbox_attributionsIconContentDescription">Иконка функции. Активирай, за да покажеш диалог функции.</string>
+ <string name="mapbox_myLocationViewContentDescription">Изглед локация. Това показва местоположението ти на картата.</string>
+ <string name="mapbox_mapActionDescription">Показва карта създадена с Mapbox. Скролни с два пръста. Мащабирай с два пръста.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Android SDK</string>
+ <string name="mapbox_attributionTelemetryTitle">Направи Mapbox картите по-добри.</string>
+ <string name="mapbox_attributionTelemetryMessage">Помагаш OpenStreetMap и Mapbox картите да станат по-добри, като предоставяш анонимни данни за потребление.</string>
+ <string name="mapbox_attributionTelemetryPositive">Съгласявам се</string>
+ <string name="mapbox_attributionTelemetryNegative">Не се съгласявам</string>
+ <string name="mapbox_attributionTelemetryNeutral">Повече инфо</string>
+ <string name="mapbox_offline_error_region_definition_invalid">Предоставените OfflineRegionDefinition не пасват в границите на света: %s</string>
+
+ </resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-hu/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000000..520edb2733
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-hu/strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mapbox_myLocationViewContentDescription">Hely nézet. Megmutatja, hol vagy a térképen.</string>
+ <string name="mapbox_mapActionDescription">Egy Mapbox-szal készült térkép megjelenítése. Húzd két ujjadat a görgetéshez. Csippentsd össze a nagyításhoz.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Android SDK</string>
+ <string name="mapbox_attributionTelemetryTitle">Tedd jobbá a Mapbox térképeket</string>
+ <string name="mapbox_attributionTelemetryMessage">Segítesz az OpenStreetMap és Mapbox térképek jobbá tételében névtelen felhasználási adatok elküldésével.</string>
+ <string name="mapbox_attributionTelemetryPositive">Egyetértek</string>
+ <string name="mapbox_attributionTelemetryNegative">Nem értek egyet</string>
+ <string name="mapbox_attributionTelemetryNeutral">Több infó</string>
+ <string name="mapbox_offline_error_region_definition_invalid">A megadott OfflineRegionDefinition nem fér bele a világ kereteibe: %s</string>
+
+ </resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
deleted file mode 100644
index eba1fb3a7d..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <style name="mapbox_AlertDialogStyle" parent="Theme.AppCompat.Light.Dialog.Alert"/>
-
-</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
index 8d9a360714..bb96c9939d 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
@@ -74,15 +74,6 @@ public class LatLngBoundsTest {
}
@Test
- public void emptySpan() {
- latLngBounds = new LatLngBounds.Builder()
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .include(LAT_LNG_NOT_NULL_ISLAND)
- .build();
- assertTrue("Should be empty", latLngBounds.isEmptySpan());
- }
-
- @Test
public void notEmptySpan() {
latLngBounds = new LatLngBounds.Builder()
.include(LAT_LNG_NOT_NULL_ISLAND)
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AnnotationManagerTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AnnotationManagerTest.java
index 0d592f9bb3..239ad7392b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AnnotationManagerTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/AnnotationManagerTest.java
@@ -10,6 +10,7 @@ import com.mapbox.mapboxsdk.annotations.MarkerViewManager;
import com.mapbox.mapboxsdk.geometry.LatLng;
import org.junit.Test;
+import org.mockito.ArgumentMatchers;
import java.util.ArrayList;
import java.util.List;
@@ -32,8 +33,9 @@ public class AnnotationManagerTest {
Markers markers = new MarkerContainer(aNativeMapView, aMapView, annotationsArray, aIconManager, aMarkerViewManager);
Polygons polygons = new PolygonContainer(aNativeMapView, annotationsArray);
Polylines polylines = new PolylineContainer(aNativeMapView, annotationsArray);
+ ShapeAnnotations shapeAnnotations = new ShapeAnnotationContainer(aNativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(aNativeMapView, aMapView, annotationsArray,
- aMarkerViewManager, aIconManager, annotations, markers, polygons, polylines);
+ aMarkerViewManager, aIconManager, annotations, markers, polygons, polylines, shapeAnnotations);
Marker aMarker = mock(Marker.class);
long aId = 5L;
when(aNativeMapView.addMarker(aMarker)).thenReturn(aId);
@@ -58,18 +60,23 @@ public class AnnotationManagerTest {
Markers markers = new MarkerContainer(aNativeMapView, aMapView, annotationsArray, aIconManager, aMarkerViewManager);
Polygons polygons = new PolygonContainer(aNativeMapView, annotationsArray);
Polylines polylines = new PolylineContainer(aNativeMapView, annotationsArray);
+ ShapeAnnotations shapeAnnotations = new ShapeAnnotationContainer(aNativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(aNativeMapView, aMapView, annotationsArray,
- aMarkerViewManager, aIconManager, annotations, markers, polygons, polylines);
+ aMarkerViewManager, aIconManager, annotations, markers, polygons, polylines, shapeAnnotations);
long firstId = 1L;
long secondId = 2L;
List<BaseMarkerOptions> markerList = new ArrayList<>();
MarkerOptions firstMarkerOption = new MarkerOptions().position(new LatLng()).title("first");
MarkerOptions secondMarkerOption = new MarkerOptions().position(new LatLng()).title("second");
+
markerList.add(firstMarkerOption);
markerList.add(secondMarkerOption);
MapboxMap aMapboxMap = mock(MapboxMap.class);
when(aNativeMapView.addMarker(any(Marker.class))).thenReturn(firstId, secondId);
+ when(aNativeMapView.addMarkers(ArgumentMatchers.<Marker>anyList()))
+ .thenReturn(new long[]{firstId, secondId});
+
annotationManager.addMarkers(markerList, aMapboxMap);
assertEquals(2, annotationManager.getAnnotations().size());
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcherTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcherTest.java
new file mode 100644
index 0000000000..090d274fe7
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/CameraChangeDispatcherTest.java
@@ -0,0 +1,87 @@
+package com.mapbox.mapboxsdk.maps;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class CameraChangeDispatcherTest {
+
+ @Test
+ public void testSetCameraIdleListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraIdleListener listener = mock(MapboxMap.OnCameraIdleListener.class);
+ dispatcher.setOnCameraIdleListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraIdle();
+ verify(listener).onCameraIdle();
+ }
+
+ @Test
+ public void testSetCameraMoveStartedListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveStartedListener listener = mock(MapboxMap.OnCameraMoveStartedListener.class);
+ dispatcher.setOnCameraMoveStartedListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ verify(listener).onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ }
+
+ @Test
+ public void testSetCameraMoveCancelListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveCanceledListener listener = mock(MapboxMap.OnCameraMoveCanceledListener.class);
+ dispatcher.setOnCameraMoveCanceledListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraMoveCanceled();
+ verify(listener).onCameraMoveCanceled();
+ }
+
+ @Test
+ public void testSetCameraMoveListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveListener listener = mock(MapboxMap.OnCameraMoveListener.class);
+ dispatcher.setOnCameraMoveListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraMove();
+ verify(listener).onCameraMove();
+ }
+
+ @Test
+ public void testAddCameraIdleListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraIdleListener listener = mock(MapboxMap.OnCameraIdleListener.class);
+ dispatcher.addOnCameraIdleListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraIdle();
+ verify(listener).onCameraIdle();
+ }
+
+ @Test
+ public void testAddCameraMoveStartedListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveStartedListener listener = mock(MapboxMap.OnCameraMoveStartedListener.class);
+ dispatcher.addOnCameraMoveStartedListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ verify(listener).onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ }
+
+ @Test
+ public void testAddCameraMoveCancelListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveCanceledListener listener = mock(MapboxMap.OnCameraMoveCanceledListener.class);
+ dispatcher.addOnCameraMoveCancelListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraMoveCanceled();
+ verify(listener).onCameraMoveCanceled();
+ }
+
+ @Test
+ public void testAddCameraMoveListener() {
+ CameraChangeDispatcher dispatcher = new CameraChangeDispatcher();
+ MapboxMap.OnCameraMoveListener listener = mock(MapboxMap.OnCameraMoveListener.class);
+ dispatcher.addOnCameraMoveListener(listener);
+ dispatcher.onCameraMoveStarted(MapboxMap.OnCameraMoveStartedListener.REASON_API_GESTURE);
+ dispatcher.onCameraMove();
+ verify(listener).onCameraMove();
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 81ee635cf1..f45ad3dc3a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -59,6 +59,7 @@ dependencies {
// Support libraries
compile rootProject.ext.dep.supportAppcompatV7
compile rootProject.ext.dep.supportRecyclerView
+ compile rootProject.ext.dep.supportDesign
// Leak Canary
debugCompile rootProject.ext.dep.leakCanaryDebug
@@ -71,7 +72,6 @@ dependencies {
compile rootProject.ext.dep.lost
// Testing dependencies
- androidTestCompile rootProject.ext.dep.testSpoonRunner
androidTestCompile rootProject.ext.dep.supportAnnotations
androidTestCompile rootProject.ext.dep.testRunner
androidTestCompile rootProject.ext.dep.testRules
@@ -81,8 +81,6 @@ dependencies {
apply from: 'gradle-make.gradle'
apply from: 'gradle-config.gradle'
-apply from: 'gradle-device-farm.gradle'
-apply from: 'gradle-spoon.gradle'
apply from: 'gradle-checkstyle.gradle'
apply from: '../gradle-lint.gradle'
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle
deleted file mode 100644
index 5cb5d75bbb..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/gradle-device-farm.gradle
+++ /dev/null
@@ -1,43 +0,0 @@
-apply plugin: 'devicefarm'
-
-def getAccessKeyDeviceFarm() {
- if (project.hasProperty('AWS_ACCESS_KEY_ID_DEVICE_FARM')) {
- return AWS_ACCESS_KEY_ID_DEVICE_FARM
- } else {
- println("Could not locate AWS_ACCESS_KEY_ID_DEVICE_FARM in gradle.properties")
- return ""
- }
-}
-
-def getSecretAccessKeyDeviceFarm() {
- if (project.hasProperty('AWS_SECRET_ACCESS_KEY_DEVICE_FARM')) {
- return AWS_SECRET_ACCESS_KEY_DEVICE_FARM
- } else {
- println("Could not locate AWS_SECRET_ACCESS_KEY_DEVICE_FARM in gradle.properties")
- return ""
- }
-}
-
-devicefarm {
-
- projectName "Mapbox GL Android" // required: Must already exists.
- devicePool "sanity" // optional: Defaults to "Top Devices"
-
- authentication {
- accessKey getAccessKeyDeviceFarm()
- secretKey getSecretAccessKeyDeviceFarm()
- }
-
- devicestate {
- wifi "on"
- bluetooth "off"
- gps "on"
- nfc "on"
- latitude 47.6204 // default
- longitude - 122.3491 // default
- }
-
- instrumentation {
-
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/gradle-spoon.gradle b/platform/android/MapboxGLAndroidSDKTestApp/gradle-spoon.gradle
deleted file mode 100644
index 7a5b966443..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/gradle-spoon.gradle
+++ /dev/null
@@ -1,8 +0,0 @@
-println "configuring spoon"
-apply plugin: 'spoon'
-spoon {
- // Spoon: distributes instrumentation tests to all your Androids
- // for more options see https://github.com/stanfy/spoon-gradle-plugin
- grantAllPermissions = true
- debug = true
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
index 294d57bce1..3dbbaceb1a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -14,6 +14,7 @@ import com.mapbox.mapboxsdk.annotations.Polygon;
import com.mapbox.mapboxsdk.annotations.PolygonOptions;
import com.mapbox.mapboxsdk.annotations.Polyline;
import com.mapbox.mapboxsdk.annotations.PolylineOptions;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.InvalidMarkerPositionException;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -31,9 +32,12 @@ import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
+import timber.log.Timber;
+
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static com.mapbox.mapboxsdk.testapp.utils.TestConstants.LAT_LNG_DELTA;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertEquals;
@@ -90,9 +94,34 @@ public class MapboxMapTest extends BaseActivityTest {
}
//
- // CameraForLatLngBounds
+ // Camera tests
//
@Test
+ public void testCameraPositionOnFinish() {
+ ViewUtils.checkViewIsDisplayed(R.id.mapView);
+ onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
+ @Override
+ public void onViewAction(UiController uiController, View view) {
+
+ final LatLng latLng = new LatLng(30.0, 30.0);
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(latLng), new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ }
+
+ @Override
+ public void onFinish() {
+ LatLng cameraPositionLatLng = mapboxMap.getCameraPosition().target;
+ Timber.d(cameraPositionLatLng.toString());
+ assertEquals(cameraPositionLatLng.getLatitude(), latLng.getLatitude(), LAT_LNG_DELTA);
+ assertEquals(cameraPositionLatLng.getLongitude(), latLng.getLongitude(), LAT_LNG_DELTA);
+ }
+ });
+ }
+ }));
+ }
+
+ @Test
public void testCameraForLatLngBounds() {
ViewUtils.checkViewIsDisplayed(R.id.mapView);
onView(withId(R.id.mapView)).perform(new MapboxMapAction(new InvokeViewAction() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
index c029bc09c4..61bff1f113 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/BaseActivityTest.java
@@ -49,8 +49,9 @@ public abstract class BaseActivityTest {
throw new RuntimeException("Could not start test for " + getActivityClass().getSimpleName() + ".\n"
+ "The ViewHierarchy doesn't contain a view with resource id = R.id.mapView or \n"
+ "the Activity doesn't contain an instance variable with a name equal to mapboxMap.\n"
- + "You can resolve this issue be implementing the requirements above or\n add "
- + getActivityClass().getSimpleName() + " to the excludeActivities array in `generate-test-code.js`.\n");
+ + "You can resolve this issue by adding the requirements above or\n add "
+ + getActivityClass().getSimpleName() + " to the platform/android/scripts/exclude-activity-gen.json to blacklist"
+ + " the Activity from being generated.\n");
}
}
@@ -67,8 +68,7 @@ public abstract class BaseActivityTest {
protected abstract Class getActivityClass();
protected void checkViewIsDisplayed(int id) {
- onView(withId(id))
- .check(matches(isDisplayed()));
+ onView(withId(id)).check(matches(isDisplayed()));
}
protected void waitLoop() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
index d37c6db2d5..a20426c29c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/AttributionTest.java
@@ -21,6 +21,7 @@ import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import static android.support.test.espresso.Espresso.onData;
@@ -67,6 +68,7 @@ public class AttributionTest extends BaseActivityTest {
}
@Test
+ @Ignore
public void testMapboxStreetsMapboxAttributionLink() {
validateTestSetup();
if (urlSpans == null) {
@@ -87,6 +89,7 @@ public class AttributionTest extends BaseActivityTest {
}
@Test
+ @Ignore
public void testMapboxStreetsOpenStreetMapAttributionLink() {
validateTestSetup();
if (urlSpans == null) {
@@ -107,6 +110,7 @@ public class AttributionTest extends BaseActivityTest {
}
@Test
+ @Ignore
public void testImproveMapLink() {
validateTestSetup();
if (urlSpans == null) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
index 1c4981ca5e..0e2e4587ee 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/utils/OnMapReadyIdlingResource.java
@@ -13,10 +13,8 @@ public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallb
private MapboxMap mapboxMap;
private IdlingResource.ResourceCallback resourceCallback;
- private Activity activity;
public OnMapReadyIdlingResource(Activity activity) {
- this.activity = activity;
try {
Field field = activity.getClass().getDeclaredField("mapView");
field.setAccessible(true);
@@ -24,7 +22,6 @@ public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallb
} catch (Exception err) {
throw new RuntimeException(err);
}
-
}
@Override
@@ -53,4 +50,4 @@ public class OnMapReadyIdlingResource implements IdlingResource, OnMapReadyCallb
resourceCallback.onTransitionToIdle();
}
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
index cc44ac9715..c8c5c6bd37 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
@@ -5,13 +5,20 @@ import android.animation.AnimatorSet;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.os.Bundle;
+import android.support.v4.util.LongSparseArray;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
+import android.support.v4.view.animation.PathInterpolatorCompat;
import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.view.animation.AnticipateOvershootInterpolator;
+import android.view.animation.BounceInterpolator;
+import android.view.animation.Interpolator;
import com.mapbox.mapboxsdk.camera.CameraPosition;
+import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -24,6 +31,51 @@ import com.mapbox.mapboxsdk.testapp.R;
public class CameraAnimatorActivity extends AppCompatActivity implements OnMapReadyCallback {
private static final double ANIMATION_DELAY_FACTOR = 1.5;
+ private static final LatLng START_LAT_LNG = new LatLng(37.787947, -122.407432);
+
+ private final LongSparseArray<AnimatorBuilder> animators = new LongSparseArray<AnimatorBuilder>() {
+ {
+ put(R.id.menu_action_accelerate_decelerate_interpolator, new AnimatorBuilder() {
+ @Override
+ public Animator build() {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(
+ createLatLngAnimator(START_LAT_LNG, new LatLng(37.826715, -122.422795)),
+ obtainExampleInterpolator(new FastOutSlowInInterpolator(), 2500)
+ );
+ return animatorSet;
+ }
+ });
+
+ put(R.id.menu_action_bounce_interpolator, new AnimatorBuilder() {
+ @Override
+ public Animator build() {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(
+ createLatLngAnimator(START_LAT_LNG, new LatLng(37.787947, -122.407432)),
+ obtainExampleInterpolator(new BounceInterpolator(), 3750)
+ );
+ return animatorSet;
+ }
+ });
+
+ put(R.id.menu_action_anticipate_overshoot_interpolator, new AnimatorBuilder() {
+ @Override
+ public Animator build() {
+ return obtainExampleInterpolator(new AnticipateOvershootInterpolator(), 2500);
+ }
+ });
+
+ put(R.id.menu_action_path_interpolator, new AnimatorBuilder() {
+ @Override
+ public Animator build() {
+ return obtainExampleInterpolator(
+ PathInterpolatorCompat.create(.22f, .68f, 0, 1.71f), 2500);
+ }
+ });
+ }
+ };
+
private MapView mapView;
private MapboxMap mapboxMap;
@@ -32,7 +84,6 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera_animator);
-
mapView = (MapView) findViewById(R.id.mapView);
if (mapView != null) {
mapView.onCreate(savedInstanceState);
@@ -43,27 +94,42 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
@Override
public void onMapReady(final MapboxMap map) {
mapboxMap = map;
+ initFab();
+ }
+
+ private void initFab() {
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
view.setVisibility(View.GONE);
- createAnimator(mapboxMap.getCameraPosition()).start();
+
+ CameraPosition animatedPosition = new CameraPosition.Builder()
+ .target(new LatLng(37.789992, -122.402214))
+ .tilt(60)
+ .zoom(14.5f)
+ .bearing(135)
+ .build();
+
+ createExampleAnimator(mapboxMap.getCameraPosition(), animatedPosition).start();
}
});
}
- private Animator createAnimator(CameraPosition currentPosition) {
+ //
+ // Animator API used for the animation on the FAB
+ //
+
+ private Animator createExampleAnimator(CameraPosition currentPosition, CameraPosition targetPosition) {
AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.play(createLatLngAnimator(currentPosition.target));
- animatorSet.play(createZoomAnimator(currentPosition.zoom));
- animatorSet.play(createBearingAnimator(currentPosition.bearing));
- animatorSet.play(createTiltAnimator(currentPosition.tilt));
+ animatorSet.play(createLatLngAnimator(currentPosition.target, targetPosition.target));
+ animatorSet.play(createZoomAnimator(currentPosition.zoom, targetPosition.zoom));
+ animatorSet.play(createBearingAnimator(currentPosition.bearing, targetPosition.bearing));
+ animatorSet.play(createTiltAnimator(currentPosition.tilt, targetPosition.tilt));
return animatorSet;
}
- private Animator createLatLngAnimator(LatLng currentPosition) {
- LatLng target = new LatLng(37.789992, -122.402214);
- ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, target);
+ private Animator createLatLngAnimator(LatLng currentPosition, LatLng targetPosition) {
+ ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, targetPosition);
latLngAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
latLngAnimator.setInterpolator(new FastOutSlowInInterpolator());
latLngAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -75,8 +141,8 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
return latLngAnimator;
}
- private Animator createZoomAnimator(double currentZoom) {
- ValueAnimator zoomAnimator = ValueAnimator.ofFloat((float) currentZoom, 14.5f);
+ private Animator createZoomAnimator(double currentZoom, double targetZoom) {
+ ValueAnimator zoomAnimator = ValueAnimator.ofFloat((float) currentZoom, (float) targetZoom);
zoomAnimator.setDuration((long) (2200 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setStartDelay((long) (600 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setInterpolator(new AnticipateOvershootInterpolator());
@@ -89,8 +155,8 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
return zoomAnimator;
}
- private Animator createBearingAnimator(double currentBearing) {
- ValueAnimator bearingAnimator = ValueAnimator.ofFloat((float) currentBearing, 135);
+ private Animator createBearingAnimator(double currentBearing, double targetBearing) {
+ ValueAnimator bearingAnimator = ValueAnimator.ofFloat((float) currentBearing, (float) targetBearing);
bearingAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setStartDelay((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setInterpolator(new FastOutLinearInInterpolator());
@@ -103,8 +169,8 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
return bearingAnimator;
}
- private Animator createTiltAnimator(double currentTilt) {
- ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, 60);
+ private Animator createTiltAnimator(double currentTilt, double targetTilt) {
+ ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, (float) targetTilt);
tiltAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
tiltAnimator.setStartDelay((long) (1500 * ANIMATION_DELAY_FACTOR));
tiltAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@@ -116,20 +182,66 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
return tiltAnimator;
}
- private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
+ //
+ // Interpolator examples
+ //
- private final LatLng latLng = new LatLng();
+ private Animator obtainExampleInterpolator(int menuItemId) {
+ return animators.get(menuItemId).build();
+ }
- @Override
- public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
- latLng.setLatitude(startValue.getLatitude()
- + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
- latLng.setLongitude(startValue.getLongitude()
- + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
- return latLng;
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_animator, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (mapboxMap == null) {
+ return false;
}
+ findViewById(R.id.fab).setVisibility(View.GONE);
+ resetCameraPosition();
+ playAnimation(item.getItemId());
+ return super.onOptionsItemSelected(item);
}
+ private void resetCameraPosition() {
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(
+ new CameraPosition.Builder()
+ .target(START_LAT_LNG)
+ .zoom(11)
+ .bearing(0)
+ .tilt(0)
+ .build()
+ ));
+ }
+
+ private void playAnimation(int itemId) {
+ Animator animator = obtainExampleInterpolator(itemId);
+ if (animator != null) {
+ animator.start();
+ }
+ }
+
+ private Animator obtainExampleInterpolator(Interpolator interpolator, long duration) {
+ ValueAnimator zoomAnimator = ValueAnimator.ofFloat(11.0f, 16.0f);
+ zoomAnimator.setDuration((long) (duration * ANIMATION_DELAY_FACTOR));
+ zoomAnimator.setInterpolator(interpolator);
+ zoomAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mapboxMap.setZoom((Float) animation.getAnimatedValue());
+ }
+ });
+ return zoomAnimator;
+ }
+
+ //
+ // MapView lifecycle
+ //
+
@Override
protected void onStart() {
super.onStart();
@@ -171,4 +283,25 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
super.onLowMemory();
mapView.onLowMemory();
}
+
+ /**
+ * Helper class to evaluate LatLng objects with a ValueAnimator
+ */
+ private static class LatLngEvaluator implements TypeEvaluator<LatLng> {
+
+ private final LatLng latLng = new LatLng();
+
+ @Override
+ public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
+ latLng.setLatitude(startValue.getLatitude()
+ + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
+ latLng.setLongitude(startValue.getLongitude()
+ + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
+ return latLng;
+ }
+ }
+
+ interface AnimatorBuilder {
+ Animator build();
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
index 2820bdbd53..e5c6a3f584 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraPositionActivity.java
@@ -1,6 +1,5 @@
package com.mapbox.mapboxsdk.testapp.activity.camera;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
@@ -28,11 +27,13 @@ import timber.log.Timber;
/**
* Test activity showcasing how to listen to camera change events.
*/
-public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback {
+public class CameraPositionActivity extends AppCompatActivity implements OnMapReadyCallback, View.OnClickListener,
+ MapboxMap.OnMapLongClickListener {
private MapView mapView;
private MapboxMap mapboxMap;
private FloatingActionButton fab;
+ private boolean logCameraChanges;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -47,96 +48,48 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe
@Override
public void onMapReady(@NonNull final MapboxMap map) {
mapboxMap = map;
-
- mapboxMap.setOnCameraIdleListener(new MapboxMap.OnCameraIdleListener() {
- @Override
- public void onCameraIdle() {
- Timber.e("OnCameraIdle");
- fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_green_dark));
- }
- });
-
- mapboxMap.setOnCameraMoveCancelListener(new MapboxMap.OnCameraMoveCanceledListener() {
- @Override
- public void onCameraMoveCanceled() {
- Timber.e("OnCameraMoveCanceled");
- }
- });
-
- mapboxMap.setOnCameraMoveListener(new MapboxMap.OnCameraMoveListener() {
- @Override
- public void onCameraMove() {
- Timber.e("OnCameraMove");
- fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_orange_dark));
- }
- });
-
- mapboxMap.setOnCameraMoveStartedListener(new MapboxMap.OnCameraMoveStartedListener() {
-
- private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"};
-
- @Override
- public void onCameraMoveStarted(int reason) {
- // reason ranges from 1 <-> 3
- fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_red_dark));
- Timber.e("OnCameraMoveStarted: %s", REASONS[reason - 1]);
- }
- });
+ toggleLogCameraChanges();
// add a listener to FAB
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, R.color.primary));
- fab.setOnClickListener(new View.OnClickListener() {
- @SuppressLint("InflateParams")
- @Override
- public void onClick(View view) {
- Context context = view.getContext();
- 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.mapbox_AlertDialogStyle);
- 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,
- new MapboxMap.CancelableCallback() {
- @Override
- public void onCancel() {
- Timber.v("OnCancel called");
- }
-
- @Override
- public void onFinish() {
- Timber.v("OnFinish called");
- }
- });
- Timber.v(cameraPosition.toString());
- }
- });
- builder.setNegativeButton("Cancel", null);
- builder.setCancelable(false);
- builder.show();
- }
- });
+ fab.setOnClickListener(this);
+
+ // listen to long click events to toggle logging camera changes
+ mapboxMap.setOnMapLongClickListener(this);
+ }
+
+ @Override
+ public void onMapLongClick(@NonNull LatLng point) {
+ toggleLogCameraChanges();
+ }
+
+ @Override
+ public void onClick(View view) {
+ Context context = view.getContext();
+ final View dialogContent = LayoutInflater.from(context).inflate(R.layout.dialog_camera_position, null);
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.dialog_camera_position);
+ builder.setView(onInflateDialogContent(dialogContent));
+ builder.setPositiveButton("Animate", new DialogClickListener(mapboxMap, dialogContent));
+ builder.setNegativeButton("Cancel", null);
+ builder.setCancelable(false);
+ builder.show();
+ }
+
+ private void toggleLogCameraChanges() {
+ logCameraChanges = !logCameraChanges;
+ if (logCameraChanges) {
+ mapboxMap.addOnCameraIdleListener(idleListener);
+ mapboxMap.addOnCameraMoveCancelListener(moveCanceledListener);
+ mapboxMap.addOnCameraMoveListener(moveListener);
+ mapboxMap.addOnCameraMoveStartedListener(moveStartedListener);
+ } else {
+ mapboxMap.removeOnCameraIdleListener(idleListener);
+ mapboxMap.removeOnCameraMoveCancelListener(moveCanceledListener);
+ mapboxMap.removeOnCameraMoveListener(moveListener);
+ mapboxMap.removeOnCameraMoveStartedListener(moveStartedListener);
+ }
}
@Override
@@ -193,6 +146,42 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe
seekBar.setProgress(defaultValue);
}
+ private MapboxMap.OnCameraIdleListener idleListener = new MapboxMap.OnCameraIdleListener() {
+ @Override
+ public void onCameraIdle() {
+ Timber.e("OnCameraIdle");
+ fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_green_dark));
+ }
+ };
+
+ private MapboxMap.OnCameraMoveListener moveListener = new MapboxMap.OnCameraMoveListener() {
+ @Override
+ public void onCameraMove() {
+ Timber.e("OnCameraMove");
+ fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_orange_dark));
+ }
+ };
+
+ private MapboxMap.OnCameraMoveCanceledListener moveCanceledListener = new MapboxMap.OnCameraMoveCanceledListener() {
+ @Override
+ public void onCameraMoveCanceled() {
+ Timber.e("OnCameraMoveCanceled");
+
+ }
+ };
+
+ private MapboxMap.OnCameraMoveStartedListener moveStartedListener = new MapboxMap.OnCameraMoveStartedListener() {
+
+ private final String[] REASONS = {"REASON_API_GESTURE", "REASON_DEVELOPER_ANIMATION", "REASON_API_ANIMATION"};
+
+ @Override
+ public void onCameraMoveStarted(int reason) {
+ // reason ranges from 1 <-> 3
+ fab.setColorFilter(ContextCompat.getColor(CameraPositionActivity.this, android.R.color.holo_red_dark));
+ Timber.e("OnCameraMoveStarted: %s", REASONS[reason - 1]);
+ }
+ };
+
private class ValueChangeListener implements SeekBar.OnSeekBarChangeListener {
protected TextView textView;
@@ -224,4 +213,50 @@ public class CameraPositionActivity extends AppCompatActivity implements OnMapRe
super.onProgressChanged(seekBar, progress - 180, fromUser);
}
}
+
+ private static class DialogClickListener implements DialogInterface.OnClickListener {
+
+ private MapboxMap mapboxMap;
+ private View dialogContent;
+
+ public DialogClickListener(MapboxMap mapboxMap, View view) {
+ this.mapboxMap = mapboxMap;
+ this.dialogContent = view;
+ }
+
+ @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,
+ new MapboxMap.CancelableCallback() {
+ @Override
+ public void onCancel() {
+ Timber.v("OnCancel called");
+ }
+
+ @Override
+ public void onFinish() {
+ Timber.v("OnFinish called");
+ }
+ });
+ Timber.v(cameraPosition.toString());
+ }
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
index 5bffd4d930..3a59e0628d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/OfflineActivity.java
@@ -264,6 +264,7 @@ public class OfflineActivity extends AppCompatActivity
if (status.isComplete()) {
// Download complete
endProgress("Region downloaded successfully.");
+ offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
offlineRegion.setObserver(null);
return;
} else if (status.isRequiredResourceCountPrecise()) {
@@ -281,11 +282,13 @@ public class OfflineActivity extends AppCompatActivity
@Override
public void onError(OfflineRegionError error) {
Timber.e("onError: %s, %s", error.getReason(), error.getMessage());
+ offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
}
@Override
public void mapboxTileCountLimitExceeded(long limit) {
Timber.e("Mapbox tile count limit exceeded: %s", limit);
+ offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE);
}
});
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
index 0eaccfef0c..6e9e45cfaa 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
@@ -1,13 +1,14 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.support.v7.app.AppCompatActivity;
import android.graphics.Color;
import android.graphics.PointF;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
-
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -32,7 +33,7 @@ import com.mapbox.services.commons.geojson.custom.PositionDeserializer;
import com.mapbox.services.commons.models.Position;
import java.io.IOException;
-
+import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
@@ -64,49 +65,10 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
}
@Override
- public void onMapReady(MapboxMap map) {
+ public void onMapReady(final MapboxMap map) {
mapboxMap = map;
- try {
- // read local geojson from raw folder
- String tinyCountriesJson = ResourceUtils.readRawResource(this, R.raw.tiny_countries);
-
- // convert geojson to a model
- FeatureCollection featureCollection = new GsonBuilder()
- .registerTypeAdapter(Geometry.class, new GeometryDeserializer())
- .registerTypeAdapter(Position.class, new PositionDeserializer())
- .create().fromJson(tinyCountriesJson, FeatureCollection.class);
-
- // add a geojson to the map
- Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
- mapboxMap.addSource(source);
-
- // for each feature add a symbolLayer
- for (Feature feature : featureCollection.getFeatures()) {
- String countryName = feature.getStringProperty(FEATURE_ID);
-
- // create View
- TextView textView = new TextView(this);
- textView.setBackgroundColor(getResources().getColor(R.color.blueAccent));
- textView.setPadding(10, 5, 10, 5);
- textView.setTextColor(Color.WHITE);
- textView.setText(countryName);
-
- // create bitmap from view
- mapboxMap.addImage(countryName, SymbolGenerator.generate(textView));
- }
-
- // create layer use
- mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
- .withProperties(
- iconImage("{" + FEATURE_ID + "}"), // { } is a token notation
- iconAllowOverlap(false)
- )
- );
-
- addSymbolClickListener();
- } catch (IOException exception) {
- Timber.e(exception);
- }
+ addSymbolClickListener();
+ new LoadDataTask(map, SymbolGeneratorActivity.this).execute();
}
private void addSymbolClickListener() {
@@ -213,4 +175,91 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
return bitmap;
}
}
-}
+
+ private static class LoadDataTask extends AsyncTask<Void, Void, FeatureCollection> {
+
+ private final MapboxMap mapboxMap;
+ private final Context context;
+
+ LoadDataTask(MapboxMap mapboxMap, Context context) {
+ this.mapboxMap = mapboxMap;
+ this.context = context;
+ }
+
+ @Override
+ protected FeatureCollection doInBackground(Void... params) {
+ try {
+ // read local geojson from raw folder
+ String tinyCountriesJson = ResourceUtils.readRawResource(context, R.raw.tiny_countries);
+
+ // convert geojson to a model
+ FeatureCollection featureCollection = new GsonBuilder()
+ .registerTypeAdapter(Geometry.class, new GeometryDeserializer())
+ .registerTypeAdapter(Position.class, new PositionDeserializer())
+ .create().fromJson(tinyCountriesJson, FeatureCollection.class);
+
+ return featureCollection;
+ } catch (IOException exception) {
+ return null;
+ }
+ }
+
+
+ @Override
+ protected void onPostExecute(FeatureCollection featureCollection) {
+ super.onPostExecute(featureCollection);
+ if (featureCollection == null) {
+ return;
+ }
+
+ // add a geojson to the map
+ Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
+ mapboxMap.addSource(source);
+
+ // create layer use
+ mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
+ .withProperties(
+ iconImage("{" + FEATURE_ID + "}"), // { } is a token notation
+ iconAllowOverlap(false)
+ )
+ );
+
+ new GenerateSymbolTask(mapboxMap, context).execute(featureCollection);
+ }
+ }
+
+ private static class GenerateSymbolTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
+
+ private MapboxMap mapboxMap;
+ private Context context;
+
+ GenerateSymbolTask(MapboxMap mapboxMap, Context context) {
+ this.mapboxMap = mapboxMap;
+ this.context = context;
+ }
+
+ @SuppressWarnings("WrongThread")
+ @Override
+ protected HashMap<String, Bitmap> doInBackground(FeatureCollection... params) {
+ FeatureCollection featureCollection = params[0];
+
+ HashMap<String, Bitmap> imagesMap = new HashMap<>();
+ for (Feature feature : featureCollection.getFeatures()) {
+ String countryName = feature.getStringProperty(FEATURE_ID);
+ TextView textView = new TextView(context);
+ textView.setBackgroundColor(context.getResources().getColor(R.color.blueAccent));
+ textView.setPadding(10, 5, 10, 5);
+ textView.setTextColor(Color.WHITE);
+ textView.setText(countryName);
+ imagesMap.put(countryName, SymbolGenerator.generate(textView));
+ }
+ return imagesMap;
+ }
+
+ @Override
+ protected void onPostExecute(HashMap<String, Bitmap> bitmapHashMap) {
+ super.onPostExecute(bitmapHashMap);
+ mapboxMap.addImages(bitmapHashMap);
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
index 95c3929c1d..abfd7ae529 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
@@ -12,6 +12,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.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
@@ -32,6 +33,7 @@ import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;
/**
* Test activity showcasing changing the icon with a zoom function and adding selection state to a SymbolLayer.
@@ -49,9 +51,11 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
private MapView mapView;
private MapboxMap mapboxMap;
private GeoJsonSource source;
+ private SymbolLayer layer;
private boolean isInitialPosition = true;
private boolean isSelected = false;
+ private boolean isShowingSymbolLayer = true;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -81,6 +85,13 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
}
}
+ private void toggleSymbolLayerVisibility() {
+ layer.setProperties(
+ visibility(isShowingSymbolLayer ? Property.NONE : Property.VISIBLE)
+ );
+ isShowingSymbolLayer = !isShowingSymbolLayer;
+ }
+
private FeatureCollection createFeatureCollection() {
Position position = isInitialPosition
? Position.fromCoordinates(-74.01618140, 40.701745)
@@ -95,7 +106,7 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
}
private void addLayer() {
- SymbolLayer layer = new SymbolLayer(LAYER_ID, SOURCE_ID);
+ layer = new SymbolLayer(LAYER_ID, SOURCE_ID);
layer.setProperties(
iconImage(
zoom(
@@ -145,9 +156,13 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- if (mapboxMap != null && item.getItemId() == R.id.menu_action_change_location) {
- isInitialPosition = !isInitialPosition;
- updateSource();
+ if (mapboxMap != null) {
+ if (item.getItemId() == R.id.menu_action_change_location) {
+ isInitialPosition = !isInitialPosition;
+ updateSource();
+ } else if (item.getItemId() == R.id.menu_action_toggle_source) {
+ toggleSymbolLayerVisibility();
+ }
}
return super.onOptionsItemSelected(item);
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animator.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animator.xml
index d4933bfb9a..cb14aab91f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animator.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_camera_animator.xml
@@ -10,8 +10,8 @@
android:id="@id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:mapbox_cameraTargetLat="37.774913"
- app:mapbox_cameraTargetLng="-122.419368"
+ app:mapbox_cameraTargetLat="37.787947"
+ app:mapbox_cameraTargetLng="-122.407432"
app:mapbox_cameraZoom="11"
app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"/>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_animator.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_animator.xml
new file mode 100644
index 0000000000..db5a62d2cb
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_animator.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">
+ <item
+ android:id="@+id/menu_action_accelerate_decelerate_interpolator"
+ android:title="@string/menuitem_title_accelerate_decelerate"
+ app:showAsAction="never"/>
+ <item
+ android:id="@+id/menu_action_bounce_interpolator"
+ android:title="@string/menuitem_title_bounce"
+ app:showAsAction="never"/>
+ <item
+ android:id="@+id/menu_action_anticipate_overshoot_interpolator"
+ android:title="@string/menuitem_title_anticipate_overshoot"
+ app:showAsAction="never"/>
+ <item
+ android:id="@+id/menu_action_path_interpolator"
+ android:title="@string/menuitem_title_path"
+ app:showAsAction="never"/>
+</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbols.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbols.xml
index 3e5c8ab14c..7f3c44262d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbols.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_symbols.xml
@@ -5,4 +5,8 @@
android:id="@+id/menu_action_change_location"
android:title="@string/menuitem_change_location"
app:showAsAction="never"/>
+ <item
+ android:id="@+id/menu_action_toggle_source"
+ android:title="@string/menuitem_toggle_symbol_layer_visibility"
+ app:showAsAction="never"/>
</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
index 4ca19def71..5c0828ab74 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
@@ -12,6 +12,11 @@
<string name="menuitem_title_change_location_source_null">Reset location source to null</string>
<string name="menuitem_change_icon_overlap">Toggle icon overlap</string>
<string name="menuitem_change_location">Change location</string>
+ <string name="menuitem_title_accelerate_decelerate">Accelerate/Decelerate interpolator</string>
+ <string name="menuitem_title_bounce">Bounce interpolator</string>
+ <string name="menuitem_title_anticipate_overshoot">Anticipate/Overshoot interpolator</string>
+ <string name="menuitem_title_path">PathInterpolator interpolator</string>
+ <string name="menuitem_toggle_symbol_layer_visibility">Toggle Symbol Layer Visibility</string>
<string name="button_camera_move">Move</string>
<string name="button_camera_ease">Ease</string>
<string name="button_camera_animate">Animate</string>
diff --git a/platform/android/build.gradle b/platform/android/build.gradle
index e298b84da8..f3301d0b5a 100644
--- a/platform/android/build.gradle
+++ b/platform/android/build.gradle
@@ -4,8 +4,6 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
- classpath 'com.amazonaws:aws-devicefarm-gradle-plugin:1.2'
- classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.1'
}
}
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 4af7a4293d..b3888a9418 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -142,6 +142,8 @@ add_library(mbgl-android STATIC
platform/android/src/style/conversion/types_string_values.hpp
platform/android/src/map/camera_position.cpp
platform/android/src/map/camera_position.hpp
+ platform/android/src/map/image.cpp
+ platform/android/src/map/image.hpp
# Style conversion Java -> C++
platform/android/src/style/android_conversion.hpp
diff --git a/platform/android/dependencies.gradle b/platform/android/dependencies.gradle
index 650cf38952..8d4c32045c 100644
--- a/platform/android/dependencies.gradle
+++ b/platform/android/dependencies.gradle
@@ -27,7 +27,6 @@ ext {
mockito : 'org.mockito:mockito-core:2.10.0',
// instrumentation test
- testSpoonRunner : 'com.squareup.spoon:spoon-client:1.7.1',
testRunner : "com.android.support.test:runner:${testRunnerVersion}",
testRules : "com.android.support.test:rules:${testRunnerVersion}",
testEspressoCore : "com.android.support.test.espresso:espresso-core:${espressoVersion}",
@@ -36,7 +35,7 @@ ext {
// support
supportAnnotations : "com.android.support:support-annotations:${supportLibVersion}",
supportAppcompatV7 : "com.android.support:appcompat-v7:${supportLibVersion}",
- supportV4 : "com.android.support:support-v4:${supportLibVersion}",
+ supportFragmentV4 : "com.android.support:support-fragment:${supportLibVersion}",
supportDesign : "com.android.support:design:${supportLibVersion}",
supportRecyclerView : "com.android.support:recyclerview-v7:${supportLibVersion}",
diff --git a/platform/android/scripts/exclude-activity-gen.json b/platform/android/scripts/exclude-activity-gen.json
new file mode 100644
index 0000000000..f05001c6ae
--- /dev/null
+++ b/platform/android/scripts/exclude-activity-gen.json
@@ -0,0 +1,31 @@
+[
+ "BaseLocationActivity",
+ "MapSnapshotterMarkerActivity",
+ "MapSnapshotterReuseActivity",
+ "LatLngBoundsActivity",
+ "BottomSheetActivity",
+ "MapSnapshotterActivity",
+ "MockLocationEngine",
+ "DeleteRegionActivity",
+ "RealTimeGeoJsonActivity",
+ "UpdateMetadataActivity",
+ "CarDrivingActivity",
+ "MyLocationTrackingModeActivity",
+ "MyLocationToggleActivity",
+ "MyLocationTintActivity",
+ "MyLocationDrawableActivity",
+ "DoubleMapActivity",
+ "LocationPickerActivity",
+ "GeoJsonClusteringActivity",
+ "RuntimeStyleTestActivity",
+ "AnimatedMarkerActivity",
+ "ViewPagerActivity",
+ "MapFragmentActivity",
+ "SupportMapFragmentActivity",
+ "SnapshotActivity",
+ "NavigationDrawerActivity",
+ "QueryRenderedFeaturesBoxHighlightActivity",
+ "MultiMapActivity",
+ "MapInDialogActivity",
+ "SimpleMapActivity"
+] \ No newline at end of file
diff --git a/platform/android/scripts/generate-test-code.js b/platform/android/scripts/generate-test-code.js
index 01a294a301..e27de7e40b 100644
--- a/platform/android/scripts/generate-test-code.js
+++ b/platform/android/scripts/generate-test-code.js
@@ -13,8 +13,7 @@ global.camelize = function (str) {
});
}
-
-const excludeActivities = ["BaseLocationActivity","MockLocationEngine","DeleteRegionActivity","RealTimeGeoJsonActivity","UpdateMetadataActivity","CarDrivingActivity","MyLocationTrackingModeActivity","MyLocationToggleActivity","MyLocationTintActivity","MyLocationDrawableActivity","DoubleMapActivity", "LocationPickerActivity","GeoJsonClusteringActivity","RuntimeStyleTestActivity", "AnimatedMarkerActivity", "ViewPagerActivity","MapFragmentActivity","SupportMapFragmentActivity","SnapshotActivity","NavigationDrawerActivity", "QueryRenderedFeaturesBoxHighlightActivity", "MultiMapActivity", "MapInDialogActivity", "SimpleMapActivity"];
+const excludeClasses = JSON.parse(fs.readFileSync('platform/android/scripts/exclude-activity-gen.json', 'utf8'));
const appBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity';
const testBasePath = 'platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/activity/gen';
const subPackages = fs.readdirSync(appBasePath);
@@ -24,7 +23,9 @@ if (!fs.existsSync(testBasePath)){
fs.mkdirSync(testBasePath);
}
-console.log("Generating test activities:");
+console.log("\nGenerating test activities:\n");
+var generatedClasses = [];
+var excludedClasses = [];
for(const subPackage of subPackages) {
if(!(subPackage.slice(-5) == '.java')) {
const activities = fs.readdirSync(appBasePath+'/'+subPackage);
@@ -45,18 +46,22 @@ for(const subPackage of subPackages) {
try {
fs.accessSync(filePath, fs.F_OK);
fs.unlinkSync(filePath);
- console.log("Removed file: "+filePath);
} catch (e) {
- console.log("No file found: "+filePath);
}
- // only generate test file if not part of exclude list
- if (!(excludeActivities.indexOf(activityName) > -1)) {
- console.log("Created file: "+filePath);
+ // only generate test file if not part of exclude list + if contains Activity in name
+ if ((!(excludeClasses.indexOf(activityName) > -1)) && activityName.includes("Activity")) {
fs.writeFileSync(filePath, ejsConversionTask([activityName, subPackage]));
+ generatedClasses.push(activityName);
}else{
- console.log("Excluding file: "+filePath);
+ excludedClasses.push(activityName);
}
}
}
}
+
+for(const generatedClass of generatedClasses){
+ console.log(generatedClass+"Test");
+}
+
+console.log("\nFinished generating " + generatedClasses.length + " activity sanity tests, excluded " + excludeClasses.length + " classes.\n"); \ No newline at end of file
diff --git a/platform/android/src/android_renderer_frontend.cpp b/platform/android/src/android_renderer_frontend.cpp
index b80e23e21f..afdb08a10e 100644
--- a/platform/android/src/android_renderer_frontend.cpp
+++ b/platform/android/src/android_renderer_frontend.cpp
@@ -112,6 +112,11 @@ AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& bo
return mapRenderer.actor().ask(&Renderer::queryPointAnnotations, box).get();
}
+AnnotationIDs AndroidRendererFrontend::queryShapeAnnotations(const ScreenBox& box) const {
+ // Waits for the result from the orchestration thread and returns
+ return mapRenderer.actor().ask(&Renderer::queryShapeAnnotations, box).get();
+}
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/android_renderer_frontend.hpp b/platform/android/src/android_renderer_frontend.hpp
index 94508fd816..178870c452 100644
--- a/platform/android/src/android_renderer_frontend.hpp
+++ b/platform/android/src/android_renderer_frontend.hpp
@@ -36,6 +36,7 @@ public:
std::vector<Feature> queryRenderedFeatures(const ScreenBox&, const RenderedQueryOptions&) const;
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
+ AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
// Memory
void onLowMemory();
diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp
index 262e3d3c6a..a576661a4f 100644
--- a/platform/android/src/file_source.cpp
+++ b/platform/android/src/file_source.cpp
@@ -8,8 +8,6 @@
#include "asset_manager_file_source.hpp"
#include "jni/generic_global_ref_deleter.hpp"
-#include <string>
-
namespace mbgl {
namespace android {
@@ -64,6 +62,14 @@ void FileSource::setResourceTransform(jni::JNIEnv& env, jni::Object<FileSource::
}
}
+void FileSource::resume(jni::JNIEnv&) {
+ fileSource->resume();
+}
+
+void FileSource::pause(jni::JNIEnv&) {
+ fileSource->pause();
+}
+
jni::Class<FileSource> FileSource::javaClass;
FileSource* FileSource::getNativePeer(jni::JNIEnv& env, jni::Object<FileSource> jFileSource) {
@@ -93,7 +99,9 @@ void FileSource::registerNative(jni::JNIEnv& env) {
METHOD(&FileSource::getAccessToken, "getAccessToken"),
METHOD(&FileSource::setAccessToken, "setAccessToken"),
METHOD(&FileSource::setAPIBaseUrl, "setApiBaseUrl"),
- METHOD(&FileSource::setResourceTransform, "setResourceTransform")
+ METHOD(&FileSource::setResourceTransform, "setResourceTransform"),
+ METHOD(&FileSource::resume, "resume"),
+ METHOD(&FileSource::pause, "pause")
);
}
diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp
index 4abe352bff..2933aedf86 100644
--- a/platform/android/src/file_source.hpp
+++ b/platform/android/src/file_source.hpp
@@ -41,6 +41,10 @@ public:
void setResourceTransform(jni::JNIEnv&, jni::Object<FileSource::ResourceTransformCallback>);
+ void resume(jni::JNIEnv&);
+
+ void pause(jni::JNIEnv&);
+
static jni::Class<FileSource> javaClass;
static FileSource* getNativePeer(jni::JNIEnv&, jni::Object<FileSource>);
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index f39aeb6374..f4e5734861 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -172,6 +172,7 @@ void registerNatives(JavaVM *vm) {
// Map
CameraPosition::registerNative(env);
+ Image::registerNative(env);
// Connectivity
ConnectivityListener::registerNative(env);
diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp
new file mode 100644
index 0000000000..5f5c90eddd
--- /dev/null
+++ b/platform/android/src/map/image.cpp
@@ -0,0 +1,44 @@
+#include <mbgl/style/image.hpp>
+#include <mbgl/util/exception.hpp>
+#include "image.hpp"
+
+namespace mbgl {
+namespace android {
+
+mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object<Image> image) {
+ static auto widthField = Image::javaClass.GetField<jni::jint>(env, "width");
+ static auto heightField = Image::javaClass.GetField<jni::jint>(env, "height");
+ static auto pixelRatioField = Image::javaClass.GetField<jni::jfloat>(env, "pixelRatio");
+ static auto bufferField = Image::javaClass.GetField<jni::Array<jbyte>>(env, "buffer");
+ static auto nameField = Image::javaClass.GetField<jni::String>(env, "name");
+
+ auto height = image.Get(env, heightField);
+ auto width = image.Get(env, widthField);
+ auto pixelRatio = image.Get(env, pixelRatioField);
+ auto pixels = image.Get(env, bufferField);
+ auto name = jni::Make<std::string>(env, image.Get(env, nameField));
+
+ jni::NullCheck(env, &pixels);
+ std::size_t size = pixels.Length(env);
+
+ mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
+ if (premultipliedImage.bytes() != uint32_t(size)) {
+ throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
+ }
+
+ jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
+
+ return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio};
+}
+
+void Image::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ Image::javaClass = *jni::Class<Image>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Image> Image::javaClass;
+
+
+} // namespace android
+} // namespace mb
+
diff --git a/platform/android/src/map/image.hpp b/platform/android/src/map/image.hpp
new file mode 100644
index 0000000000..1513e13ee7
--- /dev/null
+++ b/platform/android/src/map/image.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+
+#include <jni/jni.hpp>
+#include <mbgl/style/image.hpp>
+
+namespace mbgl {
+namespace android {
+
+class Image : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "com/mapbox/mapboxsdk/maps/Image"; };
+
+ static mbgl::style::Image getImage(jni::JNIEnv&, jni::Object<Image>);
+
+ static jni::Class<Image> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+
+};
+
+
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 24a35a7068..04cbb21927 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -49,6 +49,7 @@
#include "java/util.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "map/camera_position.hpp"
+#include "map/image.hpp"
#include "style/light.hpp"
#include "bitmap_factory.hpp"
@@ -633,6 +634,26 @@ jni::Array<jlong> NativeMapView::queryPointAnnotations(JNIEnv& env, jni::Object<
return result;
}
+jni::Array<jlong> NativeMapView::queryShapeAnnotations(JNIEnv &env, jni::Object<RectF> rect) {
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ // Convert input
+ mbgl::ScreenBox box = {
+ {RectF::getLeft(env, rect), RectF::getTop(env, rect)},
+ {RectF::getRight(env, rect), RectF::getBottom(env, rect)},
+ };
+
+ mbgl::AnnotationIDs ids = rendererFrontend->queryShapeAnnotations(box);
+
+ // Convert result
+ std::vector<jlong> longIds(ids.begin(), ids.end());
+ auto result = jni::Array<jni::jlong>::New(env, ids.size());
+ result.SetRegion<std::vector<jni::jlong>>(env, 0, longIds);
+
+ return result;
+}
+
jni::Array<jni::Object<geojson::Feature>> NativeMapView::queryRenderedFeaturesForPoint(JNIEnv& env, jni::jfloat x, jni::jfloat y,
jni::Array<jni::String> layerIds,
jni::Array<jni::Object<>> jfilter) {
@@ -904,6 +925,18 @@ void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::ji
float(scale)));
}
+void NativeMapView::addImages(JNIEnv& env, jni::Array<jni::Object<mbgl::android::Image>> jimages) {
+ jni::NullCheck(env, &jimages);
+ std::size_t len = jimages.Length(env);
+
+ for (std::size_t i = 0; i < len; i++) {
+ jni::Object<mbgl::android::Image> jimage = jimages.Get(env, i);
+ auto image = mbgl::android::Image::getImage(env, jimage);
+ map->getStyle().addImage(std::make_unique<mbgl::style::Image>(image));
+ jni::DeleteLocalRef(env, jimage);
+ }
+}
+
void NativeMapView::removeImage(JNIEnv& env, jni::String name) {
map->getStyle().removeImage(jni::Make<std::string>(env, name));
}
@@ -1000,6 +1033,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::getTransitionDelay, "nativeGetTransitionDelay"),
METHOD(&NativeMapView::setTransitionDelay, "nativeSetTransitionDelay"),
METHOD(&NativeMapView::queryPointAnnotations, "nativeQueryPointAnnotations"),
+ METHOD(&NativeMapView::queryShapeAnnotations, "nativeQueryShapeAnnotations"),
METHOD(&NativeMapView::queryRenderedFeaturesForPoint, "nativeQueryRenderedFeaturesForPoint"),
METHOD(&NativeMapView::queryRenderedFeaturesForBox, "nativeQueryRenderedFeaturesForBox"),
METHOD(&NativeMapView::getLight, "nativeGetLight"),
@@ -1017,6 +1051,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) {
METHOD(&NativeMapView::removeSourceById, "nativeRemoveSourceById"),
METHOD(&NativeMapView::removeSource, "nativeRemoveSource"),
METHOD(&NativeMapView::addImage, "nativeAddImage"),
+ METHOD(&NativeMapView::addImages, "nativeAddImages"),
METHOD(&NativeMapView::removeImage, "nativeRemoveImage"),
METHOD(&NativeMapView::getImage, "nativeGetImage"),
METHOD(&NativeMapView::setLatLngBounds, "nativeSetLatLngBounds"),
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 4d226d0fa9..d7e3b17b99 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -22,6 +22,7 @@
#include "style/sources/sources.hpp"
#include "geometry/lat_lng_bounds.hpp"
#include "map/camera_position.hpp"
+#include "map/image.hpp"
#include "style/light.hpp"
#include "bitmap.hpp"
@@ -197,6 +198,8 @@ public:
jni::Array<jlong> queryPointAnnotations(JNIEnv&, jni::Object<RectF>);
+ jni::Array<jlong> queryShapeAnnotations(JNIEnv&, jni::Object<RectF>);
+
jni::Array<jni::Object<geojson::Feature>> queryRenderedFeaturesForPoint(JNIEnv&, jni::jfloat, jni::jfloat,
jni::Array<jni::String>,
jni::Array<jni::Object<>> jfilter);
@@ -235,6 +238,8 @@ public:
void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array<jbyte>);
+ void addImages(JNIEnv&, jni::Array<jni::Object<mbgl::android::Image>>);
+
void removeImage(JNIEnv&, jni::String);
jni::Object<Bitmap> getImage(JNIEnv&, jni::String);