Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insufficient geolocation permissions

Tags:

java

android

xml

I'm working on an Android Project. Basically, I'm trying to run WebView that displays Google Maps.

I wanted to display my own location but when I press the button for this, I get exceptions like:

11-18 17:29:56.237 7678-7678/com.example.ali.bellsolution E/LocationProvider: Caught security exception while registering for location updates from the system. The application does not have sufficient geolocation permissions.
11-18 17:29:56.257 7678-7678/com.example.ali.bellsolution E/LocationProvider: Caught security exception while registering for location updates from the system. The application does not have sufficient geolocation permissions.
11-18 17:29:56.260 7678-7678/com.example.ali.bellsolution E/LocationProvider: Caught security exception while registering for location updates from the system. The application does not have sufficient geolocation permissions.

I have added these permissions to the manifest file:

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

MainActivity.java:

package com.example.ali.bellsolution;

import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    private static final int REQUEST_FINE_LOCATION = 0;

    WebView myWebView;

    String mapPath = "https://www.google.co.uk/maps/@51.5112044,-0.2712415,14z";

    /**
     * WebViewClient subclass loads all hyperlinks in the existing WebView
     */
    public class GeoWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // When user clicks a hyperlink, load in the existing WebView
            view.loadUrl(url);
            return true;
        }
    }



    /**
     * WebChromeClient subclass handles UI-related calls
     * Note: think chrome as in decoration, not the Chrome browser
     */
    public class GeoWebChromeClient extends WebChromeClient {
        @Override
        public void onGeolocationPermissionsShowPrompt(String origin,
                                                       GeolocationPermissions.Callback callback) {
            // Always grant permission since the app itself requires location
            // permission and the user has therefore already granted it
            callback.invoke(origin, true, false);
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {



        super.onCreate(savedInstanceState);

        loadPermissions(Manifest.permission.ACCESS_COARSE_LOCATION, REQUEST_FINE_LOCATION);

        setContentView(R.layout.activity_main);
        myWebView = (WebView) this.findViewById(R.id.mapview);


        myWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
        myWebView.getSettings().setBuiltInZoomControls(true);
        myWebView.setWebViewClient(new GeoWebViewClient());



        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.getSettings().setGeolocationEnabled(true);
        myWebView.setWebChromeClient(new GeoWebChromeClient());
        myWebView.loadUrl(mapPath);

    }

    @Override
    public void onBackPressed() {
        // Pop the browser back stack or exit the activity
        if (myWebView.canGoBack()) {
            myWebView.goBack();
        }
        else {
            super.onBackPressed();
        }
    }


    private void loadPermissions(String perm, int requestCode) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(this, perm)) {
                ActivityCompat.requestPermissions(this, new String[]{perm}, requestCode);
            }
        }
    }



}

Manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ali.bellsolution" >



    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="23" />



    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="WebViewApp"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity"
                  android:label="WebViewApp"
            >

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
like image 658
Rob Neal Avatar asked Nov 18 '15 17:11

Rob Neal


People also ask

How do I enable location permissions on Android?

Open your phone's Settings app. Under "Personal," tap Location access. At the top of the screen, turn Access to my location on or off.

What are the required permissions for Android location Manager?

Android offers two location permissions: ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION . The permission you choose determines the accuracy of the location returned by the API. android.

What are location permissions?

One excellent feature found in recent versions of iOS and Android is the ability to grant an app the permission to use your location only while the app is open and you're actively using it. When installing a new app you should be given that option, and in the majority of cases that will be just what the doctor ordered.

How to request background location permission in Android?

When a feature in your app requests background location on a device that runs Android 10 (API level 29), the system permissions dialog includes an option named Allow all the time. If the user selects this option, the feature in your app gains background location access.


2 Answers

You may want to ask the user for Geolocation permissions right when they are needed, but wait for the user's response before invoking the Callback:

private static final int REQUEST_FINE_LOCATION = 1;
private String geolocationOrigin;
private GeolocationPermissions.Callback geolocationCallback;

public class GeoWebChromeClient extends WebChromeClient {
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin,
                                                   GeolocationPermissions.Callback callback) {
        // Geolocation permissions coming from this app's Manifest will only be valid for devices with
        // API_VERSION < 23. On API 23 and above, we must check for permissions, and possibly
        // ask for them.
        String perm = Manifest.permission.ACCESS_FINE_LOCATION;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
                ContextCompat.checkSelfPermission(MainActivity.this, perm) == PackageManager.PERMISSION_GRANTED) {
            // we're on SDK < 23 OR user has already granted permission
            callback.invoke(origin, true, false);
        } else {
            if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, perm)) {
                // ask the user for permission
                ActivityCompat.requestPermissions(MainActivity.this, new String[] {perm}, REQUEST_FINE_LOCATION);

                // we will use these when user responds
                geolocationOrigin = origin;
                geolocationCallback = callback;
            }
        }
    }
}

and receive the result of the permission request:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
    case REQUEST_FINE_LOCATION:
        boolean allow = false;
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // user has allowed this permission
            allow = true;
        }
        if (geolocationCallback != null) {
            // call back to web chrome client
            geolocationCallback.invoke(geolocationOrigin, allow, false);
        }
        break;
    }
}
like image 189
EricRobertBrewer Avatar answered Nov 29 '22 02:11

EricRobertBrewer


The fix for those Android 6 users is the following somewhere in your code:

if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) ==
        PackageManager.PERMISSION_GRANTED &&
        ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) ==
                PackageManager.PERMISSION_GRANTED) {
} else {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 2);
}

This is required because Android 6 requires that you prompt users for certain permissions.

like image 37
Keith Adler Avatar answered Nov 29 '22 01:11

Keith Adler