You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView无法获取地理位置问题求助

Fixing WebView Geolocation Issues on Android Marshmallow/Nougat

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 10:47:36