index.uts 5.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 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
import { GetLocation, GetLocationOptions, GetLocationSuccess,GetLocationFail } from "../interface.uts"
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) {
	
	/**
	 * 准备权限
	 */
	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) {
	
	/**
	 * add since 2023-09-14 增加默认值兼容逻辑
	 */
	if(options.type == null){
		options.type = 'wgs84'
	}
	if(options.highAccuracyExpireTime == null){
		options.highAccuracyExpireTime = 3000
	}
	
	
	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
	}
	
	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
	}
	

	
	let locationManager = UTSAndroid.getAppContext()!.getSystemService(Context.LOCATION_SERVICE) as LocationManager;
	let criteria = new Criteria()
	
	// 用户明确开启了高度
	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)
	}
	
	criteria.setPowerRequirement(Criteria.POWER_LOW)
	criteria.setSpeedRequired(true)
	
	/**
	 * 如果存在gps,那么优先gps,这样才有高度信息
	 */
	let providerName:string|null = "gps"
	if(!locationManager.getProviders(criteria, true).contains("gps")){
		providerName = locationManager.getBestProvider(criteria, true)
	}
	
	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!
	}
	
	let taskId = 0
	let startTimeMill = (new Date()).getTime()
	// 不管返回结果如何,延迟2s 返回数据
	taskId = setInterval(function () {
		if (Global.lastLocation == null) {
			// 没有得到想要的位置,统计错误计数+1
			
			let currentTimeMill = (new Date()).getTime()
			let diffTimeNum = currentTimeMill - startTimeMill
			
			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);
}