我正在开发一个跨平台应用程序,该应用程序具有HybridWebView并显示本地html文件。我有一个wwwroot文件夹,其中包含html文件、css文件、js文件和所有其他资源。我已将完整文件夹构建为BundleResource。我还使用EmbedIO启动了一个本地Web服务器。当我在iPad上启动该应用程序时(iOS 15〉),它不执行JavaScript文件。在iPhone(iOS 15〉)上,该应用程序工作正常。同样在iOS 12的iPad上,该应用程序工作正常。此外,无论使用什么设备,该应用程序都可以在Safari上工作。
我已经在info.plist中添加了NSAppTransportSecurity和NSAAllowsArbitraryLoads = true。另外,我开发了一个带有WebView的Swift应用程序,并尝试使用Xamarin.iOS应用程序的本地Web服务器来显示应用程序。但是JavaScript同样没有执行(我还设置了关于JavaScript的首选项)。
- 我的问题:**
我不明白为什么这个应用程序在Safari、iPhone和旧iPad上都能用,但在新iPad上却不行。我怀疑你必须启用JavaScript,但找不到相应的解决方案。
- 值得一提的是:**
我只在index.html中加载一个js文件,这个js文件依次加载其他js文件(如上所述,除了新的iPad之外,这在所有设备上都有效)。
下面我添加了混合网络视图. cs、混合网络视图渲染器. cs、主页. xaml.cs和主页. xaml。
- 主页面. xaml:**
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:extensions="clr-namespace:Viewer.Extensions;assembly=Viewer"
x:Class="Viewer.MainPage">
<StackLayout>
<extensions:HybridWebView x:Name="HybridWebView" Uri="{Binding WebViewSource}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
- 主页面. xaml. cs:**
namespace Viewer
{
[DesignTimeVisible(false)]
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
private readonly LocalWebServer _server = new LocalWebServer();
private string _webViewSource;
public string WebViewSource
{
get => _webViewSource;
set
{
_webViewSource = value;
OnPropertyChanged(nameof(WebViewSource));
}
}
public MainPage()
{
InitializeComponent();
BindingContext = this;
NavigationPage.SetHasNavigationBar(this, false);
HybridWebView.RegisterAction(data =>
{
DisplayAlert("Alert", "Hello " + data, "OK");
});
HybridWebView.RegisterQRAction(() =>
{
try
{
ZXingScannerPage scanPage = new ZXingScannerPage();
scanPage.OnScanResult += (result) =>
{
scanPage.IsScanning = false;
Device.BeginInvokeOnMainThread(async () =>
{
await Navigation.PopAsync();
var barcode = result.Text.ParseBarcode();
switch (barcode.BarcodeType)
{
case BarcodeType.Hotspot:
{
await HybridWebView.EvaluateJavaScriptAsync(
$"javascript:doLoadHS('{barcode.Datamodule}.html', '{barcode.Hotspot.figureId}', '{barcode.Hotspot.hotspotId}');");
break;
}
case BarcodeType.Datamodule:
default:
{
await HybridWebView.EvaluateJavaScriptAsync(
$"javascript:doLoad('{barcode.Datamodule}.html');");
break;
}
}
});
};
Device.BeginInvokeOnMainThread(() =>
{
Navigation.PushAsync(scanPage);
});
}
catch (Exception ex)
{
DisplayAlert("QR", $"Error while reading qr code: {ex.Message}", "OK");
}
});
HybridWebView.RegisterProjectSelectionAction(() =>
{
_server.Dispose();
Navigation.PopToRootAsync();
});
var docpath = Helper.PathAddBackslash(Path.Combine(DependencyService.Get<IApplicationConfigurationService>().DocumentationRootPath, Init.NAME_DIR_WWWROOT));
_server.StartWebServer(docpath, false, false);
WebViewSource = $"{LocalWebServer.Url}/index.html";
NavigationPage.SetHasBackButton(this, false);
}
protected override bool OnBackButtonPressed()
{
return true;
}
}
}
- 混合网络视图. cs:**
using System;
using Xamarin.Forms;
namespace Viewer.Extensions
{
public class HybridWebView : WebView
{
Action<string> action;
Action qrAction;
Action projectSelectionAction;
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 RegisterQRAction(Action callback)
{
qrAction = callback;
}
public void RegisterProjectSelectionAction(Action callback)
{
projectSelectionAction = callback;
}
public void Cleanup()
{
action = null;
qrAction = null;
projectSelectionAction = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
public void InvokeQRAction()
{
qrAction?.Invoke();
}
public void InvokeProjectSelectionAction()
{
projectSelectionAction?.Invoke();
}
}
}
- 混合网络视图呈现器. cs:**
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace Viewer.iOS.Views
{
public class HybridWebViewRenderer : WkWebViewRenderer, IWKScriptMessageHandler
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}" +
"function invokeCSharpQRAction(data){window.webkit.messageHandlers.invokeQRAction.postMessage(data);}";
WKUserContentController userController;
public HybridWebViewRenderer() : this(new WKWebViewConfiguration())
{
}
public HybridWebViewRenderer(WKWebViewConfiguration config) : base(config)
{
userController = config.UserContentController;
var script = new WKUserScript(new NSString(JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript(script);
userController.AddScriptMessageHandler(this, "invokeAction");
userController.AddScriptMessageHandler(this, "invokeQRAction");
}
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
userController.RemoveAllUserScripts();
userController.RemoveScriptMessageHandler("invokeAction");
userController.RemoveScriptMessageHandler("invokeQRAction");
HybridWebView hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
LoadRequest(new NSUrlRequest(new NSUrl(((HybridWebView)Element).Uri)));
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
var eventArgs = message.Body.ToString().ParseEventArgs();
switch (eventArgs.name)
{
case "invokeAction":
((HybridWebView)Element).InvokeAction(eventArgs.payload);
break;
case "invokeQRAction":
((HybridWebView)Element).InvokeQRAction();
break;
}
}
}
}
1条答案
按热度按时间kokeuurv1#
这里的问题可能与您的Javascript有关。
移动的设备和较旧的设备通常会抑制Javascript的控制台错误,而不是错误页面或异常,进一步的Javascript不执行,看起来好像根本没有执行。
特别是对于有许多用法和引用的复杂Javascript,如果一个引用有问题就足够了,所以你什么也看不到。
在这里,它可以帮助简化Javascript,并一点一点地重建它以定位错误。