WebView 里相机 / 麦克风 / 定位权限的正确处理姿势
权限请求的完整链路
网页 JS 调 getUserMedia() / navigator.geolocation
↓
WebView 拦截
↓
调用 WebChromeClient.onPermissionRequest()
↓
App 自己弹授权框 + 调用 ActivityCompat.requestPermissions()
↓
用户确认 → PermissionRequest.grant(permissions)
↓
网页 JS 收到成功回调
代码模板
声明 Manifest 权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
WebChromeClient 实现
webView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(PermissionRequest request) {
// 1. 拿到网页请求的权限列表
String[] resources = request.getResources();
// 2. 检查 Android 运行时权限(API 23+)
if (needsRuntimePermission(resources)) {
// 3. 请求 Android 运行时权限
ActivityCompat.requestPermissions(
MainActivity.this,
toManifestPermissions(resources),
1001
);
// 4. 保存 request,等 onRequestPermissionsResult 里处理
pendingPermissionRequest = request;
} else {
// 5. 直接允许
request.grant(resources);
}
}
});
onRequestPermissionsResult 回调
@Override
public void onRequestPermissionsResult(int rc, String[] perms, int[] results) {
if (rc == 1001 && pendingPermissionRequest != null) {
if (allGranted(results)) {
pendingPermissionRequest.grant(pendingPermissionRequest.getResources());
} else {
pendingPermissionRequest.deny();
}
pendingPermissionRequest = null;
}
}
容易踩的坑
漏了 WebChromeClient —— 只实现了 WebViewClient,权限请求会被默认拒绝,网页 JS 拿不到任何反馈。
只做 Android 运行时权限、不处理 PermissionRequest —— Android 弹窗用户点了"允许",但 onPermissionRequest 没调 request.grant(),网页 JS 还是收不到。
永久拒绝 —— 用户选了"以后不再问"后,ActivityCompat.requestPermissions 不再弹窗,必须引导用户去系统设置里手动打开。
其他需要 WebChromeClient 的场景
| 场景 | 回调方法 |
|---|---|
| 相机 / 麦克风 / 定位 | onPermissionRequest |
<input type=file> 文件上传 | onShowFileChooser |
alert() / confirm() JS 对话框 | onJsAlert / onJsConfirm |
| 视频全屏播放 | onShowCustomView / onHideCustomView |
| 弹窗打开新窗口 | onCreateWindow |
→ 下一页:常见坑与性能优化