diff --git a/arcgis_map_sdk/lib/arcgis_map_sdk.dart b/arcgis_map_sdk/lib/arcgis_map_sdk.dart index c1b43b7d..de66d2dd 100644 --- a/arcgis_map_sdk/lib/arcgis_map_sdk.dart +++ b/arcgis_map_sdk/lib/arcgis_map_sdk.dart @@ -1,6 +1,7 @@ // ignore: unnecessary_library_directive library arcgis_map; +export 'package:arcgis_map_sdk/src/arcgis_location_display.dart'; export 'package:arcgis_map_sdk/src/arcgis_map_controller.dart'; export 'package:arcgis_map_sdk/src/arcgis_map_sdk.dart'; export 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; diff --git a/arcgis_map_sdk/lib/src/arcgis_location_display.dart b/arcgis_map_sdk/lib/src/arcgis_location_display.dart new file mode 100644 index 00000000..1fdc629b --- /dev/null +++ b/arcgis_map_sdk/lib/src/arcgis_location_display.dart @@ -0,0 +1,55 @@ +import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; + +class ArcgisManualLocationDisplay extends ArcgisLocationDisplay { + @override + String get type => "manual"; + + ArcgisManualLocationDisplay(super.mapId); + + Future updateLocation(UserPosition position) { + return ArcgisMapPlatform.instance + .updateLocationDisplaySourcePositionManually( + mapId, + position, + ); + } +} + +class ArcgisLocationDisplay { + final int mapId; + final String type = "system"; + + ArcgisLocationDisplay(this.mapId); + + Future startSource() { + return ArcgisMapPlatform.instance.startLocationDisplayDataSource(mapId); + } + + Future stopSource() { + return ArcgisMapPlatform.instance.stopLocationDisplayDataSource(mapId); + } + + Future setDataSource() { + return ArcgisMapPlatform.instance.setLocationDisplayDataSource(mapId); + } + + Future setDefaultSymbol(Symbol symbol) { + return ArcgisMapPlatform.instance + .setLocationDisplayDefaultSymbol(mapId, symbol); + } + + Future setAccuracySymbol(Symbol symbol) { + return ArcgisMapPlatform.instance + .setLocationDisplayAccuracySymbol(mapId, symbol); + } + + Future setPingAnimationSymbol(Symbol symbol) { + return ArcgisMapPlatform.instance + .setLocationDisplayPingAnimationSymbol(mapId, symbol); + } + + Future setUseCourseSymbolOnMovement(bool useCourseSymbol) { + return ArcgisMapPlatform.instance + .setUseCourseSymbolOnMovement(mapId, useCourseSymbol); + } +} diff --git a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart index 4cb7b60e..39635463 100644 --- a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart +++ b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart @@ -1,51 +1,17 @@ +import 'package:arcgis_map_sdk/src/arcgis_location_display.dart'; import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; import 'package:flutter/services.dart'; -class ArcgisLocationDisplay { - final int mapId; - - ArcgisLocationDisplay._(this.mapId); - - Future startSource() { - return ArcgisMapPlatform.instance.startLocationDisplayDataSource(mapId); - } - - Future stopSource() { - return ArcgisMapPlatform.instance.stopLocationDisplayDataSource(mapId); - } - - Future setDataSource() { - return ArcgisMapPlatform.instance.setLocationDisplayDataSource(mapId); - } - - Future setDefaultSymbol(Symbol symbol) { - return ArcgisMapPlatform.instance - .setLocationDisplayDefaultSymbol(mapId, symbol); - } - - Future setAccuracySymbol(Symbol symbol) { - return ArcgisMapPlatform.instance - .setLocationDisplayAccuracySymbol(mapId, symbol); - } - - Future setPingAnimationSymbol(Symbol symbol) { - return ArcgisMapPlatform.instance - .setLocationDisplayPingAnimationSymbol(mapId, symbol); - } - - Future setUseCourseSymbolOnMovement(bool useCourseSymbol) { - return ArcgisMapPlatform.instance - .setUseCourseSymbolOnMovement(mapId, useCourseSymbol); - } -} - class ArcgisMapController { ArcgisMapController._({ required this.mapId, - }) : locationDisplay = ArcgisLocationDisplay._(mapId); + }) : _locationDisplay = ArcgisLocationDisplay(mapId); final int mapId; - final ArcgisLocationDisplay locationDisplay; + + late ArcgisLocationDisplay _locationDisplay; + + ArcgisLocationDisplay get locationDisplay => _locationDisplay; static Future init( int id, @@ -288,4 +254,10 @@ class ArcgisMapController { List getVisibleGraphicIds() { return ArcgisMapPlatform.instance.getVisibleGraphicIds(mapId); } + + Future setLocationDisplay(ArcgisLocationDisplay locationDisplay) { + return ArcgisMapPlatform.instance + .setLocationDisplay(mapId, locationDisplay.type) + .whenComplete(() => _locationDisplay = locationDisplay); + } } diff --git a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift index 99f4a790..dc53f9bb 100644 --- a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift +++ b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift @@ -126,6 +126,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView { case "location_display_set_accuracy_symbol": onSetLocationDisplayAccuracySymbol(call, result) case "location_display_set_ping_animation_symbol" : onSetLocationDisplayPingAnimationSymbol(call, result) case "location_display_set_use_course_symbol_on_move" : onSetLocationDisplayUseCourseSymbolOnMove(call, result) + case "location_display_update_display_source_position_manually" : onUpdateLocationDisplaySourcePositionManually(call, result) + case "location_display_set_data_source_type" : onSetLocationDisplayDataSourceType(call, result) default: result(FlutterError(code: "Unimplemented", message: "No method matching the name\(call.method)", details: nil)) } @@ -343,6 +345,44 @@ class ArcgisMapView: NSObject, FlutterPlatformView { result(true) } + private func onUpdateLocationDisplaySourcePositionManually(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + let dataSource = mapView.locationDisplay.dataSource + guard let source = dataSource as? ManualLocationDataSource else { + result(FlutterError(code: "invalid_state", message: "Expected ManualLocationDataSource but got \(dataSource)", details: nil)) + return + } + + guard let dict = call.arguments as? Dictionary, let position: UserPosition = try? JsonUtil.objectOfJson(dict) else { + result(FlutterError(code: "missing_data", message: "Expected arguments to contain data of UserPosition.", details: nil)) + return + } + + source.setNewLocation(coordinate: position.latLng, accuracy: position.accuracy, course: position.heading) + } + + private func onSetLocationDisplayDataSourceType(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + if(mapView.locationDisplay.dataSource.status == .started) { + result(FlutterError(code: "invalid_state", message: "Current data source is running. Make sure to stop it before setting a new data source", details: nil)) + return + } + + guard let type = call.arguments as? String else { + result(FlutterError(code: "missing_data", message: "Invalid argument, expected a type of data source as string.", details: nil)) + return + } + + switch(type) { + case "manual" : + mapView.locationDisplay.dataSource = ManualLocationDataSource() + result(true) + case "system" : + mapView.locationDisplay.dataSource = AGSCLLocationDataSource() + result(true) + default: + result(FlutterError(code: "missing_data", message: "Unknown data source type \(String(describing: type))", details: nil)) + } + } + private func operationWithSymbol(_ call: FlutterMethodCall, _ result: @escaping FlutterResult, handler: (AGSSymbol) -> Void) { do { guard let args = call.arguments as? [String: Any] else { diff --git a/arcgis_map_sdk_ios/ios/Classes/ManualLocationDataSource.swift b/arcgis_map_sdk_ios/ios/Classes/ManualLocationDataSource.swift new file mode 100644 index 00000000..6ddbee41 --- /dev/null +++ b/arcgis_map_sdk_ios/ios/Classes/ManualLocationDataSource.swift @@ -0,0 +1,22 @@ +// +// ManualLocationDataSource.swift +// arcgis_map_sdk_ios +// +// Created by Julian Bissekkou on 27.11.23. +// + +import Foundation +import ArcGIS + +class ManualLocationDataSource: AGSLocationDataSource { + public func setNewLocation(coordinate: LatLng, accuracy: Double?, course: Double?) { + let loc = AGSLocation( + position: coordinate.toAGSPoint(), + horizontalAccuracy: accuracy ?? 0, + velocity: 0, + course: course ?? 0, + lastKnown: false + ) + didUpdate(loc) + } +} diff --git a/arcgis_map_sdk_ios/ios/Classes/Models/UserPosition.swift b/arcgis_map_sdk_ios/ios/Classes/Models/UserPosition.swift new file mode 100644 index 00000000..aeac0bfd --- /dev/null +++ b/arcgis_map_sdk_ios/ios/Classes/Models/UserPosition.swift @@ -0,0 +1,14 @@ +// +// UserPosition.swift +// arcgis_map_sdk_ios +// +// Created by Julian Bissekkou on 27.11.23. +// + +import Foundation + +struct UserPosition: Codable { + let latLng: LatLng + let accuracy: Double? + let heading: Double? +} diff --git a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart index 01b42ac4..7800f06a 100644 --- a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart +++ b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart @@ -263,4 +263,23 @@ class MethodChannelArcgisMapPlugin extends ArcgisMapPlatform { useCourseSymbol, ); } + + @override + Future updateLocationDisplaySourcePositionManually( + int mapId, + UserPosition position, + ) { + return _methodChannelBuilder(mapId).invokeMethod( + "location_display_update_display_source_position_manually", + position.toMap(), + ); + } + + @override + Future setLocationDisplay(int mapId, String type) { + return _methodChannelBuilder(mapId).invokeMethod( + "location_display_set_data_source_type", + type, + ); + } } diff --git a/arcgis_map_sdk_method_channel/lib/src/model_extension.dart b/arcgis_map_sdk_method_channel/lib/src/model_extension.dart index ac78bc4f..8fca1914 100644 --- a/arcgis_map_sdk_method_channel/lib/src/model_extension.dart +++ b/arcgis_map_sdk_method_channel/lib/src/model_extension.dart @@ -20,6 +20,14 @@ extension LatLngJsonExtension on LatLng { }; } +extension UserPositionExtension on UserPosition { + Map toMap() => { + 'latLng': latLng.toMap(), + 'accuracy': accuracy, + 'heading': heading, + }; +} + extension ArcgisMapOptionsJsonExtension on ArcgisMapOptions { Map toMap() { return { diff --git a/arcgis_map_sdk_platform_interface/lib/arcgis_map_sdk_platform_interface.dart b/arcgis_map_sdk_platform_interface/lib/arcgis_map_sdk_platform_interface.dart index 984039cc..fffaabfd 100644 --- a/arcgis_map_sdk_platform_interface/lib/arcgis_map_sdk_platform_interface.dart +++ b/arcgis_map_sdk_platform_interface/lib/arcgis_map_sdk_platform_interface.dart @@ -6,6 +6,7 @@ export 'package:arcgis_map_sdk_platform_interface/src/events/map_event.dart'; export 'package:arcgis_map_sdk_platform_interface/src/models/animation_options.dart'; export 'package:arcgis_map_sdk_platform_interface/src/models/basemap.dart'; export 'package:arcgis_map_sdk_platform_interface/src/models/ground.dart'; +export 'package:arcgis_map_sdk_platform_interface/src/models/user_position.dart'; export 'package:arcgis_map_sdk_platform_interface/src/models/view_position.dart'; export 'package:arcgis_map_sdk_platform_interface/src/types/arcgis_map_options.dart'; export 'package:arcgis_map_sdk_platform_interface/src/types/attributes.dart'; diff --git a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart index 5c40144b..aa2f9b31 100644 --- a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart +++ b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart @@ -247,4 +247,19 @@ class ArcgisMapPlatform extends PlatformInterface { 'setUseCourseSymbolOnMovement() has not been implemented.', ); } + + Future updateLocationDisplaySourcePositionManually( + int mapId, + UserPosition position, + ) { + throw UnimplementedError( + 'updateLocationDisplaySourcePositionManually() has not been implemented.', + ); + } + + Future setLocationDisplay(int mapId, String type) { + throw UnimplementedError( + 'setLocationDisplay() has not been implemented.', + ); + } } diff --git a/arcgis_map_sdk_platform_interface/lib/src/models/user_position.dart b/arcgis_map_sdk_platform_interface/lib/src/models/user_position.dart new file mode 100644 index 00000000..4c21b88b --- /dev/null +++ b/arcgis_map_sdk_platform_interface/lib/src/models/user_position.dart @@ -0,0 +1,13 @@ +import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; + +class UserPosition { + final LatLng latLng; + final double? accuracy; + final double? heading; + + const UserPosition({ + required this.latLng, + required this.accuracy, + this.heading, + }); +}