In Android 10, when asking for some permission like Location, the system prompts the user 3 options:
Allow APP to access this device's location?
-Allow all the time
-Allow only while using the app
-Deny
Is there a way to know how exactly has been granted? I use this code to know if location is granted:
boolean hasPermission = (ContextCompat.checkSelfPermission(oContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
But I need to know if it has been granted "all the time" or just "while using the app".
What I really need is to have permission all the time as my app has a background location service. So I need to know if the permission has been granted to to that, or the possibility to ask for the permission but without the option of allowing it "only when using the app".
requestPermissions(Context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 123);
You can use:
boolean backgroundLocationPermissionApproved =
ActivityCompat.checkSelfPermission(this,
permission.ACCESS_BACKGROUND_LOCATION)
There is no possibility to prompt the user without letting him choose the "only when using the app" option.
You can use this method, I have tested this method on android level 10 and above :
private void checkLocationPermissionState(Context context){
int fineLocation = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
int coarseLocation = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
int bgLocation = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
boolean isAppLocationPermissionGranted = (bgLocation == PackageManager.PERMISSION_GRANTED) &&
(coarseLocation == PackageManager.PERMISSION_GRANTED);
boolean preciseLocationAllowed = (fineLocation == PackageManager.PERMISSION_GRANTED)
&& (coarseLocation == PackageManager.PERMISSION_GRANTED);
if (preciseLocationAllowed) {
Log.e("PERMISSION","Precise location is enabled in Android 12");
} else {
Log.e("PERMISSION","Precise location is disabled in Android 12");
}
if (isAppLocationPermissionGranted) {
Log.e("PERMISSION","Location is allowed all the time");
} else if(coarseLocation == PackageManager.PERMISSION_GRANTED){
Log.e("PERMISSION","Location is allowed while using the app");
}else{
Log.e("PERMISSION","Location is not allowed.");
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
int bgLocation = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
boolean isAppLocationPermissionGranted = (bgLocation == PackageManager.PERMISSION_GRANTED) &&
(coarseLocation == PackageManager.PERMISSION_GRANTED);
if (isAppLocationPermissionGranted) {
Log.e("PERMISSION","Location is allowed all the time");
} else if(coarseLocation == PackageManager.PERMISSION_GRANTED){
Log.e("PERMISSION","Location is allowed while using the app");
}else{
Log.e("PERMISSION","Location is not allowed.");
}
} else {
boolean isAppLocationPermissionGranted = (fineLocation == PackageManager.PERMISSION_GRANTED) &&
(coarseLocation == PackageManager.PERMISSION_GRANTED);
if (isAppLocationPermissionGranted) {
Log.e("PERMISSION","Location permission is granted");
} else {
Log.e("PERMISSION","Location permission is not granted");
}
}
}
As of 18th July 2021 based on #gkpln3's answer it is not returning Boolean value but returning Integer value so added a small boolean converter in Kotlin
val backgroundLocationPermissionApproved: Boolean = ActivityCompat.checkSelfPermission(requireContext(),
Manifest.permission.ACCESS_BACKGROUND_LOCATION) > -1
Related
I am new in Android development. So my question may be too basic. Sorry for this. Now I am maintaining a previously written code.
This application use the location services of the phone. In the manifest file it is written:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
But although users give permisson for using location services, in most cases by application can not get location directly.
For example while my app can not get location information, after opening Google Maps application, my application can always get the location information. Then I have no problem with location.But firstly I have to trigger with Google Maps.
What could cause this? Why my app can get location after opening Google Maps? Do I need another permission in my manifest file?
My code block is like the following ,
private static final int LOCATION_SERVICES_RESOLUTION_REQUEST = 9001;
private void initMainActivity() {
int fineAccessGranted = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
int coarseAccessGranted = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION);
int externalWrite = ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE);
int externalRead = ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE);
int camera = ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA);
ArrayList<String> permissionsNeeded = new ArrayList<String>();
if (fineAccessGranted == PackageManager.PERMISSION_DENIED)
permissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
if (coarseAccessGranted == PackageManager.PERMISSION_DENIED)
permissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
if (externalWrite == PackageManager.PERMISSION_DENIED)
permissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (externalRead == PackageManager.PERMISSION_DENIED)
permissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
if (camera == PackageManager.PERMISSION_DENIED)
permissionsNeeded.add(Manifest.permission.CAMERA);
if (permissionsNeeded.size() == 0) {
this.initMainActivityAfterPermissions();
} else {
ActivityCompat.requestPermissions(this, permissionsNeeded.toArray(new String[0]), LOCATION_SERVICES_RESOLUTION_REQUEST);
}
}
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
// super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LOCATION_SERVICES_RESOLUTION_REQUEST: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
this.initMainActivityAfterPermissions();
} else {
}
return;
}
Code fragment that gets the location;
result = LocationServices.FusedLocationApi.getLastLocation(instance.mGoogleApiClient);
Basically it means that you try to retrieve location via mFusedLocationClient.getLastLocation() and there is no location on device at this time. So you need to request location updates , like mFusedLocationClient.requestLocationUpdates.
This links will be useful https://developer.android.com/training/location/receive-location-updates?hl=es and https://github.com/googlesamples/android-play-location
my device on android marshmallow.
so I use get permission this method.
int currentApiVer = Build.VERSION.SDK_INT;
Log.d(TAG, "currentApiVer = " + currentApiVer);
if (currentApiVer >= Build.VERSION_CODES.M) {
Log.d(TAG, "currentApiVer ----------------------------");
verifyPermissions(this);
} //onCreate()
private static boolean verifyPermissions(AppCompatActivity activity) {
Log.d(TAG, "verifyPermissions --------------------------------------");
int writePerm = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPerm = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
int camera_perm = ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (writePerm != PackageManager.PERMISSION_GRANTED ||
readPerm != PackageManager.PERMISSION_GRANTED ||
camera_perm != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
activity, PERMISSIONS_REQ, REQUEST_CODE_PERMISSIONS
);
return false;
} else {
return true;
}
}
my app is CCTV app. I use WebRTC
my problem when I first build my app.
show permission dialog. when I check permit permission.
success CCTV connect.
but I try again start built app.
fail CCTV connect.
clearly I already check permit permission.
perhaps, I think marshmallow permission problem.
in this situation. how I fix this problem?
thanks.
If I ask for several permissions at one time on Android, run time permissions works great and asks the user for all the permissions I am requesting. That is if I do them all in one call.
If I instead choose to separate run time permission requests into groups, so that I first request access to contacts, then afterwards request access to SMS, my program will ignore the request to SMS and will ultimately treat the SMS request as rejected. Why is this? does the program proceed through code while waiting for the user to respond? How can I keep my permission requests separate and still be able to request permissions right after each other?
The reason why I don't want to do all permissions at once is because I only want ask for permissions when I need them. That is why I have separated permissions into groups.
Any help is greatly appreciated!
EDIT:
Sample code: checkPermissions is called
public boolean checkPermissions(int permissionsToCheck)
{
// Use constants above to specify permissions check to do
if (Build.VERSION.SDK_INT < 23) {
//Do not need to check the permission
return true;
} else {
switch (permissionsToCheck) {
case PERMISSIONS_FOR_MESSAGING:
return ( checkAndRequestContactPermissions() && checkAndRequestSMSPermissions() );
case PERMISSIONS_FOR_BLUETOOTH:
return checkAndRequestBluetoothPermissions();
default:
return false;
}
}
}
Calls checkAndRequestContactPermissions() and checkAndRequestSMSPermissions()
private boolean checkAndRequestContactPermissions() {
int permissionReadContacts = ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_CONTACTS);
int permissionWriteContacts = ContextCompat.checkSelfPermission(mContext, Manifest.permission.WRITE_CONTACTS);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionReadContacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_CONTACTS);
}
if (permissionWriteContacts != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_CONTACTS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(mActivity, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MY_PERMISSIONS_REQUEST_CONTACTS);
return false;
}
return true;
}
private boolean checkAndRequestSMSPermissions() {
int permissionReadSMS = ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_SMS);
int permissionSendSMS = ContextCompat.checkSelfPermission(mContext, Manifest.permission.SEND_SMS);
List<String> listPermissionsNeeded = new ArrayList<>();
if (permissionReadSMS != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.SEND_SMS);
}
if (permissionSendSMS != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(mActivity, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MY_PERMISSIONS_REQUEST_SMS);
return false;
}
return true;
}
I try to check if I have permissions to Contacts and SMS but it only requests permission to Contacts instead of both.
I want to get all granted permissions. I know I can get all requested permissions by packageinfo.requestedPermissions but I want to know list of granted permissions and granted permissions can be lesser then requested in case of android M. So I just wanted to know that is there way that I can get list of all granted permissions?
I know from list of requested permission I can check for that permission weather granted or not but I want to know list of all granted permission. Don't want to check for every requested permission.
A simple function that returns all the permissions that have been requested and granted for a given package could look like this:
List<String> getGrantedPermissions(final String appPackage) {
List<String> granted = new ArrayList<String>();
try {
PackageInfo pi = getPackageManager().getPackageInfo(appPackage, PackageManager.GET_PERMISSIONS);
for (int i = 0; i < pi.requestedPermissions.length; i++) {
if ((pi.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
granted.add(pi.requestedPermissions[i]);
}
}
} catch (Exception e) {
}
return granted;
}
Note that this requires API level 16 or above, but that should hopefully not be an issue these days.
You can check permission one by one and add to list:
// Should we show an explanation?
List<String> listPermissionsNeeded = new ArrayList<>();
// No explanation needed, we can request the permission.
if((ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED))
{
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if((ContextCompat.checkSelfPermission(context,
Manifest.permission.GET_ACCOUNTS)
!= PackageManager.PERMISSION_GRANTED))
{
listPermissionsNeeded.add(Manifest.permission.GET_ACCOUNTS);
}
if((ContextCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED))
{
listPermissionsNeeded.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if((ContextCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED))
{
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if((ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED))
{
listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(context,
listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),
MY_PERMISSIONS_REQUEST_MULTIPLE_PERMISSION);
}
I use Android API lvl 23 in my application. When I check Camera permission, the ContextCompat.checkSelfPermission always return 0 (== PackageManager.PERMISSION_GRANTED)
I managed to change it from ContextCompat to ActivityCompat.
Here is my code:
public static boolean verify(Activity activity, final String[] PERMISSIONS, final int PERMISSIONS_REQUEST_ID) {
if (underAPI23())
return true;
String[] denyPermission = new String[PERMISSIONS.length];
int denyPermissionLength = 0;
boolean shouldShowRequest = false;
for (int i = 0; i < PERMISSIONS.length; i++) {
int check = ContextCompat.checkSelfPermission(activity, PERMISSIONS[i]);
LogUtils.e(TAG, PERMISSIONS[i] + ": " + (check != PackageManager.PERMISSION_GRANTED));
// ===== ===== =====
// This always return true. :'(
// ===== ===== =====
if (check != PackageManager.PERMISSION_GRANTED) {
denyPermission[denyPermissionLength++] = PERMISSIONS[i];
if (shouldShowRequest == false) {
boolean should = ActivityCompat.shouldShowRequestPermissionRationale(activity, PERMISSIONS[i]);
if (should)
shouldShowRequest = true;
}
}
}
if (denyPermissionLength > 0) {
if (shouldShowRequest) {
ActivityCompat.requestPermissions(activity, denyPermission, PERMISSIONS_REQUEST_ID);
} else {
ActivityCompat.requestPermissions(activity, denyPermission, PERMISSIONS_REQUEST_ID);
}
return false;
} else {
return true;
}
}
My dependencies in Gradle build
dependencies {
//...
compile 'com.android.support:support-v4:23.2.0'
compile 'com.android.support:appcompat-v7:23.2.0'
//...
}
Updated: Permission call
if (PermissionGrant.verify(getActivity(), new String[]{Manifest.permission.CAMERA}, GRANT_TAKE_PHOTO)) {
// Do my jobs
}
Your permission should be Manifest.permission.<Android permission>
What is your Android target version? shouldShowRequestPermissionRationale always return false that mean ContextCompat.checkSelfPermission(activity, permission) always return false at Android API lvl under 23 too.
Document here. Please focus on:
Note: If the user turned down the permission request in the past and chose the Don't ask again option in the permission request system dialog, this method returns false. The method also returns false if a device policy prohibits the app from having that permission.