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>
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.
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.
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.
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.
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;
}
}
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.
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