Android WebView 中的 Html 网页定位操做

利用 HTML5 提供的定位 API 能够帮助网页获取用户设备的当前位置信息。但若是是在 Android 系统下的应用中打开网页,咱们使用 Hybrid 开发模式时用到的 WebView 包括应用自己都须要作必定的设置才能支持内嵌网页的定位功能。javascript

这里是一个简单的网页源码,其中有一段 JavaScript 代码,用于向宿主浏览器请求定位:html

<!DOCTYPE html>
<head>
</head>
<body>
    <button onclick="fetchLocation()">获取位置</button>
    <script> var tipsEle = document.getElementById('tips') function fetchLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoError) } else { alert('当前设备不支持定位!') } } function onGeoSuccess(event){ alert("Success: " + event.coords.latitude + ", " + event.coords.longitude) } function onGeoError(event){ alert("Error code " + event.code + ". " + event.message) } </script>
</body>复制代码

简单说明:(有关 HTML5 定位 API 的详细使用,能够参考连接:菜鸟教程 - HTML5 Geolocationhtml5

  • navigator.geolocation 属性判断当前硬件浏览器环境是否支持定位;java

  • getCurrentPosition() 函数,在支持定位的前提下,发起请求定位,并传递定位成功和失败两个函数做为回调参数。android

而后在咱们的 WebView 中添加以下设置:(这里假设上面的测试 html 文件放置在 assets 目录下)git

WebView contentWv = (WebView) findViewById(R.id.wv_content);
WebSettings settings = contentWv.getSettings();
settings.setJavaScriptEnabled(true);
contentWv.setWebChromeClient(new WebChromeClient(){
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, true);
        super.onGeolocationPermissionsShowPrompt(origin, callback);
    }
});
contentWv.loadUrl("file:///android_asset/location.html");复制代码

代码很简单,最重要的一个地方就是,重写 WebChromeClient 的这个方法:程序员

onGeolocationPermissionsShowPrompt()web

当网页发起定位请求时,会调用到宿主 WebView 的这个方法,由开发者自行处理这个请求。能够看到,示例中包含这么一行代码:浏览器

callback.invoke(origin, true, true);复制代码

这行代码就是用来处理定位请求,通常会向用户给出一个请求定位权限的弹窗。第二个 boolean 类型的参数表示是否授予网页定位权限;而第三个 boolean 类型的参数则表示是否保留这个权限状态。微信

值得注意的是,第三个参数的设置影响的是整个应用中的 WebView。若是咱们在某个页面的 WebView 中处理过一次网页的定位请求,并设置第三个参数为 true,即保留状态的状况下,当下次在其余页面或者仍是这个页面打开网页时将再也不向用户发起定位权限的请求,而是直接执行定位操做。

通常比较合适的作法是,在该回调函数中设置一个对话框,告知用户是否受权定位操做。作得更好一点的话,还能够帮助用户检测设备的系统定位是否打开。没有打开的状况下,提示用户并跳转至设置界面。

检测系统定位是否打开的示例代码:

private boolean isSystemLocationEnable() {
    LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    boolean gpsLocationEnable = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    boolean networkLocationEnable = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    return gpsLocationEnable && networkLocationEnable;
}复制代码

跳转至系统设置中的定位界面:

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);复制代码

还有最后一步,别忘了在 Manifest 清单文件中添加定位相关的权限,固然也包括网络权限:(经过 GPS 精准定位和 WI-FI 的粗略定位)

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>复制代码

这段示例网页代码调用时的效果如图:

总体看来,使用方式还挺简单的,那是否是这种方式就必定万无一失呢?

前面提过,使用 HTML5 定位 API 获取用户位置的前提是浏览器或者说咱们 Android 系统中的原生 WebView 环境支持定位操做。事实上,经测试,这种方式不彻底稳定。尤为是在国内各类厂商各类 ROM 的复杂环境下,仍是有至关多品牌的手机是不支持这种定位操做的。甚至,你还会碰见,即便是使用同一台手机,安装不一样的浏览器 App 对于定位的支持也不尽相同。

因此,HTML5 自身的定位操做只能做为一种辅助手段。更稳妥的作法是,开发人员经过百度、高德之类的第三方定位 SDK 在原生代码中获取用户位置信息,当打开 WebView 中的网页时经过拼接 URL 参数的形式传递给网页。网页自行判断,若是 URL 中不包含定位信息的话,再经过自身的 API 发起定位请求。

或者经过HTML 网页的 JS代码 与 Java 原生代码交互的方式间接操做。关于 JS 与 Java 交互的相关知识,能够参考个人这篇文章:

Android WebView —— Java 与 JavaScript 交互总结

关于我:亦枫,博客地址:yifeng.studio/,新浪微博:IT亦枫

微信扫描二维码,欢迎关注个人我的公众号:安卓笔记侠

不只分享个人原创技术文章,还有程序员的职场遐想

相关文章
相关标签/搜索