WebRTC WebView视频在模拟器正常但真机无法显示问题求助
看起来你遇到的是WebRTC在真机WebView上渲染失败的典型问题——模拟器正常但真机白屏,摄像头已经启动说明权限和媒体流获取没问题,大概率是WebView配置或者渲染逻辑的问题。我来帮你一步步排查:
1. 先修复代码里的明显错误:重复设置WebChromeClient
你代码里先后设置了两个WebChromeClient:
WebChromeClientCustomPoster chromeClient = new WebChromeClientCustomPoster(); mWebView.setWebChromeClient(chromeClient); // ... 后面又覆盖了这个设置 mWebView.setWebChromeClient(new WebChromeClient() { ... });
后面的匿名WebChromeClient会完全覆盖前面的WebChromeClientCustomPoster,如果你的自定义ChromeClient里有视频渲染相关的逻辑(比如处理自定义视图),那这部分代码根本不会执行,直接导致视频画面无法显示。
解决方法是把权限请求逻辑合并到自定义的ChromeClient中:
WebChromeClientCustomPoster chromeClient = new WebChromeClientCustomPoster() { @Override public void onPermissionRequest(final PermissionRequest request) { MainActivity.this.runOnUiThread(new Runnable(){ @TargetApi(Build.VERSION_CODES.M) @Override public void run() { // 可以先打印请求的权限资源,确认包含视频和音频权限 for (String resource : request.getResources()) { Log.d("WebRTC", "Requested permission: " + resource); } request.grant(request.getResources()); } }); } }; mWebView.setWebChromeClient(chromeClient);
2. 补充WebSettings的关键配置
API 28的WebView默认有些限制,需要手动开启必要的选项来支持WebRTC:
WebSettings settings = mWebView.getSettings(); settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); // 允许媒体自动播放,WebRTC视频不需要用户手势触发播放 settings.setMediaPlaybackRequiresUserGesture(false); // 强制启用硬件加速(真机上部分设备默认可能有问题) mWebView.setLayerType(View.LAYER_TYPE_HARDWARE, null); // 开启WebView的调试模式,方便在Chrome里远程调试页面 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); }
开启调试模式后,你可以在电脑Chrome里输入chrome://inspect,连接真机查看Web页面的控制台日志,看看是否有WebRTC相关的报错(比如媒体流无法绑定到video元素)。
3. 再次确认权限的完整性
虽然你说已经获取了权限,但还是要做双重检查:
- 确保AndroidManifest.xml里声明了所有必要权限:
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-feature android:name="android.hardware.camera" android:required="true" /> <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" /> - 在代码中验证运行时权限是否真的获取成功:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { // 这里说明权限没获取到,需要重新请求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, 100); }
4. 排查WebView版本差异
模拟器的WebView版本通常是最新的,但真机可能因为系统更新不及时,WebView版本较旧,存在WebRTC渲染的bug。你可以在真机的「设置-应用-Android System WebView」里查看版本,建议更新到最新版本后再测试。
5. 用本地测试页面排除远程页面问题
先不要加载google.com,换成一个简单的本地WebRTC测试页面,排除远程页面的兼容性问题。比如在assets目录下创建test_webrtc.html:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <video id="localVideo" autoplay playsinline width="100%" height="auto"></video> <script> // 简单获取本地摄像头并显示 navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(stream => { const video = document.getElementById('localVideo'); video.srcObject = stream; console.log("Media stream attached to video element"); }) .catch(err => { console.error("Get user media error: ", err); alert("无法获取媒体流: " + err.message); }); </script> </body> </html>
然后加载这个本地页面:
mWebView.loadUrl("file:///android_asset/test_webrtc.html");
如果这个本地页面能正常显示视频,说明问题出在远程页面的兼容性上;如果还是白屏,那就是WebView本身的配置或系统问题。
按照上面的步骤一步步排查,应该能解决真机白屏的问题。
内容的提问来源于stack exchange,提问作者Cyngan

