diff --git a/lib/android/build.gradle b/lib/android/build.gradle
index 79db9f0..8959ed6 100644
--- a/lib/android/build.gradle
+++ b/lib/android/build.gradle
@@ -40,4 +40,5 @@ dependencies {
api 'com.facebook.react:react-native:+'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.amap.api:3dmap:9.4.0'
+ implementation 'com.amap.api:location:6.1.0'
}
diff --git a/lib/android/src/main/AndroidManifest.xml b/lib/android/src/main/AndroidManifest.xml
index 5942f9a..f1a33f1 100644
--- a/lib/android/src/main/AndroidManifest.xml
+++ b/lib/android/src/main/AndroidManifest.xml
@@ -7,4 +7,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt b/lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt
index 9214426..3c716d1 100644
--- a/lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt
+++ b/lib/android/src/main/java/cn/feewee/amap3d/AMap3DPackage.kt
@@ -6,11 +6,13 @@ import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ViewManager
import cn.feewee.amap3d.map_view.*
import cn.feewee.amap3d.modules.SdkModule
+import cn.feewee.amap3d.modules.AMapGeolocationModule
class AMap3DPackage : ReactPackage {
override fun createNativeModules(reactContext: ReactApplicationContext): List {
return listOf(
SdkModule(reactContext),
+ new AMapGeolocationModule(reactContext)
)
}
diff --git a/lib/android/src/main/java/cn/feewee/amap3d/modules/AMapGeolocationModule.java b/lib/android/src/main/java/cn/feewee/amap3d/modules/AMapGeolocationModule.java
new file mode 100644
index 0000000..d999ea6
--- /dev/null
+++ b/lib/android/src/main/java/cn/feewee/amap3d/modules/AMapGeolocationModule.java
@@ -0,0 +1,205 @@
+package cn.feewee.amap3d.modules;
+
+import com.amap.api.location.AMapLocation;
+import com.amap.api.location.AMapLocationClient;
+import com.amap.api.location.AMapLocationClientOption;
+import com.amap.api.location.AMapLocationListener;
+import com.facebook.react.bridge.*;
+import com.facebook.react.modules.core.DeviceEventManagerModule;
+import org.jetbrains.annotations.NotNull;
+
+@SuppressWarnings("unused")
+public class AMapGeolocationModule extends ReactContextBaseJavaModule implements AMapLocationListener {
+ private final ReactApplicationContext reactContext;
+ private final AMapLocationClientOption option = new AMapLocationClientOption();
+ private DeviceEventManagerModule.RCTDeviceEventEmitter eventEmitter;
+ private AMapLocationClient client;
+
+ AMapGeolocationModule(ReactApplicationContext reactContext) {
+ super(reactContext);
+ this.reactContext = reactContext;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "AMapGeolocation";
+ }
+
+ @Override
+ public void onLocationChanged(AMapLocation location) {
+ if (location != null) {
+ eventEmitter.emit("AMapGeolocation", toJSON(location));
+ }
+ }
+
+ @ReactMethod
+ public void init(String key, Promise promise) throws Exception {
+ if (client != null) {
+ client.onDestroy();
+ }
+
+ AMapLocationClient.setApiKey(key);
+ AMapLocationClient.updatePrivacyShow(reactContext, true, true);
+ AMapLocationClient.updatePrivacyAgree(reactContext, true);
+ client = new AMapLocationClient(reactContext);
+ client.setLocationListener(this);
+ eventEmitter = reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
+ promise.resolve(null);
+ }
+
+ @ReactMethod
+ public void start() {
+ client.startLocation();
+ }
+
+ @ReactMethod
+ public void stop() {
+ client.stopLocation();
+ }
+
+ @ReactMethod
+ public void addListener(String name) {
+ }
+
+ @ReactMethod
+ public void removeListeners(Integer count) {
+ }
+
+ @ReactMethod
+ public void isStarted(Promise promise) {
+ promise.resolve(client.isStarted());
+ }
+
+ @ReactMethod
+ public void getLastKnownLocation(Promise promise) {
+ promise.resolve(toJSON(client.getLastKnownLocation()));
+ }
+
+ @ReactMethod
+ public void setOnceLocation(boolean value) {
+ option.setOnceLocation(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setWifiScan(boolean value) {
+ option.setWifiScan(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setInterval(int interval) {
+ option.setInterval(interval);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setSensorEnable(boolean value) {
+ option.setSensorEnable(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setOpenAlwaysScanWifi(boolean value) {
+ AMapLocationClientOption.setOpenAlwaysScanWifi(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setNeedAddress(boolean value) {
+ option.setNeedAddress(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setOnceLocationLatest(boolean value) {
+ option.setOnceLocationLatest(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setMockEnable(boolean value) {
+ option.setMockEnable(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setLocationCacheEnable(boolean value) {
+ option.setLocationCacheEnable(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setGpsFirst(boolean value) {
+ option.setGpsFirst(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setHttpTimeout(int value) {
+ option.setHttpTimeOut(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setGpsFirstTimeout(int value) {
+ option.setGpsFirstTimeout(value);
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setLocationMode(String mode) {
+ option.setLocationMode(AMapLocationClientOption.AMapLocationMode.valueOf(mode));
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setLocationPurpose(String purpose) {
+ option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.valueOf(purpose));
+ client.setLocationOption(option);
+ }
+
+ @ReactMethod
+ public void setGeoLanguage(String language) {
+ option.setGeoLanguage(AMapLocationClientOption.GeoLanguage.valueOf(language));
+ client.setLocationOption(option);
+ }
+
+ private ReadableMap toJSON(AMapLocation location) {
+ if (location == null) {
+ return null;
+ }
+ WritableMap map = Arguments.createMap();
+ map.putInt("errorCode", location.getErrorCode());
+ map.putString("errorInfo", location.getErrorInfo());
+ map.putString("locationDetail", location.getLocationDetail());
+ if (location.getErrorCode() == AMapLocation.LOCATION_SUCCESS) {
+ map.putDouble("timestamp", location.getTime());
+ map.putDouble("accuracy", location.getAccuracy());
+ map.putDouble("latitude", location.getLatitude());
+ map.putDouble("longitude", location.getLongitude());
+ map.putDouble("altitude", location.getAltitude());
+ map.putDouble("speed", location.getSpeed());
+ map.putDouble("heading", location.getBearing());
+ map.putInt("locationType", location.getLocationType());
+ map.putString("coordinateType", location.getCoordType());
+ map.putInt("gpsAccuracy", location.getGpsAccuracyStatus());
+ map.putInt("trustedLevel", location.getTrustedLevel());
+ if (!location.getAddress().isEmpty()) {
+ map.putString("address", location.getAddress());
+ map.putString("description", location.getDescription());
+ map.putString("poiName", location.getPoiName());
+ map.putString("country", location.getCountry());
+ map.putString("province", location.getProvince());
+ map.putString("city", location.getCity());
+ map.putString("cityCode", location.getCityCode());
+ map.putString("district", location.getDistrict());
+ map.putString("street", location.getStreet());
+ map.putString("streetNumber", location.getStreetNum());
+ map.putString("adCode", location.getAdCode());
+ }
+ }
+ return map;
+ }
+}
diff --git a/lib/src/amap-geolocation.ts b/lib/src/amap-geolocation.ts
new file mode 100644
index 0000000..10dcf04
--- /dev/null
+++ b/lib/src/amap-geolocation.ts
@@ -0,0 +1,352 @@
+import { NativeModules, NativeEventEmitter, Platform } from "react-native";
+import { ILocation as Location, ReGeocode, AppKey, LocationMode, LocationPurpose, GeoLanguage } from "./gen-types";
+
+const AMapGeolocation = NativeModules.AMapGeolocation;
+const eventEmitter = new NativeEventEmitter(AMapGeolocation);
+
+/**
+ * 初始化 SDK
+ *
+ * @param key 高德开放平台应用 Key
+ */
+export function init(key: AppKey): Promise {
+ return AMapGeolocation.init(Platform.select(key));
+}
+
+/**
+ * 添加定位监听函数
+ *
+ * @param listener
+ */
+export function addLocationListener(listener: (location: Location & ReGeocode) => void) {
+ return eventEmitter.addListener("AMapGeolocation", listener);
+}
+
+/**
+ * 开始持续定位
+ */
+export function start() {
+ AMapGeolocation.start();
+}
+
+/**
+ * 停止持续定位
+ */
+export function stop() {
+ AMapGeolocation.stop();
+}
+
+/**
+ * 获取当前是否正在定位的状态
+ *
+ * @platform android
+ */
+export function isStarted(): boolean {
+ return AMapGeolocation.isStarted();
+}
+
+/**
+ * 设置发起定位请求的时间间隔(毫秒),默认 2000,最小值为 1000
+ *
+ * @default 2000
+ * @platform android
+ */
+export function setInterval(interval: number) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setInterval(interval);
+ }
+}
+
+/**
+ * 设置是否单次定位
+ *
+ * @default false
+ * @platform android
+ */
+export function setOnceLocation(isOnceLocation: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setOnceLocation(isOnceLocation);
+ }
+}
+
+/**
+ * 设置是否允许调用 WiFi 刷新
+ *
+ * 当设置为 `false` 时会停止主动调用 wifi 刷新,将会极大程度影响定位精度,
+ * 但可以有效的降低定位耗电。
+ *
+ * @default true
+ * @platform android
+ */
+export function setWifiScan(isWifiScan: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setWifiScan(isWifiScan);
+ }
+}
+
+/**
+ * 设置是否使用设备传感器
+ *
+ * @default false
+ * @platform android
+ */
+export function setSensorEnable(enable: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setSensorEnable(enable);
+ }
+}
+
+/**
+ * 设置是否开启wifi始终扫描
+ *
+ * 只有设置了 `android.permission.WRITE_SECURE_SETTINGS` 权限后才会开启。
+ * 开启后,即使关闭 wifi 开关的情况下也会扫描 wifi。
+ * 此方法为静态方法,设置一次后其他定位 client 也会生效。
+ *
+ * @default true
+ * @platform android
+ */
+export function setOpenAlwaysScanWifi(isOpen: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setOpenAlwaysScanWifi(isOpen);
+ }
+}
+
+/**
+ * 设置定位是否等待 WiFi 列表刷新
+ *
+ * 定位精度会更高,但是定位速度会变慢 1-3 秒,
+ * 当设置为 `true` 时,连续定位会自动变为单次定位。
+ *
+ * @default false
+ * @platform android
+ */
+export function setOnceLocationLatest(isOnceLocationLatest: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setOnceLocationLatest(isOnceLocationLatest);
+ }
+}
+
+/**
+ * 设置是否返回地址信息,默认返回地址信息
+ *
+ * GPS 定位时也可以返回地址信息,但需要网络通畅,第一次有可能没有地址信息返回。
+ *
+ * @default true
+ * @platform android
+ */
+export function setNeedAddress(isNeedAddress: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setNeedAddress(isNeedAddress);
+ }
+}
+
+/**
+ * 设置是否允许模拟位置
+ *
+ * @default true
+ * @platform android
+ */
+export function setMockEnable(enable: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setMockEnable(enable);
+ }
+}
+
+/**
+ * 设置是否使用缓存策略
+ *
+ * @default true
+ * @platform android
+ */
+export function setLocationCacheEnable(enable: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setLocationCacheEnable(enable);
+ }
+}
+
+/**
+ * 设置联网超时时间(毫秒)
+ *
+ * @default 30000
+ * @platform android
+ */
+export function setHttpTimeout(timeout: number) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setHttpTimeout(timeout);
+ }
+}
+
+/**
+ * 设置优先返回卫星定位信息时等待卫星定位结果的超时时间(毫秒)
+ *
+ * 只有在 `setGpsFirst(true)` 时才有效。
+ *
+ * @platform android
+ */
+export function setGpsFirstTimeout(timeout: number) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setGpsFirstTimeout(timeout);
+ }
+}
+
+/**
+ * 设置首次定位是否等待卫星定位结果
+ *
+ * 只有在单次定位高精度定位模式下有效,设置为 `true` 时,会等待卫星定位结果返回,
+ * 最多等待 30 秒,若 30 秒后仍无卫星定位结果返回,返回网络定位结果。
+ * 等待卫星定位结果返回的时间可以通过 [[setGpsFirstTimeout]] 进行设置。
+ *
+ * @default false
+ * @platform android
+ */
+export function setGpsFirst(isGpsFirst: boolean) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setGpsFirst(isGpsFirst);
+ }
+}
+
+/**
+ * 设置定位模式
+ *
+ * @platform android
+ */
+export function setLocationMode(mode: LocationMode) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setLocationMode(mode);
+ }
+}
+
+/**
+ * 设置定位场景
+ *
+ * 根据场景快速修改 option,不支持动态改变,修改后需要调用 [[start]] 使其生效,当不需要场景时,可以设置为 `null`。
+ *
+ * 注意:不建议设置场景和自定义 option 混合使用。设置场景后,如果已经开始定位了,建议调用一次 [[stop]],然后主动调用一次 [[start]]
+ * 以保证 option 正确生效。当主动设置的 option 和场景中的 option 有冲突时,以后设置的为准,比如:签到场景中默认的为单次定位,
+ * 当主动设置 option 为连续定位时,如果先设置的场景,后改变的 option,这时如果不调用 [[start]] 不会变为连续定位,
+ * 如果调用了 [[start]] 则会变为连续定位,如果先改变 option,后设置场景为签到场景,则会变为单次定位。
+ *
+ * @platform android
+ */
+export function setLocationPurpose(purpose: LocationPurpose) {
+ if (Platform.OS === "android") {
+ AMapGeolocation.setLocationPurpose(purpose);
+ }
+}
+
+/**
+ * 设置逆地理信息的语言,目前支持中文和英文
+ *
+ * @default GeoLanguage.DEFAULT
+ */
+export function setGeoLanguage(language: GeoLanguage) {
+ AMapGeolocation.setGeoLanguage(language);
+}
+
+/**
+ * 设定定位的最小更新距离(米)
+ *
+ * 默认为 `kCLDistanceFilterNone`,表示只要检测到设备位置发生变化就会更新位置信息。
+ *
+ * @platform ios
+ */
+export function setDistanceFilter(distance: number) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setDistanceFilter(distance);
+ }
+}
+
+/**
+ * 设定期望的定位精度(米)
+ *
+ * 默认为 `kCLLocationAccuracyBest`。
+ * 定位服务会尽可能去获取满足 `desiredAccuracy` 的定位结果,但不保证一定会得到满足期望的结果。
+ *
+ * 注意:设置为 `kCLLocationAccuracyBest` 或 `kCLLocationAccuracyBestForNavigation` 时,
+ * 单次定位会在达到 `locationTimeout` 设定的时间后,将时间内获取到的最高精度的定位结果返回。
+ *
+ * @platform ios
+ */
+export function setDesiredAccuracy(desiredAccuracy: number) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setDesiredAccuracy(desiredAccuracy);
+ }
+}
+
+/**
+ * 指定定位是否会被系统自动暂停
+ *
+ * @default false
+ * @platform ios
+ */
+export function setPausesLocationUpdatesAutomatically(isPause: boolean) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setPausesLocationUpdatesAutomatically(isPause);
+ }
+}
+
+/**
+ * 是否允许后台定位
+ *
+ * 只在iOS 9.0 及之后起作用。
+ * 设置为YES的时候必须保证 `Background Modes` 中的 `Location updates` 处于选中状态,否则会抛出异常。
+ * 由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
+ *
+ * @default false
+ * @platform ios
+ */
+export function setAllowsBackgroundLocationUpdates(isAllow: boolean) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setAllowsBackgroundLocationUpdates(isAllow);
+ }
+}
+
+/**
+ * 指定单次定位超时时间(秒)
+ *
+ * 最小值是 2s。注意在单次定位请求前设置。
+ *
+ * 注意: 单次定位超时时间从确定了定位权限(非 `kCLAuthorizationStatusNotDetermined` 状态)后开始计算。
+ *
+ * @default 10
+ * @platform ios
+ */
+export function setLocationTimeout(timeout: number) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setLocationTimeout(timeout);
+ }
+}
+
+/**
+ * 指定单次定位逆地理超时时间(秒)
+ *
+ * 最小值是 2s。注意在单次定位请求前设置。
+ *
+ * @default 5
+ * @platform ios
+ */
+export function setReGeocodeTimeout(timeout: number) {
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setReGeocodeTimeout(timeout);
+ }
+}
+
+interface Options {
+ locatingWithReGeocode?: boolean;
+}
+
+export const _options: Options = {};
+
+/**
+ * 连续定位是否返回逆地理编码
+ *
+ * @default false
+ * @platform ios
+ */
+export function setLocatingWithReGeocode(withReGeocode: boolean) {
+ _options.locatingWithReGeocode = withReGeocode;
+ if (Platform.OS === "ios") {
+ AMapGeolocation.setLocatingWithReGeocode(withReGeocode);
+ }
+}
diff --git a/lib/src/gen-types.ts b/lib/src/gen-types.ts
new file mode 100644
index 0000000..b663845
--- /dev/null
+++ b/lib/src/gen-types.ts
@@ -0,0 +1,398 @@
+/**
+ * 高德开放平台应用 Key
+ */
+export interface AppKey {
+ ios: string;
+ android: string;
+}
+
+/**
+ * 定位结果类型
+ *
+ * @platform android
+ */
+export enum LocationType {
+ /**
+ * 卫星定位结果
+ *
+ * 通过设备卫星定位模块返回的定位结果
+ */
+ GPS = 1,
+
+ /**
+ * 前次定位结果
+ *
+ * 网络定位请求低于1秒、或两次定位之间设备位置变化非常小时返回,设备位移通过传感器感知
+ */
+ SAME_REQ,
+
+ /**
+ * @deprecated
+ */
+ FAST,
+
+ /**
+ * 缓存定位结果
+ *
+ * 返回一段时间前设备在相同的环境中缓存下来的网络定位结果,节省无必要的设备定位消耗
+ */
+ FIX_CACHE,
+
+ /**
+ * Wifi定位结果
+ *
+ * 属于网络定位,定位精度相对基站定位会更好
+ */
+ WIFI,
+
+ /**
+ * 基站定位结果
+ *
+ * 属于网络定位
+ */
+ CELL,
+
+ AMAP,
+
+ /**
+ * 离线定位结果
+ */
+ OFFLINE,
+
+ /**
+ * 最后位置缓存
+ */
+ LAST_LOCATION_CACHE,
+}
+
+/**
+ * iOS 错误代码
+ *
+ * @platform ios
+ */
+export enum ErrorCodeIOS {}
+
+/**
+ * Android 错误代码
+ *
+ * @platform android
+ */
+export enum ErrorCodeAndroid {
+ /**
+ * 定位成功
+ */
+ LOCATION_SUCCESS,
+
+ /**
+ * 一些重要参数为空,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ INVALID_PARAMETER,
+
+ /**
+ * 定位失败,由于设备仅扫描到单个 wifi,不能精准的计算出位置信息
+ */
+ FAILURE_WIFI_INFO,
+
+ /**
+ * 获取到的请求参数为空,可能获取过程中出现异常,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ FAILURE_LOCATION_PARAMETER,
+
+ /**
+ * 网络连接异常,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ FAILURE_CONNECTION,
+
+ /**
+ * 解析 XML 出错,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ FAILURE_PARSER,
+
+ /**
+ * 定位结果错误,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ FAILURE_LOCATION,
+
+ /**
+ * Key 错误,可以通过 [[Location.locationDetail]] 获取详细信息来跟注册的 Key 信息进行对照
+ */
+ FAILURE_AUTH,
+
+ /**
+ * 其他错误,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ UNKNOWN,
+
+ /**
+ * 初始化异常,可以通过 [[Location.locationDetail]] 获取详细信息
+ */
+ FAILURE_INIT,
+
+ /**
+ * 定位服务启动失败,请检查是否配置 service 并且 manifest 中 service 标签是否配置在 application 标签内
+ */
+ SERVICE_FAIL,
+
+ /**
+ * 错误的基站信息,请检查是否安装 sim 卡
+ */
+ FAILURE_CELL,
+
+ /**
+ * 缺少定位权限,请检查是否配置定位权限,并在安全软件和设置中给应用打开定位权限
+ */
+ FAILURE_LOCATION_PERMISSION,
+
+ /**
+ * 网络定位失败,请检查设备是否插入 sim 卡、开启移动网络或开启了 wifi 模块
+ */
+ FAILURE_NOWIFIANDAP,
+
+ /**
+ * 卫星定位失败,可用卫星数不足
+ */
+ FAILURE_NOENOUGHSATELLITES,
+
+ /**
+ * 定位位置可能被模拟
+ */
+ FAILURE_SIMULATION_LOCATION,
+
+ /**
+ * 定位失败,飞行模式下关闭了 wifi 开关,请关闭飞行模式或者打开 wifi 开关
+ */
+ AIRPLANEMODE_WIFIOFF = 18,
+
+ /**
+ * 定位失败,没有检查到 sim 卡,并且关闭了 wifi 开关,请打开 wifi 开关或者插入 sim 卡
+ */
+ NOCGI_WIFIOFF,
+}
+
+export type ErrorCode = ErrorCodeAndroid | ErrorCodeIOS;
+
+/**
+ * 定位模式,目前支持三种定位模式
+ *
+ * @platform android
+ */
+export enum LocationMode {
+ /**
+ * 低功耗模式,在这种模式下,将只使用高德网络定位。
+ */
+ Battery_Saving = "Battery_Saving",
+
+ /**
+ * 仅设备模式,只使用卫星定位,不支持室内环境的定位
+ */
+ Device_Sensors = "Device_Sensors",
+
+ /**
+ * 高精度模式,在这种定位模式下,将同时使用高德网络定位和卫星定位,优先返回精度高的定位
+ */
+ Hight_Accuracy = "Hight_Accuracy",
+}
+
+/**
+ * 定位场景
+ *
+ * @platform android
+ */
+export enum LocationPurpose {
+ /**
+ * 签到场景
+ *
+ * 只进行一次定位返回最接近真实位置的定位结果(定位速度可能会延迟 1-3s)。
+ */
+ SignIn = "SignIn",
+
+ /**
+ * 运动场景
+ *
+ * 高精度连续定位,适用于有户内外切换的场景,卫星定位和网络定位相互切换,卫星定位成功之后网络定位不再返回,卫星信号断开之后一段时间才会返回网络结果。
+ */
+ Sport = "Sport",
+
+ /**
+ * 出行场景
+ *
+ * 高精度连续定位,适用于有户内外切换的场景,卫星定位和网络定位相互切换,卫星定位成功之后网络定位不再返回,卫星信号断开之后一段时间才会返回网络结果。
+ */
+ Transport = "Transport",
+}
+
+/**
+ * 逆地理编码语言
+ */
+export enum GeoLanguage {
+ /**
+ * 默认,根据位置按照相应的语言返回逆地理信息,在国外按英语返回,在国内按中文返回
+ */
+ DEFAULT = "DEFAULT",
+
+ /**
+ * 中文,无论在国外还是国内都为返回中文的逆地理信息
+ */
+ ZH = "ZH",
+
+ /**
+ * 英文,无论在国外还是国内都为返回英文的逆地理信息
+ */
+ EN = "EN",
+}
+
+/**
+ * 卫星信号强度
+ *
+ * @platform android
+ */
+export enum GpsAccuracy {
+ UNKNOWN,
+ BAD,
+ GOOD,
+}
+
+/**
+ * 定位结果的可信度
+ */
+export enum TrustedLevel {
+ HIGH = 1,
+ NORMAL,
+ LOW,
+ BAD,
+}
+
+/**
+ * 定位信息
+ */
+export interface ILocation {
+ /**
+ * 定位精度 (米)
+ */
+ accuracy: number;
+
+ /**
+ * 经度,[-180, 180]
+ */
+ latitude: number;
+
+ /**
+ * 纬度,[-90, 90]
+ */
+ longitude: number;
+
+ /**
+ * 海拔(米),需要 GPS
+ */
+ altitude?: number;
+
+ /**
+ * 移动速度(米/秒),需要 GPS
+ */
+ speed?: number;
+
+ /**
+ * 移动方向,需要 GPS
+ */
+ heading?: number;
+
+ /**
+ * 定位时间(毫秒)
+ */
+ timestamp?: number;
+
+ /**
+ * 错误码
+ */
+ errorCode?: ErrorCode;
+
+ /**
+ * 错误信息
+ */
+ errorInfo?: string;
+
+ /**
+ * 定位信息描述
+ *
+ * @platform android
+ */
+ locationDetail?: string;
+
+ /**
+ * 定位结果来源
+ *
+ * @platform android
+ */
+ locationType?: LocationType;
+
+ /**
+ * 卫星信号强度,仅在卫星定位时有效
+ *
+ * @platform android
+ */
+ gpsAccuracy?: GpsAccuracy;
+
+ /**
+ * 坐标系类型
+ *
+ * @platform android
+ */
+ coordinateType?: "WGS84" | "GCJ02";
+
+ /**
+ * 定位结果的可信度,只有在定位结果正确时,才有意义
+ *
+ * @platform android
+ */
+ trustedLevel?: TrustedLevel;
+}
+
+/**
+ * 逆地理编码信息
+ */
+export interface ReGeocode {
+ /**
+ * 详细地址
+ */
+ address?: string;
+
+ /**
+ * 国家
+ */
+ country?: string;
+
+ /**
+ * 省份
+ */
+ province?: string;
+
+ /**
+ * 城市
+ */
+ city?: string;
+
+ /**
+ * 城市编码
+ */
+ cityCode?: string;
+
+ /**
+ * 地区
+ */
+ district?: string;
+
+ /**
+ * 街道
+ */
+ street?: string;
+
+ /**
+ * 门牌号
+ */
+ streetNumber?: string;
+
+ /**
+ * 兴趣点
+ */
+ poiName?: string;
+}
diff --git a/lib/src/geolocation.ts b/lib/src/geolocation.ts
new file mode 100644
index 0000000..82744e0
--- /dev/null
+++ b/lib/src/geolocation.ts
@@ -0,0 +1,151 @@
+import { EmitterSubscription } from "react-native";
+import { addLocationListener, start, stop, _options } from "./amap-geolocation";
+import { ILocation as Location } from "./gen-types";
+
+/**
+ * 坐标信息
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Coordinates
+ */
+export interface Coordinates {
+ latitude: number;
+ longitude: number;
+ altitude: number;
+ accuracy: number;
+ altitudeAccuracy: number;
+ heading: number;
+ speed: number;
+}
+
+/**
+ * 定位信息
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Position
+ */
+export interface Position {
+ coords: Coordinates;
+ timestamp: number;
+ location: Location;
+}
+
+/**
+ * 定位错误信息
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/PositionError
+ */
+export class PositionError {
+ static PERMISSION_DENIED: 1;
+ static POSITION_UNAVAILABLE: 2;
+ static TIMEOUT: 3;
+
+ code: number;
+ message: string;
+ location: Location;
+
+ constructor(code: number, message: string, location: Location) {
+ this.code = code;
+ this.message = message;
+ this.location = location;
+ }
+}
+
+/**
+ * 定位选项
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/PositionOptions
+ */
+export interface PositionOptions {
+ timeout?: number;
+ maximumAge?: number;
+ enableHighAccuracy?: boolean;
+
+ /**
+ * @see [[setDistanceFilter]]
+ */
+ distanceFilter?: number;
+}
+
+let watchId = 0;
+const watchMap: { [watchId: number]: EmitterSubscription } = {};
+
+/**
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation
+ */
+export default class Geolocation {
+ /**
+ * 获取当前位置信息
+ *
+ * 注意:使用该方法会停止持续定位
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/getCurrentPosition
+ */
+ static getCurrentPosition(
+ success: (position: Position) => void,
+ error?: (error: PositionError) => void
+ // options: PositionOptions = {}
+ ) {
+ const listener = addLocationListener((location) => {
+ if (location.errorCode) {
+ error && error(new PositionError(location.errorCode, location.errorInfo ?? "", location));
+ stop();
+ return listener.remove();
+ }
+ if (_options.locatingWithReGeocode && typeof location.address !== "string") {
+ return;
+ }
+ success(toPosition(location));
+ stop();
+ return listener.remove();
+ });
+ start();
+ }
+
+ /**
+ * 注册监听器进行持续定位
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/watchPosition
+ */
+ static watchPosition(
+ success: (position: Position) => void,
+ error?: (error: PositionError) => void
+ // options?: PositionOptions
+ ) {
+ watchMap[++watchId] = addLocationListener((location) => {
+ if (location.errorCode) {
+ error && error(new PositionError(location.errorCode, location.errorInfo ?? "", location));
+ } else {
+ success(toPosition(location));
+ }
+ });
+ start();
+ return watchId;
+ }
+
+ /**
+ * 移除位置监听
+ *
+ * @see https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/clearWatch
+ */
+ static clearWatch(id: number) {
+ const listener = watchMap[id];
+ if (listener) {
+ listener.remove();
+ }
+ }
+}
+
+function toPosition(location: Location) {
+ return {
+ location,
+ coords: {
+ latitude: location.latitude,
+ longitude: location.longitude,
+ altitude: location.altitude ?? 0,
+ accuracy: location.accuracy,
+ altitudeAccuracy: 0, // 高德定位接口没有找到对应的数据
+ heading: location.heading ?? 0,
+ speed: location.speed ?? 0,
+ },
+ timestamp: location.timestamp ?? 0,
+ };
+}
diff --git a/lib/src/index.ts b/lib/src/index.ts
index c2ded5a..0b57598 100644
--- a/lib/src/index.ts
+++ b/lib/src/index.ts
@@ -6,6 +6,10 @@ export { default as Marker } from "./marker";
export { default as MultiPoint } from "./multi-point";
export { default as Polygon } from "./polygon";
export { default as Polyline } from "./polyline";
+import * as AMapSdk from "./sdk";
export * from "./types";
+export * from "./gen-types";
+export * from "./geolocation";
+export * from "./amap-geolocation";
+export { default as Geolocation } from "./geolocation";
export { AMapSdk };
-import * as AMapSdk from "./sdk";
diff --git a/package.json b/package.json
index 4ac0578..c40f526 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@cqfw/react-native-amap3d",
- "version": "0.0.1",
+ "version": "0.0.2",
"description": "react-native 高德地图组件,支持 Android + iOS",
"author": "feewee",
"license": "MIT",
@@ -34,6 +34,7 @@
"supercluster": "^7.1.4"
},
"devDependencies": {
+ "@types/react-native": "^0.70.4",
"@types/supercluster": "^5.0.3",
"react": "17.0.2",
"react-native": "^0.62.0"