├── .gitattributes
├── .gitignore
├── README.md
├── analysis_options.yaml
├── fl_amap
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── settings.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ └── fl
│ │ │ └── amap
│ │ │ ├── AMapGeoFence.kt
│ │ │ ├── AMapLocation.kt
│ │ │ └── AMapPlugin.kt
│ │ └── res
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ └── mipmap-xxxhdpi
│ │ └── ic_launcher.png
├── example
│ ├── .gitignore
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── android
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── amap.jks
│ │ │ ├── build.gradle.kts
│ │ │ └── src
│ │ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── fl
│ │ │ │ │ │ └── amap
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── res
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── values-night
│ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ ├── build.gradle.kts
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ └── gradle-wrapper.properties
│ │ └── settings.gradle.kts
│ ├── ios
│ │ ├── .gitignore
│ │ ├── Flutter
│ │ │ ├── AppFrameworkInfo.plist
│ │ │ ├── Debug.xcconfig
│ │ │ └── Release.xcconfig
│ │ ├── Podfile
│ │ ├── Runner.xcodeproj
│ │ │ ├── project.pbxproj
│ │ │ └── xcshareddata
│ │ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ ├── Runner.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ └── Runner
│ │ │ ├── AppDelegate.swift
│ │ │ ├── Assets.xcassets
│ │ │ ├── AppIcon.appiconset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ └── LaunchImage.imageset
│ │ │ │ ├── Contents.json
│ │ │ │ ├── LaunchImage.png
│ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ └── README.md
│ │ │ ├── Base.lproj
│ │ │ ├── LaunchScreen.storyboard
│ │ │ └── Main.storyboard
│ │ │ ├── Info.plist
│ │ │ ├── Runner-Bridging-Header.h
│ │ │ └── Runner.entitlements
│ ├── lib
│ │ ├── main.dart
│ │ └── src
│ │ │ ├── coordinate_converter_page.dart
│ │ │ ├── geo_fence_page.dart
│ │ │ └── loaction_page.dart
│ └── pubspec.yaml
├── format.sh
├── ios
│ ├── .gitignore
│ ├── Classes
│ │ ├── AMapGeoFence.swift
│ │ ├── AMapLocation.swift
│ │ └── AMapPlugin.swift
│ ├── Resources
│ │ └── PrivacyInfo.xcprivacy
│ └── fl_amap.podspec
├── lib
│ ├── fl_amap.dart
│ └── src
│ │ ├── amap_geo_fence.dart
│ │ ├── amap_location.dart
│ │ └── enum.dart
└── pubspec.yaml
├── fl_amap_map
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── analysis_options.yaml
├── android
│ ├── .gitignore
│ ├── build.gradle
│ ├── consumer-rules.pro
│ ├── settings.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ └── kotlin
│ │ └── fl
│ │ └── amap
│ │ └── map
│ │ ├── AMapMapPlugin.kt
│ │ ├── Extension.kt
│ │ └── map
│ │ ├── AMapPlatformViewFactory.kt
│ │ ├── AMapView.kt
│ │ └── AMapViewListener.kt
├── example
│ ├── .gitignore
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── android
│ │ ├── .gitignore
│ │ ├── app
│ │ │ ├── amap.jks
│ │ │ ├── build.gradle.kts
│ │ │ └── src
│ │ │ │ ├── debug
│ │ │ │ └── AndroidManifest.xml
│ │ │ │ ├── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── kotlin
│ │ │ │ │ └── com
│ │ │ │ │ │ └── fl
│ │ │ │ │ │ └── amap
│ │ │ │ │ │ └── example
│ │ │ │ │ │ └── MainActivity.kt
│ │ │ │ └── res
│ │ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ │ ├── values-night
│ │ │ │ │ └── styles.xml
│ │ │ │ │ └── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── profile
│ │ │ │ └── AndroidManifest.xml
│ │ ├── build.gradle.kts
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ └── gradle-wrapper.properties
│ │ └── settings.gradle.kts
│ ├── ios
│ │ ├── .gitignore
│ │ ├── Flutter
│ │ │ ├── AppFrameworkInfo.plist
│ │ │ ├── Debug.xcconfig
│ │ │ └── Release.xcconfig
│ │ ├── Podfile
│ │ ├── Runner.xcodeproj
│ │ │ ├── project.pbxproj
│ │ │ └── xcshareddata
│ │ │ │ └── xcschemes
│ │ │ │ └── Runner.xcscheme
│ │ ├── Runner.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ └── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ ├── Runner
│ │ │ ├── AppDelegate.swift
│ │ │ ├── Assets.xcassets
│ │ │ │ ├── AppIcon.appiconset
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ │ │ ├── Icon-App-20x20@1x.png
│ │ │ │ │ ├── Icon-App-20x20@2x.png
│ │ │ │ │ ├── Icon-App-20x20@3x.png
│ │ │ │ │ ├── Icon-App-29x29@1x.png
│ │ │ │ │ ├── Icon-App-29x29@2x.png
│ │ │ │ │ ├── Icon-App-29x29@3x.png
│ │ │ │ │ ├── Icon-App-40x40@1x.png
│ │ │ │ │ ├── Icon-App-40x40@2x.png
│ │ │ │ │ ├── Icon-App-40x40@3x.png
│ │ │ │ │ ├── Icon-App-60x60@2x.png
│ │ │ │ │ ├── Icon-App-60x60@3x.png
│ │ │ │ │ ├── Icon-App-76x76@1x.png
│ │ │ │ │ ├── Icon-App-76x76@2x.png
│ │ │ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ │ │ └── LaunchImage.imageset
│ │ │ │ │ ├── Contents.json
│ │ │ │ │ ├── LaunchImage.png
│ │ │ │ │ ├── LaunchImage@2x.png
│ │ │ │ │ ├── LaunchImage@3x.png
│ │ │ │ │ └── README.md
│ │ │ ├── Base.lproj
│ │ │ │ ├── LaunchScreen.storyboard
│ │ │ │ └── Main.storyboard
│ │ │ ├── Info.plist
│ │ │ └── Runner-Bridging-Header.h
│ │ └── RunnerTests
│ │ │ └── RunnerTests.swift
│ ├── lib
│ │ ├── main.dart
│ │ └── src
│ │ │ └── map_view_page.dart
│ └── pubspec.yaml
├── ios
│ ├── .gitignore
│ ├── Classes
│ │ ├── AMapPlugin.swift
│ │ ├── Extension.swift
│ │ └── map
│ │ │ ├── AMapPlatformViewFactory.swift
│ │ │ ├── AMapView.swift
│ │ │ └── AMapViewDelegate.swift
│ ├── Resources
│ │ └── PrivacyInfo.xcprivacy
│ └── fl_amap_map.podspec
├── lib
│ ├── fl_amap_map.dart
│ └── src
│ │ ├── amap_view.dart
│ │ ├── controller.dart
│ │ ├── controller_for_android.dart
│ │ ├── controller_for_ios.dart
│ │ ├── enum.dart
│ │ └── model.dart
└── pubspec.yaml
├── format.sh
└── pubspec.yaml
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.dart linguist-language=Dart
2 | *.h linguist-language=Dart
3 | *.m linguist-language=Dart
4 | *.html linguist-language=Dart
5 | *.xml linguist-language=Dart
6 | *.xml linguist-language=Dart
7 | *.java linguist-language=Dart
8 | *.md linguist-language=Dart
9 | *.cmd linguist-language=Dart
10 | *.dart linguist-language=Dart
11 | *.swift linguist-language=Dart
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 |
7 | # Xcode
8 | #
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 |
28 | # Android/IntelliJ
29 | #
30 | build/
31 | .idea
32 | .gradle
33 | local.properties
34 | *.iml
35 | *.lock
36 | *.packages
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | /.dart_tool/
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 高德地图
2 |
3 | ### [fl_amap](https://github.com/Wayaer/fl_amap/tree/main/fl_amap)
4 |
5 | - 高德定位 地理围栏
6 |
7 | ### [fl_amap_amap](https://github.com/Wayaer/fl_amap/tree/main/fl_amap_map)
8 |
9 | - 高德地图(...)
10 |
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/fl_amap/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 |
7 | # Xcode
8 | #
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 |
28 | # Android/IntelliJ
29 | #
30 | build/
31 | .idea
32 | .gradle
33 | local.properties
34 | *.iml
35 | *.lock
36 | *.packages
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | /.dart_tool/
43 |
--------------------------------------------------------------------------------
/fl_amap/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 3.4.3
2 |
3 | * 修复在 ios 上的错误
4 |
5 | ## 3.4.2
6 |
7 | * JDK to 17
8 | * `setAMapKey` 改为 ` FlAMap().setAMapKey()`
9 |
10 | ## 3.4.0
11 |
12 | * 迁移至 3.27
13 |
14 | ## 3.3.0
15 |
16 | * 高德定位初始化添加默认配置
17 |
18 | ## 3.2.0
19 |
20 | * 支持其他地图经纬度转换 `coordinateConverter()`
21 | * 支持校验是否为有效经纬度 `isAMapDataAvailable()`
22 | * 支持坐标点距离计算(仅支持android)`calculateLineDistance()`
23 |
24 | ## 3.1.0
25 |
26 | * 更新 android sdk版本
27 |
28 | ## 3.0.1
29 |
30 | * 修改ios默认定位精度为十米级,和上个版本一致
31 | * 修改ios默认获取逆地理位置
32 |
33 | ## 3.0.0
34 |
35 | * 设置定位参数,返回定位信息均添加详细文档说明,且数据完整
36 | * 区分`android`和`ios`
37 | 的返回定位信息,返回数据均有不同,且数据完整,`AMapLocation`、`AMapLocationForIOS`、
38 | `AMapLocationForAndroid`
39 | * 区分`android`和`ios`
40 | 的定位参数配置,可进行多次配置更新,`AMapLocationOptionForIOS`、`AMapLocationOptionForAndroid`
41 | * `android`支持设置前台任务服务,保证后台定位常驻,使用`enableBackgroundLocation`
42 | 和`disableBackgroundLocation`开启和关闭
43 | * `ios`添加 `headingAvailable`(设备是否支持方向识别)、`startUpdatingHeading`(
44 | 开始获取设备朝向)、`stopUpdatingHeading`(停止获取设备朝向)、`dismissHeadingCalibrationDisplay`(
45 | 停止设备朝向校准显示)
46 |
47 | ## 2.5.3
48 |
49 | * Upgrade the Android AMap locating SDK
50 | * Add `namespace` in Android
51 |
52 | ## 2.5.1
53 |
54 | * Fixed issues on ios
55 |
56 | ## 2.5.0
57 |
58 | * Modify some nouns
59 |
60 | ## 2.3.1+1
61 |
62 | * Upgrade gradle version
63 |
64 | ## 2.1.0
65 |
66 | * Upgrade the Android AMap locating SDK
67 | * Compatible with flutter 3.0.0
68 |
69 | ## 2.0.0
70 |
71 | * Upgrade the Android AMap locating SDK to 5.6.0
72 | * To upgrade the ios AMap SDK to 2.8.0, run the `pod update` command to update the SDK to 2.8.0
73 | * Add SDK compliance use scheme [AMap doc](https://lbs.amap.com/news/sdkhgsy)
74 |
75 | ## 1.2.0
76 |
77 | * Change IOS OC to swift
78 | * Simplify geofencing services
79 | * Fix bugs
80 |
81 | ## 1.1.0
82 |
83 | * Remove instance , direct initialization
84 | * Update gradle version
85 | * Update kotlin version
86 |
87 | ## 1.0.0
88 |
89 | * Add Singleton Pattern
90 | * Upgrade Android Gradle
91 | * Upgrade Android AMap SDK version
92 |
93 | ## 0.2.1
94 |
95 | * Upgrade Android AMap SDK version
96 | * Add platform restrictions
97 |
98 | ## 0.2.0
99 |
100 | * Add AMapGeoFence
101 |
102 | ## 0.1.3
103 |
104 | * Update Android com.android.tools.build:gradle version
105 | * Replace jcenter() to mavenCentral()
106 |
107 | ## 0.1.2
108 |
109 | * Add Android proguard rules
110 |
111 | ## 0.1.1
112 |
113 | * Normative approach
114 | * Fix bugs
115 | * Modify APIs
116 | * Android add consumer-rules.pro
117 |
118 | ## 0.0.6
119 |
120 | * Example update to 2.12.1
121 | * Update dart version to 2.12.1
122 |
123 | ## 0.0.3
124 |
125 | * Support single location
126 | * Support location monitoring
--------------------------------------------------------------------------------
/fl_amap/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Wayaer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/fl_amap/README.md:
--------------------------------------------------------------------------------
1 | 高德地图定位flutter组件。
2 |
3 | 目前实现获取定位和监听定位功能。
4 |
5 | 1、申请一个key
6 | http://lbs.amap.com/api/ios-sdk/guide/create-project/get-key
7 |
8 | 直接在dart文件中设置key
9 |
10 | * 权限申请需要额外使用 [permission_handler](https://pub.dev/packages/permission_handler) 或者其他的第三方包
11 |
12 | # ios
13 |
14 | 1. 在info.plist中增加:
15 |
16 | ```
17 | NSLocationWhenInUseUsageDescription
18 | 要用定位
19 | ```
20 |
21 | 如果ios定位没有返回逆地理信息,添加一下内容
22 |
23 | ```
24 | NSAppTransportSecurity
25 |
26 | NSAllowsArbitraryLoads
27 |
28 | NSAllowsArbitraryLoadsForMedia
29 |
30 | NSAllowsArbitraryLoadsInWebContent
31 |
32 | /// 解决ios HTTP 警告,需要添加的
33 | NSExceptionDomains
34 |
35 | restios.amap.com/key>
36 |
37 | NSExceptionAllowsInsecureHTTPLoads
38 |
39 | NSIncludesSubdomains
40 |
41 | NSExceptionMinimumTLSVersion
42 | TLSv1.2
43 |
44 |
45 |
46 | ```
47 |
48 | 2. iOS 9及以上版本使用后台定位功能, 需要保证"Background Modes"中的"Location updates"处于选中状态
49 |
50 | 3.使用地理围栏
51 |
52 | iOS14及以上版本使用地理围栏功能,需要在plist中配置NSLocationTemporaryUsageDescriptionDictionary字典描述,
53 | 且添加自定义Key描述地理围栏的使用场景,此描述会在申请临时精确定位权限的弹窗中展示。
54 | 该回调触发条件:拥有定位权限,但是没有获得精确定位权限的情况下,会触发该回调。此方法实现调用申请临时精确定位权限API即可;
55 |
56 | ** 需要注意,在iOS9及之后版本的系统中,如果您希望程序在后台持续检测围栏触发行为,需要保证manager的
57 | allowsBackgroundLocationUpdates 为 YES,
58 | 设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
59 |
60 | # android
61 |
62 | - `android/src/main/AndroidManifest.xml` 添加以下内容 具体参考 `example`
63 |
64 | ```xml
65 |
66 |
67 |
68 | /// 需要配置的
69 |
70 |
71 |
72 |
73 | ```
74 |
75 | ## 开始使用
76 |
77 | ## 高德定位功能
78 |
79 | - 设置key
80 |
81 | ```dart
82 |
83 | Future setAMapKey() async {
84 | final bool key = await FlAMap().setAMapKey(
85 | iosKey: 'ios key',
86 | androidKey: 'android key');
87 |
88 | if (key != null && key) print('高德地图ApiKey设置成功');
89 | }
90 |
91 | ```
92 |
93 | - 初始化定位参数
94 |
95 | ```dart
96 | Future initialize() async {
97 | /// 获取权限
98 | if (getPermissions) return;
99 |
100 | /// 初始化AMap
101 | final bool data = await FlAMapLocation().initialize();
102 | if (data) {
103 | show('初始化成功');
104 | }
105 | }
106 |
107 | ```
108 |
109 | - 单次获取定位
110 |
111 | ```dart
112 | Future getLocation() async {
113 | /// 务必先初始化 并获取权限
114 | if (getPermissions) return;
115 | AMapLocation location = await FlAMapLocation().getLocation();
116 | if (isAndroid) {
117 | AMapLocation is AMapLocationForAndroid;
118 | }
119 | if (isIOS) {
120 | AMapLocation is AMapLocationForIOS;
121 | }
122 | }
123 |
124 | ```
125 |
126 | - 开启定位变化监听
127 |
128 | ```dart
129 | Future startLocationChange() async {
130 | /// 务必先初始化 并获取权限
131 | FlAMapLocation().addListener(
132 |
133 | /// 连续定位回调 android & ios 均支持
134 | onLocationChanged: (AMapLocation? location) {
135 | locationState.value = location;
136 | },
137 |
138 | /// ios连续定位 错误监听 仅在ios中生效
139 | onLocationFailed: (AMapLocationError? error) {
140 | text.value = 'ios 连续定位错误:${error?.toMap()}';
141 | },
142 |
143 | /// 监听设备朝向变化 仅在ios中生效
144 | onHeadingChanged: (AMapLocationHeading? heading) {
145 | headingState.value = heading;
146 | },
147 |
148 | /// 监听权限状态变化 仅在ios中生效
149 | onAuthorizationChanged: (int? status) {
150 | text.value = 'ios 权限状态变化:$status';
151 | });
152 | }
153 |
154 | ```
155 |
156 | - 关闭定位变化监听
157 |
158 | ```dart
159 | void stopLocation() {
160 | FlAMapLocation().stopLocation();
161 | }
162 | ```
163 |
164 | - 关闭定位服务
165 |
166 | ```dart
167 | void dispose() {
168 | FlAMapLocation().dispose();
169 | }
170 | ```
171 |
172 | - 开启前台任务 仅支持android 8.0 +
173 | 如需开启前台任务需要添加以下配置 至 `android/src/main/AndroidManifest.xml` 具体参考 `example`
174 |
175 | ```xml
176 |
177 |
178 | /// 需要添加的权限
179 |
180 |
181 | /// 需要配置的服务
182 |
184 |
185 |
186 | ```
187 |
188 | ```dart
189 |
190 | void enableBackgroundLocation() {
191 | FlAMapLocation().enableBackgroundLocation(
192 | AMapNotificationForAndroid(
193 | notificationId: 999,
194 | title: '我在定位',
195 | content: '我正在定位',
196 | channelId: 'channelId',
197 | channelName: 'name',
198 | lightColor: Colors.red));
199 | }
200 | ```
201 |
202 | - 关闭前台任务 仅支持android
203 |
204 | ```dart
205 | void disableBackgroundLocation() {
206 | FlAMapLocation().disableBackgroundLocation();
207 | }
208 | ```
209 |
210 | - 设备是否支持方向识别 仅支持ios
211 |
212 | ```dart
213 | void headingAvailable() async {
214 | final result = await location.headingAvailable();
215 | }
216 | ```
217 |
218 | - 开始获取设备朝向 仅支持ios
219 |
220 | ```dart
221 | void startUpdatingHeading() async {
222 | await location.startUpdatingHeading();
223 | }
224 | ```
225 |
226 | - 停止获取设备朝向 仅支持ios
227 |
228 | ```dart
229 | void stopUpdatingHeading() async {
230 | await location.stopUpdatingHeading();
231 | }
232 | ```
233 |
234 | - 停止设备朝向校准显示 仅支持ios
235 |
236 | ```dart
237 | void dismissHeadingCalibrationDisplay() async {
238 | await location.dismissHeadingCalibrationDisplay();
239 | }
240 | ```
241 |
242 | ## 高德地理围栏功能
243 |
244 | - 初始化地理围栏
245 |
246 | ```dart
247 |
248 | Future get initialize async {
249 | final bool data = await FlAMapGeoFence().initialize(GeoFenceActivateAction.stayed);
250 | if (data) {
251 | show('初始化地理围栏:$data');
252 | }
253 | }
254 |
255 | ```
256 |
257 | - 关闭围栏服务
258 |
259 | ```dart
260 | void dispose() {
261 | super.dispose();
262 | FlAMapGeoFence().dispose();
263 | }
264 | ```
265 |
266 | - 根据POI添加围栏
267 |
268 | ```dart
269 | Future addPOI() async {
270 | final AMapPoiModel model = AMapPoiModel(
271 | keyword: '首开广场',
272 | poiType: '写字楼',
273 | city: '北京',
274 | size: 1,
275 | customId: '000FATE23(考勤打卡)');
276 | final bool state = await FlAMapGeoFence().addPOI(model);
277 | }
278 | ```
279 |
280 | - 根据坐标关键字添加围栏
281 |
282 | ```dart
283 | Future addLatLng() async {
284 | final LatLng latLng = LatLng(39.933921, 116.372927);
285 | final AMapLatLngModel model = AMapLatLngModel(
286 | latLng: latLng,
287 | keyword: '首开广场',
288 | poiType: '',
289 | customId: '000FATE23(考勤打卡)',
290 | size: 20,
291 | aroundRadius: 1000);
292 | final bool state = await FlAMapGeoFence().addLatLng(model);
293 | }
294 | ```
295 |
296 | - 添加行政区划围栏
297 |
298 | ```dart
299 | Future addDistrict() async {
300 | final bool state = await FlAMapGeoFence().addDistrict(
301 | keyword: '海淀区', customId: '000FATE23(考勤打卡)');
302 | }
303 | ```
304 |
305 | - 添加圆形围栏
306 |
307 | ```dart
308 | Future addCircle() async {
309 | final LatLng latLng = LatLng(30.651411, 103.998638);
310 | final bool state = await FlAMapGeoFence().addCircle(
311 | latLng: latLng,
312 | radius: 10,
313 | customId: '000FATE23(考勤打卡)');
314 | }
315 | ```
316 |
317 | - 添加多边形围栏
318 |
319 | ```dart
320 | Future addCustom() async {
321 | final bool state = await FlAMapGeoFence().addCustom(latLngs: [
322 | LatLng(39.933921, 116.372927),
323 | LatLng(39.907261, 116.376532),
324 | LatLng(39.900611, 116.418161),
325 | LatLng(39.941949, 116.435497),
326 | ], customId: '000FATE23(考勤打卡)');
327 | }
328 | ```
329 |
330 | - 获取所有围栏信息
331 |
332 | ```dart
333 | Future getAll() async {
334 | /// 传入 customID 获取指定标识的围栏信息 仅支持ios
335 | final List data = await FlAMapGeoFence().getAll();
336 | }
337 | ```
338 |
339 | - 删除地理围栏
340 |
341 | ```dart
342 | Future remove() async {
343 | /// 传入 customID 删除指定标识的围栏
344 | /// 不传 删除所有围栏
345 | final bool state = await FlAMapGeoFence().remove();
346 | }
347 | ```
348 |
349 | - 暂停监听围栏
350 |
351 | ```dart
352 | Future pause() async {
353 | /// 传入 customID 暂停指定标识的围栏
354 | /// 不传 暂停所有围栏
355 | final bool state = await FlAMapGeoFence().pause();
356 | }
357 | ```
358 |
359 | - 开始监听围栏
360 |
361 | ```dart
362 | Future start() async {
363 | /// 传入 customID 开始指定标识的围栏
364 | /// 不传 开始所有围栏
365 | final bool state = await FlAMapGeoFence().start();
366 | }
367 | ```
--------------------------------------------------------------------------------
/fl_amap/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/fl_amap/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/fl_amap/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'fl.amap'
2 | version '1.0'
3 |
4 | buildscript {
5 | repositories {
6 | google()
7 | mavenCentral()
8 | }
9 |
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:8.5.2'
12 | }
13 | }
14 |
15 | rootProject.allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | }
20 | }
21 |
22 | apply plugin: 'com.android.library'
23 | apply plugin: 'kotlin-android'
24 |
25 | android {
26 | compileSdk = 34
27 |
28 | if (project.android.hasProperty("namespace")) {
29 | namespace 'fl.amap'
30 | }
31 |
32 | compileOptions {
33 | sourceCompatibility = JavaVersion.VERSION_17
34 | targetCompatibility = JavaVersion.VERSION_17
35 | }
36 |
37 | kotlinOptions {
38 | jvmTarget = JavaVersion.VERSION_17.toString()
39 | }
40 |
41 | sourceSets {
42 | main.java.srcDirs += 'src/main/kotlin'
43 | }
44 |
45 | defaultConfig {
46 | minSdk = 21
47 | consumerProguardFiles 'consumer-rules.pro'
48 | }
49 |
50 | packagingOptions {
51 | merge 'AndroidManifest.xml'
52 | merge 'R.txt'
53 | merge 'classes.jar'
54 | merge 'proguard.txt'
55 | }
56 |
57 | dependencies {
58 | api 'com.amap.api:location:6.4.9'
59 | }
60 | }
--------------------------------------------------------------------------------
/fl_amap/android/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class com.amap.api.location.**{*;}
2 | -keep class com.amap.api.fence.**{*;}
3 | -keep class com.autonavi.aps.amapapi.model.**{*;}
4 | -keep class com.loc.**{*;}
5 |
--------------------------------------------------------------------------------
/fl_amap/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'fl_amap'
2 |
--------------------------------------------------------------------------------
/fl_amap/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/fl_amap/android/src/main/kotlin/fl/amap/AMapPlugin.kt:
--------------------------------------------------------------------------------
1 | package fl.amap
2 |
3 | import io.flutter.embedding.engine.plugins.FlutterPlugin
4 | import io.flutter.plugin.common.MethodCall
5 | import io.flutter.plugin.common.MethodChannel
6 |
7 |
8 | class AMapPlugin : FlutterPlugin {
9 | private var location: AMapLocation? = null
10 | private var geoFence: AMapGeoFence? = null
11 |
12 | override fun onAttachedToEngine(plugin: FlutterPlugin.FlutterPluginBinding) {
13 | location = AMapLocation(plugin)
14 | geoFence = AMapGeoFence(plugin)
15 | }
16 |
17 |
18 | override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
19 | location?.detached()
20 | geoFence?.detached()
21 | }
22 |
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/fl_amap/android/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/android/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/android/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/android/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/android/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/android/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/android/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/android/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | .lock
12 | .iml
13 | .metadata
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Web related
38 | lib/generated_plugin_registrant.dart
39 |
40 | # Symbolication related
41 | app.*.symbols
42 |
43 | # Obfuscation related
44 | app.*.map.json
45 |
46 | # Android Studio will place build artifacts here
47 | /android/app/debug
48 | /android/app/profile
49 | /android/app/release
50 |
--------------------------------------------------------------------------------
/fl_amap/example/README.md:
--------------------------------------------------------------------------------
1 | # example
--------------------------------------------------------------------------------
/fl_amap/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/fl_amap/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | .cxx
13 | .kotlin
--------------------------------------------------------------------------------
/fl_amap/example/android/app/amap.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/amap.jks
--------------------------------------------------------------------------------
/fl_amap/example/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("kotlin-android")
4 | id("dev.flutter.flutter-gradle-plugin")
5 | }
6 |
7 | android {
8 | namespace = "com.fl.amap.example"
9 | compileSdk = flutter.compileSdkVersion
10 |
11 | compileOptions {
12 | sourceCompatibility = JavaVersion.VERSION_21
13 | targetCompatibility = JavaVersion.VERSION_21
14 | }
15 |
16 | kotlinOptions {
17 | jvmTarget = JavaVersion.VERSION_21.toString()
18 | }
19 |
20 | defaultConfig {
21 | applicationId = "com.fl.amap.example"
22 | minSdk = flutter.minSdkVersion
23 | targetSdk = flutter.targetSdkVersion
24 | versionCode = flutter.versionCode
25 | versionName = flutter.versionName
26 | }
27 |
28 | signingConfigs {
29 | create("release") {
30 | storeFile = file("amap.jks")
31 | storePassword = "amap123"
32 | keyAlias = "amap"
33 | keyPassword = "amap123"
34 | }
35 | }
36 |
37 | buildTypes {
38 | getByName("debug") {
39 | signingConfig = signingConfigs.getByName("release")
40 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "consumer-rules.pro")
41 | }
42 | getByName("release") {
43 | signingConfig = signingConfigs.getByName("release")
44 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "consumer-rules.pro")
45 | }
46 | }
47 |
48 | }
49 |
50 | flutter {
51 | source = "../.."
52 | }
53 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
37 |
42 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/kotlin/com/fl/amap/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.fl.amap.example
2 |
3 | import androidx.annotation.NonNull
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/fl_amap/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fl_amap/example/android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
9 | rootProject.layout.buildDirectory.value(newBuildDir)
10 |
11 | subprojects {
12 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
13 | project.layout.buildDirectory.value(newSubprojectBuildDir)
14 | }
15 | subprojects {
16 | project.evaluationDependsOn(":app")
17 | }
18 |
19 | tasks.register("clean") {
20 | delete(rootProject.layout.buildDirectory)
21 | }
22 |
--------------------------------------------------------------------------------
/fl_amap/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/fl_amap/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
6 |
--------------------------------------------------------------------------------
/fl_amap/example/android/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | val flutterSdkPath = run {
3 | val properties = java.util.Properties()
4 | file("local.properties").inputStream().use { properties.load(it) }
5 | val flutterSdkPath = properties.getProperty("flutter.sdk")
6 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
7 | flutterSdkPath
8 | }
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id("dev.flutter.flutter-plugin-loader") version "1.0.0"
21 | id("com.android.application") version "8.7.0" apply false
22 | id("org.jetbrains.kotlin.android") version "2.0.20" apply false
23 | }
24 |
25 | include(":app")
26 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '13.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | end
36 |
37 | post_install do |installer|
38 | installer.pods_project.targets.each do |target|
39 | flutter_additional_ios_build_settings(target)
40 | # Start of the permission_handler configuration
41 | target.build_configurations.each do |config|
42 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
43 | '$(inherited)',
44 |
45 | ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
46 | 'PERMISSION_LOCATION=1',
47 | ]
48 | end
49 | # End of the permission_handler configuration
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @main
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | FlAMap
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(FLUTTER_BUILD_NAME)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(FLUTTER_BUILD_NUMBER)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSAllowsArbitraryLoadsForMedia
32 |
33 | NSAllowsArbitraryLoadsInWebContent
34 |
35 | NSExceptionDomains
36 |
37 | restios.amap.com
38 |
39 | NSExceptionAllowsInsecureHTTPLoads
40 |
41 | NSExceptionMinimumTLSVersion
42 | TLSv1.2
43 | NSIncludesSubdomains
44 |
45 |
46 |
47 |
48 | NSLocationAlwaysAndWhenInUseUsageDescription
49 | 获取定位
50 | NSLocationAlwaysUsageDescription
51 | 获取定位
52 | NSLocationWhenInUseUsageDescription
53 | 获取定位
54 | UIApplicationSupportsIndirectInputEvents
55 |
56 | UIBackgroundModes
57 |
58 | fetch
59 | location
60 | processing
61 | remote-notification
62 |
63 | UILaunchStoryboardName
64 | LaunchScreen
65 | UIMainStoryboardFile
66 | Main
67 | UISupportedInterfaceOrientations
68 |
69 | UIInterfaceOrientationPortrait
70 |
71 | UISupportedInterfaceOrientations~ipad
72 |
73 | UIInterfaceOrientationPortrait
74 | UIInterfaceOrientationPortraitUpsideDown
75 | UIInterfaceOrientationLandscapeLeft
76 | UIInterfaceOrientationLandscapeRight
77 |
78 | UIViewControllerBasedStatusBarAppearance
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/fl_amap/example/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.developer.networking.wifi-info
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fl_amap/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/src/coordinate_converter_page.dart';
2 | import 'package:example/src/geo_fence_page.dart';
3 | import 'package:example/src/loaction_page.dart';
4 | import 'package:fl_amap/fl_amap.dart';
5 | import 'package:fl_extended/fl_extended.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:permission_handler/permission_handler.dart';
8 |
9 | void main() {
10 | WidgetsFlutterBinding.ensureInitialized();
11 | runApp(MaterialApp(
12 | navigatorKey: FlExtended().navigatorKey,
13 | scaffoldMessengerKey: FlExtended().scaffoldMessengerKey,
14 | debugShowCheckedModeBanner: false,
15 | title: 'FlAMap',
16 | theme: ThemeData.light(),
17 | darkTheme: ThemeData.dark(),
18 | home: Scaffold(
19 | appBar: AppBar(title: const Text('高德定位')), body: const App())));
20 | }
21 |
22 | class App extends StatelessWidget {
23 | const App({super.key});
24 |
25 | @override
26 | Widget build(BuildContext context) {
27 | bool isInit = false;
28 | return Universal(
29 | width: double.infinity,
30 | mainAxisAlignment: MainAxisAlignment.center,
31 | crossAxisAlignment: CrossAxisAlignment.center,
32 | children: [
33 | ElevatedText(
34 | onPressed: () async {
35 | isInit = await FlAMap().setAMapKey(
36 | iosKey: '7d3261c06027bdc87aca547c99ad5b2f',
37 | // iosKey: 'e0e98395277890e48caa0c4bed423ead',
38 | androidKey: '77418e726d0eefc0ac79a8619b5f4d97',
39 | isAgree: true,
40 | isContains: true,
41 | isShow: true);
42 | showToast('高德地图ApiKey设置$isInit');
43 | },
44 | text: '设置高德key'),
45 | ElevatedText(
46 | onPressed: () {
47 | if (!isInit) {
48 | showToast('请先设置高德key');
49 | return;
50 | }
51 | push(const AMapLocationPage());
52 | },
53 | text: '高德定位功能'),
54 | ElevatedText(
55 | onPressed: () {
56 | if (!isInit) {
57 | showToast('请先设置高德key');
58 | return;
59 | }
60 | push(const AMapGeoFencePage());
61 | },
62 | text: '高德地理围栏功能'),
63 | ElevatedText(
64 | onPressed: () {
65 | push(const CoordinateConverterPage());
66 | },
67 | text: '坐标转换器'),
68 | ]);
69 | }
70 | }
71 |
72 | class ElevatedText extends StatelessWidget {
73 | const ElevatedText({super.key, required this.text, required this.onPressed});
74 |
75 | final String text;
76 | final VoidCallback onPressed;
77 |
78 | @override
79 | Widget build(BuildContext context) =>
80 | ElevatedButton(onPressed: onPressed, child: Text(text));
81 | }
82 |
83 | Future getPermission(Permission permission) async {
84 | final PermissionStatus status = await permission.request();
85 | if (!status.isGranted) {
86 | await openAppSettings();
87 | return await permission.request().isGranted;
88 | }
89 | return status.isGranted;
90 | }
91 |
--------------------------------------------------------------------------------
/fl_amap/example/lib/src/coordinate_converter_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/main.dart';
2 | import 'package:fl_amap/fl_amap.dart';
3 | import 'package:fl_extended/fl_extended.dart';
4 | import 'package:flutter/material.dart';
5 |
6 | class CoordinateConverterPage extends StatefulWidget {
7 | const CoordinateConverterPage({super.key});
8 |
9 | @override
10 | State createState() =>
11 | _CoordinateConverterPageState();
12 | }
13 |
14 | class _CoordinateConverterPageState extends State {
15 | LatLng? otherLatLng;
16 |
17 | @override
18 | Widget build(BuildContext context) {
19 | return Scaffold(
20 | appBar: AppBar(title: const Text('高德地理围栏')),
21 | body: Padding(
22 | padding: const EdgeInsets.all(12.0),
23 | child: Column(children: children),
24 | ));
25 | }
26 |
27 | TextEditingController latitudeController =
28 | TextEditingController(text: '39.950842');
29 | TextEditingController longitudeController =
30 | TextEditingController(text: '116.360072');
31 |
32 | CoordType coordType = CoordType.baidu;
33 |
34 | List get children => [
35 | Row(children: [
36 | TextField(
37 | controller: longitudeController,
38 | decoration: InputDecoration(hintText: 'longitude'))
39 | .expanded,
40 | 20.widthBox,
41 | TextField(
42 | controller: latitudeController,
43 | decoration: InputDecoration(hintText: 'latitude'),
44 | ).expanded,
45 | ]),
46 | 20.heightBox,
47 | PopupMenuButton(
48 | initialValue: coordType,
49 | onSelected: (value) {
50 | coordType = value;
51 | },
52 | child: Universal(
53 | mainAxisSize: MainAxisSize.min,
54 | direction: Axis.horizontal,
55 | padding: EdgeInsets.symmetric(vertical: 10),
56 | children: [
57 | Text('转换类型:${coordType.name}'),
58 | 10.widthBox,
59 | Icon(Icons.arrow_circle_down_rounded)
60 | ]),
61 | itemBuilder: (_) => CoordType.values
62 | .builder((e) => PopupMenuItem(value: e, child: Text(e.name)))),
63 | ElevatedText(text: '转换', onPressed: convert),
64 | if (otherLatLng != null)
65 | Padding(
66 | padding: const EdgeInsets.all(8.0),
67 | child: Text('转换后的坐标:\n${otherLatLng?.toMap()}',
68 | textAlign: TextAlign.center)),
69 | ];
70 |
71 | convert() async {
72 | final latitude = double.tryParse(latitudeController.text);
73 | final longitude = double.tryParse(longitudeController.text);
74 | if (latitude == null || longitude == null) {
75 | showToast('请输入正确的经纬度');
76 | return;
77 | }
78 | final result = await FlAMapLocation()
79 | .coordinateConverter(LatLng(latitude, longitude), coordType);
80 | if (result == null) {
81 | showToast('转换失败');
82 | return;
83 | }
84 | switch (result.code) {
85 | case null:
86 | break;
87 | case CoordinateConverterResultCode.success:
88 | if (result.latLng != null) {
89 | otherLatLng = result.latLng;
90 | setState(() {});
91 | }
92 | break;
93 | case CoordinateConverterResultCode.exception:
94 | if (result.message != null) {
95 | showToast(result.message!);
96 | }
97 | break;
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/fl_amap/example/lib/src/geo_fence_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/main.dart';
2 | import 'package:fl_amap/fl_amap.dart';
3 | import 'package:fl_dio/fl_dio.dart';
4 | import 'package:fl_extended/fl_extended.dart';
5 | import 'package:flutter/material.dart';
6 | import 'package:permission_handler/permission_handler.dart';
7 |
8 | class AMapGeoFencePage extends StatefulWidget {
9 | const AMapGeoFencePage({super.key});
10 |
11 | @override
12 | State createState() => _AMapGeoFencePageState();
13 | }
14 |
15 | class _AMapGeoFencePageState extends State {
16 | late ValueNotifier text = ValueNotifier('未初始化');
17 | String customID = 'TestCustomID';
18 |
19 | ValueNotifier geoFenceState =
20 | ValueNotifier(null);
21 |
22 | final geoFence = FlAMapGeoFence();
23 |
24 | ValueNotifier json = ValueNotifier(null);
25 |
26 | /// 获取定位权限
27 | Future get getPermissions async {
28 | if (!await getPermission(Permission.location)) {
29 | show('未获取到定位权限');
30 | return false;
31 | }
32 | return true;
33 | }
34 |
35 | /// 初始化地理围栏
36 | Future initGeoFence() async {
37 | if (!await getPermissions) return;
38 | final bool data = await geoFence.initialize(GeoFenceActivateAction.stayed);
39 | if (data) {
40 | show('初始化地理围栏:$data');
41 | }
42 | }
43 |
44 | @override
45 | Widget build(BuildContext context) => Scaffold(
46 | appBar: AppBar(title: const Text('高德地理围栏')),
47 | body: Universal(
48 | padding: const EdgeInsets.all(8.0),
49 | isScroll: true,
50 | width: double.infinity,
51 | mainAxisAlignment: MainAxisAlignment.center,
52 | children: [
53 | Container(
54 | margin: const EdgeInsets.symmetric(horizontal: 10),
55 | padding: const EdgeInsets.all(10),
56 | alignment: Alignment.center,
57 | decoration: BoxDecoration(
58 | borderRadius: BorderRadius.circular(10),
59 | color: Colors.grey.withValues(alpha: 0.3)),
60 | child: ValueListenableBuilder(
61 | valueListenable: text,
62 | builder: (_, String value, __) => Text(value,
63 | textAlign: TextAlign.center,
64 | style: const TextStyle(fontSize: 18)))),
65 | const SizedBox(height: 10),
66 | Wrap(
67 | runSpacing: 10,
68 | spacing: 10,
69 | alignment: WrapAlignment.center,
70 | children: [
71 | ElevatedText(onPressed: initGeoFence, text: 'initialize'),
72 | ElevatedText(
73 | onPressed: () {
74 | geoFence.dispose();
75 | show('未初始化');
76 | },
77 | text: 'dispose'),
78 | ElevatedText(
79 | onPressed: () async {
80 | final AMapPoiModel model = AMapPoiModel(
81 | keyword: '首开广场',
82 | poiType: '写字楼',
83 | city: '北京',
84 | size: 1,
85 | customID: customID);
86 | final result = await geoFence.addPOI(model);
87 | show('addPOI : ${result?.toMap()}');
88 | },
89 | text: '添加POI围栏'),
90 | ElevatedText(
91 | onPressed: () async {
92 | final LatLng latLng = LatLng(30.630259, 103.974113);
93 | final model = AMapGeoFenceLatLngModel(
94 | latLng: latLng,
95 | keyword: '西部智谷',
96 | poiType: '',
97 | customID: customID,
98 | size: 20,
99 | aroundRadius: 10000);
100 | final result = await geoFence.addLatLng(model);
101 | show('addLatLng : ${result?.toMap()}');
102 | },
103 | text: '添加经纬度围栏'),
104 | ElevatedText(
105 | onPressed: () async {
106 | final result = await geoFence.addDistrict(
107 | keyword: '海淀区', customID: customID);
108 | show('addDistrict : ${result?.toMap()}');
109 | },
110 | text: '添加行政区划围栏'),
111 | ElevatedText(
112 | onPressed: () async {
113 | final LatLng latLng = LatLng(30.651411, 103.998638);
114 | final result = await geoFence.addCircle(
115 | latLng: latLng, radius: 10, customID: customID);
116 | show('addCircle : ${result?.toMap()}');
117 | },
118 | text: '添加圆形围栏'),
119 | ElevatedText(
120 | onPressed: () async {
121 | final result =
122 | await geoFence.addCustom(latLng: [
123 | LatLng(39.933921, 116.372927),
124 | LatLng(39.907261, 116.376532),
125 | LatLng(39.900611, 116.418161),
126 | LatLng(39.941949, 116.435497),
127 | ], customID: customID);
128 | show('addCustom : ${result?.toMap()}');
129 | },
130 | text: '添加多边形围栏'),
131 | ElevatedText(
132 | onPressed: () async {
133 | final List data =
134 | await geoFence.getAll();
135 | if (data.isEmpty) {
136 | json.value = '没有添加围栏信息';
137 | } else {
138 | json.value = data
139 | .map((AMapGeoFenceModel e) => e.toMap())
140 | .toList();
141 | }
142 | },
143 | text: '获取所有围栏信息'),
144 | ElevatedText(
145 | onPressed: () async {
146 | final bool state = await geoFence.remove();
147 | show('remove : $state');
148 | json.value = '没有添加围栏信息';
149 | },
150 | text: '删除所有地理围栏'),
151 | ]),
152 | ElevatedText(
153 | onPressed: () async {
154 | final bool state = await geoFence.start(
155 | customID: customID,
156 | onGeoFenceChanged: (AMapGeoFenceStatusModel? geoFence) {
157 | show('围栏状态 : ${getStatus(geoFence?.status)}');
158 | geoFenceState.value = geoFence;
159 | });
160 | show('start : $state');
161 | },
162 | text: '开始围栏状态监听'),
163 | ElevatedText(
164 | onPressed: () async {
165 | final bool state = await geoFence.pause(customID: customID);
166 | show('pause : $state');
167 | },
168 | text: '暂停状态围栏监听'),
169 | Padding(
170 | padding: const EdgeInsets.all(20.0),
171 | child: ValueListenableBuilder(
172 | valueListenable: geoFenceState,
173 | builder: (_, AMapGeoFenceStatusModel? value, __) => Text(
174 | 'customID : ${value?.customID}\n'
175 | '围栏类型 type : ${getType(value?.type)}\n'
176 | '围栏状态 status : ${getStatus(value?.status)}\n'
177 | '围栏ID fenceID : ${value?.fenceID}\n',
178 | style: const TextStyle(fontSize: 15)))),
179 | Padding(
180 | padding: const EdgeInsets.all(20.0),
181 | child: ValueListenableBuilder(
182 | valueListenable: json,
183 | builder: (_, dynamic value, __) {
184 | if (value is Map) return JsonParse(value);
185 | if (value is List) return JsonParse.list(value);
186 | return Text(value.toString());
187 | }))
188 | ]));
189 |
190 | String getType(GenFenceType? type) {
191 | switch (type) {
192 | case GenFenceType.circle:
193 | return '圆形地理围栏';
194 | case GenFenceType.custom:
195 | return '多边形地理围栏';
196 | case GenFenceType.poi:
197 | return '(POI)地理围栏';
198 | case GenFenceType.district:
199 | return '行政区划地理围栏';
200 | default:
201 | return '未知类型';
202 | }
203 | }
204 |
205 | String getStatus(GenFenceStatus? status) {
206 | switch (status) {
207 | case GenFenceStatus.inside:
208 | return '在范围内';
209 | case GenFenceStatus.outside:
210 | return '在范围外';
211 | case GenFenceStatus.stayed:
212 | return '停留(在范围内超过10分钟)';
213 | default:
214 | return '未知状态';
215 | }
216 | }
217 |
218 | void show(String str) {
219 | text.value = str;
220 | }
221 |
222 | @override
223 | void dispose() {
224 | super.dispose();
225 | geoFence.dispose();
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/fl_amap/example/lib/src/loaction_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/main.dart';
2 | import 'package:fl_amap/fl_amap.dart';
3 | import 'package:fl_dio/fl_dio.dart';
4 | import 'package:fl_extended/fl_extended.dart';
5 | import 'package:flutter/foundation.dart';
6 | import 'package:flutter/material.dart';
7 | import 'package:permission_handler/permission_handler.dart';
8 |
9 | class AMapLocationPage extends StatefulWidget {
10 | const AMapLocationPage({super.key});
11 |
12 | @override
13 | State createState() => _AMapLocationPageState();
14 | }
15 |
16 | class _AMapLocationPageState extends State {
17 | late ValueNotifier text = ValueNotifier('未初始化');
18 | late ValueNotifier locationState = ValueNotifier(null);
19 | late ValueNotifier headingState = ValueNotifier(null);
20 | final location = FlAMapLocation();
21 |
22 | /// 获取定位权限
23 | Future get getPermissions async {
24 | if (!await getPermission(Permission.location)) {
25 | text.value = '未获取到定位权限';
26 | return false;
27 | }
28 | return true;
29 | }
30 |
31 | /// 初始化定位
32 | Future initLocation() async {
33 | if (!await getPermissions) return;
34 |
35 | /// 初始化AMap
36 | final bool data = await location.initialize();
37 | text.value = '初始化定位:$data';
38 | }
39 |
40 | @override
41 | void initState() {
42 | super.initState();
43 | location.addListener(
44 |
45 | /// 连续定位回调 android & ios 均支持
46 | onLocationChanged: (AMapLocation? location) {
47 | locationState.value = location;
48 | },
49 |
50 | /// ios连续定位 错误监听 仅在ios中生效
51 | onLocationFailed: (AMapLocationError? error) {
52 | text.value = 'ios 连续定位错误:${error?.toMap()}';
53 | },
54 |
55 | /// 监听设备朝向变化 仅在ios中生效
56 | onHeadingChanged: (AMapLocationHeading? heading) {
57 | headingState.value = heading;
58 | },
59 |
60 | /// 监听权限状态变化 仅在ios中生效
61 | onAuthorizationChanged: (int? status) {
62 | text.value = 'ios 权限状态变化:$status';
63 | });
64 | }
65 |
66 | @override
67 | Widget build(BuildContext context) => Scaffold(
68 | appBar: AppBar(title: const Text('高德定位')),
69 | body: Universal(
70 | isScroll: true,
71 | width: double.infinity,
72 | padding: const EdgeInsets.all(8.0),
73 | mainAxisAlignment: MainAxisAlignment.center,
74 | children: [
75 | Container(
76 | margin: const EdgeInsets.symmetric(horizontal: 10),
77 | padding: const EdgeInsets.all(10),
78 | alignment: Alignment.center,
79 | decoration: BoxDecoration(
80 | borderRadius: BorderRadius.circular(10),
81 | color: Colors.grey.withValues(alpha: 0.3)),
82 | child: ValueListenableBuilder(
83 | valueListenable: text,
84 | builder: (_, String value, __) => Text(value,
85 | textAlign: TextAlign.center,
86 | style: const TextStyle(fontSize: 18)))),
87 | const SizedBox(height: 10),
88 | Wrap(
89 | runSpacing: 10,
90 | spacing: 10,
91 | alignment: WrapAlignment.center,
92 | children: [
93 | ElevatedText(onPressed: initLocation, text: 'initialize'),
94 | ElevatedText(
95 | onPressed: () {
96 | location.dispose();
97 | locationState.value = null;
98 | text.value = '未初始化';
99 | },
100 | text: 'dispose'),
101 | ElevatedText(onPressed: getLocation, text: '直接获取定位'),
102 | ElevatedText(onPressed: startLocationState, text: '开启监听定位'),
103 | ElevatedText(
104 | onPressed: () async {
105 | var result =
106 | await getPermission(Permission.notification);
107 | if (result) {
108 | result = await location.enableBackgroundLocation(
109 | AMapNotificationForAndroid(
110 | notificationId: 999,
111 | title: '我在定位',
112 | content: '我正在定位',
113 | channelId: 'channelId',
114 | channelName: 'name',
115 | lightColor: Colors.red));
116 | text.value = '开启前台任务 $result';
117 | } else {
118 | text.value = '开启前台任务 未获得权限';
119 | }
120 | },
121 | text: '开启前台任务'),
122 | ElevatedText(
123 | onPressed: () async {
124 | final result =
125 | await location.disableBackgroundLocation();
126 | text.value = '关闭前台任务 $result';
127 | },
128 | text: '关闭前台任务'),
129 | ElevatedText(
130 | onPressed: () async {
131 | locationState.value = null;
132 | final result = await location.stopLocation();
133 | text.value = '定位监听关闭 $result';
134 | },
135 | text: '关闭监听定位'),
136 | if (TargetPlatform.iOS == defaultTargetPlatform) ...[
137 | ElevatedText(
138 | onPressed: () async {
139 | final result = await location.headingAvailable();
140 | text.value = 'ios 设备是否支持方向识别:$result';
141 | },
142 | text: '设备是否支持方向识别'),
143 | ElevatedText(
144 | onPressed: () async {
145 | final result = await location.startUpdatingHeading();
146 | text.value = 'ios 开始获取设备朝向 $result';
147 | },
148 | text: '开始获取设备朝向'),
149 | ElevatedText(
150 | onPressed: () async {
151 | final result = await location.stopUpdatingHeading();
152 | headingState.value = null;
153 | text.value = 'ios 停止获取设备朝向 $result';
154 | },
155 | text: '停止获取设备朝向'),
156 | ElevatedText(
157 | onPressed: () async {
158 | final result =
159 | await location.dismissHeadingCalibrationDisplay();
160 | text.value = 'ios 停止设备朝向校准显示 $result';
161 | },
162 | text: '停止设备朝向校准显示'),
163 | ],
164 | ]),
165 | Padding(
166 | padding: const EdgeInsets.all(20.0),
167 | child: ValueListenableBuilder(
168 | valueListenable: locationState,
169 | builder: (_, AMapLocation? value, __) {
170 | return value == null
171 | ? const Text('暂无定位信息')
172 | : JsonParse(value.toMapForPlatform());
173 | })),
174 | if (TargetPlatform.iOS == defaultTargetPlatform)
175 | Padding(
176 | padding: const EdgeInsets.all(20.0),
177 | child: ValueListenableBuilder(
178 | valueListenable: headingState,
179 | builder: (_, AMapLocationHeading? value, __) {
180 | return value == null
181 | ? const Text('暂无Heading信息')
182 | : JsonParse(value.toMap());
183 | })),
184 | ]));
185 |
186 | Future getLocation() async {
187 | if (!await getPermissions) return;
188 | text.value = '单次定位获取';
189 | locationState.value = null;
190 | locationState.value = await location.getLocation();
191 | }
192 |
193 | Future startLocationState() async {
194 | if (!await getPermissions) return;
195 | locationState.value = null;
196 | final bool data = await FlAMapLocation().startLocation();
197 | text.value = '开启连续定位${!data ? '失败' : '成功'}';
198 | }
199 |
200 | @override
201 | void dispose() {
202 | super.dispose();
203 | location.dispose();
204 | text.dispose();
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/fl_amap/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 | publish_to: 'none'
4 | version: 1.0.0
5 |
6 | environment:
7 | sdk: '>=3.6.0 <4.0.0'
8 | flutter: '>=3.27.0'
9 |
10 | dependencies:
11 | fl_amap:
12 | path: ../
13 | flutter:
14 | sdk: flutter
15 | fl_extended: ^1.7.2
16 | fl_dio: ^1.4.0
17 | permission_handler: ^11.4.0
18 |
19 | dev_dependencies:
20 | flutter_lints: ^5.0.0
21 |
22 | flutter:
23 | uses-material-design: true
24 |
--------------------------------------------------------------------------------
/fl_amap/format.sh:
--------------------------------------------------------------------------------
1 | dart format lib
2 | dart format example/lib
--------------------------------------------------------------------------------
/fl_amap/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 |
--------------------------------------------------------------------------------
/fl_amap/ios/Classes/AMapGeoFence.swift:
--------------------------------------------------------------------------------
1 | import AMapLocationKit
2 | import Flutter
3 | import Foundation
4 |
5 | class AMapGeoFence: NSObject, AMapGeoFenceManagerDelegate {
6 | var channel: FlutterMethodChannel
7 | private var manager: AMapGeoFenceManager?
8 | private var result: FlutterResult?
9 |
10 | init(_ binaryMessenger: FlutterBinaryMessenger) {
11 | channel = FlutterMethodChannel(name: "fl.amap.GeoFence", binaryMessenger:
12 | binaryMessenger)
13 | super.init()
14 | channel.setMethodCallHandler(handle)
15 | }
16 |
17 | public func setMethodCallHandler() {
18 | channel.setMethodCallHandler(handle)
19 | }
20 |
21 | public func detach() {
22 | channel.setMethodCallHandler(nil)
23 | }
24 |
25 | func handle(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) {
26 | self.result = result
27 | switch call.method {
28 | case "initialize":
29 | manager = manager ?? AMapGeoFenceManager()
30 | manager?.delegate = self
31 | result(initGeoFenceOption(call))
32 | case "dispose":
33 | manager?.removeAllGeoFenceRegions()
34 | manager?.delegate = nil
35 | manager = nil
36 | result(manager == nil)
37 | case "getAll":
38 | result(getAllGeoFence(call.arguments as? String))
39 | case "addPOI":
40 | let args = call.arguments as! [String: Any?]
41 | manager?.addKeywordPOIRegionForMonitoring(withKeyword: args["keyword"] as? String, poiType: args["type"] as? String, city: args["city"] as? String, size: args["size"] as! Int, customID: args["customID"] as? String)
42 | case "addLatLng":
43 | let args = call.arguments as! [String: Any?]
44 | let coordinate = CLLocationCoordinate2DMake(args["latitude"] as! Double, args["longitude"] as! Double)
45 | manager?.addAroundPOIRegionForMonitoring(withLocationPoint: coordinate, aroundRadius: Int(args["aroundRadius"] as! Double), keyword: args["keyword"] as? String, poiType: args["type"] as? String, size: args["size"] as! Int, customID: args["customID"] as? String)
46 | case "addDistrict":
47 | let args = call.arguments as! [String: Any?]
48 | manager?.addDistrictRegionForMonitoring(withDistrictName: args["keyword"] as? String, customID: args["customID"] as? String)
49 | case "addCircle":
50 | let args = call.arguments as! [String: Any?]
51 | let coordinate = CLLocationCoordinate2DMake(args["latitude"] as! Double, args["longitude"] as! Double)
52 | manager?.addCircleRegionForMonitoring(withCenter: coordinate, radius: args["radius"] as! Double, customID: args["customID"] as? String)
53 | case "addCustom":
54 | let args = call.arguments as! [String: Any?]
55 | let latLngs = args["latLng"] as! [[String: Double]]
56 | var coordinates = [CLLocationCoordinate2D]()
57 | for latLng in latLngs {
58 | coordinates.append(CLLocationCoordinate2D(
59 | latitude: latLng["latitude"]!, longitude: latLng["longitude"]!
60 | ))
61 | }
62 | manager?.addPolygonRegionForMonitoring(withCoordinates: &coordinates, count: latLngs.count, customID: args["customID"] as? String)
63 | case "remove":
64 | let customID = call.arguments as? String
65 | if customID != nil {
66 | manager?.removeGeoFenceRegions(withCustomID: customID)
67 | } else {
68 | manager?.removeAllGeoFenceRegions()
69 | }
70 | result(manager != nil)
71 | case "start":
72 | manager?.startGeoFenceRegions(withCustomID: call.arguments as? String)
73 | result(true)
74 | case "pause":
75 | manager?.pauseGeoFenceRegions(withCustomID: call.arguments as? String)
76 | result(true)
77 | default:
78 | result(FlutterMethodNotImplemented)
79 | }
80 | }
81 |
82 | func getAllGeoFence(_ customId: String?) -> [[String: Any?]] {
83 | var list = [[String: Any?]]()
84 | let fences = manager?.geoFenceRegions(withCustomID: customId)
85 | if fences == nil {
86 | return list
87 | }
88 | for region in fences! {
89 | if region is AMapGeoFenceRegion {
90 | let map = regionToMap(region as! AMapGeoFenceRegion)
91 | if map != nil {
92 | list.append(map!)
93 | }
94 | }
95 | }
96 | return list
97 | }
98 |
99 | func initGeoFenceOption(_ call: FlutterMethodCall) -> Bool {
100 | if manager == nil {
101 | return false
102 | }
103 | let args = call.arguments as! [AnyHashable: Any]
104 | switch args["action"] as! Int {
105 | case 0:
106 | manager!.activeAction = .inside
107 | case 1:
108 | manager!.activeAction = .outside
109 | case 2:
110 | manager!.activeAction = [.inside, .outside]
111 | case 3:
112 | manager!.activeAction = [.inside, .outside, .stayed]
113 | default:
114 | manager!.activeAction = [.inside, .outside, .stayed]
115 | }
116 | return true
117 | }
118 |
119 | /// 获取围栏创建后的回调
120 | /// 在如下回调中知道创建的围栏是否成功,以及查看所创建围栏的具体内容
121 | func amapGeoFenceManager(_ manager: AMapGeoFenceManager!, didAddRegionForMonitoringFinished regions: [AMapGeoFenceRegion]?, customID: String?, error: Error?) {
122 | result?([
123 | "customId": customID as Any,
124 | "geoFenceList": regions?.map { $0.data } as Any,
125 | "errorCode": (error as? NSError)?.code as? Int?,
126 | ])
127 | }
128 |
129 | /// 围栏状态改变时的回调
130 | func amapGeoFenceManager(_ manager: AMapGeoFenceManager!, didGeoFencesStatusChangedFor region: AMapGeoFenceRegion!, customID: String?, error: Error?) {
131 | channel.invokeMethod("onGeoFencesStatus", arguments: [
132 | "region": region.data,
133 | "customId": customID as Any,
134 | "errorCode": (error as? NSError)?.code as? Int?,
135 | ])
136 | }
137 |
138 | func amapLocationManager(_ manager: AMapGeoFenceManager!, doRequireTemporaryFullAccuracyAuth locationManager: CLLocationManager!, completion: ((Error?) -> Void)!) {}
139 |
140 | func amapGeoFenceManager(_ manager: AMapGeoFenceManager!, doRequireLocationAuth locationManager: CLLocationManager!) {}
141 |
142 | func regionToMap(_ region: AMapGeoFenceRegion) -> [String: Any?]? {
143 | if region is AMapGeoFenceCircleRegion {
144 | return (region as! AMapGeoFenceCircleRegion).circleData
145 | } else if region is AMapGeoFencePOIRegion {
146 | return (region as! AMapGeoFencePOIRegion).poiData
147 | } else if region is AMapGeoFencePolygonRegion {
148 | return (region as! AMapGeoFencePolygonRegion).polygonData
149 | } else if region is AMapGeoFenceDistrictRegion {
150 | return (region as! AMapGeoFenceDistrictRegion).districtData
151 | }
152 | return nil
153 | }
154 | }
155 |
156 | extension AMapGeoFenceRegion {
157 | var data: [String: Any?] {
158 | [
159 | "customID": customID,
160 | "status": fenceStatus.rawValue,
161 | "type": regionType.rawValue,
162 | "location": currentLocation?.data,
163 | "fenceID": identifier,
164 | ]
165 | }
166 | }
167 |
168 | extension AMapGeoFenceCircleRegion {
169 | var circleData: [String: Any?] {
170 | var map = [:] as [String: Any?]
171 | for (key, value) in data {
172 | map[key] = value
173 | }
174 | map["center"] = center.data
175 | map["radius"] = radius
176 | return map
177 | }
178 | }
179 |
180 | extension AMapGeoFencePOIRegion {
181 | var poiData: [String: Any?] {
182 | var map = [:] as [String: Any?]
183 | for (key, value) in circleData {
184 | map[key] = value
185 | }
186 | map["poiItem"] = poiItem.data
187 | return map
188 | }
189 | }
190 |
191 | extension AMapGeoFencePolygonRegion {
192 | var polygonData: [String: Any?] {
193 | var map = [:] as [String: Any?]
194 | for (key, value) in data {
195 | map[key] = value
196 | }
197 | map["count"] = count
198 | map["point"] = coordinates.pointee.data
199 | return map
200 | }
201 | }
202 |
203 | extension AMapGeoFenceDistrictRegion {
204 | var districtData: [String: Any?] {
205 | var map = [:] as [String: Any?]
206 | for (key, value) in data {
207 | map[key] = value
208 | }
209 | map["districtItem"] = districtItem.data
210 | map["pointList"] = polylinePoints.map { points in
211 | points.map { point in
212 | point.data
213 | }
214 | }
215 | return map
216 | }
217 | }
218 |
219 | extension AMapLocationDistrictItem {
220 | var data: [String: Any?] {
221 | [
222 | "cityCode": cityCode,
223 | "district": district,
224 | "districtCode": districtCode,
225 | "pointList": polylinePoints.map { points in
226 | points.map { point in
227 | point.data
228 | }
229 | },
230 | ]
231 | }
232 | }
233 |
234 | extension AMapLocationPOIItem {
235 | var data: [String: Any?] {
236 | [
237 | "pId": pId,
238 | "name": name,
239 | "type": type,
240 | "typeCode": typeCode,
241 | "address": address,
242 | "location": location.data,
243 | "tel": tel,
244 | "province": province,
245 | "city": city,
246 | "district": district,
247 | ]
248 | }
249 | }
250 |
251 | extension CLLocationCoordinate2D {
252 | var data: [String: Any?] {
253 | [
254 | "latitude": latitude,
255 | "longitude": longitude,
256 | ]
257 | }
258 | }
259 |
260 | extension AMapLocationPoint {
261 | var data: [String: Any?] {
262 | [
263 | "latitude": latitude,
264 | "longitude": longitude,
265 | ]
266 | }
267 | }
268 |
--------------------------------------------------------------------------------
/fl_amap/ios/Classes/AMapPlugin.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 |
3 | public class AMapPlugin: NSObject, FlutterPlugin {
4 | private var location: AMapLocation
5 | private var geoFence: AMapGeoFence
6 |
7 | public static func register(with registrar: FlutterPluginRegistrar) {
8 | _ = AMapPlugin(registrar.messenger())
9 | }
10 |
11 | init(_ binaryMessenger: FlutterBinaryMessenger) {
12 | location = AMapLocation(binaryMessenger)
13 | geoFence = AMapGeoFence(binaryMessenger)
14 | super.init()
15 | }
16 |
17 | public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
18 | location.detach()
19 | geoFence.detach()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/fl_amap/ios/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTrackingDomains
6 |
7 | NSPrivacyAccessedAPITypes
8 |
9 | NSPrivacyCollectedDataTypes
10 |
11 | NSPrivacyTracking
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/fl_amap/ios/fl_amap.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
3 | #
4 | Pod::Spec.new do |s|
5 | s.name = 'fl_amap'
6 | s.version = '0.0.1'
7 | s.summary = 'A Flutter plugin.'
8 | s.description = <<-DESC
9 | A new Flutter plugin.
10 | DESC
11 | s.homepage = 'http://example.com'
12 | s.license = { :file => '../LICENSE' }
13 | s.author = { 'Your Company' => 'email@example.com' }
14 | s.source = { :path => '.' }
15 | s.source_files = 'Classes/**/*'
16 | s.dependency 'Flutter'
17 | s.dependency 'AMapLocation'
18 | s.static_framework = true
19 | s.platform = :ios, '12.0'
20 | # Flutter.framework does not contain a i386 slice.
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
22 | s.swift_version = '5.0'
23 |
24 | end
25 |
26 |
--------------------------------------------------------------------------------
/fl_amap/lib/fl_amap.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter/services.dart';
4 |
5 | part 'src/amap_geo_fence.dart';
6 |
7 | part 'src/amap_location.dart';
8 |
9 | part 'src/enum.dart';
10 |
11 | class FlAMap {
12 | factory FlAMap() => _singleton ??= FlAMap._();
13 |
14 | FlAMap._();
15 |
16 | static FlAMap? _singleton;
17 |
18 | /// 设置ios&android的key
19 | Future setAMapKey({
20 | required String iosKey,
21 | required String androidKey,
22 |
23 | /// 设置是否同意用户授权政策 设置为true才可以调用其他功能
24 | bool isAgree = true,
25 |
26 | /// 设置包含隐私政策 设置为true才可以调用其他功能
27 | bool isContains = true,
28 |
29 | /// 并展示用户授权弹窗 设置为true才可以调用其他功能
30 | bool isShow = true,
31 | }) async {
32 | if (!_supportPlatform) return false;
33 | String? key;
34 | if (_isAndroid) key = androidKey;
35 | if (_isIOS) key = iosKey;
36 | if (key == null) return false;
37 | final state = await FlAMapLocation()._channel.invokeMethod('setApiKey', {
38 | 'key': key,
39 | 'isAgree': isAgree,
40 | 'isContains': isContains,
41 | 'isShow': isShow
42 | });
43 | return state == true;
44 | }
45 | }
46 |
47 | bool get _supportPlatform {
48 | if (!kIsWeb && (_isAndroid || _isIOS)) return true;
49 | debugPrint('Not support platform for $defaultTargetPlatform');
50 | return false;
51 | }
52 |
53 | bool get _isAndroid => defaultTargetPlatform == TargetPlatform.android;
54 |
55 | bool get _isIOS => defaultTargetPlatform == TargetPlatform.iOS;
56 |
57 | class LatLng {
58 | LatLng(this.latitude, this.longitude);
59 |
60 | LatLng.fromMap(Map map)
61 | : latitude = map['latitude'] as double?,
62 | longitude = map['longitude'] as double?;
63 |
64 | /// 维度
65 | double? latitude;
66 |
67 | /// 经度
68 | double? longitude;
69 |
70 | Map toMap() =>
71 | {'latitude': latitude, 'longitude': longitude};
72 | }
73 |
--------------------------------------------------------------------------------
/fl_amap/lib/src/enum.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap.dart';
2 |
3 | enum GenFenceType {
4 | /// 圆形地理围栏
5 | circle,
6 |
7 | /// 多边形地理围栏
8 | custom,
9 |
10 | /// 兴趣点(POI)地理围栏
11 | poi,
12 |
13 | /// 行政区划地理围栏
14 | district
15 | }
16 |
17 | enum GenFenceStatus {
18 | /// 未知
19 | none,
20 |
21 | /// 在范围内
22 | inside,
23 |
24 | /// 在范围外
25 | outside,
26 |
27 | /// 停留(在范围内超过10分钟)
28 | stayed,
29 |
30 | /// android 定位失败时,围栏状态无法进行检测
31 | locFailed
32 | }
33 |
34 | enum GeoFenceActivateAction {
35 | /// 进入地理围栏
36 | onlyInside,
37 |
38 | /// 退出地理围栏
39 | onlyOutside,
40 |
41 | /// 监听进入并退出
42 | insideAndOutside,
43 |
44 | /// 停留在地理围栏内10分钟
45 | stayed,
46 | }
47 |
--------------------------------------------------------------------------------
/fl_amap/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: fl_amap
2 | description: AMap location plugin for flutter, supports single positioning and continuous positioning
3 | version: 3.4.3
4 | repository: https://github.com/Wayaer/fl_amap/tree/main/fl_amap
5 |
6 | environment:
7 | sdk: '>=3.0.0 <4.0.0'
8 | flutter: '>=3.10.0'
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_lints: ^5.0.0
16 |
17 | flutter:
18 | plugin:
19 | platforms:
20 | android:
21 | package: fl.amap
22 | pluginClass: AMapPlugin
23 | ios:
24 | pluginClass: AMapPlugin
25 |
--------------------------------------------------------------------------------
/fl_amap_map/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 |
7 | # Xcode
8 | #
9 | build/
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata
19 | *.xccheckout
20 | *.moved-aside
21 | DerivedData
22 | *.hmap
23 | *.ipa
24 | *.xcuserstate
25 | project.xcworkspace
26 |
27 |
28 | # Android/IntelliJ
29 | #
30 | build/
31 | .idea
32 | .gradle
33 | local.properties
34 | *.iml
35 | *.lock
36 | *.packages
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | /.dart_tool/
43 |
--------------------------------------------------------------------------------
/fl_amap_map/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.0.1
2 |
3 | *
4 |
--------------------------------------------------------------------------------
/fl_amap_map/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Wayaer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/fl_amap_map/README.md:
--------------------------------------------------------------------------------
1 | ## 高德地图flutter组件。
2 |
3 | ### 目前实现获取定位、监听定位和部分地图功能 (依赖此插件无需再依赖[fl_amap](https://pub.dev/packages/fl_amap))
4 |
5 | 1、申请一个key
6 | http://lbs.amap.com/api/ios-sdk/guide/create-project/get-key
7 |
8 | 直接在dart文件中设置key
9 |
10 | # ios
11 |
12 | 1. 在info.plist中增加:
13 |
14 | ```
15 | NSLocationWhenInUseUsageDescription
16 | 要用定位
17 | ```
18 |
19 | 2. iOS 9及以上版本使用后台定位功能, 需要保证"Background Modes"中的"Location updates"处于选中状态
20 |
21 | 3.使用地理围栏
22 |
23 | iOS14及以上版本使用地理围栏功能,需要在plist中配置NSLocationTemporaryUsageDescriptionDictionary字典描述,
24 | 且添加自定义Key描述地理围栏的使用场景,此描述会在申请临时精确定位权限的弹窗中展示。
25 | 该回调触发条件:拥有定位权限,但是没有获得精确定位权限的情况下,会触发该回调。此方法实现调用申请临时精确定位权限API即可;
26 |
27 | ** 需要注意,在iOS9及之后版本的系统中,如果您希望程序在后台持续检测围栏触发行为,需要保证manager的 allowsBackgroundLocationUpdates 为 YES,
28 | 设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
29 |
30 | # android
31 |
32 | - `android/src/main/AndroidManifest.xml` 添加以下内容 具体参考 `example`
33 |
34 | ```xml
35 |
36 |
37 | ```
38 |
39 | ## 开始使用
40 |
41 | ## 高德定位功能
42 |
43 | - 设置key
44 |
45 | ```dart
46 |
47 | Future setAMapKey() async {
48 | final key = await FlAMapMap().setAMapKey(
49 | iosKey: 'ios key',
50 | androidKey: 'android key');
51 |
52 | if (key != null && key) print('高德地图ApiKey设置成功');
53 | }
54 |
55 | ```
56 |
57 | - 初始化定位参数
58 |
59 | ```dart
60 | Future initialize() async {
61 | /// 获取权限
62 | if (getPermissions) return;
63 |
64 | /// 初始化AMap
65 | final bool data = await FlAMapLocation().initialize(AMapLocationOption());
66 | if (data) {
67 | show('初始化成功');
68 | }
69 | }
70 |
71 | ```
72 |
73 | - 单次获取定位
74 |
75 | ```dart
76 | Future getLocation() async {
77 | /// 务必先初始化 并获取权限
78 | if (getPermissions) return;
79 | AMapLocation location = await FlAMapLocation().getLocation(true);
80 | }
81 |
82 | ```
83 |
84 | - 开启定位变化监听
85 |
86 | ```dart
87 | Future startLocationChange() async {
88 | /// 务必先初始化 并获取权限
89 | if (getPermissions) return;
90 | final bool data =
91 | await FlAMapLocation().startLocationChanged(onLocationChanged:
92 | (AMapLocation location) {
93 | locationState.value = location;
94 | text.value = '位置更新$i次';
95 | });
96 | print(!data ? '开启成功' : '开启失败');
97 | }
98 |
99 | ```
100 |
101 | - 关闭定位变化监听
102 |
103 | ```dart
104 | void stopLocation() {
105 | FlAMapLocation().stopLocation();
106 | }
107 | ```
108 |
109 | - 关闭定位服务
110 |
111 | ```dart
112 | void dispose() {
113 | super.dispose();
114 | FlAMapLocation().dispose();
115 | }
116 | ```
117 |
118 | ## 高德地理围栏功能
119 |
120 | - 初始化地理围栏
121 |
122 | ```dart
123 |
124 | Future get initialize async {
125 | final bool data = await FlAMapGeoFence().initialize(GeoFenceActivateAction.stayed);
126 | if (data) {
127 | show('初始化地理围栏:$data');
128 | }
129 | }
130 |
131 | ```
132 |
133 | - 关闭围栏服务
134 |
135 | ```dart
136 | void dispose() {
137 | super.dispose();
138 | FlAMapGeoFence().dispose();
139 | }
140 | ```
141 |
142 | - 根据POI添加围栏
143 |
144 | ```dart
145 | Future addPOI() async {
146 | final AMapPoiModel model = AMapPoiModel(
147 | keyword: '首开广场',
148 | poiType: '写字楼',
149 | city: '北京',
150 | size: 1,
151 | customId: '000FATE23(考勤打卡)');
152 | final bool state = await FlAMapGeoFence().addPOI(model);
153 | }
154 | ```
155 |
156 | - 根据坐标关键字添加围栏
157 |
158 | ```dart
159 | Future addLatLng() async {
160 | final LatLng latLong = LatLng(39.933921, 116.372927);
161 | final AMapLatLngModel model = AMapLatLngModel(
162 | latLong: latLong,
163 | keyword: '首开广场',
164 | poiType: '',
165 | customId: '000FATE23(考勤打卡)',
166 | size: 20,
167 | aroundRadius: 1000);
168 | final bool state = await FlAMapGeoFence().addLatLng(model);
169 | }
170 | ```
171 |
172 | - 添加行政区划围栏
173 |
174 | ```dart
175 | Future addDistrict() async {
176 | final bool state = await FlAMapGeoFence().addDistrict(
177 | keyword: '海淀区', customId: '000FATE23(考勤打卡)');
178 | }
179 | ```
180 |
181 | - 添加圆形围栏
182 |
183 | ```dart
184 | Future addCircle() async {
185 | final LatLng latLong = LatLng(30.651411, 103.998638);
186 | final bool state = await FlAMapGeoFence().addCircle(
187 | latLong: latLong,
188 | radius: 10,
189 | customId: '000FATE23(考勤打卡)');
190 | }
191 | ```
192 |
193 | - 添加多边形围栏
194 |
195 | ```dart
196 | Future addCustom() async {
197 | final bool state = await FlAMapGeoFence().addCustom(latLongs: [
198 | LatLng(39.933921, 116.372927),
199 | LatLng(39.907261, 116.376532),
200 | LatLng(39.900611, 116.418161),
201 | LatLng(39.941949, 116.435497),
202 | ], customId: '000FATE23(考勤打卡)');
203 | }
204 | ```
205 |
206 | - 获取所有围栏信息
207 |
208 | ```dart
209 | Future getAll() async {
210 | /// 传入 customID 获取指定标识的围栏信息 仅支持ios
211 | final List data = await FlAMapGeoFence().getAll();
212 | }
213 | ```
214 |
215 | - 删除地理围栏
216 |
217 | ```dart
218 | Future remove() async {
219 | /// 传入 customID 删除指定标识的围栏
220 | /// 不传 删除所有围栏
221 | final bool state = await FlAMapGeoFence().remove();
222 | }
223 | ```
224 |
225 | - 暂停监听围栏
226 |
227 | ```dart
228 | Future pause() async {
229 | /// 传入 customID 暂停指定标识的围栏
230 | /// 不传 暂停所有围栏
231 | final bool state = await FlAMapGeoFence().pause();
232 | }
233 | ```
234 |
235 | - 开始监听围栏
236 |
237 | ```dart
238 | Future start() async {
239 | /// 传入 customID 开始指定标识的围栏
240 | /// 不传 开始所有围栏
241 | final bool state = await FlAMapGeoFence().start();
242 | }
243 | ```
--------------------------------------------------------------------------------
/fl_amap_map/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/fl_amap_map/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/fl_amap_map/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'fl.amap'
2 | version '1.0'
3 |
4 | buildscript {
5 | repositories {
6 | google()
7 | mavenCentral()
8 | }
9 |
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:8.5.2'
12 | }
13 | }
14 |
15 | rootProject.allprojects {
16 | repositories {
17 | google()
18 | mavenCentral()
19 | }
20 | }
21 |
22 | apply plugin: 'com.android.library'
23 | apply plugin: 'kotlin-android'
24 |
25 | android {
26 | compileSdk = 34
27 |
28 | if (project.android.hasProperty("namespace")) {
29 | namespace 'fl.amap'
30 | }
31 |
32 | compileOptions {
33 | sourceCompatibility = JavaVersion.VERSION_17
34 | targetCompatibility = JavaVersion.VERSION_17
35 | }
36 |
37 | kotlinOptions {
38 | jvmTarget = JavaVersion.VERSION_17.toString()
39 | }
40 |
41 | sourceSets {
42 | main.java.srcDirs += 'src/main/kotlin'
43 | }
44 | defaultConfig {
45 | minSdk = 21
46 | consumerProguardFiles 'consumer-rules.pro'
47 | }
48 | packagingOptions {
49 | merge 'AndroidManifest.xml'
50 | merge 'R.txt'
51 | merge 'classes.jar'
52 | merge 'proguard.txt'
53 | }
54 |
55 | dependencies {
56 | api 'com.amap.api:3dmap:10.0.600'
57 | }
58 |
59 | }
60 |
61 |
62 |
--------------------------------------------------------------------------------
/fl_amap_map/android/consumer-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class com.amap.api.location.**{*;}
2 | -keep class com.amap.api.fence.**{*;}
3 | -keep class com.autonavi.aps.amapapi.model.**{*;}
4 | -keep class com.loc.**{*;}
5 |
--------------------------------------------------------------------------------
/fl_amap_map/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'fl_amap'
2 |
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/kotlin/fl/amap/map/AMapMapPlugin.kt:
--------------------------------------------------------------------------------
1 | package fl.amap.map
2 |
3 | import android.content.Context
4 | import androidx.lifecycle.Lifecycle
5 | import com.amap.api.location.AMapLocationClient
6 | import com.amap.api.maps.MapsInitializer
7 | import fl.amap.map.map.AMapPlatformViewFactory
8 | import fl.channel.FlChannelPlugin
9 | import fl.channel.FlEventChannel
10 | import io.flutter.embedding.engine.plugins.FlutterPlugin
11 | import io.flutter.embedding.engine.plugins.activity.ActivityAware
12 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
13 | import io.flutter.embedding.engine.plugins.lifecycle.HiddenLifecycleReference
14 | import io.flutter.plugin.common.BinaryMessenger
15 | import io.flutter.plugin.common.MethodCall
16 | import io.flutter.plugin.common.MethodChannel
17 |
18 |
19 | class AMapMapPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
20 | private lateinit var channel: MethodChannel
21 | private lateinit var context: Context
22 | private lateinit var binaryMessenger: BinaryMessenger
23 |
24 |
25 | companion object {
26 | var lifecycle: Lifecycle? = null
27 | var flEventChannel: FlEventChannel? = null
28 | }
29 |
30 | override fun onAttachedToEngine(plugin: FlutterPlugin.FlutterPluginBinding) {
31 | binaryMessenger = plugin.binaryMessenger
32 | channel = MethodChannel(plugin.binaryMessenger, "fl_amap_map")
33 | context = plugin.applicationContext
34 | channel.setMethodCallHandler(this)
35 | plugin.platformViewRegistry.registerViewFactory(
36 | "fl_amap_map", AMapPlatformViewFactory(plugin.binaryMessenger)
37 | )
38 | }
39 |
40 | override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
41 | when (call.method) {
42 | "setApiKey" -> {
43 | val key = call.argument("key")!!
44 | val isAgree = call.argument("isAgree")!!
45 | val isContains = call.argument("isContains")!!
46 | val isShow = call.argument("isShow")!!
47 | val enableHTTPS = call.argument("enableHTTPS")!!
48 | AMapLocationClient.updatePrivacyAgree(context, isAgree)
49 | AMapLocationClient.updatePrivacyShow(context, isContains, isShow)
50 | AMapLocationClient.setApiKey(key)
51 | MapsInitializer.setApiKey(key)
52 | MapsInitializer.initialize(context)
53 | MapsInitializer.setProtocol(if (enableHTTPS) MapsInitializer.HTTPS else MapsInitializer.HTTP)
54 | MapsInitializer.updatePrivacyAgree(context, isAgree)
55 | MapsInitializer.updatePrivacyShow(context, isContains, isShow)
56 | flEventChannel = FlChannelPlugin.getEventChannel("fl_amap_map_event")
57 | result.success(true)
58 | }
59 | }
60 |
61 | }
62 |
63 | override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
64 | channel.setMethodCallHandler(null)
65 | }
66 |
67 | override fun onAttachedToActivity(binding: ActivityPluginBinding) {
68 | val reference = binding.lifecycle as HiddenLifecycleReference
69 | lifecycle = reference.lifecycle
70 | }
71 |
72 | override fun onDetachedFromActivityForConfigChanges() {
73 | onDetachedFromActivity()
74 | }
75 |
76 | override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
77 | onAttachedToActivity(binding)
78 | }
79 |
80 | override fun onDetachedFromActivity() {
81 | lifecycle = null
82 | }
83 |
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/kotlin/fl/amap/map/Extension.kt:
--------------------------------------------------------------------------------
1 | package fl.amap.map
2 |
3 | import android.location.Location
4 | import com.amap.api.maps.model.*
5 | import com.autonavi.amap.mapcore.DPoint
6 | import com.autonavi.amap.mapcore.IPoint
7 |
8 | val Location.data: Map
9 | get() = mapOf(
10 | "accuracy" to accuracy,
11 | "altitude" to altitude,
12 | "speed" to speed,
13 | "timestamp" to (time.toDouble() / 1000),
14 | "latLng" to mapOf(
15 | "latitude" to latitude,
16 | "longitude" to longitude,
17 | ),
18 | "provider" to provider,
19 | "bearing" to bearing,
20 | )
21 |
22 | val LatLng.data: Map
23 | get() = mapOf(
24 | "latitude" to latitude,
25 | "longitude" to longitude,
26 | )
27 | val IPoint.data: Map
28 | get() = mapOf(
29 | "x" to x,
30 | "y" to y,
31 | )
32 | val DPoint.data: Map
33 | get() = mapOf(
34 | "x" to x,
35 | "y" to y,
36 | )
37 | val CameraPosition.data: Map
38 | get() = mapOf(
39 | "target" to target.data,
40 | "zoom" to zoom,
41 | "tilt" to tilt,
42 | "bearing" to bearing,
43 | "isAbroad" to isAbroad,
44 | )
45 |
46 |
47 | val MarkerOptions.data: Map
48 | get() = mapOf(
49 | "anchorU" to anchorU,
50 | "anchorV" to anchorV,
51 | "infoWindowOffsetX" to infoWindowOffsetX,
52 | "infoWindowOffsetY" to infoWindowOffsetY,
53 | "alpha" to alpha,
54 | "altitude" to altitude,
55 | "period" to period,
56 | "position" to position,
57 | "rotateAngle" to rotateAngle,
58 | "snippet" to snippet,
59 | "title" to title,
60 | "zIndex" to zIndex,
61 | "isDraggable" to isDraggable,
62 | "isVisible" to isVisible,
63 | "isFlat" to isFlat,
64 | "isInfoWindowAutoOverturn" to isInfoWindowAutoOverturn,
65 | "isInfoWindowEnable" to isInfoWindowEnable,
66 | )
67 | val Marker.data: Map
68 | get() = mapOf(
69 | "options" to options.data,
70 | "alpha" to alpha,
71 | "altitude" to altitude,
72 | "id" to id,
73 | "period" to period,
74 | "position" to position,
75 | "rotateAngle" to rotateAngle,
76 | "snippet" to snippet,
77 | "title" to title,
78 | "zIndex" to zIndex,
79 | "geoPoint" to geoPoint.data,
80 | "isRemoved" to isRemoved,
81 | "isClickable" to isClickable,
82 | "isDraggable" to isDraggable,
83 | "isVisible" to isVisible,
84 | "isFlat" to isFlat,
85 | "isViewMode" to isViewMode,
86 | "isInfoWindowAutoOverturn" to isInfoWindowAutoOverturn,
87 | "isInfoWindowEnable" to isInfoWindowEnable,
88 | )
89 |
90 |
91 | val Poi.data: Map
92 | get() = mapOf(
93 | "latLng" to coordinate.data,
94 | "name" to name,
95 | "poiId" to poiId,
96 | )
97 |
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/kotlin/fl/amap/map/map/AMapPlatformViewFactory.kt:
--------------------------------------------------------------------------------
1 | package fl.amap.map.map
2 |
3 | import android.content.Context
4 | import io.flutter.plugin.common.BinaryMessenger
5 | import io.flutter.plugin.common.MethodChannel
6 | import io.flutter.plugin.common.StandardMessageCodec
7 | import io.flutter.plugin.platform.PlatformView
8 | import io.flutter.plugin.platform.PlatformViewFactory
9 |
10 | class AMapPlatformViewFactory(
11 | private val binaryMessenger: BinaryMessenger,
12 | ) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
13 |
14 | override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
15 | val channel = MethodChannel(binaryMessenger, "fl_amap_map_$viewId")
16 | return AMapView(context, channel, viewId, args as Map<*, *>)
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/kotlin/fl/amap/map/map/AMapView.kt:
--------------------------------------------------------------------------------
1 | package fl.amap.map.map
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.view.View
6 | import androidx.lifecycle.DefaultLifecycleObserver
7 | import androidx.lifecycle.LifecycleOwner
8 | import com.amap.api.maps.AMap
9 | import com.amap.api.maps.CameraUpdateFactory
10 | import com.amap.api.maps.TextureMapView
11 | import com.amap.api.maps.model.*
12 | import fl.amap.map.AMapMapPlugin.Companion.lifecycle
13 | import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding.OnSaveInstanceStateListener
14 | import io.flutter.plugin.common.MethodCall
15 | import io.flutter.plugin.common.MethodChannel
16 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler
17 | import io.flutter.plugin.platform.PlatformView
18 |
19 |
20 | class AMapView(
21 | context: Context?, private var channel: MethodChannel, private var viewId: Int, args: Map<*, *>
22 | ) : DefaultLifecycleObserver, OnSaveInstanceStateListener, MethodCallHandler, PlatformView {
23 | private var mapview: TextureMapView
24 | private var mapViewListener: AMapViewListener? = null
25 |
26 | init {
27 | channel.setMethodCallHandler(this)
28 | mapview = TextureMapView(context)
29 | setOptions(args)
30 |
31 | lifecycle?.addObserver(this)
32 | }
33 |
34 | override fun onCreate(owner: LifecycleOwner) {
35 | mapview.onCreate(null)
36 | }
37 |
38 | override fun onResume(owner: LifecycleOwner) {
39 | mapview.onResume()
40 | }
41 |
42 | override fun onPause(owner: LifecycleOwner) {
43 | mapview.onPause()
44 | }
45 |
46 | override fun onDestroy(owner: LifecycleOwner) {
47 | mapview.onDestroy()
48 | lifecycle?.removeObserver(this)
49 | }
50 |
51 | override fun onSaveInstanceState(bundle: Bundle) {
52 | mapview.onSaveInstanceState(bundle)
53 | }
54 |
55 | override fun onRestoreInstanceState(bundle: Bundle?) {
56 | mapview.onCreate(bundle)
57 | }
58 |
59 | override fun getView(): View {
60 | return mapview
61 | }
62 |
63 | override fun dispose() {
64 |
65 | }
66 |
67 | override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
68 | when (call.method) {
69 | "setOptions" -> setOptions(call.arguments as Map<*, *>)
70 | "dispose" -> {
71 | mapViewListener?.removeListener()
72 | mapViewListener = null
73 | channel.setMethodCallHandler(null)
74 | mapview.onDestroy()
75 | lifecycle?.removeObserver(this)
76 | }
77 |
78 | "addListener" -> {
79 | if (mapViewListener == null) {
80 | mapViewListener = AMapViewListener(viewId, mapview.map)
81 | }
82 | result.success(true)
83 | }
84 |
85 | "removeListener" -> {
86 | mapViewListener?.removeListener()
87 | mapViewListener = null
88 | result.success(true)
89 | }
90 |
91 | "setCenter" -> {
92 | val animated = call.argument("animated")!!
93 | val cameraUpdate = CameraUpdateFactory.newCameraPosition(
94 | CameraPosition(
95 | LatLng(
96 | call.argument("latitude")!!, call.argument("longitude")!!
97 | ),
98 | call.argument("zoom")!!.toFloat(),
99 | call.argument("tilt")!!.toFloat(),
100 | call.argument("bearing")!!.toFloat()
101 | )
102 | )
103 | if (animated) {
104 | mapview.map.animateCamera(cameraUpdate)
105 | } else {
106 | mapview.map.moveCamera(cameraUpdate)
107 | }
108 | result.success(true)
109 | }
110 |
111 | "reloadMap" -> {
112 | mapview.map.reloadMap()
113 | result.success(true)
114 | }
115 |
116 | "setRenderFps" -> {
117 | mapview.map.setRenderFps(call.arguments as Int)
118 | result.success(true)
119 | }
120 |
121 | "setTrackingMode" -> {
122 | val mode = call.argument("mode") ?: 0
123 | val locationStyle = MyLocationStyle()
124 | locationStyle.myLocationType(mode)
125 | mapview.map.myLocationStyle = locationStyle
126 | result.success(true)
127 | }
128 |
129 | "addMarker" -> {
130 | val markerOptions = MarkerOptions()
131 | val marker = mapview.map.addMarker(markerOptions)
132 | result.success(marker.id)
133 | }
134 |
135 | else -> result.notImplemented()
136 | }
137 | }
138 |
139 | private fun setOptions(args: Map<*, *>) {
140 | val map = mapview.map
141 | val options = map.uiSettings
142 | options.isZoomControlsEnabled = false
143 | val latitude = args["latitude"] as Double
144 | val longitude = args["longitude"] as Double
145 | val zoom = (args["zoom"] as Double).toFloat()
146 | val tilt = (args["tilt"] as Double).toFloat()
147 | val bearing = (args["bearing"] as Double).toFloat()
148 | map.moveCamera(
149 | CameraUpdateFactory.newCameraPosition(
150 | CameraPosition(LatLng(latitude, longitude), zoom, tilt, bearing)
151 | )
152 | )
153 | options.isRotateGesturesEnabled = args["isRotateGesturesEnabled"] as Boolean
154 | options.isCompassEnabled = args["showCompass"] as Boolean
155 | options.isScaleControlsEnabled = args["showScale"] as Boolean
156 | options.isScrollGesturesEnabled = args["isScrollGesturesEnabled"] as Boolean
157 | options.isZoomGesturesEnabled = args["isZoomGesturesEnabled"] as Boolean
158 | options.isTiltGesturesEnabled = args["isTiltGesturesEnabled"] as Boolean
159 | options.isMyLocationButtonEnabled = args["showUserLocationButton"] as Boolean
160 | map.isMyLocationEnabled = args["showUserLocation"] as Boolean
161 | options.setZoomInByScreenCenter(args["zoomingInPivotsAroundAnchorPoint"] as Boolean)
162 | map.mapType = (args["mapType"] as Int) + 1
163 | map.isTouchPoiEnable = args["isTouchPoiEnable"] as Boolean
164 | map.isTrafficEnabled = args["showTraffic"] as Boolean
165 | map.showIndoorMap(args["showIndoorMap"] as Boolean)
166 | map.showMapText(args["showMapText"] as Boolean)
167 | map.showBuildings(args["showBuildings"] as Boolean)
168 | val language = args["language"] as Int
169 | map.setMapLanguage(if (language == 0) AMap.CHINESE else AMap.ENGLISH)
170 | map.maxZoomLevel = (args["maxZoom"] as Double).toFloat()
171 | map.minZoomLevel = (args["minZoom"] as Double).toFloat()
172 | }
173 |
174 | }
--------------------------------------------------------------------------------
/fl_amap_map/android/src/main/kotlin/fl/amap/map/map/AMapViewListener.kt:
--------------------------------------------------------------------------------
1 | package fl.amap.map.map
2 |
3 | import android.graphics.Bitmap
4 | import android.graphics.Rect
5 | import android.location.Location
6 | import android.view.MotionEvent
7 | import android.view.View
8 | import com.amap.api.maps.AMap
9 | import com.amap.api.maps.CustomRenderer
10 | import com.amap.api.maps.LocationSource
11 | import com.amap.api.maps.SwipeDismissTouchListener
12 | import com.amap.api.maps.WearMapView
13 | import com.amap.api.maps.model.*
14 | import com.autonavi.base.ae.gmap.AMapAppRequestParam
15 | import fl.amap.map.AMapMapPlugin.Companion.flEventChannel
16 | import fl.amap.map.data
17 | import fl.channel.FlChannelPlugin
18 | import fl.channel.FlEventChannel
19 | import javax.microedition.khronos.egl.EGLConfig
20 | import javax.microedition.khronos.opengles.GL10
21 |
22 | // AMap.CancelableCallback, AMap.ImageInfoWindowAdapter,AMap.OnCacheRemoveListener,AMap.InfoWindowAdapter, AMap.OnMapScreenShotListener, AMap.OnMapSnapshotListener, AMap.OnPolylineClickListener, CustomRenderer, LocationSource, LocationSource.OnLocationChangedListener, AMap.OnMultiPointClickListener, SwipeDismissTouchListener.DismissCallbacks, WearMapView.OnDismissCallback
23 | class AMapViewListener(private var viewId: Int, private var map: AMap) : AMap.AMapAppResourceRequestListener,
24 |
25 | AMap.OnCameraChangeListener, AMap.OnIndoorBuildingActiveListener, AMap.OnInfoWindowClickListener,
26 | AMap.OnMapClickListener, AMap.OnMapLoadedListener, AMap.OnMapLongClickListener, AMap.OnMapTouchListener,
27 | AMap.OnMarkerClickListener, AMap.OnMarkerDragListener, AMap.OnMyLocationChangeListener, AMap.OnPOIClickListener {
28 |
29 | init {
30 | map.addAMapAppResourceListener(this)
31 | map.addOnCameraChangeListener(this)
32 | map.addOnIndoorBuildingActiveListener(this)
33 | map.addOnInfoWindowClickListener(this)
34 | map.addOnMapClickListener(this)
35 | map.addOnMapLoadedListener(this)
36 | map.addOnMapLongClickListener(this)
37 | map.addOnMapTouchListener(this)
38 | map.addOnMarkerClickListener(this)
39 | map.addOnMarkerDragListener(this)
40 | map.addOnMyLocationChangeListener(this)
41 | map.addOnPOIClickListener(this)
42 | }
43 |
44 | override fun onMapLoaded() {
45 | val map = getIdMap()
46 | map["method"] = "onMapLoaded"
47 | flEventChannel?.send(map)
48 | }
49 |
50 | override fun onMyLocationChange(location: Location?) {
51 | val map = getIdMap()
52 | map["method"] = "onMyLocationChange"
53 | location?.data?.let { map.putAll(it) }
54 | flEventChannel?.send(map)
55 | }
56 |
57 | override fun onCameraChange(position: CameraPosition?) {
58 | val map = getIdMap()
59 | map["method"] = "onCameraChange"
60 | position?.data?.let { map.putAll(it) }
61 | flEventChannel?.send(map)
62 | }
63 |
64 | override fun onCameraChangeFinish(position: CameraPosition?) {
65 | val map = getIdMap()
66 | map["method"] = "onCameraChangeFinish"
67 | position?.data?.let { map.putAll(it) }
68 | flEventChannel?.send(map)
69 | }
70 |
71 | override fun onMapClick(latlng: LatLng?) {
72 | val map = getIdMap()
73 | map["method"] = "onMapClick"
74 | latlng?.let { map.putAll(it.data) }
75 | flEventChannel?.send(map)
76 | }
77 |
78 | override fun onMapLongClick(latlng: LatLng?) {
79 | val map = getIdMap()
80 | map["method"] = "onMapLongClick"
81 | latlng?.let { map.putAll(it.data) }
82 | flEventChannel?.send(map)
83 | }
84 |
85 | override fun onPOIClick(poi: Poi?) {
86 | val map = getIdMap()
87 | map["method"] = "onPOIClick"
88 | poi?.let { map["poi"] = listOf(it.data) }
89 | flEventChannel?.send(map)
90 | }
91 |
92 | override fun onMarkerClick(marker: Marker?): Boolean {
93 | val map = getIdMap()
94 | map["method"] = "onMarkerClick"
95 | marker?.let { map.putAll(it.data) }
96 | flEventChannel?.send(map)
97 | return true
98 | }
99 |
100 | override fun onMarkerDragStart(marker: Marker?) {
101 | val map = getIdMap()
102 | map["method"] = "onMarkerDragStart"
103 | marker?.let { map.putAll(it.data) }
104 | flEventChannel?.send(map)
105 | }
106 |
107 | override fun onMarkerDrag(marker: Marker?) {
108 | val map = getIdMap()
109 | map["method"] = "onMarkerDrag"
110 | marker?.let { map.putAll(it.data) }
111 | flEventChannel?.send(map)
112 | }
113 |
114 | override fun onMarkerDragEnd(marker: Marker?) {
115 | val map = getIdMap()
116 | map["method"] = "onMarkerDragEnd"
117 | marker?.let { map.putAll(it.data) }
118 | flEventChannel?.send(map)
119 | }
120 |
121 |
122 | override fun onRequest(param: AMapAppRequestParam?) {
123 | val map = getIdMap()
124 | map["method"] = "onRequest"
125 | flEventChannel?.send(map)
126 | }
127 |
128 |
129 | override fun OnIndoorBuilding(info: IndoorBuildingInfo?) {
130 | val map = getIdMap()
131 | map["method"] = "onIndoorBuilding"
132 | flEventChannel?.send(map)
133 | }
134 |
135 | override fun onInfoWindowClick(marker: Marker?) {
136 | val map = getIdMap()
137 | map["method"] = "onInfoWindowClick"
138 | marker?.let { map.putAll(it.data) }
139 | flEventChannel?.send(map)
140 | }
141 |
142 |
143 | override fun onTouch(event: MotionEvent?) {
144 | val map = getIdMap()
145 | map["method"] = "onTouch"
146 | flEventChannel?.send(map)
147 | }
148 |
149 |
150 | private fun getIdMap(): MutableMap {
151 | return mutableMapOf("id" to viewId)
152 | }
153 |
154 | fun removeListener() {
155 | map.removeAMapAppResourceListener(this)
156 | map.removeOnCameraChangeListener(this)
157 | map.removeOnIndoorBuildingActiveListener(this)
158 | map.removeOnInfoWindowClickListener(this)
159 | map.removeOnMapClickListener(this)
160 | map.removeOnMapLoadedListener(this)
161 | map.removeOnMapLongClickListener(this)
162 | map.removeOnMapTouchListener(this)
163 | map.removeOnMarkerClickListener(this)
164 | map.removeOnMarkerDragListener(this)
165 | map.removeOnMyLocationChangeListener(this)
166 | map.removeOnPOIClickListener(this)
167 | }
168 |
169 | }
--------------------------------------------------------------------------------
/fl_amap_map/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | .lock
12 | .iml
13 | .metadata
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .packages
33 | .pub-cache/
34 | .pub/
35 | /build/
36 |
37 | # Web related
38 | lib/generated_plugin_registrant.dart
39 |
40 | # Symbolication related
41 | app.*.symbols
42 |
43 | # Obfuscation related
44 | app.*.map.json
45 |
46 | # Android Studio will place build artifacts here
47 | /android/app/debug
48 | /android/app/profile
49 | /android/app/release
50 |
--------------------------------------------------------------------------------
/fl_amap_map/example/README.md:
--------------------------------------------------------------------------------
1 | # example
--------------------------------------------------------------------------------
/fl_amap_map/example/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:flutter_lints/flutter.yaml
--------------------------------------------------------------------------------
/fl_amap_map/example/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /.kotlin
6 | /gradlew.bat
7 | /local.properties
8 | GeneratedPluginRegistrant.java
9 |
10 | # Remember to never publicly share your keystore.
11 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
12 | key.properties
13 | **/*.keystore
14 | **/*.jks
15 | .cxx
16 | .kotlin
17 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/amap.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/amap.jks
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("com.android.application")
3 | id("kotlin-android")
4 | id("dev.flutter.flutter-gradle-plugin")
5 | }
6 |
7 | android {
8 | namespace = "com.fl.amap.example"
9 | compileSdk = flutter.compileSdkVersion
10 |
11 | compileOptions {
12 | sourceCompatibility = JavaVersion.VERSION_21
13 | targetCompatibility = JavaVersion.VERSION_21
14 | }
15 |
16 | kotlinOptions {
17 | jvmTarget = JavaVersion.VERSION_21.toString()
18 | }
19 |
20 | defaultConfig {
21 | applicationId = "com.fl.amap.example"
22 | minSdk = flutter.minSdkVersion
23 | targetSdk = flutter.targetSdkVersion
24 | versionCode = flutter.versionCode
25 | versionName = flutter.versionName
26 | }
27 | signingConfigs {
28 | create("release") {
29 | storeFile = file("amap.jks")
30 | storePassword = "amap123"
31 | keyAlias = "amap"
32 | keyPassword = "amap123"
33 | }
34 | }
35 |
36 | buildTypes {
37 | getByName("debug") {
38 | signingConfig = signingConfigs.getByName("release")
39 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "consumer-rules.pro")
40 | }
41 | getByName("release") {
42 | signingConfig = signingConfigs.getByName("release")
43 | proguardFiles(getDefaultProguardFile("proguard-android.txt"), "consumer-rules.pro")
44 | }
45 | }
46 | }
47 |
48 | flutter {
49 | source = "../.."
50 | }
51 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/kotlin/com/fl/amap/example/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.fl.amap.example
2 |
3 | import androidx.annotation.NonNull
4 | import io.flutter.embedding.android.FlutterActivity
5 | import io.flutter.embedding.engine.FlutterEngine
6 | import io.flutter.plugins.GeneratedPluginRegistrant
7 |
8 | class MainActivity: FlutterActivity() {
9 | override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
10 | GeneratedPluginRegistrant.registerWith(flutterEngine);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
9 | rootProject.layout.buildDirectory.value(newBuildDir)
10 |
11 | subprojects {
12 | val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
13 | project.layout.buildDirectory.value(newSubprojectBuildDir)
14 | }
15 | subprojects {
16 | project.evaluationDependsOn(":app")
17 | }
18 |
19 | tasks.register("clean") {
20 | delete(rootProject.layout.buildDirectory)
21 | }
22 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/fl_amap_map/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
--------------------------------------------------------------------------------
/fl_amap_map/example/android/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | val flutterSdkPath = run {
3 | val properties = java.util.Properties()
4 | file("local.properties").inputStream().use { properties.load(it) }
5 | val flutterSdkPath = properties.getProperty("flutter.sdk")
6 | require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
7 | flutterSdkPath
8 | }
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id("dev.flutter.flutter-plugin-loader") version "1.0.0"
21 | id("com.android.application") version "8.7.0" apply false
22 | id("org.jetbrains.kotlin.android") version "2.0.20" apply false
23 | }
24 |
25 | include(":app")
26 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | platform :ios, '13.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | target 'RunnerTests' do
36 | inherit! :search_paths
37 | end
38 | end
39 |
40 | post_install do |installer|
41 | installer.pods_project.targets.each do |target|
42 | flutter_additional_ios_build_settings(target)
43 | # Start of the permission_handler configuration
44 | target.build_configurations.each do |config|
45 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
46 | '$(inherited)',
47 |
48 | ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
49 | 'PERMISSION_LOCATION=1',
50 | ]
51 | end
52 | # End of the permission_handler configuration
53 | end
54 | end
55 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
43 |
49 |
50 |
51 |
52 |
53 |
64 |
66 |
72 |
73 |
74 |
75 |
81 |
83 |
89 |
90 |
91 |
92 |
94 |
95 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @main
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wayaer/fl_amap/e92db535d2c715d4e41be7326059ec1f5b524dae/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CADisableMinimumFrameDurationOnPhone
6 |
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
9 | CFBundleDisplayName
10 | FlAMap
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | FlAMap
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | $(FLUTTER_BUILD_NUMBER)
27 | LSRequiresIPhoneOS
28 |
29 | NSAppTransportSecurity
30 |
31 | NSAllowsArbitraryLoads
32 |
33 | NSAllowsArbitraryLoadsForMedia
34 |
35 | NSAllowsArbitraryLoadsInWebContent
36 |
37 |
38 | NSLocationAlwaysAndWhenInUseUsageDescription
39 | 获取定位
40 | NSLocationAlwaysUsageDescription
41 | 获取定位
42 | NSLocationWhenInUseUsageDescription
43 | 获取定位
44 | UIApplicationSupportsIndirectInputEvents
45 |
46 | UIBackgroundModes
47 |
48 | fetch
49 | location
50 | processing
51 | remote-notification
52 |
53 | UILaunchStoryboardName
54 | LaunchScreen
55 | UIMainStoryboardFile
56 | Main
57 | UISupportedInterfaceOrientations
58 |
59 | UIInterfaceOrientationLandscapeLeft
60 | UIInterfaceOrientationLandscapeRight
61 | UIInterfaceOrientationPortrait
62 | UIInterfaceOrientationPortraitUpsideDown
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/fl_amap_map/example/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/fl_amap_map/example/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:example/src/map_view_page.dart';
2 | import 'package:fl_amap_map/fl_amap_map.dart';
3 | import 'package:fl_extended/fl_extended.dart';
4 | import 'package:flutter/material.dart';
5 | import 'package:permission_handler/permission_handler.dart';
6 |
7 | void main() {
8 | WidgetsFlutterBinding.ensureInitialized();
9 | runApp(MaterialApp(
10 | navigatorKey: FlExtended().navigatorKey,
11 | scaffoldMessengerKey: FlExtended().scaffoldMessengerKey,
12 | debugShowCheckedModeBanner: false,
13 | theme: ThemeData.light(),
14 | darkTheme: ThemeData.dark(),
15 | title: 'FlAMap',
16 | home: const App()));
17 | }
18 |
19 | class App extends StatelessWidget {
20 | const App({super.key});
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | bool isInit = false;
25 | return Scaffold(
26 | appBar: AppBar(title: const Text('高德地图')),
27 | body: Universal(
28 | width: double.infinity,
29 | mainAxisAlignment: MainAxisAlignment.center,
30 | crossAxisAlignment: CrossAxisAlignment.center,
31 | children: [
32 | ElevatedText(
33 | onPressed: () async {
34 | isInit = await FlAMapMap().setAMapKey(
35 | iosKey: '7d3261c06027bdc87aca547c99ad5b2f',
36 | androidKey: '77418e726d0eefc0ac79a8619b5f4d97',
37 | isAgree: true,
38 | isContains: true,
39 | isShow: true);
40 | showToast('高德地图ApiKey设置$isInit');
41 | },
42 | text: '设置高德key'),
43 | ElevatedText(
44 | onPressed: () async {
45 | if (!isInit) {
46 | showToast('请先设置高德key');
47 | return;
48 | }
49 | if (!await getPermission(Permission.location)) {
50 | showToast('未获取到定位权限');
51 | return;
52 | }
53 | push(const MapViewPage());
54 | },
55 | text: '高德地图'),
56 | ]));
57 | }
58 | }
59 |
60 | class ElevatedText extends StatelessWidget {
61 | const ElevatedText({super.key, required this.text, required this.onPressed});
62 |
63 | final String text;
64 | final VoidCallback onPressed;
65 |
66 | @override
67 | Widget build(BuildContext context) => ElevatedButton(onPressed: onPressed, child: Text(text));
68 | }
69 |
70 | Future getPermission(Permission permission) async {
71 | final PermissionStatus status = await permission.request();
72 | if (!status.isGranted) {
73 | await openAppSettings();
74 | return await permission.request().isGranted;
75 | }
76 | return status.isGranted;
77 | }
78 |
--------------------------------------------------------------------------------
/fl_amap_map/example/lib/src/map_view_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:fl_amap_map/fl_amap_map.dart';
2 | import 'package:flutter/material.dart';
3 |
4 | class MapViewPage extends StatefulWidget {
5 | const MapViewPage({super.key});
6 |
7 | @override
8 | State createState() => _MapViewPageState();
9 | }
10 |
11 | class _MapViewPageState extends State {
12 | AMapController? controller;
13 |
14 | @override
15 | Widget build(BuildContext context) {
16 | return Scaffold(
17 | appBar: AppBar(title: const Text('高德地图')),
18 | body: AMapView(
19 | options: const AMapOptions(
20 | mapType: MapType.standardNight,
21 | showCompass: true,
22 | showMapText: true,
23 | showTraffic: true,
24 | showUserLocation: true,
25 | showUserLocationButton: true,
26 | latLng: LatLng(30.572961, 104.066301)),
27 | onCreateController: (AMapController controller) {
28 | this.controller = controller;
29 | controller.setTrackingMode(TrackingMode.none);
30 | controller.android?.addListener();
31 | controller.ios?.addListener();
32 | }));
33 | }
34 |
35 | @override
36 | void dispose() {
37 | controller?.dispose();
38 | super.dispose();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/fl_amap_map/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: example
2 | description: A new Flutter project.
3 | publish_to: 'none'
4 | version: 1.0.0
5 |
6 | environment:
7 | sdk: '>=3.0.0 <4.0.0'
8 | flutter: '>=3.24.0'
9 |
10 | dependencies:
11 | fl_amap_map:
12 | path: ../
13 | flutter:
14 | sdk: flutter
15 | fl_extended: ^1.7.2
16 | fl_dio: ^1.4.0
17 | flutter_curiosity: ^6.6.0
18 | permission_handler: ^11.4.0
19 |
20 | dev_dependencies:
21 | flutter_lints: ^5.0.0
22 |
23 | flutter:
24 | uses-material-design: true
25 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/Classes/AMapPlugin.swift:
--------------------------------------------------------------------------------
1 | import fl_channel
2 | import Flutter
3 | import MAMapKit
4 |
5 | public class AMapMapPlugin: NSObject, FlutterPlugin {
6 | private var channel: FlutterMethodChannel?
7 | private var binaryMessenger: FlutterBinaryMessenger
8 | public static var flEventChannel: FlEventChannel?
9 |
10 | public static func register(with registrar: FlutterPluginRegistrar) {
11 | let channel = FlutterMethodChannel(name: "fl_amap_map", binaryMessenger:
12 | registrar.messenger())
13 | let instance = AMapMapPlugin(channel, registrar.messenger())
14 | registrar.addMethodCallDelegate(instance, channel: channel)
15 | registrar.register(AMapPlatformViewFactory(registrar), withId: "fl_amap_map", gestureRecognizersBlockingPolicy: FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded)
16 | }
17 |
18 | init(_ channel: FlutterMethodChannel, _ binaryMessenger: FlutterBinaryMessenger) {
19 | self.channel = channel
20 | self.binaryMessenger = binaryMessenger
21 | super.init()
22 | }
23 |
24 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
25 | switch call.method {
26 | case "setApiKey":
27 | let args = call.arguments as! [String: Any?]
28 | let key = args["key"] as! String
29 | let isAgree = args["isAgree"] as! Bool
30 | let isContains = args["isContains"] as! Bool
31 | let isShow = args["isShow"] as! Bool
32 | AMapServices.shared().apiKey = key
33 | AMapServices.shared().enableHTTPS = args["enableHTTPS"] as! Bool
34 | MAMapView.updatePrivacyAgree(isAgree ? .didAgree : .notAgree)
35 | MAMapView.updatePrivacyShow(isShow ? .didShow : .notShow, privacyInfo: isContains ? .didContain : .notContain)
36 | AMapMapPlugin.flEventChannel = FlChannelPlugin.getEventChannel("fl_amap_map_event")
37 | result(true)
38 | default:
39 | result(FlutterMethodNotImplemented)
40 | }
41 | }
42 |
43 | public func detachFromEngine(for registrar: FlutterPluginRegistrar) {
44 | channel?.setMethodCallHandler(nil)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/Classes/Extension.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 | import MAMapKit
3 |
4 | extension Dictionary {
5 | mutating func merge(_ other: S)
6 | where S: Sequence, S.Iterator.Element == (key: Key, value: Value)
7 | {
8 | for (k, v) in other {
9 | self[k] = v
10 | }
11 | }
12 | }
13 |
14 | extension CLLocationCoordinate2D {
15 | var data: [String: Any?] {
16 | [
17 | "longitude": longitude,
18 | "latitude": latitude,
19 | ]
20 | }
21 | }
22 |
23 | extension MATouchPoi {
24 | var data: [String: Any?] {
25 | [
26 | "latLng": coordinate.data,
27 | "name": name,
28 | "poiId": uid,
29 | ]
30 | }
31 | }
32 |
33 | extension CLHeading {
34 | var data: [String: Any?] {
35 | [
36 | "x": x,
37 | "y": y,
38 | "z": z,
39 | "timestamp": timestamp.timeIntervalSince1970,
40 | "magneticHeading": magneticHeading,
41 | "trueHeading": trueHeading,
42 | "headingAccuracy": headingAccuracy,
43 | ]
44 | }
45 | }
46 |
47 | extension CLLocation {
48 | var data: [String: Any?] {
49 | [
50 | "latLng": coordinate.data,
51 | "accuracy": (horizontalAccuracy + verticalAccuracy) / 2,
52 | "altitude": altitude,
53 | "speed": speed,
54 | "timestamp": timestamp.timeIntervalSince1970,
55 | ]
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/Classes/map/AMapPlatformViewFactory.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 |
3 | public class AMapPlatformViewFactory: NSObject, FlutterPlatformViewFactory {
4 | private var registrar: FlutterPluginRegistrar
5 |
6 | init(_ registrar: FlutterPluginRegistrar) {
7 | self.registrar = registrar
8 | super.init()
9 | }
10 |
11 | public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
12 | let channel = FlutterMethodChannel(name: "fl_amap_map_\(viewId)", binaryMessenger: registrar.messenger())
13 | let options = args as! [String: Any]
14 | return AMapView(channel: channel, frame: frame, viewId: viewId, options: options)
15 | }
16 |
17 | public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
18 | FlutterStandardMessageCodec.sharedInstance()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/Classes/map/AMapView.swift:
--------------------------------------------------------------------------------
1 | import AMapFoundationKit
2 | import Flutter
3 | import MAMapKit
4 |
5 | public class AMapView: NSObject, FlutterPlatformView {
6 | private var channel: FlutterMethodChannel?
7 | private var mapview: MAMapView?
8 | private var viewId: Int64
9 | private var mapviewDelegate: AMapViewDelegate?
10 |
11 | init(channel: FlutterMethodChannel, frame: CGRect, viewId: Int64, options: [String: Any]) {
12 | self.channel = channel
13 | self.viewId = viewId
14 | mapview = MAMapView(frame: frame)
15 | super.init()
16 | channel.setMethodCallHandler(handle)
17 | mapview!.accessibilityElementsHidden = false
18 | setOptions(args: options)
19 | }
20 |
21 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
22 | switch call.method {
23 | case "setOptions":
24 | let options = call.arguments as! [String: Any]
25 | setOptions(args: options)
26 | case "reloadMap":
27 | mapview?.reloadMap()
28 | result(true)
29 | case "setRenderFps":
30 | mapview?.maxRenderFrame = UInt(call.arguments as! Int)
31 | result(true)
32 | case "setCenter":
33 | let args = call.arguments as! [String: Any]
34 | mapview?.setCenter(CLLocationCoordinate2D(latitude: args["latitude"] as! Double, longitude: args["longitude"] as! Double), animated: args["animated"] as! Bool)
35 | result(true)
36 | case "setTrackingMode":
37 | let args = call.arguments as! [String: Any]
38 | let mode = args["mode"] as! Int
39 | var trackingMode = MAUserTrackingMode.follow
40 | if mode == 0 {
41 | trackingMode = MAUserTrackingMode.none
42 | } else if mode == 7 {
43 | trackingMode = MAUserTrackingMode.followWithHeading
44 | }
45 | mapview?.setUserTrackingMode(trackingMode, animated: args["animated"] as! Bool)
46 | result(true)
47 | case "addListener":
48 | if mapviewDelegate == nil, mapview != nil {
49 | mapviewDelegate = AMapViewDelegate(viewId)
50 | mapview!.delegate = mapviewDelegate
51 | }
52 | result(mapviewDelegate != nil)
53 | case "removeListener":
54 | mapviewDelegate = nil
55 | mapview?.delegate = nil
56 | result(mapviewDelegate == nil)
57 |
58 | case "dispose":
59 | mapview = nil
60 | mapview?.removeObserver(self, forKeyPath: "frame")
61 | channel?.setMethodCallHandler(nil)
62 | channel = nil
63 | result(true)
64 | case "addOverlays":
65 | // mapview?.addOverlays( /* <#T##overlays: [Any]!##[Any]!#> */, level: <#T##MAOverlayLevel#>)
66 | case "addAnnotation":
67 | let point = MAPointAnnotation()
68 | point.coordinate = CLLocationCoordinate2D(latitude: 39.979590, longitude: 116.352792)
69 | mapview?.addAnnotation(point)
70 | default:
71 | result(FlutterMethodNotImplemented)
72 | }
73 | }
74 |
75 | func setOptions(args: [String: Any?]) {
76 | let animated = args["animated"] as! Bool
77 | mapview?.rotationDegree = CGFloat(args["tilt"] as! Double)
78 | mapview?.isRotateEnabled = args["isTiltGesturesEnabled"] as! Bool
79 | mapview?.cameraDegree = CGFloat(args["bearing"] as! Double)
80 | mapview?.mapType = MAMapType(rawValue: args["mapType"] as! Int) ?? MAMapType.standard
81 | mapview?.setZoomLevel(CGFloat(args["zoom"] as! Double), animated: animated)
82 | mapview?.maxZoomLevel = args["maxZoom"] as! Double
83 | mapview?.minZoomLevel = args["minZoom"] as! Double
84 | mapview?.isZoomEnabled = args["isZoomGesturesEnabled"] as! Bool
85 | mapview?.zoomingInPivotsAroundAnchorPoint = args["zoomingInPivotsAroundAnchorPoint"] as! Bool
86 | mapview?.isRotateCameraEnabled = args["isRotateGesturesEnabled"] as! Bool
87 | mapview?.showsUserLocation = args["showUserLocation"] as! Bool
88 | mapview?.allowsBackgroundLocationUpdates = args["allowsBackgroundLocationUpdates"] as! Bool
89 | mapview?.showsCompass = args["showCompass"] as! Bool
90 | mapview?.showsScale = args["showScale"] as! Bool
91 | mapview?.isScrollEnabled = args["isScrollGesturesEnabled"] as! Bool
92 | mapview?.touchPOIEnabled = args["isTouchPoiEnable"] as! Bool
93 | mapview?.isShowTraffic = args["showTraffic"] as! Bool
94 | mapview?.isShowsIndoorMap = args["showIndoorMap"] as! Bool
95 | mapview?.isShowsLabels = args["showMapText"] as! Bool
96 | mapview?.isShowsBuildings = args["showBuildings"] as! Bool
97 | mapview?.mapLanguage = NSNumber(value: args["language"] as! Int)
98 | mapview?.centerCoordinate = CLLocationCoordinate2D(latitude: args["latitude"] as! Double, longitude: args["longitude"] as! Double)
99 | }
100 |
101 | public func view() -> UIView {
102 | mapview!
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/Resources/PrivacyInfo.xcprivacy:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSPrivacyTrackingDomains
6 |
7 | NSPrivacyAccessedAPITypes
8 |
9 | NSPrivacyCollectedDataTypes
10 |
11 | NSPrivacyTracking
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/fl_amap_map/ios/fl_amap_map.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
3 | #
4 | Pod::Spec.new do |s|
5 | s.name = 'fl_amap_map'
6 | s.version = '0.0.1'
7 | s.summary = 'A Flutter plugin.'
8 | s.description = <<-DESC
9 | A new Flutter plugin.
10 | DESC
11 | s.homepage = 'https://github.com/Wayaer/fl_amap.git'
12 | s.license = { :file => '../LICENSE' }
13 | s.author = { 'email' => 'wayaer@foxmail.com' }
14 | s.source = { :path => '.' }
15 | s.source_files = 'Classes/**/*'
16 | s.dependency 'Flutter'
17 | s.dependency 'AMap3DMap'
18 | s.dependency 'fl_channel'
19 | s.static_framework = true
20 | s.ios.deployment_target = '12.0'
21 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
22 | s.swift_version = '5.0'
23 |
24 | end
25 |
26 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/fl_amap_map.dart:
--------------------------------------------------------------------------------
1 | import 'dart:async';
2 | import 'dart:ffi';
3 |
4 | import 'package:fl_channel/fl_channel.dart';
5 | import 'package:flutter/foundation.dart';
6 | import 'package:flutter/gestures.dart';
7 | import 'package:flutter/material.dart';
8 | import 'package:flutter/services.dart';
9 |
10 | part 'src/amap_view.dart';
11 |
12 | part 'src/controller.dart';
13 |
14 | part 'src/model.dart';
15 |
16 | part 'src/enum.dart';
17 |
18 | part 'src/controller_for_android.dart';
19 |
20 | part 'src/controller_for_ios.dart';
21 |
22 | class FlAMapMap {
23 | final MethodChannel _channel = MethodChannel('fl_amap_map');
24 |
25 | factory FlAMapMap() => _singleton ??= FlAMapMap._();
26 |
27 | FlAMapMap._();
28 |
29 | static FlAMapMap? _singleton;
30 |
31 | FlEventChannel? _flEventChannel;
32 |
33 | /// 设置ios&android的key
34 | Future setAMapKey({
35 | required String iosKey,
36 | required String androidKey,
37 |
38 | /// 设置是否同意用户授权政策 设置为true才可以调用其他功能
39 | bool isAgree = true,
40 |
41 | /// 设置包含隐私政策 设置为true才可以调用其他功能
42 | bool isContains = true,
43 |
44 | /// 并展示用户授权弹窗 设置为true才可以调用其他功能
45 | bool isShow = true,
46 | bool enableHTTPS = true,
47 | }) async {
48 | if (!_supportPlatform) return false;
49 | String? key;
50 | if (_isAndroid) key = androidKey;
51 | if (_isIOS) key = iosKey;
52 | if (key == null) return false;
53 | _flEventChannel ??= await FlChannel().create('${_channel.name}_event');
54 | final state = await _channel.invokeMethod(
55 | 'setApiKey', {'key': key, 'isAgree': isAgree, 'isContains': isContains, 'isShow': isShow, 'enableHTTPS': enableHTTPS});
56 | return state ?? false;
57 | }
58 |
59 | void dispose() {
60 | _flEventChannel?.dispose();
61 | _flEventChannel = null;
62 | }
63 | }
64 |
65 | bool get _supportPlatform {
66 | if (!kIsWeb && (_isAndroid || _isIOS)) return true;
67 | debugPrint('Not support platform for $defaultTargetPlatform');
68 | return false;
69 | }
70 |
71 | bool get _isAndroid => defaultTargetPlatform == TargetPlatform.android;
72 |
73 | bool get _isIOS => defaultTargetPlatform == TargetPlatform.iOS;
74 |
75 | class LatLng {
76 | const LatLng(this.latitude, this.longitude);
77 |
78 | LatLng.fromMap(Map map)
79 | : latitude = map['latitude'] as double?,
80 | longitude = map['longitude'] as double?;
81 |
82 | final double? latitude;
83 | final double? longitude;
84 |
85 | Map toMap() => {'latitude': latitude, 'longitude': longitude};
86 | }
87 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/src/amap_view.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap_map.dart';
2 |
3 | typedef OnAMapControllerCreated = void Function(AMapController controller);
4 |
5 | class AMapView extends StatefulWidget {
6 | const AMapView(
7 | {super.key,
8 | this.gestureRecognizers,
9 | this.onCreateController,
10 | this.options = const AMapOptions(latLng: LatLng(30.651411, 103.998638))});
11 |
12 | /// 需要应用到地图上的手势集合
13 | final Set>? gestureRecognizers;
14 |
15 | /// AMapController 回调
16 | final OnAMapControllerCreated? onCreateController;
17 |
18 | /// 初始配置信息
19 | final AMapOptions options;
20 |
21 | @override
22 | State createState() => _AMapViewState();
23 | }
24 |
25 | class _AMapViewState extends State {
26 | @override
27 | Widget build(BuildContext context) {
28 | if (defaultTargetPlatform == TargetPlatform.android) {
29 | return AndroidView(
30 | viewType: 'fl_amap_map',
31 | onPlatformViewCreated: onPlatformViewCreated,
32 | gestureRecognizers: widget.gestureRecognizers,
33 | creationParams: widget.options.toMap(),
34 | creationParamsCodec: const StandardMessageCodec());
35 | } else if (defaultTargetPlatform == TargetPlatform.iOS) {
36 | return UiKitView(
37 | viewType: 'fl_amap_map',
38 | onPlatformViewCreated: onPlatformViewCreated,
39 | gestureRecognizers: widget.gestureRecognizers,
40 | creationParams: widget.options.toMap(),
41 | creationParamsCodec: const StandardMessageCodec());
42 | }
43 | return Text('当前平台:$defaultTargetPlatform, 不支持使用高德地图插件');
44 | }
45 |
46 | Future onPlatformViewCreated(int id) async {
47 | final AMapController controller = AMapController(id: id);
48 | widget.onCreateController?.call(controller);
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/src/controller.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap_map.dart';
2 |
3 | class AMapController {
4 | AMapController({required this.id}) {
5 | _channel = MethodChannel('fl_amap_map_$id');
6 | if (_isAndroid) _android = AMapControllerForAndroid(_channel, id);
7 | if (_isIOS) _ios = AMapControllerForIOS(_channel, id);
8 | }
9 |
10 | final int id;
11 |
12 | late MethodChannel _channel;
13 |
14 | /// 仅 android 可用
15 | AMapControllerForAndroid? _android;
16 |
17 | AMapControllerForAndroid? get android => _android;
18 |
19 | /// 仅 ios 可用
20 | AMapControllerForIOS? _ios;
21 |
22 | AMapControllerForIOS? get ios => _ios;
23 |
24 | /// 设置地图配置信息
25 | Future setOptions(AMapOptions options) async {
26 | final result = await _channel.invokeMethod('setOptions', options.toMap());
27 | return result ?? false;
28 | }
29 |
30 | /// 销毁地图
31 | Future dispose() async {
32 | final result = await _channel.invokeMethod('dispose');
33 | return result ?? false;
34 | }
35 |
36 | /// 最大帧数,有效的帧数为:60、30、20、10等能被60整除的数。默认为60
37 | Future setRenderFps(int fps) async {
38 | final result = await _channel.invokeMethod('setRenderFps', fps);
39 | return result ?? false;
40 | }
41 |
42 | /// 重新加载地图
43 | Future reloadMap() async {
44 | final result = await _channel.invokeMethod('reloadMap');
45 | return result ?? false;
46 | }
47 |
48 | /// 设置地图定位跟随模式
49 | Future setTrackingMode(TrackingMode mode, {bool animated = true}) async {
50 | int modeIndex = mode.index;
51 | if (modeIndex > 2 && _isIOS) modeIndex = 1;
52 | final result = await _channel.invokeMethod('setTrackingMode', {
53 | 'mode': modeIndex,
54 | 'animated': animated,
55 | });
56 | return result ?? false;
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/src/controller_for_android.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap_map.dart';
2 |
3 | typedef AMapLocationChangeListener = void Function(Location location);
4 | typedef AMapLoadedListener = void Function();
5 | typedef AMapLatLngListener = void Function(LatLng latLng);
6 | typedef AMapPOIPressedListener = void Function(List poi);
7 | typedef AMapMarkerPressedListener = void Function(Marker marker);
8 |
9 | class AMapControllerForAndroid {
10 | AMapControllerForAndroid(this._channel, this._id);
11 |
12 | final MethodChannel _channel;
13 | final int _id;
14 |
15 | /// 添加回调监听
16 | Future addListener({
17 | /// 定位改变回调
18 | AMapLocationChangeListener? onLocationChange,
19 |
20 | /// 地图加载完成回调
21 | AMapLoadedListener? onMapLoaded,
22 |
23 | /// 单击地图回调
24 | AMapLatLngListener? onMapPressed,
25 |
26 | /// 长按地图回调
27 | AMapLatLngListener? onMapLongPressed,
28 |
29 | /// poi 点击回调
30 | AMapPOIPressedListener? onPOIPressed,
31 |
32 | /// marker 点击回调
33 | AMapMarkerPressedListener? onMarkerPressed,
34 | }) async {
35 | /// 初始化原生sdk listener
36 | final result = await _channel.invokeMethod('addListener');
37 |
38 | /// 添加消息监听通道
39 | FlAMapMap()._flEventChannel?.listen((data) {
40 | if (data is! Map || data['id'] != _id) return;
41 | final method = data['method'];
42 | debugPrint('消息回调==$method===$data');
43 | switch (method) {
44 | case 'Loaded':
45 | onMapLoaded?.call();
46 | break;
47 | case 'LocationChange':
48 | onLocationChange?.call(Location.fromMap(data));
49 | break;
50 | case 'Pressed':
51 | onMapPressed?.call(LatLng.fromMap(data));
52 | break;
53 | case 'LongPressed':
54 | onMapLongPressed?.call(LatLng.fromMap(data));
55 | break;
56 | case 'MarkerPressed':
57 | onMarkerPressed?.call(Marker.formMap(data));
58 | break;
59 | case 'POIPressed':
60 | onPOIPressed?.call(getPoiList(data['poi']));
61 | break;
62 | }
63 | });
64 | return result == true;
65 | }
66 |
67 | /// 重新加载地图
68 | Future addMarker() async {
69 | final marker = await _channel.invokeMapMethod('addMarker');
70 | return marker == null ? null : Marker.formMap(marker);
71 | }
72 | }
73 |
74 | class MarkerOptions {}
75 |
76 | class Marker {
77 | Marker.formMap(Map map)
78 | : title = map['title'] as String?,
79 | snippet = map['snippet'] as String?,
80 | draggable = map['draggable'] as bool?,
81 | visible = map['visible'] as bool?,
82 | alpha = map['alpha'] as Double?,
83 | latLng = LatLng.fromMap(map['latLng']);
84 |
85 | /// 在地图上标记位置的经纬度值
86 | final LatLng? latLng;
87 |
88 | /// 点标记的标题
89 | final String? title;
90 |
91 | /// 点标记的内容
92 | final String? snippet;
93 |
94 | /// 点标记是否可拖拽
95 | final bool? draggable;
96 |
97 | /// 点标记是否可见
98 | final bool? visible;
99 |
100 | /// 点的透明度
101 | final Double? alpha;
102 | }
103 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/src/controller_for_ios.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap_map.dart';
2 |
3 | class AMapControllerForIOS {
4 | const AMapControllerForIOS(this._channel, this._id);
5 |
6 | final MethodChannel _channel;
7 | final int _id;
8 |
9 | /// 添加回调监听
10 | Future addListener() async {
11 | /// 初始化原生sdk listener
12 | final result = await _channel.invokeMethod('addListener');
13 |
14 | /// 添加消息监听通道
15 | FlAMapMap()._flEventChannel?.listen((data) {
16 | if (data is! Map || data['id'] != _id) return;
17 | final method = data['method'];
18 | debugPrint('消息回调==$method===$data');
19 | switch (method) {}
20 | });
21 | return result == true;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/fl_amap_map/lib/src/enum.dart:
--------------------------------------------------------------------------------
1 | part of '../fl_amap_map.dart';
2 |
3 | enum MapType {
4 | /// 普通地图 ios 0 android 1
5 | standard,
6 |
7 | /// 卫星地图 ios 1 android 2
8 | satellite,
9 |
10 | /// 黑夜地图 ios 2 android 3
11 | standardNight,
12 |
13 | /// 导航模式 ios 3 android 4
14 | navi,
15 |
16 | /// 公交模式 ios 4 android 5
17 | bus,
18 | }
19 |
20 | enum MapLanguage { chinese, english }
21 |
22 | enum TrackingMode {
23 | /// 不追踪用户的location更新
24 | none,
25 |
26 | /// 定位一次,且将视角移动到地图中心点。
27 | locate,
28 |
29 | /// 连续定位、且将视角移动到地图中心点,定位蓝点跟随设备移动。(1秒1次定位)
30 | follow,
31 |
32 | /// 连续定位、且将视角移动到地图中心点,地图依照设备方向旋转,定位点会跟随设备移动。(1秒1次定位)
33 | /// 仅支持 Android
34 | followRotate,
35 |
36 | /// 连续定位、且将视角移动到地图中心点,定位点依照设备方向旋转,并且会跟随设备移动。(1秒1次定位)默认执行此种模式。
37 | /// 仅支持 Android
38 | followLocationRotate,
39 |
40 | /// 连续定位、蓝点不会移动到地图中心点,定位点依照设备方向旋转,并且蓝点会跟随设备移动。
41 | /// 仅支持 Android
42 | followLocationRotateNoCenter,
43 |
44 | /// 连续定位、蓝点不会移动到地图中心点,地图依照设备方向旋转,并且蓝点会跟随设备移动。
45 | /// 仅支持 Android
46 | followRotateNoCenter,
47 |
48 | /// 追踪用户的location与heading更新
49 | /// 仅支持 IOS
50 | followWithHeading,
51 | }
52 |
--------------------------------------------------------------------------------
/fl_amap_map/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: fl_amap_map
2 | description: AMap location and AMap plugin for flutter, supports single positioning and continuous positioning
3 | version: 0.0.1
4 | repository: https://github.com/Wayaer/fl_amap/tree/main/fl_amap_amap
5 |
6 | environment:
7 | sdk: '>=3.0.0 <4.0.0'
8 | flutter: '>=3.24.0'
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | fl_channel: ^1.0.3
14 |
15 | dev_dependencies:
16 | flutter_lints: ^5.0.0
17 |
18 | flutter:
19 | plugin:
20 | platforms:
21 | android:
22 | package: fl.amap.map
23 | pluginClass: AMapMapPlugin
24 | ios:
25 | pluginClass: AMapMapPlugin
26 |
--------------------------------------------------------------------------------
/format.sh:
--------------------------------------------------------------------------------
1 | dart format fl_amap/lib
2 | dart format fl_amap/example/lib
3 | dart format fl_amap_map/lib
4 | dart format fl_amap_map/example/lib
5 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: fl_amap
2 | description: AMap plugin for flutter
3 | version: 1.0.0
4 | repository: https://github.com/Wayaer/fl_amap
5 |
6 | environment:
7 | sdk: '>=3.0.0 <4.0.0'
8 | flutter: '>=3.29.0'
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 |
14 | dev_dependencies:
15 | flutter_lints: ^5.0.0
16 |
--------------------------------------------------------------------------------