提交 f4f3504a 编写于 作者: DCloud-yyl's avatar DCloud-yyl

开源:uni.getLocation 的 系统定位

上级 1fe790d4
{
"id": "uni-getLocation-system",
"displayName": "uni-getLocation-system",
"version": "1.0.0",
"description": "uni-getLocation-system",
"keywords": [
"uni-getLocation-system"
],
"repository": "",
"engines": {
"HBuilderX": "^3.6.8"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "",
"data": "",
"permissions": ""
},
"npmurl": ""
},
"uni_modules": {
"uni-ext-api": {
"uni": {
"getLocation": {
"name": "getLocation",
"app": {
"js": false,
"kotlin": true,
"swift": false
}
}
}
},
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "u",
"aliyun": "u"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-android": "u",
"app-ios": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}
\ No newline at end of file
# uts-location
### 开发文档
[UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html)
[UTS API插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html)
[UTS 组件插件](https://uniapp.dcloud.net.cn/plugin/uts-component.html)
[Hello UTS](https://gitcode.net/dcloud/hello-uts)
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
package="io.dcloud.uni.getlocation.system">
<!--permissions-->
<!-- 通过GPS得到精确位置 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 通过网络得到粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 访问网络,某些位置信息需要从网络服务器获取 -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
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);
}
export interface Uni {
/**
* @description 获取当前的地理位置、速度
* @param {GetLocation} option
* @example
* ```typescript
* uni.getLocation({
* type: 'wgs84',
* success: function (res) {
* console.log('当前位置的经度:' + res.longitude);
* console.log('当前位置的纬度:' + res.latitude);
* }
* });
* ```
* @tutorial [](http://uniapp.dcloud.io/api/location/location?id=getlocation)
* @uniPlatform {
* "app": {
* "android": {
* "osVer": "4.4.4",
* "uniVer": "√",
* "unixVer": "3.9.0"
* },
* "ios": {
* "osVer": "x",
* "uniVer": "x",
* "unixVer": "x"
* }
* }
* }
*/
getLocation(options: GetLocationOptions):void;
}
export type GetLocation = (options: GetLocationOptions) => void;
export type GetLocationSuccess = {
/**
* 纬度,浮点数,范围为-90~90,负数表示南纬
* @defaultValue 0
*/
latitude: number,
/**
* 经度,范围为-180~180,负数表示西经
* @defaultValue 0
*/
longitude: number,
/**
* 速度,浮点数,单位m/s
* @defaultValue 0
*/
speed: number,
/**
* 位置的精确度
*/
accuracy: number,
/**
* 高度,单位 m
* @defaultValue 0
*/
altitude: number,
/**
* 垂直精度,单位 m(Android 无法获取,返回 0)
* @defaultValue 0
*/
verticalAccuracy: number,
/**
* 水平精度,单位 m
* @defaultValue 0
*/
horizontalAccuracy: number,
/**
* 地址信息
* @defaultValue null
*/
address: any | null
};
type GetLocationSuccessCallback = (result: GetLocationSuccess) => void;
type GetLocationFailCallback = (result: UniError) => void;
type GetLocationComplete = any;
type GetLocationCompleteCallback = (result: GetLocationComplete) => void;
export type GetLocationOptions = {
/**
* 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于uni.openLocation的坐标
* @defaultValue wgs84
*/
type?: string | null,
/**
* 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度
* @type boolean
* @defaultValue false
*/
altitude?: boolean | null,
/**
* 传入 true 会解析地址
* @type boolean
* @defaultValue false
*/
geocode?: boolean | null,
/**
* 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果
* @defaultValue 3000
*/
highAccuracyExpireTime?: number | null,
/**
* 开启高精度定位
* @type boolean
* @defaultValue false
*/
isHighAccuracy?: boolean | null,
/**
* 接口调用成功的回调函数
*/
success?: GetLocationSuccessCallback | null,
/**
* 接口调用失败的回调函数
*/
fail?: GetLocationFailCallback | null,
/**
* 接口调用结束的回调函数(调用成功、失败都会执行)
*/
complete?: GetLocationCompleteCallback | null
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册