Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Show Prompt to know the location

I am using Xamarin WebView controller to display a web site (in both iOS/Android). The web site's home page prompts to access the device location. But that prompt is not showing when I have this website on a WebView (from the App). When I open this site on the browser, from the same mobile device it shows the message box. I am just wondering if it is possible to have such prompts on Xamarin WebView?

Here is an example prompt.

enter image description here

This is all I have in the Xamarin app.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:nCollar"
             x:Class="nCollar.MainPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.iOS>0,20,0,0</OnPlatform.iOS>
            <OnPlatform.Android>0,0,0,0</OnPlatform.Android>
            <OnPlatform.WinPhone>0,0,0,0</OnPlatform.WinPhone>
        </OnPlatform>
    </ContentPage.Padding>

    <WebView x:Name="webView"
                 Grid.Row="0"
                 VerticalOptions="FillAndExpand" 
                 Source="https://www.ncollar.com.au/"/>

</ContentPage>

UPDATE 1

Android

I've tried the solution mentioned in this post, but still it doesn't show the prompt.

WebViewRenderer.cs

using Android.Webkit;
using Xamarin.Forms.Platform.Android;

[assembly: Xamarin.Forms.ExportRenderer(typeof(TestApp.Controls.WebView), typeof(TestApp.Droid.Renderers.WebViewRenderer))]
namespace TestApp.Droid.Renderers
{
    public class WebViewRenderer : Xamarin.Forms.Platform.Android.WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);

            if (this.Control == null)
            {
                return;
            }

            var webView = this.Element as TestApp.Controls.WebView;
            if (webView == null)
            {
                return;
            }


           // webView. ings.JavaScriptEnabled = true;
            this.Control.Settings.DomStorageEnabled = true;
            this.Control.Settings.DisplayZoomControls = true;
            this.Control.Settings.BuiltInZoomControls = true;
            this.Control.Settings.SetGeolocationEnabled(true);
            this.Control.Settings.JavaScriptCanOpenWindowsAutomatically = true;

            this.Control.SetWebViewClient(new GeoWebViewClient());
            this.Control.SetWebChromeClient(new GeoWebChromeClient());
        }
    }

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

    public class GeoWebViewClient : WebViewClient
    {
        public override bool ShouldOverrideUrlLoading(WebView view, string url)
        {
            view.LoadUrl(url);
            return true;
        }
    }
}

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-sdk android:minSdkVersion="15" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <application android:label="TestApp.Android"></application>
</manifest>

iOS

Tried NSLocationWhenInUseUsageDescription in the plist file, but no difference.

like image 836
CharithJ Avatar asked Jun 19 '17 11:06

CharithJ


2 Answers

Updated answer (with code)

In case of Android - you will need a custom renderer for your WebView control. (ref: gist)

public class ExtendedWebViewRenderer : WebViewRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null || Element == null)
        {
            return;
        }

        Control.Settings.JavaScriptEnabled = true;
        Control.Settings.SetGeolocationEnabled(true);
        Control.Settings.SetGeolocationDatabasePath(Control.Context.FilesDir.Path);

        Control.SetWebViewClient(new CustomWebViewClient());
        Control.SetWebChromeClient(new CustomChromeClient(Control.Context));
    }
}

public class CustomWebViewClient : WebViewClient
{
    public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, string url)
    {
        view.LoadUrl(url);
        return true;
    }
}

public class CustomChromeClient : WebChromeClient
{
    private readonly Context _context;

    public CustomChromeClient(Context context)
    {
        _context = context;
    }

    public override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
    {
        const bool remember = false;
        var builder = new AlertDialog.Builder(_context);
        builder.SetTitle("Location")
            .SetMessage(string.Format("{0} would like to use your current location", origin))
            .SetPositiveButton("Allow", (sender, args) => callback.Invoke(origin, true, remember))
            .SetNegativeButton("Disallow", (sender, args) => callback.Invoke(origin, false, remember));
        var alert = builder.Create();
        alert.Show();
    }
}

Manifest permissions

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

Usage sample

<StackLayout Margin="30" BackgroundColor="#ededed">
    <Label Text="WebView location prompt sample" Margin="15" HorizontalOptions="Center" />
    <local:ExtendedWebView x:Name="webView" Source="https://www.yellowpages.com/" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</StackLayout>

android output

And, in case of iOS, you need to set NSLocationWhenInUseUsageDescription description in the info.plist file.

info.plist

And it displays the prompt.

ios output

Complete code sample can be found at this link


Original answer

In case of Android - you should be able to resolve this by adding a platform-specific renderer for WebView and implement the permission handling by adding a custom WebChromeClient.

In case of iOS - you need to add NSLocationWhenInUseUsageDescription description in your info plist

like image 166
Sharada Gururaj Avatar answered Nov 14 '22 02:11

Sharada Gururaj


But that prompt is not showing when I have this website on a WebView (from the App).

If I got it right, you're wrapping this in an app. That's not the expected user experience from a mobile app. your app should use the platform(e.g iOS,Android) location permissions in order to get the user approval.

Xamarin will let you access Location on each platform quite differently. If the Xamarin app has access to location than the webview should inherit these permissions. So it might worth trying this recipe and try accsing location before opening the webview itself

like image 24
ApriOri Avatar answered Nov 14 '22 02:11

ApriOri