WebGL в WebView не работает в сборке UNO, но работает в сборке Xamarin - PullRequest
1 голос
/ 03 мая 2019

В настоящее время я занимаюсь разработкой мобильного приложения, которое использует платформу UNO.Для показа 3D-модели я использую элемент управления WebView и некоторый код JavaScript ThreeJS.Это очень хорошо работает с UWP, а также с WASM.(Обходной путь для WebView в сборке WASM также можно найти здесь в StackOverflow.) Однако сборка Android вызывает головную боль: загрузка HTML-страницы, вывод отладки показывает, что части скрипта WebGLвыполняется, но пользовательский интерфейс ничего не показывает.

Я уже убедился, что (на мой взгляд) используется правильный элемент управления WebView.Кроме того, я протестировал альтернативный WebView из «Chrome», который я скачал из «Play Store» (версия 74.xxx).HTTP-агент WebView верен, поэтому WebView используется в соответствии с настройками разработчика системы Android.Аппаратное ускорение установлено на «ИСТИНА» как в активности, так и в файле AndroidManifest.

Я также провел очень простой тест с «Android-XAML-App», которое работает «из коробки».Куб отображается практически мгновенно.

MainView.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:WebViewTestAndroid"
             x:Class="WebViewTestAndroid.MainPage">
    <Grid>
        <WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />        
    </Grid>
</ContentPage>

Это пример главной страницы UNO, которая не работает.Страница загружается, но трехмерный куб не отображается.

MainPage.xaml

<Page
    x:Class="UnoWebViewTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnoWebViewTest"
    xmlns:ios="http://uno.ui/ios"
    xmlns:android="http://uno.ui/android"
    xmlns:xamarin="http://uno.ui/xamarin"
    xmlns:wasm="http://uno.ui/wasm"
    mc:Ignorable="d ios android xamarin wasm"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <android:WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
    </Grid>
</Page>

Я сравнил файлы манифеста, но до сих пор не пришел к выводу, что я мог бы продолжить расследование.,Я ожидаю, что UNO использует собственный элемент управления Android WebView, но, возможно, отсутствует какой-либо параметр или это даже не тот же элемент управления?

Ответы [ 2 ]

2 голосов
/ 03 мая 2019

Действительно, это связано с отключением аппаратного ускорения Uno WebView.Кроме того, Uno и Xamarin.Forms аналогичным образом используют Android.WebKit.WebView под капотом.

Аппаратное ускорение можно легко включить в Uno с помощью присоединенного свойства:

    public static class WebViewHardware
    {
        public static bool GetIsEnabled(WebView obj)
        {
            return (bool)obj.GetValue(IsEnabledProperty);
        }

        public static void SetIsEnabled(WebView obj, bool value)
        {
            obj.SetValue(IsEnabledProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(WebViewHardware), new PropertyMetadata(false, OnIsEnabledChanged));

        private static void OnIsEnabledChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
        {
            var webView = (WebView)dependencyObject;

            var isEnabled = (bool)args.NewValue;

#if __ANDROID__
            webView.Loaded += OnLoaded;

            void OnLoaded(object sender, RoutedEventArgs e)
            {
                webView.Loaded -= OnLoaded;
                var layerType = isEnabled ? Android.Views.LayerType.Hardware : Android.Views.LayerType.Software;

                webView.SetLayerType(layerType, null);
            }
#endif
        }

Это может быть использовано в XAML следующим образом:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <WebView Source="https://threejs.org/examples/?q=cube#webgl_geometry_cube" local:WebViewHardware.IsEnabled="True"/>
</Grid>
1 голос
/ 03 мая 2019

Эта проблема привела меня в бешенство, поэтому я потратил весь день на скачивание полного исходного кода Xamarin и UNO и отладку всех вещей с нуля.

Прежде всего, UNO устанавливает для "HardwareAcceleration" значение false для элемента управления WebView. Во-вторых, пропущенная подсказка - это строка:

view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);

Проблема в том, что на самом деле невозможно установить это извне, поэтому мы создаем новый класс, наследующийся от Android.Webkit.WebView:

public partial class MyCustomWebView : Android.Webkit.WebView
{
    protected MyCustomWebView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
        MakeSettings();
    }

    public MyCustomWebView(Context context) : base(context)
    {
        MakeSettings();
    }

    public MyCustomWebView(Context context, IAttributeSet attrs) : base(context, attrs)
    {
        MakeSettings();
    }

    public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
        MakeSettings();
    }

    public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, bool privateBrowsing) : base(context, attrs, defStyleAttr, privateBrowsing)
    {
        MakeSettings();
    }

    public MyCustomWebView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
    {
        MakeSettings();
    }

    private void MakeSettings()
    {
        SetLayerType(LayerType.Hardware, null);
        ForceHasOverlappingRendering(true);

        SetWebViewClient(new MyCustomWebViewClient(this));
        SetWebChromeClient(new WebChromeClient());

        Settings.AllowFileAccessFromFileURLs = true;
        Settings.AllowUniversalAccessFromFileURLs = true;
        Settings.JavaScriptEnabled = true;
        Settings.DomStorageEnabled = true;
        Settings.AllowFileAccess = true;
        Settings.CacheMode = CacheModes.NoCache;
        Settings.MediaPlaybackRequiresUserGesture = false;
        Settings.SetPluginState(WebSettings.PluginState.On);
    }


    public string HtmlContent
    {
        get { return string.Empty; }
        set { LoadUrl(value); }
    }
}

public class MyCustomWebViewClient : Android.Webkit.WebViewClient
{
    public MyCustomWebViewClient(WebView view)
    {
        var test = view.IsHardwareAccelerated;
        view.SetLayerType(LayerType.Hardware, null);
    }

    public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
    {
        view.LoadUrl(request.Url.ToString());
        return true;
    }

    public override void OnPageStarted(WebView view, string url, Bitmap favicon)
    {
        // The native webview control requires to have LayoutParameters to function properly.
        view.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.MatchParent);

        base.OnPageStarted(view, url, favicon);
    }
}

Использование этого пользовательского элемента управления в XAML позволяет использовать WebGL с аппаратным ускорением в WebView:

<android:MyCustomWebView HtmlContent="https://threejs.org/examples/?q=cube#webgl_geometry_cube" />
...