Forum Xamarin.Android

Accsses geo location in webview

EmbapeEmbape Member ✭✭
edited April 2019 in Xamarin.Android

In Xamarin.android I created a webview like this :

               protected override void OnCreate(Bundle savedInstanceState)
                {
                        base.OnCreate(savedInstanceState);
                        SetContentView(Resource.Layout.activity_main);

                        var webView = FindViewById<WebView>(Resource.Id.webView);

                        webView.Settings.JavaScriptEnabled = true;
                        webView.Settings.JavaScriptCanOpenWindowsAutomatically = true;
                        webView.Settings.DomStorageEnabled = true;
                        webView.Settings.SetGeolocationEnabled(true);
                        webView.Settings.SetAppCacheEnabled(true);
                        webView.SetWebChromeClient(new HybridWebViewChormClient());
                        webView.LoadUrl("myaddress");

                }

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

                    }


                }

and set this permission > Access_fine_location in android manifest
but the webview can't get access location
note : in external browser like chrome or Firefox access location works fine
i try it in android 9 pie

Best Answer

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    @Embape For Api 23+, we have to request the runtime permission to enable the location service on Android. Try my activity to test your webpage again:

    public class MainActivity : Activity
    {
        public String mGeolocationOrigin;
        public GeolocationPermissions.ICallback mGeolocationCallback;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            // Initialize the permission plugin
            Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, savedInstanceState);
    
            SetContentView(Resource.Layout.main_layout);
    
            var webView = FindViewById<WebView>(Resource.Id.webView);
            webView.Settings.JavaScriptEnabled = true;
            webView.SetWebChromeClient(new WebViewChormClient(this));
    
            // I used a local webpage to test
            webView.LoadUrl("file:///android_asset/localPage.html");
    
        }
    
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    
            if (permissions.Contains(Manifest.Permission.AccessFineLocation))
            {
                bool allow = false;
                if (grantResults[0] == Android.Content.PM.Permission.Granted)
                {
                    // user has allowed these permissions
                    allow = true;
                }
                if (mGeolocationCallback != null)
                {
                    mGeolocationCallback.Invoke(mGeolocationOrigin, allow, false);
                }
            }
        }
    }
    
    public class WebViewChormClient : WebChromeClient
    {
        MainActivity currentActivity;
    
        public WebViewChormClient(MainActivity activity)
        {
            currentActivity = activity;
        }
        public async override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
        {
            var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
            if (Build.VERSION.SdkInt < BuildVersionCodes.M || status == PermissionStatus.Granted)
            {
                // we're on SDK < 23 OR user has already granted permission
                callback.Invoke(origin, true, false);
            }
            else
            {                
                // ask the user for permissions
                var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
                //Best practice to always check that the key exists
                if (results.ContainsKey(Permission.Location))
                    status = results[Permission.Location];
                currentActivity.mGeolocationOrigin = origin;
                currentActivity.mGeolocationCallback = callback;
            }
        }
    
    }
    

    Here I used https://github.com/jamesmontemagno/PermissionsPlugin to request the runtime permissions.

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    Did you use the correct permissions?
    Try to check this thread: https://stackoverflow.com/questions/5329662/android-webview-geolocation
    It lists all the permissions for referring.

  • EmbapeEmbape Member ✭✭

    yes i had tried those solutions before that but doesn't work

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    @Embape For Api 23+, we have to request the runtime permission to enable the location service on Android. Try my activity to test your webpage again:

    public class MainActivity : Activity
    {
        public String mGeolocationOrigin;
        public GeolocationPermissions.ICallback mGeolocationCallback;
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
    
            // Initialize the permission plugin
            Plugin.CurrentActivity.CrossCurrentActivity.Current.Init(this, savedInstanceState);
    
            SetContentView(Resource.Layout.main_layout);
    
            var webView = FindViewById<WebView>(Resource.Id.webView);
            webView.Settings.JavaScriptEnabled = true;
            webView.SetWebChromeClient(new WebViewChormClient(this));
    
            // I used a local webpage to test
            webView.LoadUrl("file:///android_asset/localPage.html");
    
        }
    
        public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    
            if (permissions.Contains(Manifest.Permission.AccessFineLocation))
            {
                bool allow = false;
                if (grantResults[0] == Android.Content.PM.Permission.Granted)
                {
                    // user has allowed these permissions
                    allow = true;
                }
                if (mGeolocationCallback != null)
                {
                    mGeolocationCallback.Invoke(mGeolocationOrigin, allow, false);
                }
            }
        }
    }
    
    public class WebViewChormClient : WebChromeClient
    {
        MainActivity currentActivity;
    
        public WebViewChormClient(MainActivity activity)
        {
            currentActivity = activity;
        }
        public async override void OnGeolocationPermissionsShowPrompt(string origin, GeolocationPermissions.ICallback callback)
        {
            var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
            if (Build.VERSION.SdkInt < BuildVersionCodes.M || status == PermissionStatus.Granted)
            {
                // we're on SDK < 23 OR user has already granted permission
                callback.Invoke(origin, true, false);
            }
            else
            {                
                // ask the user for permissions
                var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
                //Best practice to always check that the key exists
                if (results.ContainsKey(Permission.Location))
                    status = results[Permission.Location];
                currentActivity.mGeolocationOrigin = origin;
                currentActivity.mGeolocationCallback = callback;
            }
        }
    
    }
    

    Here I used https://github.com/jamesmontemagno/PermissionsPlugin to request the runtime permissions.

Sign In or Register to comment.