android Xamarin Forms WebView地理位置问题

ruoxqz4g  于 2023-05-05  发布在  Android
关注(0)|答案(3)|浏览(171)

我正在尝试在xamarin表单应用程序中启用webview,以获取Android设备的当前GPS坐标。目前,当在手机或笔记本电脑上的Chrome浏览器中打开时,WebView/网站将返回GPS坐标,但在应用程序中不会。尝试让这个工作尽可能简单,并在之后扩展它。
到目前为止的代码: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"
             x:Class="UITrial.Page2"
             BackgroundColor = "#f0f0ea">
    <Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />

  <WebView Source="https://danu6.it.nuigalway.ie/OliverInternetProgramming/project/Loginproject.html" />

</ContentPage>

HTML页面:

<!DOCTYPE html>
<html>
<body>

<p>Click the button to get your coordinates.</p>

<button onclick="getLocation()">Try It</button>

<p id="demo"></p>

<script>
var x = document.getElementById("demo");

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.watchPosition(showPosition);
    } else { 
        x.innerHTML = "Geolocation is not supported by this browser.";}
    }

function showPosition(position) {
    x.innerHTML="Latitude: " + position.coords.latitude + 
    "<br>Longitude: " + position.coords.longitude;
}
</script>

</body>
</html>
hivapdat

hivapdat1#

目前,当在手机或笔记本电脑上的Chrome浏览器中打开时,WebView/网站将返回GPS坐标,但在应用程序中不会。
您需要在Droid项目中为WebView使用自定义WebChromeClient。请参阅Android WebView Geolocation
在Xamarin.Forms中,您可以按照以下步骤来完成此操作:
1.在PCL项目中为WebView创建自定义控件:

public class GeoWebView:WebView
{
}

在Xaml中使用:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:WebViewFormsDemo"
         x:Class="WebViewFormsDemo.MainPage">
<local:GeoWebView 
    Source="https://danu6.it.nuigalway.ie/OliverInternetProgramming/project/Loginproject.html"></local:GeoWebView>

1.在Droid Project中为GeoWebView创建一个自定义渲染器,如下所示:

[assembly:ExportRenderer(typeof(GeoWebView),typeof(GeoWebViewRenderer))]
namespace WebViewFormsDemo.Droid
{
    public class GeoWebViewRenderer:WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);
            Control.Settings.JavaScriptEnabled = true;
            Control.SetWebChromeClient(new MyWebClient());
        }
    }

    public class MyWebClient : WebChromeClient
    {
        public override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
        {
            callback.Invoke(origin, true, false);
        }
    }
}

1.向AndroidManifest.xml添加权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

然后,您将在webview中正确获取您的位置。

aelbi1ox

aelbi1ox2#

欢呼猫王设法让一切工作,不得不做一些小的变化,所以将张贴我所做的一切详细:
在App.xaml.cs中:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Xamarin.Forms;

namespace WebViewFormsDemo
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            MainPage = new MainPage();
        }

    protected override void OnStart()
    {
        // Handle when your app starts
    }

    protected override void OnSleep()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume()
    {
        // Handle when your app resumes
    }
}

}
在MainPage.xaml中,确保您的网站是'https'

<?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:WebViewFormsDemo"
             x:Class="WebViewFormsDemo.MainPage">

  <local:GeoWebView
    Source="https:// --- Your Website ----></local:GeoWebView>

</ContentPage>

正如Elvis所说,然后需要在PLC项目中创建一个自定义控件。右键单击并添加新的“类”来执行此操作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace WebViewFormsDemo
{
    public class GeoWebView : WebView
    {
    }
}

然后在Droid类中创建一个自定义渲染。最初这里有一些错误,主要是缺少“using”指令,以及“assembly”中需要的关键字。

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 Xamarin.Forms.Platform.Android;
using Android.Webkit;

[assembly: ExportRenderer(typeof(WebViewFormsDemo.GeoWebView), typeof(WebViewFormsDemo.Droid.GeoWebViewRenderer))]
namespace WebViewFormsDemo.Droid
{
    public class GeoWebViewRenderer : WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);
            Control.Settings.JavaScriptEnabled = true;
            Control.SetWebChromeClient(new MyWebClient());
        }
    }

    public class MyWebClient : WebChromeClient
    {
        public override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
        {
            callback.Invoke(origin, true, false);
        }
    }
}

在这些变化之后,一切都很完美。再次感谢猫王!

ztmd8pv5

ztmd8pv53#

对于Android API 23及更高版本,这同样可以使用Xamarin.Essentials命名空间来实现。
1.确保您已请求Manifest文件中的所有适当权限。在写这篇文章的时候,这些是我需要的:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.LOCATION_HARDWARE" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

1.为WebView创建一个自定义渲染器,并创建一个要使用的自定义WebChromeClient

using Android.Content;
using Android.Webkit;

using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer( typeof( Xamarin.Forms.WebView ), typeof( Namespace.Droid.Renderers.WebViewRenderer ) )]
namespace Namespace.Droid.Renderers
{
    /// <summary>
    /// The <see cref="Xamarin.Forms.WebView"/> renderer.
    /// Implements the <see cref="WebViewRenderer" />
    /// </summary>
    /// <seealso cref="WebViewRenderer" />
    public class WebViewRenderer : Xamarin.Forms.Platform.Android.WebViewRenderer 
    {
        public WebViewRenderer( Context context )
            : base( context ) { }

        protected override void OnElementChanged( ElementChangedEventArgs<Xamarin.Forms.WebView> e )
        {
            base.OnElementChanged( e );

            if( e.NewElement != null )
            {
                GeoWebViewClient cwc = new GeoWebViewClient();
                Control.SetWebChromeClient( cwc );
            }
        }

        /// <summary>
        /// A custom Chrome Web Client used to process geolocation permission in Android.
        /// Implements the <see cref="WebChromeClient" />
        /// </summary>
        /// <seealso cref="WebChromeClient" />
        public class GeoWebViewClient : WebChromeClient
        {
            /// <summary>
            /// Called when the geolocation prompt is requested through the WebView.
            /// </summary>
            /// <param name="origin">The origin.</param>
            /// <param name="callback">The callback.</param>
            public override async void OnGeolocationPermissionsShowPrompt( string origin, GeolocationPermissions.ICallback callback )
            {
                // Check if we have location permissions already granted.
                var locationAlwaysPermissionStatus = await Xamarin.Essentials.Permissions.CheckStatusAsync<Xamarin.Essentials.Permissions.LocationAlways>();
                var locationWhenInUsePermissionStatus = await Xamarin.Essentials.Permissions.CheckStatusAsync<Xamarin.Essentials.Permissions.LocationWhenInUse>();

                // If not, request them.
                if( locationAlwaysPermissionStatus != PermissionStatus.Granted && locationWhenInUsePermissionStatus != PermissionStatus.Granted )
                {
                    await Xamarin.Essentials.Permissions.RequestAsync<Xamarin.Essentials.Permissions.LocationWhenInUse>();
                }

                callback.Invoke( origin, true, true );
            }
        }
    }
}

瞧!

相关问题