You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI中如何监听浏览器关闭?实现等待关闭后执行后续操作

MAUI中等待浏览器关闭后执行后续逻辑的解决方案

MAUI自带的Browser.Default.OpenAsync仅在浏览器启动完成后就继续执行代码,不会等待用户关闭页面。要实现等待用户完成操作(比如Stripe支付)并关闭浏览器后再执行后续逻辑,可采用以下两种方案:

方案一:使用嵌入式WebView控制页面生命周期

通过在应用内嵌入WebView,直接监听页面导航事件,在支付完成的回调URL触发时结束等待。

实现步骤

  1. 在XAML页面中添加WebView控件:
<WebView x:Name="PaymentWebView" IsVisible="False" />
  1. 后台代码中处理导航逻辑并等待完成:
private async Task<string> HandleNoFunds()
{
    if (!HasAcceptedStripeTerms)
    {
        // 处理Stripe条款展示逻辑
    }

    var completionSource = new TaskCompletionSource<string>();

    // 监听WebView导航事件,判断支付状态
    PaymentWebView.Navigated += (sender, args) =>
    {
        // 假设Stripe支付成功后会跳转到包含"payment_success"的URL
        if (args.Url.Contains("payment_success"))
        {
            PaymentWebView.IsVisible = false;
            completionSource.SetResult("success");
        }
        // 处理取消支付的情况
        else if (args.Url.Contains("payment_cancel"))
        {
            PaymentWebView.IsVisible = false;
            completionSource.SetResult("cancel");
        }
    };

    // 显示WebView并导航到支付页面
    PaymentWebView.IsVisible = true;
    PaymentWebView.Source = myStripeCustomPageUrl;

    // 等待支付流程结束
    var result = await completionSource.Task;
    return result;
}

优缺点:跨平台逻辑统一,容易自定义交互;但缺少系统浏览器的原生特性(如自动填充、安全验证),用户体验略有折扣。

方案二:平台特定的浏览器关闭监听

利用MAUI的依赖注入能力,为各平台实现系统浏览器的关闭回调,保留系统浏览器的原生体验。

实现步骤

  1. 定义跨平台接口:
public interface ICustomBrowser
{
    Task<string> OpenAsync(string url);
}
  1. Android平台实现(使用CustomTabs):
[assembly: Dependency(typeof(CustomBrowserAndroid))]
namespace YourAppNamespace.Droid
{
    public class CustomBrowserAndroid : ICustomBrowser
    {
        public async Task<string> OpenAsync(string url)
        {
            var completionSource = new TaskCompletionSource<string>();
            var customTabsIntent = new AndroidX.Browser.CustomTabs.CustomTabsIntent.Builder().Build();

            var serviceConnection = new CustomTabServiceConnection(completionSource);
            Application.Context.BindService(
                new Intent(Application.Context, typeof(CustomTabService)),
                serviceConnection,
                Bind.AutoCreate);

            customTabsIntent.LaunchUrl(Application.Context, Android.Net.Uri.Parse(url));

            return await completionSource.Task;
        }

        private class CustomTabServiceConnection : IServiceConnection
        {
            private readonly TaskCompletionSource<string> _completionSource;

            public CustomTabServiceConnection(TaskCompletionSource<string> completionSource)
            {
                _completionSource = completionSource;
            }

            public void OnServiceConnected(ComponentName name, IBinder service)
            {
                var customTabService = AndroidX.Browser.CustomTabs.ICustomTabsService.Stub.AsInterface(service);
                var callback = new CustomTabCallback(_completionSource);
                customTabService.Warmup(0);
                customTabService.NewSession(callback);
            }

            public void OnServiceDisconnected(ComponentName name)
            {
                _completionSource.TrySetResult("closed");
            }

            private class CustomTabCallback : AndroidX.Browser.CustomTabs.CustomTabsCallback
            {
                private readonly TaskCompletionSource<string> _completionSource;

                public CustomTabCallback(TaskCompletionSource<string> completionSource)
                {
                    _completionSource = completionSource;
                }

                public override void OnNavigationEvent(int navigationEvent, Bundle extras)
                {
                    if (navigationEvent == CustomTabsCallback.NavigationEventTabClosed)
                    {
                        _completionSource.TrySetResult("closed");
                    }
                }
            }
        }
    }
}
  1. iOS平台实现(使用SFSafariViewController):
[assembly: Dependency(typeof(CustomBrowseriOS))]
namespace YourAppNamespace.iOS
{
    public class CustomBrowseriOS : ICustomBrowser
    {
        public async Task<string> OpenAsync(string url)
        {
            var completionSource = new TaskCompletionSource<string>();
            var safariVC = new SafariServices.SFSafariViewController(new NSUrl(url));

            safariVC.DidFinish += (sender, args) =>
            {
                completionSource.SetResult("closed");
                safariVC.DismissViewController(true, null);
            };

            var keyWindow = UIApplication.SharedApplication.ConnectedScenes
                .OfType<UIWindowScene>()
                .FirstOrDefault()?
                .Windows
                .FirstOrDefault(w => w.IsKeyWindow);

            keyWindow?.RootViewController.PresentViewController(safariVC, true, null);

            return await completionSource.Task;
        }
    }
}
  1. MAUI项目中调用自定义浏览器:
private async Task<string> HandleNoFunds()
{
    if (!HasAcceptedStripeTerms)
    {
        // 处理Stripe条款展示逻辑
    }

    var customBrowser = DependencyService.Get<ICustomBrowser>();
    await customBrowser.OpenAsync(myStripeCustomPageUrl);

    // 浏览器关闭后才会执行后续代码
    return "success";
}

优缺点:保留系统浏览器的全部原生特性,用户体验好;但需要编写各平台的专属代码,维护成本相对较高。


内容的提问来源于stack exchange,提问作者Mihai Vasile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 00:50:54