I'm trying to enable a webview within a xamarin forms app to get the current GPS coordinates of an android device. Currently the webview/website will return the GPS coordinates when opened in a chrome browser on the phone or a laptop, however within the app will not. Trying to get this working as simply as possible and to expand on it after.
Code so far: XAML page:
<?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 PAGE:
<!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>
Currently the webview/website will return the GPS coordinates when opened in a chrome browser on the phone or a laptop, however within the app will not.
You need to use a custom WebChromeClient
for WebView
in Droid project. Please refer to Android WebView Geolocation.
In Xamarin.Forms you can follow the below steps to accomplish this:
Create a custom Control for WebView in PCL project:
public class GeoWebView:WebView
{
}
And use it in 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>
Create a Custom Renderer for GeoWebView
in Droid Project like below:
[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);
}
}
}
Add Permissions to AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Then you will get your location in webview correctly.
Cheers Elvis managed to get everything working, had to make some minor changes so will post everything I did in detail:
In 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
}
}
}
In MainPage.xaml ensure that your website is '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>
As Elvis said then need to create a custom control in the PLC project. Right click and add new 'Class' to do this.
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
{
}
}
Following this create a Custom Render in the Droid Class. Had some errors here initially, mostly with missing 'using' directives and also with keywords needed in the '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);
}
}
}
Following these changes everything worked perfectly. Thanks again Elvis!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With