react-native-anavi
Version:
react native amap navigation component, Android + iOS
279 lines (254 loc) • 7.24 kB
text/typescript
import { NativeModules, NativeEventEmitter, AppState, AppStateStatus } from 'react-native';
const { AMapLocation } = NativeModules;
const eventEmitter = new NativeEventEmitter(AMapLocation);
export class ALocationProxy {
listener: ALocationListner;
constructor(listener: ALocationListner) {
this.listener = listener;
}
public stop(): void {
const index = listeners.indexOf(this.listener);
if (index > -1) {
listeners.splice(index, 1);
}
}
}
class ALocationListner {
once: boolean;
background: boolean;
callback: (location: ALocation) => void;
callbackTarget: any;
public constructor(once: boolean, backgroud: boolean, callback: (location: ALocation) => void) {
this.once = once;
this.background = backgroud;
this.callback = callback;
}
public apply(location: ALocation): void {
if (this.callback) {
this.callback(location);
}
}
}
interface LocationError {
readonly code: number;
readonly info: string;
readonly details: string;
}
interface LocationQualityReport {
/**
* 获取提示语义,状态良好时,返回的是内容为空 根据当前的质量报告,给出相应的建议
*/
readonly adviseMessage: string;
/**
* 获取当前的卫星数, 只有在非低功耗模式下此值才有效
*/
readonly gpsSatellites: number;
/**
* 获取卫星状态信息,只有在非低功耗模式下此值才有效
*/
readonly gpsStatus: number;
/**
* 获取网络定位时的网络耗时 单位:毫秒
*/
readonly netUseTime: number;
/**
* 获取网络连接类型(2G、3G、4G、WIFI)
*/
readonly networkType: string;
/**
* 是否安装了高危位置模拟软件 首次定位可能没有结果
*/
readonly isInstalledHighDangerMockApp: boolean;
/**
* wifi开关是否打开 如果wifi关闭建议打开wifi开关,提高定位质量
*/
readonly isWifiAble: boolean;
}
export interface ALocation {
/**
*
*/
readonly error: LocationError;
/**
* 获取定位结果来源
*/
readonly type: number;
/**
* 获取纬度
*/
readonly latitude: number;
/**
* 获取纬度
*/
readonly longitude: number;
/**
* 获取定位精度
*/
readonly accuracy: number;
/**
* 获取定位提供者
*/
readonly provider: string;
/**
* 获取速度
*/
readonly speed: number;
/**
* 获取角度
*/
readonly bearing: number;
/**
* 获取当前可用卫星数量, 仅在卫星定位时有效
*/
readonly satellites: number;
/**
* 获取国家名称
*/
readonly country: string;
/**
* 获取城市名称
*/
readonly city: string;
/**
* 获取城市编码
*/
readonly cityCode: string;
/**
* 获取区域名称
*/
readonly district: string;
/**
* 获取区域编码
*/
readonly districtCode: string;
/**
* 获取地址
*/
readonly address: string;
/**
* 获取兴趣点
*/
readonly poiName: string;
/**
* 获取定位时间
*/
readonly time: number;
/**
* 获取定位质量报告
*/
readonly quality: LocationQualityReport;
}
export type ALocationCallback = (location: ALocation) => void;
export class ALocationClientOptions {
httpTimeout?: number;
interval?: number;
cacheEnabled?: boolean;
mode?: 'Battery_Saving' | 'Device_Sensors' | 'Hight_Accuracy';
protocol?: 'HTTP' | 'HTTPS';
mockEnabled?: boolean;
needAddress?: boolean;
sensorEnable?: boolean;
wifiScan?: boolean;
}
/** 当前是否在后台运行 */
var isBackground: boolean = false;
/** 当前是否在后台定位 */
var isBackgroundLocation: boolean = false;
var listeners: ALocationListner[] = [];
var locationOptions: ALocationClientOptions = {};
/** 是否已经开始定位*/
var isStarted = false;
const start = () => {
if (isStarted) {
return;
}
isStarted = true;
AMapLocation.start(locationOptions);
};
const stop = () => {
isStarted = false;
AMapLocation.stop();
};
const appStateChangeListner = (status: AppStateStatus) => {
isBackground = status !== 'active';
console.log(`------>AMapLocation: The application's status is ${status}`);
if (!isBackground) {
console.log(`------>AMapLocation: enter forground disable background location`);
AMapLocation.enabledBackground(false);
} else if (isBackgroundLocation) {
console.log(`------>AMapLocation: enter background, enabled background location`);
AMapLocation.enabledBackground(true);
}
};
const amapLocationListner = (location: ALocation) => {
for (const listener of listeners) {
if (!listener.background && isBackground) {
continue;
}
listener.apply(location);
}
// 删除once的listener
listeners = listeners.filter((listener) => !listener.once);
// 没有后台监听
if (isBackgroundLocation && !listeners.find((l) => l.background)) {
isBackgroundLocation = false;
console.log(`------>AMapLoaction: There has't background location callback, will stop backgroud location`);
}
// 已经没有位置监听,自动关闭位置服务
if (!listeners.length) {
console.log(`------>AMapLoaction: There has't location callback, will auto stop the location service`);
stop();
}
};
/**
* 高德定位服务
*/
export class ALocationClient {
private constructor() {
AppState.addEventListener('change', appStateChangeListner);
eventEmitter.addListener('amap_location', amapLocationListner);
}
private static instance: ALocationClient;
/**
* 获取ALoaction的单例
*/
public static getInstace(): ALocationClient {
if (!ALocationClient.instance) {
ALocationClient.instance = new ALocationClient();
}
return ALocationClient.instance;
}
/**
* 当前是否已启用后台定位
*/
public get isBackground(): boolean {
return isBackgroundLocation;
}
/**
* 获取或设置定位选项
*/
public set options(options: ALocationClientOptions) {
locationOptions = options;
}
public get options(): ALocationClientOptions {
return locationOptions;
}
public location(callback: ALocationCallback, background: boolean = false): ALocationProxy {
this.checkIsAutoStop();
if (background && !isBackgroundLocation) {
isBackgroundLocation = true;
}
const listener: ALocationListner = new ALocationListner(false, background, callback);
listeners.push(listener);
return new ALocationProxy(listener);
}
public locationOnce(callback: ALocationCallback): void {
this.checkIsAutoStop();
listeners.push(new ALocationListner(true, false, callback));
}
private checkIsAutoStop(): void {
if (!isStarted) {
start();
}
}
}