Forum General

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

GeoLocation in WebView

jvckejvcke Member ✭✭

I have created a web-application that uses the Google Maps JavaScript API.
The application works fine in a regular browser, even on mobile phones.

I am now trying to "wrap" the web-app in a Xamarin WebView, so that I can deploy it as a mobile app.
I'm focusing on trying to get it to work on Android first, then deal with iPhone later.
Therefore, it doesn't really matter if I get this to work with Xamarin.Forms or Xamarin.Android. As long as it works, I'm happy.

The problem is that when my javascript calls the navigator.geolocation.getCurrentPosition
When this happens in a regular browser, you get prompted with a question that asks if you allow the app to get your current position. You presss "allow" and the app continues.

This doesn't happen when the the app wrapped in a WebView.

I've created a simple webpage that uses the navigator.geolocation.getCurrentPosition method and just displays lat & lng inside a h1 tag on the page.

Here is the page: httpsjakethesnake .se

If I'm able to get that page to work in a WebView, hopefully my real app with google maps will work too.

I've read a couple of stackoverflow threads and other posts about this. Most of the solutions there are obsolete or works sometimes and sometimes not.

Thankful for any help.

Tagged:

Answers

  • JohnHardmanJohnHardman GBUniversity admin

    @jvcke

    Have you specified the appropriate permissions in the Android manifest in the Android-specific project of your Xamarin.Forms app?

    I'd start with:
    ACCESS_COARSE_LOCATION
    ACCESS_FINE_LOCATION
    LOCATION_HARDWARE

    As an aside - if you are basically building a thin wrapper around a web view in order to create a native app, have you considered using Apache Cordova instead of Xamarin.Forms?

  • jvckejvcke Member ✭✭

    @JohnHardman Thank you for answering.

    I think the manifest is OK:

      <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="27" />
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.LOCATION_HARDWARE" />
    

    My app is working when I manually go in to my app settings and enable location pemissions for the app. Although it's a 5 second delay for the javascript callback to return to the app with the coordinates...but that's better than nothing.

    I want my code to trigger an alert that gives the user the ability to accept the permissions.
    I guess you cant force permissions nowadays?

    This is my code so far (Mainactivity):

    public class MainActivity : AppCompatActivity
    {
        WebView webView;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.activity_main);
            webView = FindViewById<WebView>(Resource.Id.webView1);
    
            webView.SetWebViewClient(new GeoWebViewClient());
            webView.SetWebChromeClient(new GeoWebChromeClient());
    
            webView.Settings.JavaScriptCanOpenWindowsAutomatically = true;
            webView.Settings.JavaScriptEnabled = true;
            webView.Settings.DomStorageEnabled = true;
            webView.Settings.SetGeolocationEnabled(true);
    
            webView.LoadUrl("httpswww.jakethesnake.se/");
        }
    }
    
    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, IWebResourceRequest request)
        {
            Android.Net.Uri url = request.Url;
            view.LoadUrl(url.ToString());
            return true;
        }
        public override void OnReceivedSslError(WebView view, SslErrorHandler handler, SslError er)
        {
            // Ignore SSL certificate errors
            handler.Proceed();
        }
    }
    
  • jvckejvcke Member ✭✭

    I've also tried this. This actually prompts the user and asks for permissions.
    It seems that my javascript doesn't wait for this though. And even if the user presses "allow", nothing really happens in the appsettings.

       public override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
                {
                    const bool remember = false;
                    var builder = new Android.App.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();
                }
    
  • ChristianAbataChristianAbata Member ✭✭

    jvcke did you solve it? I'm facing the same problem I click on allow but noting hapends on my app

  • soufianemarlysoufianemarly Member ✭✭✭
    edited June 2020

    MainActivity :

                private void GetPermission()
        {
            string[] permissionsLocation =
            {
                Manifest.Permission.AccessCoarseLocation,
                Manifest.Permission.AccessFineLocation
            };
    
            const string permission = Manifest.Permission.AccessFineLocation;
    
            if (CheckSelfPermission(permission) == (int)Permission.Granted)
    
            {
                Console.WriteLine("Granted Location");
                string status = "StatutGranted";
                //BeaconUuid BC = new BeaconUuid(null, null, status);
                //OnStartServiceMessage(null);
            }
    
            else
            {
                // if the user has been asked about the permission before  
                if (ShouldShowRequestPermissionRationale(permission))
                {
                    //Explain to the user why we need to read the contacts
                    var alertDialog = new AlertDialog.Builder(this);
                    Console.WriteLine("Access to location");
                    alertDialog.SetTitle("Access to location");
                    alertDialog.SetMessage("Location access is required to start monitoring the beacon");
                    alertDialog.SetPositiveButton("Yes", delegate
                    {
                        RequestPermissions(permissionsLocation, RequestLocationId);
                    });
    
                    alertDialog.SetNegativeButton("No", delegate { });
                    alertDialog.Show();
                }
    
                else
                {
                    RequestPermissions(permissionsLocation, RequestLocationId);
                }
    
            }
    
        }
    
    
    
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
        {
            switch (requestCode)
            {
                case RequestLocationId:
                    {
                        if (grantResults[0] == Permission.Granted)
                        {
                            Console.WriteLine("Location permission is available");
                            //Toast.MakeText(this, "Location permission is available,Starting the service.", ToastLength.Short).Show();
                            string status = "StatutGranted";
                        }
                        else
                        {
                            Console.WriteLine("Location permission is denied");
                            Toast.MakeText(this, "Location permission is denied.", ToastLength.Short).Show();
                            string status = "StatutDenied";
                        }
    
                        break;
    
                    }
    
                default:
    
                    return;
    
            }
    
        }
    

    page where you call the geolocation

                private async void Location()
        {
            Console.WriteLine("  BeforLocation");
    
            try
            {
                Console.WriteLine(" Location");
    
                var request = new GeolocationRequest(GeolocationAccuracy.Best);
    
                var location1 = await Geolocation.GetLocationAsync(request);
                if (location1 != null)
                {
                    GPS = location1.Latitude.ToString() + "|" + location1.Longitude.ToString() + "|" + location1.Altitude;
                    Console.WriteLine(" GET gps " + GPS);
                }
                else
                {
                    await DisplayAlert("Localisation", "Veuillez activer la localisation et relancer le cours", "OK");
                    Console.WriteLine("IMPOSSIBLE DE DETECTED LA LOCALISATION");
                    GPS = "Probleme";
                }
            }
            catch (PermissionException pEx)
            {
                Console.WriteLine(" Handle permission exception " + pEx);
                GPS = "NotGranted";
                // Handle permission exception
            }
            catch (FeatureNotSupportedException fnsEx)
            {
                // Handle not supported on device exception
                Console.WriteLine(" Handle not supported on device exception " + fnsEx);
                GPS = "LocationNotSupportedOnDevice";
    
            }
            catch (FeatureNotEnabledException fneEx)
            {
                // Handle not enabled on device exception
                Console.WriteLine(" Handle not enabled on device exception " + fneEx);
                GPS = "NotGranted";
    
            }
            catch (Exception ex)
            {
                // Unable to get location
                Console.WriteLine(" Unable to get location " + ex);
    
    
            }
    
        }
    
Sign In or Register to comment.