Android WebView兼容API23前后获取位置权限问题(Kotlin)
Hey there! Let's break down why your WebView isn't prompting for location permissions and fix it for both API23+ and older Android versions step by step.
1. Handle Dynamic Permissions for API23+ (Android 6.0+)
Starting with Android 6.0, dangerous permissions like ACCESS_FINE_LOCATION require explicit runtime requests—adding them to the manifest alone isn't enough. Here's how to implement this in Kotlin:
First, define constants for permissions and request codes:
private val LOCATION_PERMISSIONS = arrayOf( android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_COARSE_LOCATION // Optional but recommended for broader device support ) private val LOCATION_PERMISSION_REQUEST_CODE = 1001
Then, check permissions and initialize the WebView only after they're granted:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_blind_spot_web_view) // Check if we already have location permissions if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED ) { // Request permissions from the user ActivityCompat.requestPermissions( this, LOCATION_PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE ) } else { // Permissions are already granted, set up the WebView initWebView() } }
Add a handler to process the permission request result:
override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permissions approved, initialize WebView now initWebView() } else { // Permissions denied, inform the user Toast.makeText(this, "Location permissions are required to access your location", Toast.LENGTH_SHORT).show() } } }
Move your WebView setup into a reusable function:
private fun initWebView() { val webView: WebView = findViewById(R.id.webView) val webSettings = webView.settings webSettings.javaScriptEnabled = true webSettings.setGeolocationEnabled(true) // Critical: Set a local path for WebView to store geolocation cache data webSettings.geolocationDatabasePath = filesDir.path val client = ModifiedWebChromeClient() webView.webChromeClient = client webView.loadUrl("https://www.example.com") }
2. Refine Your ModifiedWebChromeClient
Your current callback auto-grants site-specific location access, which works—but you can make it more user-friendly if needed. For now, keep it simple but ensure it only runs after the app has system-level permissions:
class ModifiedWebChromeClient : WebChromeClient() { override fun onGeolocationPermissionsShowPrompt( origin: String?, callback: GeolocationPermissions.Callback? ) { // Optional: Show a custom dialog to confirm if the user wants to allow this site access to location // For now, we'll auto-allow as your original code did callback?.invoke(origin, true, false) } }
3. Fix Issues for API23- (Pre-Marshmallow)
For older Android versions, dynamic permissions aren't required, but two tweaks often resolve location issues:
- Add
ACCESS_COARSE_LOCATIONto your manifest (some devices expect this alongside fine location access) - Ensure you set the
geolocationDatabasePathas we did ininitWebView—WebView needs this path to store location-related data.
Update your manifest permissions:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
4. Additional Checks
- Verify Location Services are enabled: Even with app permissions, if the device's location toggle is off, WebView can't retrieve data. You can add code to check this and prompt the user to enable it.
- Test with a geolocation-aware webpage: Replace
https://www.example.comwith a page that explicitly callsnavigator.geolocation.getCurrentPosition()to confirm the issue isn't with the webpage itself.
内容的提问来源于stack exchange,提问作者Trev14

