Android Studio中WebView无法请求用户地理位置权限求助
解决WebView位置权限弹窗不显示的问题
第一步:清理并修正AndroidManifest.xml
你之前的Manifest里加了几个废弃或不必要的权限,先删掉冗余内容,保留核心权限即可:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.hav"> <uses-permission android:name="android.permission.INTERNET"/> <!-- 只保留这两个必要的位置权限,其他权限要么已废弃要么暂时不需要 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 如果你的APP需要后台定位才打开下面这行,否则直接删掉 --> <!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> --> <application android:allowBackup="true" android:usesCleartextTraffic="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Hav"> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 删掉那个你不知道填什么的service,完全不需要它 --> </application> </manifest>
第二步:修改MainActivity.kt,添加权限请求逻辑
WebView不会自动弹出位置权限请求,必须手动处理权限申请,同时通过WebChromeClient承接网页的位置请求,直接在MainActivity里加代码就行,不用额外创建类:
package com.example.hav import android.Manifest import android.content.pm.PackageManager import android.os.Bundle import android.webkit.GeolocationPermissions import android.webkit.WebChromeClient import android.webkit.WebView import android.webkit.WebViewClient import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat class MainActivity : AppCompatActivity() { private val LOCATION_PERMISSION_REQUEST_CODE = 1001 private lateinit var myWeb: WebView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) myWeb = findViewById<WebView>(R.id.myWebView) myWeb.webViewClient = WebViewClient() // 核心:自定义WebChromeClient处理网页的位置权限请求 myWeb.webChromeClient = object : WebChromeClient() { override fun onGeolocationPermissionsShowPrompt( origin: String?, callback: GeolocationPermissions.Callback? ) { // 先检查有没有位置权限 if (ContextCompat.checkSelfPermission( this@MainActivity, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( this@MainActivity, Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { // 没有权限,弹出系统权限请求弹窗 ActivityCompat.requestPermissions( this@MainActivity, arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION ), LOCATION_PERMISSION_REQUEST_CODE ) } else { // 已有权限,直接允许网页获取位置 callback?.invoke(origin, true, false) } } } myWeb.apply{ loadUrl("linktomywebsite.com") settings.javaScriptEnabled = true settings.setGeolocationEnabled(true) } } // 处理用户权限请求的结果 override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { // 如果用户同意了权限,通知WebView允许网页获取位置 if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { myWeb.webChromeClient.onGeolocationPermissionsShowPrompt( myWeb.url, object : GeolocationPermissions.Callback { override fun invoke(origin: String?, allow: Boolean, retain: Boolean) { origin?.let { callback?.invoke(it, true, false) } } } ) } } } }
关键说明
- WebView的位置请求必须通过
WebChromeClient的回调触发,默认的客户端不会处理这个逻辑,所以必须自定义。 - 不需要额外创建任何位置服务类,所有逻辑都在MainActivity里就能完成,不用纠结目录结构。
- 当网页请求位置时,APP会先弹出系统权限弹窗,用户同意后网页就能正常获取位置了。
内容的提问来源于stack exchange,提问作者misha sachenko
相关产品推荐
相关产品推荐

