index.uts 5.1 KB
Newer Older
杜庆泉's avatar
杜庆泉 已提交
1
import { GetLocation, GetLocationOptions, GetLocationSuccess } from "../interface.uts"
2 3 4 5 6 7 8 9 10 11 12 13 14
import UTSAndroid from 'io.dcloud.uts.UTSAndroid';
import Context from 'android.content.Context';
import LocationManager from 'android.location.LocationManager';
import Criteria from 'android.location.Criteria';
import Location from 'android.location.Location';
import LocationListener from 'android.location.LocationListener';



/**
 * 对外的函数接口
 */
export const getLocation : GetLocation = function (options : GetLocationOptions) {
杜庆泉's avatar
杜庆泉 已提交
15

16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
	/**
	 * 准备权限
	 */
	let permissionNeed : string[] = utsArrayOf("android.permission.ACCESS_FINE_LOCATION");
	UTSAndroid.requestSystemPermission(UTSAndroid.getUniActivity()!, permissionNeed, function (allRight:boolean,_grantedList:string[]) {
		if (allRight) {
			// 交给目前的location 引擎,真实执行
			getLocationImpl(options)
		}
	}, function (_doNotAskAgain:boolean,_grantedList:string[]) {
		console.log("用户拒绝了部分权限:")
		let err = new UniError("uni-getLocation-system",-10,"permission missed.");
		options.fail?.(err)
		options.complete?.(err)
	})

}

/****************************************内部功能实现****************************************************/
/**
 * 全局信息处理
 */
class Global {
	/**
	 * 默认实现
	 */
	static lastLocation : Location | null = null;
}


/**
 * 封装系统监听回调
 */
class CustomSystemLocationListener extends LocationListener {
	override onLocationChanged(location : Location) : void {
		Global.lastLocation = location
	}
}


/**
 * 真实的执行位置定位
 */
function getLocationImpl(options : GetLocationOptions) {
杜庆泉's avatar
杜庆泉 已提交
60

61 62 63 64 65 66 67 68 69
	/**
	 * add since 2023-09-14 增加默认值兼容逻辑
	 */
	if(options.type == null){
		options.type = 'wgs84'
	}
	if(options.highAccuracyExpireTime == null){
		options.highAccuracyExpireTime = 3000
	}
杜庆泉's avatar
杜庆泉 已提交
70 71


72 73 74 75 76 77 78
	if(options.type != 'wgs84'){
		// 系统定位只支持wgs84,如果不是则报错
		let err = new UniError("uni-getLocation-system",-1,"system location support wgs84 only.");
		options.fail?.(err)
		options.complete?.(err)
		return
	}
杜庆泉's avatar
杜庆泉 已提交
79

80 81 82 83 84 85 86 87
	if(options.geocode != null && options.geocode == true){
		// 系统定位不支持逆地理编码
		let err = new UniError("uni-getLocation-system",-2,"system location not support geocode.");
		options.fail?.(err)
		options.complete?.(err)
		return
	}

杜庆泉's avatar
杜庆泉 已提交
88 89


90 91
	let locationManager = UTSAndroid.getAppContext()!.getSystemService(Context.LOCATION_SERVICE) as LocationManager;
	let criteria = new Criteria()
杜庆泉's avatar
杜庆泉 已提交
92

93 94 95 96 97 98 99 100 101 102
	// 用户明确开启了高度
	if (options.altitude != null && options.altitude == true) {
		criteria.setAltitudeRequired(true)
	}
	// 设置精度
	if (options.isHighAccuracy != null && options.isHighAccuracy == true) {
		criteria.setAccuracy(Criteria.ACCURACY_FINE)
	} else{
		criteria.setAccuracy(Criteria.ACCURACY_COARSE)
	}
杜庆泉's avatar
杜庆泉 已提交
103

104 105
	criteria.setPowerRequirement(Criteria.POWER_LOW)
	criteria.setSpeedRequired(true)
杜庆泉's avatar
杜庆泉 已提交
106

107 108 109 110 111 112 113
	/**
	 * 如果存在gps,那么优先gps,这样才有高度信息
	 */
	let providerName:string|null = "gps"
	if(!locationManager.getProviders(criteria, true).contains("gps")){
		providerName = locationManager.getBestProvider(criteria, true)
	}
杜庆泉's avatar
杜庆泉 已提交
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
	if (providerName == null) {
		// 没有找到合法的系统定位能力提供者,错误的逻辑 todo
		let err = new UniError("uni-getLocation-system",-3,"Provider is not find,Please ensure that the device location function is turned on");
		options.fail?.(err)
		options.complete?.(err)
		return;
	}
	// 兜底的逻辑是上次定位的信息
	Global.lastLocation = locationManager.getLastKnownLocation(providerName)
	let systemListener = new CustomSystemLocationListener()
	locationManager.requestLocationUpdates(providerName, 2000, 0.0.toFloat(), systemListener)


	// 默认超时6000ms
	let timeoutMill:number = 6000;
	/**
	 * 只有设置超出3000ms 才会认为有效
	 * https://uniapp.dcloud.net.cn/api/location/location.html#getlocation
	 */
	if(options.highAccuracyExpireTime != null && options.highAccuracyExpireTime! >= 3000){
		timeoutMill = options.highAccuracyExpireTime!
	}
杜庆泉's avatar
杜庆泉 已提交
137

138 139 140 141 142 143
	let taskId = 0
	let startTimeMill = (new Date()).getTime()
	// 不管返回结果如何,延迟2s 返回数据
	taskId = setInterval(function () {
		if (Global.lastLocation == null) {
			// 没有得到想要的位置,统计错误计数+1
杜庆泉's avatar
杜庆泉 已提交
144

145 146
			let currentTimeMill = (new Date()).getTime()
			let diffTimeNum = currentTimeMill - startTimeMill
杜庆泉's avatar
杜庆泉 已提交
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
			if (diffTimeNum > timeoutMill) {
				locationManager.removeUpdates(systemListener)
				// 超过6s了,返回错误
				clearInterval(taskId)
				let err = new UniError("uni-getLocation-system",-4,"location fail: timeout");
				options.fail?.(err)
				options.complete?.(err)
			}
		} else {
			locationManager.removeUpdates(systemListener)
			clearInterval(taskId)
			let ret : GetLocationSuccess = {
				latitude: Global.lastLocation!.getLatitude(),
				longitude: Global.lastLocation!.getLongitude(),
				speed: Global.lastLocation!.getSpeed(),
				accuracy: Global.lastLocation!.getAccuracy(),
				altitude: Global.lastLocation!.getAltitude(),
				verticalAccuracy: 0,
				horizontalAccuracy: Global.lastLocation!.getAccuracy(),
				address: null
			}
			options.success?.(ret)
			Global.lastLocation = null
		}

	}, 2000);
}