Android WebView 加载网页url中,H5通过js获取位置定位信息。 window.init = function() { v
Android WebView 加载网页url中,H5通过js获取位置定位信息。
window.init = function() {
var map = new AMap.Map('mapContainer', {
resizeEnable: true,
zoom: 14
});
map.plugin('AMap.Geolocation', function() {
geolocation = new AMap.Geolocation({
enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:无穷大
maximumAge: 0, //定位结果缓存0毫秒,默认:0
convert: true, //自动偏移坐标,偏移后的坐标为高德坐标,默认:true
showButton: true, //显示定位按钮,默认:true
buttonPosition: 'LB', //定位按钮停靠位置,默认:'LB',左下角
buttonOffset: new AMap.Pixel(10, 20), //定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
showMarker: true, //定位成功后在定位到的位置显示点标记,默认:true
showCircle: true, //定位成功后用圆圈表示定位精度范围,默认:true
panToLocation: true, //定位成功后将定位到的位置作为地图中心点,默认:true
zoomToAccuracy: true //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
});
map.addControl(geolocation);
geolocation.getCurrentPosition();
AMap.event.addListener(geolocation, 'complete', onComplete); //返回定位信息
AMap.event.addListener(geolocation, 'error', onError); //返回定位出错信息
});
function onComplete(data) {
var lng_my = data.position.lng;
var lat_my = data.position.lat;
var address_my = data.fORMattedAddress;
var address_province = data.addressComponent.province;
var address_city = data.addressComponent.city;
var address_district = data.addressComponent.district;
var address_township = data.addressComponent.township;
address_my = address_my.replace(address_province, '').replace(address_city, '').replace(address_district, '').replace(address_township, '');
var lnglat = GCj02towgs84(lng_my, lat_my);
var lnglat = gcj02towgs84(lng_my, lat_my);
$('#lng').val(lnglat[0]);
$('#lat').val(lnglat[1]);
$('#addrDetail').val(address_my);
}
function onError(data) {
mui.alert('请打开GPS!', ' ', '确定', function() {
removeDrop();
}, 'div');
$('.mui-popup').addClass('new-popup');
}
var geocoder = null;
var clickHandler = function(e) {
if(!geocoder) {
geocoder = new AMap.Geocoder({
city: "济南", //城市设为北京,默认:“全国”
radius: 1000 //范围,默认:500
});
}
var lnglat = [];
lnglat.push(e.lnglat.getLng())
lnglat.push(e.lnglat.getLat())
geocoder.getAddress(lnglat, function(status, result) {
if(status === 'complete' && result.regeocode) {
var address = result.regeocode.formattedAddress;
var address_province = result.regeocode.addressComponent.province;
var address_city = result.regeocode.addressComponent.city;
var address_district = result.regeocode.addressComponent.district;
var address_township = result.regeocode.addressComponent.township;
address = address.replace(address_province, '').replace(address_city, '').replace(address_district, '').replace(address_township, '');
var btnArray = ['取消', '确认'];
mui.confirm('选中“' + address + '”?', ' ', btnArray, function(ee) {
$('.mui-popup-backdrop').hide()
if(ee.index == 1) {
var lnglat84 = gcj02towgs84(lnglat[0], lnglat[1]);
$('#lng').val(lnglat84[0]);
$('#lat').val(lnglat84[1]);
//回填位置信息
$('#addrDetail').val(address);
$('#mapContainer').addClass('mapContainer').removeClass('mapContainer-fullScreen');
returnPageOne();
addModel.step = 1;
hideErrorSymbol('addrDetail', '../img/icon/icon-located.png');
//显示第三页的单元信息
showUnitAmountInfo();
} else {
}
}, 'div');
$('.mui-popup').addClass('new-popup');
} else {
// alert(JSON.stringify(result))
}
});
};
// 绑定地图单击事件
map.on('click', clickHandler);
map.on('resize', function() {
map.setZoom(14);
});
}
以前也进行过H5需要位置信息的功能开发,不过以往的方案都是使用 Android 原生定位(集成高德/百度SDK),再将位置信息传给H5来实现,不过这次由于考虑到apk大小的问题(不再集成高德SDK)以及“懒”(不用再写定位的代码),所以就准备都让H5来做。本来认为这个方案应该是很简单的,没想到遇到了一个大坑——H5无法获取到位置信息。
1. 首先,想要获取位置信息,一定要来点定位权限!见代码
2. 在刚进入页面时,一般为onCreate()方法中,动态申请权限(我就不信你的app没有适配Android 6.0+)。在获取到权限后,再调用webview的loadUrl()比较稳妥~
3. webview相关代码
WEBSettings webSettings = mWebView.getSettings();
// 允许调用 js,因为网页地图使用的是 JS 定位
webSettings.setjavascriptEnabled(true);
//启用数据库
webSettings.setDatabaseEnabled(true);
//启用地理定位,默认为true
webSettings.setGeolocationEnabled(true);
//设置定位的数据库路径
String dir = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
webSettings.setGeolocationDatabasePath(dir);
//开启DomStorage缓存
webSettings.setDomStorageEnabled(true);
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onGeolocationPermissionsshowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
super.onGeolocationPermissionsShowPrompt(origin, callback);
}
});
以上代码,自我感觉setJavaScriptEnabled()、setGeolocationEnabled()、setWebChromeClient()十分重要,其余的应该是可写可不写吧,不过没测试过。
4. 初步总结
第1步和第2步,主要是用于引导用户开启设备定位权限;第3步则是引导用户开启浏览器定位权限。
可但是!经过我代码的断点,设备定位权限获取到了,为什么没有走WebChromeClient中的onGeolocationPermissionsShowPrompt()方法?!!why??
5. 查阅资料
于是,我各种百度Google,各种推荐将targetSdkVersion降到23,终于,我在官方讲解中发现:
重点在这里:
Note that for applications targeting Android N and later SDKs (api level > Build.VERSION_CODES.M) this method is only called for requests originating from secure origins such as https. On non-secure origins geolocation requests are automatically denied.
翻译如下:
注意,对于针对Android N和以后的SDKs (API级别> Build.VERSION_CODES.M)的应用程序,此方法仅对来自安全源(如Https)的请求调用。在非安全源上,将自动拒绝地理位置请求。
好吧,我的H5的url是“http”开头,被自动屏蔽了。
6. 总结
WebView定位的解决方案:
方案一:webview的定位,乖乖的使用原生的定位方法,之后将位置信息传递到H5~
方案二:使用高德地图的辅助H5页面定位,已经测试过,可行!
方案三:降低targetSdkVersion版本到23,要求较低的懒人法
方案四:升级http到https
--结束END--
本文标题: Android6.0(Api23)以后 WebView定位失效问题
本文链接: https://lsjlt.com/news/29352.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0