Andorid App 通过webview内嵌h5获取定位
Android app中内嵌h5获取辅助定位一般需要两步:
第一步在Android的AndroidManifest.xml文件中添加读写权限、模糊定位权限、精确定位权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
第二部通过webview开启辅助定位
1、初始化AMapLocationClient
locationClient = new AMapLocationClient(getApplicationContext());
2、加载webview控件
webView = (WebView) findViewById(R.id.webView);
3、在设置webview属性之前开启辅助定位,在设置属性之后体验不好
locationClient.startAssistantLocation(webView);
4、设置webview属性
//加载URL
webView.loadUrl(Utils.URL_H5LOCATION);
//设置webView参数和WebViewClient
WebSettings webSettings = webView.getSettings();
// 允许webview执行javaScript脚本
webSettings.setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
});
webView.setWebChromeClient(new WebChromeClient() {
// 处理javascript中的alert
public boolean onJsAlert(WebView view, String url, String message,
final JsResult result) {
return true;
};
// 处理javascript中的confirm
public boolean onJsConfirm(WebView view, String url,
String message, final JsResult result) {
return true;
};
// 处理定位权限请求
@Override
public void onGeolocationPermissionsShowPrompt(String origin,
Callback callback) {
callback.invoke(origin, true, false);
super.onGeolocationPermissionsShowPrompt(origin, callback);
}
@Override
// 设置网页加载的进度条
public void onProgressChanged(WebView view, int newProgress) {
Assistant_Location_Activity.this.getWindow().setFeatureInt(
Window.FEATURE_PROGRESS, newProgress * 100);
super.onProgressChanged(view, newProgress);
}
// 设置应用程序的标题title
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
}
});
5、使用完辅助 H5 页面定位功能时,及时停止该功能,避免不必要的设备能耗开销
locationClient.stopAssistantLocation();
H5获取定位:
1、使用Geolocation获取定位
if(navigator.geolocation){
// getCurrentPosition支持三个参数
// getSuccess是执行成功的回调函数
// getError是失败的回调函数
// getOptions是一个对象,用于设置getCurrentPosition的参数
// 后两个不是必要参数
var getOptions = {
//是否使用高精度设备,如GPS。默认是true
enableHighAccuracy:true,
//超时时间,单位毫秒,默认为0
timeout:5000,
//使用设置时间内的缓存数据,单位毫秒
//默认为0,即始终请求新数据
//如设为Infinity,则始终使用缓存数据
maximumAge:0
};
navigator.geolocation.getCurrentPosition(getSuccess, getError, getOptions);
//成功回调
function getSuccess(position){
// getCurrentPosition执行成功后,会把getSuccess传一个position对象
// position有两个属性,coords和timeStamp
// timeStamp表示地理数据创建的时间??????
// coords是一个对象,包含了地理位置数据
console.log(position.timeStamp);
// 估算的纬度
console.log(position.coords.latitude);
// 估算的经度
console.log(position.coords.longitude);
// 估算的高度 (以米为单位的海拔值)
console.log(position.coords.altitude);
// 所得经度和纬度的估算精度,以米为单位
console.log(position.coords.accuracy);
// 所得高度的估算精度,以米为单位
console.log(position.coords.altitudeAccuracy);
// 宿主设备的当前移动方向,以度为单位,相对于正北方向顺时针方向计算
console.log(position.coords.heading);
// 设备的当前对地速度,以米/秒为单位
console.log(position.coords.speed);
// 除上述结果外,Firefox还提供了另外一个属性address
if(position.address){
//通过address,可以获得国家、省份、城市
console.log(position.address.country);
console.log(position.address.province);
console.log(position.address.city);
}
}
//失败回调
function getError(error){
// 执行失败的回调函数,会接受一个error对象作为参数
// error拥有一个code属性和三个常量属性TIMEOUT、PERMISSION_DENIED、POSITION_UNAVAILABLE
// 执行失败时,code属性会指向三个常量中的一个,从而指明错误原因
switch(error.code){
case error.TIMEOUT:
console.log('超时');
break;
case error.PERMISSION_DENIED:
console.log('用户拒绝提供地理位置');
break;
case error.POSITION_UNAVAILABLE:
console.log('地理位置不可用');
break;
default:
break;
}
}
// watchPosition方法一样可以设置三个参数
// 使用方法和getCurrentPosition方法一致,只是执行效果不同。
// getCurrentPosition只执行一次
// watchPosition只要设备位置发生变化,就会执行
var watcher_id = navigator.geolocation.watchPosition(getSuccess, getError, getOptions);
//clearwatch用于终止watchPosition方法
clearWatch(watcher_id);
}
使用这种方法部分手机会出现超时问题,不过依然能够获取到定位地址,可以将超时时间设置的大一些就不会出现这种问题,另外设置一个延时也是可以的
2、使用uni app 提供的uni.getLocation方法获取定位,建议使用国标局类型的,使用过wgs84的,但是有些机子获取的定位要么获取不到定位要么定位很奇怪,没有仔细研究过源码,也不好直接说问题出在哪里。
uni.getLocation({
type: 'gcj02',
// 高精度定位超时时间(ms)部分Android机子返回定位需要很长时间,所以最好设置一下
highAccuracyExpireTime: 100,
success: (res) => {
this.longitude = res.longitude
this.latitude = res.latitude
},
fail: (e) => {
console.log(err)
// #ifdef MP-BAIDU
if (err.errCode === 202 || err.errCode === 10003) {
// 202模拟器 10003真机 user deny
}
// #endif
// #ifndef MP-BAIDU
if (err.errMsg.indexOf("auth deny") >= 0) {
uni.showToast({
title: "访问位置被拒绝"
})
} else {
uni.showToast({
title: err.errMsg
})
}
// #endif
},
complete: (c) => {
// 经过实测有些Android机子很奇怪,在success方法中无法获取到返回结果,只能在complete中拿到,不想吐槽
this.longitude = res.longitude
this.latitude = res.latitude
});
使用国标局的需要引一下三方的SDK,在manifest.json文件里面配置一下
"h5": {
"sdkConfigs": {
// 使用地图或位置相关功能必须填写其一
"maps": {
"qqmap": {
// 腾讯地图秘钥 https://lbs.qq.com/dev/console/key/manage
"key": ""
},
"google": {
// 谷歌地图秘钥(HBuilderX 3.2.10+)https://developers.google.com/maps/documentation/javascript/get-api-key
"key": ""
},
"amap": {
// 高德地图秘钥(HBuilderX 3.6.0+)https://console.amap.com/dev/key/app
"key": "",
// 高德地图安全密钥(HBuilderX 3.6.0+)https://console.amap.com/dev/key/app
"securityJsCode": "",
// 高德地图安全密钥代理服务器地址(HBuilderX 3.6.0+)https://lbs.amap.com/api/jsapi-v2/guide/abc/prepare
"serviceHost": "",
}
}
}
}
当然,不想这么干的,在index.html中引入也是可行的
直接内嵌html的,在使用的页面引入对应的sdk即可,然后使用Geolocation方法获取定位也是可以,不过要稍微处理一下可能出现的超时问题。
在最后解释一下为什么有些机子里面的webview不要授权也是可以获取到的,因为这些机子的系统太老了,新版的基本都需要了;另外uni.getLocation也只是对Geolocation的进一步封装,其他的框架也基本是这样的,用的不爽的可以选择不用,自己重新封装一个就好,理解原理了咋弄都成