Android WebView无法获取地理位置问题求助
Hey there, let's troubleshoot why your WebView-based app isn't pulling geolocation data on Marshmallow (6.0) and Nougat (7.0) devices. The core problem here is Android's runtime permission system introduced in API 23—your current code only declares permissions in the manifest, but doesn't request them at runtime, which is mandatory for devices running API 23+. Let's break down the fixes step by step:
1. Add Runtime Permission Handling
Starting with Android 6.0, dangerous permissions (like ACCESS_FINE_LOCATION) need explicit user approval while the app is running. Here's how to update your MainActivity to handle this:
First, define a permission request code:
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
Then, in your onCreate method, check if you already have the permission, and request it if not:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Fix the typo here: acitivity_main → activity_main setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.webView1); // Check for location permission first if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request permission from the user ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } else { // Permission already granted, initialize WebView initWebView(); } }
Add the permission result handler to respond to the user's choice:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission granted, initialize WebView now initWebView(); } else { // Permission denied—show a message to inform the user Toast.makeText(this, "Location permission is required for geolocation features", Toast.LENGTH_SHORT).show(); } } }
Move your WebView setup code into a reusable method:
private void initWebView() { // Browser niceties -- pinch/zoom, follow links in-place mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); mWebView.getSettings().setBuiltInZoomControls(true); mWebView.setWebViewClient(new GeoWebViewClient()); // Required for geolocation mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setGeolocationEnabled(true); // Optional: Enable database storage to remember location permission preferences mWebView.getSettings().setDatabaseEnabled(true); mWebView.setWebChromeClient(new GeoWebChromeClient()); // Load your target URL mWebView.loadUrl("http://www.google.com"); }
2. Fix the Layout Typo
In your original onCreate code, you have setContentView(R.layout.acitivity_main)—that's a typo (acitivity should be activity). While you mentioned other functions work, fixing this ensures your WebView is properly inflated from the layout file.
3. Verify Device Settings
Make sure your test devices have:
- Location Services enabled (go to Settings → Location, toggle it on)
- Set to High Accuracy mode (combines GPS, Wi-Fi, and mobile networks for reliable location data)
4. Full Updated MainActivity.java
Here's the complete, fixed version of your activity code:
package com.example.webview; import android.app.Activity; import android.content.pm.PackageManager; import android.os.Bundle; import android.Manifest; import android.webkit.GeolocationPermissions; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; /** * A minimal WebView app with HTML5 geolocation capability * * @author David M. Chandler */ public class MainActivity extends Activity { private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001; WebView mWebView; /** * WebViewClient subclass loads all hyperlinks in the existing WebView */ public class GeoWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { // When user clicks a hyperlink, load in the existing WebView view.loadUrl(url); return true; } } /** * WebChromeClient subclass handles UI-related calls * Note: think chrome as in decoration, not the Chrome browser */ public class GeoWebChromeClient extends WebChromeClient { @Override public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { // Always grant permission since the app itself requires location // permission and the user has therefore already granted it callback.invoke(origin, true, false); } } /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.webView1); // Check for location permission if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE); } else { initWebView(); } } private void initWebView() { // Brower niceties -- pinch / zoom, follow links in place mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); mWebView.getSettings().setBuiltInZoomControls(true); mWebView.setWebViewClient(new GeoWebViewClient()); // Below required for geolocation mWebView.getSettings().setJavaScriptEnabled(true); mWebView.getSettings().setGeolocationEnabled(true); mWebView.getSettings().setDatabaseEnabled(true); mWebView.setWebChromeClient(new GeoWebChromeClient()); // Load google.com mWebView.loadUrl("http://www.google.com"); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { initWebView(); } else { Toast.makeText(this, "Location permission is required to use geolocation", Toast.LENGTH_SHORT).show(); } } } @Override public void onBackPressed() { // Pop the browser back stack or exit the activity if (mWebView.canGoBack()) { mWebView.goBack(); } else { super.onBackPressed(); } } }
After implementing these changes, your WebView should successfully access geolocation data on Marshmallow and Nougat devices.
内容的提问来源于stack exchange,提问作者asimdev

