Commit 76a8d3050c4d6a705081bded8166d96cd99c80e4

Authored by 张志伟
1 parent 0c299ac9

新增定位模块

lib/android/build.gradle
... ... @@ -40,4 +40,5 @@ dependencies {
40 40 api 'com.facebook.react:react-native:+'
41 41 implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
42 42 implementation 'com.amap.api:3dmap:9.4.0'
  43 + implementation 'com.amap.api:location:6.1.0'
43 44 }
... ...
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 &quot;./marker&quot;;
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"
... ...