文章轉自:https://www.jianshu.com/p/d32d3641741f
最近遇到了一個問題,有一個需求是使用 WebView 來加載一個網頁url,H5通過js來獲取位置定位信息。以前也進行過H5需要位置信息的功能開發,不過以往的方案都是使用 Android 原生定位(集成高德/百度SDK),再將位置信息傳給H5來實現,不過這次由於考慮到apk大小的問題(不再集成高德SDK)以及“懶”(不用再寫定位的代碼),所以就准備都讓H5來做。本來認為這個方案應該是很簡單的,沒想到遇到了一個大bug——H5無法獲取到位置信息。此時本想第一時間甩鍋給H5(我的代碼怎么可能會有問題?!!),然而iOS的好使,手機原生瀏覽器打開url也好使,頓時一臉懵逼,瞬間打臉。。。好吧,准備填坑吧~
1. 首先,想要獲取位置信息,一定要來點定位權限!見代碼
<!-- 網絡權限,加載網絡網頁需要聯網 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 粗略定位權限,允許一個程序通過網絡獲取粗略的位置 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 精確定位權限,允許一個程序訪問精確位置(GPS定位) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
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](https://developer.android.com/reference/android/os/Build.VERSION_CODES.html#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
作者:Typist夫少
鏈接:https://www.jianshu.com/p/d32d3641741f
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。