I have added in my activity -location permission check on run time- but I still get the error that tell me to add the permission check...
here is my code. In Oncreate () I have added:
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
bPermissionGranted = checkLocationPermission();
}
In on onConnected:
public void onConnected(Bundle bundle) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (bPermissionGranted) {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
handleNewLocation(location);
} else {
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
handleNewLocation(location);
}
}
}
And the two method:
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
handleNewLocation(location);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
And it still mark the follow with red error:
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Well your code is somewhat fine. Don't check for permission in onCreate. Check it in your onConnected() method because its possible that the user has not granted the permission yet and onConnected() is executed before.
Then when you receive the permission result in onRequestPermissionsResult(), then start fetching the location updates if the result is positive.
Also an advice -
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
This piece of code is redundant. Android only requires run time permissions in Android M and above so your permission check code would only be executed if the Android version is above M else it won't execute.
Related
My application crashes if users enable the location permission through the app, then head to their phone's settings and disable the permission there. I have tried fixing this by checking the permissions through onResume but can't seem to get it right. Other solutions on StackOverflow haven't worked.
The following code runs within my onCreate() and checks for location permissions:
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
//check which API users are running.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//location permission dialog
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_FINE_LOCATION);
}
}
My onRequestPermissionsResult():
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSION_FINE_LOCATION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
}
} else {
Toast.makeText(getContext(), "The app requires location permissions", Toast.LENGTH_LONG).show();
getActivity().finish();
}
break;
}
}
Here is my onResume() code within the same fragment:
#Override
public void onResume() {
super.onResume();
updatePermissions();
if (googleApiClient.isConnected()) {
requestLocationUpdates();
}
}
public void updatePermissions(){
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
// mMap.setMyLocationEnabled(true);
} else {
//check which API users are running.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//location permission dialog
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_FINE_LOCATION);
}
}
}
The app crashes with the error:
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0 at fluo.tuki10.fragments.MapFragment.onRequestPermissionsResult(MapFragment.java:232)
which is the line
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
I feel like the solution is to implement a better onResume() that checks for permissions after users modify them outside the app. Unfortunately my code falls short
An advice, before comparing it with a head that is not without elements:
if (grantResults.length> 0)
i have an error that i cant fix and when i press alt+enter nothing
happens, i already added permission.ACCESS_FINE_LOCATION etc in the
manifest, can someone please help me ? i tried everything but nothing
seems to work
private void startLocationUpdates(){
String[] PERMISSIONS = {android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION};
if (ContextCompat.checkSelfPermission(this, PERMISSIONS[0])
!= PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(this, PERMISSIONS[1])
!= PackageManager.PERMISSION_GRANTED
) {
//gives me error in this activity.compat.request
ActivityCompat.requestPermissions((Activity) this, PERMISSIONS, 0 );
} else {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);// and error in this line too
Toast.makeText(this, "sinal pedido", Toast.LENGTH_SHORT).show();
}
}
Try this
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
new AlertDialog.Builder(this)
.setTitle(R.string.title_location_permission)
.setMessage(R.string.text_location_permission)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// location-related task you need to do.
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
}
}
Then you would just modify your onResume() override to call checkLocationPermission():
#Override
protected void onResume() {
super.onResume();
if (checkLocationPermission()) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
locationManager.requestLocationUpdates(provider, 400, 1, this);
}
}
}
Source: this
here is my code and it asks me for permission if i click Allow it works good but when the user clicks on DENY i want to get a result or log for denied
if user clicks "DENY" permission how can i set something on that
here is my code :
LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
Location location;
if (network_enabled) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
;
}
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION},
1);
location = locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location!=null){
lat = location.getLongitude();
lon = location.getLatitude();
Log.d("lat", "onCreate: "+lat+","+lon);
txtLocation.setText(+lat+","+lon);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setMessage("Latitude:"+lat+"\n"+"Longitude:"+lon);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d("", "onRequestPermissionsResult: "+requestCode);
Toast.makeText(MainActivity.this, ""+grantResults.length, Toast.LENGTH_SHORT).show();
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this, "Granted", Toast.LENGTH_SHORT).show();
// permission was granted, yay! Do the
} else {
Toast.makeText(MainActivity.this, "Denied", Toast.LENGTH_SHORT).show();
//user denied permission additionally you can check
//ActivityCompat.shouldShowRequestPermissionRationale if user checked on "do not show again" while clicking deny
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
First implement an onRequestPermissionResult like this:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_ACCESS_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
} else {
//user denied permission additionally you can check
//ActivityCompat.shouldShowRequestPermissionRationale if user checked on "do not show again" while clicking deny
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
I could write code that get user's location and that works fine in API < 23. But in API 23 and above, my code return nothing in Log.
More Details:
I enable manually device's GPS.
In the first run the app request permission and no log returns.
In the next running the app return my prepared Toast (Check your provider).
this is my wrote code:
public class MainActivity extends AppCompatActivity implements LocationListener {
private static final int MY_PERMISSIONS_REQUEST_COARSE_LOCATION = 124;
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 123;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_COARSE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
MY_PERMISSIONS_REQUEST_COARSE_LOCATION);
}
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
String provider = locationManager.getBestProvider(new Criteria(), false);
Location location = locationManager.getLastKnownLocation(provider);
if (location == null) {
Toast.makeText(this, "Check your provider", Toast.LENGTH_SHORT).show();
} else {
Log.i("New Location", "lat: " + location.getLatitude());
Log.i("New Location", "lng: " + location.getLongitude());
}
}
#Override
public void onLocationChanged(Location location) {
Log.i("Location", "lat: " + location.getLatitude());
Log.i("Location", "lng: " + location.getLongitude());
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
}
In Android API 23+ there is a new way to handle permissions considered as "dangerous", that´s the case of android.permission.ACCESS_FINE_LOCATION and android.permission.ACCESS_COARSE_LOCATION among others.
You don´t need to handle android.permission.ACCESS_COARSE_LOCATION if you are already using the android.permission.ACCESS_FINE_LOCATION.
Please take a look at this link from the official documentation which shows you how to handle permissions at runtime in Android API 23+.
https://developer.android.com/training/permissions/requesting.html
This one might also help you.
https://developer.android.com/guide/topics/location/strategies.html
How to check for permissions:
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.ACCESS_FINE_LOCATION);
How to request for permissions:
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
// MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Note that even if you request for permissions at runtime you will still have to keep the permission entry in the android manifest like this:
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
<!-- Needed only if your app targets Android 5.0 (API level 21) or higher. -->
<uses-feature android:name="android.hardware.location.gps" />
...
</manifest>
After checking and granting permissions you should review the link with the location strategies above, there you can find the details of what you are missing.
Basically you are not registering the listener to receive the location updates. After adding this line at the end of the onCreate() method you should start seeing the location updates in your log.
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
I'm developing an app and using following code to fetch current coordinates of the user (from this library):
ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(getBaseContext());
locationProvider.getLastKnownLocation().subscribe(new Action1<Location>() {
#Override
public void call(Location location) {
currentLatDouble = location.getLatitude();
currentLngDouble = location.getLongitude();
Toast.makeText(getBaseContext(), "User's location retrieved using library for android M in btnRetryGpsEvents()", Toast.LENGTH_SHORT).show();
}
});
The problem is that this code sometimes don't even gets executed even after all the conditions are true. See the code below:
if (currentLatDouble != null || currentLngDouble != null) {
retrieveHWrapper();
progressBarLoadingRequests.setVisibility(View.VISIBLE);
btnRetryGps.setVisibility(View.INVISIBLE);
gps_off.setVisibility(View.INVISIBLE);
Toast.makeText(getBaseContext(), "Loading hrequests...", Toast.LENGTH_LONG).show();
} else {
gps_off.setVisibility(View.VISIBLE);
progressBarLoadingRequests.setVisibility(View.INVISIBLE);
btnRetryGps.setVisibility(View.VISIBLE);
btnRetryGps.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
btnRetryGpsEvents();
int hasWriteContactsPermission = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) & ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) & ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) & ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_SETTINGS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getBaseContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) && !ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) && !ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) && !ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.WRITE_SETTINGS)) {
showMessageOKCancel("You need to allow access to few permissions so that the app can work as expected.",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_SETTINGS},
REQUEST_RUNTIME_PERMISSION);
}
});
return;
}
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.WRITE_SETTINGS},
REQUEST_RUNTIME_PERMISSION);
return;
}
}
ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(getBaseContext());
locationProvider.getLastKnownLocation()
.subscribe(new Action1<Location>() {
#Override
public void call(Location location) {
currentLatDouble = location.getLatitude();
currentLngDouble = location.getLongitude();
Toast.makeText(getBaseContext(), "User's location retrieved using library for android M in btnRetryGpsEvents()", Toast.LENGTH_SHORT).show();
}
});
Toast.makeText(getBaseContext(), "called from btnRetryGpsEvents() - GPS available", Toast.LENGTH_SHORT).show();
}
});
}
After running the above code, the toast due to this code is shown: Toast.makeText(getBaseContext(), "called from btnRetryGpsEvents() - GPS available", Toast.LENGTH_SHORT).show(); which means that this is getting executed, but the toast just above it viz.: Toast.makeText(getBaseContext(), "User's location retrieved using library for android M in btnRetryGpsEvents()", Toast.LENGTH_SHORT).show(); is not shown which means it doesn't gets executed!
How this can happen? What's going wrong here????
Please let me know.
P.S.: This problem is occuring only in Android M and above.
Please check code inside ReactiveLocationProvider. I think it implements LocationListener. Guessing that getLastLocation called inside. It will give location only if last location available. Or please provide code so we can check.