如何在Xamarin Android上使用C#在文档开始时注入Javascript

如何在Xamarin Android上使用C#在文档开始时注入Javascript,c#,android,xamarin,xamarin.android,C#,Android,Xamarin,Xamarin.android,我正在尝试在VisualStudio中将一个应用程序从Swift(仅限iOS)移植到C#,而且进展(稍微)顺利。不过,我在安卓系统上遇到了一些问题(其中很多问题——但这个问题只有一个!) 页面在Android版本的应用程序的webview中正确加载,但Javascript直到页面呈现后才执行,结果是在应用程序商店广告消失之前短暂显示 我的iOS应用程序工作正常-iOS版本的源代码如下: public class PortalViewRenderer : ViewRenderer<Porta

我正在尝试在VisualStudio中将一个应用程序从Swift(仅限iOS)移植到C#,而且进展(稍微)顺利。不过,我在安卓系统上遇到了一些问题(其中很多问题——但这个问题只有一个!)

页面在Android版本的应用程序的webview中正确加载,但Javascript直到页面呈现后才执行,结果是在应用程序商店广告消失之前短暂显示

我的iOS应用程序工作正常-iOS版本的源代码如下:

public class PortalViewRenderer : ViewRenderer<PortalView, WKWebView>, IWKScriptMessageHandler, IWKNavigationDelegate {

    private class NavigationDelegate : WKNavigationDelegate {
        private readonly WeakReference<PortalViewRenderer> _webView;

        public NavigationDelegate(PortalViewRenderer webView) {
            _webView = new WeakReference<PortalViewRenderer>(webView);
        }

        public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation) {
        }

        public override void DidStartProvisionalNavigation(WKWebView webView, WKNavigation navigation) {
            NSUrl currentURL = webView.Url;
            var current = Connectivity.NetworkAccess;

            if (current != NetworkAccess.Internet) {
                if (!(currentURL.AbsoluteString.Contains("file://"))) {
                    string noConnectionPath = Path.Combine(NSBundle.MainBundle.BundlePath, "Common/NoInternet.html");
                    webView.LoadRequest(new NSUrlRequest(NSUrl.FromString(noConnectionPath)));
                }
            }
        }

        public override void DidFailNavigation(WKWebView webView, WKNavigation navigation, NSError error) {

        }

        public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler) {
            NSUrl url = navigationAction.Request.Url;
            if (url != null) {
                if (url.Host == "<website url>" || url.AbsoluteString.Contains("file://")) {
                    decisionHandler(WKNavigationActionPolicy.Allow);
                } else if (url.AbsoluteString.Contains("<website url>/mydavylamp/timeout")) {
                    decisionHandler(WKNavigationActionPolicy.Cancel);
                    webView.LoadRequest(new NSUrlRequest(NSUrl.FromString(Element.Uri)));
                } else {
                    UIApplication.SharedApplication.OpenUrl(url);
                }
            } 
        }
    }

    WKUserContentController userController;

    protected override void OnElementChanged (ElementChangedEventArgs<PortalView> e) {
        base.OnElementChanged (e);

        var javaScriptFunction = System.IO.File.ReadAllText("Common/HideAppStoreAds.js");

        if (Control == null) {
            userController = new WKUserContentController();
            var script = new WKUserScript(new NSString(javaScriptFunction), WKUserScriptInjectionTime.AtDocumentStart, false);
            userController.AddUserScript(script);
            userController.AddScriptMessageHandler(this, "invokeAction");

            var config = new WKWebViewConfiguration { UserContentController = userController };
            var webView = new WKWebView(Frame, config);
            webView.BackgroundColor = UIKit.UIColor.FromRGB(0x11, 0x25, 0x43);
            webView.ScrollView.BackgroundColor = webView.BackgroundColor;
            webView.CustomUserAgent = "headbanger.davylamp.ios";
            webView.ScrollView.ScrollEnabled = true;
            webView.ScrollView.Bounces = false;
            webView.AllowsBackForwardNavigationGestures = false;
            webView.ContentMode = UIKit.UIViewContentMode.ScaleToFill;
            webView.NavigationDelegate = new NavigationDelegate(this);

            SetNativeControl(webView);
        }
        if (e.OldElement != null) {
            userController.RemoveAllUserScripts();
            userController.RemoveScriptMessageHandler("invokeAction");
            var portalView = e.OldElement as PortalView;
            portalView.Cleanup();
        }
        if (e.NewElement != null) {
            Control.LoadRequest(new NSUrlRequest(NSUrl.FromString(Element.Uri)));
        }
    }

    public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message) {
        Element.InvokeAction (message.Body.ToString ());
    }
}
我在谷歌上搜索了这个魔咒,但我似乎找不到任何关于如何用C#为Android构建网络视图的指南,尤其是对于iOS开发者


