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亦楓

微信掃描二維碼,歡迎關注個人我的公衆號:安卓筆記俠

不只分享個人原創技術文章,還有程序員的職場遐想

相關文章
相關標籤/搜索