Commit 76a8d3050c4d6a705081bded8166d96cd99c80e4
1 parent
0c299ac9
新增定位模块
Showing
9 changed files
with
1125 additions
and
2 deletions
lib/android/build.gradle
lib/android/src/main/AndroidManifest.xml
... | ... | @@ -7,4 +7,13 @@ |
7 | 7 | <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> |
8 | 8 | <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
9 | 9 | <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> |
10 | + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> | |
11 | + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> | |
12 | + <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> | |
13 | + <uses-permission android:name="android.permission.BLUETOOTH" /> | |
14 | + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> | |
15 | + | |
16 | + <application> | |
17 | + <service android:name="com.amap.api.location.APSService" /> | |
18 | + </application> | |
10 | 19 | </manifest> | ... | ... |
lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt
... | ... | @@ -6,11 +6,13 @@ import com.facebook.react.bridge.ReactApplicationContext |
6 | 6 | import com.facebook.react.uimanager.ViewManager |
7 | 7 | import cn.feewee.amap3d.map_view.* |
8 | 8 | import cn.feewee.amap3d.modules.SdkModule |
9 | +import cn.feewee.amap3d.modules.AMapGeolocationModule | |
9 | 10 | |
10 | 11 | class AMap3DPackage : ReactPackage { |
11 | 12 | override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { |
12 | 13 | return listOf( |
13 | 14 | SdkModule(reactContext), |
15 | + new AMapGeolocationModule(reactContext) | |
14 | 16 | ) |
15 | 17 | } |
16 | 18 | ... | ... |
lib/android/src/main/java/cn/feewee/amap3d/modules/AMapGeolocationModule.java
0 → 100644
1 | +package cn.feewee.amap3d.modules; | |
2 | + | |
3 | +import com.amap.api.location.AMapLocation; | |
4 | +import com.amap.api.location.AMapLocationClient; | |
5 | +import com.amap.api.location.AMapLocationClientOption; | |
6 | +import com.amap.api.location.AMapLocationListener; | |
7 | +import com.facebook.react.bridge.*; | |
8 | +import com.facebook.react.modules.core.DeviceEventManagerModule; | |
9 | +import org.jetbrains.annotations.NotNull; | |
10 | + | |
11 | +@SuppressWarnings("unused") | |
12 | +public class AMapGeolocationModule extends ReactContextBaseJavaModule implements AMapLocationListener { | |
13 | + private final ReactApplicationContext reactContext; | |
14 | + private final AMapLocationClientOption option = new AMapLocationClientOption(); | |
15 | + private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter; | |
16 | + private AMapLocationClient client; | |
17 | + | |
18 | + AMapGeolocationModule(ReactApplicationContext reactContext) { | |
19 | + super(reactContext); | |
20 | + this.reactContext = reactContext; | |
21 | + } | |
22 | + | |
23 | + @NotNull | |
24 | + @Override | |
25 | + public String getName() { | |
26 | + return "AMapGeolocation"; | |
27 | + } | |
28 | + | |
29 | + @Override | |
30 | + public void onLocationChanged(AMapLocation location) { | |
31 | + if (location != null) { | |
32 | + eventEmitter.emit("AMapGeolocation", toJSON(location)); | |
33 | + } | |
34 | + } | |
35 | + | |
36 | + @ReactMethod | |
37 | + public void init(String key, Promise promise) throws Exception { | |
38 | + if (client != null) { | |
39 | + client.onDestroy(); | |
40 | + } | |
41 | + | |
42 | + AMapLocationClient.setApiKey(key); | |
43 | + AMapLocationClient.updatePrivacyShow(reactContext, true, true); | |
44 | + AMapLocationClient.updatePrivacyAgree(reactContext, true); | |
45 | + client = new AMapLocationClient(reactContext); | |
46 | + client.setLocationListener(this); | |
47 | + eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); | |
48 | + promise.resolve(null); | |
49 | + } | |
50 | + | |
51 | + @ReactMethod | |
52 | + public void start() { | |
53 | + client.startLocation(); | |
54 | + } | |
55 | + | |
56 | + @ReactMethod | |
57 | + public void stop() { | |
58 | + client.stopLocation(); | |
59 | + } | |
60 | + | |
61 | + @ReactMethod | |
62 | + public void addListener(String name) { | |
63 | + } | |
64 | + | |
65 | + @ReactMethod | |
66 | + public void removeListeners(Integer count) { | |
67 | + } | |
68 | + | |
69 | + @ReactMethod | |
70 | + public void isStarted(Promise promise) { | |
71 | + promise.resolve(client.isStarted()); | |
72 | + } | |
73 | + | |
74 | + @ReactMethod | |
75 | + public void getLastKnownLocation(Promise promise) { | |
76 | + promise.resolve(toJSON(client.getLastKnownLocation())); | |
77 | + } | |
78 | + | |
79 | + @ReactMethod | |
80 | + public void setOnceLocation(boolean value) { | |
81 | + option.setOnceLocation(value); | |
82 | + client.setLocationOption(option); | |
83 | + } | |
84 | + | |
85 | + @ReactMethod | |
86 | + public void setWifiScan(boolean value) { | |
87 | + option.setWifiScan(value); | |
88 | + client.setLocationOption(option); | |
89 | + } | |
90 | + | |
91 | + @ReactMethod | |
92 | + public void setInterval(int interval) { | |
93 | + option.setInterval(interval); | |
94 | + client.setLocationOption(option); | |
95 | + } | |
96 | + | |
97 | + @ReactMethod | |
98 | + public void setSensorEnable(boolean value) { | |
99 | + option.setSensorEnable(value); | |
100 | + client.setLocationOption(option); | |
101 | + } | |
102 | + | |
103 | + @ReactMethod | |
104 | + public void setOpenAlwaysScanWifi(boolean value) { | |
105 | + AMapLocationClientOption.setOpenAlwaysScanWifi(value); | |
106 | + client.setLocationOption(option); | |
107 | + } | |
108 | + | |
109 | + @ReactMethod | |
110 | + public void setNeedAddress(boolean value) { | |
111 | + option.setNeedAddress(value); | |
112 | + client.setLocationOption(option); | |
113 | + } | |
114 | + | |
115 | + @ReactMethod | |
116 | + public void setOnceLocationLatest(boolean value) { | |
117 | + option.setOnceLocationLatest(value); | |
118 | + client.setLocationOption(option); | |
119 | + } | |
120 | + | |
121 | + @ReactMethod | |
122 | + public void setMockEnable(boolean value) { | |
123 | + option.setMockEnable(value); | |
124 | + client.setLocationOption(option); | |
125 | + } | |
126 | + | |
127 | + @ReactMethod | |
128 | + public void setLocationCacheEnable(boolean value) { | |
129 | + option.setLocationCacheEnable(value); | |
130 | + client.setLocationOption(option); | |
131 | + } | |
132 | + | |
133 | + @ReactMethod | |
134 | + public void setGpsFirst(boolean value) { | |
135 | + option.setGpsFirst(value); | |
136 | + client.setLocationOption(option); | |
137 | + } | |
138 | + | |
139 | + @ReactMethod | |
140 | + public void setHttpTimeout(int value) { | |
141 | + option.setHttpTimeOut(value); | |
142 | + client.setLocationOption(option); | |
143 | + } | |
144 | + | |
145 | + @ReactMethod | |
146 | + public void setGpsFirstTimeout(int value) { | |
147 | + option.setGpsFirstTimeout(value); | |
148 | + client.setLocationOption(option); | |
149 | + } | |
150 | + | |
151 | + @ReactMethod | |
152 | + public void setLocationMode(String mode) { | |
153 | + option.setLocationMode(AMapLocationClientOption.AMapLocationMode.valueOf(mode)); | |
154 | + client.setLocationOption(option); | |
155 | + } | |
156 | + | |
157 | + @ReactMethod | |
158 | + public void setLocationPurpose(String purpose) { | |
159 | + option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.valueOf(purpose)); | |
160 | + client.setLocationOption(option); | |
161 | + } | |
162 | + | |
163 | + @ReactMethod | |
164 | + public void setGeoLanguage(String language) { | |
165 | + option.setGeoLanguage(AMapLocationClientOption.GeoLanguage.valueOf(language)); | |
166 | + client.setLocationOption(option); | |
167 | + } | |
168 | + | |
169 | + private ReadableMap toJSON(AMapLocation location) { | |
170 | + if (location == null) { | |
171 | + return null; | |
172 | + } | |
173 | + WritableMap map = Arguments.createMap(); | |
174 | + map.putInt("errorCode", location.getErrorCode()); | |
175 | + map.putString("errorInfo", location.getErrorInfo()); | |
176 | + map.putString("locationDetail", location.getLocationDetail()); | |
177 | + if (location.getErrorCode() == AMapLocation.LOCATION_SUCCESS) { | |
178 | + map.putDouble("timestamp", location.getTime()); | |
179 | + map.putDouble("accuracy", location.getAccuracy()); | |
180 | + map.putDouble("latitude", location.getLatitude()); | |
181 | + map.putDouble("longitude", location.getLongitude()); | |
182 | + map.putDouble("altitude", location.getAltitude()); | |
183 | + map.putDouble("speed", location.getSpeed()); | |
184 | + map.putDouble("heading", location.getBearing()); | |
185 | + map.putInt("locationType", location.getLocationType()); | |
186 | + map.putString("coordinateType", location.getCoordType()); | |
187 | + map.putInt("gpsAccuracy", location.getGpsAccuracyStatus()); | |
188 | + map.putInt("trustedLevel", location.getTrustedLevel()); | |
189 | + if (!location.getAddress().isEmpty()) { | |
190 | + map.putString("address", location.getAddress()); | |
191 | + map.putString("description", location.getDescription()); | |
192 | + map.putString("poiName", location.getPoiName()); | |
193 | + map.putString("country", location.getCountry()); | |
194 | + map.putString("province", location.getProvince()); | |
195 | + map.putString("city", location.getCity()); | |
196 | + map.putString("cityCode", location.getCityCode()); | |
197 | + map.putString("district", location.getDistrict()); | |
198 | + map.putString("street", location.getStreet()); | |
199 | + map.putString("streetNumber", location.getStreetNum()); | |
200 | + map.putString("adCode", location.getAdCode()); | |
201 | + } | |
202 | + } | |
203 | + return map; | |
204 | + } | |
205 | +} | ... | ... |
lib/src/amap-geolocation.ts
0 → 100644
1 | +import { NativeModules, NativeEventEmitter, Platform } from "react-native"; | |
2 | +import { ILocation as Location, ReGeocode, AppKey, LocationMode, LocationPurpose, GeoLanguage } from "./gen-types"; | |
3 | + | |
4 | +const AMapGeolocation = NativeModules.AMapGeolocation; | |
5 | +const eventEmitter = new NativeEventEmitter(AMapGeolocation); | |
6 | + | |
7 | +/** | |
8 | + * 初始化 SDK | |
9 | + * | |
10 | + * @param key 高德开放平台应用 Key | |
11 | + */ | |
12 | +export function init(key: AppKey): Promise<void> { | |
13 | + return AMapGeolocation.init(Platform.select(key)); | |
14 | +} | |
15 | + | |
16 | +/** | |
17 | + * 添加定位监听函数 | |
18 | + * | |
19 | + * @param listener | |
20 | + */ | |
21 | +export function addLocationListener(listener: (location: Location & ReGeocode) => void) { | |
22 | + return eventEmitter.addListener("AMapGeolocation", listener); | |
23 | +} | |
24 | + | |
25 | +/** | |
26 | + * 开始持续定位 | |
27 | + */ | |
28 | +export function start() { | |
29 | + AMapGeolocation.start(); | |
30 | +} | |
31 | + | |
32 | +/** | |
33 | + * 停止持续定位 | |
34 | + */ | |
35 | +export function stop() { | |
36 | + AMapGeolocation.stop(); | |
37 | +} | |
38 | + | |
39 | +/** | |
40 | + * 获取当前是否正在定位的状态 | |
41 | + * | |
42 | + * @platform android | |
43 | + */ | |
44 | +export function isStarted(): boolean { | |
45 | + return AMapGeolocation.isStarted(); | |
46 | +} | |
47 | + | |
48 | +/** | |
49 | + * 设置发起定位请求的时间间隔(毫秒),默认 2000,最小值为 1000 | |
50 | + * | |
51 | + * @default 2000 | |
52 | + * @platform android | |
53 | + */ | |
54 | +export function setInterval(interval: number) { | |
55 | + if (Platform.OS === "android") { | |
56 | + AMapGeolocation.setInterval(interval); | |
57 | + } | |
58 | +} | |
59 | + | |
60 | +/** | |
61 | + * 设置是否单次定位 | |
62 | + * | |
63 | + * @default false | |
64 | + * @platform android | |
65 | + */ | |
66 | +export function setOnceLocation(isOnceLocation: boolean) { | |
67 | + if (Platform.OS === "android") { | |
68 | + AMapGeolocation.setOnceLocation(isOnceLocation); | |
69 | + } | |
70 | +} | |
71 | + | |
72 | +/** | |
73 | + * 设置是否允许调用 WiFi 刷新 | |
74 | + * | |
75 | + * 当设置为 `false` 时会停止主动调用 wifi 刷新,将会极大程度影响定位精度, | |
76 | + * 但可以有效的降低定位耗电。 | |
77 | + * | |
78 | + * @default true | |
79 | + * @platform android | |
80 | + */ | |
81 | +export function setWifiScan(isWifiScan: boolean) { | |
82 | + if (Platform.OS === "android") { | |
83 | + AMapGeolocation.setWifiScan(isWifiScan); | |
84 | + } | |
85 | +} | |
86 | + | |
87 | +/** | |
88 | + * 设置是否使用设备传感器 | |
89 | + * | |
90 | + * @default false | |
91 | + * @platform android | |
92 | + */ | |
93 | +export function setSensorEnable(enable: boolean) { | |
94 | + if (Platform.OS === "android") { | |
95 | + AMapGeolocation.setSensorEnable(enable); | |
96 | + } | |
97 | +} | |
98 | + | |
99 | +/** | |
100 | + * 设置是否开启wifi始终扫描 | |
101 | + * | |
102 | + * 只有设置了 `android.permission.WRITE_SECURE_SETTINGS` 权限后才会开启。 | |
103 | + * 开启后,即使关闭 wifi 开关的情况下也会扫描 wifi。 | |
104 | + * 此方法为静态方法,设置一次后其他定位 client 也会生效。 | |
105 | + * | |
106 | + * @default true | |
107 | + * @platform android | |
108 | + */ | |
109 | +export function setOpenAlwaysScanWifi(isOpen: boolean) { | |
110 | + if (Platform.OS === "android") { | |
111 | + AMapGeolocation.setOpenAlwaysScanWifi(isOpen); | |
112 | + } | |
113 | +} | |
114 | + | |
115 | +/** | |
116 | + * 设置定位是否等待 WiFi 列表刷新 | |
117 | + * | |
118 | + * 定位精度会更高,但是定位速度会变慢 1-3 秒, | |
119 | + * 当设置为 `true` 时,连续定位会自动变为单次定位。 | |
120 | + * | |
121 | + * @default false | |
122 | + * @platform android | |
123 | + */ | |
124 | +export function setOnceLocationLatest(isOnceLocationLatest: boolean) { | |
125 | + if (Platform.OS === "android") { | |
126 | + AMapGeolocation.setOnceLocationLatest(isOnceLocationLatest); | |
127 | + } | |
128 | +} | |
129 | + | |
130 | +/** | |
131 | + * 设置是否返回地址信息,默认返回地址信息 | |
132 | + * | |
133 | + * GPS 定位时也可以返回地址信息,但需要网络通畅,第一次有可能没有地址信息返回。 | |
134 | + * | |
135 | + * @default true | |
136 | + * @platform android | |
137 | + */ | |
138 | +export function setNeedAddress(isNeedAddress: boolean) { | |
139 | + if (Platform.OS === "android") { | |
140 | + AMapGeolocation.setNeedAddress(isNeedAddress); | |
141 | + } | |
142 | +} | |
143 | + | |
144 | +/** | |
145 | + * 设置是否允许模拟位置 | |
146 | + * | |
147 | + * @default true | |
148 | + * @platform android | |
149 | + */ | |
150 | +export function setMockEnable(enable: boolean) { | |
151 | + if (Platform.OS === "android") { | |
152 | + AMapGeolocation.setMockEnable(enable); | |
153 | + } | |
154 | +} | |
155 | + | |
156 | +/** | |
157 | + * 设置是否使用缓存策略 | |
158 | + * | |
159 | + * @default true | |
160 | + * @platform android | |
161 | + */ | |
162 | +export function setLocationCacheEnable(enable: boolean) { | |
163 | + if (Platform.OS === "android") { | |
164 | + AMapGeolocation.setLocationCacheEnable(enable); | |
165 | + } | |
166 | +} | |
167 | + | |
168 | +/** | |
169 | + * 设置联网超时时间(毫秒) | |
170 | + * | |
171 | + * @default 30000 | |
172 | + * @platform android | |
173 | + */ | |
174 | +export function setHttpTimeout(timeout: number) { | |
175 | + if (Platform.OS === "android") { | |
176 | + AMapGeolocation.setHttpTimeout(timeout); | |
177 | + } | |
178 | +} | |
179 | + | |
180 | +/** | |
181 | + * 设置优先返回卫星定位信息时等待卫星定位结果的超时时间(毫秒) | |
182 | + * | |
183 | + * 只有在 `setGpsFirst(true)` 时才有效。 | |
184 | + * | |
185 | + * @platform android | |
186 | + */ | |
187 | +export function setGpsFirstTimeout(timeout: number) { | |
188 | + if (Platform.OS === "android") { | |
189 | + AMapGeolocation.setGpsFirstTimeout(timeout); | |
190 | + } | |
191 | +} | |
192 | + | |
193 | +/** | |
194 | + * 设置首次定位是否等待卫星定位结果 | |
195 | + * | |
196 | + * 只有在单次定位高精度定位模式下有效,设置为 `true` 时,会等待卫星定位结果返回, | |
197 | + * 最多等待 30 秒,若 30 秒后仍无卫星定位结果返回,返回网络定位结果。 | |
198 | + * 等待卫星定位结果返回的时间可以通过 [[setGpsFirstTimeout]] 进行设置。 | |
199 | + * | |
200 | + * @default false | |
201 | + * @platform android | |
202 | + */ | |
203 | +export function setGpsFirst(isGpsFirst: boolean) { | |
204 | + if (Platform.OS === "android") { | |
205 | + AMapGeolocation.setGpsFirst(isGpsFirst); | |
206 | + } | |
207 | +} | |
208 | + | |
209 | +/** | |
210 | + * 设置定位模式 | |
211 | + * | |
212 | + * @platform android | |
213 | + */ | |
214 | +export function setLocationMode(mode: LocationMode) { | |
215 | + if (Platform.OS === "android") { | |
216 | + AMapGeolocation.setLocationMode(mode); | |
217 | + } | |
218 | +} | |
219 | + | |
220 | +/** | |
221 | + * 设置定位场景 | |
222 | + * | |
223 | + * 根据场景快速修改 option,不支持动态改变,修改后需要调用 [[start]] 使其生效,当不需要场景时,可以设置为 `null`。 | |
224 | + * | |
225 | + * 注意:不建议设置场景和自定义 option 混合使用。设置场景后,如果已经开始定位了,建议调用一次 [[stop]],然后主动调用一次 [[start]] | |
226 | + * 以保证 option 正确生效。当主动设置的 option 和场景中的 option 有冲突时,以后设置的为准,比如:签到场景中默认的为单次定位, | |
227 | + * 当主动设置 option 为连续定位时,如果先设置的场景,后改变的 option,这时如果不调用 [[start]] 不会变为连续定位, | |
228 | + * 如果调用了 [[start]] 则会变为连续定位,如果先改变 option,后设置场景为签到场景,则会变为单次定位。 | |
229 | + * | |
230 | + * @platform android | |
231 | + */ | |
232 | +export function setLocationPurpose(purpose: LocationPurpose) { | |
233 | + if (Platform.OS === "android") { | |
234 | + AMapGeolocation.setLocationPurpose(purpose); | |
235 | + } | |
236 | +} | |
237 | + | |
238 | +/** | |
239 | + * 设置逆地理信息的语言,目前支持中文和英文 | |
240 | + * | |
241 | + * @default GeoLanguage.DEFAULT | |
242 | + */ | |
243 | +export function setGeoLanguage(language: GeoLanguage) { | |
244 | + AMapGeolocation.setGeoLanguage(language); | |
245 | +} | |
246 | + | |
247 | +/** | |
248 | + * 设定定位的最小更新距离(米) | |
249 | + * | |
250 | + * 默认为 `kCLDistanceFilterNone`,表示只要检测到设备位置发生变化就会更新位置信息。 | |
251 | + * | |
252 | + * @platform ios | |
253 | + */ | |
254 | +export function setDistanceFilter(distance: number) { | |
255 | + if (Platform.OS === "ios") { | |
256 | + AMapGeolocation.setDistanceFilter(distance); | |
257 | + } | |
258 | +} | |
259 | + | |
260 | +/** | |
261 | + * 设定期望的定位精度(米) | |
262 | + * | |
263 | + * 默认为 `kCLLocationAccuracyBest`。 | |
264 | + * 定位服务会尽可能去获取满足 `desiredAccuracy` 的定位结果,但不保证一定会得到满足期望的结果。 | |
265 | + * | |
266 | + * 注意:设置为 `kCLLocationAccuracyBest` 或 `kCLLocationAccuracyBestForNavigation` 时, | |
267 | + * 单次定位会在达到 `locationTimeout` 设定的时间后,将时间内获取到的最高精度的定位结果返回。 | |
268 | + * | |
269 | + * @platform ios | |
270 | + */ | |
271 | +export function setDesiredAccuracy(desiredAccuracy: number) { | |
272 | + if (Platform.OS === "ios") { | |
273 | + AMapGeolocation.setDesiredAccuracy(desiredAccuracy); | |
274 | + } | |
275 | +} | |
276 | + | |
277 | +/** | |
278 | + * 指定定位是否会被系统自动暂停 | |
279 | + * | |
280 | + * @default false | |
281 | + * @platform ios | |
282 | + */ | |
283 | +export function setPausesLocationUpdatesAutomatically(isPause: boolean) { | |
284 | + if (Platform.OS === "ios") { | |
285 | + AMapGeolocation.setPausesLocationUpdatesAutomatically(isPause); | |
286 | + } | |
287 | +} | |
288 | + | |
289 | +/** | |
290 | + * 是否允许后台定位 | |
291 | + * | |
292 | + * 只在iOS 9.0 及之后起作用。 | |
293 | + * 设置为YES的时候必须保证 `Background Modes` 中的 `Location updates` 处于选中状态,否则会抛出异常。 | |
294 | + * 由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。 | |
295 | + * | |
296 | + * @default false | |
297 | + * @platform ios | |
298 | + */ | |
299 | +export function setAllowsBackgroundLocationUpdates(isAllow: boolean) { | |
300 | + if (Platform.OS === "ios") { | |
301 | + AMapGeolocation.setAllowsBackgroundLocationUpdates(isAllow); | |
302 | + } | |
303 | +} | |
304 | + | |
305 | +/** | |
306 | + * 指定单次定位超时时间(秒) | |
307 | + * | |
308 | + * 最小值是 2s。注意在单次定位请求前设置。 | |
309 | + * | |
310 | + * 注意: 单次定位超时时间从确定了定位权限(非 `kCLAuthorizationStatusNotDetermined` 状态)后开始计算。 | |
311 | + * | |
312 | + * @default 10 | |
313 | + * @platform ios | |
314 | + */ | |
315 | +export function setLocationTimeout(timeout: number) { | |
316 | + if (Platform.OS === "ios") { | |
317 | + AMapGeolocation.setLocationTimeout(timeout); | |
318 | + } | |
319 | +} | |
320 | + | |
321 | +/** | |
322 | + * 指定单次定位逆地理超时时间(秒) | |
323 | + * | |
324 | + * 最小值是 2s。注意在单次定位请求前设置。 | |
325 | + * | |
326 | + * @default 5 | |
327 | + * @platform ios | |
328 | + */ | |
329 | +export function setReGeocodeTimeout(timeout: number) { | |
330 | + if (Platform.OS === "ios") { | |
331 | + AMapGeolocation.setReGeocodeTimeout(timeout); | |
332 | + } | |
333 | +} | |
334 | + | |
335 | +interface Options { | |
336 | + locatingWithReGeocode?: boolean; | |
337 | +} | |
338 | + | |
339 | +export const _options: Options = {}; | |
340 | + | |
341 | +/** | |
342 | + * 连续定位是否返回逆地理编码 | |
343 | + * | |
344 | + * @default false | |
345 | + * @platform ios | |
346 | + */ | |
347 | +export function setLocatingWithReGeocode(withReGeocode: boolean) { | |
348 | + _options.locatingWithReGeocode = withReGeocode; | |
349 | + if (Platform.OS === "ios") { | |
350 | + AMapGeolocation.setLocatingWithReGeocode(withReGeocode); | |
351 | + } | |
352 | +} | ... | ... |
lib/src/gen-types.ts
0 → 100644
1 | +/** | |
2 | + * 高德开放平台应用 Key | |
3 | + */ | |
4 | +export interface AppKey { | |
5 | + ios: string; | |
6 | + android: string; | |
7 | +} | |
8 | + | |
9 | +/** | |
10 | + * 定位结果类型 | |
11 | + * | |
12 | + * @platform android | |
13 | + */ | |
14 | +export enum LocationType { | |
15 | + /** | |
16 | + * 卫星定位结果 | |
17 | + * | |
18 | + * 通过设备卫星定位模块返回的定位结果 | |
19 | + */ | |
20 | + GPS = 1, | |
21 | + | |
22 | + /** | |
23 | + * 前次定位结果 | |
24 | + * | |
25 | + * 网络定位请求低于1秒、或两次定位之间设备位置变化非常小时返回,设备位移通过传感器感知 | |
26 | + */ | |
27 | + SAME_REQ, | |
28 | + | |
29 | + /** | |
30 | + * @deprecated | |
31 | + */ | |
32 | + FAST, | |
33 | + | |
34 | + /** | |
35 | + * 缓存定位结果 | |
36 | + * | |
37 | + * 返回一段时间前设备在相同的环境中缓存下来的网络定位结果,节省无必要的设备定位消耗 | |
38 | + */ | |
39 | + FIX_CACHE, | |
40 | + | |
41 | + /** | |
42 | + * Wifi定位结果 | |
43 | + * | |
44 | + * 属于网络定位,定位精度相对基站定位会更好 | |
45 | + */ | |
46 | + WIFI, | |
47 | + | |
48 | + /** | |
49 | + * 基站定位结果 | |
50 | + * | |
51 | + * 属于网络定位 | |
52 | + */ | |
53 | + CELL, | |
54 | + | |
55 | + AMAP, | |
56 | + | |
57 | + /** | |
58 | + * 离线定位结果 | |
59 | + */ | |
60 | + OFFLINE, | |
61 | + | |
62 | + /** | |
63 | + * 最后位置缓存 | |
64 | + */ | |
65 | + LAST_LOCATION_CACHE, | |
66 | +} | |
67 | + | |
68 | +/** | |
69 | + * iOS 错误代码 | |
70 | + * | |
71 | + * @platform ios | |
72 | + */ | |
73 | +export enum ErrorCodeIOS {} | |
74 | + | |
75 | +/** | |
76 | + * Android 错误代码 | |
77 | + * | |
78 | + * @platform android | |
79 | + */ | |
80 | +export enum ErrorCodeAndroid { | |
81 | + /** | |
82 | + * 定位成功 | |
83 | + */ | |
84 | + LOCATION_SUCCESS, | |
85 | + | |
86 | + /** | |
87 | + * 一些重要参数为空,可以通过 [[Location.locationDetail]] 获取详细信息 | |
88 | + */ | |
89 | + INVALID_PARAMETER, | |
90 | + | |
91 | + /** | |
92 | + * 定位失败,由于设备仅扫描到单个 wifi,不能精准的计算出位置信息 | |
93 | + */ | |
94 | + FAILURE_WIFI_INFO, | |
95 | + | |
96 | + /** | |
97 | + * 获取到的请求参数为空,可能获取过程中出现异常,可以通过 [[Location.locationDetail]] 获取详细信息 | |
98 | + */ | |
99 | + FAILURE_LOCATION_PARAMETER, | |
100 | + | |
101 | + /** | |
102 | + * 网络连接异常,可以通过 [[Location.locationDetail]] 获取详细信息 | |
103 | + */ | |
104 | + FAILURE_CONNECTION, | |
105 | + | |
106 | + /** | |
107 | + * 解析 XML 出错,可以通过 [[Location.locationDetail]] 获取详细信息 | |
108 | + */ | |
109 | + FAILURE_PARSER, | |
110 | + | |
111 | + /** | |
112 | + * 定位结果错误,可以通过 [[Location.locationDetail]] 获取详细信息 | |
113 | + */ | |
114 | + FAILURE_LOCATION, | |
115 | + | |
116 | + /** | |
117 | + * Key 错误,可以通过 [[Location.locationDetail]] 获取详细信息来跟注册的 Key 信息进行对照 | |
118 | + */ | |
119 | + FAILURE_AUTH, | |
120 | + | |
121 | + /** | |
122 | + * 其他错误,可以通过 [[Location.locationDetail]] 获取详细信息 | |
123 | + */ | |
124 | + UNKNOWN, | |
125 | + | |
126 | + /** | |
127 | + * 初始化异常,可以通过 [[Location.locationDetail]] 获取详细信息 | |
128 | + */ | |
129 | + FAILURE_INIT, | |
130 | + | |
131 | + /** | |
132 | + * 定位服务启动失败,请检查是否配置 service 并且 manifest 中 service 标签是否配置在 application 标签内 | |
133 | + */ | |
134 | + SERVICE_FAIL, | |
135 | + | |
136 | + /** | |
137 | + * 错误的基站信息,请检查是否安装 sim 卡 | |
138 | + */ | |
139 | + FAILURE_CELL, | |
140 | + | |
141 | + /** | |
142 | + * 缺少定位权限,请检查是否配置定位权限,并在安全软件和设置中给应用打开定位权限 | |
143 | + */ | |
144 | + FAILURE_LOCATION_PERMISSION, | |
145 | + | |
146 | + /** | |
147 | + * 网络定位失败,请检查设备是否插入 sim 卡、开启移动网络或开启了 wifi 模块 | |
148 | + */ | |
149 | + FAILURE_NOWIFIANDAP, | |
150 | + | |
151 | + /** | |
152 | + * 卫星定位失败,可用卫星数不足 | |
153 | + */ | |
154 | + FAILURE_NOENOUGHSATELLITES, | |
155 | + | |
156 | + /** | |
157 | + * 定位位置可能被模拟 | |
158 | + */ | |
159 | + FAILURE_SIMULATION_LOCATION, | |
160 | + | |
161 | + /** | |
162 | + * 定位失败,飞行模式下关闭了 wifi 开关,请关闭飞行模式或者打开 wifi 开关 | |
163 | + */ | |
164 | + AIRPLANEMODE_WIFIOFF = 18, | |
165 | + | |
166 | + /** | |
167 | + * 定位失败,没有检查到 sim 卡,并且关闭了 wifi 开关,请打开 wifi 开关或者插入 sim 卡 | |
168 | + */ | |
169 | + NOCGI_WIFIOFF, | |
170 | +} | |
171 | + | |
172 | +export type ErrorCode = ErrorCodeAndroid | ErrorCodeIOS; | |
173 | + | |
174 | +/** | |
175 | + * 定位模式,目前支持三种定位模式 | |
176 | + * | |
177 | + * @platform android | |
178 | + */ | |
179 | +export enum LocationMode { | |
180 | + /** | |
181 | + * 低功耗模式,在这种模式下,将只使用高德网络定位。 | |
182 | + */ | |
183 | + Battery_Saving = "Battery_Saving", | |
184 | + | |
185 | + /** | |
186 | + * 仅设备模式,只使用卫星定位,不支持室内环境的定位 | |
187 | + */ | |
188 | + Device_Sensors = "Device_Sensors", | |
189 | + | |
190 | + /** | |
191 | + * 高精度模式,在这种定位模式下,将同时使用高德网络定位和卫星定位,优先返回精度高的定位 | |
192 | + */ | |
193 | + Hight_Accuracy = "Hight_Accuracy", | |
194 | +} | |
195 | + | |
196 | +/** | |
197 | + * 定位场景 | |
198 | + * | |
199 | + * @platform android | |
200 | + */ | |
201 | +export enum LocationPurpose { | |
202 | + /** | |
203 | + * 签到场景 | |
204 | + * | |
205 | + * 只进行一次定位返回最接近真实位置的定位结果(定位速度可能会延迟 1-3s)。 | |
206 | + */ | |
207 | + SignIn = "SignIn", | |
208 | + | |
209 | + /** | |
210 | + * 运动场景 | |
211 | + * | |
212 | + * 高精度连续定位,适用于有户内外切换的场景,卫星定位和网络定位相互切换,卫星定位成功之后网络定位不再返回,卫星信号断开之后一段时间才会返回网络结果。 | |
213 | + */ | |
214 | + Sport = "Sport", | |
215 | + | |
216 | + /** | |
217 | + * 出行场景 | |
218 | + * | |
219 | + * 高精度连续定位,适用于有户内外切换的场景,卫星定位和网络定位相互切换,卫星定位成功之后网络定位不再返回,卫星信号断开之后一段时间才会返回网络结果。 | |
220 | + */ | |
221 | + Transport = "Transport", | |
222 | +} | |
223 | + | |
224 | +/** | |
225 | + * 逆地理编码语言 | |
226 | + */ | |
227 | +export enum GeoLanguage { | |
228 | + /** | |
229 | + * 默认,根据位置按照相应的语言返回逆地理信息,在国外按英语返回,在国内按中文返回 | |
230 | + */ | |
231 | + DEFAULT = "DEFAULT", | |
232 | + | |
233 | + /** | |
234 | + * 中文,无论在国外还是国内都为返回中文的逆地理信息 | |
235 | + */ | |
236 | + ZH = "ZH", | |
237 | + | |
238 | + /** | |
239 | + * 英文,无论在国外还是国内都为返回英文的逆地理信息 | |
240 | + */ | |
241 | + EN = "EN", | |
242 | +} | |
243 | + | |
244 | +/** | |
245 | + * 卫星信号强度 | |
246 | + * | |
247 | + * @platform android | |
248 | + */ | |
249 | +export enum GpsAccuracy { | |
250 | + UNKNOWN, | |
251 | + BAD, | |
252 | + GOOD, | |
253 | +} | |
254 | + | |
255 | +/** | |
256 | + * 定位结果的可信度 | |
257 | + */ | |
258 | +export enum TrustedLevel { | |
259 | + HIGH = 1, | |
260 | + NORMAL, | |
261 | + LOW, | |
262 | + BAD, | |
263 | +} | |
264 | + | |
265 | +/** | |
266 | + * 定位信息 | |
267 | + */ | |
268 | +export interface ILocation { | |
269 | + /** | |
270 | + * 定位精度 (米) | |
271 | + */ | |
272 | + accuracy: number; | |
273 | + | |
274 | + /** | |
275 | + * 经度,[-180, 180] | |
276 | + */ | |
277 | + latitude: number; | |
278 | + | |
279 | + /** | |
280 | + * 纬度,[-90, 90] | |
281 | + */ | |
282 | + longitude: number; | |
283 | + | |
284 | + /** | |
285 | + * 海拔(米),需要 GPS | |
286 | + */ | |
287 | + altitude?: number; | |
288 | + | |
289 | + /** | |
290 | + * 移动速度(米/秒),需要 GPS | |
291 | + */ | |
292 | + speed?: number; | |
293 | + | |
294 | + /** | |
295 | + * 移动方向,需要 GPS | |
296 | + */ | |
297 | + heading?: number; | |
298 | + | |
299 | + /** | |
300 | + * 定位时间(毫秒) | |
301 | + */ | |
302 | + timestamp?: number; | |
303 | + | |
304 | + /** | |
305 | + * 错误码 | |
306 | + */ | |
307 | + errorCode?: ErrorCode; | |
308 | + | |
309 | + /** | |
310 | + * 错误信息 | |
311 | + */ | |
312 | + errorInfo?: string; | |
313 | + | |
314 | + /** | |
315 | + * 定位信息描述 | |
316 | + * | |
317 | + * @platform android | |
318 | + */ | |
319 | + locationDetail?: string; | |
320 | + | |
321 | + /** | |
322 | + * 定位结果来源 | |
323 | + * | |
324 | + * @platform android | |
325 | + */ | |
326 | + locationType?: LocationType; | |
327 | + | |
328 | + /** | |
329 | + * 卫星信号强度,仅在卫星定位时有效 | |
330 | + * | |
331 | + * @platform android | |
332 | + */ | |
333 | + gpsAccuracy?: GpsAccuracy; | |
334 | + | |
335 | + /** | |
336 | + * 坐标系类型 | |
337 | + * | |
338 | + * @platform android | |
339 | + */ | |
340 | + coordinateType?: "WGS84" | "GCJ02"; | |
341 | + | |
342 | + /** | |
343 | + * 定位结果的可信度,只有在定位结果正确时,才有意义 | |
344 | + * | |
345 | + * @platform android | |
346 | + */ | |
347 | + trustedLevel?: TrustedLevel; | |
348 | +} | |
349 | + | |
350 | +/** | |
351 | + * 逆地理编码信息 | |
352 | + */ | |
353 | +export interface ReGeocode { | |
354 | + /** | |
355 | + * 详细地址 | |
356 | + */ | |
357 | + address?: string; | |
358 | + | |
359 | + /** | |
360 | + * 国家 | |
361 | + */ | |
362 | + country?: string; | |
363 | + | |
364 | + /** | |
365 | + * 省份 | |
366 | + */ | |
367 | + province?: string; | |
368 | + | |
369 | + /** | |
370 | + * 城市 | |
371 | + */ | |
372 | + city?: string; | |
373 | + | |
374 | + /** | |
375 | + * 城市编码 | |
376 | + */ | |
377 | + cityCode?: string; | |
378 | + | |
379 | + /** | |
380 | + * 地区 | |
381 | + */ | |
382 | + district?: string; | |
383 | + | |
384 | + /** | |
385 | + * 街道 | |
386 | + */ | |
387 | + street?: string; | |
388 | + | |
389 | + /** | |
390 | + * 门牌号 | |
391 | + */ | |
392 | + streetNumber?: string; | |
393 | + | |
394 | + /** | |
395 | + * 兴趣点 | |
396 | + */ | |
397 | + poiName?: string; | |
398 | +} | ... | ... |
lib/src/geolocation.ts
0 → 100644
1 | +import { EmitterSubscription } from "react-native"; | |
2 | +import { addLocationListener, start, stop, _options } from "./amap-geolocation"; | |
3 | +import { ILocation as Location } from "./gen-types"; | |
4 | + | |
5 | +/** | |
6 | + * 坐标信息 | |
7 | + * | |
8 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Coordinates | |
9 | + */ | |
10 | +export interface Coordinates { | |
11 | + latitude: number; | |
12 | + longitude: number; | |
13 | + altitude: number; | |
14 | + accuracy: number; | |
15 | + altitudeAccuracy: number; | |
16 | + heading: number; | |
17 | + speed: number; | |
18 | +} | |
19 | + | |
20 | +/** | |
21 | + * 定位信息 | |
22 | + * | |
23 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Position | |
24 | + */ | |
25 | +export interface Position { | |
26 | + coords: Coordinates; | |
27 | + timestamp: number; | |
28 | + location: Location; | |
29 | +} | |
30 | + | |
31 | +/** | |
32 | + * 定位错误信息 | |
33 | + * | |
34 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/PositionError | |
35 | + */ | |
36 | +export class PositionError { | |
37 | + static PERMISSION_DENIED: 1; | |
38 | + static POSITION_UNAVAILABLE: 2; | |
39 | + static TIMEOUT: 3; | |
40 | + | |
41 | + code: number; | |
42 | + message: string; | |
43 | + location: Location; | |
44 | + | |
45 | + constructor(code: number, message: string, location: Location) { | |
46 | + this.code = code; | |
47 | + this.message = message; | |
48 | + this.location = location; | |
49 | + } | |
50 | +} | |
51 | + | |
52 | +/** | |
53 | + * 定位选项 | |
54 | + * | |
55 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/PositionOptions | |
56 | + */ | |
57 | +export interface PositionOptions { | |
58 | + timeout?: number; | |
59 | + maximumAge?: number; | |
60 | + enableHighAccuracy?: boolean; | |
61 | + | |
62 | + /** | |
63 | + * @see [[setDistanceFilter]] | |
64 | + */ | |
65 | + distanceFilter?: number; | |
66 | +} | |
67 | + | |
68 | +let watchId = 0; | |
69 | +const watchMap: { [watchId: number]: EmitterSubscription } = {}; | |
70 | + | |
71 | +/** | |
72 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation | |
73 | + */ | |
74 | +export default class Geolocation { | |
75 | + /** | |
76 | + * 获取当前位置信息 | |
77 | + * | |
78 | + * 注意:使用该方法会停止持续定位 | |
79 | + * | |
80 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/getCurrentPosition | |
81 | + */ | |
82 | + static getCurrentPosition( | |
83 | + success: (position: Position) => void, | |
84 | + error?: (error: PositionError) => void | |
85 | + // options: PositionOptions = {} | |
86 | + ) { | |
87 | + const listener = addLocationListener((location) => { | |
88 | + if (location.errorCode) { | |
89 | + error && error(new PositionError(location.errorCode, location.errorInfo ?? "", location)); | |
90 | + stop(); | |
91 | + return listener.remove(); | |
92 | + } | |
93 | + if (_options.locatingWithReGeocode && typeof location.address !== "string") { | |
94 | + return; | |
95 | + } | |
96 | + success(toPosition(location)); | |
97 | + stop(); | |
98 | + return listener.remove(); | |
99 | + }); | |
100 | + start(); | |
101 | + } | |
102 | + | |
103 | + /** | |
104 | + * 注册监听器进行持续定位 | |
105 | + * | |
106 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/watchPosition | |
107 | + */ | |
108 | + static watchPosition( | |
109 | + success: (position: Position) => void, | |
110 | + error?: (error: PositionError) => void | |
111 | + // options?: PositionOptions | |
112 | + ) { | |
113 | + watchMap[++watchId] = addLocationListener((location) => { | |
114 | + if (location.errorCode) { | |
115 | + error && error(new PositionError(location.errorCode, location.errorInfo ?? "", location)); | |
116 | + } else { | |
117 | + success(toPosition(location)); | |
118 | + } | |
119 | + }); | |
120 | + start(); | |
121 | + return watchId; | |
122 | + } | |
123 | + | |
124 | + /** | |
125 | + * 移除位置监听 | |
126 | + * | |
127 | + * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/clearWatch | |
128 | + */ | |
129 | + static clearWatch(id: number) { | |
130 | + const listener = watchMap[id]; | |
131 | + if (listener) { | |
132 | + listener.remove(); | |
133 | + } | |
134 | + } | |
135 | +} | |
136 | + | |
137 | +function toPosition(location: Location) { | |
138 | + return { | |
139 | + location, | |
140 | + coords: { | |
141 | + latitude: location.latitude, | |
142 | + longitude: location.longitude, | |
143 | + altitude: location.altitude ?? 0, | |
144 | + accuracy: location.accuracy, | |
145 | + altitudeAccuracy: 0, // 高德定位接口没有找到对应的数据 | |
146 | + heading: location.heading ?? 0, | |
147 | + speed: location.speed ?? 0, | |
148 | + }, | |
149 | + timestamp: location.timestamp ?? 0, | |
150 | + }; | |
151 | +} | ... | ... |
lib/src/index.ts
... | ... | @@ -6,6 +6,10 @@ export { default as Marker } from "./marker"; |
6 | 6 | export { default as MultiPoint } from "./multi-point"; |
7 | 7 | export { default as Polygon } from "./polygon"; |
8 | 8 | export { default as Polyline } from "./polyline"; |
9 | +import * as AMapSdk from "./sdk"; | |
9 | 10 | export * from "./types"; |
11 | +export * from "./gen-types"; | |
12 | +export * from "./geolocation"; | |
13 | +export * from "./amap-geolocation"; | |
14 | +export { default as Geolocation } from "./geolocation"; | |
10 | 15 | export { AMapSdk }; |
11 | -import * as AMapSdk from "./sdk"; | ... | ... |
package.json
1 | 1 | { |
2 | 2 | "name": "@cqfw/react-native-amap3d", |
3 | - "version": "0.0.1", | |
3 | + "version": "0.0.2", | |
4 | 4 | "description": "react-native 高德地图组件,支持 Android + iOS", |
5 | 5 | "author": "feewee", |
6 | 6 | "license": "MIT", |
... | ... | @@ -34,6 +34,7 @@ |
34 | 34 | "supercluster": "^7.1.4" |
35 | 35 | }, |
36 | 36 | "devDependencies": { |
37 | + "@types/react-native": "^0.70.4", | |
37 | 38 | "@types/supercluster": "^5.0.3", |
38 | 39 | "react": "17.0.2", |
39 | 40 | "react-native": "^0.62.0" | ... | ... |