和往常一样,任何人能够提供的任何帮助都会得到感激。

对于我的用例,答案似乎如下

onPageCommitVisible的Android文档()说明:

此回调可用于确定使回收的WebView可见的安全点,以确保不显示过时的内容。它在最早的时候被调用,可以保证WebView#onDraw不再从以前的导航中提取任何内容。下一个绘图将显示WebView的WebView#setBackgroundColor或新加载页面的部分内容

在我看来,这意味着HTML已经加载(虽然不一定是任何其他资源),页面可能会开始呈现(但至关重要的是,在回调完成之前不会呈现)

我使用了以下代码:

    public override void OnPageCommitVisible(WebView view, string url) {
        view.EvaluateJavascript(_javascript, null);
        base.OnPageCommitVisible(view, url);
    }

而且它似乎工作正常。我希望这能帮助其他人。

对于我的用例,答案似乎如下

onPageCommitVisible的Android文档()说明:

此回调可用于确定使回收的WebView可见的安全点,以确保不显示过时的内容。它在最早的时候被调用,可以保证WebView#onDraw不再从以前的导航中提取任何内容。下一个绘图将显示WebView的WebView#setBackgroundColor或新加载页面的部分内容

在我看来,这意味着HTML已经加载(虽然不一定是任何其他资源),页面可能会开始呈现(但至关重要的是,在回调完成之前不会呈现)

我使用了以下代码:

    public override void OnPageCommitVisible(WebView view, string url) {
        view.EvaluateJavascript(_javascript, null);
        base.OnPageCommitVisible(view, url);
    }

而且它似乎工作正常。我希望这对其他任何人都有帮助。

您只需覆盖OnPageCommitVisible方法:

public override void OnPageCommitVisible(AWebView view, string url)
    {
       //Insert javascript injection first
        view.EvaluateJavascript(_javascript, null);
        base.OnPageCommitVisible(view, url);
    }
它当然会开火。
有一个好的代码

您只需覆盖OnPageCommitVisible方法:

public override void OnPageCommitVisible(AWebView view, string url)
    {
       //Insert javascript injection first
        view.EvaluateJavascript(_javascript, null);
        base.OnPageCommitVisible(view, url);
    }
它当然会开火。
有一个好的代码

通常,js是在OnPageFinished中注入的,您可以尝试注入js
view.EvaluateJavascript(_javascript,null)OnPageStarted
OnPageFInished中的code>在所有场景中都不起作用-我尝试了,但没有起作用。我现在正在考虑是否需要保留两个Web视图,并在javascript完成后交换它们。但这似乎是浪费,我对一个浪费的解决方案不太满意OnPageStartedOnPageFInished中的code>在所有场景中都不起作用-我尝试了,但没有起作用。我现在正在考虑是否需要保留两个Web视图,并在javascript完成后交换它们。但这似乎是浪费,我对一个浪费的解决方案不太满意。这是我之前的回答,从2019年7月31日开始。这是我之前的回答,从2019年7月31日开始。