diff --git a/uni_modules/uni-getLocation-tencent/changelog.md b/uni_modules/uni-getLocation-tencent/changelog.md new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/uni_modules/uni-getLocation-tencent/package.json b/uni_modules/uni-getLocation-tencent/package.json new file mode 100644 index 0000000000000000000000000000000000000000..93bd425e0e943adeee1a1ebdf14d6cf8f6ac5419 --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/package.json @@ -0,0 +1,84 @@ +{ + "id": "uni-getLocation-tencent", + "displayName": "uni-getLocation-tencent", + "version": "1.0.0", + "description": "uni-getLocation-tencent", + "keywords": [ + "uni-getLocation-tencent" + ], + "repository": "", + "engines": { + "HBuilderX": "^3.6.11" + }, + "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"] + }, + "dependencies": [], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "u", + "aliyun": "u" + }, + "client": { + "Vue": { + "vue2": "n", + "vue3": "y" + }, + "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 diff --git a/uni_modules/uni-getLocation-tencent/readme.md b/uni_modules/uni-getLocation-tencent/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..f1ab96ced7687b2b2bb84244e9c07430d95f2c81 --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/readme.md @@ -0,0 +1,50 @@ +# uts-tencentgeolocation腾讯定位插件使用文档 + +## Android 平台 + +1. 申请腾讯地图key + +[申请网址](https://lbs.qq.com/mobile/androidMapSDK/developerGuide/getKey) + +2. 配置key到插件中 + +修改项目根目录下 AndroidManifest.xml +`` + +3. 打包自定义基座 + +注意将`uts-tencentgeolocation/utssdk/app-android/libs/androix-core-1.0.0.jar`先移到其他目录。 + +4. 运行自定义基座 + +注意打包自定义基座后将androix-core-1.0.0.jar移回原位,然后真机运行自定义基座。这个临时的移出移入问题后续会升级解决,详见uts插件开发文档的[临时注意](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html#tempnotice)。 + +## iOS 平台 + +1.申请腾讯地图key + +[申请网址](https://lbs.qq.com/mobile/androidMapSDK/developerGuide/getKey) + +2.配置key到插件中 + +将申请的key配置到插件目录下 app-ios -> info.plist 中 TencentLBSAPIKey 对应的值 + +```xml +TencentLBSAPIKey +您申请的Key +``` + +3.配置访问位置权限描述信息 + +选中工程中的 manifest.json -> App权限配置 -> iOS隐私信息访问的许可描述,分别配置下列权限描述信息 + +- NSLocationAlwaysUsageDescription +- NSLocationWhenInUseUsageDescription +- NSLocationAlwaysAndWhenInUseUsageDescription + +4.制作自定义基座运行后生效 + +## 相关开发文档 + +- [UTS 语法](https://uniapp.dcloud.net.cn/tutorial/syntax-uts.html) +- [UTS 原生插件](https://uniapp.dcloud.net.cn/plugin/uts-plugin.html) \ No newline at end of file diff --git a/uni_modules/uni-getLocation-tencent/utssdk/app-android/AndroidManifest.xml b/uni_modules/uni-getLocation-tencent/utssdk/app-android/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..3b88fd195d6d32bb34cbe06be73a475659c9f327 --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/utssdk/app-android/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uni_modules/uni-getLocation-tencent/utssdk/app-android/config.json b/uni_modules/uni-getLocation-tencent/utssdk/app-android/config.json new file mode 100644 index 0000000000000000000000000000000000000000..440faa8e357993e70f46a624de6509a09fc6f73a --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/utssdk/app-android/config.json @@ -0,0 +1,7 @@ +{ + "dependencies": [ + "com.tencent.map.geolocation:TencentLocationSdk-openplatform:7.3.0" + ], + "minSdkVersion": 21 +} + diff --git a/uni_modules/uni-getLocation-tencent/utssdk/app-android/index.uts b/uni_modules/uni-getLocation-tencent/utssdk/app-android/index.uts new file mode 100644 index 0000000000000000000000000000000000000000..7e8be43a51517af060fb82e68e9c661c2fe213e7 --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/utssdk/app-android/index.uts @@ -0,0 +1,219 @@ +import { + UTSAndroid +} from "io.dcloud.uts"; + +import ActivityCompat from "androidx.core.app.ActivityCompat"; +import Manifest from "android.Manifest"; +import Looper from "android.os.Looper"; +import TencentLocationManager from "com.tencent.map.geolocation.TencentLocationManager"; +import TencentLocationListener from "com.tencent.map.geolocation.TencentLocationListener"; +import TencentLocation from "com.tencent.map.geolocation.TencentLocation"; +import TencentLocationRequest from "com.tencent.map.geolocation.TencentLocationRequest"; +import PackageManager from "android.content.pm.PackageManager"; +import Class from 'java.lang.Class'; +import Exception from 'java.lang.Exception'; + +import { GetLocation, GetLocationOptions, GetLocationSuccess,GetLocationFail } from "../interface.uts" + + + +export const getLocation : GetLocation = function (options : GetLocationOptions) { + + if(!checkHasIntegration()){ + // 当前没有集成腾讯sdk,提示需要打包 + let ret : GetLocationFail = { + errCode: -10, + errMsg: "需要打自定义基座", + errSubject: "uni-getLocation-tencent" + } + options.fail?.(ret) + options.complete?.(ret) + return; + } + if (!checkLocationConfig()) { + let ret : GetLocationFail = { + errCode: -20, + errMsg: "未通过配置预校验,通常是app key 配置错误", + errSubject: "uni-getLocation-tencent" + } + options.fail?.(ret) + options.complete?.(ret) + return; + } + + /** + * 准备权限 + */ + 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 ret : GetLocationFail = { + errCode: -30, + errMsg: "permission missed.", + errSubject: "uni-getLocation-tencent" + } + options.fail?.(ret) + options.complete?.(ret) + }) + + +} + + +/****************************************内部功能实现****************************************************/ + + +/** + * 定位监听结果包装类 + */ +class LocationOptionsWapper { + + hostOption : GetLocationOptions; + + constructor(option : GetLocationOptions) { + this.hostOption = option + } + + onLocationChanged(location : TencentLocation, _error : Int, + _reason : string) { + + let ret : GetLocationSuccess = { + latitude: location.latitude, + longitude: location.longitude, + speed: 0, + accuracy: location.accuracy, + altitude: location.altitude, + verticalAccuracy: 0, + horizontalAccuracy: location.accuracy, + address: location.address + } + + this.hostOption.success?.(ret) + // 包装数据结构返回 + } + + + onStatusUpdate(_name : string, _status : Int, _desc : string) { + // 定位状态发生变化 + } +}; + + +/** + * Tencent 定位监听实现类 + */ +class SingleLocationListener extends TencentLocationListener { + + + hostOptionWraper : LocationOptionsWapper; + + constructor(option : LocationOptionsWapper) { + super(); + this.hostOptionWraper = option + } + + override onLocationChanged(location : TencentLocation, error : Int, + reason : string) : void { + this.hostOptionWraper.onLocationChanged(location, error, reason); + } + + override onStatusUpdate(name : string, status : Int, desc : string) : void { + this.hostOptionWraper.onStatusUpdate(name, status, desc); + } + +} +/** + * 判断当前的基座是否已经集成了sdk, 即是否是自定义基座 + */ +function checkHasIntegration() : boolean { + + let hasIntegration = true + try { + let xClass = Class.forName("com.tencent.map.geolocation.TencentLocationListener") + } catch (e : Exception) { + hasIntegration = false; + } + + if (!hasIntegration) { + return false; + } + + return true +} +/** + * 检查定位的相关配置是否正确 + */ +function checkLocationConfig() : boolean { + + let packageName = UTSAndroid.getAppContext()!.getPackageName(); + let appInfo = UTSAndroid.getAppContext()!.getPackageManager()!.getApplicationInfo(packageName, PackageManager.GET_META_DATA) + + let metaData = appInfo.metaData + if (metaData == null) { + return false; + } + let adId = metaData.getString("TencentMapSDK") + if (adId == null) { + return false; + } + let splitArray = adId!.split("-") + let keyCharNum = splitArray.size + + if (keyCharNum > 5) { + // 存在超过5个-,说明是符合规则的appkey + return true; + } + // 不符合校验规则,打回 + return false; +} + + +/** + * 腾讯地图获取定位信息 + * 参考文档:https://lbs.qq.com/mobile/androidLocationSDK/androidGeoGuide/androidGeoAdapt + */ +function getLocationImpl(locationOptions : GetLocationOptions) { + + if(locationOptions.type != null && locationOptions.type!.toUpperCase() != 'GCJ-02' && locationOptions.type!.toUpperCase() != 'GCJ02'){ + // 腾讯定位只支持GCJ-02,如果不是则报错 + let ret : GetLocationFail = { + errCode: -1, + errMsg: "GCJ-02 support only.", + errSubject: "uni-getLocation-tencent" + } + locationOptions.fail?.(ret) + locationOptions.complete?.(ret) + return + } + + let mLocationManager = TencentLocationManager.getInstance(UTSAndroid.getAppContext()); + // 定位监听器封装 + let locationOptionWrapper = new LocationOptionsWapper(locationOptions); + let mLocationListener = new SingleLocationListener(locationOptionWrapper); + // 发起单次请求 + let locationRequest = TencentLocationRequest.create() + // 是否需要逆地理编码 + if (locationOptions.geocode != null && locationOptions.geocode == true) { + locationRequest.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_NAME); + } else { + locationRequest.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_GEO); + } + // 是否开启了高精度 + if (locationOptions.isHighAccuracy != null && locationOptions.isHighAccuracy == true) { + locationRequest.setAllowGPS(true) + } + /** + * 高度信息,腾讯没有明确的api设置 + */ + if (locationOptions.altitude != null && locationOptions.altitude == true) { + locationRequest.setAllowGPS(true) + } + + mLocationManager.requestSingleFreshLocation(locationRequest, mLocationListener, Looper.getMainLooper()); + +} diff --git a/uni_modules/uni-getLocation-tencent/utssdk/interface.uts b/uni_modules/uni-getLocation-tencent/utssdk/interface.uts new file mode 100644 index 0000000000000000000000000000000000000000..96bc6270164b3b31bc232d3dfd58b4a7414502c9 --- /dev/null +++ b/uni_modules/uni-getLocation-tencent/utssdk/interface.uts @@ -0,0 +1,93 @@ +export interface Uni { + /** + * 获取当前的地理位置、速度 + * + * @tutorial http://uniapp.dcloud.io/api/location/location?id=getlocation + */ + getLocation: GetLocation; +} + +export type GetLocation = (options: GetLocationOptions) => void; +export type GetLocationSuccess = { + /** + * 纬度,浮点数,范围为-90~90,负数表示南纬 + */ + latitude: number, + /** + * 经度,范围为-180~180,负数表示西经 + */ + longitude: number, + /** + * 速度,浮点数,单位m/s + */ + speed: number, + /** + * 位置的精确度 + */ + accuracy: number, + /** + * 高度,单位 m + */ + altitude: number, + /** + * 垂直精度,单位 m(Android 无法获取,返回 0) + */ + verticalAccuracy: number, + /** + * 水平精度,单位 m + */ + horizontalAccuracy: number, + /** + * 地址信息 + */ + address: any | null +}; +type GetLocationSuccessCallback = (result: GetLocationSuccess) => void; +export type GetLocationFail = UniError; +type UniError = { + errSubject: string, + errCode: number, + errMsg: string, + data: object | null, + cause: any | null +}; +type GetLocationFailCallback = (result: GetLocationFail) => void; +type GetLocationComplete = any; +type GetLocationCompleteCallback = (result: GetLocationComplete) => void; +export type GetLocationOptions = { + /** + * 默认为 wgs84 返回 gps 坐标,gcj02 返回可用于uni.openLocation的坐标 + */ + type?: string | null, + /** + * 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度 + * @type boolean + */ + altitude?: boolean | null, + /** + * 传入 true 会解析地址 + * @type boolean + */ + geocode?: boolean | null, + /** + * 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果 + */ + highAccuracyExpireTime?: number | null, + /** + * 开启高精度定位 + * @type boolean + */ + isHighAccuracy?: boolean | null, + /** + * 接口调用成功的回调函数 + */ + success?: GetLocationSuccessCallback | null, + /** + * 接口调用失败的回调函数 + */ + fail?: GetLocationFailCallback | null, + /** + * 接口调用结束的回调函数(调用成功、失败都会执行) + */ + complete?: GetLocationCompleteCallback | null +};