From caef1785eb8bb5471ccfbd6a8327888513818134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 12 Mar 2016 11:32:52 -0800 Subject: [PATCH 001/104] [ios, osx] Removed pack nil check from MGLOfflineRegionObserver Due to ARC, MGLOfflinePack can be deallocated at any time following its initialization. -dealloc ensures that the offline region observer is unset, but that step is asynchronous; there is no guarantee that it completes before the first status change update. In fact, the pack is deallocated before the first status change update unless it is captured outside of the MGLOfflinePackAdditionCompletionHandler. The pack nil check is unnecessary because the subsequent code would be a no-op. --- platform/darwin/src/MGLOfflinePack.mm | 6 ------ 1 file changed, 6 deletions(-) diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index c6e483e6d..42bd871e5 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -189,16 +189,12 @@ NSError *MGLErrorFromResponseError(mbgl::Response::Error error) { void MBGLOfflineRegionObserver::statusChanged(mbgl::OfflineRegionStatus status) { dispatch_async(dispatch_get_main_queue(), ^{ - NSCAssert(pack, @"MBGLOfflineRegionObserver is dangling without an associated MGLOfflinePack."); - [pack offlineRegionStatusDidChange:status]; }); } void MBGLOfflineRegionObserver::responseError(mbgl::Response::Error error) { dispatch_async(dispatch_get_main_queue(), ^{ - NSCAssert(pack, @"MBGLOfflineRegionObserver is dangling without an associated MGLOfflinePack."); - if ([pack.delegate respondsToSelector:@selector(offlinePack:didReceiveError:)]) { [pack.delegate offlinePack:pack didReceiveError:MGLErrorFromResponseError(error)]; } @@ -207,8 +203,6 @@ void MBGLOfflineRegionObserver::responseError(mbgl::Response::Error error) { void MBGLOfflineRegionObserver::mapboxTileCountLimitExceeded(uint64_t limit) { dispatch_async(dispatch_get_main_queue(), ^{ - NSCAssert(pack, @"MBGLOfflineRegionObserver is dangling without an associated MGLOfflinePack."); - if ([pack.delegate respondsToSelector:@selector(offlinePack:didReceiveMaximumAllowedMapboxTiles:)]) { [pack.delegate offlinePack:pack didReceiveMaximumAllowedMapboxTiles:limit]; } From ac541290607e968343490c046e0d4e5f48471bba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 12 Mar 2016 15:04:44 -0800 Subject: [PATCH 002/104] [ios, osx] Allow null completion handlers in MGLOfflineStorage Cherry-picked from f6c21a0efebbda69591fa922de4af96c59933d2f. --- platform/darwin/include/MGLOfflineStorage.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/darwin/include/MGLOfflineStorage.h b/platform/darwin/include/MGLOfflineStorage.h index 022c1f0a1..4f3432163 100644 --- a/platform/darwin/include/MGLOfflineStorage.h +++ b/platform/darwin/include/MGLOfflineStorage.h @@ -66,7 +66,7 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac @param completion The completion handler to call once the pack has been added. This handler is executed asynchronously on the main queue. */ -- (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion; +- (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(nullable MGLOfflinePackAdditionCompletionHandler)completion; /** Unregisters the given offline pack and frees any resources that are no longer @@ -82,7 +82,7 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac @param completion The completion handler to call once the pack has been removed. This handler is executed asynchronously on the main queue. */ -- (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(MGLOfflinePackRemovalCompletionHandler)completion; +- (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(nullable MGLOfflinePackRemovalCompletionHandler)completion; /** Asynchronously calls a completion callback with all existing offline packs. From 922269cd7c543df6b5e2b2c649e72099d9320262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 12 Mar 2016 15:08:34 -0800 Subject: [PATCH 003/104] [ios] Immediately remove offline pack from table Remove all references to an offline pack before the call to -removePackWithCompletionHander:. Cherry-picked from d64b8ad25ca7c2297221337d4021924b5103cc77. --- platform/ios/app/MBXOfflinePacksTableViewController.m | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index 32e4bfea0..3410f075a 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -164,12 +164,9 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; - __weak MBXOfflinePacksTableViewController *weakSelf = self; - [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError *error) { - MBXOfflinePacksTableViewController *strongSelf = weakSelf; - [strongSelf.offlinePacks removeObjectAtIndex:indexPath.row]; - [strongSelf.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; - }]; + [self.offlinePacks removeObjectAtIndex:indexPath.row]; + [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:nil]; } } From e04fea8409714c6c4c055b95ddfc67122a2b860d Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 14 Mar 2016 15:10:45 -0400 Subject: [PATCH 004/104] [android] #4304 - logo visibility fix for attributes defined in xml --- .../com/mapbox/mapboxsdk/maps/MapboxMapOptions.java | 4 ++-- .../src/main/res/values/attrs.xml | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java index 941d2f1c6..6b7a0db8b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java @@ -130,14 +130,14 @@ public class MapboxMapOptions implements Parcelable { , ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_right, DIMENSION_TEN_DP * screenDensity)) , ((int) typedArray.getDimension(R.styleable.MapView_compass_margin_bottom, DIMENSION_TEN_DP * screenDensity))}); - mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.MapView_logo_visibility, true)); + mapboxMapOptions.logoEnabled(typedArray.getBoolean(R.styleable.MapView_logo_enabled, true)); mapboxMapOptions.logoGravity(typedArray.getInt(R.styleable.MapView_logo_gravity, Gravity.BOTTOM | Gravity.START)); mapboxMapOptions.logoMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_logo_margin_left, DIMENSION_SIXTEEN_DP) * screenDensity) , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_top, DIMENSION_SIXTEEN_DP) * screenDensity) , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_right, DIMENSION_SIXTEEN_DP) * screenDensity) , (int) (typedArray.getDimension(R.styleable.MapView_logo_margin_bottom, DIMENSION_SIXTEEN_DP) * screenDensity)}); - mapboxMapOptions.attributionEnabled(typedArray.getBoolean(R.styleable.MapView_attribution_visibility, true)); + mapboxMapOptions.attributionEnabled(typedArray.getBoolean(R.styleable.MapView_attribution_enabled, true)); mapboxMapOptions.attributionGravity(typedArray.getInt(R.styleable.MapView_attribution_gravity, Gravity.BOTTOM)); mapboxMapOptions.attributionMargins(new int[]{(int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_left, DIMENSION_SEVENTY_SIX_DP) * screenDensity) , (int) (typedArray.getDimension(R.styleable.MapView_attribution_margin_top, DIMENSION_SEVEN_DP) * screenDensity) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml index f516e98dd..a6e1f044c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml +++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml @@ -59,11 +59,8 @@ - - - - - + + @@ -84,10 +81,6 @@ - - - - - + From 6f86bee283d803581e8901977b825d5c0cd3a9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 14 Mar 2016 12:08:21 -0700 Subject: [PATCH 005/104] [ios] Only set preferred action on iOS 9+ Fixed a crash on iOS 8 when presenting the Add Offline Pack dialog. Fixes #4305. --- platform/ios/app/MBXOfflinePacksTableViewController.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index 3410f075a..fb9d5fb3e 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -100,7 +100,9 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac }]; }]; [alertController addAction:downloadAction]; - alertController.preferredAction = downloadAction; + if ([alertController respondsToSelector:@selector(setPreferredAction:)]) { + alertController.preferredAction = downloadAction; + } [self presentViewController:alertController animated:YES completion:nil]; } From 76bb6b8746daafd038484039396e6b9adffabc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 14 Mar 2016 15:38:19 -0700 Subject: [PATCH 006/104] ios-v3.2.0-pre.3 --- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 08e27053c..984763874 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.2.0-pre.2-symbols' + m.version = '3.2.0-pre.3-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' From 4a042a939ed1f0294e2182257dd850cc6cf54d55 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 15 Mar 2016 10:58:24 -0400 Subject: [PATCH 007/104] [android] #4317 - Updating release version and fabric version to 4.0.0-beta.1 --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- .../fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 0e3858644..126d8bbc5 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-SNAPSHOT +VERSION_NAME=4.0.0-beta.1 POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native diff --git a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties index 353943059..d524fe998 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties +++ b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties @@ -1,3 +1,3 @@ fabric-identifier=com.mapbox.mapboxsdk.mapbox-android-sdk -fabric-version=3.2.0 +fabric-version=4.0.0-beta.1 fabric-build-type=binary From f823021e0de489fe6974779fe4d57a9344fd4fc8 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 15 Mar 2016 12:02:37 -0400 Subject: [PATCH 008/104] [android] #4317 - Adding 4.0.0-beta.1 to CHANGELOG --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e041e6ec6..b11fdff49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Android +## 4.0.0-beta.1 + +Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major new features being released. To help us produce the highest quality SDK possible we're releasing an official Beta release first so that everyone has time to explore it and help hardened it before the official 4.0.0 Final Release. + +* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145) +* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891) +* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421) + ## 3.2.0 * Fixed crash caused by annotation image with non-integer width or height ([#3031](https://github.com/mapbox/mapbox-gl-native/issues/3031)) From 93123e4d0eb0e5b4f95a6d7d92395b0cc2c48755 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 15 Mar 2016 11:59:57 -0400 Subject: [PATCH 009/104] [android] #4318 - move min/max zoom level to MapboxMap --- .../mapboxsdk/camera/CameraUpdateFactory.java | 2 +- .../com/mapbox/mapboxsdk/maps/MapView.java | 4 +- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 76 +++++++++++++++++++ .../com/mapbox/mapboxsdk/maps/UiSettings.java | 67 ---------------- .../mapboxsdk/testapp/MaxMinZoomActivity.java | 7 +- .../mapboxsdk/testapp/OfflineActivity.java | 3 +- .../mapbox/mapboxsdk/maps/MapboxMapTest.java | 41 +++++++--- .../mapbox/mapboxsdk/maps/UiSettingsTest.java | 24 ------ 8 files changed, 113 insertions(+), 111 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java index acec8f17f..763ab8d66 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java @@ -250,7 +250,7 @@ public final class CameraUpdateFactory { float scaleY = (uiSettings.getHeight() - padding.top - padding.bottom) / height; float minScale = scaleX < scaleY ? scaleX : scaleY; double zoom = projection.calculateZoom(minScale); - zoom = MathUtils.clamp(zoom, (float) uiSettings.getMinZoom(), (float) uiSettings.getMaxZoom()); + zoom = MathUtils.clamp(zoom, (float) mapboxMap.getMinZoom(), (float) mapboxMap.getMaxZoom()); // Calculate the center point PointF paddedNEPixel = new PointF(nePixel.x + padding.right / minScale, nePixel.y + padding.top / minScale); 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 92a815a39..a9ae39972 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 @@ -265,8 +265,8 @@ public class MapView extends FrameLayout { uiSettings.setZoomControlsEnabled(options.getZoomControlsEnabled()); // Zoom - uiSettings.setMaxZoom(options.getMaxZoom()); - uiSettings.setMinZoom(options.getMinZoom()); + mMapboxMap.setMaxZoom(options.getMaxZoom()); + mMapboxMap.setMinZoom(options.getMinZoom()); // Compass uiSettings.setCompassEnabled(options.getCompassEnabled()); 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 fbeefd6ef..432dc0ae8 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 @@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.maps; import android.location.Location; import android.os.SystemClock; +import android.support.annotation.FloatRange; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.UiThread; @@ -72,6 +73,9 @@ public class MapboxMap { private MapboxMap.OnFpsChangedListener mOnFpsChangedListener; private MapboxMap.OnCameraChangeListener mOnCameraChangeListener; + private double mMaxZoomLevel = -1; + private double mMinZoomLevel = -1; + MapboxMap(@NonNull MapView mapView) { mMapView = mapView; mMapView.addOnMapChangedListener(new MapChangeCameraPositionListener()); @@ -83,6 +87,78 @@ public class MapboxMap { mInfoWindows = new ArrayList<>(); } + // + // MinZoom + // + + /** + *

+ * Sets the minimum zoom level the map can be displayed at. + *

+ * + * @param minZoom The new minimum zoom level. + */ + @UiThread + public void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { + if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Log.e(MapboxConstants.TAG, "Not setting minZoom, value is in unsupported range: " + minZoom); + return; + } + mMinZoomLevel = minZoom; + mMapView.setMinZoom(minZoom); + } + + /** + *

+ * Gets the maximum zoom level the map can be displayed at. + *

+ * + * @return The minimum zoom level. + */ + @UiThread + public double getMinZoom() { + if (mMinZoomLevel == -1) { + return mMinZoomLevel = mMapView.getMinZoom(); + } + return mMinZoomLevel; + } + + // + // MaxZoom + // + + /** + *

+ * Sets the maximum zoom level the map can be displayed at. + *

+ * + * @param maxZoom The new maximum zoom level. + */ + @UiThread + public void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { + if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { + Log.e(MapboxConstants.TAG, "Not setting maxZoom, value is in unsupported range: " + maxZoom); + return; + } + mMaxZoomLevel = maxZoom; + mMapView.setMaxZoom(maxZoom); + } + + /** + *

+ * Gets the maximum zoom level the map can be displayed at. + *

+ * + * @return The maximum zoom level. + */ + @UiThread + public double getMaxZoom() { + if (mMaxZoomLevel == -1) { + return mMaxZoomLevel = mMapView.getMaxZoom(); + } + return mMaxZoomLevel; + } + // // UiSettings // diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java index 4c2502cdb..f87ddb4ca 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java @@ -26,9 +26,6 @@ public class UiSettings { private boolean zoomControlsEnabled; private boolean scrollGesturesEnabled; - private double maxZoomLevel = -1; - private double minZoomLevel = -1; - UiSettings(@NonNull MapView mapView) { this.mapView = mapView; this.compassSettings = new ViewSettings(); @@ -36,70 +33,6 @@ public class UiSettings { this.attributionSettings = new ViewSettings(); } - /** - *

- * Sets the minimum zoom level the map can be displayed at. - *

- * - * @param minZoom The new minimum zoom level. - */ - @UiThread - public void setMinZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double minZoom) { - if ((minZoom < MapboxConstants.MINIMUM_ZOOM) || (minZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Log.e(MapboxConstants.TAG, "Not setting minZoom, value is in unsupported range: " + minZoom); - return; - } - minZoomLevel = minZoom; - mapView.setMinZoom(minZoom); - } - - /** - *

- * Gets the maximum zoom level the map can be displayed at. - *

- * - * @return The minimum zoom level. - */ - @UiThread - public double getMinZoom() { - if (minZoomLevel == -1) { - return minZoomLevel = mapView.getMinZoom(); - } - return minZoomLevel; - } - - /** - *

- * Sets the maximum zoom level the map can be displayed at. - *

- * - * @param maxZoom The new maximum zoom level. - */ - @UiThread - public void setMaxZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double maxZoom) { - if ((maxZoom < MapboxConstants.MINIMUM_ZOOM) || (maxZoom > MapboxConstants.MAXIMUM_ZOOM)) { - Log.e(MapboxConstants.TAG, "Not setting maxZoom, value is in unsupported range: " + maxZoom); - return; - } - maxZoomLevel = maxZoom; - mapView.setMaxZoom(maxZoom); - } - - /** - *

- * Gets the maximum zoom level the map can be displayed at. - *

- * - * @return The maximum zoom level. - */ - @UiThread - public double getMaxZoom() { - if (maxZoomLevel == -1) { - return maxZoomLevel = mapView.getMaxZoom(); - } - return maxZoomLevel; - } - /** *

* Enables or disables the compass. The compass is an icon on the map that indicates the diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java index 16dc5d8a7..a5fa5d61b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java @@ -15,7 +15,6 @@ import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.OnMapReadyCallback; -import com.mapbox.mapboxsdk.maps.UiSettings; import com.mapbox.mapboxsdk.testapp.utils.ApiAccess; public class MaxMinZoomActivity extends AppCompatActivity { @@ -45,10 +44,8 @@ public class MaxMinZoomActivity extends AppCompatActivity { @Override public void onMapReady(@NonNull final MapboxMap mapboxMap) { mMapboxMap = mapboxMap; - - UiSettings uiSettings = mapboxMap.getUiSettings(); - uiSettings.setMinZoom(3); - uiSettings.setMaxZoom(5); + mMapboxMap.setMinZoom(3); + mMapboxMap.setMaxZoom(5); mMapboxMap.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(-1.063510, 32.895425))); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java index 91c3400bd..3a156c55f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java @@ -257,7 +257,7 @@ public class OfflineActivity extends AppCompatActivity String styleURL = mMapboxMap.getStyleUrl(); LatLngBounds bounds = mMapboxMap.getProjection().getVisibleRegion().latLngBounds; double minZoom = mMapboxMap.getCameraPosition().zoom; - double maxZoom = mMapboxMap.getUiSettings().getMaxZoom(); + double maxZoom = mMapboxMap.getMaxZoom(); float pixelRatio = this.getResources().getDisplayMetrics().density; OfflineTilePyramidRegionDefinition definition = new OfflineTilePyramidRegionDefinition( styleURL, bounds, minZoom, maxZoom, pixelRatio); @@ -346,6 +346,7 @@ public class OfflineActivity extends AppCompatActivity mProgressBar.setIndeterminate(true); mProgressBar.setVisibility(View.VISIBLE); } + private void setPercentage(final int percentage) { mProgressBar.setIndeterminate(false); mProgressBar.setProgress(percentage); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java index 1bf49823c..9e06a46aa 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java @@ -10,9 +10,7 @@ import com.mapbox.mapboxsdk.annotations.PolygonOptions; import com.mapbox.mapboxsdk.annotations.Polyline; import com.mapbox.mapboxsdk.annotations.PolylineOptions; import com.mapbox.mapboxsdk.camera.CameraPosition; - import com.mapbox.mapboxsdk.camera.CameraUpdateFactory; -import com.mapbox.mapboxsdk.constants.Style; import com.mapbox.mapboxsdk.geometry.LatLng; import org.junit.Before; @@ -26,11 +24,9 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.matches; -import static org.mockito.Mockito.mock; - import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -108,6 +104,30 @@ public class MapboxMapTest { assertNotNull("UiSettings should not be null", mMapboxMap.getUiSettings()); } + // + // MinZoomLevel + // + + @Test + public void testMinZoom() { + double zoom = 10; + mMapboxMap.setMinZoom(zoom); + assertEquals("MinZoom should match", zoom, mMapboxMap.getMinZoom(), 0); + } + + @Test + public void testMaxZoom() { + double zoom = 10; + mMapboxMap.setMaxZoom(zoom); + assertEquals("MaxZoom should match", zoom, mMapboxMap.getMaxZoom(), 0); + } + + @Test + public void testInitialZoomLevels() { + assertEquals("MaxZoom should match", 0, mMapboxMap.getMaxZoom(), 0); + assertEquals("MinZoom should match", 0, mMapboxMap.getMinZoom(), 0); + } + // // TrackingSettings // @@ -221,15 +241,15 @@ public class MapboxMapTest { } @Test - public void testOnBearingTrackingModeChangeListener(){ + public void testOnBearingTrackingModeChangeListener() { mMapboxMap.setOnMyBearingTrackingModeChangeListener(mMyBearingTrackingModeChangeListener); - assertEquals("MyBearingTrackingChangeListerner should match",mMyBearingTrackingModeChangeListener, mMapboxMap.getOnMyBearingTrackingModeChangeListener()); + assertEquals("MyBearingTrackingChangeListerner should match", mMyBearingTrackingModeChangeListener, mMapboxMap.getOnMyBearingTrackingModeChangeListener()); } @Test - public void testOnLocationTrackingModeChangeListener(){ + public void testOnLocationTrackingModeChangeListener() { mMapboxMap.setOnMyLocationTrackingModeChangeListener(mMyLocationTrackingModeChangeListener); - assertEquals("MyLocationTrackigChangeListener should match",mMyLocationTrackingModeChangeListener, mMapboxMap.getOnMyLocationTrackingModeChangeListener()); + assertEquals("MyLocationTrackigChangeListener should match", mMyLocationTrackingModeChangeListener, mMapboxMap.getOnMyLocationTrackingModeChangeListener()); } // @@ -709,7 +729,6 @@ public class MapboxMapTest { assertTrue("Selected markers should be empty", mMapboxMap.getSelectedMarkers().isEmpty()); } - // // OnMarkerClick interface // diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java index cb9031c66..4af44a3f4 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java @@ -21,30 +21,6 @@ public class UiSettingsTest { assertNotNull("uiSettings should not be null", uiSettings); } - @Test - public void testMinZoom() { - double zoom = 10; - UiSettings uiSettings = new UiSettings(mMapView); - uiSettings.setMinZoom(zoom); - assertEquals("MinZoom should match", zoom, uiSettings.getMinZoom(), 0); - } - - @Test - public void testMaxZoom() { - double zoom = 10; - UiSettings uiSettings = new UiSettings(mMapView); - uiSettings.setMaxZoom(zoom); - assertEquals("MaxZoom should match", zoom, uiSettings.getMaxZoom(), 0); - } - - @Test - public void testInitialZoomLevels() { - //we are mocking MapView we expect a value of 0 to be returned - UiSettings uiSettings = new UiSettings(mMapView); - assertEquals("MaxZoom should match", 0, uiSettings.getMaxZoom(), 0); - assertEquals("MinZoom should match", 0, uiSettings.getMinZoom(), 0); - } - @Test public void testCompassEnabled() { UiSettings uiSettings = new UiSettings(mMapView); From 4681d0b54577715cf1e9fcf33fa483b07b164987 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 15 Mar 2016 11:45:40 -0400 Subject: [PATCH 010/104] [android] #4320 - rename including to contains --- .../java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java | 2 +- .../java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java index 3b6387138..5251ab4d6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java @@ -162,7 +162,7 @@ public class LatLngBounds implements Parcelable { * @param latLng the point which may be contained * @return true, if the point is contained within the box. */ - public boolean including(final ILatLng latLng) { + public boolean contains(final ILatLng latLng) { final double latitude = latLng.getLatitude(); final double longitude = latLng.getLongitude(); return ((latitude < this.mLatNorth) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java index e3870b63e..f9cdf29b8 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java @@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.geometry; import com.mapbox.mapboxsdk.exceptions.InvalidLatLngBoundsException; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -100,12 +99,12 @@ public class LatLngBoundsTest { @Test public void testIncluding() { - assertTrue("LatLng should be included", mLatLngBounds.including(new LatLng(1, 1))); + assertTrue("LatLng should be included", mLatLngBounds.contains(new LatLng(1, 1))); } @Test public void testNoIncluding() { - assertFalse("LatLng should not be included", mLatLngBounds.including(new LatLng(3, 1))); + assertFalse("LatLng should not be included", mLatLngBounds.contains(new LatLng(3, 1))); } @Test From 1962fce1de3ea18db14b298e62c932fd13996537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 15 Mar 2016 09:38:58 -0700 Subject: [PATCH 011/104] [ios] Copy .der files into static framework Fixes #4316. --- platform/ios/scripts/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index 5d84ba5e2..459de6d10 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -210,7 +210,7 @@ else fi if [[ ${BUILD_STATIC} == true ]]; then mkdir -p "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" - cp -pv platform/ios/resources/* "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" + cp -pv platform/{default,ios}/resources/* "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" INFO_PLIST_PATH="${OUTPUT}/static/${NAME}.framework/Info.plist" cp -pv platform/ios/framework/Info.plist "${INFO_PLIST_PATH}" plutil -replace CFBundleExecutable -string ${NAME} "${INFO_PLIST_PATH}" From 2ab075b309af77b240ff19420e47bc09df1f16c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 15 Mar 2016 11:11:16 -0700 Subject: [PATCH 012/104] ios-v3.2.0-beta.1 --- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 984763874..f42f71778 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.2.0-pre.3-symbols' + m.version = '3.2.0-beta.1-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' From 4c455f4053e30881655648a7151561278e04ff62 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Tue, 15 Mar 2016 15:05:57 -0400 Subject: [PATCH 013/104] [android] #4317 - Revert to 4.0.0-SNAPSHOT for development --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 126d8bbc5..0e3858644 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-beta.1 +VERSION_NAME=4.0.0-SNAPSHOT POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native From 46830f1ea5e1054d35466731345e8b1f2b5dd380 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 15 Mar 2016 12:45:07 -0700 Subject: [PATCH 014/104] [core] Assert and guard against null std::exception_ptr in toString We don't expect toString to be called with a null std::exception_ptr. But if it is, we'd prefer not to terminate the process in release builds. --- include/mbgl/util/string.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp index 6c2433534..51ee848f2 100644 --- a/include/mbgl/util/string.hpp +++ b/include/mbgl/util/string.hpp @@ -28,6 +28,12 @@ inline std::string toString(uint8_t num) { } inline std::string toString(std::exception_ptr error) { + assert(error); + + if (!error) { + return "(null)"; + } + try { std::rethrow_exception(error); } catch (const std::exception& ex) { From fc0f32b6bf25183fadabbff7fbe132fdadc976c9 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Wed, 16 Mar 2016 18:31:25 -0300 Subject: [PATCH 015/104] Bump mason Fixes aarch64 build for android. Fixes #1956 Fixes #3128 --- .mason | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mason b/.mason index b30e09ebc..a910657c7 160000 --- a/.mason +++ b/.mason @@ -1 +1 @@ -Subproject commit b30e09ebc724b17cd000721938b3d26d3264900d +Subproject commit a910657c77e70589d68033ca94796abe4c03c493 From a69df28d21fd7f4009103f601f7bc4bbace33308 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Thu, 17 Mar 2016 14:28:41 -0300 Subject: [PATCH 016/104] [android] Build ARMv8 on the `apackage` target Follow-up of 51a3907. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fbda9b631..553bae542 100644 --- a/Makefile +++ b/Makefile @@ -93,7 +93,7 @@ android: android-lib cd platform/android && ./gradlew --parallel --max-workers=$(JOBS) assemble$(BUILDTYPE) # Builds all android architectures for distribution. -apackage: android-lib-arm-v5 android-lib-arm-v7 +apackage: android-lib-arm-v5 android-lib-arm-v7 android-lib-arm-v8 apackage: android-lib-x86 android-lib-x86-64 apackage: android-lib-mips cd platform/android && ./gradlew --parallel-threads=$(JOBS) assemble$(BUILDTYPE) From aa60d295346871bad0884238d13dcd9995d97151 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Wed, 16 Mar 2016 07:06:43 -0700 Subject: [PATCH 017/104] [iOS] Use CFBundleIdentifier instead of CFBundleName in UA string Although often recommended, CFBundleName is not guaranteed to exist in an app's configuration. As an identifier of telemetry data, even when it is present it can be inconsistent because of localization. CFBundleIdentifier, although possibly longer, will be consistent across locales and for the lifetime of an app in the App Store even if the app name changes in any locale. --- platform/ios/src/MGLAPIClient.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m index 7a72496ac..91bc07442 100644 --- a/platform/ios/src/MGLAPIClient.m +++ b/platform/ios/src/MGLAPIClient.m @@ -115,7 +115,7 @@ static NSString * const MGLAPIClientHTTPMethodPost = @"POST"; } - (void)setupUserAgent { - NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; + NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"]; NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; NSString *appBuildNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; NSString *semanticVersion = [NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"]; From 5130ca8843a342a1b708bb63263fd44c6c908120 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 15 Mar 2016 15:23:25 -0700 Subject: [PATCH 018/104] [core] Implement a vacuum strategy for the offline database Enable `PRAGMA auto_vacuum = INCREMENTAL`, and perform a `PRAGMA incremental_vacuum` when deleting an offline region. --- .gitignore | 1 + .../default/mbgl/storage/offline_database.cpp | 39 ++++++++++-------- .../default/mbgl/storage/offline_database.hpp | 2 + test/fixtures/offline/v2.db | Bin 0 -> 43008 bytes test/storage/offline_database.cpp | 28 +++++++++++++ 5 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 test/fixtures/offline/v2.db diff --git a/.gitignore b/.gitignore index 1b6ed5386..68e242a31 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ offline.db /test/fixtures/api/1.png /test/fixtures/api/2.png /test/fixtures/database/*.db +/test/fixtures/offline/v3.db /test/fixtures/**/actual.png /test/fixtures/**/diff.png /test/output diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index a42591d60..e1cd69366 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -14,9 +14,6 @@ namespace mbgl { using namespace mapbox::sqlite; -// If you change the schema you must write a migration from the previous version. -static const uint32_t schemaVersion = 2; - OfflineDatabase::Statement::~Statement() { stmt.reset(); stmt.clearBindings(); @@ -50,15 +47,12 @@ void OfflineDatabase::ensureSchema() { try { connect(ReadWrite); - { - auto userVersionStmt = db->prepare("PRAGMA user_version"); - userVersionStmt.run(); - switch (userVersionStmt.get(0)) { - case 0: break; // cache-only database; ok to delete - case 1: break; // cache-only database; ok to delete - case 2: return; - default: throw std::runtime_error("unknown schema version"); - } + switch (userVersion()) { + case 0: break; // cache-only database; ok to delete + case 1: break; // cache-only database; ok to delete + case 2: migrateToVersion3(); // fall through + case 3: return; + default: throw std::runtime_error("unknown schema version"); } removeExisting(); @@ -76,8 +70,17 @@ void OfflineDatabase::ensureSchema() { #include "offline_schema.cpp.include" connect(ReadWrite | Create); + + // If you change the schema you must write a migration from the previous version. + db->exec("PRAGMA auto_vacuum = INCREMENTAL"); db->exec(schema); - db->exec("PRAGMA user_version = " + util::toString(schemaVersion)); + db->exec("PRAGMA user_version = 3"); +} + +int OfflineDatabase::userVersion() { + auto stmt = db->prepare("PRAGMA user_version"); + stmt.run(); + return stmt.get(0); } void OfflineDatabase::removeExisting() { @@ -92,6 +95,11 @@ void OfflineDatabase::removeExisting() { } } +void OfflineDatabase::migrateToVersion3() { + db->exec("PRAGMA auto_vacuum = INCREMENTAL"); + db->exec("VACUUM"); +} + OfflineDatabase::Statement OfflineDatabase::getStatement(const char * sql) { auto it = statements.find(sql); @@ -458,6 +466,7 @@ void OfflineDatabase::deleteRegion(OfflineRegion&& region) { stmt->run(); evict(0); + db->exec("PRAGMA incremental_vacuum"); // Ensure that the cached offlineTileCount value is recalculated. offlineMapboxTileCount = {}; @@ -614,10 +623,6 @@ bool OfflineDatabase::evict(uint64_t neededFreeSize) { uint64_t pageSize = getPragma("PRAGMA page_size"); uint64_t pageCount = getPragma("PRAGMA page_count"); - if (pageSize * pageCount > maximumCacheSize) { - Log::Warning(mbgl::Event::Database, "Current size is larger than the maximum size. Database won't get truncated."); - } - auto usedSize = [&] { return pageSize * (pageCount - getPragma("PRAGMA freelist_count")); }; diff --git a/platform/default/mbgl/storage/offline_database.hpp b/platform/default/mbgl/storage/offline_database.hpp index eb18cc18d..1e77d560d 100644 --- a/platform/default/mbgl/storage/offline_database.hpp +++ b/platform/default/mbgl/storage/offline_database.hpp @@ -58,8 +58,10 @@ public: private: void connect(int flags); + int userVersion(); void ensureSchema(); void removeExisting(); + void migrateToVersion3(); class Statement { public: diff --git a/test/fixtures/offline/v2.db b/test/fixtures/offline/v2.db new file mode 100644 index 0000000000000000000000000000000000000000..8fadec4abe5e9216a1b1c43f49b246d22295c7bb GIT binary patch literal 43008 zcmeHQ3tSY{8lRan`+l$wa!o3x-97r(}sJU4t zm9M;-k4#PTbty_Q-`uW`yz0-&G#_YJAxkk8AL;F$8JHE7g>LSzU&)yt^PO+bcjkOE z|Cx_-=6v6tlRhNb>ab8_3QG#i4k`j8F&xMGQxt|_QE=}D_h7i=a2LRxggd*@c?5gl zA&tU9>+3mmLC{DSk%M1ABcTG<-Q_1MNuElj!e8Y$%%k%y4r{)}&JfOkG(%j5fy#)B zPc~3Y78N9t%_`|73T6I#tJYc+R#tGSl4B5R4o z&dTUY3kq|rW2_eUozQs}hj}b>dGtY!*noPzi>Cahb^( zR2W^*oSofzF?Ao4LTEgGGbO zyW>2Szdt@DgsBtWdSPh^tjx_2ch%$0{@t&~{cpuMc%$qCbAwHz_~(0=@M-A@uFBx= z>1ny~G3i+rTAzS6XFl1&HiKx}#E;_n*nhDKOwC%TOCu0rQFQ4FF`vwJIEs4p=wT@{ zLxZw(hp%Rj*k>CrjMtsy)NTsN4%pSjBs=$g*3BjI%9vGYowJ_p{oM@xgta{Dn$@o4 zO*3DqNiOI*a^Q|HZ(Xp3N4~DuvLdTIZ2gX$oZa8+Uxip|{Z4qA7_J~VEw5=`Ni`sl$ z8oX_7`UlqrE$s;fB##S(kopn?2I>Hp_>nk7d`7%SOd;}!!9+Ci82C3qfGV&MOabFS z8i)lHERME^3V}yK4BpCr_3$uX4-$Q>(vzg8!jmLM?nx3Y^CXG#@g#|qdXhv)JW0aE zo+NsaCrOyFGl*&pomhbfK~KI1K@87>Ae!qz5XJEzh$KA-B7g@$IP7vq30ir|dI@}& z3Gg2bT!92_2myq^!-s%`0RA}J_qY2Bao{H?v5d7A+U&Ib-}P1h@ZCMSBZL4#zyktw z{~y`E2XIg}Lf|1sfNuYB@Bs$@(1s8|2>cll$ig|8GYXriwmZh>TTIY{qwb|v>(rwQ zOKmxJb+3`3v0>fAbfNm5bi(iq`9tI%q?X|L-0*^TXr+vjb>>eA)^n_#TXdUBtjw zpdSHMh!7#kZiEm;H2vd!$ zTc6De9wp+c^#1rnrat$Gh5HnDj`Xg2-P!JfblvV;D#%^GbGU$~3JAc({Y$KqoMW!D62Y@azP>a}Ts1_|B2US;XV1LPPP% z%9fb8(Q7X2J{Goyja%wXeAr6c!-y?sZv!W`46F-c)sN3rrH8hI6?=-^jh8z|1Z{#b zAE%PbQ~CMf&Pgq>gMkXnljpU9l>PSwDdbqjSZ!7qqhh;1Rw2h?&n~eRF+w_IO)E)m68%jC8QWqF)4ynL<%7lk^)EtBp*^f$%B+f zav|lC97s7N2`MCy0+N7~05}jd`TxNSwEbTJKY_F0Bsc=Ce-GFRHiJ*VT4?)=!MosX z@H&hEm;?)=4IzLKct8ZWqyWc#eVIh5WDboMmJz>89|EJNZ;lb1X!#la%mOhEUw8X{pNX zcsH@!9hGd3UDldfx3uM%E!4Z^R1nM3Ap(E3xRw|pSM|GsKT!Ywo>v_mA_O`Z0`qGJ z*)KQ~GlI^7)#A4WZ*Jw^5Z(GA;@5eNgK~?qe;*=hD6_#uwTBjOJfo$W(Cj6AvY44SF28ek)fBqS#oJ-*ydv2uY$=di}#t& zZLIx%LH`9WFD-lQ$+*?M5BX=D8Q|CyxHs=u*NU6^ly~HBg`a=2)SmKMM7DUSSbOYL z!sj1Uule$+)bcNSxPn4c97`L@h8Z87-?%reN^)mIPbZ+y?0kgL^r-RzP$C-gm2TXILdp>Oz#_XD{^5-^u-J+;KL)^ z*6di8Wed4IdRAh!cJb-A`l(WMSL5d9Y_bhMajJUz{(5U!>Dq$QMFJbY`x)1|b1}>P zEMu?x1Rj@Vf4Xmd)Y6ygd;YLmGw#iWK1VkUGuK8->lOxdijLd9{M?RPeJU{JjE#B2 zEvDSwxu?epLoX{XjIaOK@jgfOoo$uHA=k!L{>+b<=l{~EDdJNThm5Rq0r~9eE}|Y| zB+A?1xL^9O!?))yyAd69u?_>8@X+M0XB(bFaYT-7b$!S@?Ro9?Gj*HmLq6Iw z`s)LgM^_%cu_(TP}a%=9ra7`p&o-wqNNtZPmMpToS29yVx7jsqT&(PI`x0$cH)K?osRSB zqG~`%XX`YbZ+x!Yzh#<)9>DX$|0-nu$o!G{cUbesko_b3NA{2GA9epx_aAltJ6!i4 zwg2ezAASCJ+|Pex|H%H4{UiHF!~bab9}WL^yy1V;{-gFEwg0I7N9{jq|55wj0o#8R z|ARUJr~}Y3I{-SZTL0^=waw7_U%zeLHnjeiw^qRWL)QOtueaCj zH`u>cA;MzXSpQG&ttI*3zoM=#t-Kv=-ZDw3Ex@IfwWG~jOY%W&T9?+R9c|uPk`HRr zxU|xCw0UbuKB!IY(n{LV=B*|9ptdJnT5&ttytO1B)JD0qqIR@-VM#v5B%wBcmsZ%0 zwy+0Z0Fc%87}SWN{y*yfqyB%#?EfSCN5B6;zyImjzyCq)KWhI``;XdxrvL6Z(|`XD6XiFz literal 0 HcmV?d00001 diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp index 23269a98e..11d56c237 100644 --- a/test/storage/offline_database.cpp +++ b/test/storage/offline_database.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -660,3 +661,30 @@ TEST(OfflineDatabase, OfflineMapboxTileCount) { db.deleteRegion(std::move(region1)); EXPECT_EQ(0, db.getOfflineMapboxTileCount()); } + +static int databasePageCount(const std::string& path) { + mapbox::sqlite::Database db(path, mapbox::sqlite::ReadOnly); + mapbox::sqlite::Statement stmt = db.prepare("pragma page_count"); + stmt.run(); + return stmt.get(0); +} + +TEST(OfflineDatabase, MigrateFromV2Schema) { + using namespace mbgl; + + // v2.db is a v2 database containing a single offline region with a small number of resources. + + deleteFile("test/fixtures/offline/v3.db"); + writeFile("test/fixtures/offline/v3.db", util::read_file("test/fixtures/offline/v2.db")); + + { + OfflineDatabase db("test/fixtures/offline/v3.db", 0); + auto regions = db.listRegions(); + for (auto& region : regions) { + db.deleteRegion(std::move(region)); + } + } + + EXPECT_LT(databasePageCount("test/fixtures/offline/v3.db"), + databasePageCount("test/fixtures/offline/v2.db")); +} From bcb3bb0931cbe0a85cb0f4ee9a311eceec7689c7 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Tue, 15 Mar 2016 21:42:09 -0700 Subject: [PATCH 019/104] [core] Stop download when tile limit is reached The tile limit guard (when used) stops a download from continuing when the tile limit is reached. This wraps the guard in a method and employs it in both places currently necessary to ensure the guard has a chance to function. Tests have been updated to ensure the fix works for a less trivial tile limit scenario. --- .../default/mbgl/storage/offline_download.cpp | 24 +++++-- .../default/mbgl/storage/offline_download.hpp | 3 +- test/storage/offline_download.cpp | 64 +++++++++++++++++-- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp index 36b6f5d50..cda00bf8d 100644 --- a/platform/default/mbgl/storage/offline_download.cpp +++ b/platform/default/mbgl/storage/offline_download.cpp @@ -229,12 +229,8 @@ void OfflineDownload::ensureResource(const Resource& resource, std::functionmapboxTileCountLimitExceeded(offlineDatabase.getOfflineMapboxTileCountLimit()); - setState(OfflineRegionDownloadState::Inactive); + + if (checkTileCountLimit(resource)) { return; } @@ -256,6 +252,10 @@ void OfflineDownload::ensureResource(const Resource& resource, std::functionstatusChanged(status); + if (checkTileCountLimit(resource)) { + return; + } + if (status.complete()) { setState(OfflineRegionDownloadState::Inactive); } @@ -263,4 +263,16 @@ void OfflineDownload::ensureResource(const Resource& resource, std::functionmapboxTileCountLimitExceeded(offlineDatabase.getOfflineMapboxTileCountLimit()); + setState(OfflineRegionDownloadState::Inactive); + return true; + } + + return false; +} + } // namespace mbgl diff --git a/platform/default/mbgl/storage/offline_download.hpp b/platform/default/mbgl/storage/offline_download.hpp index d5ba80154..be8e90b25 100644 --- a/platform/default/mbgl/storage/offline_download.hpp +++ b/platform/default/mbgl/storage/offline_download.hpp @@ -49,7 +49,8 @@ private: */ void ensureResource(const Resource&, std::function = {}); void ensureTiles(SourceType, uint16_t, const SourceInfo&); - + bool checkTileCountLimit(const Resource& resource); + int64_t id; OfflineRegionDefinition definition; OfflineDatabase& offlineDatabase; diff --git a/test/storage/offline_download.cpp b/test/storage/offline_download.cpp index 26d0fb29e..5dc1bf295 100644 --- a/test/storage/offline_download.cpp +++ b/test/storage/offline_download.cpp @@ -364,7 +364,7 @@ TEST(OfflineDownload, RequestErrorsAreRetried) { test.loop.run(); } -TEST(OfflineDownload, TileCountLimitExceeded) { +TEST(OfflineDownload, TileCountLimitExceededNoTileResponse) { OfflineTest test; OfflineRegion region = test.createRegion(); OfflineDownload download( @@ -372,7 +372,9 @@ TEST(OfflineDownload, TileCountLimitExceeded) { OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), test.db, test.fileSource); - test.db.setOfflineMapboxTileCountLimit(0); + uint64_t tileLimit = 0; + + test.db.setOfflineMapboxTileCountLimit(tileLimit); test.fileSource.styleResponse = [&] (const Resource& resource) { EXPECT_EQ("http://127.0.0.1:3000/offline/style.json", resource.url); @@ -384,18 +386,72 @@ TEST(OfflineDownload, TileCountLimitExceeded) { observer->mapboxTileCountLimitExceededFn = [&] (uint64_t limit) { EXPECT_FALSE(mapboxTileCountLimitExceededCalled); - EXPECT_EQ(0, limit); + EXPECT_EQ(tileLimit, limit); mapboxTileCountLimitExceededCalled = true; }; observer->statusChangedFn = [&] (OfflineRegionStatus status) { - EXPECT_FALSE(status.complete()); + if (!mapboxTileCountLimitExceededCalled) { + EXPECT_FALSE(status.complete()); + EXPECT_EQ(OfflineRegionDownloadState::Active, status.downloadState); + } else { + EXPECT_EQ(OfflineRegionDownloadState::Inactive, status.downloadState); + test.loop.stop(); + } + }; + + download.setObserver(std::move(observer)); + download.setState(OfflineRegionDownloadState::Active); + + test.loop.run(); +} + +TEST(OfflineDownload, TileCountLimitExceededWithTileResponse) { + OfflineTest test; + OfflineRegion region = test.createRegion(); + OfflineDownload download( + region.getID(), + OfflineTilePyramidRegionDefinition("http://127.0.0.1:3000/offline/style.json", LatLngBounds::world(), 0.0, 0.0, 1.0), + test.db, test.fileSource); + + uint64_t tileLimit = 1; + + test.db.setOfflineMapboxTileCountLimit(tileLimit); + + test.fileSource.styleResponse = [&] (const Resource& resource) { + EXPECT_EQ("http://127.0.0.1:3000/offline/style.json", resource.url); + return test.response("offline/mapbox_source.style.json"); + }; + + test.fileSource.tileResponse = [&] (const Resource& resource) { + const Resource::TileData& tile = *resource.tileData; + EXPECT_EQ("mapbox://{z}-{x}-{y}.vector.pbf", tile.urlTemplate); + EXPECT_EQ(1, tile.pixelRatio); + EXPECT_EQ(0, tile.x); + EXPECT_EQ(0, tile.y); + EXPECT_EQ(0, tile.z); + return test.response("offline/0-0-0.vector.pbf"); + }; + + auto observer = std::make_unique(); + bool mapboxTileCountLimitExceededCalled = false; + + observer->mapboxTileCountLimitExceededFn = [&] (uint64_t limit) { + EXPECT_FALSE(mapboxTileCountLimitExceededCalled); + EXPECT_EQ(tileLimit, limit); + mapboxTileCountLimitExceededCalled = true; + }; + + observer->statusChangedFn = [&] (OfflineRegionStatus status) { if (!mapboxTileCountLimitExceededCalled) { EXPECT_EQ(OfflineRegionDownloadState::Active, status.downloadState); } else { EXPECT_EQ(OfflineRegionDownloadState::Inactive, status.downloadState); test.loop.stop(); } + if (status.completedResourceCount > tileLimit) { + test.loop.stop(); + } }; download.setObserver(std::move(observer)); From 115a5d10f90b7da1726e9cb274bfaf58f806e54d Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Thu, 17 Mar 2016 18:23:02 -0300 Subject: [PATCH 020/104] [core] Fix regression of prior expiration time not being respected --- platform/default/online_file_source.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp index 77dddac11..944bcd56d 100644 --- a/platform/default/online_file_source.cpp +++ b/platform/default/online_file_source.cpp @@ -206,7 +206,11 @@ OnlineFileRequestImpl::OnlineFileRequestImpl(FileRequest* key_, const Resource& resource(resource_), callback(std::move(callback_)) { // Force an immediate first request if we don't have an expiration time. - schedule(impl, SystemClock::now()); + if (resource.priorExpires) { + schedule(impl, resource.priorExpires); + } else { + schedule(impl, SystemClock::now()); + } } OnlineFileRequestImpl::~OnlineFileRequestImpl() { From 35e6aa70bc7971dd91234b26110d71c1ca852999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 18 Mar 2016 00:15:36 -0700 Subject: [PATCH 021/104] [ios] Include offline headers in static umbrella header Include offline headers in the umbrella header used by the static framework. These includes are already present in the umbrella header used by the dynamic framework. jazzy relies on the static umbrella header to include all the headers, so the offline headers were also missing from documentation. --- .jazzy.yaml | 2 +- platform/ios/include/Mapbox.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 430bfbeba..3cf8a3041 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -37,7 +37,7 @@ custom_categories: - MGLOverlay - MGLShape - MGLUserLocation - - name: Offline Viewing + - name: Offline Storage children: - MGLOfflineRegion - MGLOfflineStorage diff --git a/platform/ios/include/Mapbox.h b/platform/ios/include/Mapbox.h index fd4f532a4..fb25a0104 100644 --- a/platform/ios/include/Mapbox.h +++ b/platform/ios/include/Mapbox.h @@ -8,11 +8,15 @@ #import "MGLMapView+IBAdditions.h" #import "MGLMapView+MGLCustomStyleLayerAdditions.h" #import "MGLMultiPoint.h" +#import "MGLOfflinePack.h" +#import "MGLOfflineRegion.h" +#import "MGLOfflineStorage.h" #import "MGLOverlay.h" #import "MGLPointAnnotation.h" #import "MGLPolygon.h" #import "MGLPolyline.h" #import "MGLShape.h" #import "MGLStyle.h" +#import "MGLTilePyramidOfflineRegion.h" #import "MGLTypes.h" #import "MGLUserLocation.h" From ec072b437aa21315b174affb9eac03e2b845fc37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 18 Mar 2016 00:29:58 -0700 Subject: [PATCH 022/104] [ios] Copy dynamic framework .dSYM into distribution --- CHANGELOG.md | 1 + platform/ios/scripts/package.sh | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b11fdff49..78d42e8d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Known issues: - Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) - Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) - An account’s monthly active users metric only counts a user once a map view is displayed to that user. ([#3713](https://github.com/mapbox/mapbox-gl-native/pull/3713)) +- A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. ([#4379](https://github.com/mapbox/mapbox-gl-native/pull/4379)) - Updated documentation to reflect the requirement that you must embed the framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) - Polygons and polylines now default to using the map view’s tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028)) - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index 459de6d10..c4357c45d 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -147,6 +147,8 @@ if [[ "${BUILD_FOR_DEVICE}" == true ]]; then cp -r \ gyp/build/${BUILDTYPE}-iphoneos/${NAME}.framework \ ${OUTPUT}/dynamic/ + cp -r gyp/build/${BUILDTYPE}-iphoneos/${NAME}.framework.dSYM \ + ${OUTPUT}/dynamic/ step "Merging simulator dynamic library into device dynamic library…" lipo \ @@ -170,6 +172,8 @@ else cp -r \ gyp/build/${BUILDTYPE}-iphonesimulator/${NAME}.framework \ ${OUTPUT}/dynamic/${NAME}.framework + cp -r gyp/build/${BUILDTYPE}-iphonesimulator/${NAME}.framework.dSYM \ + ${OUTPUT}/dynamic/ fi fi From 3814f38c07301328a28c7e9ba965c97dcf9f743b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 18 Mar 2016 00:33:14 -0700 Subject: [PATCH 023/104] [ios] Updated changelog ec072b437aa21315b174affb9eac03e2b845fc37 was unintentionally committed directly to the release branch, so no PR was created. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d42e8d2..618f4d261 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ Known issues: - Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) - Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) - An account’s monthly active users metric only counts a user once a map view is displayed to that user. ([#3713](https://github.com/mapbox/mapbox-gl-native/pull/3713)) -- A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. ([#4379](https://github.com/mapbox/mapbox-gl-native/pull/4379)) +- A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. - Updated documentation to reflect the requirement that you must embed the framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) - Polygons and polylines now default to using the map view’s tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028)) - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) From fff13d0976015650c2c79348dd8d51d25ce0b2d1 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 18 Mar 2016 12:47:39 -0400 Subject: [PATCH 024/104] [android] #4294 - JavaDocs for Telemetry classes --- .../java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java | 3 +++ .../com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java | 6 +++++- .../mapboxsdk/telemetry/TelemetryLocationReceiver.java | 3 +++ .../com/mapbox/mapboxsdk/telemetry/TelemetryService.java | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java index cd42fc044..41dec08ee 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEvent.java @@ -2,6 +2,9 @@ package com.mapbox.mapboxsdk.telemetry; import java.io.Serializable; +/** + * Constants for Telemetry Metadata + */ public class MapboxEvent implements Serializable { public static final int VERSION_NUMBER = 2; public static final String MAPBOX_EVENTS_BASE_URL = "https://api.mapbox.com"; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index 97393df4a..baf37e5c6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -46,6 +46,10 @@ import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; +/** + * Singleton control center for managing Telemetry Data. + * Primary access is via MapboxEventManager.getMapboxEventManager() + */ public class MapboxEventManager { private static final String TAG = "MapboxEventManager"; @@ -86,7 +90,7 @@ public class MapboxEventManager { * Private Constructor for configuring the single instance per app. */ private MapboxEventManager() { - + super(); } /** diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java index aaf5af22e..a35a87eb0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryLocationReceiver.java @@ -8,6 +8,9 @@ import android.location.LocationManager; import android.os.Handler; import android.util.Log; +/** + * Listener for Location updates generated by implementing app. + */ public class TelemetryLocationReceiver extends BroadcastReceiver { private static final String TAG = "TelemLocationReceiver"; diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java index 820502db6..41989dd8b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java @@ -1,4 +1,5 @@ package com.mapbox.mapboxsdk.telemetry; + import android.app.Service; import android.content.Context; import android.content.Intent; @@ -9,6 +10,9 @@ import android.os.IBinder; import android.support.annotation.Nullable; import android.util.Log; +/** + * Manages Startup and Shutdown of Telemetry resources + */ public class TelemetryService extends Service { private static final String TAG = "TelemetryService"; From b493bdc649b4e32cbedb3fd5cb9e3e4157dfdb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Thu, 17 Mar 2016 16:37:37 -0700 Subject: [PATCH 025/104] [ios, osx] Unified offline and ambient caches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is now only one instance of mbgl::OfflineFileSource, created when the shared MGLOfflineStorage object is initialized. Also create and use the shared MGLOfflineStorage object when initializing an MGLMapView object. The unified cache file is located in a subdirectory of Application Support, where the SDK has control over the file’s lifetime. The subdirectory is already named after the host application’s bundle identifier, ensuring that each Mapbox-powered application has an independent tile limit. If there’s an ambient cache in a subdirectory of Caches, delete it. If there’s an offline cache in a subdirectory of Documents on iOS or Caches on OS X, move it to the unified cache location in a subdirectory of Application Support. Fixes the iOS/OS X side of #4338. --- CHANGELOG.md | 3 +- platform/darwin/src/MGLOfflineStorage.mm | 41 ++++++++++++++--- platform/ios/src/MGLMapView.mm | 42 ++++------------- platform/osx/src/MGLMapView.mm | 58 ++++++++---------------- 4 files changed, 63 insertions(+), 81 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 618f4d261..9cd8ae1e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -57,9 +57,10 @@ 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 -## iOS master +## iOS 3.2.0 - Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) +- Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) - The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) - The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) - An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839)) diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 3eac28ca7..1f925b3ee 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -22,18 +22,20 @@ static dispatch_once_t onceToken; static MGLOfflineStorage *sharedOfflineStorage; dispatch_once(&onceToken, ^{ - sharedOfflineStorage = [[self alloc] initWithFileName:@"offline.db"]; + sharedOfflineStorage = [[self alloc] initWithFileName:@"cache.db"]; }); return sharedOfflineStorage; } +// This method can’t be called -init, because that selector has been marked +// unavailable in MGLOfflineStorage.h. - (instancetype)initWithFileName:(NSString *)fileName { if (self = [super init]) { -#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *cachePath = [paths.firstObject stringByAppendingPathComponent:fileName]; -#elif TARGET_OS_MAC - NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory + // Place the cache in a location specific to the application, so that + // packs downloaded by other applications don’t count toward this + // application’s limits. + // ~/Library/Application Support/tld.app.bundle.id/cache.db + NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES @@ -46,7 +48,34 @@ error:nil]; NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:fileName]; NSString *cachePath = cacheURL ? cacheURL.path : @""; + + // Move the offline cache from v3.2.0-beta.1 to a location that can also + // be used for ambient caching. + NSString *legacyCacheFileName = @"offline.db"; +#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR + // ~/Documents/offline.db + NSArray *legacyPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:legacyCacheFileName]; +#elif TARGET_OS_MAC + // ~/Library/Caches/tld.app.bundle.id/offline.db + NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory + inDomain:NSUserDomainMask + appropriateForURL:nil + create:YES + error:nil]; + legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent: + [NSBundle mainBundle].bundleIdentifier]; + [[NSFileManager defaultManager] createDirectoryAtURL:legacyCacheDirectoryURL + withIntermediateDirectories:YES + attributes:nil + error:nil]; + NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:legacyCacheFileName]; + NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @""; #endif + if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) { + [[NSFileManager defaultManager] moveItemAtPath:legacyCachePath toPath:cachePath error:NULL]; + } + _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String); // Observe for changes to the global access token (and find out the current one). diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 21d15ed1d..2def0c54f 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -30,6 +30,7 @@ #import "Mapbox.h" #import "../../darwin/src/MGLGeometry_Private.h" #import "../../darwin/src/MGLMultiPoint_Private.h" +#import "../../darwin/src/MGLOfflineStorage_Private.h" #import "NSBundle+MGLAdditions.h" #import "NSString+MGLAdditions.h" @@ -37,7 +38,6 @@ #import "NSException+MGLAdditions.h" #import "MGLUserLocationAnnotationView.h" #import "MGLUserLocation_Private.h" -#import "MGLAccountManager_Private.h" #import "MGLAnnotationImage_Private.h" #import "MGLMapboxEvents.h" #import "MGLCompactCalloutView.h" @@ -187,7 +187,6 @@ public: { mbgl::Map *_mbglMap; MBGLView *_mbglView; - mbgl::DefaultFileSource *_mbglFileSource; BOOL _opaque; @@ -303,18 +302,15 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) // setup mbgl view const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale]; _mbglView = new MBGLView(self, scaleFactor); - - // setup mbgl cache & file source - NSString *fileCachePath = @""; + + // Delete the pre-offline ambient cache at ~/Library/Caches/cache.db. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - if ([paths count] != 0) { - NSString *libraryDirectory = [paths objectAtIndex:0]; - fileCachePath = [libraryDirectory stringByAppendingPathComponent:@"cache.db"]; - } - _mbglFileSource = new mbgl::DefaultFileSource([fileCachePath UTF8String], [[[[NSBundle mainBundle] resourceURL] path] UTF8String]); + NSString *fileCachePath = [paths.firstObject stringByAppendingPathComponent:@"cache.db"]; + [[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL]; // setup mbgl map - _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None); + mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; + _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None); // start paused if in IB if (_isTargetingInterfaceBuilder || background) { @@ -322,13 +318,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _mbglMap->pause(); } - // Observe for changes to the global access token (and find out the current one). - [[MGLAccountManager sharedManager] addObserver:self - forKeyPath:@"accessToken" - options:(NSKeyValueObservingOptionInitial | - NSKeyValueObservingOptionNew) - context:NULL]; - // Notify map object when network reachability status changes. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) @@ -506,7 +495,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"]; [_attributionButton removeObserver:self forKeyPath:@"hidden"]; [self validateDisplayLink]; @@ -517,12 +505,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _mbglMap = nullptr; } - if (_mbglFileSource) - { - delete _mbglFileSource; - _mbglFileSource = nullptr; - } - if (_mbglView) { delete _mbglView; @@ -1606,15 +1588,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(__unused void *)context { - // Synchronize mbgl::Map’s access token with the global one in MGLAccountManager. - if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) - { - NSString *accessToken = change[NSKeyValueChangeNewKey]; - if (![accessToken isKindOfClass:[NSNull class]]) { - _mbglFileSource->setAccessToken((std::string)[accessToken UTF8String]); - } - } - else if ([keyPath isEqualToString:@"hidden"] && object == _attributionButton) + if ([keyPath isEqualToString:@"hidden"] && object == _attributionButton) { NSNumber *hiddenNumber = change[NSKeyValueChangeNewKey]; BOOL attributionButtonWasHidden = [hiddenNumber boolValue]; diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm index 07c080663..e09a6c267 100644 --- a/platform/osx/src/MGLMapView.mm +++ b/platform/osx/src/MGLMapView.mm @@ -4,10 +4,11 @@ #import "MGLOpenGLLayer.h" #import "MGLStyle.h" -#import "../../darwin/src/MGLAccountManager_Private.h" #import "../../darwin/src/MGLGeometry_Private.h" #import "../../darwin/src/MGLMultiPoint_Private.h" +#import "../../darwin/src/MGLOfflineStorage_Private.h" +#import "MGLAccountManager.h" #import "MGLMapCamera.h" #import "MGLPolygon.h" #import "MGLPolyline.h" @@ -151,7 +152,6 @@ public: /// Cross-platform map view controller. mbgl::Map *_mbglMap; MGLMapViewImpl *_mbglView; - mbgl::DefaultFileSource *_mbglFileSource; NSPanGestureRecognizer *_panGestureRecognizer; NSMagnificationGestureRecognizer *_magnificationGestureRecognizer; @@ -232,36 +232,25 @@ public: // Set up cross-platform controllers and resources. _mbglView = new MGLMapViewImpl(self, [NSScreen mainScreen].backingScaleFactor); - // Place the cache in a location that can be shared among all the - // applications that embed the Mapbox OS X SDK. - NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory - inDomain:NSUserDomainMask - appropriateForURL:nil - create:YES - error:nil]; - cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent: - [[NSBundle mgl_frameworkBundle] bundleIdentifier]]; - [[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL - withIntermediateDirectories:YES - attributes:nil - error:nil]; - NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:@"cache.db"]; - NSString *cachePath = cacheURL ? cacheURL.path : @""; - _mbglFileSource = new mbgl::DefaultFileSource(cachePath.UTF8String, [[[[NSBundle mainBundle] resourceURL] path] UTF8String]); + // Delete the pre-offline ambient cache at + // ~/Library/Caches/com.mapbox.sdk.ios/cache.db. + NSURL *cachesDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory + inDomain:NSUserDomainMask + appropriateForURL:nil + create:NO + error:nil]; + cachesDirectoryURL = [cachesDirectoryURL URLByAppendingPathComponent: + [NSBundle mgl_frameworkBundle].bundleIdentifier]; + NSURL *legacyCacheURL = [cachesDirectoryURL URLByAppendingPathComponent:@"cache.db"]; + [[NSFileManager defaultManager] removeItemAtURL:legacyCacheURL error:NULL]; - _mbglMap = new mbgl::Map(*_mbglView, *_mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None); + mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource; + _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None); // Install the OpenGL layer. Interface Builder’s synchronous drawing means // we can’t display a map, so don’t even bother to have a map layer. self.layer = _isTargetingInterfaceBuilder ? [CALayer layer] : [MGLOpenGLLayer layer]; - // Observe for changes to the global access token (and find out the current one). - [[MGLAccountManager sharedManager] addObserver:self - forKeyPath:@"accessToken" - options:(NSKeyValueObservingOptionInitial | - NSKeyValueObservingOptionNew) - context:NULL]; - // Notify map object when network reachability status changes. MGLReachability *reachability = [MGLReachability reachabilityForInternetConnection]; reachability.reachableBlock = ^(MGLReachability *) { @@ -443,7 +432,6 @@ public: } - (void)dealloc { - [[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"]; [self.window removeObserver:self forKeyPath:@"contentLayoutRect"]; [self.window removeObserver:self forKeyPath:@"titlebarAppearsTransparent"]; @@ -455,25 +443,15 @@ public: delete _mbglMap; _mbglMap = nullptr; } - if (_mbglFileSource) { - delete _mbglFileSource; - _mbglFileSource = nullptr; - } if (_mbglView) { delete _mbglView; _mbglView = nullptr; } } -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(__unused void *)context { - // Synchronize mbgl::Map’s access token with the global one in MGLAccountManager. - if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) { - NSString *accessToken = change[NSKeyValueChangeNewKey]; - if (![accessToken isKindOfClass:[NSNull class]]) { - _mbglFileSource->setAccessToken((std::string)accessToken.UTF8String); - } - } else if ([keyPath isEqualToString:@"contentLayoutRect"] || - [keyPath isEqualToString:@"titlebarAppearsTransparent"]) { +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(__unused id)object change:(__unused NSDictionary *)change context:(__unused void *)context { + if ([keyPath isEqualToString:@"contentLayoutRect"] || + [keyPath isEqualToString:@"titlebarAppearsTransparent"]) { [self adjustContentInsets]; } } From 4f816dcfbea1d2b9801d81f57152d893adbc19a2 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Thu, 17 Mar 2016 18:10:10 -0700 Subject: [PATCH 026/104] [iOS] Increase distance filter to 5 m --- platform/ios/src/MGLLocationManager.m | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/platform/ios/src/MGLLocationManager.m b/platform/ios/src/MGLLocationManager.m index 7a3f8de4f..b5740e354 100644 --- a/platform/ios/src/MGLLocationManager.m +++ b/platform/ios/src/MGLLocationManager.m @@ -1,9 +1,10 @@ #import "MGLLocationManager.h" #import -static const NSTimeInterval fiveMinuteTimeInterval = 300.0; -static const NSTimeInterval fiveSecondTimeInterval = 5.0; -static const CLLocationDistance regionRadiusLocationDistance = 300.0; +static const NSTimeInterval MGLLocationManagerHibernationTimeout = 300.0; +static const NSTimeInterval MGLLocationManagerHibernationPollInterval = 5.0; +static const CLLocationDistance MGLLocationManagerHibernationRadius = 300.0; +static const CLLocationDistance MGLLocationManagerDistanceFilter = 5.0; static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManagerRegionIdentifier.fence.center"; @interface MGLLocationManager () @@ -54,7 +55,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage CLLocationManager *standardLocationManager = [[CLLocationManager alloc] init]; standardLocationManager.delegate = self; standardLocationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers; - standardLocationManager.distanceFilter = 1; + standardLocationManager.distanceFilter = MGLLocationManagerDistanceFilter; self.standardLocationManager = standardLocationManager; } } @@ -105,12 +106,12 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage - (void)startBackgroundTimeoutTimer { [self.backgroundLocationServiceTimeoutTimer invalidate]; - self.backgroundLocationServiceTimeoutAllowedDate = [[NSDate date] dateByAddingTimeInterval:fiveMinuteTimeInterval]; - self.backgroundLocationServiceTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:fiveSecondTimeInterval target:self selector:@selector(timeoutAllowedCheck) userInfo:nil repeats:YES]; + self.backgroundLocationServiceTimeoutAllowedDate = [[NSDate date] dateByAddingTimeInterval:MGLLocationManagerHibernationTimeout]; + self.backgroundLocationServiceTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:MGLLocationManagerHibernationPollInterval target:self selector:@selector(timeoutAllowedCheck) userInfo:nil repeats:YES]; } - (void)establishRegionMonitoringForLocation:(CLLocation *)location { - CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:regionRadiusLocationDistance identifier:MGLLocationManagerRegionIdentifier]; + CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier]; region.notifyOnEntry = NO; region.notifyOnExit = YES; [self.standardLocationManager startMonitoringForRegion:region]; @@ -135,7 +136,7 @@ static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManage if (location.speed > 0.0) { [self startBackgroundTimeoutTimer]; } - if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < regionRadiusLocationDistance) { + if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLLocationManagerHibernationRadius) { [self establishRegionMonitoringForLocation:location]; } if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) { From d33cee7fd82d98c0993baefebff796354f3a6641 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 18 Mar 2016 16:48:42 -0400 Subject: [PATCH 027/104] [android] #4328 - Make Telemetry start only when savedInstanceState is null --- .../src/main/java/com/mapbox/mapboxsdk/maps/MapView.java | 4 ++-- .../com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index a9ae39972..e66786ab2 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 @@ -371,13 +371,13 @@ public class MapView extends FrameLayout { trackingSettings.setMyLocationTrackingMode(savedInstanceState.getInt(MapboxConstants.STATE_MY_LOCATION_TRACKING_MODE, MyLocationTracking.TRACKING_NONE)); //noinspection ResourceType trackingSettings.setMyBearingTrackingMode(savedInstanceState.getInt(MapboxConstants.STATE_MY_BEARING_TRACKING_MODE, MyBearingTracking.NONE)); - } else { + } else if (savedInstanceState == null) { // Force a check for Telemetry validateTelemetryServiceConfigured(); // Start Telemetry (authorization determined in initial MapboxEventManager constructor) MapboxEventManager eventManager = MapboxEventManager.getMapboxEventManager(); - eventManager.initialise(getContext(), getAccessToken()); + eventManager.initialize(getContext(), getAccessToken()); } // Initialize EGL diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index baf37e5c6..7ac42b826 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -101,7 +101,7 @@ public class MapboxEventManager { * @param context The context associated with MapView * @param accessToken The accessToken to load MapView */ - public void initialise(@NonNull Context context, @NonNull String accessToken) { + public void initialize(@NonNull Context context, @NonNull String accessToken) { this.context = context.getApplicationContext(); this.accessToken = accessToken; From 7155c9bb81be17d86a4aa8ce2cee278d7abf32a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 18 Mar 2016 14:34:22 -0700 Subject: [PATCH 028/104] ios-v3.2.0-beta.2 --- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index f42f71778..2f9f5f20e 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.2.0-beta.1-symbols' + m.version = '3.2.0-beta.2-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' From 90d271709f5b0e8698f746c1b2ec7972007b1a11 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 18 Mar 2016 16:08:00 -0700 Subject: [PATCH 029/104] [core] Add additional logging for exceptions during database connection / creation Refs #4382 --- .../default/mbgl/storage/offline_database.cpp | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index e1cd69366..43f7abaf9 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -58,23 +58,36 @@ void OfflineDatabase::ensureSchema() { removeExisting(); connect(ReadWrite | Create); } catch (mapbox::sqlite::Exception& ex) { - if (ex.code == SQLITE_CANTOPEN) { - connect(ReadWrite | Create); - } else if (ex.code == SQLITE_NOTADB) { - removeExisting(); + if (ex.code != SQLITE_CANTOPEN && ex.code != SQLITE_NOTADB) { + Log::Error(Event::Database, "Unexpected error connecting to database: %s", ex.what()); + throw; + } + + try { + if (ex.code == SQLITE_NOTADB) { + removeExisting(); + } connect(ReadWrite | Create); + } catch (...) { + Log::Error(Event::Database, "Unexpected error creating database: %s", util::toString(std::current_exception()).c_str()); + throw; } } } - #include "offline_schema.cpp.include" + try { + #include "offline_schema.cpp.include" - connect(ReadWrite | Create); + connect(ReadWrite | Create); - // If you change the schema you must write a migration from the previous version. - db->exec("PRAGMA auto_vacuum = INCREMENTAL"); - db->exec(schema); - db->exec("PRAGMA user_version = 3"); + // If you change the schema you must write a migration from the previous version. + db->exec("PRAGMA auto_vacuum = INCREMENTAL"); + db->exec(schema); + db->exec("PRAGMA user_version = 3"); + } catch (...) { + Log::Error(Event::Database, "Unexpected error creating database schema: %s", util::toString(std::current_exception()).c_str()); + throw; + } } int OfflineDatabase::userVersion() { From ca565a2cb2013be251bf2240b8429ab2c752d191 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 21 Mar 2016 15:08:06 +0100 Subject: [PATCH 030/104] [android] #4327 - OnDoubleTap needs to trigger camera invalidation after a zoom occurs --- .../com/mapbox/mapboxsdk/maps/MapView.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 e66786ab2..391d8dd62 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 @@ -694,6 +694,9 @@ public class MapView extends FrameLayout { } else { mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, MapboxConstants.ANIMATION_DURATION); } + + // work around to invalidate camera position + postDelayed(new ZoomInvalidator(mMapboxMap), MapboxConstants.ANIMATION_DURATION); } // @@ -2543,6 +2546,21 @@ public class MapView extends FrameLayout { } } + private static class ZoomInvalidator implements Runnable{ + + private MapboxMap mapboxMap; + + public ZoomInvalidator(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + @Override + public void run() { + // invalidate camera position + mapboxMap.getCameraPosition(); + } + } + /** * Definition of a map change event. * From 682b404bf677dda2ddaa5a6ef446da6f16b0507f Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Fri, 18 Mar 2016 12:55:32 -0400 Subject: [PATCH 031/104] [android] Unify cache and offline databases See #4362 --- .../mapbox/mapboxsdk/maps/NativeMapView.java | 7 ++++- .../mapboxsdk/offline/OfflineManager.java | 29 +++++++++++++++++-- platform/android/src/native_map_view.cpp | 2 +- 3 files changed, 34 insertions(+), 4 deletions(-) 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 20b881cbe..c6ac6dc6e 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 @@ -50,8 +50,13 @@ final class NativeMapView { public NativeMapView(MapView mapView) { Context context = mapView.getContext(); - String cachePath = context.getCacheDir().getAbsolutePath(); String dataPath = context.getFilesDir().getAbsolutePath(); + + // With the availability of offline, we're unifying the ambient (cache) and the offline + // databases to be in the same folder, outside cache, to avoid automatic deletion from + // the system + String cachePath = dataPath; + float pixelRatio = context.getResources().getDisplayMetrics().density; String apkPath = context.getPackageCodePath(); int availableProcessors = Runtime.getRuntime().availableProcessors(); diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index e632bcd76..eade67af6 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -4,6 +4,7 @@ import android.content.Context; import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; +import android.util.Log; import java.io.File; @@ -13,8 +14,10 @@ import java.io.File; */ public class OfflineManager { + private final static String LOG_TAG = "OfflineManager"; + // Default database name - private final static String OFFLINE_DATABASE_NAME = "mbgl-offline.db"; + private final static String DATABASE_NAME = "mbgl-offline.db"; /* * The maximumCacheSize parameter is a limit applied to non-offline resources only, @@ -53,8 +56,30 @@ public class OfflineManager { private OfflineManager(Context context) { // Get a pointer to the DefaultFileSource instance String assetRoot = context.getFilesDir().getAbsolutePath(); - String cachePath = assetRoot + File.separator + OFFLINE_DATABASE_NAME; + String cachePath = assetRoot + File.separator + DATABASE_NAME; mDefaultFileSourcePtr = createDefaultFileSource(cachePath, assetRoot, DEFAULT_MAX_CACHE_SIZE); + + // Delete any existing previous ambient cache database + deleteAmbientDatabase(context); + } + + private void deleteAmbientDatabase(final Context context) { + // Delete the file in a separate thread to avoid affecting the UI + new Thread(new Runnable() { + @Override + public void run() { + try { + String path = context.getCacheDir().getAbsolutePath() + File.separator + "mbgl-cache.db"; + File file = new File(path); + if (file.exists()) { + file.delete(); + Log.d(LOG_TAG, "Old ambient cache database deleted to save space: " + path); + } + } catch (Exception e) { + Log.e(LOG_TAG, "Failed to delete old ambient cache database: " + e.getMessage()); + } + } + }).start(); } public static synchronized OfflineManager getInstance(Context context) { diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 23eb39dab..58883b231 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -76,7 +76,7 @@ NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_, int a } fileSource = std::make_unique( - mbgl::android::cachePath + "/mbgl-cache.db", + mbgl::android::cachePath + "/mbgl-offline.db", mbgl::android::apkPath); map = std::make_unique(*this, *fileSource, MapMode::Continuous); From ead63abadd373433b066f07b8e7f2faf9a101d6b Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Mon, 21 Mar 2016 14:33:18 -0400 Subject: [PATCH 032/104] [android] Make sure we always load mapbox-gl when a native method is loaded Fixes #4175 --- .../java/com/mapbox/mapboxsdk/offline/OfflineManager.java | 8 ++++++++ .../java/com/mapbox/mapboxsdk/offline/OfflineRegion.java | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index eade67af6..8ddc68c86 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -16,6 +16,14 @@ public class OfflineManager { private final static String LOG_TAG = "OfflineManager"; + // + // Static methods + // + + static { + System.loadLibrary("mapbox-gl"); + } + // Default database name private final static String DATABASE_NAME = "mbgl-offline.db"; 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 f47b41e24..7714f9f36 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 @@ -17,6 +17,14 @@ public class OfflineRegion { private final static String LOG_TAG = "OfflineRegion"; + // + // Static methods + // + + static { + System.loadLibrary("mapbox-gl"); + } + // Parent OfflineManager private OfflineManager offlineManager; From 8508aea6fba05e4139f17077d6334e33f132144a Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 21 Mar 2016 15:08:06 +0100 Subject: [PATCH 033/104] [android] #4327 - OnDoubleTap needs to trigger camera invalidation after a zoom occurs --- .../com/mapbox/mapboxsdk/maps/MapView.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) 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 e66786ab2..391d8dd62 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 @@ -694,6 +694,9 @@ public class MapView extends FrameLayout { } else { mNativeMapView.scaleBy(0.5, x / mScreenDensity, y / mScreenDensity, MapboxConstants.ANIMATION_DURATION); } + + // work around to invalidate camera position + postDelayed(new ZoomInvalidator(mMapboxMap), MapboxConstants.ANIMATION_DURATION); } // @@ -2543,6 +2546,21 @@ public class MapView extends FrameLayout { } } + private static class ZoomInvalidator implements Runnable{ + + private MapboxMap mapboxMap; + + public ZoomInvalidator(MapboxMap mapboxMap) { + this.mapboxMap = mapboxMap; + } + + @Override + public void run() { + // invalidate camera position + mapboxMap.getCameraPosition(); + } + } + /** * Definition of a map change event. * From 967b6c7248e0b8986d3f3d7f6aa94065d548555c Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 21 Mar 2016 10:31:37 -0700 Subject: [PATCH 034/104] [core] Stop any OfflineDownload before deleting a region No progress events should be processed after deleting a region. --- platform/default/default_file_source.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index e3b785d08..36839b238 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -88,6 +88,7 @@ public: void deleteRegion(OfflineRegion&& region, std::function callback) { try { + downloads.erase(region.getID()); offlineDatabase.deleteRegion(std::move(region)); callback({}); } catch (...) { From 1856b3aeeaf7ea11621cb11ea4b9a7b10d076cc2 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 21 Mar 2016 12:32:10 -0500 Subject: [PATCH 035/104] [android] #4328 - Adding check of userAgent to see if it's still in initial state before prepending app meta data to it --- .../java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index 7ac42b826..fb98903c8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -156,7 +156,7 @@ public class MapboxEventManager { } // Build User Agent - if (!TextUtils.isEmpty(appName) && !TextUtils.isEmpty(versionName)) { + if (TextUtils.equals(userAgent, BuildConfig.MAPBOX_EVENTS_USER_AGENT_BASE) && !TextUtils.isEmpty(appName) && !TextUtils.isEmpty(versionName)) { userAgent = appName + "/" + versionName + "/" + versionCode + " " + userAgent; } From b163e9949918c9d495b92765d694c8ed7049b260 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Fri, 18 Mar 2016 14:09:03 -0700 Subject: [PATCH 036/104] [iOS] Send turnstile event as much as once per day Previously, the post of the turnstile event was a side effect of the map.load event and would happen when the host app was started from a terminated state at the first initialization of MGLMapView. The turnstile event post was guarded with dispatch_once so that it would only ever be sent once during the lifecycle of the application after it started from the terminated state. This changes that behavior by: - Allowing a new turnstile event to be posted as much as once per day - Only triggering a map.view event when a map is initialized if the map is loaded outside of the 'background' application state - Sending a map.view event whenever a MGLMapView is instantiated and the application did become active or enters foreground iOS turnstile event sending behavior is now: - A map.view event is generated whenever a map is loaded and also when a map is shown again when the host app becomes active and moves into the foreground - Turnstile events are still triggered by mapviews and will be sent as frequently as once per day for a host app that is not terminated and also whenever a host app is terminated and restarted w --- platform/ios/src/MGLMapView.mm | 6 ++- platform/ios/src/MGLMapboxEvents.m | 63 +++++++++++++++--------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 2def0c54f..adfb63531 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -439,7 +439,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _pendingLongitude = NAN; _targetCoordinate = kCLLocationCoordinate2DInvalid; - [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}]; + if ([UIApplication sharedApplication].applicationState != UIApplicationStateBackground) { + [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}]; + } } - (void)createGLView @@ -982,6 +984,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) _displayLink.paused = NO; [self validateLocationServices]; + + [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}]; } } diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m index f5628bc6f..13540bfd0 100644 --- a/platform/ios/src/MGLMapboxEvents.m +++ b/platform/ios/src/MGLMapboxEvents.m @@ -122,7 +122,8 @@ const NSTimeInterval MGLFlushInterval = 180; @property (nonatomic) dispatch_queue_t debugLogSerialQueue; @property (nonatomic) MGLLocationManager *locationManager; @property (nonatomic) NSTimer *timer; -@property (nonatomic) NSDate *lastInstanceIDRotationDate; +@property (nonatomic) NSDate *instanceIDRotationDate; +@property (nonatomic) NSDate *turnstileSendDate; @end @@ -233,13 +234,13 @@ const NSTimeInterval MGLFlushInterval = 180; } - (NSString *)instanceID { - if (self.lastInstanceIDRotationDate && [[NSDate date] timeIntervalSinceDate:self.lastInstanceIDRotationDate] >= 0) { + if (self.instanceIDRotationDate && [[NSDate date] timeIntervalSinceDate:self.instanceIDRotationDate] >= 0) { _instanceID = nil; } if (!_instanceID) { _instanceID = [[NSUUID UUID] UUIDString]; NSTimeInterval twentyFourHourTimeInterval = 24 * 3600; - self.lastInstanceIDRotationDate = [[NSDate date] dateByAddingTimeInterval:twentyFourHourTimeInterval]; + self.instanceIDRotationDate = [[NSDate date] dateByAddingTimeInterval:twentyFourHourTimeInterval]; } return _instanceID; } @@ -314,38 +315,36 @@ const NSTimeInterval MGLFlushInterval = 180; } - (void)pushTurnstileEvent { - __weak MGLMapboxEvents *weakSelf = self; + if (self.turnstileSendDate && [[NSDate date] timeIntervalSinceDate:self.turnstileSendDate] < 0) { + return; + } - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - MGLMapboxEvents *strongSelf = weakSelf; - - if (!strongSelf) { + NSString *vendorID = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; + if (!vendorID) { + return; + } + + NSDictionary *turnstileEventAttributes = @{MGLEventKeyEvent: MGLEventTypeAppUserTurnstile, + MGLEventKeyCreated: [self.rfc3339DateFormatter stringFromDate:[NSDate date]], + MGLEventKeyVendorID: vendorID, + MGLEventKeyEnabledTelemetry: @([[self class] isEnabled])}; + + if ([MGLAccountManager accessToken] == nil) { + return; + } + + __weak __typeof__(self) weakSelf = self; + [self.apiClient postEvent:turnstileEventAttributes completionHandler:^(NSError * _Nullable error) { + __strong __typeof__(weakSelf) strongSelf = weakSelf; + if (error) { + [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error", + @"error": error}]; return; } - - NSString *vendorID = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; - if (!vendorID) { - return; - } - - NSDictionary *turnstileEventAttributes = @{MGLEventKeyEvent: MGLEventTypeAppUserTurnstile, - MGLEventKeyCreated: [strongSelf.rfc3339DateFormatter stringFromDate:[NSDate date]], - MGLEventKeyVendorID: vendorID, - MGLEventKeyEnabledTelemetry: @([[strongSelf class] isEnabled])}; - - if ([MGLAccountManager accessToken] == nil) { - return; - } - [strongSelf.apiClient postEvent:turnstileEventAttributes completionHandler:^(NSError * _Nullable error) { - if (error) { - [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error", - @"error": error}]; - return; - } - [strongSelf writeEventToLocalDebugLog:turnstileEventAttributes]; - }]; - }); + [strongSelf writeEventToLocalDebugLog:turnstileEventAttributes]; + NSTimeInterval twentyFourHourTimeInterval = 24 * 3600; + strongSelf.turnstileSendDate = [[NSDate date] dateByAddingTimeInterval:twentyFourHourTimeInterval]; + }]; } + (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary { From 8dd6c063bd1744722e6a961d5c4211c18e7237ab Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 21 Mar 2016 10:57:43 -0700 Subject: [PATCH 037/104] [node] Drop Node 5 from build matrix (fixes #4370) --- .travis.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 69d1041dc..191a42458 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,25 +27,12 @@ matrix: - os: linux include: - # OS X/Node.js 5 - Xcode 7 - - os: osx - osx_image: xcode7 - compiler: clang - env: FLAVOR=node NODE_VERSION=5 - # OS X/Node.js 4 - Xcode 7 - os: osx osx_image: xcode7 compiler: clang env: FLAVOR=node NODE_VERSION=4 - - # Linux/Node.js 5 - Clang 3.5 - Release - - os: linux - compiler: ": node5-clang35-release" - env: FLAVOR=node BUILDTYPE=Release NODE_VERSION=5 _CXX=clang++-3.5 _CC=clang-3.5 CCACHE=1 - addons: *clang35 - # Linux/Node.js 4 - Clang 3.5 - Release - os: linux compiler: ": node4-clang35-release" From d329800806425a17e9d5c5e4a696e4730b85b4b9 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 21 Mar 2016 14:42:07 +0100 Subject: [PATCH 038/104] [android] #4326 - using the camera API vs getCameraPosition should return same output --- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) 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 432dc0ae8..280f5c77b 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 @@ -245,14 +245,15 @@ public class MapboxMap { */ @UiThread public final void moveCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) { - mCameraPosition = update.getCameraPosition(this); - mMapView.jumpTo(mCameraPosition.bearing, mCameraPosition.target, mCameraPosition.tilt, mCameraPosition.zoom); + CameraPosition position = update.getCameraPosition(this); + mMapView.jumpTo(position.bearing, position.target, position.tilt, position.zoom); if (mOnCameraChangeListener != null) { mOnCameraChangeListener.onCameraChange(mCameraPosition); } if (callback != null) { callback.onFinish(); } + invalidateCameraPosition(); } /** @@ -288,24 +289,22 @@ public class MapboxMap { */ @UiThread public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - mCameraPosition = update.getCameraPosition(this); - mMapView.easeTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, new CancelableCallback() { + CameraPosition position = update.getCameraPosition(this); + mMapView.easeTo(position.bearing, position.target, getDurationNano(durationMs), position.tilt, position.zoom, new CancelableCallback() { @Override public void onCancel() { if (callback != null) { callback.onCancel(); } + invalidateCameraPosition(); } @Override public void onFinish() { - if (mOnCameraChangeListener != null) { - mOnCameraChangeListener.onCameraChange(mCameraPosition); - } - if (callback != null) { callback.onFinish(); } + invalidateCameraPosition(); } }); } @@ -358,13 +357,14 @@ public class MapboxMap { */ @UiThread public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - mCameraPosition = update.getCameraPosition(this); - mMapView.flyTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, new CancelableCallback() { + CameraPosition cameraPosition = update.getCameraPosition(this); + mMapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom, new CancelableCallback() { @Override public void onCancel() { if (callback != null) { callback.onCancel(); } + invalidateCameraPosition(); } @Override @@ -376,6 +376,7 @@ public class MapboxMap { if (callback != null) { callback.onFinish(); } + invalidateCameraPosition(); } }); } From a0225d6ef70b4ac1854701a2e5d09cf176cc592b Mon Sep 17 00:00:00 2001 From: Tobrun Date: Mon, 21 Mar 2016 20:19:17 +0100 Subject: [PATCH 039/104] [android] #4326 - making the code compatible with unit tests again --- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) 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 280f5c77b..9ab883c13 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 @@ -245,11 +245,8 @@ public class MapboxMap { */ @UiThread public final void moveCamera(CameraUpdate update, MapboxMap.CancelableCallback callback) { - CameraPosition position = update.getCameraPosition(this); - mMapView.jumpTo(position.bearing, position.target, position.tilt, position.zoom); - if (mOnCameraChangeListener != null) { - mOnCameraChangeListener.onCameraChange(mCameraPosition); - } + mCameraPosition = update.getCameraPosition(this); + mMapView.jumpTo(mCameraPosition.bearing, mCameraPosition.target, mCameraPosition.tilt, mCameraPosition.zoom); if (callback != null) { callback.onFinish(); } @@ -289,8 +286,8 @@ public class MapboxMap { */ @UiThread public final void easeCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - CameraPosition position = update.getCameraPosition(this); - mMapView.easeTo(position.bearing, position.target, getDurationNano(durationMs), position.tilt, position.zoom, new CancelableCallback() { + mCameraPosition = update.getCameraPosition(this); + mMapView.easeTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, new CancelableCallback() { @Override public void onCancel() { if (callback != null) { @@ -357,8 +354,8 @@ public class MapboxMap { */ @UiThread public final void animateCamera(CameraUpdate update, int durationMs, final MapboxMap.CancelableCallback callback) { - CameraPosition cameraPosition = update.getCameraPosition(this); - mMapView.flyTo(cameraPosition.bearing, cameraPosition.target, getDurationNano(durationMs), cameraPosition.tilt, cameraPosition.zoom, new CancelableCallback() { + mCameraPosition = update.getCameraPosition(this); + mMapView.flyTo(mCameraPosition.bearing, mCameraPosition.target, getDurationNano(durationMs), mCameraPosition.tilt, mCameraPosition.zoom, new CancelableCallback() { @Override public void onCancel() { if (callback != null) { @@ -396,7 +393,12 @@ public class MapboxMap { */ private void invalidateCameraPosition() { mInvalidCameraPosition = false; - mCameraPosition = mMapView.invalidateCameraPosition(); + + CameraPosition cameraPosition = mMapView.invalidateCameraPosition(); + if (cameraPosition != null) { + mCameraPosition = cameraPosition; + } + if (mOnCameraChangeListener != null) { mOnCameraChangeListener.onCameraChange(mCameraPosition); } From 6fb87fb0eed69d6eb607bfc283515257b8641f9b Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 21 Mar 2016 17:31:25 -0500 Subject: [PATCH 040/104] [android] #4419 - Updating version name for artifact and fabric --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- .../fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 0e3858644..8a06a9855 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-SNAPSHOT +VERSION_NAME=4.0.0-beta.2 POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native diff --git a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties index d524fe998..00499bda3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties +++ b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties @@ -1,3 +1,3 @@ fabric-identifier=com.mapbox.mapboxsdk.mapbox-android-sdk -fabric-version=4.0.0-beta.1 +fabric-version=4.0.0-beta.2 fabric-build-type=binary From a6012a1cb5661683dea30f0f2fbcd80894791d21 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 21 Mar 2016 17:49:38 -0500 Subject: [PATCH 041/104] [android] #4419 - Beta 2 Changelog --- CHANGELOG.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cd8ae1e2..9ecfd0200 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,22 @@ ## Android +## 4.0.0-beta.2 + +* arm64 ABI Support ([#3128](https://github.com/mapbox/mapbox-gl-native/issues/3128)) +* Unify Offline And Cache Databases ([#4362](https://github.com/mapbox/mapbox-gl-native/issues/4362)) +* Offline Database Vacuuming ([#4342](https://github.com/mapbox/mapbox-gl-native/pull/4342)) +* Telemetry User Agent Fix ([#4328](https://github.com/mapbox/mapbox-gl-native/issues/4328)) +* OnCameraChange Bug Fix ([#4327](https://github.com/mapbox/mapbox-gl-native/issues/4327)) +* OnCameraChangeListener vs getCameraPosition ([#4326](https://github.com/mapbox/mapbox-gl-native/issues/4326)) + ## 4.0.0-beta.1 Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major new features being released. To help us produce the highest quality SDK possible we're releasing an official Beta release first so that everyone has time to explore it and help hardened it before the official 4.0.0 Final Release. -* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145) -* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891) -* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421) +* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145)) +* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891)) +* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421)) ## 3.2.0 From ca8212de92737c084fda5edfacf0cdd899e03104 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 21 Mar 2016 13:49:43 -0700 Subject: [PATCH 042/104] [all] Set maximum maxZoom to 21 Numbers greater than 21 trigger various bugs. --- CHANGELOG.md | 1 + .../java/com/mapbox/mapboxsdk/constants/MapboxConstants.java | 2 +- src/mbgl/util/constants.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ecfd0200..5940999e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,7 @@ Known issues: - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) +- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417))) ## iOS 3.1.2 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 983dd96ed..475489f62 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 @@ -40,7 +40,7 @@ public class MapboxConstants { /** * The currently supported maximum zoom level. */ - public static final float MAXIMUM_ZOOM = 25.5f; + public static final float MAXIMUM_ZOOM = 21.0f; /** * The currently supported maximum tilt value. diff --git a/src/mbgl/util/constants.cpp b/src/mbgl/util/constants.cpp index 7ff00800a..c08e0bf45 100644 --- a/src/mbgl/util/constants.cpp +++ b/src/mbgl/util/constants.cpp @@ -29,7 +29,7 @@ const double LONGITUDE_MAX = 180; const double DEGREES_MAX = 360; const double PITCH_MAX = M_PI / 3; const double MIN_ZOOM = 0.0; -const double MAX_ZOOM = 25.5; +const double MAX_ZOOM = 21.0; const uint64_t DEFAULT_MAX_CACHE_SIZE = 50 * 1024 * 1024; From bbe13b8cc684ee41675d22c0a0c5a08dae9f88ee Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Mon, 21 Mar 2016 18:59:33 -0500 Subject: [PATCH 043/104] [android] #4419 - Re-enabling development on 4.0.0-SNAPSHOT --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 8a06a9855..0e3858644 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-beta.2 +VERSION_NAME=4.0.0-SNAPSHOT POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native From b57f0fb987cde24643d5913bbcea83e3aa5ae04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Tue, 22 Mar 2016 10:52:10 -0700 Subject: [PATCH 044/104] [ios] Fix up center coordinate after lopsided pinch gesture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gesture recognizer only reports the gesture’s current center point, so use the previous center point to anchor the transition. Fixes #4315. --- CHANGELOG.md | 1 + platform/ios/src/MGLMapView.mm | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5940999e4..2756f579b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,7 @@ Known issues: - Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) - The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) - The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) +- Fixed an issue causing the map to pan the wrong way when the user pinches unevenly. ([#4427](https://github.com/mapbox/mapbox-gl-native/pull/4427)) - An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839)) - Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) - Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index adfb63531..1d7a5090d 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -211,6 +211,10 @@ public: NSUInteger _changeDelimiterSuppressionDepth; + /// Center coordinate of the pinch gesture on the previous iteration of the gesture. + CLLocationCoordinate2D _previousPinchCenterCoordinate; + NSUInteger _previousPinchNumberOfTouches; + BOOL _delegateHasAlphasForShapeAnnotations; BOOL _delegateHasStrokeColorsForShapeAnnotations; BOOL _delegateHasFillColorsForShapeAnnotations; @@ -1133,6 +1137,17 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) if (log2(newScale) < _mbglMap->getMinZoom()) return; _mbglMap->setScale(newScale, { centerPoint.x, centerPoint.y }); + + // The gesture recognizer only reports the gesture’s current center + // point, so use the previous center point to anchor the transition. + // If the number of touches has changed, the remembered center point is + // meaningless. + if (self.userTrackingMode == MGLUserTrackingModeNone && pinch.numberOfTouches == _previousPinchNumberOfTouches) + { + CLLocationCoordinate2D centerCoordinate = _previousPinchCenterCoordinate; + _mbglMap->setLatLng(MGLLatLngFromLocationCoordinate2D(centerCoordinate), + { centerPoint.x, centerPoint.y }); + } [self notifyMapChange:mbgl::MapChangeRegionIsChanging]; } @@ -1176,6 +1191,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) [self unrotateIfNeededForGesture]; } + + _previousPinchCenterCoordinate = [self convertPoint:[pinch locationInView:pinch.view] toCoordinateFromView:self]; + _previousPinchNumberOfTouches = pinch.numberOfTouches; } - (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate From a7fedcb604c45965d4172deb8c67f958f9877b12 Mon Sep 17 00:00:00 2001 From: Antonio Zugaldia Date: Tue, 15 Mar 2016 10:48:28 -0400 Subject: [PATCH 045/104] [android] Add Javadoc for offline package Fixes #4295 --- .../mapboxsdk/offline/OfflineManager.java | 31 ++++++++++++++-- .../mapboxsdk/offline/OfflineRegion.java | 35 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java index 8ddc68c86..85b3d619b 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineManager.java @@ -43,17 +43,42 @@ public class OfflineManager { // This object is implemented as a singleton private static OfflineManager instance; - /* - * Callbacks + /** + * This callback receives an asynchronous response containing a list of all + * {@link OfflineRegion} in the database, or an error message otherwise. */ - public interface ListOfflineRegionsCallback { + /** + * Receives the list of offline regions + * + * @param offlineRegions + */ void onList(OfflineRegion[] offlineRegions); + + /** + * Receives the error message + * + * @param error + */ void onError(String error); } + /** + * This callback receives an asynchronous response containing the newly created + * {@link OfflineRegion} in the database, or an error message otherwise. + */ public interface CreateOfflineRegionCallback { + /** + * Receives the newly created offline region + * @param offlineRegion + */ void onCreate(OfflineRegion offlineRegion); + + /** + * Receives the error message + * + * @param error + */ void onError(String error); } 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 7714f9f36..7f066e74d 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 @@ -10,8 +10,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** - * To use offline maps on mobile, you will first have to create an offline region. - * Use OfflineManager.createOfflineRegion() to create a new offline region. + * An offline region is the basic building block for offline mobile maps. + * Use {@link com.mapbox.mapboxsdk.offline.OfflineManager.CreateOfflineRegionCallback} + * to create a new offline region. */ public class OfflineRegion { @@ -84,17 +85,41 @@ public class OfflineRegion { void mapboxTileCountLimitExceeded(long limit); } - /* - * Callbacks + /** + * This callback receives an asynchronous response containing the {@link OfflineRegionStatus} + * of the offline region, or a {@link String} error message otherwise. */ - public interface OfflineRegionStatusCallback { + /** + * Receives the status + * + * @param status + */ void onStatus(OfflineRegionStatus status); + + /** + * Receives the error message + * + * @param error + */ void onError(String error); } + /** + * This callback receives an asynchronous response containing a notification when + * an offline region has been deleted, or a {@link String} error message otherwise. + */ public interface OfflineRegionDeleteCallback { + /** + * Receives the delete notification + */ void onDelete(); + + /** + * Receives the error message + * + * @param error + */ void onError(String error); } From 38e6d518d70814fd7f43b5813df7d3a769c8e667 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 22 Mar 2016 18:42:00 -0700 Subject: [PATCH 046/104] [node] Drop OS X build from Travis --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 191a42458..f287996b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,12 +27,6 @@ matrix: - os: linux include: - # OS X/Node.js 4 - Xcode 7 - - os: osx - osx_image: xcode7 - compiler: clang - env: FLAVOR=node NODE_VERSION=4 - # Linux/Node.js 4 - Clang 3.5 - Release - os: linux compiler: ": node4-clang35-release" From 79069d13b42885ff708130420756af560bf78b53 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Wed, 23 Mar 2016 10:18:38 +0100 Subject: [PATCH 047/104] [android] #4398 - Default value bug fix for MapboxMapOptions --- .../java/com/mapbox/mapboxsdk/maps/MapView.java | 14 +++++++++++++- .../mapboxsdk/testapp/MapFragmentActivity.java | 6 +++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java index 391d8dd62..9c6709683 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 @@ -13,6 +13,7 @@ import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.PointF; @@ -274,6 +275,9 @@ public class MapView extends FrameLayout { int[] compassMargins = options.getCompassMargins(); if (compassMargins != null) { uiSettings.setCompassMargins(compassMargins[0], compassMargins[1], compassMargins[2], compassMargins[3]); + } else { + int tenDp = (int) getResources().getDimension(R.dimen.ten_dp); + uiSettings.setCompassMargins(tenDp, tenDp, tenDp, tenDp); } // Logo @@ -282,6 +286,9 @@ public class MapView extends FrameLayout { int[] logoMargins = options.getLogoMargins(); if (logoMargins != null) { uiSettings.setLogoMargins(logoMargins[0], logoMargins[1], logoMargins[2], logoMargins[3]); + } else { + int sixteenDp = (int) getResources().getDimension(R.dimen.sixteen_dp); + uiSettings.setLogoMargins(sixteenDp, sixteenDp, sixteenDp, sixteenDp); } // Attribution @@ -290,6 +297,11 @@ public class MapView extends FrameLayout { int[] attributionMargins = options.getAttributionMargins(); if (attributionMargins != null) { uiSettings.setAttributionMargins(attributionMargins[0], attributionMargins[1], attributionMargins[2], attributionMargins[3]); + } else { + Resources resources = getResources(); + int sevenDp = (int) resources.getDimension(R.dimen.seven_dp); + int seventySixDp = (int) resources.getDimension(R.dimen.seventy_six_dp); + uiSettings.setAttributionMargins(seventySixDp, sevenDp, sevenDp, sevenDp); } } @@ -2546,7 +2558,7 @@ public class MapView extends FrameLayout { } } - private static class ZoomInvalidator implements Runnable{ + private static class ZoomInvalidator implements Runnable { private MapboxMap mapboxMap; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java index d2fc7b671..74516a2e4 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapFragmentActivity.java @@ -48,9 +48,9 @@ public class MapFragmentActivity extends AppCompatActivity { options.rotateGesturesEnabled(false); options.debugActive(false); - options.compassEnabled(false); - options.attributionEnabled(false); - options.logoEnabled(false); +// options.compassEnabled(false); +// options.attributionEnabled(false); +// options.logoEnabled(false); options.minZoom(9); options.maxZoom(11); From 47ebf0fd59e3ed2b20ae29c0a4291ef8ff162f49 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Wed, 20 Jan 2016 14:03:45 -0800 Subject: [PATCH 048/104] [node] Build OS X on Bitrise --- platform/node/bitrise.yml | 64 +++++++++++++++++++++++++++ platform/node/scripts/after_script.sh | 3 +- platform/node/scripts/install.sh | 4 -- platform/node/scripts/run.sh | 7 +-- 4 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 platform/node/bitrise.yml diff --git a/platform/node/bitrise.yml b/platform/node/bitrise.yml new file mode 100644 index 000000000..134925d6e --- /dev/null +++ b/platform/node/bitrise.yml @@ -0,0 +1,64 @@ +format_version: 1.1.0 +default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git + +trigger_map: +- pattern: "*" + is_pull_request_allowed: true + workflow: primary + +workflows: + primary: + steps: + - script: + title: Check for skipping CI + inputs: + - content: |- + #!/bin/bash + if [[ -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[skip ci\]/p')" || + -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_SUBJECT | sed -n '/\[ci skip\]/p')" || + -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[skip ci\]/p')" || + -n "$(echo $GIT_CLONE_COMMIT_MESSAGE_BODY | sed -n 's/\[ci skip\]/p')" ]]; then + envman add --key SKIPCI --value true + else + envman add --key SKIPCI --value false + fi + - select-xcode-version: + title: Select Xcode version + run_if: '{{enveq "SKIPCI" "false"}}' + - script: + title: Run build script + run_if: '{{enveq "SKIPCI" "false"}}' + inputs: + - content: |- + #!/bin/bash + set -e + set -o pipefail + export TRAVIS_OS_NAME=osx + export TRAVIS_TAG=$BITRISE_GIT_TAG + export NODE_VERSION=4 + export CXX=clang++ + export CC=clang + source ./scripts/set_compiler.sh + ./platform/node/scripts/install.sh + if command -v ccache >/dev/null 2>&1; then ccache --zero-stats ; fi + ./platform/node/scripts/run.sh + if command -v ccache >/dev/null 2>&1; then ccache --show-stats ; fi + ./platform/node/scripts/after_script.sh + - slack: + title: Post to Slack + run_if: '{{enveq "SKIPCI" "false"}}' + inputs: + - webhook_url: "$SLACK_HOOK_URL" + - channel: "#gl-bots" + - from_username: 'Bitrise Node OS X' + - from_username_on_error: 'Bitrise Node OS X' + - message: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> + for + by ${GIT_CLONE_COMMIT_COMMITER_NAME} + passed' + - message_on_error: '<${BITRISE_BUILD_URL}|Build #${BITRISE_BUILD_NUMBER}> + for + by ${GIT_CLONE_COMMIT_COMMITER_NAME} + failed' + - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png + - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png diff --git a/platform/node/scripts/after_script.sh b/platform/node/scripts/after_script.sh index af2cd78dd..8cbfa4d8f 100755 --- a/platform/node/scripts/after_script.sh +++ b/platform/node/scripts/after_script.sh @@ -10,10 +10,9 @@ else otool -L ./lib/mapbox-gl-native.node fi -COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)") -if [[ ${TRAVIS_TAG} == node-v${PACKAGE_JSON_VERSION} ]] || test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then +if [[ ${TRAVIS_TAG} == node-v${PACKAGE_JSON_VERSION} ]]; then source ~/.nvm/nvm.sh nvm use $NODE_VERSION diff --git a/platform/node/scripts/install.sh b/platform/node/scripts/install.sh index 1edc2c91d..b550933cd 100755 --- a/platform/node/scripts/install.sh +++ b/platform/node/scripts/install.sh @@ -3,13 +3,11 @@ set -e set -o pipefail -mapbox_time "checkout_mason" \ git submodule update --init .mason export PATH="`pwd`/.mason:${PATH}" MASON_DIR="`pwd`/.mason" if [ ${TRAVIS_OS_NAME} == "linux" ]; then - mapbox_time "install_mesa" \ mason install mesa 10.4.3 fi @@ -19,9 +17,7 @@ fi source ~/.nvm/nvm.sh -mapbox_time $NODE_VERSION \ nvm install $NODE_VERSION - nvm alias default $NODE_VERSION node --version diff --git a/platform/node/scripts/run.sh b/platform/node/scripts/run.sh index 07395d6a6..fdebaaeb9 100755 --- a/platform/node/scripts/run.sh +++ b/platform/node/scripts/run.sh @@ -13,19 +13,14 @@ BUILDTYPE=${BUILDTYPE:-Release} source ~/.nvm/nvm.sh nvm use $NODE_VERSION - -mapbox_time "compile_program" \ npm install --build-from-source ################################################################################ # Test ################################################################################ -# Travis OS X has no GPU +# https://github.com/mapbox/mapbox-gl-native/issues/2150 if [[ ${TRAVIS_OS_NAME} == "linux" ]]; then - mapbox_time "run_tests" \ npm test - - mapbox_time "run_render_tests" \ npm run test-suite fi From 34cea826b9ae4d2fb9d713415c21880e195941cf Mon Sep 17 00:00:00 2001 From: Vacxe Date: Thu, 24 Mar 2016 15:45:47 +0300 Subject: [PATCH 049/104] TelemetryService: Catch IllegalArgumentException exception when unregisterReceiver --- .../com/mapbox/mapboxsdk/telemetry/TelemetryService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java index 41989dd8b..0db75c92f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/TelemetryService.java @@ -147,6 +147,11 @@ public class TelemetryService extends Service { Log.e(TAG, "Error while trying to sleep for 1 second: " + e); } - unregisterReceiver(telemetryLocationReceiver); + try { + unregisterReceiver(telemetryLocationReceiver); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Error when unregisterReceiver: " + e); + } + } } From 6a29e7e624ee6c4051aa014cd6c2c31dc574e4db Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Thu, 24 Mar 2016 16:59:47 -0500 Subject: [PATCH 050/104] [android] #4444 - Wrapping all LatLng from nativeLatLngForPixel() to solve problem and mirror Android Google Maps API --- .../src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java | 2 +- platform/android/src/jni.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java index f24c2ed43..d9ffe48b3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java @@ -147,7 +147,7 @@ public class LatLng implements ILatLng, Parcelable { @Override public String toString() { - return "LatLng [longitude=" + longitude + ", latitude=" + latitude + ", altitude=" + altitude + "]"; + return "LatLng [latitude=" + latitude + ", longitude=" + longitude + ", altitude=" + altitude + "]"; } @Override diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 237fbb99d..4b75f324f 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -1176,7 +1176,7 @@ jni::jobject* nativeLatLngForPixel(JNIEnv *env, jni::jobject* obj, jlong nativeM jfloat x = jni::GetField(*env, pixel, *pointFXId); jfloat y = jni::GetField(*env, pixel, *pointFYId); - mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y)); + mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y)).wrapped(); return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude); } From 48cc510d295162c4d9b0f9e8376db9e05d9ab3e9 Mon Sep 17 00:00:00 2001 From: Cameron Mace Date: Thu, 24 Mar 2016 11:46:45 -0500 Subject: [PATCH 051/104] [android] #4429 Removed NonNull from OnMapReady --- .../com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java index 255ca1e5f..7ace9ec2d 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/OnMapReadyCallback.java @@ -1,12 +1,10 @@ package com.mapbox.mapboxsdk.maps; -import android.support.annotation.NonNull; - /** * Interface definition for a callback to be invoked when the map is ready to be used. *

* Once an instance of this interface is set on a {@link MapFragment} or {@link MapView} object, - * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides a non-null instance of {@link MapboxMap}. + * the onMapReady(MapboxMap) method is triggered when the map is ready to be used and provides an instance of {@link MapboxMap}. *

*/ public interface OnMapReadyCallback { @@ -14,8 +12,8 @@ public interface OnMapReadyCallback { /** * Called when the map is ready to be used. * - * @param mapboxMap A non-null instance of a MapboxMap associated with the {@link MapFragment} - * or {@link MapView} that defines the callback. + * @param mapboxMap An instance of MapboxMap associated with the {@link MapFragment} or + * {@link MapView} that defines the callback. */ - void onMapReady(@NonNull MapboxMap mapboxMap); + void onMapReady(MapboxMap mapboxMap); } From b4d365c3c8d09792b4e7a44e51a4e15d4d08c687 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Wed, 23 Mar 2016 08:55:51 +0100 Subject: [PATCH 052/104] [android] #4424 - NativeMapView null pointer bug when updating CompassView --- .../main/java/com/mapbox/mapboxsdk/maps/MapView.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 9c6709683..883aac10a 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 @@ -596,6 +596,10 @@ public class MapView extends FrameLayout { // double getDirection() { + if(mDestroyed){ + return 0; + } + double direction = -mNativeMapView.getBearing(); while (direction > 360) { @@ -1286,6 +1290,10 @@ public class MapView extends FrameLayout { // Must handle window resizing here. @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + if(mDestroyed){ + return; + } + mNativeMapView.resizeFramebuffer(width, height); } @@ -1293,6 +1301,10 @@ public class MapView extends FrameLayout { // Must sync with UI here @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { + if(mDestroyed){ + return; + } + mCompassView.update(getDirection()); mUserLocationView.update(); for (InfoWindow infoWindow : mMapboxMap.getInfoWindows()) { From abec88642bb7fa6753a87c169fb2a4c1e96bfd07 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 10:17:57 -0500 Subject: [PATCH 053/104] [android] [ios] #4432 - Splitting the CHANGELOG into iOS and Android specific CHANGELOGS --- CHANGELOG.md | 266 +--------------------------------- platform/android/CHANGELOG.md | 67 +++++++++ platform/ios/CHANGELOG.md | 202 ++++++++++++++++++++++++++ 3 files changed, 272 insertions(+), 263 deletions(-) create mode 100644 platform/android/CHANGELOG.md create mode 100644 platform/ios/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 2756f579b..a18492c1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,266 +1,6 @@ # Changelog -## Android +As of iOS 3.2.0 and Android 4.0.0 we've split the CHANGELOG into platform specific CHANGELOGS to make it easier to follow the progress of a particular project. Their new locations are as follows: -## 4.0.0-beta.2 - -* arm64 ABI Support ([#3128](https://github.com/mapbox/mapbox-gl-native/issues/3128)) -* Unify Offline And Cache Databases ([#4362](https://github.com/mapbox/mapbox-gl-native/issues/4362)) -* Offline Database Vacuuming ([#4342](https://github.com/mapbox/mapbox-gl-native/pull/4342)) -* Telemetry User Agent Fix ([#4328](https://github.com/mapbox/mapbox-gl-native/issues/4328)) -* OnCameraChange Bug Fix ([#4327](https://github.com/mapbox/mapbox-gl-native/issues/4327)) -* OnCameraChangeListener vs getCameraPosition ([#4326](https://github.com/mapbox/mapbox-gl-native/issues/4326)) - -## 4.0.0-beta.1 - -Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major new features being released. To help us produce the highest quality SDK possible we're releasing an official Beta release first so that everyone has time to explore it and help hardened it before the official 4.0.0 Final Release. - -* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145)) -* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891)) -* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421)) - -## 3.2.0 - -* Fixed crash caused by annotation image with non-integer width or height ([#3031](https://github.com/mapbox/mapbox-gl-native/issues/3031)) -* Tracking Mode Reverses Bearing Fix ([#3664](https://github.com/mapbox/mapbox-gl-native/issues/3664)) -* GPS Extra Rotation Fix ([#3661](https://github.com/mapbox/mapbox-gl-native/issues/3661)) -* Added new methods for getting and setting the min and max zoom levels: `getMinZoom`, `setMinZoom`, `getMaxZoom`, `setMaxZoom`. ([#509](https://github.com/mapbox/mapbox-gl-native/issues/509)) - -## 3.1.0 - -* Camera API Callback Improvements ([#3412](https://github.com/mapbox/mapbox-gl-native/issues/3412)) -* Coordinate Deprecated For LatLng ([#3309](https://github.com/mapbox/mapbox-gl-native/issues/3309)) -* Responsive User Dot Location Tracking ([#2049](https://github.com/mapbox/mapbox-gl-native/issues/2049)) - -## 3.0.0 - -* Added Camera API ([#3244](https://github.com/mapbox/mapbox-gl-native/issues/3244)) -* Custom Layer Support ([#3248](https://github.com/mapbox/mapbox-gl-native/issues/3348)) -* Reverse Tilt Gesutre Detection ([#3245](https://github.com/mapbox/mapbox-gl-native/issues/3245)) -* Decoupled Location Provider ([#2954](https://github.com/mapbox/mapbox-gl-native/issues/2954)) - -## 2.3.0 - -* Added Tilt / Pitch Support ([#2805](https://github.com/mapbox/mapbox-gl-native/issues/2805)) -* Keep InfoWindow Open When Panning ([#3121](https://github.com/mapbox/mapbox-gl-native/issues/3121)) -* Concurrent Multiple Open InfoWindows ([#3115](https://github.com/mapbox/mapbox-gl-native/issues/3115)) -* OkHttp Replace curl ([#2856](https://github.com/mapbox/mapbox-gl-native/issues/2856)) -* GPS and Compass Customization Support ([#2858](https://github.com/mapbox/mapbox-gl-native/issues/2858)) - -## 2.2.0 - -- New User Dot location graphics ([#2732](https://github.com/mapbox/mapbox-gl-native/issues/2732)) -- Custom Drawable Markers ([#2744](https://github.com/mapbox/mapbox-gl-native/issues/2744)) -- `MapView.setOnInfoWindowClickListener()` support ([#2448](https://github.com/mapbox/mapbox-gl-native/issues/2448)) -- Completed Annotations API ([#1716](https://github.com/mapbox/mapbox-gl-native/issues/1716)) -- 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 - -- 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 - -## iOS 3.2.0 - -- Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) -- Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) -- The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) -- The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) -- Fixed an issue causing the map to pan the wrong way when the user pinches unevenly. ([#4427](https://github.com/mapbox/mapbox-gl-native/pull/4427)) -- An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839)) -- Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) -- Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) -- An account’s monthly active users metric only counts a user once a map view is displayed to that user. ([#3713](https://github.com/mapbox/mapbox-gl-native/pull/3713)) -- A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. -- Updated documentation to reflect the requirement that you must embed the framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) -- Polygons and polylines now default to using the map view’s tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028)) -- The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) -- The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) -- Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) -- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417))) - -## iOS 3.1.2 - -- You can once again install the static framework without manually linking several framework and library dependencies. ([#4029](https://github.com/mapbox/mapbox-gl-native/pull/4029)) -- The location manager used by MGLMapView to show the user’s location is now paused when the application is sent to the background. ([#4034](https://github.com/mapbox/mapbox-gl-native/pull/4034)) - -## iOS 3.1.1 - -- Corrected the dynamic framework’s minimum deployment target to iOS 8.0. ([#3872](https://github.com/mapbox/mapbox-gl-native/pull/3872)) -- Fixed Fabric compatibility. ([#3847](https://github.com/mapbox/mapbox-gl-native/pull/3847)) -- Fixed a crash that can occur when reselecting an annotation. ([#3881](https://github.com/mapbox/mapbox-gl-native/pull/3881)) -- Fixed an issue preventing the Latitude inspectable from working when it is set before setting the Zoom Level inspectable in Interface Builder. ([#3886](https://github.com/mapbox/mapbox-gl-native/pull/3886)) -- Fixed an issue that incorrectly expanded the tappable area of an annotation and prevented the annotation’s alignment rect insets from having any effect on the tappable area. ([#3898](https://github.com/mapbox/mapbox-gl-native/pull/3898)) -- Fixed an issue preventing `-[MGLMapViewDelegate mapView:tapOnCalloutForAnnotation:]` from being called when a non-custom callout view is tapped. ([#3875](https://github.com/mapbox/mapbox-gl-native/pull/3875)) - -## iOS 3.1.0 - -- The SDK is now distributed as a dynamic framework instead of a static library, resulting in a simpler installation workflow and significantly reduced download size. The framework contains both simulator and device content. If you install the dynamic framework manually, you’ll need to strip out the simulator content before submitting your application to the App Store due to [an Xcode bug](http://www.openradar.me/radar?id=6409498411401216); see the installation instructions included with the framework for details. ([#3183](https://github.com/mapbox/mapbox-gl-native/pull/3183)) -- Fixed an issue causing the entire MGLMapView to leak. ([#3448](https://github.com/mapbox/mapbox-gl-native/pull/3448)) -- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090)) -- You can now modify an annotation’s image after adding the annotation to the map. ([#3146](https://github.com/mapbox/mapbox-gl-native/pull/3146)) -- Tapping now selects annotations more reliably. Tapping near the top of a large annotation image now selects that annotation. An annotation image’s alignment insets influence how far away the user can tap and still select the annotation. For example, if your annotation image has a large shadow, you can keep that shadow from being tappable by excluding it from the image’s alignment rect. ([#3261](https://github.com/mapbox/mapbox-gl-native/pull/3261)) -- Annotations remain visible after switching to a different style. ([#3049](https://github.com/mapbox/mapbox-gl-native/pull/3049)) -- The minimum and maximum zoom levels can now be configured using the `minimumZoomLevel` and `maximumZoomLevel` properties, respectively. The map is no longer limited to zoom level 18: by default, the maximum zoom level is now 20, allowing for a more detailed map in urban areas. ([#3712](https://github.com/mapbox/mapbox-gl-native/pull/3712)) -- A new method on MGLMapView, `-flyToCamera:withDuration:completionHandler:`, lets you transition between viewpoints along an arc as if by aircraft. ([#3171](https://github.com/mapbox/mapbox-gl-native/pull/3171), [#3301](https://github.com/mapbox/mapbox-gl-native/pull/3301)) -- MGLMapCamera’s `altitude` values now match those of MKMapCamera. ([#3362](https://github.com/mapbox/mapbox-gl-native/pull/3362)) -- MGLMapView properties like `centerCoordinate` and `camera` now offset the center to account for any translucent top or bottom bar. As a result, when user tracking is enabled and the map view is an immediate child of a view controller, the user dot is centered in the unobscured portion of the map view. To override this offset, modify the `contentInset` property; you may also need to set the containing view controller’s `automaticallyAdjustsScrollViewInsets` property to `NO`. ([#3583](https://github.com/mapbox/mapbox-gl-native/pull/3583)) -- In user tracking mode, the user dot stays in a fixed position within MGLMapView while the map pans smoothly. A new property, `userLocationVerticalAlignment`, determines the user dot’s fixed position. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) -- When the user tracking mode is set to `MGLUserTrackingModeFollowWithCourse`, an optional `targetCoordinate` is kept within sight at all times as the user changes location. This property, in conjunction with the `userLocationVerticalAlignment` property, may be useful for displaying the user’s progress toward a waypoint. ([#3680](https://github.com/mapbox/mapbox-gl-native/pull/3680)) -- Heading or course tracking mode can now be enabled as soon as an MGLMapView is initialized. ([#3680](https://github.com/mapbox/mapbox-gl-native/pull/3680)) -- Zooming and rotation gestures no longer disable user tracking mode. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) -- User tracking mode starts out at a lower zoom level by default. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) -- Fixed an issue with small map views not properly fitting annotations within bounds. (#[3407](https://github.com/mapbox/mapbox-gl-native/pull/3407)) -- When the user rotates the map to within 7° of true north, the map view now snaps to true north. ([#3403](https://github.com/mapbox/mapbox-gl-native/pull/3403)) -- The map view’s background can now be transparent or translucent, as long as the style’s background layer is transparent or translucent and `MGLMapView.opaque` is set to `NO`. ([#3096](https://github.com/mapbox/mapbox-gl-native/pull/3096)) -- Documentation is now generated by [jazzy](https://github.com/realm/jazzy) instead of appledoc. ♪♫ ([#3203](https://github.com/mapbox/mapbox-gl-native/pull/3203)) -- New API to provide a custom callout view to the map for annotations. ([#3456](https://github.com/mapbox/mapbox-gl-native/pull/3456)) -- Made telemetry on/off setting available in-app. ([#3445](https://github.com/mapbox/mapbox-gl-native/pull/3445)) -- Fixed an issue with users not being counted by Mapbox if they had disabled telemetry. ([#3495](https://github.com/mapbox/mapbox-gl-native/pull/3495)) -- Fixed crash caused by MGLAnnotationImage with non-integer width or height ([#2198](https://github.com/mapbox/mapbox-gl-native/issues/2198)) -- Fixed “include of non-modular header” errors in Swift projects managed by CocoaPods. ([#3679](https://github.com/mapbox/mapbox-gl-native/pull/3679)) -- Avoids triggering the blue background location status bar when user has granted "when in use" permission. ([#3671](https://github.com/mapbox/mapbox-gl-native/issues/3671)) -- Deprecated the `debugActive` property and `-toggleDebug` method on MGLMapView in favor of a new `debugMask` property that exposes individual style debugging options. ([#3742](https://github.com/mapbox/mapbox-gl-native/pull/3742)) - -## iOS 3.0.1 - -- Fixed CoreTelephony.framework crash. ([#3170](https://github.com/mapbox/mapbox-gl-native/pull/3170)) -- Fixed an issue preventing the compass from responding to taps after the compass is moved programmatically. ([#3117](https://github.com/mapbox/mapbox-gl-native/pull/3117)) -- CocoaPods is now distributed via a (static) framework. ([#3181](https://github.com/mapbox/mapbox-gl-native/issues/3181)) - -## iOS 3.0.0 - -- If you install this SDK via CocoaPods, CocoaPods version 0.38.0 or above is required. ([#2132](https://github.com/mapbox/mapbox-gl-native/pull/2132)) -- The `styleID` property has been removed from MGLMapView. Instead, set the `styleURL` property to an NSURL in the form `mapbox://styles/STYLE_ID`. If you previously set the style ID in Interface Builder’s Attributes inspector, delete the `styleID` entry from the User Defined Runtime Attributes section of the Identity inspector, then set the new “Style URL” inspectable to a value in the form `mapbox://styles/STYLE_ID`. ([#2632](https://github.com/mapbox/mapbox-gl-native/pull/2632)) -- Default styles such as Streets are no longer bundled with the SDK; instead, they are loaded at runtime from the style API on mapbox.com. As always, you can use these default styles with any valid access token, and Streets continues to be `MGLMapView`’s initial style. The `bundledStyleURLs` property on `MGLMapView` has been deprecated in favor of several class methods on `MGLStyle` that provide direct access to the default styles. ([#2746](https://github.com/mapbox/mapbox-gl-native/pull/2746)) -- The SDK now builds with Bitcode enabled. A version of libMapbox.a with Bitcode disabled is also available. ([#2332](https://github.com/mapbox/mapbox-gl-native/issues/2332), [#3003](https://github.com/mapbox/mapbox-gl-native/pull/3003)) -- The style URL can be set to a local resource: `asset://local-color.json` and `local-color.json` both resolve to a file named `local-color.json` in the application’s root folder. ([#3087](https://github.com/mapbox/mapbox-gl-native/pull/3087)) -- The double-tap-drag gesture for zooming in and out is now consistent with the Google Maps SDK. ([#2153](https://github.com/mapbox/mapbox-gl-native/pull/2153)) -- A new `MGLAnnotationImage.enabled` property allows you to disable touch events on individual annotations. ([#2501](https://github.com/mapbox/mapbox-gl-native/pull/2501)) -- Fixed a rendering issue that caused one-way arrows along tile boundaries to point due east instead of in the direction of travel. ([#2530](https://github.com/mapbox/mapbox-gl-native/pull/2530)) -- Fixed an issue that prevented zoom level–dependent style properties from updating after zooming programmatically with animation. ([#2951](https://github.com/mapbox/mapbox-gl-native/pull/2951)) -- Performance and appearance improvements during annotation adds & removes. ([#1688](https://github.com/mapbox/mapbox-gl-native/issues/1688)) -- Overall improved performance during renders by not rendering faster than necessary. ([#1975](https://github.com/mapbox/mapbox-gl-native/issues/1975)) -- Fixed a rendering issue with styles that use the `background-pattern` property. ([#2531](https://github.com/mapbox/mapbox-gl-native/pull/2531)) -- Fixed a crash when reusing a single `MGLMapView` across multiple `UIViewController`s. ([#2969](https://github.com/mapbox/mapbox-gl-native/pull/2969)) -- Fixed a crash on iPod touch and other devices or simulators without a cell carrier. ([#2687](https://github.com/mapbox/mapbox-gl-native/issues/2687)) -- Eliminated flickering when opening and closing an overlay, such as an alert or action sheet. ([#2309](https://github.com/mapbox/mapbox-gl-native/pull/2309)) -- Labels can now line wrap on hyphens and other punctuation. ([#2598](https://github.com/mapbox/mapbox-gl-native/pull/2598)) -- A new delegate callback was added for observing taps to annotation callout views. ([#2596](https://github.com/mapbox/mapbox-gl-native/pull/2596)) -- `-mapViewRegionIsChanging:` is now sent to the map view’s delegate during gestures. ([#2700](https://github.com/mapbox/mapbox-gl-native/pull/2700)) -- Improved gesture recognition while the map is tilted. ([#2770](https://github.com/mapbox/mapbox-gl-native/pull/2770)) -- `-mapViewWillStartLoadingMap:` and `-mapViewDidFinishLoadingMap:` delegate methods now work. ([#2706](https://github.com/mapbox/mapbox-gl-native/pull/2706)) -- Removed CoreTelephony.framework dependency. ([#2581](https://github.com/mapbox/mapbox-gl-native/pull/2581)) -- Improved user location annotation responsiveness. ([#2643](https://github.com/mapbox/mapbox-gl-native/pull/2643)) - -## iOS 2.1.2 - -- Built with Xcode 6.4 to not yet trigger Bitcode compatibility until Xcode 7 stabilizes. ([#2332](https://github.com/mapbox/mapbox-gl-native/issues/2332)) - -## iOS 2.1.1 - -- Fixes for Xcode 7 and Bitcode. ([#2238](https://github.com/mapbox/mapbox-gl-native/pull/2238)) - -## iOS 2.1.0 - -- A two-finger vertical swipe now tilts the map into perspective mode. ([#2116](https://github.com/mapbox/mapbox-gl-native/pull/2116)) -- A new `MGLMapCamera` API allows you to transition multiple viewpoint properties, including rotation and pitch, simultaneously with an optional custom duration and timing function. ([#2193](https://github.com/mapbox/mapbox-gl-native/pull/2193)) -- A new user tracking mode, `MGLUserTrackingModeFollowWithCourse`, has been added for indicating the current direction of travel. ([#2068](https://github.com/mapbox/mapbox-gl-native/pull/2068)) -- Version 8 (`v8`) of the [Mapbox GL style spec](https://www.mapbox.com/mapbox-gl-style-spec/) is now required. If you are using a custom `v7` style, it needs to be upgraded using [this migrator script](https://github.com/mapbox/mapbox-gl-style-spec/blob/mb-pages/migrations/v7.js). ([#2052](https://github.com/mapbox/mapbox-gl-native/pull/2052)) -- Applications built with Mapbox GL no longer crash when Location Services launches them in background mode. ([#1821](https://github.com/mapbox/mapbox-gl-native/pull/1821), [#1869](https://github.com/mapbox/mapbox-gl-native/pull/1869)) -- Fixed a crash when adding annotations to an `MGLMapView` inside `-viewDidLoad`. ([#1874](https://github.com/mapbox/mapbox-gl-native/pull/1874)) -- The user location annotation view now indicates the location reading’s accuracy and the device’s heading. ([#2010](https://github.com/mapbox/mapbox-gl-native/pull/2010)) -- Eliminated linker warnings and errors when building against the iOS 9.0 SDK in Xcode 7. ([#1962](https://github.com/mapbox/mapbox-gl-native/pull/1962)) -- Worked around a bug in the iOS 9.0 SDK that caused a crash on launch. ([#1958](https://github.com/mapbox/mapbox-gl-native/pull/1958)) -- User location tracking no longer sends `MGLMapView` into an invalid region on iOS 9. ([#1925](https://github.com/mapbox/mapbox-gl-native/pull/1925)) -- Eliminated console spew in the iOS demo application that was related to Mapbox Metrics HTTP requests. ([#1937](https://github.com/mapbox/mapbox-gl-native/issues/1937)) -- Implemented `-[MGLMapView showAnnotations:animated:]`. ([#2050](https://github.com/mapbox/mapbox-gl-native/pull/2050)) -- Fixed a crash adding a shape annotation with zero points. ([#2098](https://github.com/mapbox/mapbox-gl-native/pull/2098)) -- Debug mode now displays information useful for debugging the label collision algorithm. ([#1808](https://github.com/mapbox/mapbox-gl-native/pull/1808)) -- Minor style updates. ([#1910](https://github.com/mapbox/mapbox-gl-native/pull/1910)) -- The CocoaPods pod now contains a `README.md` file. ([#1886](https://github.com/mapbox/mapbox-gl-native/pull/1886)) - -## iOS 2.0.0 - -Repackaging 2.0.0-pre.1 as it contained no issues. - -## iOS 2.0.0-pre.1 - -Repackaging 0.5.1 as the Mapbox iOS SDK 2.0.0 series. - -## 0.5.1 - -### iOS - -- Added support for CocoaPods 0.38.0. ([#1876](https://github.com/mapbox/mapbox-gl-native/pull/1876)) - -## 0.5.0 - -### Core - -- Support for runtime marker imagery. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) -- Added `Map::fitBounds()` for region-based viewport setting. ([#1092](https://github.com/mapbox/mapbox-gl-native/issues/1092)) -- Added a raster satellite bundled style and improved raster rendering. ([#963](https://github.com/mapbox/mapbox-gl-native/issues/963)) -- Improved round line joins for semi-transparent lines. ([#1839](https://github.com/mapbox/mapbox-gl-native/pull/1839)) -- Improved map render lifecycle notifications. ([#1026](https://github.com/mapbox/mapbox-gl-native/issues/1026)) -- Fixed a bug that caused annotations not to show at zoom level zero. ([#1279](https://github.com/mapbox/mapbox-gl-native/issues/1279)) -- Fixed a bug with the ordering of shape layers. ([#1866](https://github.com/mapbox/mapbox-gl-native/pull/1866)) -- Other bug fixes and performance improvements. - -### iOS - -- **Breaking:** Headers now make use of lightweight generics, eliminating many unnecessary casts when working with annotations in Swift 2.0 in Xcode 7. ([#1711](https://github.com/mapbox/mapbox-gl-native/pull/1711)) -- **Breaking:** `-mapView:symbolNameForAnnotation:` has been removed from the `MGLMapViewDelegate` protocol. Implement `-mapView:imageForAnnotation:` instead, which accepts images at runtime. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) -- **Breaking:** `MGLMapView.direction` is now expressed in terms of degrees clockwise from true north, as indicated in the documentation, rather than counterclockwise. ([#1789](https://github.com/mapbox/mapbox-gl-native/pull/1789)) -- A Satellite style showing Mapbox Satellite imagery is now bundled with Mapbox GL. ([#1845](https://github.com/mapbox/mapbox-gl-native/pull/1845)) -- Improved `UIView` tracking to the map. ([#1813](https://github.com/mapbox/mapbox-gl-native/pull/1813)) -- Delegate method `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` now works. ([#1608](https://github.com/mapbox/mapbox-gl-native/pull/1608)) -- It is now possible to fit the map’s viewport to a coordinate bounding box via `-[MGLMapView setVisibleCoordinateBounds:animated:]` or to a specific set of coordinates via `-[MGLMapView setVisibleCoordinates:count:edgePadding:animated:]`. ([#1783](https://github.com/mapbox/mapbox-gl-native/pull/1783), [#1795](https://github.com/mapbox/mapbox-gl-native/pull/1795)) -- The logo and ℹ️ no longer disappear or get distorted after embedding MGLMapView in a different view, and you can now access these subviews directly via properties on MGLMapView. ([#1779](https://github.com/mapbox/mapbox-gl-native/pull/1779), [#1815](https://github.com/mapbox/mapbox-gl-native/pull/1815)) -- Raster tiles now look sharper midway between two zoom levels. ([#1843](https://github.com/mapbox/mapbox-gl-native/pull/1843)) -- Resetting the map rotation to north no longer also resets the user location tracking mode. ([#1809](https://github.com/mapbox/mapbox-gl-native/pull/1809)) -- `-[MGLMapView convertPoint:toCoordinateFromView:]` now returns accurate coordinates on iPhone 6. ([#1827](https://github.com/mapbox/mapbox-gl-native/pull/1827)) -- Fixed an issue in which `-[MGLMapView direction]` would sometimes return 360 instead of 0. ([#1829](https://github.com/mapbox/mapbox-gl-native/pull/1829)) -- Build against iOS 8.4. ([#1868](https://github.com/mapbox/mapbox-gl-native/pull/1868)) - -## 0.4.0 - -### Core - -- Support for polyline and polygon shape annotations. ([#1655](https://github.com/mapbox/mapbox-gl-native/issues/1655)) -- Improved placement and density of labels. ([#1666](https://github.com/mapbox/mapbox-gl-native/issues/1666), [blog](https://www.mapbox.com/blog/better-label-placement-mapbox-mobile/)) -- Improved z-ordering appearance of point markers. ([#988](https://github.com/mapbox/mapbox-gl-native/issues/988)) -- Fixed an issue in which certain features, such as roundabouts, were not rendered completely. ([#1725](https://github.com/mapbox/mapbox-gl-native/issues/1725)) -- Many bug fixes and performance and stability improvements. -- Improved tests. - -### iOS - -- **Breaking:** `MGLMapView` no longer manages Mapbox access tokens directly; an access token cannot be passed in when initializing the map view. Instead, set `MGLMapboxAccessToken` to your access token in your app’s `Info.plist` file, or call `+[MGLAccountManager setAccessToken:]` before initializing the map view. If you were setting the access token inside an Interface Builder inspectable, also remove it from the User Defined Runtime Attributes section of the Identity inspector. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553)) -- **Breaking:** `MGLAccountManager`'s `-setMapboxMetricsEnabledSettingShownInApp:` has been removed. If you implement a Mapbox Metrics switch inside your app, instead of inside a Settings bundle, set `MGLMapboxMetricsEnabledSettingShownInApp` to `YES` in the `Info.plist` file. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553)) -- **Breaking:** `MGLMapView`'s `-mapID` has been renamed to `-styleID`. ([#1561](https://github.com/mapbox/mapbox-gl-native/issues/1561)) -- Headers have been audited for nullability, improving type safety in both Objective-C and Swift 1.2 when compiling with Xcode 6.3 or above. ([#1578](https://github.com/mapbox/mapbox-gl-native/issues/1578)) -- Fixed an issue in which the map would sometimes spin 180° while rotating the map with two fingers. ([#1453](https://github.com/mapbox/mapbox-gl-native/issues/1453)) -- Added a shortcut to the Mapbox Metrics switch in `MGLMapView`'s action sheet that is attached to the ℹ️ button. ([#1611](https://github.com/mapbox/mapbox-gl-native/issues/1611)) -- `MGLMapView` now supports Interface Builder designables. When you add an `MGLMapView` to a storyboard, it displays instructions for getting set up directly on the storyboard canvas. ([#1573](https://github.com/mapbox/mapbox-gl-native/issues/1573)) -- The default title for the user location annotation is now “You Are Here”. You can customize the title by setting `mapView.userAnnotation.title`. ([#1559](https://github.com/mapbox/mapbox-gl-native/issues/1559)) -- Internal use of the Reachability library has been cleaned up so that your app can include its own copy of Reachability. ([#1718](https://github.com/mapbox/mapbox-gl-native/issues/1718)) -- Now distribute a binary stripped of debugging symbols by default with an optional, secondary symbols build. ([#1650](https://github.com/mapbox/mapbox-gl-native/issues/1650)) - -## 0.3.1 - -- Temporarily removed `IBDesignable` support on iOS. - -## 0.3.0 - -- Initial iOS beta release. - -Known issues: - -- None. +* iOS --> [`/platform/ios/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/ios/CHANGELOG.md) +* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/android/CHANGELOG.md) \ No newline at end of file diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md new file mode 100644 index 000000000..135d8a7cc --- /dev/null +++ b/platform/android/CHANGELOG.md @@ -0,0 +1,67 @@ +# Changelog for Mapbox Android SDK + +Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. + +## 4.0.0-beta.2 + +* arm64 ABI Support ([#3128](https://github.com/mapbox/mapbox-gl-native/issues/3128)) +* Unify Offline And Cache Databases ([#4362](https://github.com/mapbox/mapbox-gl-native/issues/4362)) +* Offline Database Vacuuming ([#4342](https://github.com/mapbox/mapbox-gl-native/pull/4342)) +* Telemetry User Agent Fix ([#4328](https://github.com/mapbox/mapbox-gl-native/issues/4328)) +* OnCameraChange Bug Fix ([#4327](https://github.com/mapbox/mapbox-gl-native/issues/4327)) +* OnCameraChangeListener vs getCameraPosition ([#4326](https://github.com/mapbox/mapbox-gl-native/issues/4326)) + +## 4.0.0-beta.1 + +Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major new features being released. To help us produce the highest quality SDK possible we're releasing an official Beta release first so that everyone has time to explore it and help hardened it before the official 4.0.0 Final Release. + +* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145)) +* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891)) +* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421)) + +## 3.2.0 + +* Fixed crash caused by annotation image with non-integer width or height ([#3031](https://github.com/mapbox/mapbox-gl-native/issues/3031)) +* Tracking Mode Reverses Bearing Fix ([#3664](https://github.com/mapbox/mapbox-gl-native/issues/3664)) +* GPS Extra Rotation Fix ([#3661](https://github.com/mapbox/mapbox-gl-native/issues/3661)) +* Added new methods for getting and setting the min and max zoom levels: `getMinZoom`, `setMinZoom`, `getMaxZoom`, `setMaxZoom`. ([#509](https://github.com/mapbox/mapbox-gl-native/issues/509)) + +## 3.1.0 + +* Camera API Callback Improvements ([#3412](https://github.com/mapbox/mapbox-gl-native/issues/3412)) +* Coordinate Deprecated For LatLng ([#3309](https://github.com/mapbox/mapbox-gl-native/issues/3309)) +* Responsive User Dot Location Tracking ([#2049](https://github.com/mapbox/mapbox-gl-native/issues/2049)) + +## 3.0.0 + +* Added Camera API ([#3244](https://github.com/mapbox/mapbox-gl-native/issues/3244)) +* Custom Layer Support ([#3248](https://github.com/mapbox/mapbox-gl-native/issues/3348)) +* Reverse Tilt Gesutre Detection ([#3245](https://github.com/mapbox/mapbox-gl-native/issues/3245)) +* Decoupled Location Provider ([#2954](https://github.com/mapbox/mapbox-gl-native/issues/2954)) + +## 2.3.0 + +* Added Tilt / Pitch Support ([#2805](https://github.com/mapbox/mapbox-gl-native/issues/2805)) +* Keep InfoWindow Open When Panning ([#3121](https://github.com/mapbox/mapbox-gl-native/issues/3121)) +* Concurrent Multiple Open InfoWindows ([#3115](https://github.com/mapbox/mapbox-gl-native/issues/3115)) +* OkHttp Replace curl ([#2856](https://github.com/mapbox/mapbox-gl-native/issues/2856)) +* GPS and Compass Customization Support ([#2858](https://github.com/mapbox/mapbox-gl-native/issues/2858)) + +## 2.2.0 + +- New User Dot location graphics ([#2732](https://github.com/mapbox/mapbox-gl-native/issues/2732)) +- Custom Drawable Markers ([#2744](https://github.com/mapbox/mapbox-gl-native/issues/2744)) +- `MapView.setOnInfoWindowClickListener()` support ([#2448](https://github.com/mapbox/mapbox-gl-native/issues/2448)) +- Completed Annotations API ([#1716](https://github.com/mapbox/mapbox-gl-native/issues/1716)) +- 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 + +- 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 \ No newline at end of file diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md new file mode 100644 index 000000000..3938249c5 --- /dev/null +++ b/platform/ios/CHANGELOG.md @@ -0,0 +1,202 @@ +# Changelog for Mapbox iOS SDK + +Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. + +## iOS 3.2.0 + +- Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) +- Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) +- The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) +- The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) +- Fixed an issue causing the map to pan the wrong way when the user pinches unevenly. ([#4427](https://github.com/mapbox/mapbox-gl-native/pull/4427)) +- An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839)) +- Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) +- Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) +- An account’s monthly active users metric only counts a user once a map view is displayed to that user. ([#3713](https://github.com/mapbox/mapbox-gl-native/pull/3713)) +- A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. +- Updated documentation to reflect the requirement that you must embed the framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) +- Polygons and polylines now default to using the map view’s tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028)) +- The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) +- The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) +- Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) +- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417))) + +## iOS 3.1.2 + +- You can once again install the static framework without manually linking several framework and library dependencies. ([#4029](https://github.com/mapbox/mapbox-gl-native/pull/4029)) +- The location manager used by MGLMapView to show the user’s location is now paused when the application is sent to the background. ([#4034](https://github.com/mapbox/mapbox-gl-native/pull/4034)) + +## iOS 3.1.1 + +- Corrected the dynamic framework’s minimum deployment target to iOS 8.0. ([#3872](https://github.com/mapbox/mapbox-gl-native/pull/3872)) +- Fixed Fabric compatibility. ([#3847](https://github.com/mapbox/mapbox-gl-native/pull/3847)) +- Fixed a crash that can occur when reselecting an annotation. ([#3881](https://github.com/mapbox/mapbox-gl-native/pull/3881)) +- Fixed an issue preventing the Latitude inspectable from working when it is set before setting the Zoom Level inspectable in Interface Builder. ([#3886](https://github.com/mapbox/mapbox-gl-native/pull/3886)) +- Fixed an issue that incorrectly expanded the tappable area of an annotation and prevented the annotation’s alignment rect insets from having any effect on the tappable area. ([#3898](https://github.com/mapbox/mapbox-gl-native/pull/3898)) +- Fixed an issue preventing `-[MGLMapViewDelegate mapView:tapOnCalloutForAnnotation:]` from being called when a non-custom callout view is tapped. ([#3875](https://github.com/mapbox/mapbox-gl-native/pull/3875)) + +## iOS 3.1.0 + +- The SDK is now distributed as a dynamic framework instead of a static library, resulting in a simpler installation workflow and significantly reduced download size. The framework contains both simulator and device content. If you install the dynamic framework manually, you’ll need to strip out the simulator content before submitting your application to the App Store due to [an Xcode bug](http://www.openradar.me/radar?id=6409498411401216); see the installation instructions included with the framework for details. ([#3183](https://github.com/mapbox/mapbox-gl-native/pull/3183)) +- Fixed an issue causing the entire MGLMapView to leak. ([#3448](https://github.com/mapbox/mapbox-gl-native/pull/3448)) +- `MGLMapView` methods that alter the viewport now accept optional completion handlers. ([#3090](https://github.com/mapbox/mapbox-gl-native/pull/3090)) +- You can now modify an annotation’s image after adding the annotation to the map. ([#3146](https://github.com/mapbox/mapbox-gl-native/pull/3146)) +- Tapping now selects annotations more reliably. Tapping near the top of a large annotation image now selects that annotation. An annotation image’s alignment insets influence how far away the user can tap and still select the annotation. For example, if your annotation image has a large shadow, you can keep that shadow from being tappable by excluding it from the image’s alignment rect. ([#3261](https://github.com/mapbox/mapbox-gl-native/pull/3261)) +- Annotations remain visible after switching to a different style. ([#3049](https://github.com/mapbox/mapbox-gl-native/pull/3049)) +- The minimum and maximum zoom levels can now be configured using the `minimumZoomLevel` and `maximumZoomLevel` properties, respectively. The map is no longer limited to zoom level 18: by default, the maximum zoom level is now 20, allowing for a more detailed map in urban areas. ([#3712](https://github.com/mapbox/mapbox-gl-native/pull/3712)) +- A new method on MGLMapView, `-flyToCamera:withDuration:completionHandler:`, lets you transition between viewpoints along an arc as if by aircraft. ([#3171](https://github.com/mapbox/mapbox-gl-native/pull/3171), [#3301](https://github.com/mapbox/mapbox-gl-native/pull/3301)) +- MGLMapCamera’s `altitude` values now match those of MKMapCamera. ([#3362](https://github.com/mapbox/mapbox-gl-native/pull/3362)) +- MGLMapView properties like `centerCoordinate` and `camera` now offset the center to account for any translucent top or bottom bar. As a result, when user tracking is enabled and the map view is an immediate child of a view controller, the user dot is centered in the unobscured portion of the map view. To override this offset, modify the `contentInset` property; you may also need to set the containing view controller’s `automaticallyAdjustsScrollViewInsets` property to `NO`. ([#3583](https://github.com/mapbox/mapbox-gl-native/pull/3583)) +- In user tracking mode, the user dot stays in a fixed position within MGLMapView while the map pans smoothly. A new property, `userLocationVerticalAlignment`, determines the user dot’s fixed position. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) +- When the user tracking mode is set to `MGLUserTrackingModeFollowWithCourse`, an optional `targetCoordinate` is kept within sight at all times as the user changes location. This property, in conjunction with the `userLocationVerticalAlignment` property, may be useful for displaying the user’s progress toward a waypoint. ([#3680](https://github.com/mapbox/mapbox-gl-native/pull/3680)) +- Heading or course tracking mode can now be enabled as soon as an MGLMapView is initialized. ([#3680](https://github.com/mapbox/mapbox-gl-native/pull/3680)) +- Zooming and rotation gestures no longer disable user tracking mode. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) +- User tracking mode starts out at a lower zoom level by default. ([#3589](https://github.com/mapbox/mapbox-gl-native/pull/3589)) +- Fixed an issue with small map views not properly fitting annotations within bounds. (#[3407](https://github.com/mapbox/mapbox-gl-native/pull/3407)) +- When the user rotates the map to within 7° of true north, the map view now snaps to true north. ([#3403](https://github.com/mapbox/mapbox-gl-native/pull/3403)) +- The map view’s background can now be transparent or translucent, as long as the style’s background layer is transparent or translucent and `MGLMapView.opaque` is set to `NO`. ([#3096](https://github.com/mapbox/mapbox-gl-native/pull/3096)) +- Documentation is now generated by [jazzy](https://github.com/realm/jazzy) instead of appledoc. ♪♫ ([#3203](https://github.com/mapbox/mapbox-gl-native/pull/3203)) +- New API to provide a custom callout view to the map for annotations. ([#3456](https://github.com/mapbox/mapbox-gl-native/pull/3456)) +- Made telemetry on/off setting available in-app. ([#3445](https://github.com/mapbox/mapbox-gl-native/pull/3445)) +- Fixed an issue with users not being counted by Mapbox if they had disabled telemetry. ([#3495](https://github.com/mapbox/mapbox-gl-native/pull/3495)) +- Fixed crash caused by MGLAnnotationImage with non-integer width or height ([#2198](https://github.com/mapbox/mapbox-gl-native/issues/2198)) +- Fixed “include of non-modular header” errors in Swift projects managed by CocoaPods. ([#3679](https://github.com/mapbox/mapbox-gl-native/pull/3679)) +- Avoids triggering the blue background location status bar when user has granted "when in use" permission. ([#3671](https://github.com/mapbox/mapbox-gl-native/issues/3671)) +- Deprecated the `debugActive` property and `-toggleDebug` method on MGLMapView in favor of a new `debugMask` property that exposes individual style debugging options. ([#3742](https://github.com/mapbox/mapbox-gl-native/pull/3742)) + +## iOS 3.0.1 + +- Fixed CoreTelephony.framework crash. ([#3170](https://github.com/mapbox/mapbox-gl-native/pull/3170)) +- Fixed an issue preventing the compass from responding to taps after the compass is moved programmatically. ([#3117](https://github.com/mapbox/mapbox-gl-native/pull/3117)) +- CocoaPods is now distributed via a (static) framework. ([#3181](https://github.com/mapbox/mapbox-gl-native/issues/3181)) + +## iOS 3.0.0 + +- If you install this SDK via CocoaPods, CocoaPods version 0.38.0 or above is required. ([#2132](https://github.com/mapbox/mapbox-gl-native/pull/2132)) +- The `styleID` property has been removed from MGLMapView. Instead, set the `styleURL` property to an NSURL in the form `mapbox://styles/STYLE_ID`. If you previously set the style ID in Interface Builder’s Attributes inspector, delete the `styleID` entry from the User Defined Runtime Attributes section of the Identity inspector, then set the new “Style URL” inspectable to a value in the form `mapbox://styles/STYLE_ID`. ([#2632](https://github.com/mapbox/mapbox-gl-native/pull/2632)) +- Default styles such as Streets are no longer bundled with the SDK; instead, they are loaded at runtime from the style API on mapbox.com. As always, you can use these default styles with any valid access token, and Streets continues to be `MGLMapView`’s initial style. The `bundledStyleURLs` property on `MGLMapView` has been deprecated in favor of several class methods on `MGLStyle` that provide direct access to the default styles. ([#2746](https://github.com/mapbox/mapbox-gl-native/pull/2746)) +- The SDK now builds with Bitcode enabled. A version of libMapbox.a with Bitcode disabled is also available. ([#2332](https://github.com/mapbox/mapbox-gl-native/issues/2332), [#3003](https://github.com/mapbox/mapbox-gl-native/pull/3003)) +- The style URL can be set to a local resource: `asset://local-color.json` and `local-color.json` both resolve to a file named `local-color.json` in the application’s root folder. ([#3087](https://github.com/mapbox/mapbox-gl-native/pull/3087)) +- The double-tap-drag gesture for zooming in and out is now consistent with the Google Maps SDK. ([#2153](https://github.com/mapbox/mapbox-gl-native/pull/2153)) +- A new `MGLAnnotationImage.enabled` property allows you to disable touch events on individual annotations. ([#2501](https://github.com/mapbox/mapbox-gl-native/pull/2501)) +- Fixed a rendering issue that caused one-way arrows along tile boundaries to point due east instead of in the direction of travel. ([#2530](https://github.com/mapbox/mapbox-gl-native/pull/2530)) +- Fixed an issue that prevented zoom level–dependent style properties from updating after zooming programmatically with animation. ([#2951](https://github.com/mapbox/mapbox-gl-native/pull/2951)) +- Performance and appearance improvements during annotation adds & removes. ([#1688](https://github.com/mapbox/mapbox-gl-native/issues/1688)) +- Overall improved performance during renders by not rendering faster than necessary. ([#1975](https://github.com/mapbox/mapbox-gl-native/issues/1975)) +- Fixed a rendering issue with styles that use the `background-pattern` property. ([#2531](https://github.com/mapbox/mapbox-gl-native/pull/2531)) +- Fixed a crash when reusing a single `MGLMapView` across multiple `UIViewController`s. ([#2969](https://github.com/mapbox/mapbox-gl-native/pull/2969)) +- Fixed a crash on iPod touch and other devices or simulators without a cell carrier. ([#2687](https://github.com/mapbox/mapbox-gl-native/issues/2687)) +- Eliminated flickering when opening and closing an overlay, such as an alert or action sheet. ([#2309](https://github.com/mapbox/mapbox-gl-native/pull/2309)) +- Labels can now line wrap on hyphens and other punctuation. ([#2598](https://github.com/mapbox/mapbox-gl-native/pull/2598)) +- A new delegate callback was added for observing taps to annotation callout views. ([#2596](https://github.com/mapbox/mapbox-gl-native/pull/2596)) +- `-mapViewRegionIsChanging:` is now sent to the map view’s delegate during gestures. ([#2700](https://github.com/mapbox/mapbox-gl-native/pull/2700)) +- Improved gesture recognition while the map is tilted. ([#2770](https://github.com/mapbox/mapbox-gl-native/pull/2770)) +- `-mapViewWillStartLoadingMap:` and `-mapViewDidFinishLoadingMap:` delegate methods now work. ([#2706](https://github.com/mapbox/mapbox-gl-native/pull/2706)) +- Removed CoreTelephony.framework dependency. ([#2581](https://github.com/mapbox/mapbox-gl-native/pull/2581)) +- Improved user location annotation responsiveness. ([#2643](https://github.com/mapbox/mapbox-gl-native/pull/2643)) + +## iOS 2.1.2 + +- Built with Xcode 6.4 to not yet trigger Bitcode compatibility until Xcode 7 stabilizes. ([#2332](https://github.com/mapbox/mapbox-gl-native/issues/2332)) + +## iOS 2.1.1 + +- Fixes for Xcode 7 and Bitcode. ([#2238](https://github.com/mapbox/mapbox-gl-native/pull/2238)) + +## iOS 2.1.0 + +- A two-finger vertical swipe now tilts the map into perspective mode. ([#2116](https://github.com/mapbox/mapbox-gl-native/pull/2116)) +- A new `MGLMapCamera` API allows you to transition multiple viewpoint properties, including rotation and pitch, simultaneously with an optional custom duration and timing function. ([#2193](https://github.com/mapbox/mapbox-gl-native/pull/2193)) +- A new user tracking mode, `MGLUserTrackingModeFollowWithCourse`, has been added for indicating the current direction of travel. ([#2068](https://github.com/mapbox/mapbox-gl-native/pull/2068)) +- Version 8 (`v8`) of the [Mapbox GL style spec](https://www.mapbox.com/mapbox-gl-style-spec/) is now required. If you are using a custom `v7` style, it needs to be upgraded using [this migrator script](https://github.com/mapbox/mapbox-gl-style-spec/blob/mb-pages/migrations/v7.js). ([#2052](https://github.com/mapbox/mapbox-gl-native/pull/2052)) +- Applications built with Mapbox GL no longer crash when Location Services launches them in background mode. ([#1821](https://github.com/mapbox/mapbox-gl-native/pull/1821), [#1869](https://github.com/mapbox/mapbox-gl-native/pull/1869)) +- Fixed a crash when adding annotations to an `MGLMapView` inside `-viewDidLoad`. ([#1874](https://github.com/mapbox/mapbox-gl-native/pull/1874)) +- The user location annotation view now indicates the location reading’s accuracy and the device’s heading. ([#2010](https://github.com/mapbox/mapbox-gl-native/pull/2010)) +- Eliminated linker warnings and errors when building against the iOS 9.0 SDK in Xcode 7. ([#1962](https://github.com/mapbox/mapbox-gl-native/pull/1962)) +- Worked around a bug in the iOS 9.0 SDK that caused a crash on launch. ([#1958](https://github.com/mapbox/mapbox-gl-native/pull/1958)) +- User location tracking no longer sends `MGLMapView` into an invalid region on iOS 9. ([#1925](https://github.com/mapbox/mapbox-gl-native/pull/1925)) +- Eliminated console spew in the iOS demo application that was related to Mapbox Metrics HTTP requests. ([#1937](https://github.com/mapbox/mapbox-gl-native/issues/1937)) +- Implemented `-[MGLMapView showAnnotations:animated:]`. ([#2050](https://github.com/mapbox/mapbox-gl-native/pull/2050)) +- Fixed a crash adding a shape annotation with zero points. ([#2098](https://github.com/mapbox/mapbox-gl-native/pull/2098)) +- Debug mode now displays information useful for debugging the label collision algorithm. ([#1808](https://github.com/mapbox/mapbox-gl-native/pull/1808)) +- Minor style updates. ([#1910](https://github.com/mapbox/mapbox-gl-native/pull/1910)) +- The CocoaPods pod now contains a `README.md` file. ([#1886](https://github.com/mapbox/mapbox-gl-native/pull/1886)) + +## iOS 2.0.0 + +Repackaging 2.0.0-pre.1 as it contained no issues. + +## iOS 2.0.0-pre.1 + +Repackaging 0.5.1 as the Mapbox iOS SDK 2.0.0 series. + +## 0.5.1 + +### iOS + +- Added support for CocoaPods 0.38.0. ([#1876](https://github.com/mapbox/mapbox-gl-native/pull/1876)) + +## 0.5.0 + +### Core + +- Support for runtime marker imagery. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) +- Added `Map::fitBounds()` for region-based viewport setting. ([#1092](https://github.com/mapbox/mapbox-gl-native/issues/1092)) +- Added a raster satellite bundled style and improved raster rendering. ([#963](https://github.com/mapbox/mapbox-gl-native/issues/963)) +- Improved round line joins for semi-transparent lines. ([#1839](https://github.com/mapbox/mapbox-gl-native/pull/1839)) +- Improved map render lifecycle notifications. ([#1026](https://github.com/mapbox/mapbox-gl-native/issues/1026)) +- Fixed a bug that caused annotations not to show at zoom level zero. ([#1279](https://github.com/mapbox/mapbox-gl-native/issues/1279)) +- Fixed a bug with the ordering of shape layers. ([#1866](https://github.com/mapbox/mapbox-gl-native/pull/1866)) +- Other bug fixes and performance improvements. + +### iOS + +- **Breaking:** Headers now make use of lightweight generics, eliminating many unnecessary casts when working with annotations in Swift 2.0 in Xcode 7. ([#1711](https://github.com/mapbox/mapbox-gl-native/pull/1711)) +- **Breaking:** `-mapView:symbolNameForAnnotation:` has been removed from the `MGLMapViewDelegate` protocol. Implement `-mapView:imageForAnnotation:` instead, which accepts images at runtime. ([#941](https://github.com/mapbox/mapbox-gl-native/pull/941)) +- **Breaking:** `MGLMapView.direction` is now expressed in terms of degrees clockwise from true north, as indicated in the documentation, rather than counterclockwise. ([#1789](https://github.com/mapbox/mapbox-gl-native/pull/1789)) +- A Satellite style showing Mapbox Satellite imagery is now bundled with Mapbox GL. ([#1845](https://github.com/mapbox/mapbox-gl-native/pull/1845)) +- Improved `UIView` tracking to the map. ([#1813](https://github.com/mapbox/mapbox-gl-native/pull/1813)) +- Delegate method `-[MGLMapViewDelegate mapView:didFailToLocateUserWithError:]` now works. ([#1608](https://github.com/mapbox/mapbox-gl-native/pull/1608)) +- It is now possible to fit the map’s viewport to a coordinate bounding box via `-[MGLMapView setVisibleCoordinateBounds:animated:]` or to a specific set of coordinates via `-[MGLMapView setVisibleCoordinates:count:edgePadding:animated:]`. ([#1783](https://github.com/mapbox/mapbox-gl-native/pull/1783), [#1795](https://github.com/mapbox/mapbox-gl-native/pull/1795)) +- The logo and ℹ️ no longer disappear or get distorted after embedding MGLMapView in a different view, and you can now access these subviews directly via properties on MGLMapView. ([#1779](https://github.com/mapbox/mapbox-gl-native/pull/1779), [#1815](https://github.com/mapbox/mapbox-gl-native/pull/1815)) +- Raster tiles now look sharper midway between two zoom levels. ([#1843](https://github.com/mapbox/mapbox-gl-native/pull/1843)) +- Resetting the map rotation to north no longer also resets the user location tracking mode. ([#1809](https://github.com/mapbox/mapbox-gl-native/pull/1809)) +- `-[MGLMapView convertPoint:toCoordinateFromView:]` now returns accurate coordinates on iPhone 6. ([#1827](https://github.com/mapbox/mapbox-gl-native/pull/1827)) +- Fixed an issue in which `-[MGLMapView direction]` would sometimes return 360 instead of 0. ([#1829](https://github.com/mapbox/mapbox-gl-native/pull/1829)) +- Build against iOS 8.4. ([#1868](https://github.com/mapbox/mapbox-gl-native/pull/1868)) + +## 0.4.0 + +### Core + +- Support for polyline and polygon shape annotations. ([#1655](https://github.com/mapbox/mapbox-gl-native/issues/1655)) +- Improved placement and density of labels. ([#1666](https://github.com/mapbox/mapbox-gl-native/issues/1666), [blog](https://www.mapbox.com/blog/better-label-placement-mapbox-mobile/)) +- Improved z-ordering appearance of point markers. ([#988](https://github.com/mapbox/mapbox-gl-native/issues/988)) +- Fixed an issue in which certain features, such as roundabouts, were not rendered completely. ([#1725](https://github.com/mapbox/mapbox-gl-native/issues/1725)) +- Many bug fixes and performance and stability improvements. +- Improved tests. + +### iOS + +- **Breaking:** `MGLMapView` no longer manages Mapbox access tokens directly; an access token cannot be passed in when initializing the map view. Instead, set `MGLMapboxAccessToken` to your access token in your app’s `Info.plist` file, or call `+[MGLAccountManager setAccessToken:]` before initializing the map view. If you were setting the access token inside an Interface Builder inspectable, also remove it from the User Defined Runtime Attributes section of the Identity inspector. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553)) +- **Breaking:** `MGLAccountManager`'s `-setMapboxMetricsEnabledSettingShownInApp:` has been removed. If you implement a Mapbox Metrics switch inside your app, instead of inside a Settings bundle, set `MGLMapboxMetricsEnabledSettingShownInApp` to `YES` in the `Info.plist` file. ([#1553](https://github.com/mapbox/mapbox-gl-native/issues/1553)) +- **Breaking:** `MGLMapView`'s `-mapID` has been renamed to `-styleID`. ([#1561](https://github.com/mapbox/mapbox-gl-native/issues/1561)) +- Headers have been audited for nullability, improving type safety in both Objective-C and Swift 1.2 when compiling with Xcode 6.3 or above. ([#1578](https://github.com/mapbox/mapbox-gl-native/issues/1578)) +- Fixed an issue in which the map would sometimes spin 180° while rotating the map with two fingers. ([#1453](https://github.com/mapbox/mapbox-gl-native/issues/1453)) +- Added a shortcut to the Mapbox Metrics switch in `MGLMapView`'s action sheet that is attached to the ℹ️ button. ([#1611](https://github.com/mapbox/mapbox-gl-native/issues/1611)) +- `MGLMapView` now supports Interface Builder designables. When you add an `MGLMapView` to a storyboard, it displays instructions for getting set up directly on the storyboard canvas. ([#1573](https://github.com/mapbox/mapbox-gl-native/issues/1573)) +- The default title for the user location annotation is now “You Are Here”. You can customize the title by setting `mapView.userAnnotation.title`. ([#1559](https://github.com/mapbox/mapbox-gl-native/issues/1559)) +- Internal use of the Reachability library has been cleaned up so that your app can include its own copy of Reachability. ([#1718](https://github.com/mapbox/mapbox-gl-native/issues/1718)) +- Now distribute a binary stripped of debugging symbols by default with an optional, secondary symbols build. ([#1650](https://github.com/mapbox/mapbox-gl-native/issues/1650)) + +## 0.3.1 + +- Temporarily removed `IBDesignable` support on iOS. + +## 0.3.0 + +- Initial iOS beta release. + +Known issues: + +- None. \ No newline at end of file From 68c0c79095248546d11fd8f3defceb26fba41fad Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 11:06:55 -0500 Subject: [PATCH 054/104] [node] #4432 - Adding Node.js to primary CHANGELOG and listing platforms alphabetically --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a18492c1c..f0473953d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,5 +2,6 @@ As of iOS 3.2.0 and Android 4.0.0 we've split the CHANGELOG into platform specific CHANGELOGS to make it easier to follow the progress of a particular project. Their new locations are as follows: +* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/android/CHANGELOG.md) * iOS --> [`/platform/ios/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/ios/CHANGELOG.md) -* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/android/CHANGELOG.md) \ No newline at end of file +* Node.js --> [`/platform/node/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/node/CHANGELOG.md) From 376d9687255d02a046a4e380c262f4dfd509cc78 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 11:19:53 -0500 Subject: [PATCH 055/104] [android] [ios] #4432 - Switch links to blob instead of tree --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0473953d..09331d0e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,6 @@ As of iOS 3.2.0 and Android 4.0.0 we've split the CHANGELOG into platform specific CHANGELOGS to make it easier to follow the progress of a particular project. Their new locations are as follows: -* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/android/CHANGELOG.md) -* iOS --> [`/platform/ios/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/ios/CHANGELOG.md) +* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/CHANGELOG.md) +* iOS --> [`/platform/ios/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/ios/CHANGELOG.md) * Node.js --> [`/platform/node/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/node/CHANGELOG.md) From 2e01da1d71dd9965f1eeb608859879f70038c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Thu, 24 Mar 2016 14:13:45 -0700 Subject: [PATCH 056/104] [ios] Define C nullability block type qualifiers for Xcode 6.4 This change fixes the build in Xcode 6.4. --- platform/darwin/include/MGLTypes.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/darwin/include/MGLTypes.h b/platform/darwin/include/MGLTypes.h index 213b90670..ccb496816 100644 --- a/platform/darwin/include/MGLTypes.h +++ b/platform/darwin/include/MGLTypes.h @@ -8,6 +8,8 @@ #define nullable #define nonnull #define null_resettable + #define _Nullable + #define _Nonnull #endif NS_ASSUME_NONNULL_BEGIN From 2a56565a9c612c79f099ed627bfacd8b47627487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Thu, 24 Mar 2016 14:21:23 -0700 Subject: [PATCH 057/104] [ios, osx] Wrap coordinates converted from points ref #4444 --- platform/ios/src/MGLMapView.mm | 2 +- platform/osx/src/MGLMapView.mm | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 1d7a5090d..9b094ec89 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -2150,7 +2150,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) - (mbgl::LatLng)convertPoint:(CGPoint)point toLatLngFromView:(nullable UIView *)view { CGPoint convertedPoint = [self convertPoint:point fromView:view]; - return _mbglMap->latLngForPixel(mbgl::ScreenCoordinate(convertedPoint.x, convertedPoint.y)); + return _mbglMap->latLngForPixel(mbgl::ScreenCoordinate(convertedPoint.x, convertedPoint.y)).wrapped(); } - (CGPoint)convertCoordinate:(CLLocationCoordinate2D)coordinate toPointToView:(nullable UIView *)view diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm index e09a6c267..1ab98b9f8 100644 --- a/platform/osx/src/MGLMapView.mm +++ b/platform/osx/src/MGLMapView.mm @@ -2160,7 +2160,7 @@ public: convertedPoint.x, // mbgl origin is at the top-left corner. NSHeight(self.bounds) - convertedPoint.y, - }); + }).wrapped(); } - (NSRect)convertCoordinateBounds:(MGLCoordinateBounds)bounds toRectToView:(nullable NSView *)view { From 85297e2c6bc8765b8f57f5945889be8f3244aa7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 25 Mar 2016 09:59:55 -0700 Subject: [PATCH 058/104] [ios] Use current Swift version with jazzy Fixes #4468. --- platform/ios/scripts/document.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index c470c59db..e52176b08 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -19,6 +19,8 @@ BRANCH=$( git describe --tags --match=ios-v*.*.* --abbrev=0 ) SHORT_VERSION=$( echo ${BRANCH} | sed 's/^ios-v//' ) RELEASE_VERSION=$( echo ${SHORT_VERSION} | sed -e 's/^ios-v//' -e 's/-.*//' ) +SWIFT_VERSION=$(xcrun swift -version | head -n 1 | sed -e 's/^Apple Swift version //' -e 's/ .*$//') + rm -rf /tmp/mbgl mkdir -p /tmp/mbgl/ README=/tmp/mbgl/README.md @@ -32,6 +34,7 @@ mkdir -p ${OUTPUT} jazzy \ --sdk iphonesimulator \ + --swift-version $SWIFT_VERSION \ --github-file-prefix https://github.com/mapbox/mapbox-gl-native/tree/${BRANCH} \ --module-version ${SHORT_VERSION} \ --readme ${README} \ From 75913a5dae501e6e513980241d5b5cde19b54a85 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 13:34:55 -0500 Subject: [PATCH 059/104] [android] #4473 - Fixing toString() tests for LatLng.toString() --- .../java/com/mapbox/mapboxsdk/annotations/MarkerTest.java | 2 +- .../com/mapbox/mapboxsdk/camera/CameraPositionTest.java | 2 +- .../java/com/mapbox/mapboxsdk/geometry/LatLngTest.java | 2 +- .../com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java index 76e29c208..cc38ca40b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerTest.java @@ -113,7 +113,7 @@ public class MarkerTest { @Test public void testToString() { Marker marker = new MarkerOptions().position(new LatLng(0, 0)).getMarker(); - assertEquals(marker.toString(), "Marker [position[" + "LatLng [longitude=0.0, latitude=0.0, altitude=0.0]" + "]]"); + assertEquals(marker.toString(), "Marker [position[" + "LatLng [latitude=0.0, longitude=0.0, altitude=0.0]" + "]]"); } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java index e2109adf4..222007df7 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/camera/CameraPositionTest.java @@ -23,7 +23,7 @@ public class CameraPositionTest { public void testToString() { LatLng latLng = new LatLng(1, 2); CameraPosition cameraPosition = new CameraPosition(latLng, 3, 4, 5); - assertEquals("toString should match", "Target: LatLng [longitude=2.0, latitude=1.0, altitude=0.0], Zoom:3.0, Bearing:5.0, Tilt:4.0", cameraPosition.toString()); + assertEquals("toString should match", "Target: LatLng [latitude=1.0, longitude=2.0, altitude=0.0], Zoom:3.0, Bearing:5.0, Tilt:4.0", cameraPosition.toString()); } @Test diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java index ecce08b17..0221b448b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java @@ -151,7 +151,7 @@ public class LatLngTest { LatLng latLng = new LatLng(latitude, longitude, altitude); assertEquals("string should match", latLng.toString(), - "LatLng [longitude=3.4, latitude=1.2, altitude=5.6]"); + "LatLng [latitude=1.2, longitude=3.4, altitude=5.6]"); } @Test diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java index 83cfa3784..0682d0878 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/VisibleRegionTest.java @@ -73,10 +73,10 @@ public class VisibleRegionTest { public void testToString() { VisibleRegion region = new VisibleRegion(FAR_LEFT, FAR_RIGHT, NEAR_LEFT, NEAR_RIGHT, BOUNDS); assertEquals("string should match", - "[farLeft [LatLng [longitude=-12.0, latitude=52.0, altitude=0.0]], " + - "farRight [LatLng [longitude=26.0, latitude=52.0, altitude=0.0]], " + - "nearLeft [LatLng [longitude=-12.0, latitude=34.0, altitude=0.0]], " + - "nearRight [LatLng [longitude=26.0, latitude=34.0, altitude=0.0]], " + + "[farLeft [LatLng [latitude=52.0, longitude=-12.0, altitude=0.0]], " + + "farRight [LatLng [latitude=52.0, longitude=26.0, altitude=0.0]], " + + "nearLeft [LatLng [latitude=34.0, longitude=-12.0, altitude=0.0]], " + + "nearRight [LatLng [latitude=34.0, longitude=26.0, altitude=0.0]], " + "latLngBounds [N:52.0; E:26.0; S:34.0; W:-12.0]]" , region.toString()); } From 8cdb4f74e13085f438c22f940cec198c0dd85492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 25 Mar 2016 10:18:04 -0700 Subject: [PATCH 060/104] [ios] Fixed changelog processing Fixed a regression introduced in #4466 in which the changelog is essentially empty. Fixes #4469. --- platform/ios/CHANGELOG.md | 24 ++++++++++++------------ platform/ios/scripts/document.sh | 2 +- platform/ios/scripts/package.sh | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 3938249c5..4650e9f03 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -1,8 +1,8 @@ # Changelog for Mapbox iOS SDK -Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +Mapbox welcomes participation and contributions from everyone. If you’d like to do so please see [CONTRIBUTING.md](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. -## iOS 3.2.0 +## 3.2.0 - Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) - Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) @@ -21,12 +21,12 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) - The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417))) -## iOS 3.1.2 +## 3.1.2 - You can once again install the static framework without manually linking several framework and library dependencies. ([#4029](https://github.com/mapbox/mapbox-gl-native/pull/4029)) - The location manager used by MGLMapView to show the user’s location is now paused when the application is sent to the background. ([#4034](https://github.com/mapbox/mapbox-gl-native/pull/4034)) -## iOS 3.1.1 +## 3.1.1 - Corrected the dynamic framework’s minimum deployment target to iOS 8.0. ([#3872](https://github.com/mapbox/mapbox-gl-native/pull/3872)) - Fixed Fabric compatibility. ([#3847](https://github.com/mapbox/mapbox-gl-native/pull/3847)) @@ -35,7 +35,7 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - Fixed an issue that incorrectly expanded the tappable area of an annotation and prevented the annotation’s alignment rect insets from having any effect on the tappable area. ([#3898](https://github.com/mapbox/mapbox-gl-native/pull/3898)) - Fixed an issue preventing `-[MGLMapViewDelegate mapView:tapOnCalloutForAnnotation:]` from being called when a non-custom callout view is tapped. ([#3875](https://github.com/mapbox/mapbox-gl-native/pull/3875)) -## iOS 3.1.0 +## 3.1.0 - The SDK is now distributed as a dynamic framework instead of a static library, resulting in a simpler installation workflow and significantly reduced download size. The framework contains both simulator and device content. If you install the dynamic framework manually, you’ll need to strip out the simulator content before submitting your application to the App Store due to [an Xcode bug](http://www.openradar.me/radar?id=6409498411401216); see the installation instructions included with the framework for details. ([#3183](https://github.com/mapbox/mapbox-gl-native/pull/3183)) - Fixed an issue causing the entire MGLMapView to leak. ([#3448](https://github.com/mapbox/mapbox-gl-native/pull/3448)) @@ -64,13 +64,13 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - Avoids triggering the blue background location status bar when user has granted "when in use" permission. ([#3671](https://github.com/mapbox/mapbox-gl-native/issues/3671)) - Deprecated the `debugActive` property and `-toggleDebug` method on MGLMapView in favor of a new `debugMask` property that exposes individual style debugging options. ([#3742](https://github.com/mapbox/mapbox-gl-native/pull/3742)) -## iOS 3.0.1 +## 3.0.1 - Fixed CoreTelephony.framework crash. ([#3170](https://github.com/mapbox/mapbox-gl-native/pull/3170)) - Fixed an issue preventing the compass from responding to taps after the compass is moved programmatically. ([#3117](https://github.com/mapbox/mapbox-gl-native/pull/3117)) - CocoaPods is now distributed via a (static) framework. ([#3181](https://github.com/mapbox/mapbox-gl-native/issues/3181)) -## iOS 3.0.0 +## 3.0.0 - If you install this SDK via CocoaPods, CocoaPods version 0.38.0 or above is required. ([#2132](https://github.com/mapbox/mapbox-gl-native/pull/2132)) - The `styleID` property has been removed from MGLMapView. Instead, set the `styleURL` property to an NSURL in the form `mapbox://styles/STYLE_ID`. If you previously set the style ID in Interface Builder’s Attributes inspector, delete the `styleID` entry from the User Defined Runtime Attributes section of the Identity inspector, then set the new “Style URL” inspectable to a value in the form `mapbox://styles/STYLE_ID`. ([#2632](https://github.com/mapbox/mapbox-gl-native/pull/2632)) @@ -95,15 +95,15 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - Removed CoreTelephony.framework dependency. ([#2581](https://github.com/mapbox/mapbox-gl-native/pull/2581)) - Improved user location annotation responsiveness. ([#2643](https://github.com/mapbox/mapbox-gl-native/pull/2643)) -## iOS 2.1.2 +## 2.1.2 - Built with Xcode 6.4 to not yet trigger Bitcode compatibility until Xcode 7 stabilizes. ([#2332](https://github.com/mapbox/mapbox-gl-native/issues/2332)) -## iOS 2.1.1 +## 2.1.1 - Fixes for Xcode 7 and Bitcode. ([#2238](https://github.com/mapbox/mapbox-gl-native/pull/2238)) -## iOS 2.1.0 +## 2.1.0 - A two-finger vertical swipe now tilts the map into perspective mode. ([#2116](https://github.com/mapbox/mapbox-gl-native/pull/2116)) - A new `MGLMapCamera` API allows you to transition multiple viewpoint properties, including rotation and pitch, simultaneously with an optional custom duration and timing function. ([#2193](https://github.com/mapbox/mapbox-gl-native/pull/2193)) @@ -122,11 +122,11 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to - Minor style updates. ([#1910](https://github.com/mapbox/mapbox-gl-native/pull/1910)) - The CocoaPods pod now contains a `README.md` file. ([#1886](https://github.com/mapbox/mapbox-gl-native/pull/1886)) -## iOS 2.0.0 +## 2.0.0 Repackaging 2.0.0-pre.1 as it contained no issues. -## iOS 2.0.0-pre.1 +## 2.0.0-pre.1 Repackaging 0.5.1 as the Mapbox iOS SDK 2.0.0 series. diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index e52176b08..4890aca15 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -27,7 +27,7 @@ README=/tmp/mbgl/README.md cp platform/ios/docs/doc-README.md "${README}" # http://stackoverflow.com/a/4858011/4585461 echo "## Changes in version ${RELEASE_VERSION}" >> "${README}" -sed -n -e '/^## iOS/{' -e ':a' -e 'n' -e '/^##/q' -e 'p' -e 'ba' -e '}' CHANGELOG.md >> "${README}" +sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^##/q' -e 'p' -e 'ba' -e '}' platform/ios/CHANGELOG.md >> "${README}" rm -rf ${OUTPUT} mkdir -p ${OUTPUT} diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index c4357c45d..9f843785e 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -237,7 +237,7 @@ if [[ ${BUILD_DYNAMIC} == true ]]; then plutil -replace MGLCommitHash -string "${HASH}" "${OUTPUT}/dynamic/${NAME}.framework/Info.plist" cp -pv platform/ios/framework/strip-frameworks.sh "${OUTPUT}/dynamic/${NAME}.framework/strip-frameworks.sh" fi -sed -n -e '/^## iOS/,$p' CHANGELOG.md > "${OUTPUT}/CHANGELOG.md" +sed -n -e '/^## /,$p' platform/ios/CHANGELOG.md > "${OUTPUT}/CHANGELOG.md" rm -rf /tmp/mbgl mkdir -p /tmp/mbgl/ From 335e346ed19fc199de383f123ae5154be93588dd Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 15:34:43 -0500 Subject: [PATCH 061/104] [android] #4475 - Introducing LatLng.wrap() and removing usage of wrap() in JNI's nativeLatLngForPixel() --- .../com/mapbox/mapboxsdk/geometry/LatLng.java | 12 ++++++++++++ .../com/mapbox/mapboxsdk/utils/MathUtils.java | 19 +++++++++++++++++++ .../mapbox/mapboxsdk/geometry/LatLngTest.java | 13 +++++++++---- platform/android/src/jni.cpp | 2 +- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java index d9ffe48b3..0007a9f4a 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java @@ -6,6 +6,7 @@ import android.os.Parcelable; import com.mapbox.mapboxsdk.constants.GeoConstants; import com.mapbox.mapboxsdk.constants.MathConstants; +import com.mapbox.mapboxsdk.utils.MathUtils; import java.io.Serializable; @@ -118,6 +119,17 @@ public class LatLng implements ILatLng, Parcelable { return altitude; } + /** + * Return a new LatLng object with a wrapped Longitude. This allows original data object + * to remain unchanged. + * @return New LatLng object with wrapped Longitude + */ + public LatLng wrap(){ + LatLng wrappedVersion = new LatLng(this); + wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE)); + return wrappedVersion; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java index ff1b56422..1803462b4 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java @@ -24,4 +24,23 @@ public class MathUtils { return Math.max(min, Math.min(max, value)); } + /** + * Constrains n to the given range (including min, excluding max) via modular arithmetic. + * + * Same formula as used in Core GL (math.hpp) + * std::fmod((std::fmod((value - min), d) + d), d) + min; + * + * @param value Value to wrap + * @param min Minimum value + * @param max Maximum value + * @return Wrapped value + */ + public static double wrap(double value, double min, double max) { + double delta = max - min; + + double firstMod = (value - min) % delta; + double secondMod = (firstMod + delta) % delta; + + return secondMod + min; + } } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java index 0221b448b..984e55929 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java @@ -2,19 +2,17 @@ package com.mapbox.mapboxsdk.geometry; import android.location.Location; import android.os.Parcel; - import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.utils.MockParcel; - import org.junit.Test; - import java.util.Objects; - +import dalvik.annotation.TestTargetClass; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -202,4 +200,11 @@ public class LatLngTest { assertEquals("contents should be 0", 0, latLng.describeContents(), DELTA); } + @Test + public void testWrapped() { + LatLng latLng = new LatLng(45.0, -185.0); + LatLng wrapped = latLng.wrap(); + assertTrue(!latLng.equals(wrapped)); + assertTrue(wrapped.getLongitude() == 175.0); + } } diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index 4b75f324f..237fbb99d 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -1176,7 +1176,7 @@ jni::jobject* nativeLatLngForPixel(JNIEnv *env, jni::jobject* obj, jlong nativeM jfloat x = jni::GetField(*env, pixel, *pointFXId); jfloat y = jni::GetField(*env, pixel, *pointFYId); - mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y)).wrapped(); + mbgl::LatLng latLng = nativeMapView->getMap().latLngForPixel(mbgl::ScreenCoordinate(x, y)); return &jni::NewObject(*env, *latLngClass, *latLngConstructorId, latLng.latitude, latLng.longitude); } From ef90e2286f6a63c4299dcb6b32f4b5c89b04cabe Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 15:47:26 -0500 Subject: [PATCH 062/104] [android] #4475 - Wrap all Longitude Telemetry data --- .../mapboxsdk/telemetry/MapboxEventManager.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index fb98903c8..6e5648ee3 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -24,8 +24,10 @@ import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; import com.mapbox.mapboxsdk.BuildConfig; +import com.mapbox.mapboxsdk.constants.GeoConstants; import com.mapbox.mapboxsdk.constants.MapboxConstants; import com.mapbox.mapboxsdk.location.LocationServices; +import com.mapbox.mapboxsdk.utils.MathUtils; import org.json.JSONArray; import org.json.JSONObject; import java.security.MessageDigest; @@ -551,7 +553,16 @@ public class MapboxEventManager { jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SOURCE, evt.get(MapboxEvent.ATTRIBUTE_SOURCE)); jsonObject.putOpt(MapboxEvent.ATTRIBUTE_SESSION_ID, evt.get(MapboxEvent.ATTRIBUTE_SESSION_ID)); jsonObject.putOpt(MapboxEvent.KEY_LATITUDE, evt.get(MapboxEvent.KEY_LATITUDE)); - jsonObject.putOpt(MapboxEvent.KEY_LONGITUDE, evt.get(MapboxEvent.KEY_LONGITUDE)); + + // Make sure Longitude Is Wrapped + if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) { + double lon = (double)evt.get(MapboxEvent.KEY_LONGITUDE); + Log.i(TAG, "Original Lon = " + lon); + lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); + Log.i(TAG, "Wrapped Lon = " + lon); + jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon); + } + jsonObject.putOpt(MapboxEvent.KEY_ALTITUDE, evt.get(MapboxEvent.KEY_ALTITUDE)); jsonObject.putOpt(MapboxEvent.KEY_ZOOM, evt.get(MapboxEvent.KEY_ZOOM)); jsonObject.putOpt(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM, evt.get(MapboxEvent.ATTRIBUTE_OPERATING_SYSTEM)); From 01dfd3c15d14b46379fe8c8522f3a074b5152585 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 15:54:35 -0500 Subject: [PATCH 063/104] [android] #4475 - Only wrap Telemetry longitude when it's outside bounds --- .../mapbox/mapboxsdk/telemetry/MapboxEventManager.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index 6e5648ee3..54089aee0 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -558,8 +558,10 @@ public class MapboxEventManager { if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) { double lon = (double)evt.get(MapboxEvent.KEY_LONGITUDE); Log.i(TAG, "Original Lon = " + lon); - lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); - Log.i(TAG, "Wrapped Lon = " + lon); + if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) { + lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); + Log.i(TAG, "Wrapped Lon = " + lon); + } jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon); } @@ -640,7 +642,7 @@ public class MapboxEventManager { .post(body) .build(); Response response = client.newCall(request).execute(); - Log.d(TAG, "response code = " + response.code() + " for events " + events.size()); + Log.i(TAG, "response code = " + response.code() + " for events " + events.size()); // Reset Events // ============ From 464c29f043794925e9d303dfb6bcf2a4ed22fa8d Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 15:56:44 -0500 Subject: [PATCH 064/104] [android] #4475 - Dialing down logs --- .../com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java index 54089aee0..736247bba 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/telemetry/MapboxEventManager.java @@ -557,10 +557,8 @@ public class MapboxEventManager { // Make sure Longitude Is Wrapped if (evt.containsKey(MapboxEvent.KEY_LONGITUDE)) { double lon = (double)evt.get(MapboxEvent.KEY_LONGITUDE); - Log.i(TAG, "Original Lon = " + lon); if ((lon < GeoConstants.MIN_LONGITUDE) || (lon > GeoConstants.MAX_LONGITUDE)) { lon = MathUtils.wrap(lon, GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE); - Log.i(TAG, "Wrapped Lon = " + lon); } jsonObject.put(MapboxEvent.KEY_LONGITUDE, lon); } @@ -642,7 +640,7 @@ public class MapboxEventManager { .post(body) .build(); Response response = client.newCall(request).execute(); - Log.i(TAG, "response code = " + response.code() + " for events " + events.size()); + Log.d(TAG, "response code = " + response.code() + " for events " + events.size()); // Reset Events // ============ From 7a9a58f4fb493ce65a664422ba09ae436757316c Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 16:32:33 -0500 Subject: [PATCH 065/104] [android] #4475 - Only wrapping when needed in LatLng.wrap(). Making Javadoc more clear. Making tests consistent. --- .../java/com/mapbox/mapboxsdk/geometry/LatLng.java | 5 ++++- .../java/com/mapbox/mapboxsdk/utils/MathUtils.java | 2 +- .../com/mapbox/mapboxsdk/geometry/LatLngTest.java | 14 +++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java index 0007a9f4a..1ba2a14e9 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLng.java @@ -126,7 +126,10 @@ public class LatLng implements ILatLng, Parcelable { */ public LatLng wrap(){ LatLng wrappedVersion = new LatLng(this); - wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE)); + double lon = wrappedVersion.getLongitude(); + if (lon < GeoConstants.MIN_LONGITUDE || lon > GeoConstants.MAX_LONGITUDE) { + wrappedVersion.setLongitude(MathUtils.wrap(wrappedVersion.getLongitude(), GeoConstants.MIN_LONGITUDE, GeoConstants.MAX_LONGITUDE)); + } return wrappedVersion; } diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java index 1803462b4..922fb1186 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MathUtils.java @@ -25,7 +25,7 @@ public class MathUtils { } /** - * Constrains n to the given range (including min, excluding max) via modular arithmetic. + * Constrains value to the given range (including min, excluding max) via modular arithmetic. * * Same formula as used in Core GL (math.hpp) * std::fmod((std::fmod((value - min), d) + d), d) + min; diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java index 984e55929..e13efb970 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngTest.java @@ -6,11 +6,11 @@ import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.utils.MockParcel; import org.junit.Test; import java.util.Objects; -import dalvik.annotation.TestTargetClass; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -204,7 +204,15 @@ public class LatLngTest { public void testWrapped() { LatLng latLng = new LatLng(45.0, -185.0); LatLng wrapped = latLng.wrap(); - assertTrue(!latLng.equals(wrapped)); - assertTrue(wrapped.getLongitude() == 175.0); + assertNotSame(latLng, wrapped); + assertEquals("longitude wrapped value", wrapped.getLongitude(), 175.0, DELTA); + } + + @Test + public void testUnnecessaryWrapped() { + LatLng latLng = new LatLng(45.0, 50.0); + LatLng wrapped = latLng.wrap(); + assertNotSame(latLng, wrapped); + assertEquals("longitude wrapped value", wrapped.getLongitude(), 50.0, DELTA); } } From 75d18dac65ffdf2cc9424e97566636ef55b78483 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 17:04:01 -0500 Subject: [PATCH 066/104] [android] #4478 - Updating version to 4.0.0-rc.1 --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- .../fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 0e3858644..b2a22894a 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-SNAPSHOT +VERSION_NAME=4.0.0-rc.1 POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native diff --git a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties index 00499bda3..14ced7955 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties +++ b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties @@ -1,3 +1,3 @@ fabric-identifier=com.mapbox.mapboxsdk.mapbox-android-sdk -fabric-version=4.0.0-beta.2 +fabric-version=4.0.0-rc.1 fabric-build-type=binary From 616a77202d3a87ed3121045105977038956876f2 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 17:24:27 -0500 Subject: [PATCH 067/104] [android] #4478 - Updating CHANGELOG for 4.0.0-rc.1 --- platform/android/CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 135d8a7cc..dd761afb4 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,13 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +## 4.0.0-rc.1 + +* Default Value Bug Fix for MapboxMapOptions ([#4398](https://github.com/mapbox/mapbox-gl-native/issues/4398)) +* NullPointerException When Scrolling ([#4424](https://github.com/mapbox/mapbox-gl-native/issues/4424)) +* Platform Specific CHANGELOGS ([#4432](https://github.com/mapbox/mapbox-gl-native/issues/4432)) +* Introduce LatLng.wrap() ([#4475](https://github.com/mapbox/mapbox-gl-native/issues/4475)) + ## 4.0.0-beta.2 * arm64 ABI Support ([#3128](https://github.com/mapbox/mapbox-gl-native/issues/3128)) @@ -64,4 +71,4 @@ Mapbox Android 4.0.0 is the most ambitious Android release to date with 3 major 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 \ No newline at end of file + - Resolved in 2.2.0 From 1b842ca8231635c6bde751780e25f679dc47eeaa Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Fri, 25 Mar 2016 20:35:23 -0500 Subject: [PATCH 068/104] [android] #4478 - Returning to 4.0.0-SNAPSHOT --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index b2a22894a..0e3858644 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-rc.1 +VERSION_NAME=4.0.0-SNAPSHOT POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native From 71f6773208f61d9d567eecee5d85ddadf0d0d755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 26 Mar 2016 22:08:30 -0700 Subject: [PATCH 069/104] [ios] Copyedited changelog Changes are generally arranged by descending developer or user impact. --- platform/ios/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 4650e9f03..4ea98833c 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -9,17 +9,17 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) - The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) - Fixed an issue causing the map to pan the wrong way when the user pinches unevenly. ([#4427](https://github.com/mapbox/mapbox-gl-native/pull/4427)) +- The maximum zoom level is capped at 21 due to rendering issues at higher zoom levels. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417)) - An icon laid out along a line no longer appears if it would extend past the end of the line. Some one-way arrows no longer point the wrong way. ([#3839](https://github.com/mapbox/mapbox-gl-native/pull/3839)) - Fixed warping of dashed lines near sharp corners. ([#3914](https://github.com/mapbox/mapbox-gl-native/pull/3914)) - Telemetry location gathering now occurs only when the device is in motion. ([#4115](https://github.com/mapbox/mapbox-gl-native/pull/4115)) - An account’s monthly active users metric only counts a user once a map view is displayed to that user. ([#3713](https://github.com/mapbox/mapbox-gl-native/pull/3713)) - A .dSYM bundle is included with the dynamic framework to facilitate symbolication of crash logs. -- Updated documentation to reflect the requirement that you must embed the framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) +- Updated documentation to reflect the requirement that you must embed the dynamic framework in the “Embedded Binaries” section in Xcode. ([#4011](https://github.com/mapbox/mapbox-gl-native/issues/4011)) - Polygons and polylines now default to using the map view’s tint color. ([#4028](https://github.com/mapbox/mapbox-gl-native/pull/4028)) - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) -- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417))) ## 3.1.2 @@ -199,4 +199,4 @@ Repackaging 0.5.1 as the Mapbox iOS SDK 2.0.0 series. Known issues: -- None. \ No newline at end of file +- None. From 62f636f0c09186c8419dfe1146ad756b1aa5d1eb Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Wed, 23 Mar 2016 23:22:05 -0700 Subject: [PATCH 070/104] [ios] Fix issues with static lib signing and app store submission Fix issues with static build configuration that caused it to be problematic for host applications when they were installed on device. Also fixes issues that broke the iTunes Connect validation and upload process. This also updates the `binary` instructions in INSTALL.md to reflect these changes. --- Makefile | 6 +++--- platform/ios/CHANGELOG.md | 2 ++ platform/ios/INSTALL.md | 12 ++++++++++-- platform/ios/scripts/package.sh | 30 +++++++++++++++++++++++------- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 553bae542..40dc5859a 100644 --- a/Makefile +++ b/Makefile @@ -51,9 +51,9 @@ ibench: export XCODEBUILD_ARGS += -sdk iphoneos ARCHS="arm64" ibench: ; $(RUN) HOST=ios Xcode/ios-bench .PHONY: ipackage ipackage-strip ipackage-sim itest -ipackage: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) ./platform/ios/scripts/package.sh -ipackage-strip: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO ./platform/ios/scripts/package.sh -ipackage-sim: Xcode/ios ; @JOBS=$(JOBS) BUILDTYPE=Debug BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=false SYMBOLS=$(SYMBOLS) ./platform/ios/scripts/package.sh +ipackage: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES ./platform/ios/scripts/package.sh +ipackage-strip: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES ./platform/ios/scripts/package.sh +ipackage-sim: Xcode/ios ; @JOBS=$(JOBS) BUILDTYPE=Debug BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=false SYMBOLS=$(SYMBOLS) BUNDLE_RESOURCES=YES PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=YES ./platform/ios/scripts/package.sh iframework: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=dynamic BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=$(SYMBOLS) ./platform/ios/scripts/package.sh ifabric: Xcode/ios ; @JOBS=$(JOBS) BITCODE=$(BITCODE) FORMAT=$(FORMAT) BUILD_DEVICE=$(BUILD_DEVICE) SYMBOLS=NO BUNDLE_RESOURCES=YES ./platform/ios/scripts/package.sh itest: ipackage-sim ; ./platform/ios/scripts/test.sh diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 4ea98833c..f9dcce764 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -20,6 +20,8 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) +- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417)) +- Fixed issues with configuration and documentation that caused problems when installing apps built with the static binary to devices. This change also fixed App Store submission problems when uploading an app built with the static binary. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) ## 3.1.2 diff --git a/platform/ios/INSTALL.md b/platform/ios/INSTALL.md index b4e27acde..416bbc638 100644 --- a/platform/ios/INSTALL.md +++ b/platform/ios/INSTALL.md @@ -95,7 +95,15 @@ If your application targets iOS 7.x, you’ll need to install the static framewo 1. Build from source manually per above. -1. Open the project editor and select your application target. Drag `build/ios/pkg/static/Mapbox.framework` into the “Embedded Binaries” section of the General tab. (Don’t drag it into the “Linked Frameworks and Libraries” section; Xcode will add it there automatically.) In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish. +1. Drag the Mapbox.bundle and Mapbox.framework files in `build/ios/pkg/static` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: + + - `Mapbox.framework` is listed in your `Link Binary With Libraries` build phase. + - Your *Framework Search Paths* (`FRAMEWORK_SEARCH_PATHS`) build setting includes the directory that contains `Mapbox.framework`. For most projects, the default value of `$(inherited) $(PROJECT_DIR)` should be sufficient. + - `Mapbox.bundle` is in your target's *Copy Bundle Resources* build phase. + +1. **Optional** As [noted in the documentation](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) you may use the provided Settings.bundle to provide a Telemetry opt out for users. To use the provided file, drag the `Settings.bundle` file in `build/ios/pkg` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: + + - `Settings.bundle` is in your target's *Copy Bundle Resources* build phase. 1. Add the following Cocoa Touch frameworks and libraries to the “Linked Frameworks and Libraries” section: @@ -138,4 +146,4 @@ class ViewController: UIViewController { ### Troubleshooting -On OS X, you can also try clearing the Xcode cache with `make clear_xcode_cache`. +On OS X, you can also try clearing the Xcode cache with `make clear_xcode_cache`. \ No newline at end of file diff --git a/platform/ios/scripts/package.sh b/platform/ios/scripts/package.sh index 9f843785e..137775ef7 100755 --- a/platform/ios/scripts/package.sh +++ b/platform/ios/scripts/package.sh @@ -27,13 +27,28 @@ if [[ ${BUNDLE_RESOURCES} ]]; then BUNDLE_PATH="/${NAME}.bundle" fi +PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK=${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK:-} +STATIC_BUNDLE_PATH= +if [[ ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK} ]]; then + STATIC_BUNDLE_PATH="${OUTPUT}/static${BUNDLE_PATH}" +else + STATIC_BUNDLE_PATH="${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" +fi + +STATIC_SETTINGS_DIRECTORY= +if [[ ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK} ]]; then + STATIC_SETTINGS_DIRECTORY="${OUTPUT}" +else + STATIC_SETTINGS_DIRECTORY="${OUTPUT}/static/${NAME}.framework" +fi + SDK=iphonesimulator if [[ ${BUILD_FOR_DEVICE} == true ]]; then SDK=iphoneos fi IOS_SDK_VERSION=`xcrun --sdk ${SDK} --show-sdk-version` -echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; Bitcode: ${ENABLE_BITCODE}; Mapbox.bundle: ${BUNDLE_RESOURCES}" +echo "Configuring ${FORMAT:-dynamic and static} ${BUILDTYPE} framework for ${SDK}; symbols: ${GCC_GENERATE_DEBUGGING_SYMBOLS}; Bitcode: ${ENABLE_BITCODE}; Mapbox.bundle: ${BUNDLE_RESOURCES} bundle.outside: ${PLACE_RESOURCE_BUNDLES_OUTSIDE_FRAMEWORK}" function step { >&2 echo -e "\033[1m\033[36m* $@\033[0m"; } function finish { >&2 echo -en "\033[0m"; } @@ -206,18 +221,19 @@ step "Copying library resources…" SEM_VERSION=$( git describe --tags --match=ios-v*.*.* --abbrev=0 | sed 's/^ios-v//' ) SHORT_VERSION=${SEM_VERSION%-*} if [[ ${BUNDLE_RESOURCES} ]]; then - cp -pv LICENSE.md "${OUTPUT}/static/${NAME}.framework" - cp -rv platform/ios/app/Settings.bundle "${OUTPUT}/static/${NAME}.framework" + cp -pv LICENSE.md ${STATIC_SETTINGS_DIRECTORY} + cp -rv platform/ios/app/Settings.bundle ${STATIC_SETTINGS_DIRECTORY} else cp -pv LICENSE.md "${OUTPUT}" cp -rv platform/ios/app/Settings.bundle "${OUTPUT}" fi if [[ ${BUILD_STATIC} == true ]]; then - mkdir -p "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" - cp -pv platform/{default,ios}/resources/* "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}" + mkdir -p ${STATIC_BUNDLE_PATH} + cp -pv platform/{default,ios}/resources/* ${STATIC_BUNDLE_PATH} INFO_PLIST_PATH="${OUTPUT}/static/${NAME}.framework/Info.plist" cp -pv platform/ios/framework/Info.plist "${INFO_PLIST_PATH}" - plutil -replace CFBundleExecutable -string ${NAME} "${INFO_PLIST_PATH}" + plutil -remove CFBundleExecutable "${INFO_PLIST_PATH}" + plutil -remove CFBundlePackageType "${INFO_PLIST_PATH}" plutil -replace CFBundleIdentifier -string com.mapbox.sdk.ios "${INFO_PLIST_PATH}" plutil -replace CFBundleName -string ${NAME} "${INFO_PLIST_PATH}" plutil -replace CFBundleShortVersionString -string "${SHORT_VERSION}" "${INFO_PLIST_PATH}" @@ -225,7 +241,7 @@ if [[ ${BUILD_STATIC} == true ]]; then plutil -replace MGLSemanticVersionString -string "${SEM_VERSION}" "${INFO_PLIST_PATH}" plutil -replace MGLCommitHash -string "${HASH}" "${INFO_PLIST_PATH}" if [[ ${BUNDLE_RESOURCES} ]]; then - cp -pv "${INFO_PLIST_PATH}" "${OUTPUT}/static/${NAME}.framework${BUNDLE_PATH}/Info.plist" + cp -pv "${INFO_PLIST_PATH}" "${STATIC_BUNDLE_PATH}/Info.plist" fi mkdir "${OUTPUT}/static/${NAME}.framework/Modules" cp -pv platform/ios/framework/modulemap "${OUTPUT}/static/${NAME}.framework/Modules/module.modulemap" From 2bd9b4a591b5a64f6c62b86edba2a0de4caf1a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 28 Mar 2016 11:32:33 -0700 Subject: [PATCH 071/104] [ios] Nixed duplicate changelog entry from bad merge --- platform/ios/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index f9dcce764..ca7ac6361 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -20,7 +20,6 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) -- The maximum maximum zoom level is now 21. ([#4417](https://github.com/mapbox/mapbox-gl-native/pull/4417)) - Fixed issues with configuration and documentation that caused problems when installing apps built with the static binary to devices. This change also fixed App Store submission problems when uploading an app built with the static binary. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) ## 3.1.2 From 635aebbb89d205a52806ebfa18214d3a649c7291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 28 Mar 2016 12:27:20 -0700 Subject: [PATCH 072/104] [ios, osx] Exclude offline cache from backups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid backing up the offline cache onto iCloud, because it can be redownloaded and would easily take up a significant portion of a standard iCloud account. Ideally, we’d even put ambiently cached resources in Caches, so it can be reclaimed by the system when disk space runs low. But unfortunately it has to live in the same file as offline resources. --- platform/darwin/src/MGLOfflineStorage.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 1f925b3ee..4dbfb0580 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -49,6 +49,12 @@ NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:fileName]; NSString *cachePath = cacheURL ? cacheURL.path : @""; + // Avoid backing up the offline cache onto iCloud, because it can be + // redownloaded. Ideally, we’d even put the ambient cache in Caches, so + // it can be reclaimed by the system when disk space runs low. But + // unfortunately it has to live in the same file as offline resources. + [cacheURL setResourceValue:@YES forKey:NSURLIsExcludedFromBackupKey error:NULL]; + // Move the offline cache from v3.2.0-beta.1 to a location that can also // be used for ambient caching. NSString *legacyCacheFileName = @"offline.db"; From 13882a31e478466b98dd4dfb7eebbd97c0627e06 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Mon, 28 Mar 2016 17:28:35 -0700 Subject: [PATCH 073/104] [core] Set schema version to 3 after upgrading The migration was upgrading the schema, but not the schema version. As a result, the (expensive) migration was running every time an OfflineDatabase was constructed with a v2 database. Fixes #4501 --- platform/default/mbgl/storage/offline_database.cpp | 1 + test/storage/offline_database.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 43f7abaf9..0b8dec01b 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -111,6 +111,7 @@ void OfflineDatabase::removeExisting() { void OfflineDatabase::migrateToVersion3() { db->exec("PRAGMA auto_vacuum = INCREMENTAL"); db->exec("VACUUM"); + db->exec("PRAGMA user_version = 3"); } OfflineDatabase::Statement OfflineDatabase::getStatement(const char * sql) { diff --git a/test/storage/offline_database.cpp b/test/storage/offline_database.cpp index 11d56c237..65812c6e8 100644 --- a/test/storage/offline_database.cpp +++ b/test/storage/offline_database.cpp @@ -669,6 +669,13 @@ static int databasePageCount(const std::string& path) { return stmt.get(0); } +static int databaseUserVersion(const std::string& path) { + mapbox::sqlite::Database db(path, mapbox::sqlite::ReadOnly); + mapbox::sqlite::Statement stmt = db.prepare("pragma user_version"); + stmt.run(); + return stmt.get(0); +} + TEST(OfflineDatabase, MigrateFromV2Schema) { using namespace mbgl; @@ -685,6 +692,7 @@ TEST(OfflineDatabase, MigrateFromV2Schema) { } } + EXPECT_EQ(3, databaseUserVersion("test/fixtures/offline/v3.db")); EXPECT_LT(databasePageCount("test/fixtures/offline/v3.db"), databasePageCount("test/fixtures/offline/v2.db")); } From 4df8136188da9d02b2db71bd173a4a757197c26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 28 Mar 2016 19:20:52 -0700 Subject: [PATCH 074/104] Relative paths to platform-specific changelogs --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09331d0e4..6b8572f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -As of iOS 3.2.0 and Android 4.0.0 we've split the CHANGELOG into platform specific CHANGELOGS to make it easier to follow the progress of a particular project. Their new locations are as follows: +As of iOS 3.2.0 and Android 4.0.0, we've split the CHANGELOG into platform specific CHANGELOGS to make it easier to follow the progress of a particular project. Their new locations are as follows: -* Android --> [`/platform/android/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/CHANGELOG.md) -* iOS --> [`/platform/ios/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/ios/CHANGELOG.md) -* Node.js --> [`/platform/node/CHANGELOG.md`](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/node/CHANGELOG.md) +* Android --> [`/platform/android/CHANGELOG.md`](platform/android/CHANGELOG.md) +* iOS --> [`/platform/ios/CHANGELOG.md`](platform/ios/CHANGELOG.md) +* Node.js --> [`/platform/node/CHANGELOG.md`](platform/node/CHANGELOG.md) From 5c45ffccb2150092b3abf8a669755a9c049bf5a7 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Mar 2016 09:50:16 -0700 Subject: [PATCH 075/104] Remove failing clang-tidy row from build matrix --- .travis.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index f287996b5..79090a21a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,6 @@ addons_shortcuts: sources: [ 'ubuntu-toolchain-r-test' ] packages: [ 'gdb', 'g++-4.9', 'gcc-4.9', 'libllvm3.4', 'xutils-dev', 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ] - addons_clang38-tidy: &clang38-tidy - apt: - sources: [ 'ubuntu-toolchain-r-test', 'llvm-toolchain-precise' ] - packages: [ 'clang-tidy-3.8', 'clang-3.8', 'libgcc-4.9-dev', 'libstdc++-4.9-dev', 'libstdc++6', - 'libllvm3.4', 'libclang-common-3.8-dev', 'libclang1-3.8', 'liblldb-3.8', - 'libllvm3.8', 'lldb-3.8', 'llvm-3.8', 'llvm-3.8-dev', 'llvm-3.8-runtime', 'xutils-dev', - 'libxxf86vm-dev', 'x11proto-xf86vidmode-dev', 'mesa-utils' ] matrix: exclude: @@ -57,12 +50,6 @@ matrix: env: FLAVOR=linux BUILDTYPE=Release _CXX=clang++-3.5 _CC=clang-3.5 CCACHE=1 addons: *clang35 - # clang-tidy - Clang 3.8 - Release - - os: linux - compiler: ": tidy-clang38-release" - env: FLAVOR=linux ACTION=tidy BUILDTYPE=Release _CXX=clang++-3.8 _CC=clang-3.8 AWS_ACCESS_KEY_ID= - addons: *clang38-tidy - cache: directories: - $HOME/.ccache From c4d435ce7160d949f281a4cf45d36ffddc93b150 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Mon, 28 Mar 2016 11:52:02 -0700 Subject: [PATCH 076/104] [ios] Update the pod-README and changelog regarding static lib changes --- platform/ios/CHANGELOG.md | 1 + platform/ios/docs/pod-README.md | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index ca7ac6361..56853cc4e 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -21,6 +21,7 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) - Fixed issues with configuration and documentation that caused problems when installing apps built with the static binary to devices. This change also fixed App Store submission problems when uploading an app built with the static binary. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) +- If you’ve previously installed the SDK as a static framework, the installation workflow has changed to address issues in the App Store submission process and installation on devices. The new workflow requires that you add Mapbox.bundle to the Copy Resources build phase and remove Mapbox.framework from the Embed Binaries build phase. ## 3.1.2 diff --git a/platform/ios/docs/pod-README.md b/platform/ios/docs/pod-README.md index e2c8ff813..4ca3847fd 100644 --- a/platform/ios/docs/pod-README.md +++ b/platform/ios/docs/pod-README.md @@ -33,7 +33,17 @@ bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mapbox.framework/strip-fra If your application targets iOS 7.x, you’ll need to install the static framework instead: -1. Open the project editor and select your application target. Drag `Mapbox.framework` from the `static` folder into the “Embedded Binaries” section of the General tab. (Don’t drag it into the “Linked Frameworks and Libraries” section; Xcode will add it there automatically.) In the sheet that appears, make sure “Copy items if needed” is checked, then click Finish. +1. Build from source manually per above. + +1. Drag the Mapbox.bundle and Mapbox.framework files in `build/ios/pkg/static` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: + + - `Mapbox.framework` is listed in your `Link Binary With Libraries` build phase. + - Your *Framework Search Paths* (`FRAMEWORK_SEARCH_PATHS`) build setting includes the directory that contains `Mapbox.framework`. For most projects, the default value of `$(inherited) $(PROJECT_DIR)` should be sufficient. + - `Mapbox.bundle` is in your target's *Copy Bundle Resources* build phase. + +1. **Optional** As [noted in the documentation](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) you may use the provided Settings.bundle to provide a Telemetry opt out for users. To use the provided file, drag the `Settings.bundle` file in `build/ios/pkg` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: + + - `Settings.bundle` is in your target's *Copy Bundle Resources* build phase. 1. Add the following Cocoa Touch frameworks and libraries to the “Linked Frameworks and Libraries” section: From 5adb102d98a08b6ed683aa72c5762f8e530453e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Mon, 28 Mar 2016 12:01:26 -0700 Subject: [PATCH 077/104] [ios] Copyedited changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrected a few Xcode terms in the changelog entry about static framework installation fixes. Merged that entry with the one above it because they discuss the same fixes. Also moved the combined entry to the top, because it’s about as close to a breaking change as we can get without incurring a major version bump. --- platform/ios/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 56853cc4e..473375469 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,6 +4,7 @@ Mapbox welcomes participation and contributions from everyone. If you’d like ## 3.2.0 +- If you’ve previously installed the SDK as a static framework, the installation workflow has changed to address issues when submitting your application to the App Store or installing it on a device. Upon upgrading to this version of the SDK, you’ll need to add Mapbox.bundle to the Copy Bundle Resources build phase and remove Mapbox.framework from the Embed Frameworks build phase. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) - Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) - Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) - The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) @@ -20,8 +21,6 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - The user dot no longer lags when panning the map. ([#3683](https://github.com/mapbox/mapbox-gl-native/pull/3683)) - The Improve This Map tool now uses the same zoom level that is currently being shown in the map view. ([#4068](https://github.com/mapbox/mapbox-gl-native/pull/4068)) - Fixed a formatting issue in the documentation for `MGLCoordinateBoundsIsEmpty()`. ([#3958](https://github.com/mapbox/mapbox-gl-native/pull/3958)) -- Fixed issues with configuration and documentation that caused problems when installing apps built with the static binary to devices. This change also fixed App Store submission problems when uploading an app built with the static binary. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) -- If you’ve previously installed the SDK as a static framework, the installation workflow has changed to address issues in the App Store submission process and installation on devices. The new workflow requires that you add Mapbox.bundle to the Copy Resources build phase and remove Mapbox.framework from the Embed Binaries build phase. ## 3.1.2 From 1d6ce5e80924429ca69a4a866e1d32cd0f3f7d09 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Tue, 29 Mar 2016 08:54:36 -0700 Subject: [PATCH 078/104] [ios] Make more adjustments to the pod readme for the static framework case --- platform/ios/docs/pod-README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/ios/docs/pod-README.md b/platform/ios/docs/pod-README.md index 4ca3847fd..d62e23b60 100644 --- a/platform/ios/docs/pod-README.md +++ b/platform/ios/docs/pod-README.md @@ -33,15 +33,13 @@ bash "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/Mapbox.framework/strip-fra If your application targets iOS 7.x, you’ll need to install the static framework instead: -1. Build from source manually per above. - -1. Drag the Mapbox.bundle and Mapbox.framework files in `build/ios/pkg/static` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: +1. Drag the Mapbox.bundle and Mapbox.framework files in `static` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: - `Mapbox.framework` is listed in your `Link Binary With Libraries` build phase. - Your *Framework Search Paths* (`FRAMEWORK_SEARCH_PATHS`) build setting includes the directory that contains `Mapbox.framework`. For most projects, the default value of `$(inherited) $(PROJECT_DIR)` should be sufficient. - `Mapbox.bundle` is in your target's *Copy Bundle Resources* build phase. -1. **Optional** As [noted in the documentation](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) you may use the provided Settings.bundle to provide a Telemetry opt out for users. To use the provided file, drag the `Settings.bundle` file in `build/ios/pkg` into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: +1. **Optional** As [noted in the documentation](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) you may use the provided Settings.bundle to provide a Telemetry opt out for users. To use the provided file, drag the `Settings.bundle` file from the release root folder into the Project navigator, checking "Copy items if needed". It should happen automatically, but ensure that: - `Settings.bundle` is in your target's *Copy Bundle Resources* build phase. From fb15582d5377f494b01247491970e061171b54c8 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Mon, 28 Mar 2016 11:57:45 -0700 Subject: [PATCH 079/104] [core] fix background-pattern rendering in perspective view fix #3801 --- package.json | 2 +- src/mbgl/renderer/painter.cpp | 84 ------------------ src/mbgl/renderer/painter.hpp | 9 +- src/mbgl/renderer/painter_background.cpp | 105 +++++++++++++++++++++++ src/mbgl/renderer/painter_fill.cpp | 23 ++--- src/mbgl/shader/pattern.vertex.glsl | 8 +- src/mbgl/shader/pattern_shader.hpp | 4 +- 7 files changed, 123 insertions(+), 112 deletions(-) create mode 100644 src/mbgl/renderer/painter_background.cpp diff --git a/package.json b/package.json index 57452a060..c178c3dfd 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ ], "devDependencies": { "aws-sdk": "^2.2.21", - "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#8859b504ef241bca49d4c2f9a79ff4d0bfdf81a1", + "mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#872753bf80fc026caf99e540b9f2089be8c06030", "node-gyp": "^3.2.1", "request": "^2.67.0", "tape": "^4.2.2" diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index ebadee35d..655e1c079 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -33,7 +33,6 @@ #include #include -#include #if defined(DEBUG) #include @@ -257,89 +256,6 @@ void Painter::renderPass(RenderPass pass_, } } -void Painter::renderBackground(const BackgroundLayer& layer) { - // Note that for bottommost layers without a pattern, the background color is drawn with - // glClear rather than this method. - const BackgroundPaintProperties& properties = layer.paint; - - if (!properties.pattern.value.to.empty()) { - optional imagePosA = spriteAtlas->getPosition(properties.pattern.value.from, true); - optional imagePosB = spriteAtlas->getPosition(properties.pattern.value.to, true); - - if (!imagePosA || !imagePosB) - return; - - config.program = patternShader->getID(); - patternShader->u_matrix = identityMatrix; - patternShader->u_pattern_tl_a = (*imagePosA).tl; - patternShader->u_pattern_br_a = (*imagePosA).br; - patternShader->u_pattern_tl_b = (*imagePosB).tl; - patternShader->u_pattern_br_b = (*imagePosB).br; - patternShader->u_mix = properties.pattern.value.t; - patternShader->u_opacity = properties.opacity; - - LatLng latLng = state.getLatLng(); - double centerX = state.lngX(latLng.longitude); - double centerY = state.latY(latLng.latitude); - float scale = 1 / std::pow(2, state.getZoomFraction()); - - std::array sizeA = (*imagePosA).size; - mat3 matrixA; - matrix::identity(matrixA); - matrix::scale(matrixA, matrixA, - 1.0f / (sizeA[0] * properties.pattern.value.fromScale), - 1.0f / (sizeA[1] * properties.pattern.value.fromScale)); - matrix::translate(matrixA, matrixA, - std::fmod(centerX, sizeA[0] * properties.pattern.value.fromScale), - std::fmod(centerY, sizeA[1] * properties.pattern.value.fromScale)); - matrix::rotate(matrixA, matrixA, -state.getAngle()); - matrix::scale(matrixA, matrixA, - scale * state.getWidth() / 2, - -scale * state.getHeight() / 2); - - std::array sizeB = (*imagePosB).size; - mat3 matrixB; - matrix::identity(matrixB); - matrix::scale(matrixB, matrixB, - 1.0f / (sizeB[0] * properties.pattern.value.toScale), - 1.0f / (sizeB[1] * properties.pattern.value.toScale)); - matrix::translate(matrixB, matrixB, - std::fmod(centerX, sizeB[0] * properties.pattern.value.toScale), - std::fmod(centerY, sizeB[1] * properties.pattern.value.toScale)); - matrix::rotate(matrixB, matrixB, -state.getAngle()); - matrix::scale(matrixB, matrixB, - scale * state.getWidth() / 2, - -scale * state.getHeight() / 2); - - patternShader->u_patternmatrix_a = matrixA; - patternShader->u_patternmatrix_b = matrixB; - - VertexArrayObject::Unbind(); - backgroundBuffer.bind(glObjectStore); - patternShader->bind(0); - spriteAtlas->bind(true, glObjectStore); - } else { - Color color = properties.color; - color[0] *= properties.opacity; - color[1] *= properties.opacity; - color[2] *= properties.opacity; - color[3] *= properties.opacity; - - config.program = plainShader->getID(); - plainShader->u_matrix = identityMatrix; - plainShader->u_color = color; - backgroundArray.bind(*plainShader, backgroundBuffer, BUFFER_OFFSET(0), glObjectStore); - } - - config.stencilTest = GL_FALSE; - config.depthFunc.reset(); - config.depthTest = GL_TRUE; - config.depthMask = GL_FALSE; - setDepthSublayer(0); - - MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -} - mat4 Painter::translatedMatrix(const mat4& matrix, const std::array &translation, const TileID &id, TranslateAnchorType anchor) { if (translation[0] == 0 && translation[1] == 0) { return matrix; diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp index 4a07d651d..e58985dcc 100644 --- a/src/mbgl/renderer/painter.hpp +++ b/src/mbgl/renderer/painter.hpp @@ -181,13 +181,6 @@ private: std::unique_ptr collisionBoxShader; std::unique_ptr circleShader; - StaticVertexBuffer backgroundBuffer = { - { -1, -1 }, { 1, -1 }, - { -1, 1 }, { 1, 1 } - }; - - VertexArrayObject backgroundArray; - // Set up the stencil quad we're using to generate the stencil mask. StaticVertexBuffer tileStencilBuffer = { // top left triangle @@ -203,6 +196,8 @@ private: VertexArrayObject coveringPlainArray; VertexArrayObject coveringRasterArray; + VertexArrayObject backgroundPatternArray; + VertexArrayObject backgroundArray; // Set up the tile boundary lines we're using to draw the tile outlines. StaticVertexBuffer tileBorderBuffer = { diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp new file mode 100644 index 000000000..fbca8b59f --- /dev/null +++ b/src/mbgl/renderer/painter_background.cpp @@ -0,0 +1,105 @@ +#include + +#include +#include +#include +#include +#include + +using namespace mbgl; + +void Painter::renderBackground(const BackgroundLayer& layer) { + // Note that for bottommost layers without a pattern, the background color is drawn with + // glClear rather than this method. + const BackgroundPaintProperties& properties = layer.paint; + + const bool isPatterned = !properties.pattern.value.to.empty();// && false; + optional imagePosA; + optional imagePosB; + + if (isPatterned) { + imagePosA = spriteAtlas->getPosition(properties.pattern.value.from, true); + imagePosB = spriteAtlas->getPosition(properties.pattern.value.to, true); + + if (!imagePosA || !imagePosB) + return; + + config.program = patternShader->getID(); + patternShader->u_matrix = identityMatrix; + patternShader->u_pattern_tl_a = (*imagePosA).tl; + patternShader->u_pattern_br_a = (*imagePosA).br; + patternShader->u_pattern_tl_b = (*imagePosB).tl; + patternShader->u_pattern_br_b = (*imagePosB).br; + patternShader->u_mix = properties.pattern.value.t; + patternShader->u_opacity = properties.opacity; + + spriteAtlas->bind(true, glObjectStore); + backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), glObjectStore); + + } else { + Color color = properties.color; + color[0] *= properties.opacity; + color[1] *= properties.opacity; + color[2] *= properties.opacity; + color[3] *= properties.opacity; + + config.program = plainShader->getID(); + plainShader->u_color = color; + backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), glObjectStore); + } + + config.stencilTest = GL_FALSE; + config.depthFunc.reset(); + config.depthTest = GL_TRUE; + config.depthMask = GL_FALSE; + setDepthSublayer(0); + + auto tileIDs = tileCover(state, state.getIntegerZoom(), state.getIntegerZoom()); + + for (auto &id: tileIDs) { + mat4 vtxMatrix; + state.matrixFor(vtxMatrix, id, id.z); + matrix::multiply(vtxMatrix, projMatrix, vtxMatrix); + + if (isPatterned) { + patternShader->u_matrix = vtxMatrix; + const float factor = util::EXTENT / util::tileSize; + + std::array imageSizeScaledA = {{ + (int)((*imagePosA).size[0] * properties.pattern.value.fromScale), + (int)((*imagePosA).size[1] * properties.pattern.value.fromScale) + }}; + std::array imageSizeScaledB = {{ + (int)((*imagePosB).size[0] * properties.pattern.value.toScale), + (int)((*imagePosB).size[1] * properties.pattern.value.toScale) + }}; + + patternShader->u_patternscale_a = {{ + 1.0f / (factor * imageSizeScaledA[0]), + 1.0f / (factor * imageSizeScaledA[1]) + }}; + patternShader->u_patternscale_b = {{ + 1.0f / (factor * imageSizeScaledB[0]), + 1.0f / (factor * imageSizeScaledB[1]) + }}; + + float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.x) / (float)imageSizeScaledA[0]; + float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.y) / (float)imageSizeScaledA[1]; + + float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * id.x) / (float)imageSizeScaledB[0]; + float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * id.y) / (float)imageSizeScaledB[1]; + + patternShader->u_offset_a = std::array{{offsetAx, offsetAy}}; + patternShader->u_offset_b = std::array{{offsetBx, offsetBy}}; + + + } else { + plainShader->u_matrix = vtxMatrix; + Color color = properties.color; + plainShader->u_color = color; + } + + MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)tileStencilBuffer.index())); + } + +} diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp index a8be7255b..d65745f4e 100644 --- a/src/mbgl/renderer/painter_fill.cpp +++ b/src/mbgl/renderer/painter_fill.cpp @@ -6,7 +6,6 @@ #include #include #include -#include using namespace mbgl; @@ -68,17 +67,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI const float factor = (util::EXTENT / util::tileSize / std::pow(2, state.getIntegerZoom() - id.sourceZ)); - mat3 patternMatrixA; - matrix::identity(patternMatrixA); - matrix::scale(patternMatrixA, patternMatrixA, - 1.0f / ((*posA).size[0] * factor * properties.pattern.value.fromScale), - 1.0f / ((*posA).size[1] * factor * properties.pattern.value.fromScale)); - mat3 patternMatrixB; - matrix::identity(patternMatrixB); - matrix::scale(patternMatrixB, patternMatrixB, - 1.0f / ((*posB).size[0] * factor * properties.pattern.value.toScale), - 1.0f / ((*posB).size[1] * factor * properties.pattern.value.toScale)); - config.program = patternShader->getID(); patternShader->u_matrix = vtxMatrix; patternShader->u_pattern_tl_a = (*posA).tl; @@ -88,8 +76,6 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI patternShader->u_opacity = properties.opacity; patternShader->u_image = 0; patternShader->u_mix = properties.pattern.value.t; - patternShader->u_patternmatrix_a = patternMatrixA; - patternShader->u_patternmatrix_b = patternMatrixB; std::array imageSizeScaledA = {{ (int)((*posA).size[0] * properties.pattern.value.fromScale), @@ -100,6 +86,15 @@ void Painter::renderFill(FillBucket& bucket, const FillLayer& layer, const TileI (int)((*posB).size[1] * properties.pattern.value.toScale) }}; + patternShader->u_patternscale_a = {{ + 1.0f / (factor * imageSizeScaledA[0]), + 1.0f / (factor * imageSizeScaledA[1]) + }}; + patternShader->u_patternscale_b = {{ + 1.0f / (factor * imageSizeScaledB[0]), + 1.0f / (factor * imageSizeScaledB[1]) + }}; + float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.x) / (float)imageSizeScaledA[0]; float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.y) / (float)imageSizeScaledA[1]; diff --git a/src/mbgl/shader/pattern.vertex.glsl b/src/mbgl/shader/pattern.vertex.glsl index 4ff51cad6..1363f1730 100644 --- a/src/mbgl/shader/pattern.vertex.glsl +++ b/src/mbgl/shader/pattern.vertex.glsl @@ -1,6 +1,6 @@ uniform mat4 u_matrix; -uniform mat3 u_patternmatrix_a; -uniform mat3 u_patternmatrix_b; +uniform vec2 u_patternscale_a; +uniform vec2 u_patternscale_b; uniform vec2 u_offset_a; uniform vec2 u_offset_b; @@ -12,6 +12,6 @@ varying vec2 v_pos_b; void main() { gl_Position = u_matrix * vec4(a_pos, 0, 1); - v_pos_a = (u_patternmatrix_a * vec3(a_pos, 1)).xy + u_offset_a; - v_pos_b = (u_patternmatrix_b * vec3(a_pos, 1)).xy + u_offset_b; + v_pos_a = u_patternscale_a * a_pos + u_offset_a; + v_pos_b = u_patternscale_b * a_pos + u_offset_b; } diff --git a/src/mbgl/shader/pattern_shader.hpp b/src/mbgl/shader/pattern_shader.hpp index 8692f6ed3..0898dc0b8 100644 --- a/src/mbgl/shader/pattern_shader.hpp +++ b/src/mbgl/shader/pattern_shader.hpp @@ -20,8 +20,8 @@ public: Uniform u_opacity = {"u_opacity", *this}; Uniform u_mix = {"u_mix", *this}; Uniform u_image = {"u_image", *this}; - UniformMatrix<3> u_patternmatrix_a = {"u_patternmatrix_a", *this}; - UniformMatrix<3> u_patternmatrix_b = {"u_patternmatrix_b", *this}; + Uniform> u_patternscale_a = {"u_patternscale_a", *this}; + Uniform> u_patternscale_b = {"u_patternscale_b", *this}; Uniform> u_offset_a = {"u_offset_a", *this}; Uniform> u_offset_b = {"u_offset_b", *this}; }; From af4871f7bf8ec6717b9bba2245af3a7ad7187ed5 Mon Sep 17 00:00:00 2001 From: Justas Medeisis Date: Mon, 28 Mar 2016 23:38:15 +0300 Subject: [PATCH 080/104] [android] #4510 - Remove onStart() and onStop() lifecycle methods from MapView. --- .../mapbox/mapboxsdk/maps/MapFragment.java | 2 -- .../com/mapbox/mapboxsdk/maps/MapView.java | 16 ------------- .../mapboxsdk/maps/SupportMapFragment.java | 2 -- .../maps/widgets/UserLocationView.java | 24 +++++++------------ .../testapp/AnimatedMarkerActivity.java | 12 ---------- .../mapboxsdk/testapp/BulkMarkerActivity.java | 12 ---------- .../mapboxsdk/testapp/CameraActivity.java | 12 ---------- .../testapp/CoordinateChangeActivity.java | 12 ---------- .../mapboxsdk/testapp/DirectionsActivity.java | 12 ---------- .../mapboxsdk/testapp/DoubleMapActivity.java | 14 ----------- .../testapp/DynamicMarkerChangeActivity.java | 13 ---------- .../mapboxsdk/testapp/GeocoderActivity.java | 12 ---------- .../mapboxsdk/testapp/InfoWindowActivity.java | 12 ---------- .../testapp/InfoWindowAdapterActivity.java | 12 ---------- .../testapp/InfoWindowConcurrentActivity.java | 12 ---------- .../testapp/LatLngBoundsActivity.java | 12 ---------- .../mapboxsdk/testapp/ManualZoomActivity.java | 12 ---------- .../mapboxsdk/testapp/MapPaddingActivity.java | 12 ---------- .../mapboxsdk/testapp/MapboxMapActivity.java | 12 ---------- .../MyLocationTrackingModeActivity.java | 12 ---------- .../mapboxsdk/testapp/OfflineActivity.java | 12 ---------- .../mapboxsdk/testapp/PolylineActivity.java | 12 ---------- .../testapp/PressForMarkerActivity.java | 12 ---------- .../mapboxsdk/testapp/ScrollByActivity.java | 12 ---------- .../mapboxsdk/testapp/TiltActivity.java | 12 ---------- 25 files changed, 9 insertions(+), 290 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java index dd056ff9b..2fefd805e 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapFragment.java @@ -76,7 +76,6 @@ public final class MapFragment extends Fragment { @Override public void onStart() { super.onStart(); - mMap.onStart(); mMap.getMapAsync(mOnMapReadyCallback); } @@ -115,7 +114,6 @@ public final class MapFragment extends Fragment { @Override public void onStop() { super.onStop(); - mMap.onStop(); } /** 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 883aac10a..5d4a171c1 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 @@ -496,22 +496,6 @@ public class MapView extends FrameLayout { mNativeMapView = null; } - /** - * You must call this method from the parent's {@link Activity#onStart()} or {@link Fragment#onStart()}. - */ - @UiThread - public void onStart() { - mUserLocationView.onStart(); - } - - /** - * You must call this method from the parent's {@link Activity#onStop()} or {@link Fragment#onStop()} - */ - @UiThread - public void onStop() { - mUserLocationView.onStop(); - } - /** * You must call this method from the parent's {@link Activity#onPause()} or {@link Fragment#onPause()}. */ diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java index 9cf946758..ffdb57de8 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/SupportMapFragment.java @@ -76,7 +76,6 @@ public class SupportMapFragment extends Fragment { @Override public void onStart() { super.onStart(); - mMap.onStart(); mMap.getMapAsync(mOnMapReadyCallback); } @@ -115,7 +114,6 @@ public class SupportMapFragment extends Fragment { @Override public void onStop() { super.onStop(); - mMap.onStop(); } /** diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java index 37a88e2ff..36e48488f 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java +++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/UserLocationView.java @@ -198,17 +198,6 @@ public final class UserLocationView extends View { mProjection = mapboxMap.getProjection(); } - public void onStart() { - if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) { - mBearingChangeListener.onStart(getContext()); - } - } - - public void onStop() { - mBearingChangeListener.onStop(); - cancelAnimations(); - } - @Override public void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -395,9 +384,9 @@ public final class UserLocationView extends View { if (myBearingTrackingMode == MyBearingTracking.COMPASS) { mShowAccuracy = false; mShowDirection = true; - mBearingChangeListener.onStart(getContext()); + mBearingChangeListener.onResume(); } else { - mBearingChangeListener.onStop(); + mBearingChangeListener.onPause(); if (myBearingTrackingMode == MyBearingTracking.GPS) { mShowDirection = (mUserLocation != null) && mUserLocation.hasBearing(); } else { @@ -433,12 +422,12 @@ public final class UserLocationView extends View { mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); } - public void onStart(Context context) { + public void onResume() { mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_GAME); } - public void onStop() { + public void onPause() { mSensorManager.unregisterListener(this, mAccelerometer); mSensorManager.unregisterListener(this, mMagnetometer); } @@ -661,11 +650,16 @@ public final class UserLocationView extends View { public void onPause() { mPaused = true; + mBearingChangeListener.onPause(); + cancelAnimations(); toggleGps(false); } public void onResume() { mPaused = false; + if (mMyBearingTrackingMode == MyBearingTracking.COMPASS) { + mBearingChangeListener.onResume(); + } if (isEnabled()) { toggleGps(true); } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java index a1386d7d1..27cd7f175 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/AnimatedMarkerActivity.java @@ -86,12 +86,6 @@ public class AnimatedMarkerActivity extends AppCompatActivity { } } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -104,12 +98,6 @@ public class AnimatedMarkerActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java index fda5648be..9381992bb 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/BulkMarkerActivity.java @@ -87,12 +87,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView // nothing selected, nothing to do! } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -105,12 +99,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java index dd3e4805b..3f7703954 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CameraActivity.java @@ -126,12 +126,6 @@ public class CameraActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -144,12 +138,6 @@ public class CameraActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java index 1270dbc67..f6b3095a0 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/CoordinateChangeActivity.java @@ -70,12 +70,6 @@ public class CoordinateChangeActivity extends AppCompatActivity { return first ? new LatLng(38.87000, -77.00800) : new LatLng(38.87031, -77.00897); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -88,12 +82,6 @@ public class CoordinateChangeActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java index 78ceabe4f..0292ce206 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DirectionsActivity.java @@ -140,12 +140,6 @@ public class DirectionsActivity extends AppCompatActivity { .width(5)); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -158,12 +152,6 @@ public class DirectionsActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java index 4452b03ff..b4dd6bd2c 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DoubleMapActivity.java @@ -107,13 +107,6 @@ public class DoubleMapActivity extends AppCompatActivity { }); } - @Override - public void onStart() { - super.onStart(); - mMapView.onStart(); - mMapViewMini.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -128,13 +121,6 @@ public class DoubleMapActivity extends AppCompatActivity { mMapViewMini.onPause(); } - @Override - public void onStop() { - super.onStop(); - mMapView.onStop(); - mMapViewMini.onStop(); - } - @Override public void onDestroy() { super.onDestroy(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java index 4a23ce576..a665a085e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/DynamicMarkerChangeActivity.java @@ -87,13 +87,6 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity { mMarker.setIcon(mIconFactory.fromResource(first ? R.drawable.ic_chelsea : R.drawable.ic_arsenal)); } - - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -106,12 +99,6 @@ public class DynamicMarkerChangeActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java index 585cb8931..618515147 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/GeocoderActivity.java @@ -107,18 +107,6 @@ public class GeocoderActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mapView.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - mapView.onStop(); - } - @Override public void onPause() { super.onPause(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java index e1172c289..d857d665b 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowActivity.java @@ -107,12 +107,6 @@ public class InfoWindowActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -125,12 +119,6 @@ public class InfoWindowActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java index 32e1d306d..56aa96502 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowAdapterActivity.java @@ -98,12 +98,6 @@ public class InfoWindowAdapterActivity extends AppCompatActivity { return marker; } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -116,12 +110,6 @@ public class InfoWindowAdapterActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java index 6ca86a412..6fa5be3ce 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/InfoWindowConcurrentActivity.java @@ -57,12 +57,6 @@ public class InfoWindowConcurrentActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -75,12 +69,6 @@ public class InfoWindowConcurrentActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java index 5a9c11350..24c6e7eb2 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/LatLngBoundsActivity.java @@ -83,12 +83,6 @@ public class LatLngBoundsActivity extends AppCompatActivity { } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -101,12 +95,6 @@ public class LatLngBoundsActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java index cabbc72da..5d0d4b1ee 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ManualZoomActivity.java @@ -91,12 +91,6 @@ public class ManualZoomActivity extends AppCompatActivity { } } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -109,12 +103,6 @@ public class ManualZoomActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java index 59a418543..c5e25f48d 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapPaddingActivity.java @@ -58,12 +58,6 @@ public class MapPaddingActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -76,12 +70,6 @@ public class MapPaddingActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java index ddab53010..b397d5d68 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxMapActivity.java @@ -56,12 +56,6 @@ public class MapboxMapActivity extends AppCompatActivity { Snackbar.LENGTH_INDEFINITE).show(); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -74,12 +68,6 @@ public class MapboxMapActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java index a201d2bc9..5a349c396 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MyLocationTrackingModeActivity.java @@ -169,12 +169,6 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -193,12 +187,6 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity implements mMapView.onSaveInstanceState(outState); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onDestroy() { super.onDestroy(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java index 3a156c55f..c6fae95d7 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/OfflineActivity.java @@ -121,12 +121,6 @@ public class OfflineActivity extends AppCompatActivity mOfflineManager.setAccessToken(ApiAccess.getToken(this)); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -139,12 +133,6 @@ public class OfflineActivity extends AppCompatActivity mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java index 46f926c61..997009d43 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PolylineActivity.java @@ -116,12 +116,6 @@ public class PolylineActivity extends AppCompatActivity { }}; } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -134,12 +128,6 @@ public class PolylineActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java index ab574d8b5..de78de62f 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/PressForMarkerActivity.java @@ -92,12 +92,6 @@ public class PressForMarkerActivity extends AppCompatActivity implements MapboxM mMapboxMap.addMarker(marker); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -117,12 +111,6 @@ public class PressForMarkerActivity extends AppCompatActivity implements MapboxM outState.putParcelableArrayList(STATE_MARKER_LIST, mMarkerList); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onDestroy() { super.onDestroy(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java index ec68a8441..57099e3ad 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/ScrollByActivity.java @@ -80,12 +80,6 @@ public class ScrollByActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -98,12 +92,6 @@ public class ScrollByActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java index b178b24c2..9ed66e4dc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/TiltActivity.java @@ -45,18 +45,6 @@ public class TiltActivity extends AppCompatActivity { }); } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override public void onPause() { super.onPause(); From bbab5a5b5e9b3cd2461a1c088f8610e6f1938686 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 29 Mar 2016 10:03:05 +0200 Subject: [PATCH 081/104] [android] #4510 - clean up test app with onStart/onStart references. --- .../com/mapbox/mapboxsdk/testapp/MainActivity.java | 9 --------- .../mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java | 12 ------------ 2 files changed, 21 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java index 45d6d3377..17bf76726 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MainActivity.java @@ -245,8 +245,6 @@ public class MainActivity extends AppCompatActivity { != PackageManager.PERMISSION_GRANTED)) { toggleGps(false); } - - mMapView.onStart(); } // Called when our app comes into the foreground @@ -265,13 +263,6 @@ public class MainActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - - mMapView.onStop(); - } - @Override protected void onDestroy() { super.onDestroy(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java index a5fa5d61b..f167e1e5e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MaxMinZoomActivity.java @@ -90,12 +90,6 @@ public class MaxMinZoomActivity extends AppCompatActivity { } } - @Override - protected void onStart() { - super.onStart(); - mMapView.onStart(); - } - @Override public void onResume() { super.onResume(); @@ -108,12 +102,6 @@ public class MaxMinZoomActivity extends AppCompatActivity { mMapView.onPause(); } - @Override - protected void onStop() { - super.onStop(); - mMapView.onStop(); - } - @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); From a1e5701fa3fa7041cbbdd3edabd1c6a8006ce68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 25 Mar 2016 17:02:08 -0700 Subject: [PATCH 082/104] [ios, osx] Centralized offline pack management MGLOfflineStorage now maintains a centralized, strongly held, KVO-compliant collection of all extant offline packs. MGLOfflineStorage issues notifications for progress updates. Client code can now react to the successful addition of an offline pack either via the completion block or via a KVO insertion. Fixes #4287. --- platform/darwin/include/MGLOfflinePack.h | 10 -- platform/darwin/include/MGLOfflineStorage.h | 36 +++--- platform/darwin/src/MGLOfflinePack_Private.h | 10 ++ platform/darwin/src/MGLOfflineStorage.mm | 110 ++++++++++++++++-- .../app/MBXOfflinePacksTableViewController.m | 110 +++++++++++------- 5 files changed, 194 insertions(+), 82 deletions(-) diff --git a/platform/darwin/include/MGLOfflinePack.h b/platform/darwin/include/MGLOfflinePack.h index d1f5a3ed5..fd8080523 100644 --- a/platform/darwin/include/MGLOfflinePack.h +++ b/platform/darwin/include/MGLOfflinePack.h @@ -148,16 +148,6 @@ typedef struct MGLOfflinePackProgress { */ - (void)suspend; -/** - Request an asynchronous update to the pack’s `state` and `progress` properties. - - The state and progress of an inactive or completed pack are computed lazily. If - you need the state or progress of a pack inside an - `MGLOfflinePackListingCompletionHandler`, set the `delegate` property then call - this method. - */ -- (void)requestProgress; - @end /** diff --git a/platform/darwin/include/MGLOfflineStorage.h b/platform/darwin/include/MGLOfflineStorage.h index 4f3432163..931982dce 100644 --- a/platform/darwin/include/MGLOfflineStorage.h +++ b/platform/darwin/include/MGLOfflineStorage.h @@ -7,6 +7,13 @@ NS_ASSUME_NONNULL_BEGIN @class MGLOfflinePack; @protocol MGLOfflineRegion; +extern NSString * const MGLOfflinePackProgressChangedNotification; +extern NSString * const MGLOfflinePackErrorNotification; +extern NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification; + +extern NSString * const MGLOfflinePackErrorUserInfoKey; +extern NSString * const MGLOfflinePackMaximumCountUserInfoKey; + /** A block to be called once an offline pack has been completely created and added. @@ -28,16 +35,6 @@ typedef void (^MGLOfflinePackAdditionCompletionHandler)(MGLOfflinePack * _Nullab */ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error); -/** - A block to be called with a complete list of offline packs. - - @param pack Contains a pointer an array of packs, or `nil` if there was an - error obtaining the packs. - @param error Contains a pointer to an error object (if any) indicating why the - list of packs could not be obtained. - */ -typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError * _Nullable error); - /** MGLOfflineStorage implements a singleton (shared object) that manages offline packs. All of this class’s instance methods are asynchronous, reflecting the @@ -50,7 +47,16 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac */ + (instancetype)sharedOfflineStorage; -- (instancetype)init NS_UNAVAILABLE; +/** + An array of all known offline packs. + + This property is set to `nil`, indicating that the receiver does not yet know + the existing packs, for an undefined amount of time starting from the moment + the shared offline storage object is initialized until the packs are fetched + from the database. After that point, this property is always non-nil, but it + may be empty to indicate that no packs are present. + */ +@property (nonatomic, copy, readonly, nullable) NS_ARRAY_OF(MGLOfflinePack *) *packs; /** Creates and registers an offline pack that downloads the resources needed to @@ -84,14 +90,6 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac */ - (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(nullable MGLOfflinePackRemovalCompletionHandler)completion; -/** - Asynchronously calls a completion callback with all existing offline packs. - - @param completion The completion handler to call with the list of packs. This - handler is executed asynchronously on the main queue. - */ -- (void)getPacksWithCompletionHandler:(MGLOfflinePackListingCompletionHandler)completion; - /** Sets the maximum number of Mapbox-hosted tiles that may be downloaded and stored on the current device. diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index e29018fc3..c1637ab4a 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -10,6 +10,16 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region; +/** + Request an asynchronous update to the pack’s `state` and `progress` properties. + + The state and progress of an inactive or completed pack are computed lazily. If + you need the state or progress of a pack inside an + `MGLOfflinePackListingCompletionHandler`, set the `delegate` property then call + this method. + */ +- (void)requestProgress; + /** Invalidates the pack and ensures that no future progress update can ever revalidate it. diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 4dbfb0580..2add5e105 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -8,12 +8,31 @@ #include -@interface MGLOfflineStorage () +static NSString * const MGLOfflineStorageFileName = @"cache.db"; +static NSString * const MGLOfflineStorageFileName3_2_0_beta_1 = @"offline.db"; +NSString * const MGLOfflinePackProgressChangedNotification = @"MGLOfflinePackProgressChanged"; +NSString * const MGLOfflinePackErrorNotification = @"MGLOfflinePackError"; +NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOfflinePackMaximumMapboxTilesReached"; + +NSString * const MGLOfflinePackErrorUserInfoKey = @"Error"; +NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; + +/** + A block to be called with a complete list of offline packs. + + @param pack Contains a pointer an array of packs, or `nil` if there was an + error obtaining the packs. + @param error Contains a pointer to an error object (if any) indicating why the + list of packs could not be obtained. + */ +typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError * _Nullable error); + +@interface MGLOfflineStorage () + +@property (nonatomic, copy, readwrite) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *packs; @property (nonatomic) mbgl::DefaultFileSource *mbglFileSource; -- (instancetype)initWithFileName:(NSString *)fileName NS_DESIGNATED_INITIALIZER; - @end @implementation MGLOfflineStorage @@ -22,14 +41,20 @@ static dispatch_once_t onceToken; static MGLOfflineStorage *sharedOfflineStorage; dispatch_once(&onceToken, ^{ - sharedOfflineStorage = [[self alloc] initWithFileName:@"cache.db"]; + sharedOfflineStorage = [[self alloc] init]; + [sharedOfflineStorage getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, __unused NSError *error) { + sharedOfflineStorage.packs = [packs mutableCopy]; + + for (MGLOfflinePack *pack in packs) { + pack.delegate = sharedOfflineStorage; + [pack requestProgress]; + } + }]; }); return sharedOfflineStorage; } -// This method can’t be called -init, because that selector has been marked -// unavailable in MGLOfflineStorage.h. -- (instancetype)initWithFileName:(NSString *)fileName { +- (instancetype)init { if (self = [super init]) { // Place the cache in a location specific to the application, so that // packs downloaded by other applications don’t count toward this @@ -46,7 +71,7 @@ withIntermediateDirectories:YES attributes:nil error:nil]; - NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:fileName]; + NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName]; NSString *cachePath = cacheURL ? cacheURL.path : @""; // Avoid backing up the offline cache onto iCloud, because it can be @@ -57,11 +82,10 @@ // Move the offline cache from v3.2.0-beta.1 to a location that can also // be used for ambient caching. - NSString *legacyCacheFileName = @"offline.db"; #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR // ~/Documents/offline.db NSArray *legacyPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:legacyCacheFileName]; + NSString *legacyCachePath = [legacyPaths.firstObject stringByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1]; #elif TARGET_OS_MAC // ~/Library/Caches/tld.app.bundle.id/offline.db NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory @@ -75,7 +99,7 @@ withIntermediateDirectories:YES attributes:nil error:nil]; - NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:legacyCacheFileName]; + NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageLegacyFileName]; NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @""; #endif if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) { @@ -101,17 +125,52 @@ _mbglFileSource = nullptr; } -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NS_DICTIONARY_OF(NSString *, id) *)change context:(__unused void *)context { +#pragma mark KVO methods + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NS_DICTIONARY_OF(NSString *, id) *)change context:(void *)context { // Synchronize the file source’s access token with the global one in MGLAccountManager. if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) { NSString *accessToken = change[NSKeyValueChangeNewKey]; if (![accessToken isKindOfClass:[NSNull class]]) { self.mbglFileSource->setAccessToken(accessToken.UTF8String); } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } +- (void)insertPacks:(NSArray *)packs atIndexes:(NSIndexSet *)indices { + [(NSMutableArray *)self.packs insertObjects:packs atIndexes:indices]; +} + +- (void)addPacksObject:(MGLOfflinePack *)pack { + [(NSMutableArray *)self.packs addObject:pack]; +} + +- (void)removePacksAtIndexes:(NSIndexSet *)indices { + [(NSMutableArray *)self.packs removeObjectsAtIndexes:indices]; +} + +- (void)removePacksObject:(MGLOfflinePack *)pack { + [(NSMutableArray *)self.packs removeObject:pack]; +} + +#pragma mark Pack management methods + - (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion { + __weak MGLOfflineStorage *weakSelf = self; + [self _addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable pack, NSError * _Nullable error) { + MGLOfflineStorage *strongSelf = weakSelf; + [strongSelf addPacksObject:pack]; + pack.delegate = strongSelf; + [pack requestProgress]; + if (completion) { + completion(pack, error); + } + }]; +} + +- (void)_addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion { if (![region conformsToProtocol:@protocol(MGLOfflineRegion_Private)]) { [NSException raise:@"Unsupported region type" format: @"Regions of type %@ are unsupported.", NSStringFromClass([region class])]; @@ -139,6 +198,15 @@ } - (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(MGLOfflinePackRemovalCompletionHandler)completion { + [self removePacksObject:pack]; + [self _removePack:pack withCompletionHandler:^(NSError * _Nullable error) { + if (completion) { + completion(error); + } + }]; +} + +- (void)_removePack:(MGLOfflinePack *)pack withCompletionHandler:(MGLOfflinePackRemovalCompletionHandler)completion { mbgl::OfflineRegion *mbglOfflineRegion = pack.mbglOfflineRegion; [pack invalidate]; self.mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) { @@ -184,4 +252,22 @@ _mbglFileSource->setOfflineMapboxTileCountLimit(maximumCount); } +#pragma mark MGLOfflinePackDelegate methods + +- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(__unused MGLOfflinePackProgress)progress { + [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackProgressChangedNotification object:pack]; +} + +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error { + [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackErrorNotification object:pack userInfo:@{ + MGLOfflinePackErrorUserInfoKey: error, + }]; +} + +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount { + [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackMaximumMapboxTilesReachedNotification object:pack userInfo:@{ + MGLOfflinePackMaximumCountUserInfoKey: @(maximumCount), + }]; +} + @end diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index fb9d5fb3e..4f399d3d4 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -28,12 +28,6 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac @end -@interface MBXOfflinePacksTableViewController () - -@property (nonatomic, strong) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *offlinePacks; - -@end - @implementation MBXOfflinePacksTableViewController { NSUInteger _untitledRegionCount; } @@ -41,25 +35,48 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac - (void)viewDidLoad { [super viewDidLoad]; - __weak MBXOfflinePacksTableViewController *weakSelf = self; - [[MGLOfflineStorage sharedOfflineStorage] getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError *error) { - MBXOfflinePacksTableViewController *strongSelf = weakSelf; - strongSelf.offlinePacks = packs.mutableCopy; - [strongSelf.tableView reloadData]; - - for (MGLOfflinePack *pack in strongSelf.offlinePacks) { - pack.delegate = strongSelf; - [pack requestProgress]; - } - - if (error) { - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Can’t Find Offline Packs" message:@"Mapbox GL was unable to find the existing offline packs." preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; - [self presentViewController:alertController animated:YES completion:^{ - [strongSelf dismissViewControllerAnimated:YES completion:nil]; + [[MGLOfflineStorage sharedOfflineStorage] addObserver:self forKeyPath:@"packs" options:NSKeyValueObservingOptionInitial context:NULL]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackProgressDidChange:) name:MGLOfflinePackProgressChangedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveError:) name:MGLOfflinePackErrorNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(offlinePackDidReceiveMaximumAllowedMapboxTiles:) name:MGLOfflinePackMaximumMapboxTilesReachedNotification object:nil]; +} + +- (void)dealloc { + [[MGLOfflineStorage sharedOfflineStorage] removeObserver:self forKeyPath:@"packs"]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NS_DICTIONARY_OF(NSString *, id) *)change context:(void *)context { + if ([keyPath isEqualToString:@"packs"]) { + NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; + NSIndexSet *indices = change[NSKeyValueChangeIndexesKey]; + NSMutableArray *indexPaths; + if (indices) { + indexPaths = [NSMutableArray arrayWithCapacity:indices.count]; + [indices enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { + [indexPaths addObject:[NSIndexPath indexPathForRow:idx inSection:0]]; }]; } - }]; + switch (changeKind) { + case NSKeyValueChangeInsertion: + [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; + break; + + case NSKeyValueChangeRemoval: + [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; + break; + + case NSKeyValueChangeReplacement: + [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationAutomatic]; + break; + + default: + [self.tableView reloadData]; + break; + } + } else { + [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; + } } - (IBAction)addCurrentRegion:(id)sender { @@ -89,13 +106,6 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Can’t Add Offline Pack" message:message preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; [self presentViewController:alertController animated:YES completion:nil]; - } else { - pack.delegate = strongSelf; - [pack resume]; - - NSIndexPath *indexPath = [NSIndexPath indexPathForRow:strongSelf.offlinePacks.count inSection:0]; - [strongSelf.offlinePacks addObject:pack]; - [strongSelf.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } }]; }]; @@ -110,11 +120,11 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.offlinePacks.count; + return [MGLOfflineStorage sharedOfflineStorage].packs.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; + MGLOfflinePack *pack = [MGLOfflineStorage sharedOfflineStorage].packs[indexPath.row]; NSString *reuseIdentifier = pack.state == MGLOfflinePackStateActive ? MBXOfflinePacksTableViewActiveCellReuseIdentifier : MBXOfflinePacksTableViewInactiveCellReuseIdentifier; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; @@ -165,9 +175,7 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { - MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; - [self.offlinePacks removeObjectAtIndex:indexPath.row]; - [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + MGLOfflinePack *pack = [MGLOfflineStorage sharedOfflineStorage].packs[indexPath.row]; [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:nil]; } } @@ -177,7 +185,7 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; + MGLOfflinePack *pack = [MGLOfflineStorage sharedOfflineStorage].packs[indexPath.row]; switch (pack.state) { case MGLOfflinePackStateUnknown: break; @@ -207,8 +215,11 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac #pragma mark - Offline pack delegate -- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(MGLOfflinePackProgress)progress { - NSUInteger index = [self.offlinePacks indexOfObject:pack]; +- (void)offlinePackProgressDidChange:(NSNotification *)notification { + MGLOfflinePack *pack = notification.object; + NSAssert([pack isKindOfClass:[MGLOfflinePack class]], @"MGLOfflineStorage notification has a non-pack object."); + + NSUInteger index = [[MGLOfflineStorage sharedOfflineStorage].packs indexOfObject:pack]; if (index == NSNotFound) { return; } @@ -217,11 +228,28 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; } -- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error { - NSLog(@"Offline pack “%@” received error: %@", pack.name, error.localizedFailureReason); +- (void)offlinePackDidReceiveError:(NSNotification *)notification { + MGLOfflinePack *pack = notification.object; + NSAssert([pack isKindOfClass:[MGLOfflinePack class]], @"MGLOfflineStorage notification has a non-pack object."); + + NSError *error = notification.userInfo[MGLOfflinePackErrorUserInfoKey]; + NSAssert([error isKindOfClass:[NSError class]], @"MGLOfflineStorage notification has a non-error error."); + + NSString *message = [NSString stringWithFormat:@"iosapp encountered an error while downloading the offline pack “%@”: %@", pack.name, error.localizedFailureReason]; + if (error.code == MGLErrorCodeConnectionFailed) { + NSLog(@"%@", message); + } else { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Error Downloading Offline Pack" message:message preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alertController animated:YES completion:nil]; + } } -- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount { +- (void)offlinePackDidReceiveMaximumAllowedMapboxTiles:(NSNotification *)notification { + MGLOfflinePack *pack = notification.object; + NSAssert([pack isKindOfClass:[MGLOfflinePack class]], @"MGLOfflineStorage notification has a non-pack object."); + + uint64_t maximumCount = [notification.userInfo[MGLOfflinePackMaximumCountUserInfoKey] unsignedLongLongValue]; NSLog(@"Offline pack “%@” reached limit of %llu tiles.", pack.name, maximumCount); } From 55f1ad11c4cc95425c733153d919eccf6de1685d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 10:21:49 -0700 Subject: [PATCH 083/104] [ios, osx] More accurate KVO, private delegate, descriptive fallback name, fewer reloads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Made MGLOfflineStorage.packs strong rather than copy so that KVO notifications on that key path include index paths. Replaced custom KVO mutable collection methods with calls to -mutableArrayValueForKey:, avoiding redundant casts. Privatized MGLOfflinePackDelegate and made its methods required, since MGLOfflineStorage is the only conforming implementation. Require a pack to be explicitly invalidated before deallocation by its owner (MGLOfflineStorage). Added a method to reload the canonical collection of packs. Previously, if the user adds an offline pack without specifying a name in the alert, the pack would be named “Untitled n” for the nth pack created since the application was launched. This logic could result in identically named packs (for example, if the user relaunches and creates another unnamed pack). Instead, use the visible coordinate bounds as a placeholder and fallback name. Resume a pack upon successful addition. Removed an extraneous weakSelf/strongSelf dance. When possible, update individual labels in a cell instead of reloading the entire cell. That way, if the user swipes to the left to reveal the Delete accessory button while the pack is actively downloading, the accessory button remains on screen as progress updates come in. --- platform/darwin/include/MGLOfflinePack.h | 104 +++++---------- platform/darwin/include/MGLOfflineStorage.h | 119 +++++++++++++++--- platform/darwin/src/MGLOfflinePack.mm | 24 ++-- platform/darwin/src/MGLOfflinePack_Private.h | 54 ++++++++ platform/darwin/src/MGLOfflineStorage.mm | 60 +++------ .../app/MBXOfflinePacksTableViewController.m | 30 +++-- 6 files changed, 238 insertions(+), 153 deletions(-) diff --git a/platform/darwin/include/MGLOfflinePack.h b/platform/darwin/include/MGLOfflinePack.h index fd8080523..666e442d2 100644 --- a/platform/darwin/include/MGLOfflinePack.h +++ b/platform/darwin/include/MGLOfflinePack.h @@ -4,8 +4,6 @@ NS_ASSUME_NONNULL_BEGIN -@protocol MGLOfflinePackDelegate; - /** The state an offline pack is currently in. */ @@ -13,11 +11,9 @@ typedef NS_ENUM (NSInteger, MGLOfflinePackState) { /** It is unknown whether the pack is inactive, active, or complete. - This is the initial state of a pack that is obtained using the - `-[MGLOfflineStorage getPacksWithCompletionHandler:]` method. The state - becomes known by the time the pack’s delegate receives its first progress - update. For inactive packs, you must explicitly request a progress update - using the `-[MGLOfflinePack requestProgress]` method. + This is the initial state of a pack. The state becomes known by the time + the shared `MGLOfflineStorage` object sends its first + `MGLOfflinePackProgressChangedNotification`. An invalid pack always has a state of `MGLOfflinePackStateInvalid`, never `MGLOfflinePackStateUnknown`. @@ -86,9 +82,7 @@ typedef struct MGLOfflinePackProgress { /** An `MGLOfflinePack` represents a collection of resources necessary for viewing - a region offline to a local database. It provides an optional - `MGLOfflinePackDelegate` object with progress updates as data or errors arrive - from the server. + a region offline to a local database. */ @interface MGLOfflinePack : NSObject @@ -109,9 +103,11 @@ typedef struct MGLOfflinePackProgress { The pack’s current state. The state of an inactive or completed pack is computed lazily and is set to - `MGLOfflinePackStateUnknown` by default. If you need the state of a pack - inside an `MGLOfflinePackListingCompletionHandler`, set the `delegate` property - then call the `-requestProgress` method. + `MGLOfflinePackStateUnknown` by default. To get notified when the state becomes + known, observe KVO change notifications on this pack’s `state` key path. + Alternatively, you can add an observer for + `MGLOfflinePackProgressChangedNotification`s about this pack that come from the + default notification center. */ @property (nonatomic, readonly) MGLOfflinePackState state; @@ -119,80 +115,48 @@ typedef struct MGLOfflinePackProgress { The pack’s current progress. The progress of an inactive or completed pack is computed lazily, and all its - fields are set to 0 by default. If you need the progress of a pack inside an - `MGLOfflinePackListingCompletionHandler`, set the `delegate` property then call - the `-requestProgress` method. + fields are set to 0 by default. To get notified when the progress becomes + known, observe KVO change notifications on this pack’s `state` key path. + Alternatively, you can add an observer for + `MGLOfflinePackProgressChangedNotification`s about this pack that come from the + default notification center. */ @property (nonatomic, readonly) MGLOfflinePackProgress progress; -/** - The pack’s delegate. - - You can use the offline pack delegate to be notified of any changes in the - pack’s progress and of any errors while downloading. For more information, see - the `MGLOfflinePackDelegate` documentation. - */ -@property (nonatomic, weak, nullable) id delegate; - - (instancetype)init NS_UNAVAILABLE; /** Resumes downloading if the pack is inactive. + + A pack resumes asynchronously. To get notified when this pack resumes, observe + KVO change notifications on this pack’s `state` key path. Alternatively, you + can add an observer for `MGLOfflinePackProgressChangedNotification`s about this + pack that come from the default notification center. + + When a pack resumes after being suspended, it may begin by iterating over the + already downloaded resources. As a result, the `progress` structure’s + `countOfResourcesCompleted` field may revert to 0 before rapidly returning to + the level of progress at the time the pack was suspended. + + To temporarily suspend downloading, call the `-suspend` method. */ - (void)resume; /** Temporarily stops downloading if the pack is active. + A pack suspends asynchronously. To get notified when this pack resumes, observe + KVO change notifications on this pack’s `state` key path. Alternatively, you + can add an observer for `MGLOfflinePackProgressChangedNotification` about this + pack that come from the default notification center. + + If the pack previously reached a higher level of progress before being + suspended, it may wait to suspend until it returns to that level. + To resume downloading, call the `-resume` method. */ - (void)suspend; @end -/** - The `MGLOfflinePackDelegate` protocol defines methods that a delegate of an - `MGLOfflinePack` object can optionally implement to be notified of any changes - in the pack’s download progress and of any errors while downloading. - */ -@protocol MGLOfflinePackDelegate - -@optional - -/** - Sent whenever the pack’s state or download progress changes. Every change to a - field in the `progress` property corresponds to an invocation of this method. - - @param pack The pack whose state of progress changed. - @param progress The updated progress. To get the updated state, refer to the - `state` property. - */ -- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(MGLOfflinePackProgress)progress; - -/** - Sent whenever the pack encounters an error while downloading. - - Download errors may be recoverable. For example, this pack’s implementation may - attempt to re-request failed resources based on an exponential backoff - strategy or upon the restoration of network access. - - @param pack The pack that encountered an error. - @param error A download error. For a list of possible error codes, see - `MGLErrorCode`. - */ -- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error; - -/** - Sent when the maximum number of Mapbox-hosted tiles has been downloaded and - stored on the current device. - - Once this limit is reached, no instance of `MGLOfflinePack` can download - additional tiles from Mapbox APIs until already downloaded tiles are removed by - calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method. - Contact your Mapbox sales representative to have the limit raised. - */ -- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount; - -@end - NS_ASSUME_NONNULL_END diff --git a/platform/darwin/include/MGLOfflineStorage.h b/platform/darwin/include/MGLOfflineStorage.h index 931982dce..f9ddba038 100644 --- a/platform/darwin/include/MGLOfflineStorage.h +++ b/platform/darwin/include/MGLOfflineStorage.h @@ -7,22 +7,76 @@ NS_ASSUME_NONNULL_BEGIN @class MGLOfflinePack; @protocol MGLOfflineRegion; +/** + Posted by the shared `MGLOfflineStorage` object when an `MGLOfflinePack` + object’s progress changes. The progress may change due to a resource being + downloaded or because the pack discovers during the download that more + resources are required for offline viewing. This notification is posted + whenever any field in the `progress` property changes. + + The `object` is the `MGLOfflinePack` object whose progress changed. For details + about the pack’s current progress, use the pack’s `progress` property. + + If you only need to observe changes in a particular pack’s progress, you can + alternatively observe KVO change notifications to the pack’s `progress` key + path. + */ extern NSString * const MGLOfflinePackProgressChangedNotification; + +/** + Posted by the shared `MGLOfflineStorage` object whenever an `MGLOfflinePack` + object encounters an error while downloading. The error may be recoverable and + may not warrant the user’s attention. For example, the pack’s implementation + may attempt to re-request failed resources based on an exponential backoff + strategy or upon the restoration of network access. + + The `object` is the `MGLOfflinePack` object that encountered the error. The + `userInfo` dictionary contains the error object in the + `MGLOfflinePackErrorUserInfoKey` key. + */ extern NSString * const MGLOfflinePackErrorNotification; + +/** + Posted by the shared `MGLOfflineStorage` object when the maximum number of + Mapbox-hosted tiles has been downloaded and stored on the current device. + + The `object` is the `MGLOfflinePack` object that reached the tile limit in the + course of downloading. The `userInfo` dictionary contains the tile limit in the + `MGLOfflinePackMaximumCountUserInfoKey` key. + + Once this limit is reached, no instance of `MGLOfflinePack` can download + additional tiles from Mapbox APIs until already downloaded tiles are removed by + calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method. + Contact your Mapbox sales representative to have the limit raised. + */ extern NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification; +/** + The key for an `NSError` object that is encountered in the course of + downloading an offline pack. The error’s domain is `MGLErrorDomain`. See + `MGLErrorCode` for possible error codes. + */ extern NSString * const MGLOfflinePackErrorUserInfoKey; + +/** + The key for an `NSNumber` object that indicates the maximum number of + Mapbox-hosted tiles that may be downloaded and stored on the current device. + Call `-unsignedLongLongValue` on the object to receive the `uint64_t`-typed + tile limit. + */ extern NSString * const MGLOfflinePackMaximumCountUserInfoKey; /** A block to be called once an offline pack has been completely created and added. + An application typically calls the `-resume` method on the pack inside this + completion handler to begin the download. + @param pack Contains a pointer to the newly added pack, or `nil` if there was an error creating or adding the pack. @param error Contains a pointer to an error object (if any) indicating why the - pack could not be created or added. For a list of possible error codes, see - `MGLErrorCode`. + pack could not be created or added. */ typedef void (^MGLOfflinePackAdditionCompletionHandler)(MGLOfflinePack * _Nullable pack, NSError * _Nullable error); @@ -30,6 +84,10 @@ typedef void (^MGLOfflinePackAdditionCompletionHandler)(MGLOfflinePack * _Nullab A block to be called once an offline pack has been completely invalidated and removed. + Avoid any references to the pack inside this completion handler: by the time + this completion handler is executed, the pack has become invalid, and any + messages passed to it will raise an exception. + @param error Contains a pointer to an error object (if any) indicating why the pack could not be invalidated or removed. */ @@ -38,7 +96,8 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error /** MGLOfflineStorage implements a singleton (shared object) that manages offline packs. All of this class’s instance methods are asynchronous, reflecting the - fact that offline resources are stored in a database. + fact that offline resources are stored in a database. The shared object + maintains a canonical collection of offline packs in its `packs` property. */ @interface MGLOfflineStorage : NSObject @@ -48,24 +107,35 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error + (instancetype)sharedOfflineStorage; /** - An array of all known offline packs. + An array of all known offline packs, in the order in which they were created. This property is set to `nil`, indicating that the receiver does not yet know the existing packs, for an undefined amount of time starting from the moment the shared offline storage object is initialized until the packs are fetched from the database. After that point, this property is always non-nil, but it may be empty to indicate that no packs are present. + + To detect when the shared offline storage object has finished loading its + `packs` property, observe KVO change notifications on the `packs` key path. + The initial load results in an `NSKeyValueChangeSetting` change. */ -@property (nonatomic, copy, readonly, nullable) NS_ARRAY_OF(MGLOfflinePack *) *packs; +@property (nonatomic, strong, readonly, nullable) NS_ARRAY_OF(MGLOfflinePack *) *packs; /** Creates and registers an offline pack that downloads the resources needed to use the given region offline. - The resulting pack starts out with a state of `MGLOfflinePackStateInactive`. To - begin downloading resources, call `-[MGLOfflinePack resume]`. To monitor - download progress, set the pack’s `delegate` property to an object that - conforms to the `MGLOfflinePackDelegate` protocol. + The resulting pack is added to the shared offline storage object’s `packs` + property, then the `completion` block is executed with that pack passed in. + + The pack has an initial state of `MGLOfflinePackStateInactive`. To begin + downloading resources, call `-[MGLOfflinePack resume]` on the pack from within + the completion handler. To monitor download progress, add an observer for + `MGLOfflinePackProgressChangedNotification`s about that pack. + + To detect when any call to this method results in a new pack, observe KVO + change notifications on the shared offline storage object’s `packs` key path. + Additions to that array result in an `NSKeyValueChangeInsertion` change. @param region A region to download. @param context Arbitrary data to store alongside the downloaded resources. @@ -81,8 +151,12 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error As soon as this method is called on a pack, the pack becomes invalid; any attempt to send it a message will result in an exception being thrown. If an error occurs and the pack cannot be removed, do not attempt to reuse the pack - object. Instead, use the `-getPacksWithCompletionHandler:` method to obtain a - valid pointer to the pack object. + object. Instead, if you need continued access to the pack, suspend all packs + and use the `-reloadPacks` method to obtain valid pointers to all the packs. + + To detect when any call to this method results in a pack being removed, observe + KVO change notifications on the shared offline storage object’s `packs` key + path. Removals from that array result in an `NSKeyValueChangeRemoval` change. @param pack The offline pack to remove. @param completion The completion handler to call once the pack has been @@ -90,14 +164,29 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error */ - (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(nullable MGLOfflinePackRemovalCompletionHandler)completion; +/** + Forcibly, asynchronously reloads the `packs` property. At some point after this + method is called, the pointer values of the `MGLOfflinePack` objects in the + `packs` property change, even if the underlying data for these packs has not + changed. If this method is called while a pack is actively downloading, the + behavior is undefined. + + You typically do not need to call this method. + + To detect when the shared offline storage object has finished reloading its + `packs` property, observe KVO change notifications on the `packs` key path. + A reload results in an `NSKeyValueChangeSetting` change. + */ +- (void)reloadPacks; + /** Sets the maximum number of Mapbox-hosted tiles that may be downloaded and stored on the current device. - Once this limit is reached, - `-[MGLOfflinePackDelegate offlinePack:didReceiveMaximumAllowedMapboxTiles:]` is - called on every delegate of `MGLOfflinePack` until already downloaded tiles are - removed by calling the `-removePack:withCompletionHandler:` method. + Once this limit is reached, an + `MGLOfflinePackMaximumMapboxTilesReachedNotification` is posted for every + attempt to download additional tiles until already downloaded tiles are removed + by calling the `-removePack:withCompletionHandler:` method. @note The [Mapbox Terms of Service](https://www.mapbox.com/tos/) prohibits changing or bypassing this limit without permission from Mapbox. Contact diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 42bd871e5..279261e9b 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -38,6 +38,7 @@ private: @interface MGLOfflinePack () +@property (nonatomic, weak, nullable) id delegate; @property (nonatomic, nullable, readwrite) mbgl::OfflineRegion *mbglOfflineRegion; @property (nonatomic, readwrite) MGLOfflinePackState state; @property (nonatomic, readwrite) MGLOfflinePackProgress progress; @@ -66,10 +67,7 @@ private: } - (void)dealloc { - if (_mbglOfflineRegion && _state != MGLOfflinePackStateInvalid) { - mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, nullptr); - } + NSAssert(_state == MGLOfflinePackStateInvalid, @"MGLOfflinePack was not invalided prior to deallocation."); } - (id )region { @@ -105,6 +103,8 @@ private: NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot invalidate an already invalid offline pack."); self.state = MGLOfflinePackStateInvalid; + mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; + mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr); self.mbglOfflineRegion = nil; } @@ -159,9 +159,7 @@ private: progress.maximumResourcesExpected = status.requiredResourceCountIsPrecise ? status.requiredResourceCount : UINT64_MAX; self.progress = progress; - if ([self.delegate respondsToSelector:@selector(offlinePack:progressDidChange:)]) { - [self.delegate offlinePack:self progressDidChange:progress]; - } + [self.delegate offlinePack:self progressDidChange:progress]; } NSError *MGLErrorFromResponseError(mbgl::Response::Error error) { @@ -187,6 +185,8 @@ NSError *MGLErrorFromResponseError(mbgl::Response::Error error) { }]; } +@end + void MBGLOfflineRegionObserver::statusChanged(mbgl::OfflineRegionStatus status) { dispatch_async(dispatch_get_main_queue(), ^{ [pack offlineRegionStatusDidChange:status]; @@ -195,18 +195,12 @@ void MBGLOfflineRegionObserver::statusChanged(mbgl::OfflineRegionStatus status) void MBGLOfflineRegionObserver::responseError(mbgl::Response::Error error) { dispatch_async(dispatch_get_main_queue(), ^{ - if ([pack.delegate respondsToSelector:@selector(offlinePack:didReceiveError:)]) { - [pack.delegate offlinePack:pack didReceiveError:MGLErrorFromResponseError(error)]; - } + [pack.delegate offlinePack:pack didReceiveError:MGLErrorFromResponseError(error)]; }); } void MBGLOfflineRegionObserver::mapboxTileCountLimitExceeded(uint64_t limit) { dispatch_async(dispatch_get_main_queue(), ^{ - if ([pack.delegate respondsToSelector:@selector(offlinePack:didReceiveMaximumAllowedMapboxTiles:)]) { - [pack.delegate offlinePack:pack didReceiveMaximumAllowedMapboxTiles:limit]; - } + [pack.delegate offlinePack:pack didReceiveMaximumAllowedMapboxTiles:limit]; }); } - -@end diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index c1637ab4a..4a121af8a 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -4,8 +4,19 @@ NS_ASSUME_NONNULL_BEGIN +@protocol MGLOfflinePackDelegate; + @interface MGLOfflinePack (Private) +/** + The pack’s delegate. + + You can use the offline pack delegate to be notified of any changes in the + pack’s progress and of any errors while downloading. For more information, see + the `MGLOfflinePackDelegate` documentation. + */ +@property (nonatomic, weak, nullable) id delegate; + @property (nonatomic, nullable) mbgl::OfflineRegion *mbglOfflineRegion; - (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region; @@ -28,4 +39,47 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + The `MGLOfflinePackDelegate` protocol defines methods that a delegate of an + `MGLOfflinePack` object can optionally implement to be notified of any changes + in the pack’s download progress and of any errors while downloading. + */ +@protocol MGLOfflinePackDelegate + +/** + Sent whenever the pack’s state or download progress changes. Every change to a + field in the `progress` property corresponds to an invocation of this method. + + @param pack The pack whose state of progress changed. + @param progress The updated progress. To get the updated state, refer to the + `state` property. + */ +- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(MGLOfflinePackProgress)progress; + +/** + Sent whenever the pack encounters an error while downloading. + + Download errors may be recoverable. For example, this pack’s implementation may + attempt to re-request failed resources based on an exponential backoff + strategy or upon the restoration of network access. + + @param pack The pack that encountered an error. + @param error A download error. For a list of possible error codes, see + `MGLErrorCode`. + */ +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error; + +/** + Sent when the maximum number of Mapbox-hosted tiles has been downloaded and + stored on the current device. + + Once this limit is reached, no instance of `MGLOfflinePack` can download + additional tiles from Mapbox APIs until already downloaded tiles are removed by + calling the `-[MGLOfflineStorage removePack:withCompletionHandler:]` method. + Contact your Mapbox sales representative to have the limit raised. + */ +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 2add5e105..4e69ba211 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -18,19 +18,9 @@ NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOffl NSString * const MGLOfflinePackErrorUserInfoKey = @"Error"; NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; -/** - A block to be called with a complete list of offline packs. - - @param pack Contains a pointer an array of packs, or `nil` if there was an - error obtaining the packs. - @param error Contains a pointer to an error object (if any) indicating why the - list of packs could not be obtained. - */ -typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError * _Nullable error); - @interface MGLOfflineStorage () -@property (nonatomic, copy, readwrite) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *packs; +@property (nonatomic, strong, readwrite) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *packs; @property (nonatomic) mbgl::DefaultFileSource *mbglFileSource; @end @@ -42,14 +32,7 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac static MGLOfflineStorage *sharedOfflineStorage; dispatch_once(&onceToken, ^{ sharedOfflineStorage = [[self alloc] init]; - [sharedOfflineStorage getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, __unused NSError *error) { - sharedOfflineStorage.packs = [packs mutableCopy]; - - for (MGLOfflinePack *pack in packs) { - pack.delegate = sharedOfflineStorage; - [pack requestProgress]; - } - }]; + [sharedOfflineStorage reloadPacks]; }); return sharedOfflineStorage; } @@ -121,12 +104,14 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac - (void)dealloc { [[MGLAccountManager sharedManager] removeObserver:self forKeyPath:@"accessToken"]; + for (MGLOfflinePack *pack in self.packs) { + [pack invalidate]; + } + delete _mbglFileSource; _mbglFileSource = nullptr; } -#pragma mark KVO methods - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NS_DICTIONARY_OF(NSString *, id) *)change context:(void *)context { // Synchronize the file source’s access token with the global one in MGLAccountManager. if ([keyPath isEqualToString:@"accessToken"] && object == [MGLAccountManager sharedManager]) { @@ -139,29 +124,13 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac } } -- (void)insertPacks:(NSArray *)packs atIndexes:(NSIndexSet *)indices { - [(NSMutableArray *)self.packs insertObjects:packs atIndexes:indices]; -} - -- (void)addPacksObject:(MGLOfflinePack *)pack { - [(NSMutableArray *)self.packs addObject:pack]; -} - -- (void)removePacksAtIndexes:(NSIndexSet *)indices { - [(NSMutableArray *)self.packs removeObjectsAtIndexes:indices]; -} - -- (void)removePacksObject:(MGLOfflinePack *)pack { - [(NSMutableArray *)self.packs removeObject:pack]; -} - #pragma mark Pack management methods - (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion { __weak MGLOfflineStorage *weakSelf = self; [self _addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable pack, NSError * _Nullable error) { MGLOfflineStorage *strongSelf = weakSelf; - [strongSelf addPacksObject:pack]; + [[strongSelf mutableArrayValueForKey:@"packs"] addObject:pack]; pack.delegate = strongSelf; [pack requestProgress]; if (completion) { @@ -198,7 +167,7 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac } - (void)removePack:(MGLOfflinePack *)pack withCompletionHandler:(MGLOfflinePackRemovalCompletionHandler)completion { - [self removePacksObject:pack]; + [[self mutableArrayValueForKey:@"packs"] removeObject:pack]; [self _removePack:pack withCompletionHandler:^(NSError * _Nullable error) { if (completion) { completion(error); @@ -224,7 +193,18 @@ typedef void (^MGLOfflinePackListingCompletionHandler)(NS_ARRAY_OF(MGLOfflinePac }); } -- (void)getPacksWithCompletionHandler:(MGLOfflinePackListingCompletionHandler)completion { +- (void)reloadPacks { + [self getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, __unused NSError * _Nullable error) { + self.packs = [packs mutableCopy]; + + for (MGLOfflinePack *pack in packs) { + pack.delegate = self; + [pack requestProgress]; + } + }]; +} + +- (void)getPacksWithCompletionHandler:(void (^)(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError * _Nullable error))completion { self.mbglFileSource->listOfflineRegions([&, completion](std::exception_ptr exception, mbgl::optional> regions) { NSError *error; if (exception) { diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index 4f399d3d4..f4a2917d6 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -28,9 +28,7 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac @end -@implementation MBXOfflinePacksTableViewController { - NSUInteger _untitledRegionCount; -} +@implementation MBXOfflinePacksTableViewController - (void)viewDidLoad { [super viewDidLoad]; @@ -81,16 +79,19 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac - (IBAction)addCurrentRegion:(id)sender { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Add Offline Pack" message:@"Choose a name for the pack:" preferredStyle:UIAlertControllerStyleAlert]; - [alertController addTextFieldWithConfigurationHandler:nil]; + [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { + textField.placeholder = [NSString stringWithFormat:@"%@", MGLStringFromCoordinateBounds(self.mapView.visibleCoordinateBounds)]; + }]; [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; UIAlertAction *downloadAction = [UIAlertAction actionWithTitle:@"Download" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { MGLMapView *mapView = self.mapView; NSAssert(mapView, @"No map view to get the current region from."); - NSString *name = alertController.textFields.firstObject.text; + UITextField *nameField = alertController.textFields.firstObject; + NSString *name = nameField.text; if (!name.length) { - name = [NSString stringWithFormat:@"Untitled %lu", (unsigned long)++_untitledRegionCount]; + name = nameField.placeholder; } MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:mapView.styleURL bounds:mapView.visibleCoordinateBounds fromZoomLevel:mapView.zoomLevel toZoomLevel:mapView.maximumZoomLevel]; @@ -98,14 +99,14 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac MBXOfflinePackContextNameKey: name, }]; - __weak MBXOfflinePacksTableViewController *weakSelf = self; [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack *pack, NSError *error) { - MBXOfflinePacksTableViewController *strongSelf = weakSelf; if (error) { NSString *message = [NSString stringWithFormat:@"Mapbox GL was unable to add the offline pack “%@”.", name]; UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Can’t Add Offline Pack" message:message preferredStyle:UIAlertControllerStyleAlert]; [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; [self presentViewController:alertController animated:YES completion:nil]; + } else { + [pack resume]; } }]; }]; @@ -128,6 +129,12 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac NSString *reuseIdentifier = pack.state == MGLOfflinePackStateActive ? MBXOfflinePacksTableViewActiveCellReuseIdentifier : MBXOfflinePacksTableViewInactiveCellReuseIdentifier; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; + [self updateTableViewCell:cell atIndexPath:indexPath forPack:pack]; + + return cell; +} + +- (void)updateTableViewCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath forPack:(MGLOfflinePack *)pack { cell.textLabel.text = pack.name; MGLOfflinePackProgress progress = pack.progress; NSString *completedString = [NSNumberFormatter localizedStringFromNumber:@(progress.countOfResourcesCompleted) @@ -169,8 +176,6 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac break; } cell.detailTextLabel.text = statusString; - - return cell; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { @@ -199,12 +204,10 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac case MGLOfflinePackStateInactive: [pack resume]; - [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; break; case MGLOfflinePackStateActive: [pack suspend]; - [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; break; case MGLOfflinePackStateInvalid: @@ -225,7 +228,8 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac } NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; - [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; + UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; + [self updateTableViewCell:cell atIndexPath:indexPath forPack:pack]; } - (void)offlinePackDidReceiveError:(NSNotification *)notification { From ec72faa7891a24795c9b040076de829642be043d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 14:12:37 -0700 Subject: [PATCH 084/104] [ios, osx] Invalidate packs upon reload --- platform/darwin/src/MGLOfflinePack_Private.h | 2 +- platform/darwin/src/MGLOfflineStorage.mm | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index 4a121af8a..0e9265540 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -33,7 +33,7 @@ NS_ASSUME_NONNULL_BEGIN /** Invalidates the pack and ensures that no future progress update can ever - revalidate it. + revalidate it. This method must be called before the pack is deallocated. */ - (void)invalidate; diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 4e69ba211..c4c57224d 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -195,6 +195,9 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; - (void)reloadPacks { [self getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, __unused NSError * _Nullable error) { + for (MGLOfflinePack *pack in self.packs) { + [pack invalidate]; + } self.packs = [packs mutableCopy]; for (MGLOfflinePack *pack in packs) { From e36f31c50302dc2194cc34fab7b89d9cef8c87a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 14:38:07 -0700 Subject: [PATCH 085/104] [ios, osx] Allow creating invalid offline packs Removed NS_UNAVAILABLE attribute from -[MGLOfflinePack init]. Packs initialized with this initializer are doomed to invalidity. Fixes #4421. --- platform/darwin/include/MGLOfflinePack.h | 6 ++++-- platform/darwin/src/MGLOfflinePack.mm | 12 ++++++------ platform/darwin/src/MGLOfflineStorage.mm | 5 +++++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/platform/darwin/include/MGLOfflinePack.h b/platform/darwin/include/MGLOfflinePack.h index 666e442d2..185bba038 100644 --- a/platform/darwin/include/MGLOfflinePack.h +++ b/platform/darwin/include/MGLOfflinePack.h @@ -83,6 +83,10 @@ typedef struct MGLOfflinePackProgress { /** An `MGLOfflinePack` represents a collection of resources necessary for viewing a region offline to a local database. + + To create an instance of `MGLOfflinePack`, use the + `+[MGLOfflineStorage addPackForRegion:withContext:completionHandler:]` method. + A pack created using `-[MGLOfflinePack init]` is immediately invalid. */ @interface MGLOfflinePack : NSObject @@ -123,8 +127,6 @@ typedef struct MGLOfflinePackProgress { */ @property (nonatomic, readonly) MGLOfflinePackProgress progress; -- (instancetype)init NS_UNAVAILABLE; - /** Resumes downloading if the pack is inactive. diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 279261e9b..30b268aaf 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -48,11 +48,11 @@ private: @implementation MGLOfflinePack - (instancetype)init { - [NSException raise:@"Method unavailable" - format: - @"-[MGLOfflinePack init] is unavailable. " - @"Use +[MGLOfflineStorage addPackForRegion:withContext:completionHandler:] instead."]; - return nil; + if (self = [super init]) { + _state = MGLOfflinePackStateInvalid; + NSLog(@"%s called; did you mean to call +[MGLOfflineStorage addPackForRegion:withContext:completionHandler:] instead?", __PRETTY_FUNCTION__); + } + return self; } - (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region { @@ -123,7 +123,7 @@ private: } - (void)requestProgress { - MGLAssertOfflinePackIsValid(); + NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot request progress from an invalid offline pack."); mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index c4c57224d..4555f0300 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -178,6 +178,11 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; - (void)_removePack:(MGLOfflinePack *)pack withCompletionHandler:(MGLOfflinePackRemovalCompletionHandler)completion { mbgl::OfflineRegion *mbglOfflineRegion = pack.mbglOfflineRegion; [pack invalidate]; + if (!mbglOfflineRegion) { + completion(nil); + return; + } + self.mbglFileSource->deleteOfflineRegion(std::move(*mbglOfflineRegion), [&, completion](std::exception_ptr exception) { NSError *error; if (exception) { From ad3bbd9c111f5913a9c69e642319c4a8bdb7d2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 15:07:26 -0700 Subject: [PATCH 086/104] [ios, osx] Clarified documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated MGLTilePyramidOfflineRegion documentation to note that local files can’t be used as style URLs. Added documentation for private offline methods. --- .../darwin/include/MGLTilePyramidOfflineRegion.h | 13 +++++++------ platform/darwin/src/MGLOfflineRegion_Private.h | 11 +++++++++++ platform/darwin/src/MGLOfflineStorage_Private.h | 3 +++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/platform/darwin/include/MGLTilePyramidOfflineRegion.h b/platform/darwin/include/MGLTilePyramidOfflineRegion.h index 89920adcc..886464587 100644 --- a/platform/darwin/include/MGLTilePyramidOfflineRegion.h +++ b/platform/darwin/include/MGLTilePyramidOfflineRegion.h @@ -17,9 +17,8 @@ NS_ASSUME_NONNULL_BEGIN In addition to the JSON stylesheet, different styles may require different font glyphs, sprite sheets, and other resources. - The URL may be a full HTTP or HTTPS URL, a Mapbox URL indicating the style’s - map ID (`mapbox://styles/{user}/{style}`), or a path to a local file - relative to the application’s resource path. + The URL may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s + map ID (`mapbox://styles/{user}/{style}`). */ @property (nonatomic, readonly) NSURL *styleURL; @@ -52,9 +51,11 @@ NS_ASSUME_NONNULL_BEGIN This is the designated initializer for `MGLTilePyramidOfflineRegion`. @param styleURL URL of the map style for which to download resources. The URL - may be a full HTTP or HTTPS URL, a Mapbox URL indicating the style’s map ID - (`mapbox://styles/{user}/{style}`), or a path to a local file relative to - the application’s resource path. Specify `nil` for the default style. + may be a full HTTP or HTTPS URL or a Mapbox URL indicating the style’s map + ID (`mapbox://styles/{user}/{style}`). Specify `nil` for the default style. + Relative file URLs cannot be used as offline style URLs. To download the + online resources required by a local style, specify a URL to an online copy + of the style. @param bounds The coordinate bounds for the geographic region to be covered by the downloaded tiles. @param minimumZoomLevel The minimum zoom level to be covered by the downloaded diff --git a/platform/darwin/src/MGLOfflineRegion_Private.h b/platform/darwin/src/MGLOfflineRegion_Private.h index 41cd5843f..22106987d 100644 --- a/platform/darwin/src/MGLOfflineRegion_Private.h +++ b/platform/darwin/src/MGLOfflineRegion_Private.h @@ -8,8 +8,19 @@ NS_ASSUME_NONNULL_BEGIN @protocol MGLOfflineRegion_Private +/** + Initializes and returns an offline region backed by the given C++ region + definition object. + + @param definition A reference to an offline region definition backing the + offline region. + */ - (instancetype)initWithOfflineRegionDefinition:(const mbgl::OfflineRegionDefinition &)definition; +/** + Creates and returns a C++ offline region definition corresponding to the + receiver. + */ - (const mbgl::OfflineRegionDefinition)offlineRegionDefinition; @end diff --git a/platform/darwin/src/MGLOfflineStorage_Private.h b/platform/darwin/src/MGLOfflineStorage_Private.h index 05c3188bd..7c7b80dc4 100644 --- a/platform/darwin/src/MGLOfflineStorage_Private.h +++ b/platform/darwin/src/MGLOfflineStorage_Private.h @@ -8,6 +8,9 @@ NS_ASSUME_NONNULL_BEGIN @interface MGLOfflineStorage (Private) +/** + The shared file source object owned by the shared offline storage object. + */ @property (nonatomic) mbgl::DefaultFileSource *mbglFileSource; @end From f02bdb8fbba25a0db0042dbbf69e0ab529ac3224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 21:10:06 -0700 Subject: [PATCH 087/104] [osx] Fixed build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed an incomplete variable renaming. Don’t bother creating intermediate directories to the legacy cache path. When the main bundle lacks a bundle identifier, as is the case when the SDK runs in the test bundle, fall back on the SDK’s bundle. --- platform/darwin/src/MGLOfflineStorage.mm | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 4555f0300..619e4ce1a 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -48,8 +48,12 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; appropriateForURL:nil create:YES error:nil]; - cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent: - [NSBundle mainBundle].bundleIdentifier]; + NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier; + if (!bundleIdentifier) { + // There’s no main bundle identifier when running in a unit test bundle. + bundleIdentifier = [NSBundle bundleForClass:[self class]].bundleIdentifier; + } + cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier]; [[NSFileManager defaultManager] createDirectoryAtURL:cacheDirectoryURL withIntermediateDirectories:YES attributes:nil @@ -74,15 +78,10 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; NSURL *legacyCacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSCachesDirectory inDomain:NSUserDomainMask appropriateForURL:nil - create:YES + create:NO error:nil]; - legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent: - [NSBundle mainBundle].bundleIdentifier]; - [[NSFileManager defaultManager] createDirectoryAtURL:legacyCacheDirectoryURL - withIntermediateDirectories:YES - attributes:nil - error:nil]; - NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageLegacyFileName]; + legacyCacheDirectoryURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier]; + NSURL *legacyCacheURL = [legacyCacheDirectoryURL URLByAppendingPathComponent:MGLOfflineStorageFileName3_2_0_beta_1]; NSString *legacyCachePath = legacyCacheURL ? legacyCacheURL.path : @""; #endif if (![[NSFileManager defaultManager] fileExistsAtPath:cachePath]) { From 4fd875a971db970b2868e2c37a7a3432cc961d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 21:12:18 -0700 Subject: [PATCH 088/104] [ios, osx] Secure coding, copying for offline regions Implemented NSSecureCoding and NSCopying protocols for MGLTilePyramidOfflineRegion so that it can be used more fluidly by client code. --- .../include/MGLTilePyramidOfflineRegion.h | 2 +- .../darwin/src/MGLTilePyramidOfflineRegion.mm | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/platform/darwin/include/MGLTilePyramidOfflineRegion.h b/platform/darwin/include/MGLTilePyramidOfflineRegion.h index 886464587..4e9f394e7 100644 --- a/platform/darwin/include/MGLTilePyramidOfflineRegion.h +++ b/platform/darwin/include/MGLTilePyramidOfflineRegion.h @@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN An offline region defined by a style URL, geographic coordinate bounds, and range of zoom levels. */ -@interface MGLTilePyramidOfflineRegion : NSObject +@interface MGLTilePyramidOfflineRegion : NSObject /** URL of the style whose resources are required for offline viewing. diff --git a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm index 6507ceef7..d1151de09 100644 --- a/platform/darwin/src/MGLTilePyramidOfflineRegion.mm +++ b/platform/darwin/src/MGLTilePyramidOfflineRegion.mm @@ -18,6 +18,10 @@ @synthesize styleURL = _styleURL; ++ (BOOL)supportsSecureCoding { + return YES; +} + - (instancetype)init { [NSException raise:@"Method unavailable" format: @@ -67,4 +71,54 @@ scaleFactor); } +- (nullable instancetype)initWithCoder:(NSCoder *)coder { + NSURL *styleURL = [coder decodeObjectForKey:@"styleURL"]; + CLLocationCoordinate2D sw = CLLocationCoordinate2DMake([coder decodeDoubleForKey:@"southWestLatitude"], + [coder decodeDoubleForKey:@"southWestLongitude"]); + CLLocationCoordinate2D ne = CLLocationCoordinate2DMake([coder decodeDoubleForKey:@"northEastLatitude"], + [coder decodeDoubleForKey:@"northEastLongitude"]); + MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(sw, ne); + double minimumZoomLevel = [coder decodeDoubleForKey:@"minimumZoomLevel"]; + double maximumZoomLevel = [coder decodeDoubleForKey:@"maximumZoomLevel"]; + + return [self initWithStyleURL:styleURL bounds:bounds fromZoomLevel:minimumZoomLevel toZoomLevel:maximumZoomLevel]; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [coder encodeObject:_styleURL forKey:@"styleURL"]; + [coder encodeDouble:_bounds.sw.latitude forKey:@"southWestLatitude"]; + [coder encodeDouble:_bounds.sw.longitude forKey:@"southWestLongitude"]; + [coder encodeDouble:_bounds.ne.latitude forKey:@"northEastLatitude"]; + [coder encodeDouble:_bounds.ne.longitude forKey:@"northEastLongitude"]; + [coder encodeDouble:_maximumZoomLevel forKey:@"maximumZoomLevel"]; + [coder encodeDouble:_minimumZoomLevel forKey:@"minimumZoomLevel"]; +} + +- (id)copyWithZone:(nullable NSZone *)zone { + return [[[self class] allocWithZone:zone] initWithStyleURL:_styleURL bounds:_bounds fromZoomLevel:_minimumZoomLevel toZoomLevel:_maximumZoomLevel]; +} + +- (BOOL)isEqual:(id)other { + if (other == self) { + return YES; + } + if (![other isKindOfClass:[self class]]) { + return NO; + } + + MGLTilePyramidOfflineRegion *otherRegion = other; + return (_minimumZoomLevel == otherRegion->_minimumZoomLevel + && _maximumZoomLevel == otherRegion->_maximumZoomLevel + && MGLCoordinateBoundsEqualToCoordinateBounds(_bounds, otherRegion->_bounds) + && [_styleURL isEqual:otherRegion->_styleURL]); +} + +- (NSUInteger)hash { + return (_styleURL.hash + + @(_bounds.sw.latitude).hash + @(_bounds.sw.longitude).hash + + @(_bounds.ne.latitude).hash + @(_bounds.ne.longitude).hash + + @(_minimumZoomLevel).hash + @(_maximumZoomLevel).hash); +} + @end From b248e43112f24c3570a7df5a9dd4096c353b6f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 21:13:42 -0700 Subject: [PATCH 089/104] [osx] Offline unit tests Added unit tests for MGLTilePyramidOfflineRegion, MGLOfflinePack, and MGLOfflineStorage. Fixes #4426. --- platform/osx/test/MGLOfflinePackTests.m | 25 +++++ platform/osx/test/MGLOfflineRegionTests.m | 35 +++++++ platform/osx/test/MGLOfflineStorageTests.m | 113 +++++++++++++++++++++ platform/osx/test/osxtest.gypi | 3 + 4 files changed, 176 insertions(+) create mode 100644 platform/osx/test/MGLOfflinePackTests.m create mode 100644 platform/osx/test/MGLOfflineRegionTests.m create mode 100644 platform/osx/test/MGLOfflineStorageTests.m diff --git a/platform/osx/test/MGLOfflinePackTests.m b/platform/osx/test/MGLOfflinePackTests.m new file mode 100644 index 000000000..c33a72cc0 --- /dev/null +++ b/platform/osx/test/MGLOfflinePackTests.m @@ -0,0 +1,25 @@ +#import + +#pragma clang diagnostic ignored "-Wgnu-statement-expression" +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" + +#import + +@interface MGLOfflinePackTests : XCTestCase + +@end + +@implementation MGLOfflinePackTests + +- (void)testInvalidation { + MGLOfflinePack *invalidPack = [[MGLOfflinePack alloc] init]; + + XCTAssertEqual(invalidPack.state, MGLOfflinePackStateInvalid, @"Offline pack should be invalid when initialized independently of MGLOfflineStorage."); + + XCTAssertThrowsSpecificNamed(invalidPack.region, NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when accessing its region."); + XCTAssertThrowsSpecificNamed(invalidPack.context, NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when accessing its context."); + XCTAssertThrowsSpecificNamed([invalidPack resume], NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when being resumed."); + XCTAssertThrowsSpecificNamed([invalidPack suspend], NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when being suspended."); +} + +@end diff --git a/platform/osx/test/MGLOfflineRegionTests.m b/platform/osx/test/MGLOfflineRegionTests.m new file mode 100644 index 000000000..63befdf14 --- /dev/null +++ b/platform/osx/test/MGLOfflineRegionTests.m @@ -0,0 +1,35 @@ +#import + +#pragma clang diagnostic ignored "-Wgnu-statement-expression" +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" + +#import + +@interface MGLOfflineRegionTests : XCTestCase + +@end + +@implementation MGLOfflineRegionTests + +- (void)testStyleURLs { + MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(kCLLocationCoordinate2DInvalid, kCLLocationCoordinate2DInvalid); + MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:nil bounds:bounds fromZoomLevel:0 toZoomLevel:DBL_MAX]; + XCTAssertEqualObjects(region.styleURL, [MGLStyle streetsStyleURL], @"Streets isn’t the default style."); + + NSURL *localURL = [NSURL URLWithString:@"beautiful.style"]; + XCTAssertThrowsSpecificNamed([[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:localURL bounds:bounds fromZoomLevel:0 toZoomLevel:DBL_MAX], NSException, @"Invalid style URL", @"No exception raised when initializing region with a local file URL as the style URL."); +} + +- (void)testEquality { + MGLCoordinateBounds bounds = MGLCoordinateBoundsMake(kCLLocationCoordinate2DInvalid, kCLLocationCoordinate2DInvalid); + MGLTilePyramidOfflineRegion *original = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:[MGLStyle lightStyleURL] bounds:bounds fromZoomLevel:5 toZoomLevel:10]; + MGLTilePyramidOfflineRegion *copy = [original copy]; + XCTAssertEqualObjects(original, copy, @"Tile pyramid region should be equal to its copy."); + + XCTAssertEqualObjects(original.styleURL, copy.styleURL, @"Style URL has changed."); + XCTAssert(MGLCoordinateBoundsEqualToCoordinateBounds(original.bounds, copy.bounds), @"Bounds have changed."); + XCTAssertEqual(original.minimumZoomLevel, original.minimumZoomLevel, @"Minimum zoom level has changed."); + XCTAssertEqual(original.maximumZoomLevel, original.maximumZoomLevel, @"Maximum zoom level has changed."); +} + +@end diff --git a/platform/osx/test/MGLOfflineStorageTests.m b/platform/osx/test/MGLOfflineStorageTests.m new file mode 100644 index 000000000..ff738f923 --- /dev/null +++ b/platform/osx/test/MGLOfflineStorageTests.m @@ -0,0 +1,113 @@ +#import + +#pragma clang diagnostic ignored "-Wgnu-statement-expression" +#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments" + +#import + +@interface MGLOfflineStorageTests : XCTestCase + +@end + +@implementation MGLOfflineStorageTests + +- (void)testSharedObject { + XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage], [MGLOfflineStorage sharedOfflineStorage], @"There should only be one shared offline storage object."); +} + +// This test needs to come first so it can test the initial loading of packs. +- (void)testAAALoadPacks { + XCTestExpectation *kvoExpectation = [self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { + NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; + return changeKind = NSKeyValueChangeSetting; + }]; + + [self waitForExpectationsWithTimeout:1 handler:nil]; + + XCTAssertNotNil([MGLOfflineStorage sharedOfflineStorage].packs, @"Shared offline storage object should have a non-nil collection of packs by this point."); +} + +- (void)testAddPack { + NSUInteger countOfPacks = [MGLOfflineStorage sharedOfflineStorage].packs.count; + + NSURL *styleURL = [MGLStyle lightStyleURL]; + /// Somewhere near Grape Grove, Ohio, United States. + MGLCoordinateBounds bounds = { + { 39.70358155855172, -83.69506472545841 }, + { 39.703818870225376, -83.69420641857361 }, + }; + double zoomLevel = 20; + MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:styleURL bounds:bounds fromZoomLevel:zoomLevel toZoomLevel:zoomLevel]; + + NSString *nameKey = @"Name"; + NSString *name = @"🍇 Grape Grove"; + + NSData *context = [NSKeyedArchiver archivedDataWithRootObject:@{ + nameKey: name, + }]; + + __block MGLOfflinePack *pack; + [self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { + NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; + NSIndexSet *indices = change[NSKeyValueChangeIndexesKey]; + return changeKind == NSKeyValueChangeInsertion && indices.count == 1; + }]; + XCTestExpectation *additionCompletionHandlerExpectation = [self expectationWithDescription:@"add pack completion handler"]; + [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable completionHandlerPack, NSError * _Nullable error) { + XCTAssertNotNil(completionHandlerPack, @"Added pack should exist."); + XCTAssertEqual(completionHandlerPack.state, MGLOfflinePackStateUnknown, @"Pack should initially have unknown state."); + pack = completionHandlerPack; + [additionCompletionHandlerExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + + XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage].packs.count, countOfPacks + 1, @"Added pack should have been added to the canonical collection of packs owned by the shared offline storage object. This assertion can fail if this test is run before -testAAALoadPacks."); + + XCTAssertEqual(pack, [MGLOfflineStorage sharedOfflineStorage].packs.lastObject, @"Pack should be appended to end of packs array."); + + XCTAssertEqualObjects(pack.region, region, @"Added pack’s region has changed."); + + NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:pack.context]; + XCTAssert([userInfo isKindOfClass:[NSDictionary class]], @"Context of offline pack isn’t a dictionary."); + XCTAssert([userInfo[nameKey] isKindOfClass:[NSString class]], @"Name of offline pack isn’t a string."); + XCTAssertEqualObjects(userInfo[nameKey], name, @"Name of offline pack has changed."); + + XCTAssertEqual(pack.state, MGLOfflinePackStateUnknown, @"Pack should initially have unknown state."); + + [self keyValueObservingExpectationForObject:pack keyPath:@"state" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { + NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; + MGLOfflinePackState state = [change[NSKeyValueChangeNewKey] integerValue]; + return changeKind == NSKeyValueChangeSetting && state == MGLOfflinePackStateInactive; + }]; + [self expectationForNotification:MGLOfflinePackProgressChangedNotification object:pack handler:^BOOL(NSNotification * _Nonnull notification) { + MGLOfflinePack *notificationPack = notification.object; + XCTAssert([notificationPack isKindOfClass:[MGLOfflinePack class]], @"Object of notification should be an MGLOfflinePack."); + return notificationPack == pack && pack.state == MGLOfflinePackStateInactive; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; +} + +- (void)testRemovePack { + NSUInteger countOfPacks = [MGLOfflineStorage sharedOfflineStorage].packs.count; + + MGLOfflinePack *pack = [MGLOfflineStorage sharedOfflineStorage].packs.lastObject; + XCTAssertNotNil(pack, @"Added pack should still exist."); + + XCTestExpectation *kvoExpectation = [self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { + NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; + NSIndexSet *indices = change[NSKeyValueChangeIndexesKey]; + return changeKind = NSKeyValueChangeRemoval && indices.count == 1; + }]; + XCTestExpectation *completionHandlerExpectation = [self expectationWithDescription:@"remove pack completion handler"]; + [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError * _Nullable error) { + XCTAssertEqual(pack.state, MGLOfflinePackStateInvalid, @"Removed pack should be invalid in the completion handler."); + [completionHandlerExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + + XCTAssertEqual(pack.state, MGLOfflinePackStateInvalid, @"Removed pack should have been invalidated synchronously."); + + XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage].packs.count, countOfPacks - 1, @"Removed pack should have been removed from the canonical collection of packs owned by the shared offline storage object. This assertion can fail if this test is run before -testAAALoadPacks or -testAddPack."); +} + +@end diff --git a/platform/osx/test/osxtest.gypi b/platform/osx/test/osxtest.gypi index 30bced31c..6165b6fa8 100644 --- a/platform/osx/test/osxtest.gypi +++ b/platform/osx/test/osxtest.gypi @@ -44,6 +44,9 @@ 'sources': [ './MGLGeometryTests.mm', + './MGLOfflinePackTests.m', + './MGLOfflineRegionTests.m', + './MGLOfflineStorageTests.m', './MGLStyleTests.mm', ], From aff1196d02cd06e71c7b2a15454384fd302946b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 26 Mar 2016 21:31:48 -0700 Subject: [PATCH 090/104] [ios, osx] Updated jazzy categories --- .jazzy.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 3cf8a3041..853db0a4f 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -43,9 +43,12 @@ custom_categories: - MGLOfflineStorage - MGLOfflinePack - MGLOfflinePackAdditionCompletionHandler - - MGLOfflinePackDelegate - - MGLOfflinePackListingCompletionHandler + - MGLOfflinePackErrorNotification + - MGLOfflinePackErrorUserInfoKey + - MGLOfflinePackMaximumCountUserInfoKey + - MGLOfflinePackMaximumMapboxTilesReachedNotification - MGLOfflinePackProgress + - MGLOfflinePackProgressChangedNotification - MGLOfflinePackRemovalCompletionHandler - MGLOfflinePackState - MGLTilePyramidOfflineRegion From 8c8b0580388460c0addafb49c852ea8986b47ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sun, 27 Mar 2016 22:40:15 -0700 Subject: [PATCH 091/104] [ios, osx] Include progress in progress change notification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An MGLOfflinePackProgressChangedNotification notification now includes the pack’s state and progress values, which match the values in the corresponding MGLOfflinePack properties. Implemented NSValue category methods to store MGLOfflinePackProgress inside a dictionary. --- .jazzy.yaml | 3 ++ platform/darwin/include/MGLOfflinePack.h | 21 +++++++++++++ platform/darwin/include/MGLOfflineStorage.h | 35 +++++++++++++++++---- platform/darwin/src/MGLOfflinePack.mm | 14 +++++++++ platform/darwin/src/MGLOfflineStorage.mm | 7 ++++- platform/osx/test/MGLOfflinePackTests.m | 15 +++++++++ platform/osx/test/MGLOfflineStorageTests.m | 12 +++++++ 7 files changed, 100 insertions(+), 7 deletions(-) diff --git a/.jazzy.yaml b/.jazzy.yaml index 853db0a4f..602e8cdb0 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -49,9 +49,12 @@ custom_categories: - MGLOfflinePackMaximumMapboxTilesReachedNotification - MGLOfflinePackProgress - MGLOfflinePackProgressChangedNotification + - MGLOfflinePackProgressUserInfoKey - MGLOfflinePackRemovalCompletionHandler - MGLOfflinePackState + - MGLOfflinePackStateUserInfoKey - MGLTilePyramidOfflineRegion + - NSValue(MGLOfflinePackAdditions) - name: Geometry children: - MGLCoordinateBounds diff --git a/platform/darwin/include/MGLOfflinePack.h b/platform/darwin/include/MGLOfflinePack.h index 185bba038..b65fed384 100644 --- a/platform/darwin/include/MGLOfflinePack.h +++ b/platform/darwin/include/MGLOfflinePack.h @@ -161,4 +161,25 @@ typedef struct MGLOfflinePackProgress { @end +/** + Methods for round-tripping `MGLOfflinePackProgress` values. + */ +@interface NSValue (MGLOfflinePackAdditions) + +/** + Creates a new value object containing the given `MGLOfflinePackProgress` + structure. + + @param progress The value for the new object. + @return A new value object that contains the offline pack progress information. + */ ++ (NSValue *)valueWithMGLOfflinePackProgress:(MGLOfflinePackProgress)progress; + +/** + The `MGLOfflinePackProgress` structure representation of the value. + */ +@property (readonly) MGLOfflinePackProgress MGLOfflinePackProgressValue; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/include/MGLOfflineStorage.h b/platform/darwin/include/MGLOfflineStorage.h index f9ddba038..5544663d3 100644 --- a/platform/darwin/include/MGLOfflineStorage.h +++ b/platform/darwin/include/MGLOfflineStorage.h @@ -14,8 +14,11 @@ NS_ASSUME_NONNULL_BEGIN resources are required for offline viewing. This notification is posted whenever any field in the `progress` property changes. - The `object` is the `MGLOfflinePack` object whose progress changed. For details - about the pack’s current progress, use the pack’s `progress` property. + The `object` is the `MGLOfflinePack` object whose progress changed. The + `userInfo` dictionary contains the pack’s current state in the + `MGLOfflinePackStateUserInfoKey` key and details about the pack’s current + progress in the `MGLOfflinePackProgressUserInfoKey` key. You may also consult + the pack’s `state` and `progress` properties, which provide the same values. If you only need to observe changes in a particular pack’s progress, you can alternatively observe KVO change notifications to the pack’s `progress` key @@ -51,18 +54,38 @@ extern NSString * const MGLOfflinePackErrorNotification; */ extern NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification; +/** + The key for an `NSNumber` object that indicates an offline pack’s current + state. This key is used in the `userInfo` dictionary of an + `MGLOfflinePackProgressChangedNotification` notification. Call `-integerValue` + on the object to receive the `MGLOfflinePackState`-typed state. + */ +extern NSString * const MGLOfflinePackStateUserInfoKey; + +/** + The key for an `NSValue` object that indicates an offline pack’s current + progress. This key is used in the `userInfo` dictionary of an + `MGLOfflinePackProgressChangedNotification` notification. Call + `-MGLOfflinePackProgressValue` on the object to receive the + `MGLOfflinePackProgress`-typed progress. + */ +extern NSString * const MGLOfflinePackProgressUserInfoKey; + /** The key for an `NSError` object that is encountered in the course of - downloading an offline pack. The error’s domain is `MGLErrorDomain`. See - `MGLErrorCode` for possible error codes. + downloading an offline pack. This key is used in the `userInfo` dictionary of + an `MGLOfflinePackErrorNotification` notification. The error’s domain is + `MGLErrorDomain`. See `MGLErrorCode` for possible error codes. */ extern NSString * const MGLOfflinePackErrorUserInfoKey; /** The key for an `NSNumber` object that indicates the maximum number of Mapbox-hosted tiles that may be downloaded and stored on the current device. - Call `-unsignedLongLongValue` on the object to receive the `uint64_t`-typed - tile limit. + This key is used in the `userInfo` dictionary of an + `MGLOfflinePackMaximumMapboxTilesReachedNotification` notification. Call + `-unsignedLongLongValue` on the object to receive the `uint64_t`-typed tile + limit. */ extern NSString * const MGLOfflinePackMaximumCountUserInfoKey; diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 30b268aaf..05ff35ec7 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -204,3 +204,17 @@ void MBGLOfflineRegionObserver::mapboxTileCountLimitExceeded(uint64_t limit) { [pack.delegate offlinePack:pack didReceiveMaximumAllowedMapboxTiles:limit]; }); } + +@implementation NSValue (MGLOfflinePackAdditions) + ++ (NSValue *)valueWithMGLOfflinePackProgress:(MGLOfflinePackProgress)progress { + return [NSValue value:&progress withObjCType:@encode(MGLOfflinePackProgress)]; +} + +- (MGLOfflinePackProgress)MGLOfflinePackProgressValue { + MGLOfflinePackProgress progress; + [self getValue:&progress]; + return progress; +} + +@end diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 619e4ce1a..3d171ca20 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -15,6 +15,8 @@ NSString * const MGLOfflinePackProgressChangedNotification = @"MGLOfflinePackPro NSString * const MGLOfflinePackErrorNotification = @"MGLOfflinePackError"; NSString * const MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOfflinePackMaximumMapboxTilesReached"; +NSString * const MGLOfflinePackStateUserInfoKey = @"State"; +NSString * const MGLOfflinePackProgressUserInfoKey = @"Progress"; NSString * const MGLOfflinePackErrorUserInfoKey = @"Error"; NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; @@ -242,7 +244,10 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; #pragma mark MGLOfflinePackDelegate methods - (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(__unused MGLOfflinePackProgress)progress { - [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackProgressChangedNotification object:pack]; + [[NSNotificationCenter defaultCenter] postNotificationName:MGLOfflinePackProgressChangedNotification object:pack userInfo:@{ + MGLOfflinePackStateUserInfoKey: @(pack.state), + MGLOfflinePackProgressUserInfoKey: [NSValue valueWithMGLOfflinePackProgress:progress], + }]; } - (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error { diff --git a/platform/osx/test/MGLOfflinePackTests.m b/platform/osx/test/MGLOfflinePackTests.m index c33a72cc0..41262d16c 100644 --- a/platform/osx/test/MGLOfflinePackTests.m +++ b/platform/osx/test/MGLOfflinePackTests.m @@ -22,4 +22,19 @@ XCTAssertThrowsSpecificNamed([invalidPack suspend], NSException, @"Invalid offline pack", @"Invalid offline pack should raise an exception when being suspended."); } +- (void)testProgressBoxing { + MGLOfflinePackProgress progress = { + .countOfResourcesCompleted = 1, + .countOfResourcesExpected = 2, + .countOfBytesCompleted = 7, + .maximumResourcesExpected = UINT64_MAX, + }; + MGLOfflinePackProgress roundTrippedProgress = [NSValue valueWithMGLOfflinePackProgress:progress].MGLOfflinePackProgressValue; + + XCTAssertEqual(progress.countOfResourcesCompleted, roundTrippedProgress.countOfResourcesCompleted, @"Completed resources should round-trip."); + XCTAssertEqual(progress.countOfResourcesExpected, roundTrippedProgress.countOfResourcesExpected, @"Expected resources should round-trip."); + XCTAssertEqual(progress.countOfBytesCompleted, roundTrippedProgress.countOfBytesCompleted, @"Completed bytes should round-trip."); + XCTAssertEqual(progress.maximumResourcesExpected, roundTrippedProgress.maximumResourcesExpected, @"Maximum expected resources should round-trip."); +} + @end diff --git a/platform/osx/test/MGLOfflineStorageTests.m b/platform/osx/test/MGLOfflineStorageTests.m index ff738f923..3657f93d4 100644 --- a/platform/osx/test/MGLOfflineStorageTests.m +++ b/platform/osx/test/MGLOfflineStorageTests.m @@ -82,6 +82,18 @@ [self expectationForNotification:MGLOfflinePackProgressChangedNotification object:pack handler:^BOOL(NSNotification * _Nonnull notification) { MGLOfflinePack *notificationPack = notification.object; XCTAssert([notificationPack isKindOfClass:[MGLOfflinePack class]], @"Object of notification should be an MGLOfflinePack."); + + NSDictionary *userInfo = notification.userInfo; + XCTAssertNotNil(userInfo, @"Progress change notification should have a userInfo dictionary."); + + NSNumber *stateNumber = userInfo[MGLOfflinePackStateUserInfoKey]; + XCTAssert([stateNumber isKindOfClass:[NSNumber class]], @"Progress change notification’s state should be an NSNumber."); + XCTAssertEqual(stateNumber.integerValue, pack.state, @"State in a progress change notification should match the pack’s state."); + + NSValue *progressValue = userInfo[MGLOfflinePackProgressUserInfoKey]; + XCTAssert([progressValue isKindOfClass:[NSValue class]], @"Progress change notification’s progress should be an NSValue."); + XCTAssertEqualObjects(progressValue, [NSValue valueWithMGLOfflinePackProgress:pack.progress], @"Progress change notification’s progress should match pack’s progress."); + return notificationPack == pack && pack.state == MGLOfflinePackStateInactive; }]; [self waitForExpectationsWithTimeout:1 handler:nil]; From 78f93708d66d99da71e3292c32f34cc4e46ecc69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 28 Mar 2016 00:05:58 -0700 Subject: [PATCH 092/104] [osx] Offline pack manager in osxapp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added an offline pack download manager to osxapp to demonstrate the use of MGLOfflineStorage with Cocoa Bindings. Like the Offline Packs view controller in iosapp, new packs are added based on the foremost map view’s current state. Double-clicking a complete offline pack opens a new map window to the pack’s bounds. --- platform/osx/app/AppDelegate.h | 2 +- platform/osx/app/AppDelegate.m | 96 +++++++++ platform/osx/app/MainMenu.xib | 202 +++++++++++++++++- platform/osx/app/MapDocument.m | 38 ++++ .../osx/app/OfflinePackNameValueTransformer.h | 5 + .../osx/app/OfflinePackNameValueTransformer.m | 33 +++ platform/osx/app/mapboxgl-app.gypi | 2 + 7 files changed, 374 insertions(+), 4 deletions(-) create mode 100644 platform/osx/app/OfflinePackNameValueTransformer.h create mode 100644 platform/osx/app/OfflinePackNameValueTransformer.m diff --git a/platform/osx/app/AppDelegate.h b/platform/osx/app/AppDelegate.h index 45d389f54..ca9edab77 100644 --- a/platform/osx/app/AppDelegate.h +++ b/platform/osx/app/AppDelegate.h @@ -15,8 +15,8 @@ extern NSString * const MGLMapboxAccessTokenDefaultsKey; @property (assign) double pendingZoomLevel; @property (copy) MGLMapCamera *pendingCamera; +@property (assign) MGLCoordinateBounds pendingVisibleCoordinateBounds; @property (copy) NSURL *pendingStyleURL; @property (assign) MGLMapDebugMaskOptions pendingDebugMask; @end - diff --git a/platform/osx/app/AppDelegate.m b/platform/osx/app/AppDelegate.m index b54ab4fe7..186a3a1ab 100644 --- a/platform/osx/app/AppDelegate.m +++ b/platform/osx/app/AppDelegate.m @@ -7,8 +7,58 @@ NSString * const MGLLastMapCameraDefaultsKey = @"MGLLastMapCamera"; NSString * const MGLLastMapStyleURLDefaultsKey = @"MGLLastMapStyleURL"; NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; +/** + Some convenience methods to make offline pack properties easier to bind to. + */ +@implementation MGLOfflinePack (Additions) + ++ (NSSet *)keyPathsForValuesAffectingStateImage { + return [NSSet setWithObjects:@"state", nil]; +} + +- (NSImage *)stateImage { + switch (self.state) { + case MGLOfflinePackStateComplete: + return [NSImage imageNamed:@"NSMenuOnStateTemplate"]; + + case MGLOfflinePackStateActive: + return [NSImage imageNamed:@"NSFollowLinkFreestandingTemplate"]; + + default: + return nil; + } +} + ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingCountOfResourcesCompleted { + return [NSSet setWithObjects:@"progress", nil]; +} + +- (uint64_t)countOfResourcesCompleted { + return self.progress.countOfResourcesCompleted; +} + ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingCountOfResourcesExpected { + return [NSSet setWithObjects:@"progress", nil]; +} + +- (uint64_t)countOfResourcesExpected { + return self.progress.countOfResourcesExpected; +} + ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingCountOfBytesCompleted { + return [NSSet setWithObjects:@"progress", nil]; +} + +- (uint64_t)countOfBytesCompleted { + return self.progress.countOfBytesCompleted; +} + +@end + @interface AppDelegate () +@property (weak) IBOutlet NSArrayController *offlinePacksArrayController; + @end @implementation AppDelegate @@ -63,6 +113,8 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; [alert runModal]; [self showPreferences:nil]; } + + [self.offlinePacksArrayController bind:@"content" toObject:[MGLOfflineStorage sharedOfflineStorage] withKeyPath:@"packs" options:nil]; } - (void)applicationWillTerminate:(NSNotification *)notification { @@ -79,6 +131,8 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; [[NSUserDefaults standardUserDefaults] setInteger:mapView.debugMask forKey:MGLLastMapDebugMaskDefaultsKey]; } } + + [self.offlinePacksArrayController unbind:@"content"]; } #pragma mark Services @@ -121,6 +175,45 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; [[NSDocumentController sharedDocumentController] openUntitledDocumentAndDisplay:YES error:NULL]; } +#pragma mark Offline pack management + +- (IBAction)delete:(id)sender { + for (MGLOfflinePack *pack in self.offlinePacksArrayController.selectedObjects) { + [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError * _Nullable error) { + if (error) { + [[NSAlert alertWithError:error] runModal]; + } + }]; + } +} + +- (IBAction)chooseOfflinePack:(id)sender { + for (MGLOfflinePack *pack in self.offlinePacksArrayController.selectedObjects) { + switch (pack.state) { + case MGLOfflinePackStateComplete: + { + if ([pack.region isKindOfClass:[MGLTilePyramidOfflineRegion class]]) { + MGLTilePyramidOfflineRegion *region = (MGLTilePyramidOfflineRegion *)pack.region; + self.pendingVisibleCoordinateBounds = region.bounds; + [[NSDocumentController sharedDocumentController] openUntitledDocumentAndDisplay:YES error:NULL]; + } + break; + } + + case MGLOfflinePackStateInactive: + [pack resume]; + break; + + case MGLOfflinePackStateActive: + [pack suspend]; + break; + + default: + break; + } + } +} + #pragma mark Help methods - (IBAction)showShortcuts:(id)sender { @@ -154,6 +247,9 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; if (menuItem.action == @selector(showPreferences:)) { return YES; } + if (menuItem.action == @selector(delete:)) { + return self.offlinePacksArrayController.selectedObjects.count; + } return NO; } diff --git a/platform/osx/app/MainMenu.xib b/platform/osx/app/MainMenu.xib index 64ff4e550..c408bdc56 100644 --- a/platform/osx/app/MainMenu.xib +++ b/platform/osx/app/MainMenu.xib @@ -1,7 +1,7 @@ - + - + @@ -17,6 +17,7 @@ + @@ -113,6 +114,12 @@ + + + + + + @@ -516,6 +523,13 @@ + + + + + + + @@ -551,7 +565,7 @@ - + @@ -609,8 +623,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OfflinePackNameValueTransformer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + context + countOfResourcesCompleted + countOfResourcesExpected + countOfBytesCompleted + stateImage + + + + diff --git a/platform/osx/app/MapDocument.m b/platform/osx/app/MapDocument.m index 7c42bc980..16d15c4ff 100644 --- a/platform/osx/app/MapDocument.m +++ b/platform/osx/app/MapDocument.m @@ -204,6 +204,10 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = { appDelegate.pendingZoomLevel = -1; appDelegate.pendingCamera = nil; } + if (!MGLCoordinateBoundsIsEmpty(appDelegate.pendingVisibleCoordinateBounds)) { + self.mapView.visibleCoordinateBounds = appDelegate.pendingVisibleCoordinateBounds; + appDelegate.pendingVisibleCoordinateBounds = (MGLCoordinateBounds){ { 0, 0 }, { 0, 0 } }; + } if (appDelegate.pendingDebugMask) { self.mapView.debugMask = appDelegate.pendingDebugMask; } @@ -350,6 +354,36 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = { [self.mapView addAnnotation:line]; } +#pragma mark Offline packs + +- (IBAction)addOfflinePack:(id)sender { + NSAlert *namePrompt = [[NSAlert alloc] init]; + namePrompt.messageText = @"Add offline pack"; + namePrompt.informativeText = @"Choose a name for the pack:"; + NSTextField *nameTextField = [[NSTextField alloc] initWithFrame:NSZeroRect]; + nameTextField.placeholderString = MGLStringFromCoordinateBounds(self.mapView.visibleCoordinateBounds); + [nameTextField sizeToFit]; + NSRect textFieldFrame = nameTextField.frame; + textFieldFrame.size.width = 300; + nameTextField.frame = textFieldFrame; + namePrompt.accessoryView = nameTextField; + [namePrompt addButtonWithTitle:@"Add"]; + [namePrompt addButtonWithTitle:@"Cancel"]; + if ([namePrompt runModal] != NSAlertFirstButtonReturn) { + return; + } + + id region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:self.mapView.styleURL bounds:self.mapView.visibleCoordinateBounds fromZoomLevel:self.mapView.zoomLevel toZoomLevel:self.mapView.maximumZoomLevel]; + NSData *context = [[NSValueTransformer valueTransformerForName:@"OfflinePackNameValueTransformer"] reverseTransformedValue:nameTextField.stringValue]; + [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable pack, NSError * _Nullable error) { + if (error) { + [[NSAlert alertWithError:error] runModal]; + } else { + [pack resume]; + } + }]; +} + #pragma mark Help methods - (IBAction)giveFeedback:(id)sender { @@ -500,6 +534,10 @@ static const CLLocationCoordinate2D WorldTourDestinations[] = { if (menuItem.action == @selector(drawPolygonAndPolyLineAnnotations:)) { return !_isShowingPolygonAndPolylineAnnotations; } + if (menuItem.action == @selector(addOfflinePack:)) { + NSURL *styleURL = self.mapView.styleURL; + return !styleURL.isFileURL; + } if (menuItem.action == @selector(giveFeedback:)) { return YES; } diff --git a/platform/osx/app/OfflinePackNameValueTransformer.h b/platform/osx/app/OfflinePackNameValueTransformer.h new file mode 100644 index 000000000..11fe3ff44 --- /dev/null +++ b/platform/osx/app/OfflinePackNameValueTransformer.h @@ -0,0 +1,5 @@ +#import + +@interface OfflinePackNameValueTransformer : NSValueTransformer + +@end diff --git a/platform/osx/app/OfflinePackNameValueTransformer.m b/platform/osx/app/OfflinePackNameValueTransformer.m new file mode 100644 index 000000000..2825e48ed --- /dev/null +++ b/platform/osx/app/OfflinePackNameValueTransformer.m @@ -0,0 +1,33 @@ +#import "OfflinePackNameValueTransformer.h" + +static NSString * const MBXOfflinePackContextNameKey = @"Name"; + +@implementation OfflinePackNameValueTransformer + ++ (Class)transformedValueClass { + return [NSString class]; +} + ++ (BOOL)allowsReverseTransformation { + return YES; +} + +- (NSString *)transformedValue:(NSData *)context { + NSAssert([context isKindOfClass:[NSData class]], @"Context should be NSData."); + + NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:context]; + NSAssert([userInfo isKindOfClass:[NSDictionary class]], @"Context of offline pack isn’t a dictionary."); + NSString *name = userInfo[MBXOfflinePackContextNameKey]; + NSAssert([name isKindOfClass:[NSString class]], @"Name of offline pack isn’t a string."); + return name; +} + +- (NSData *)reverseTransformedValue:(NSString *)name { + NSAssert([name isKindOfClass:[NSString class]], @"Name should be a string."); + + return [NSKeyedArchiver archivedDataWithRootObject:@{ + MBXOfflinePackContextNameKey: name, + }]; +} + +@end diff --git a/platform/osx/app/mapboxgl-app.gypi b/platform/osx/app/mapboxgl-app.gypi index 7b39f5d9e..8b8cc1727 100644 --- a/platform/osx/app/mapboxgl-app.gypi +++ b/platform/osx/app/mapboxgl-app.gypi @@ -29,6 +29,8 @@ './LocationCoordinate2DTransformer.m', './MapDocument.h', './MapDocument.m', + './OfflinePackNameValueTransformer.h', + './OfflinePackNameValueTransformer.m', './TimeIntervalTransformer.h', './TimeIntervalTransformer.m', './NSValue+Additions.h', From 38116e39c5832851a585798ab32de3daa03c20e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 28 Mar 2016 18:06:52 -0700 Subject: [PATCH 093/104] [ios, osx] Require progress to be requested manually Requesting progress is expensive, so it is once again computed only on demand, rather than automatically at launch. Moved progress requesting back to iosapp and osxapp. --- platform/darwin/include/MGLOfflinePack.h | 34 ++++++++++++++----- platform/darwin/src/MGLOfflinePack.mm | 3 +- platform/darwin/src/MGLOfflinePack_Private.h | 12 ++----- platform/darwin/src/MGLOfflineStorage.mm | 3 +- .../app/MBXOfflinePacksTableViewController.m | 7 ++++ platform/osx/app/AppDelegate.m | 12 +++++++ platform/osx/app/MainMenu.xib | 3 +- 7 files changed, 50 insertions(+), 24 deletions(-) diff --git a/platform/darwin/include/MGLOfflinePack.h b/platform/darwin/include/MGLOfflinePack.h index b65fed384..783650590 100644 --- a/platform/darwin/include/MGLOfflinePack.h +++ b/platform/darwin/include/MGLOfflinePack.h @@ -11,9 +11,11 @@ typedef NS_ENUM (NSInteger, MGLOfflinePackState) { /** It is unknown whether the pack is inactive, active, or complete. - This is the initial state of a pack. The state becomes known by the time - the shared `MGLOfflineStorage` object sends its first - `MGLOfflinePackProgressChangedNotification`. + This is the initial state of a pack. The state of a pack becomes known by + the time the shared `MGLOfflineStorage` object sends the first + `MGLOfflinePackProgressChangedNotification` about the pack. For inactive + packs, you must explicitly request a progress update using the + `-[MGLOfflinePack requestProgress]` method. An invalid pack always has a state of `MGLOfflinePackStateInvalid`, never `MGLOfflinePackStateUnknown`. @@ -107,9 +109,10 @@ typedef struct MGLOfflinePackProgress { The pack’s current state. The state of an inactive or completed pack is computed lazily and is set to - `MGLOfflinePackStateUnknown` by default. To get notified when the state becomes - known, observe KVO change notifications on this pack’s `state` key path. - Alternatively, you can add an observer for + `MGLOfflinePackStateUnknown` by default. To request the pack’s status, use the + `-requestProgress` method. To get notified when the state becomes known and + when it changes, observe KVO change notifications on this pack’s `state` key + path. Alternatively, you can add an observer for `MGLOfflinePackProgressChangedNotification`s about this pack that come from the default notification center. */ @@ -119,9 +122,10 @@ typedef struct MGLOfflinePackProgress { The pack’s current progress. The progress of an inactive or completed pack is computed lazily, and all its - fields are set to 0 by default. To get notified when the progress becomes - known, observe KVO change notifications on this pack’s `state` key path. - Alternatively, you can add an observer for + fields are set to 0 by default. To request the pack’s progress, use the + `-requestProgress` method. To get notified when the progress becomes + known and when it changes, observe KVO change notifications on this pack’s + `state` key path. Alternatively, you can add an observer for `MGLOfflinePackProgressChangedNotification`s about this pack that come from the default notification center. */ @@ -159,6 +163,18 @@ typedef struct MGLOfflinePackProgress { */ - (void)suspend; +/** + Request an asynchronous update to the pack’s `state` and `progress` properties. + + The state and progress of an inactive or completed pack are computed lazily. If + you need the state or progress of a pack whose `state` property is currently + set to `MGLOfflinePackStateUnknown`, observe KVO change notifications on this + pack’s `state` key path, then call this method. Alternatively, you can add an + observer for `MGLOfflinePackProgressChangedNotification` about this pack that + come from the default notification center. + */ +- (void)requestProgress; + @end /** diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 05ff35ec7..9775f1cfc 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -40,7 +40,6 @@ private: @property (nonatomic, weak, nullable) id delegate; @property (nonatomic, nullable, readwrite) mbgl::OfflineRegion *mbglOfflineRegion; -@property (nonatomic, readwrite) MGLOfflinePackState state; @property (nonatomic, readwrite) MGLOfflinePackProgress progress; @end @@ -123,7 +122,7 @@ private: } - (void)requestProgress { - NSAssert(_state != MGLOfflinePackStateInvalid, @"Cannot request progress from an invalid offline pack."); + MGLAssertOfflinePackIsValid(); mbgl::DefaultFileSource *mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index 0e9265540..95d8ba432 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -19,17 +19,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable) mbgl::OfflineRegion *mbglOfflineRegion; -- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region; +@property (nonatomic, readwrite) MGLOfflinePackState state; -/** - Request an asynchronous update to the pack’s `state` and `progress` properties. - - The state and progress of an inactive or completed pack are computed lazily. If - you need the state or progress of a pack inside an - `MGLOfflinePackListingCompletionHandler`, set the `delegate` property then call - this method. - */ -- (void)requestProgress; +- (instancetype)initWithMBGLRegion:(mbgl::OfflineRegion *)region; /** Invalidates the pack and ensures that no future progress update can ever diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 3d171ca20..89bf05024 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -130,10 +130,10 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; - (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion { __weak MGLOfflineStorage *weakSelf = self; [self _addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable pack, NSError * _Nullable error) { + pack.state = MGLOfflinePackStateInactive; MGLOfflineStorage *strongSelf = weakSelf; [[strongSelf mutableArrayValueForKey:@"packs"] addObject:pack]; pack.delegate = strongSelf; - [pack requestProgress]; if (completion) { completion(pack, error); } @@ -208,7 +208,6 @@ NSString * const MGLOfflinePackMaximumCountUserInfoKey = @"MaximumCount"; for (MGLOfflinePack *pack in packs) { pack.delegate = self; - [pack requestProgress]; } }]; } diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m index f4a2917d6..8aad4fbbf 100644 --- a/platform/ios/app/MBXOfflinePacksTableViewController.m +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -70,6 +70,13 @@ static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Ac default: [self.tableView reloadData]; + + for (MGLOfflinePack *pack in [MGLOfflineStorage sharedOfflineStorage].packs) { + if (pack.state == MGLOfflinePackStateUnknown) { + [pack requestProgress]; + } + } + break; } } else { diff --git a/platform/osx/app/AppDelegate.m b/platform/osx/app/AppDelegate.m index 186a3a1ab..d9fd96741 100644 --- a/platform/osx/app/AppDelegate.m +++ b/platform/osx/app/AppDelegate.m @@ -58,6 +58,7 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; @interface AppDelegate () @property (weak) IBOutlet NSArrayController *offlinePacksArrayController; +@property (weak) IBOutlet NSPanel *offlinePacksPanel; @end @@ -177,6 +178,14 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; #pragma mark Offline pack management +- (IBAction)showOfflinePacksPanel:(id)sender { + [self.offlinePacksPanel makeKeyAndOrderFront:sender]; + + for (MGLOfflinePack *pack in self.offlinePacksArrayController.arrangedObjects) { + [pack requestProgress]; + } +} + - (IBAction)delete:(id)sender { for (MGLOfflinePack *pack in self.offlinePacksArrayController.selectedObjects) { [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError * _Nullable error) { @@ -247,6 +256,9 @@ NSString * const MGLLastMapDebugMaskDefaultsKey = @"MGLLastMapDebugMask"; if (menuItem.action == @selector(showPreferences:)) { return YES; } + if (menuItem.action == @selector(showOfflinePacksPanel:)) { + return YES; + } if (menuItem.action == @selector(delete:)) { return self.offlinePacksArrayController.selectedObjects.count; } diff --git a/platform/osx/app/MainMenu.xib b/platform/osx/app/MainMenu.xib index c408bdc56..646c4ae40 100644 --- a/platform/osx/app/MainMenu.xib +++ b/platform/osx/app/MainMenu.xib @@ -18,6 +18,7 @@ + @@ -527,7 +528,7 @@ - + From 9a556bf24af19bf2788fef447d095d97cff728a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 28 Mar 2016 18:11:00 -0700 Subject: [PATCH 094/104] [osx] Fixed tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous change includes an additional salient change: a newly minted offline pack’s state is inactive initially, not unknown. --- platform/osx/test/MGLOfflineStorageTests.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/osx/test/MGLOfflineStorageTests.m b/platform/osx/test/MGLOfflineStorageTests.m index 3657f93d4..8ffa1207c 100644 --- a/platform/osx/test/MGLOfflineStorageTests.m +++ b/platform/osx/test/MGLOfflineStorageTests.m @@ -55,7 +55,7 @@ XCTestExpectation *additionCompletionHandlerExpectation = [self expectationWithDescription:@"add pack completion handler"]; [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack * _Nullable completionHandlerPack, NSError * _Nullable error) { XCTAssertNotNil(completionHandlerPack, @"Added pack should exist."); - XCTAssertEqual(completionHandlerPack.state, MGLOfflinePackStateUnknown, @"Pack should initially have unknown state."); + XCTAssertEqual(completionHandlerPack.state, MGLOfflinePackStateInactive, @"New pack should initially have inactive state."); pack = completionHandlerPack; [additionCompletionHandlerExpectation fulfill]; }]; @@ -72,7 +72,7 @@ XCTAssert([userInfo[nameKey] isKindOfClass:[NSString class]], @"Name of offline pack isn’t a string."); XCTAssertEqualObjects(userInfo[nameKey], name, @"Name of offline pack has changed."); - XCTAssertEqual(pack.state, MGLOfflinePackStateUnknown, @"Pack should initially have unknown state."); + XCTAssertEqual(pack.state, MGLOfflinePackStateInactive, @"New pack should initially have inactive state."); [self keyValueObservingExpectationForObject:pack keyPath:@"state" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { NSKeyValueChange changeKind = [change[NSKeyValueChangeKindKey] unsignedIntegerValue]; @@ -96,6 +96,7 @@ return notificationPack == pack && pack.state == MGLOfflinePackStateInactive; }]; + [pack requestProgress]; [self waitForExpectationsWithTimeout:1 handler:nil]; } From f8b6e1f7da5cfa2e3dc88f9b643f766230f6ea50 Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 29 Mar 2016 09:16:02 +0200 Subject: [PATCH 095/104] [android] #4487 - ArraysInOfBoundsException fix for addMarkers --- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 51 +++++++++++-------- .../mapbox/mapboxsdk/maps/MapboxMapTest.java | 17 +++++++ 2 files changed, 46 insertions(+), 22 deletions(-) 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 9ab883c13..3fd9a2af5 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 @@ -610,29 +610,36 @@ public class MapboxMap { public List addMarkers(@NonNull List markerOptionsList) { int count = markerOptionsList.size(); List markers = new ArrayList<>(count); - MarkerOptions markerOptions; - Marker marker; - for (int i = 0; i < count; i++) { - markerOptions = markerOptionsList.get(i); - marker = prepareMarker(markerOptions); - markers.add(marker); - } - - long[] ids = mMapView.addMarkers(markers); - long id = 0; - Marker m; - - for (int i = 0; i < markers.size(); i++) { - m = markers.get(i); - m.setMapboxMap(this); - if (ids != null) { - id = ids[i]; - } else { - //unit test - id++; + if (count > 0) { + MarkerOptions markerOptions; + Marker marker; + for (int i = 0; i < count; i++) { + markerOptions = markerOptionsList.get(i); + marker = prepareMarker(markerOptions); + markers.add(marker); + } + + if (markers.size() > 0) { + long[] ids = mMapView.addMarkers(markers); + + // if unittests or markers are correctly added to map + if (ids == null || ids.length == markers.size()) { + long id = 0; + Marker m; + for (int i = 0; i < markers.size(); i++) { + m = markers.get(i); + m.setMapboxMap(this); + if (ids != null) { + id = ids[i]; + } else { + //unit test + id++; + } + m.setId(id); + mAnnotations.put(id, m); + } + } } - m.setId(id); - mAnnotations.put(id, m); } return markers; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java index 9e06a46aa..2032cfe90 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java @@ -534,6 +534,23 @@ public class MapboxMapTest { assertTrue(mMapboxMap.getMarkers().contains(markerOptions2.getMarker())); } + @Test + public void testAddMarkersEmpty() { + List markerList = new ArrayList<>(); + mMapboxMap.addMarkers(markerList); + assertEquals("Markers size should be 0", 0, mMapboxMap.getMarkers().size()); + } + + @Test + public void testAddMarkersSingleMarker() { + List markerList = new ArrayList<>(); + MarkerOptions markerOptions = new MarkerOptions().title("a"); + markerList.add(markerOptions); + mMapboxMap.addMarkers(markerList); + assertEquals("Markers size should be 1", 1, mMapboxMap.getMarkers().size()); + assertTrue(mMapboxMap.getMarkers().contains(markerOptions.getMarker())); + } + @Test public void testAddPolygon() { PolygonOptions polygonOptions = new PolygonOptions().add(new LatLng()); From 8262846294067aba4d9e5a4db4d1a280b181d95b Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 29 Mar 2016 09:26:56 +0200 Subject: [PATCH 096/104] [android] #4487 - ArrayInOutOfBoundsException fix for polyline and polygon --- .../com/mapbox/mapboxsdk/maps/MapboxMap.java | 87 +++++++++++-------- .../mapbox/mapboxsdk/maps/MapboxMapTest.java | 32 +++++++ 2 files changed, 82 insertions(+), 37 deletions(-) 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 3fd9a2af5..e1a9cd8cd 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 @@ -692,28 +692,35 @@ public class MapboxMap { int count = polylineOptionsList.size(); Polyline polyline; List polylines = new ArrayList<>(count); - for (PolylineOptions options : polylineOptionsList) { - polyline = options.getPolyline(); - if (!polyline.getPoints().isEmpty()) { - polylines.add(polyline); - } - } - long[] ids = mMapView.addPolylines(polylines); - long id = 0; - Polyline p; - - for (int i = 0; i < polylines.size(); i++) { - p = polylines.get(i); - p.setMapboxMap(this); - if (ids != null) { - id = ids[i]; - } else { - // unit test - id++; + if(count>0) { + for (PolylineOptions options : polylineOptionsList) { + polyline = options.getPolyline(); + if (!polyline.getPoints().isEmpty()) { + polylines.add(polyline); + } + } + + long[] ids = mMapView.addPolylines(polylines); + + // if unit tests or polylines are correctly added to map + if (ids == null || ids.length == polylines.size()) { + long id = 0; + Polyline p; + + for (int i = 0; i < polylines.size(); i++) { + p = polylines.get(i); + p.setMapboxMap(this); + if (ids != null) { + id = ids[i]; + } else { + // unit test + id++; + } + p.setId(id); + mAnnotations.put(id, p); + } } - p.setId(id); - mAnnotations.put(id, p); } return polylines; } @@ -750,26 +757,32 @@ public class MapboxMap { Polygon polygon; List polygons = new ArrayList<>(count); - for (PolygonOptions polygonOptions : polygonOptionsList) { - polygon = polygonOptions.getPolygon(); - if (!polygon.getPoints().isEmpty()) { - polygons.add(polygon); + if(count>0) { + for (PolygonOptions polygonOptions : polygonOptionsList) { + polygon = polygonOptions.getPolygon(); + if (!polygon.getPoints().isEmpty()) { + polygons.add(polygon); + } } - } - long[] ids = mMapView.addPolygons(polygons); - long id = 0; - for (int i = 0; i < polygons.size(); i++) { - polygon = polygons.get(i); - polygon.setMapboxMap(this); - if (ids != null) { - id = ids[i]; - } else { - // unit test - id++; + long[] ids = mMapView.addPolygons(polygons); + + // if unit tests or polygons correcly added to map + if(ids==null || ids.length==polygons.size()) { + long id = 0; + for (int i = 0; i < polygons.size(); i++) { + polygon = polygons.get(i); + polygon.setMapboxMap(this); + if (ids != null) { + id = ids[i]; + } else { + // unit test + id++; + } + polygon.setId(id); + mAnnotations.put(id, polygon); + } } - polygon.setId(id); - mAnnotations.put(id, polygon); } return polygons; } diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java index 2032cfe90..1705f44fa 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java @@ -581,6 +581,22 @@ public class MapboxMapTest { assertTrue("Polygon should be ignored", !mMapboxMap.getPolygons().contains(polygonOptions3.getPolygon())); } + @Test + public void addPolygonsEmpty() { + mMapboxMap.addPolygons(new ArrayList()); + assertEquals("Polygons size should be 0", 0, mMapboxMap.getPolygons().size()); + } + + @Test + public void addPolygonsSingle() { + List polygonList = new ArrayList<>(); + PolygonOptions polygonOptions = new PolygonOptions().fillColor(Color.BLACK).add(new LatLng()); + polygonList.add(polygonOptions); + mMapboxMap.addPolygons(polygonList); + assertEquals("Polygons size should be 1", 1, mMapboxMap.getPolygons().size()); + assertTrue(mMapboxMap.getPolygons().contains(polygonOptions.getPolygon())); + } + @Test public void testAddPolyline() { PolylineOptions polylineOptions = new PolylineOptions().add(new LatLng()); @@ -611,6 +627,22 @@ public class MapboxMapTest { assertTrue("Polyline should be ignored", !mMapboxMap.getPolylines().contains(polygonOptions3.getPolyline())); } + @Test + public void testAddPolylinesEmpty() { + mMapboxMap.addPolylines(new ArrayList()); + assertEquals("Polygons size should be 0", 0, mMapboxMap.getPolylines().size()); + } + + @Test + public void testAddPolylinesSingle() { + List polylineList = new ArrayList<>(); + PolylineOptions polygonOptions = new PolylineOptions().color(Color.BLACK).add(new LatLng()); + polylineList.add(polygonOptions); + mMapboxMap.addPolylines(polylineList); + assertEquals("Polygons size should be 1", 1, mMapboxMap.getPolylines().size()); + assertTrue(mMapboxMap.getPolylines().contains(polygonOptions.getPolyline())); + } + @Test public void testRemoveMarker() { MarkerOptions markerOptions = new MarkerOptions(); From d20795b891a6dfbde55333c95234c0a6d4e82131 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Mon, 28 Mar 2016 14:30:01 -0400 Subject: [PATCH 097/104] [ios] Don't use negative content insets When a map view was smaller than the entire viewport, negative content insets would be applied. Negative content insets would only be valid if the map view extended outside of its frame, which cannot happen. Fixes #4440. --- platform/ios/CHANGELOG.md | 1 + platform/ios/src/MGLMapView.mm | 5 +++++ platform/ios/test/MGLTViewController.h | 1 + platform/ios/test/MGLTViewController.m | 5 +++++ platform/ios/test/MapViewTests.m | 23 +++++++++++++++++++++++ 5 files changed, 35 insertions(+) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 473375469..68049be4c 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -7,6 +7,7 @@ Mapbox welcomes participation and contributions from everyone. If you’d like - If you’ve previously installed the SDK as a static framework, the installation workflow has changed to address issues when submitting your application to the App Store or installing it on a device. Upon upgrading to this version of the SDK, you’ll need to add Mapbox.bundle to the Copy Bundle Resources build phase and remove Mapbox.framework from the Embed Frameworks build phase. ([#4455](https://github.com/mapbox/mapbox-gl-native/pull/4455)) - Offline packs can now be downloaded to allow users to view specific regions of the map offline. A new MGLOfflineStorage class provides APIs for managing MGLOfflinePacks. ([#4221](https://github.com/mapbox/mapbox-gl-native/pull/4221)) - Tiles and other resources are cached in the same file that holds offline resources. The combined cache file is located in a subdirectory of the user’s Application Support directory, which means iOS will not delete the file when disk space runs low. ([#4377](https://github.com/mapbox/mapbox-gl-native/pull/4377)) +- Fixed an issue where the map view’s center would always be calculated as if the view occupied the entire screen. ([#4504](https://github.com/mapbox/mapbox-gl-native/issues/4504)) - The user dot no longer disappears after panning the map across the antimeridian at low zoom levels. ([#4275](https://github.com/mapbox/mapbox-gl-native/pull/4275)) - The map no longer recoils when panning quickly at low zoom levels. ([#4214](https://github.com/mapbox/mapbox-gl-native/pull/4214)) - Fixed an issue causing the map to pan the wrong way when the user pinches unevenly. ([#4427](https://github.com/mapbox/mapbox-gl-native/pull/4427)) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 9b094ec89..e8165b41e 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -814,6 +814,11 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) - viewController.bottomLayoutGuide.length); contentInset.bottom = (CGRectGetMaxY(self.bounds) - [self convertPoint:bottomPoint fromView:viewController.view].y); + + // Negative insets are invalid, replace with 0. + contentInset.top = fmaxf(contentInset.top, 0); + contentInset.bottom = fmaxf(contentInset.bottom, 0); + self.contentInset = contentInset; } diff --git a/platform/ios/test/MGLTViewController.h b/platform/ios/test/MGLTViewController.h index 0be0e1ff2..349c21600 100644 --- a/platform/ios/test/MGLTViewController.h +++ b/platform/ios/test/MGLTViewController.h @@ -3,6 +3,7 @@ @interface MGLTViewController : UIViewController - (void)insetMapView; +- (void)tinyMapView; - (void)resetMapView; @end diff --git a/platform/ios/test/MGLTViewController.m b/platform/ios/test/MGLTViewController.m index 09c60bf61..451dea929 100644 --- a/platform/ios/test/MGLTViewController.m +++ b/platform/ios/test/MGLTViewController.m @@ -21,6 +21,11 @@ _mapView.frame = CGRectInset(_mapView.frame, 50, 50); } +- (void)tinyMapView +{ + _mapView.frame = CGRectMake(20, self.topLayoutGuide.length, self.view.frame.size.width / 2, self.view.frame.size.height / 2); +} + - (void)resetMapView { _mapView.frame = self.view.bounds; diff --git a/platform/ios/test/MapViewTests.m b/platform/ios/test/MapViewTests.m index 40022a1ee..c8fe862e0 100644 --- a/platform/ios/test/MapViewTests.m +++ b/platform/ios/test/MapViewTests.m @@ -424,6 +424,29 @@ @"compass should lie inside shrunken map view"); } +- (void)testContentInsetsWithTinyMapView { + [tester.viewController tinyMapView]; + [self keyValueObservingExpectationForObject:tester.mapView keyPath:@"contentInset" handler:^BOOL(id observedObject, NSDictionary *change) { + XCTAssertEqual(tester.mapView.contentInset.top, + 0, + @"map should not have top content inset"); + XCTAssertEqual(tester.mapView.contentInset.bottom, + 0, + @"map should not have bottom content inset"); + return YES; + }]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; + + tester.mapView.frame = CGRectMake(0, 0, tester.mapView.frame.size.width, tester.mapView.frame.size.height); + [self keyValueObservingExpectationForObject:tester.mapView keyPath:@"contentInset" handler:^BOOL(id observedObject, NSDictionary *change) { + XCTAssertEqual(tester.mapView.contentInset.top, + tester.viewController.topLayoutGuide.length, + @"map should have top content inset equal to the top layout guide"); + return YES; + }]; + [self waitForExpectationsWithTimeout:2.0 handler:nil]; +} + - (void)testDelegateRegionWillChange { __block NSUInteger unanimatedCount; __block NSUInteger animatedCount; From 593f3d511a89acb226979f4a504d2449d9a96969 Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Mon, 28 Mar 2016 15:42:14 -0400 Subject: [PATCH 098/104] [ios] Make showAnnotations default padding proportional at smaller frame sizes --- platform/ios/src/MGLMapView.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index e8165b41e..b7fc9b9a3 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -2969,9 +2969,9 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration) - (void)showAnnotations:(NS_ARRAY_OF(id ) *)annotations animated:(BOOL)animated { - CGFloat defaultPadding = 100; - CGFloat yPadding = (self.frame.size.height / 2 <= defaultPadding) ? (self.frame.size.height / 5) : defaultPadding; - CGFloat xPadding = (self.frame.size.width / 2 <= defaultPadding) ? (self.frame.size.width / 5) : defaultPadding; + CGFloat maximumPadding = 100; + CGFloat yPadding = (self.frame.size.height / 5 <= maximumPadding) ? (self.frame.size.height / 5) : maximumPadding; + CGFloat xPadding = (self.frame.size.width / 5 <= maximumPadding) ? (self.frame.size.width / 5) : maximumPadding; UIEdgeInsets edgeInsets = UIEdgeInsetsMake(yPadding, xPadding, yPadding, xPadding); From e84c937dc0571f874b46100287bd812df550e2a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 29 Mar 2016 12:50:28 -0700 Subject: [PATCH 099/104] ios-v3.2.0-beta.3 --- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 2f9f5f20e..b226ef780 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.2.0-beta.2-symbols' + m.version = '3.2.0-beta.3-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' From fc8215ecbd541d3cc0f09abe7ab3ab31f9d9467a Mon Sep 17 00:00:00 2001 From: Tobrun Date: Tue, 29 Mar 2016 12:08:17 +0200 Subject: [PATCH 100/104] [android] #4500 - OnMapReady not invoked for offline maps --- .../src/main/java/com/mapbox/mapboxsdk/maps/MapView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5d4a171c1..38dd4bccb 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 @@ -400,7 +400,7 @@ public class MapView extends FrameLayout { addOnMapChangedListener(new OnMapChangedListener() { @Override public void onMapChanged(@MapChange int change) { - if (change == DID_FINISH_LOADING_MAP) { + if (change == DID_FINISH_RENDERING_MAP_FULLY_RENDERED) { reloadIcons(); reloadMarkers(); adjustTopOffsetPixels(); From c4dbde3d59fea5c6ff4af622fdc9c35b599a4ed9 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Wed, 30 Mar 2016 11:50:41 -0500 Subject: [PATCH 101/104] [android] #4535 - Setting version to 4.0.0 for release --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- .../fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 0e3858644..71d479712 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0-SNAPSHOT +VERSION_NAME=4.0.0 POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native diff --git a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties index 14ced7955..8c1dcc38c 100644 --- a/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties +++ b/platform/android/MapboxGLAndroidSDK/src/main/resources/fabric/com.mapbox.mapboxsdk.mapbox-android-sdk.properties @@ -1,3 +1,3 @@ fabric-identifier=com.mapbox.mapboxsdk.mapbox-android-sdk -fabric-version=4.0.0-rc.1 +fabric-version=4.0.0 fabric-build-type=binary From 66ffa453f007a9c7d4ce39ac9be4e5cccb50ffd1 Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Wed, 30 Mar 2016 13:27:01 -0500 Subject: [PATCH 102/104] [android] #4535 - 4.0.0 Changelog --- platform/android/CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index dd761afb4..7ba51fd36 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -2,6 +2,14 @@ Mapbox welcomes participation and contributions from everyone. If you'd like to do so please see the [`Contributing Guide`](https://github.com/mapbox/mapbox-gl-native/blob/master/CONTRIBUTING.md) first to get started. +## 4.0.0 + +Mapbox Android 4.0.0 contains the following 3 major new features. + +* MapboxMap API Change ([#3145](https://github.com/mapbox/mapbox-gl-native/issues/3145)) +* Offline Maps ([#3891](https://github.com/mapbox/mapbox-gl-native/issues/3891)) +* Telemetry ([#2421](https://github.com/mapbox/mapbox-gl-native/issues/2421)) + ## 4.0.0-rc.1 * Default Value Bug Fix for MapboxMapOptions ([#4398](https://github.com/mapbox/mapbox-gl-native/issues/4398)) From 7c036fb61882604c91b0873c2e8a9f34e9daed5e Mon Sep 17 00:00:00 2001 From: Brad Leege Date: Wed, 30 Mar 2016 15:16:21 -0500 Subject: [PATCH 103/104] [android] #4535 - Enabling 4.1.0-SNAPSHOT --- platform/android/MapboxGLAndroidSDK/gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties index 71d479712..56cb4324f 100644 --- a/platform/android/MapboxGLAndroidSDK/gradle.properties +++ b/platform/android/MapboxGLAndroidSDK/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.mapbox.mapboxsdk -VERSION_NAME=4.0.0 +VERSION_NAME=4.1.0-SNAPSHOT POM_DESCRIPTION=Mapbox GL Android SDK POM_URL=https://github.com/mapbox/mapbox-gl-native From 7b5a1ca1670a0346cdbf2af689fabde4e70ed561 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 29 Mar 2016 16:07:10 -0700 Subject: [PATCH 104/104] [core] Localize and simplify state for MapChangeDidFinishLoadingMap event Only Map needs to track this state, and it can simply be set when beginning to load a style and reset when finished. --- include/mbgl/map/map.hpp | 1 + src/mbgl/map/map.cpp | 6 ++++-- src/mbgl/map/map_context.cpp | 5 ----- src/mbgl/map/map_data.hpp | 1 - 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index 463bee793..3b8cea83a 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -205,6 +205,7 @@ private: }; RenderState renderState = RenderState::never; + bool loading = false; }; } // namespace mbgl diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index 374e3fe61..65f19c149 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -78,8 +78,8 @@ void Map::renderSync() { } else if (renderState != RenderState::fully) { renderState = RenderState::fully; view.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered); - if (data->loading) { - data->loading = false; + if (loading) { + loading = false; view.notifyMapChange(MapChangeDidFinishLoadingMap); } } @@ -101,11 +101,13 @@ void Map::update(Update flags) { #pragma mark - Style void Map::setStyleURL(const std::string &url) { + loading = true; view.notifyMapChange(MapChangeWillStartLoadingMap); context->invoke(&MapContext::setStyleURL, url); } void Map::setStyleJSON(const std::string& json, const std::string& base) { + loading = true; view.notifyMapChange(MapChangeWillStartLoadingMap); context->invoke(&MapContext::setStyleJSON, json, base); } diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index 6a1779117..f8d805b68 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -109,7 +109,6 @@ void MapContext::setStyleURL(const std::string& url) { Log::Error(Event::Setup, "style %s could not be found or is an incompatible legacy map or style", styleURL.c_str()); } else { Log::Error(Event::Setup, "loading style failed: %s", res.error->message.c_str()); - data.loading = false; } } else if (res.notModified || res.noContent) { return; @@ -142,10 +141,6 @@ void MapContext::loadStyleJSON(const std::string& json, const std::string& base) // force style cascade, causing all pending transitions to complete. style->cascade(); - // set loading here so we don't get a false loaded event as soon as map is - // created but before a style is loaded - data.loading = true; - updateFlags |= Update::DefaultTransition | Update::Classes | Update::Zoom | Update::Annotations; asyncUpdate.send(); } diff --git a/src/mbgl/map/map_data.hpp b/src/mbgl/map/map_data.hpp index 67c66896e..8b3ac4255 100644 --- a/src/mbgl/map/map_data.hpp +++ b/src/mbgl/map/map_data.hpp @@ -149,7 +149,6 @@ public: bool paused = false; std::mutex mutexPause; std::condition_variable condPause; - bool loading = false; }; } // namespace mbgl