【问题标题】:Xamarin.forms iOS WkWebView runs in backgroundXamarin.forms iOS WkWebView 在后台运行
【发布时间】:2022-01-10 19:19:15
【问题描述】:

我有带有 EmbedIO 网络服务器的应用程序和带有 WkWebViewRenderer 的 WebView 中的角度代码。在 Angular 代码中是轮询函数。

当应用程序进入后台时,DidEnterBackground 被调用并且我处理了 webserver,但 webview 仍然运行。如何在触发此事件时使用 Angular 暂停 webview 以停止轮询,并在应用再次进入前台时重新启动它?

【问题讨论】:

  • 很难说,没有看到你的代码。也许您可以在自己的自定义渲染器中完成,如Customizing a WebView - Create the custom renderer on iOS。您还需要一个WKScriptMessageHandler,这样您就可以与网页进行通信。或者让DidEnterBackground 告诉你的 wkwebview 自定义渲染器到Dispose 可能更容易。
  • 但是我会失去 Angular 应用程序的实际状态吗?
  • 如果你处理,是的,那会失去状态。只是想让你知道这是一种方法。
  • 是的,但我不想丢失它.. 或者想办法保存它
  • 尝试注释掉“((HybridWebView)Element).Cleanup();”在 dispose 方法中

标签: xamarin.forms xamarin.ios


【解决方案1】:

所以,我想出了一些解决方案,以满足我在应用程序中使用 AppShell 进行导航的兴趣。

这是我的 EmbedIO 网络服务器助手类:

public  class WebServerHelper
{
    private static readonly Lazy<WebServerHelper> lazy = new(() => new WebServerHelper());

    public static WebServerHelper Instance => lazy.Value;

    private CancellationTokenSource _cts;
    private WebServer _webServer = null;

    public void Run()
    {
        if(_webServer == null)
        Task.Factory.StartNew(async () =>
        {
            using (_cts = new CancellationTokenSource())
            using (_webServer = CreateWebServer())
            {
                await _webServer.RunAsync(_cts.Token);
            }                
        });
    }

    public void Stop()
    {
        _cts.Cancel();
        _cts = null;
        _webServer = null;
    }

    private WebServer CreateWebServer()
    {
        var server =  new WebServer(o => o
            .WithUrlPrefix($"http://localhost:8080")
            .WithMode(HttpListenerMode.EmbedIO))
        .WithCors()
        .WithLocalSessionManager()
        .WithWebApi("/api", m => m
            .WithController<TestController>()
            ...
            .WithController<SystemController>())
        .WithModule(new ActionModule("/", HttpVerbs.Any,
            ctx => ctx.SendDataAsync(new { Message = "Error" })));

        Trace.TraceInformation($"WebApi started on port: 8080");

        server.OnUnhandledException += (s, e) => { Trace.TraceInformation("Unhadled Exception occured"); return Task.CompletedTask; };
        server.OnHttpException += (s, e) => { Trace.TraceInformation("Http exception occured"); return Task.CompletedTask; };

        return server;
    }
}

按照here 所述,我创建了混合网络视图

这一切都可以在 AppDelegate 中运行,例如:

    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        Forms.Init();

        WebServerHelper.Instance.Run();

        ...

        LoadApplication(new App());

        return base.FinishedLaunching(app, options);
    }

    public override void WillTerminate(UIApplication application)
    {
        application.Dispose();
        base.WillTerminate(application);
    }

    [Export("applicationWillEnterForeground:")]
    public override void WillEnterForeground(UIApplication application)
    {
        //TODO: handle situation when user goes foreground (eg. double tap on start button and turn camera on)
        WebServerHelper.Instance.Run();

        ((WKWebView)((HybridWebView)((WebContainer)((IShellSectionController)Shell.Current?.CurrentItem?.CurrentItem)?.PresentedPage).Content).GetRenderer().NativeView).GoForward();
    }

    [Export("applicationDidEnterBackground:")]
    public override void DidEnterBackground (UIApplication application)
    {
        ((WKWebView)((HybridWebView)((WebContainer)((IShellSectionController)Shell.Current?.CurrentItem?.CurrentItem)?.PresentedPage).Content).GetRenderer().NativeView).GoBack();

        //In background task cancelation token is called dispose of webserver.
        //This step obtain aditional (aprox.) 25 seconds to finish all ongoing operations.
        application.BeginBackgroundTask(() => {
            WebServerHelper.Instance.Stop();
        });
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    相关资源
    最近更新 更多