From 12a86a58271aa56ac1fe75d289d6ff2bc47765f9 Mon Sep 17 00:00:00 2001 From: "ipcjs.mac" Date: Tue, 29 Nov 2022 18:01:14 +0800 Subject: [PATCH 1/4] chore: regenerate android/example && add flutter_lints --- .gitignore | 4 + .metadata | 27 +++- analysis_options.yaml | 4 + example/analysis_options.yaml | 29 ++++ example/android/.gitignore | 2 + example/android/app/build.gradle | 22 ++- .../android/app/src/debug/AndroidManifest.xml | 3 +- .../android/app/src/main/AndroidManifest.xml | 19 +-- .../res/drawable-v21/launch_background.xml | 12 ++ .../app/src/main/res/values-night/styles.xml | 18 +++ .../app/src/main/res/values/styles.xml | 12 +- .../app/src/profile/AndroidManifest.xml | 3 +- example/android/build.gradle | 4 +- example/android/gradle.properties | 1 - .../gradle/wrapper/gradle-wrapper.properties | 3 +- example/pubspec.lock | 49 +++--- example/pubspec.yaml | 3 +- pubspec.lock | 147 ------------------ pubspec.yaml | 1 + 19 files changed, 156 insertions(+), 207 deletions(-) create mode 100644 analysis_options.yaml create mode 100644 example/analysis_options.yaml create mode 100644 example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 example/android/app/src/main/res/values-night/styles.xml delete mode 100644 pubspec.lock diff --git a/.gitignore b/.gitignore index 7e38965..1c87630 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,7 @@ build/ .idea + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock diff --git a/.metadata b/.metadata index 20f6071..bc5a677 100644 --- a/.metadata +++ b/.metadata @@ -1,10 +1,33 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: cc949a8e8b9cf394b9290a8e80f87af3e207dce5 + revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 channel: stable project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: android + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + - platform: ios + create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..a5744c1 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/example/analysis_options.yaml b/example/analysis_options.yaml new file mode 100644 index 0000000..61b6c4d --- /dev/null +++ b/example/analysis_options.yaml @@ -0,0 +1,29 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at + # https://dart-lang.github.io/linter/lints/index.html. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/example/android/.gitignore b/example/android/.gitignore index 0a741cb..6f56801 100644 --- a/example/android/.gitignore +++ b/example/android/.gitignore @@ -9,3 +9,5 @@ GeneratedPluginRegistrant.java # Remember to never publicly share your keystore. # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app key.properties +**/*.keystore +**/*.jks diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 16ae045..01d77e0 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -26,21 +26,29 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion - sourceSets { - main.java.srcDirs += 'src/main/kotlin' + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' } - lintOptions { - disable 'InvalidPackage' + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.alexmiller.map_launcher.map_launcher_example" - minSdkVersion 16 - targetSdkVersion 29 + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml index 00a45b3..86a1a08 100644 --- a/example/android/app/src/debug/AndroidManifest.xml +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -1,6 +1,7 @@ - diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index e06b5b6..5b3912f 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,16 +1,12 @@ - - - - diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml index 1f83a33..cb1ef88 100644 --- a/example/android/app/src/main/res/values/styles.xml +++ b/example/android/app/src/main/res/values/styles.xml @@ -1,18 +1,18 @@ - - - diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml index 00a45b3..86a1a08 100644 --- a/example/android/app/src/profile/AndroidManifest.xml +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -1,6 +1,7 @@ - diff --git a/example/android/build.gradle b/example/android/build.gradle index 33b8d95..83ae220 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.5.31' + ext.kotlin_version = '1.6.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' + classpath 'com.android.tools.build:gradle:7.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle.properties b/example/android/gradle.properties index a673820..94adc3a 100644 --- a/example/android/gradle.properties +++ b/example/android/gradle.properties @@ -1,4 +1,3 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -android.enableR8=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 493072b..cb24abd 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/example/pubspec.lock b/example/pubspec.lock index 37ba830..058e946 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.2" + version: "2.9.0" boolean_selector: dependency: transitive description: @@ -21,21 +21,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" + version: "1.2.1" clock: dependency: transitive description: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" collection: dependency: transitive description: @@ -49,12 +42,19 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.0" + version: "1.3.1" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" flutter_svg: dependency: "direct main" description: @@ -67,41 +67,48 @@ packages: description: flutter source: sdk version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" map_launcher: dependency: "direct main" description: path: ".." relative: true source: path - version: "2.4.0" + version: "2.2.3" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.11" + version: "0.12.12" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.4" + version: "0.1.5" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0" path: dependency: transitive description: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.1" + version: "1.8.2" path_drawing: dependency: transitive description: @@ -134,7 +141,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.9.0" stack_trace: dependency: transitive description: @@ -155,21 +162,21 @@ packages: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.1.1" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.2.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.9" + version: "0.4.12" vector_math: dependency: transitive description: @@ -185,5 +192,5 @@ packages: source: hosted version: "5.1.0" sdks: - dart: ">=2.17.0-0 <3.0.0" + dart: ">=2.17.0 <3.0.0" flutter: ">=1.24.0-7.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 482c725..5db78c0 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -5,7 +5,7 @@ publish_to: "none" version: 0.1.0 environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' dependencies: flutter: @@ -17,6 +17,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + flutter_lints: ^2.0.0 flutter: uses-material-design: true diff --git a/pubspec.lock b/pubspec.lock deleted file mode 100644 index 30ae488..0000000 --- a/pubspec.lock +++ /dev/null @@ -1,147 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.16.0" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.4" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.9" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" -sdks: - dart: ">=2.17.0-0 <3.0.0" - flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml index 6a08b52..05ca425 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,6 +14,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter + flutter_lints: ^2.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From becd0a9e681847a53eea4639e9502ad16539a5d3 Mon Sep 17 00:00:00 2001 From: "ipcjs.mac" Date: Wed, 30 Nov 2022 14:28:45 +0800 Subject: [PATCH 2/4] fix: filter out disabled apps --- .../com/alexmiller/map_launcher/MapLauncherPlugin.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/android/src/main/kotlin/com/alexmiller/map_launcher/MapLauncherPlugin.kt b/android/src/main/kotlin/com/alexmiller/map_launcher/MapLauncherPlugin.kt index 0027349..c0f8268 100644 --- a/android/src/main/kotlin/com/alexmiller/map_launcher/MapLauncherPlugin.kt +++ b/android/src/main/kotlin/com/alexmiller/map_launcher/MapLauncherPlugin.kt @@ -59,8 +59,11 @@ class MapLauncherPlugin : FlutterPlugin, MethodCallHandler { ) private fun getInstalledMaps(): List { - val installedApps = context?.packageManager?.getInstalledApplications(0) ?: return listOf() - return maps.filter { map -> installedApps.any { app -> app.packageName == map.packageName } } + val installedPackageNames = (context?.packageManager?.getInstalledApplications(0) ?: emptyList()) + .filter { it.enabled } + .map { it.packageName } + .toHashSet() + return maps.filter { map -> installedPackageNames.contains(map.packageName) } } From 1d55988d372352d154caf500348c42f82180f0ac Mon Sep 17 00:00:00 2001 From: "ipcjs.mac" Date: Wed, 30 Nov 2022 15:41:01 +0800 Subject: [PATCH 3/4] chore: update example/ios --- example/ios/Flutter/AppFrameworkInfo.plist | 2 +- example/ios/Podfile | 2 +- example/ios/Podfile.lock | 6 +++--- example/ios/Runner.xcodeproj/project.pbxproj | 8 ++++---- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- example/ios/Runner/Info.plist | 2 ++ 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index f2872cf..4f8d4d2 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 9.0 + 11.0 diff --git a/example/ios/Podfile b/example/ios/Podfile index 1e8c3c9..88359b2 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +# platform :ios, '11.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index aa08106..021ddff 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -14,9 +14,9 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/map_launcher/ios" SPEC CHECKSUMS: - Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 map_launcher: e325db1261d029ff33e08e03baccffe09593ffea -PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c +PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 1b8732e..450f969 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -155,7 +155,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -339,7 +339,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -425,7 +425,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -474,7 +474,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index a28140c..3db53b6 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ qqmap here-location + CADisableMinimumFrameDurationOnPhone + From c2d1056ee7487a14cb442cda1d06416a70e66a8b Mon Sep 17 00:00:00 2001 From: "ipcjs.mac" Date: Wed, 30 Nov 2022 18:17:48 +0800 Subject: [PATCH 4/4] make `destination` nullable --- ios/Classes/SwiftMapLauncherPlugin.swift | 31 +++++---- lib/src/directions_url.dart | 82 ++++++++++++++---------- lib/src/map_launcher.dart | 22 +++++-- lib/src/models.dart | 6 +- lib/src/utils.dart | 15 +++++ 5 files changed, 103 insertions(+), 53 deletions(-) diff --git a/ios/Classes/SwiftMapLauncherPlugin.swift b/ios/Classes/SwiftMapLauncherPlugin.swift index 58d94aa..886425e 100644 --- a/ios/Classes/SwiftMapLauncherPlugin.swift +++ b/ios/Classes/SwiftMapLauncherPlugin.swift @@ -93,9 +93,8 @@ private func getDirectionsMode(directionsMode: String?) -> String { } } -private func showMarker(mapType: MapType, url: String, title: String, latitude: String, longitude: String) { - switch mapType { - case MapType.apple: +private func showMarker(mapType: MapType, url: String, title: String, latitude: String, longitude: String, perfectUseMapKit: Bool) { + if (mapType == MapType.apple && perfectUseMapKit) { let coordinate = CLLocationCoordinate2DMake(Double(latitude)!, Double(longitude)!) let region = MKCoordinateRegion(center: coordinate, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.02)) let placemark = MKPlacemark(coordinate: coordinate, addressDictionary: nil) @@ -105,16 +104,13 @@ private func showMarker(mapType: MapType, url: String, title: String, latitude: MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: region.span)] mapItem.name = title mapItem.openInMaps(launchOptions: options) - default: + } else { UIApplication.shared.open(URL(string:url)!, options: [:], completionHandler: nil) - } } -private func showDirections(mapType: MapType, url: String, destinationTitle: String?, destinationLatitude: String, destinationLongitude: String, originTitle: String?, originLatitude: String?, originLongitude: String?, directionsMode: String?) { - switch mapType { - case MapType.apple: - +private func showDirections(mapType: MapType, url: String, destinationTitle: String?, destinationLatitude: String, destinationLongitude: String, originTitle: String?, originLatitude: String?, originLongitude: String?, directionsMode: String?, perfectUseMapKit: Bool) { + if (mapType == MapType.apple && perfectUseMapKit) { let destinationMapItem = getMapItem(latitude: destinationLatitude, longitude: destinationLongitude); destinationMapItem.name = destinationTitle ?? "Destination" @@ -133,9 +129,8 @@ private func showDirections(mapType: MapType, url: String, destinationTitle: Str with: [originMapItem, destinationMapItem], launchOptions: [MKLaunchOptionsDirectionsModeKey: getDirectionsMode(directionsMode: directionsMode)] ) - default: + } else { UIApplication.shared.open(URL(string:url)!, options: [:], completionHandler: nil) - } } @@ -171,6 +166,7 @@ public class SwiftMapLauncherPlugin: NSObject, FlutterPlugin { let title = args["title"] as! String let latitude = args["latitude"] as! String let longitude = args["longitude"] as! String + let perfectUseMapKit = (args["perfectUseMapKit"] as? NSNumber)?.boolValue ?? true let map = getMapByRawMapType(type: mapType) if (!isMapAvailable(map: map)) { @@ -178,12 +174,20 @@ public class SwiftMapLauncherPlugin: NSObject, FlutterPlugin { return; } - showMarker(mapType: MapType(rawValue: mapType)!, url: url, title: title, latitude: latitude, longitude: longitude) + showMarker( + mapType: MapType(rawValue: mapType)!, + url: url, + title: title, + latitude: latitude, + longitude: longitude, + perfectUseMapKit: perfectUseMapKit + ) case "showDirections": let args = call.arguments as! NSDictionary let mapType = args["mapType"] as! String let url = args["url"] as! String + let perfectUseMapKit = (args["perfectUseMapKit"] as? NSNumber)?.boolValue ?? true let destinationTitle = args["destinationTitle"] as? String let destinationLatitude = args["destinationLatitude"] as! String @@ -210,7 +214,8 @@ public class SwiftMapLauncherPlugin: NSObject, FlutterPlugin { originTitle: originTitle, originLatitude: originLatitude, originLongitude: originLongitude, - directionsMode: directionsMode + directionsMode: directionsMode, + perfectUseMapKit: perfectUseMapKit ) case "isMapAvailable": diff --git a/lib/src/directions_url.dart b/lib/src/directions_url.dart index 589297f..e13777d 100644 --- a/lib/src/directions_url.dart +++ b/lib/src/directions_url.dart @@ -5,7 +5,7 @@ import 'package:map_launcher/src/utils.dart'; /// Returns a url that is used by [showDirections] String getMapDirectionsUrl({ required MapType mapType, - required Coords destination, + required Coords? destination, String? destinationTitle, Coords? origin, String? originTitle, @@ -14,30 +14,16 @@ String getMapDirectionsUrl({ Map? extraParams, }) { switch (mapType) { - case MapType.google: - return Utils.buildUrl( - url: 'https://www.google.com/maps/dir/', - queryParams: { - 'api': '1', - 'destination': '${destination.latitude},${destination.longitude}', - 'origin': Utils.nullOrValue( - origin, - '${origin?.latitude},${origin?.longitude}', - ), - 'waypoints': waypoints - ?.map((coords) => '${coords.latitude},${coords.longitude}') - .join('|'), - 'travelmode': Utils.enumToString(directionsMode), - ...(extraParams ?? {}), - }, - ); - case MapType.googleGo: + case MapType.google: + // https://developers.google.com/maps/documentation/urls/get-started#directions-action return Utils.buildUrl( url: 'https://www.google.com/maps/dir/', queryParams: { 'api': '1', - 'destination': '${destination.latitude},${destination.longitude}', + 'destination': destination != null + ? '${destination.latitude},${destination.longitude}' + : destinationTitle, 'origin': Utils.nullOrValue( origin, '${origin?.latitude},${origin?.longitude}', @@ -49,23 +35,32 @@ String getMapDirectionsUrl({ ...(extraParams ?? {}), }, ); - case MapType.apple: + // https://developer.apple.com/library/archive/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html + // https://itnext.io/apple-maps-url-schemes-e1d3ac7340af return Utils.buildUrl( - url: 'http://maps.apple.com/maps', + url: Platform.isIOS ? 'maps://' : 'http://maps.apple.com/maps', queryParams: { - 'daddr': '${destination.latitude},${destination.longitude}', + 'dirflg': Utils.getAppleDirectionsMode(directionsMode), + 'saddr': origin != null + ? '${origin.latitude},${origin.longitude}' + : originTitle, + 'daddr': destination != null + ? '${destination.latitude},${destination.longitude}' + : destinationTitle, ...(extraParams ?? {}), }, ); case MapType.amap: + // Android: https://lbs.amap.com/api/amap-mobile/guide/android/route + // iOS: https://lbs.amap.com/api/amap-mobile/guide/ios/route return Utils.buildUrl( url: Platform.isIOS ? 'iosamap://path' : 'amapuri://route/plan/', queryParams: { 'sourceApplication': 'applicationName', - 'dlat': '${destination.latitude}', - 'dlon': '${destination.longitude}', + 'dlat': destination?.latitude.toString(), + 'dlon': destination?.longitude.toString(), 'dname': destinationTitle, 'slat': Utils.nullOrValue(origin, '${origin?.latitude}'), 'slon': Utils.nullOrValue(origin, '${origin?.longitude}'), @@ -77,15 +72,20 @@ String getMapDirectionsUrl({ ); case MapType.baidu: + // Android: https://lbsyun.baidu.com/index.php?title=uri/api/android#:~:text=URL%E6%8E%A5%E5%8F%A3%EF%BC%9A-,baidumap%3A//map/direction,-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E + // iOS: https://lbsyun.baidu.com/index.php?title=uri/api/ios#:~:text=%E6%9C%8D%E5%8A%A1%E5%9C%B0%E5%9D%80-,baidumap%3A//map/direction,-//%20iOS%E6%9C%8D%E5%8A%A1%E5%9C%B0%E5%9D%80 + String? loc(Coords? coords, String? title) => + title != null && coords != null + ? 'name:$title|latlng:${coords.latitude},${coords.longitude}' + : coords != null + ? '${coords.latitude},${coords.longitude}' + : title; + return Utils.buildUrl( url: 'baidumap://map/direction', queryParams: { - 'destination': - 'name: ${destinationTitle ?? 'Destination'}|latlng:${destination.latitude},${destination.longitude}', - 'origin': Utils.nullOrValue( - origin, - 'name: ${originTitle ?? 'Origin'}|latlng:${origin?.latitude},${origin?.longitude}', - ), + 'destination': loc(destination, destinationTitle), + 'origin': loc(origin, originTitle), 'coord_type': 'gcj02', 'mode': Utils.getBaiduDirectionsMode(directionsMode), 'src': 'com.map_launcher', @@ -94,6 +94,7 @@ String getMapDirectionsUrl({ ); case MapType.waze: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'waze://', queryParams: { @@ -105,6 +106,7 @@ String getMapDirectionsUrl({ ); case MapType.citymapper: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl(url: 'citymapper://directions', queryParams: { 'endcoord': '${destination.latitude},${destination.longitude}', 'endname': destinationTitle, @@ -118,6 +120,7 @@ String getMapDirectionsUrl({ case MapType.osmand: case MapType.osmandplus: + destination ??= Coords.zero; // Not tested, fallback to zero. if (Platform.isIOS) { return Utils.buildUrl( url: 'osmandmaps://navigate', @@ -147,6 +150,7 @@ String getMapDirectionsUrl({ // 'type': Utils.getMapsMeDirectionsMode(directionsMode), // }, // ); + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'mapsme://map', queryParams: { @@ -158,6 +162,7 @@ String getMapDirectionsUrl({ ); case MapType.yandexMaps: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'yandexmaps://maps.yandex.com/', queryParams: { @@ -169,6 +174,7 @@ String getMapDirectionsUrl({ ); case MapType.yandexNavi: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'yandexnavi://build_route_on_map', queryParams: { @@ -180,6 +186,7 @@ String getMapDirectionsUrl({ ); case MapType.doubleGis: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'dgis://2gis.ru/routeSearch/rsType/${Utils.getDoubleGisDirectionsMode(directionsMode)}/${origin == null ? '' : 'from/${origin.longitude},${origin.latitude}/'}to/${destination.longitude},${destination.latitude}', @@ -189,19 +196,26 @@ String getMapDirectionsUrl({ ); case MapType.tencent: + // When destination is null, you need to manually click the input box to search. + // https://lbs.qq.com/webApi/uriV1/uriGuide/uriMobileRoute return Utils.buildUrl( url: 'qqmap://map/routeplan', queryParams: { 'from': originTitle, - 'fromcoord': '${origin?.latitude},${origin?.longitude}', + 'fromcoord': origin != null // + ? '${origin.latitude},${origin.longitude}' + : null, 'to': destinationTitle, - 'tocoord': '${destination.latitude},${destination.longitude}', + 'tocoord': destination != null + ? '${destination.latitude},${destination.longitude}' + : null, 'type': Utils.getTencentDirectionsMode(directionsMode), ...(extraParams ?? {}), }, ); case MapType.here: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl( url: 'https://share.here.com/r/${origin?.latitude},${origin?.longitude},$originTitle/${destination.latitude},${destination.longitude}', @@ -212,6 +226,7 @@ String getMapDirectionsUrl({ ); case MapType.petal: + destination ??= Coords.zero; // Not tested, fallback to zero. return Utils.buildUrl(url: 'petalmaps://route', queryParams: { 'daddr': '${destination.latitude},${destination.longitude} (${destinationTitle ?? 'Destination'})', @@ -224,6 +239,7 @@ String getMapDirectionsUrl({ }); case MapType.tomtomgo: + destination ??= Coords.zero; // Not tested, fallback to zero. if (Platform.isIOS) { return Utils.buildUrl( url: 'tomtomgo://x-callback-url/navigate', diff --git a/lib/src/map_launcher.dart b/lib/src/map_launcher.dart index 75d7720..02f420a 100644 --- a/lib/src/map_launcher.dart +++ b/lib/src/map_launcher.dart @@ -64,9 +64,20 @@ class MapLauncher { /// Opens map app specified in [mapType] /// and shows directions to [destination] + /// + /// [destination], the coordinates of the destination. When it is `null`, use + /// [destinationTitle] to search destination, currently only some maps support it. + /// + /// - [MapType.apple], supported + /// - [MapType.google], supported + /// - [MapType.googleGo], supported + /// - [MapType.amap], supported + /// - [MapType.baidu], supported + /// - [MapType.tencent], partially supported, you need to manually click the input box to search. + /// - others map not tested, fallback to [Coords.zero] static Future showDirections({ required MapType mapType, - required Coords destination, + required Coords? destination, String? destinationTitle, Coords? origin, String? originTitle, @@ -85,13 +96,14 @@ class MapLauncher { extraParams: extraParams, ); - final Map args = { + final Map args = { 'mapType': Utils.enumToString(mapType), 'url': Uri.encodeFull(url), + // On iOS, MapKit does not support destination being null, use `UIApplication.shared.open()` instead. + 'perfectUseMapKit': destination != null, 'destinationTitle': destinationTitle, - 'destinationLatitude': destination.latitude.toString(), - 'destinationLongitude': destination.longitude.toString(), - 'destinationtitle': destinationTitle, + 'destinationLatitude': (destination?.latitude ?? 0.0).toString(), + 'destinationLongitude': (destination?.longitude ?? 0.0).toString(), 'originLatitude': origin?.latitude.toString(), 'originLongitude': origin?.longitude.toString(), 'originTitle': originTitle, diff --git a/lib/src/models.dart b/lib/src/models.dart index 72d3c19..5d23cc3 100644 --- a/lib/src/models.dart +++ b/lib/src/models.dart @@ -32,10 +32,12 @@ enum DirectionsMode { /// Class that holds latitude and longitude coordinates class Coords { + static const zero = Coords(0.0, 0.0); + final double latitude; final double longitude; - Coords(this.latitude, this.longitude); + const Coords(this.latitude, this.longitude); } /// Class that holds all the information needed to launch a map @@ -85,7 +87,7 @@ class AvailableMap { /// Launches current map and shows directions to `destination` Future showDirections({ - required Coords destination, + required Coords? destination, String? destinationTitle, Coords? origin, String? originTitle, diff --git a/lib/src/utils.dart b/lib/src/utils.dart index c8911dd..06854af 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -140,4 +140,19 @@ class Utils { return 'd'; } } + + /// Returns [DirectionsMode] for [MapType.apple] + static String? getAppleDirectionsMode(DirectionsMode? directionsMode) { + switch (directionsMode) { + case DirectionsMode.driving: + return 'd'; + case DirectionsMode.walking: + return 'w'; + case DirectionsMode.transit: + return 'r'; + case DirectionsMode.bicycling: + case null: + return null; + } + } }