PCL项目中点击YouTube视频时如何获取WebView的最新URL
解决PCL项目中WebView获取YouTube点击后最新URL的问题
我之前处理Xamarin PCL项目的WebView时,也碰到过和你一模一样的问题——点击YouTube视频后,用WebView_Navigating和WebView_Navigated事件拿到的总是上一个URL,自定义渲染器里的旧ShouldOverrideUrlLoading还死活不触发。折腾了好一阵才搞明白原因,给你分享下解决办法:
为什么原有方法行不通?
- Navigating/Navigated事件的局限性:YouTube的视频跳转很多时候是通过页面内JavaScript实现的(比如iframe跳转、修改history),这类操作不会触发WebView的
Navigating或Navigated事件,或者触发时传递的URL还是原页面的地址,不是视频的实际播放URL。 - ShouldOverrideUrlLoading过时:旧版的
ShouldOverrideUrlLoading(WebView view, string url)确实已经被废弃,Android平台现在用带IWebResourceRequest参数的重载,iOS则需要通过WKNavigationDelegate来监听URL变化。
跨平台解决方案(分平台自定义渲染器)
1. Android平台自定义渲染器
重写WebViewClient的新重载ShouldOverrideUrlLoading,从IWebResourceRequest中获取最新URL,再通过MessagingCenter传递给PCL项目:
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))] namespace YourAppName.Droid { public class CustomWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control != null) { // 设置自定义WebViewClient Control.SetWebViewClient(new CustomWebViewClient()); } } private class CustomWebViewClient : Android.Webkit.WebViewClient { // 使用未过时的重载方法 public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request) { var latestUrl = request.Url.ToString(); // 通过MessagingCenter把URL发送到PCL层 MessagingCenter.Send<object, string>(this, "WebViewUrlUpdated", latestUrl); // 返回false让WebView继续加载该URL;如果要自己处理跳转(比如打开外部浏览器),返回true return base.ShouldOverrideUrlLoading(view, request); } } } }
2. iOS平台自定义渲染器
通过WKNavigationDelegate的DidStartProvisionalNavigation方法捕获URL变化,同样用MessagingCenter传递:
[assembly: ExportRenderer(typeof(WebView), typeof(CustomWebViewRenderer))] namespace YourAppName.iOS { public class CustomWebViewRenderer : WebViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) { base.OnElementChanged(e); if (Control != null) { // 设置自定义NavigationDelegate Control.NavigationDelegate = new CustomNavigationDelegate(); } } private class CustomNavigationDelegate : WKNavigationDelegate { public override void DidStartProvisionalNavigation(WKWebView webView, WKNavigation navigation) { var latestUrl = webView.Url.ToString(); // 发送URL到PCL层 MessagingCenter.Send<object, string>(this, "WebViewUrlUpdated", latestUrl); base.DidStartProvisionalNavigation(webView, navigation); } } } }
3. PCL项目中接收并保存URL
在你的页面中订阅MessagingCenter,拿到最新URL后保存:
public class YourWebViewPage : ContentPage { private string _savedUrl; public YourWebViewPage() { InitializeComponent(); // 订阅URL更新消息 MessagingCenter.Subscribe<object, string>(this, "WebViewUrlUpdated", (sender, url) => { _savedUrl = url; // 这里可以添加保存逻辑,比如写入本地存储 Console.WriteLine($"已获取最新URL:{_savedUrl}"); }); } // 页面销毁时取消订阅,避免内存泄漏 protected override void OnDisappearing() { base.OnDisappearing(); MessagingCenter.Unsubscribe<object, string>(this, "WebViewUrlUpdated"); } }
额外注意事项
- 确保Android项目的
AndroidManifest.xml中添加了网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 如果YouTube页面使用混合内容(http+https),Android端需要在WebView设置中允许:
Control.Settings.MixedContentMode = Android.Webkit.MixedContentHandling.AlwaysAllow; - 若使用Xamarin.Forms 5.0+,也可以尝试监听
WebView.SourceChanged事件,但对于JS驱动的URL变化,自定义渲染器的方式依然更可靠。
内容的提问来源于stack exchange,提问作者Alik
相关产品推荐
相关产品推荐

