我有一个混合网络视图:
webview.RegisterAction(data => Executefrombrowser(data));`
public void Executefrombrowser(string data) {
if (data == "loaded") {
Task.Run(() =>
StopLoading()
);
}
if (data == "success") {
Task.Run(async () =>
{
Device.BeginInvokeOnMainThread(() =>
{
Application.Current.MainPage = new SocialTab();
});
});
}
}
它适用于第一个加载的网址,但在重定向后无效。
我在第一个加载页面上有一个按钮,用于重定向页面,
我在第二页上调用C#具有相同的javascript函数,但它无法正常工作。
我的混合网络视图结构: OHWebChromeClient.cs(在.Android中)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Webkit;
using Mono;
namespace App101.Droid
{
public class OHWebChromeClient : WebChromeClient
{
private IValueCallback mUploadMessage;
private static int FILECHOOSER_RESULTCODE = 1;
public override bool OnJsAlert(Android.Webkit.WebView view, string url, string message, JsResult result)
{
return base.OnJsAlert(view, url, message, result);
}
public override void OnReceivedTitle(Android.Webkit.WebView view, string title)
{
base.OnReceivedTitle(view, title);
}
public override bool OnCreateWindow(Android.Webkit.WebView view, bool isDialog, bool isUserGesture, Message resultMsg)
{
return true;
}
private void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (requestCode == FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage)
return;
mUploadMessage.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
mUploadMessage = null;
}
}
[Android.Runtime.Register("onShowFileChooser", "(Landroid/webkit/WebView;Landroid/webkit/ValueCallback;Landroid/webkit/WebChromeClient$FileChooserParams;)Z", "GetOnShowFileChooser_Landroid_webkit_WebView_Landroid_webkit_ValueCallback_Landroid_webkit_WebChromeClient_FileChooserParams_Handler")]
public override bool OnShowFileChooser(Android.Webkit.WebView webView, IValueCallback filePathCallback, FileChooserParams fileChooserParams)
{
var appActivity = Xamarin.Forms.Forms.Context as MainActivity;
mUploadMessage = filePathCallback;
Intent chooserIntent = fileChooserParams.CreateIntent();
appActivity.StartActivity(chooserIntent, FILECHOOSER_RESULTCODE, OnActivityResult);
//return base.OnShowFileChooser (webView, filePathCallback, fileChooserParams);
return true;
}
protected void openFileChooser(IValueCallback uploadMsg, String acceptType)
{
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ActionGetContent);
i.AddCategory(Intent.CategoryOpenable);
i.SetType("image/*");
startActivityForResult(Intent.CreateChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
}
private void startActivityForResult(object p, int fILECHOOSER_RESULTCODE)
{
throw new NotImplementedException();
}
}
}
HybridWebViewRenderer.cs(在.Android中)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using App101;
using App101.Droid;
using Xamarin.Forms.Platform.Android;
using Android.Webkit;
using Java.Interop;
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace App101.Droid
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
const string JavaScriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var webView = new Android.Webkit.WebView(Forms.Context);
webView.Settings.JavaScriptEnabled = true;
webView.Settings.AllowFileAccess = true;
webView.Settings.AllowContentAccess=true;
webView.SetWebChromeClient(new OHWebChromeClient());
SetNativeControl(webView);
}
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(string.Format(e.NewElement.Uri, Element.Uri));
InjectJS(JavaScriptFunction);
}
}
void InjectJS(string script)
{
if (Control != null)
{
Control.LoadUrl(string.Format("javascript: {0}", script));
}
}
}
public class JSBridge : Java.Lang.Object
{
readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;
public JSBridge(HybridWebViewRenderer hybridRenderer)
{
hybridWebViewRenderer = new WeakReference<HybridWebViewRenderer>(hybridRenderer);
}
[JavascriptInterface]
[Export("invokeAction")]
public void InvokeAction(string data)
{
HybridWebViewRenderer hybridRenderer;
if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
{
hybridRenderer.Element.InvokeAction(data);
}
}
}
}
HybridWebViewRenderer.cs(in.İOS):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using UIKit;
using System.IO;
using Xamarin.Forms;
using App101;
using App101.iOS;
using Xamarin.Forms.Platform.iOS;
using WebKit;
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace App101.iOS
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
WKUserContentController userController;
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
userController = new WKUserContentController();
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = userController };
var webView = new WKWebView(Frame, config);
SetNativeControl(webView);
}
if (e.OldElement != null)
{
userController.RemoveAllUserScripts();
userController.RemoveScriptMessageHandler("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
string fileName = Path.Combine(NSBundle.MainBundle.BundlePath, string.Format("Content/{0}", Element.Uri));
Control.LoadRequest(new NSUrlRequest(new NSUrl(fileName, false)));
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction(message.Body.ToString());
}
}
}
HybridWebView.cs(在PCL中):
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App101
{
public class HybridWebView : View
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
}
}
重定向后如何处理HybridWebView回调函数?
答案 0 :(得分:0)
在ios上,这很有效:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Uri")
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
}
对于Android,以下作品:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Uri")
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
SetNativeControl(webView);
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl(Element.Uri);
InjectJS(JavaScriptFunction);
}
}