How can I detect the status of location access when user rejected the permission in the permission manager of the app.
this is not about Android M,but all the API Level
I tried to use Context#checkPermission,but it always return true.so i can't get the right status of location access permission if the user rejected it.
private static boolean checkPermission(Context context, String permName, String pkgName){
PackageManager pm = context.getPackageManager();
if(PackageManager.PERMISSION_GRANTED == pm.checkPermission(permName, pkgName)){
System.out.println(pkgName + "has permission : " + permName);
return true;
}else{
//PackageManager.PERMISSION_DENIED == pm.checkPermission(permName, pkgName)
System.out.println(pkgName + "not has permission : " + permName);
return false;
}
}
Using ContextCompat.checkSelfPermission() has worked for me:
if(ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED){
return true;
}else{
Log.d(LOG_TAG, "Permission not granted: " + permission);
return false;
}
Related
I want to find all apps with enabled SYSTEM_ALERT_WINDOW permission installed on the device.
First of all I found all apps with SYSTEM_ALERT_WINDOW permission and I verified that the list is correct: on my phone I went to Settings -> Special app access -> Display over other apps.
Then I disabled "Allow display over other apps" option for all apps under "Display over other apps" menu.
Next, I started my app again and I found out that list of apps with SYSTEM_ALERT_WINDOW permission still the same.
I decided to check if permission is granted or not. I used the following:
PackageManager.checkPermission(SYSTEM_ALERT_WINDOW, package name) == PackageManager.PERMISSION_GRANTED
But this check returned true for all packages with SYSTEM_ALERT_WINDOW permisson! Moreover, this check returns true even if package doesn't have SYSTEM_ALERT_WINDOW permission at all.
My code is below:
public ArrayList<String> getAppsWhichHaveOverlaySettingEnabled() {
ArrayList<String> apps = new ArrayList<>();
PackageManager pm = getPackageManager();
List<PackageInfo> installedPackages = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS | PackageManager.GET_PROVIDERS);
for (PackageInfo packageInfo : installedPackages) {
String[] requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
for (String requestedPermission : requestedPermissions) {
if (requestedPermission.equals(SYSTEM_ALERT_WINDOW)) {
if (pm.checkPermission(SYSTEM_ALERT_WINDOW, packageInfo.packageName) == PackageManager.PERMISSION_GRANTED) {
String name = pm.getApplicationLabel(packageInfo.applicationInfo).toString();
apps.add(name + " (" + packageInfo.packageName + ")");
}
}
}
}
}
return apps;
}
What am I doing wrong? Or it is not possible to get such information at all?
I checked my method and another app with similar method on several Android devices and looks like it is not possible to get list of apps with currently enabled SYSTEM_ALERT_WINDOW permission.
If SYSTEM_ALERT_WINDOW permission was granted to app once then check methods will return true no matter whether this permission currently enabled or not.
Still, the more accurate way to check such a permission is:
public ArrayList<String> getAppsWhichHaveOverlaySettingEnabled() {
ArrayList<String> apps = new ArrayList<>();
PackageManager pm = getPackageManager();
List<PackageInfo> installedPackages = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS);
for (PackageInfo packageInfo : installedPackages) {
String[] requestedPermissions = packageInfo.requestedPermissions;
if (requestedPermissions != null) {
for (int i = 0; i < requestedPermissions.length; i++) {
String requestedPermission = requestedPermissions[i];
if (requestedPermission.equals(SYSTEM_ALERT_WINDOW)) {
if ((packageInfo.requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) == REQUESTED_PERMISSION_GRANTED) {
String name = pm.getApplicationLabel(packageInfo.applicationInfo).toString();
apps.add(name + " (" + packageInfo.packageName + ")");
}
}
}
}
}
return apps;
}
Read more here.
This is a rewrite of my original post because I have found that, contrary to Permissions overview:
a) The secondary permission dialog is never displayed
b) After
clicking "Deny" for the initial permission dialog, it is never shown
again.
Therefore, if I click deny, I can never allow calendar permission.
I set permissions in the manifest:
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>
<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
On start, I check for calendar permissions in MainActivity because they are necessary for the user to add appointments via my app and make them available to Google calendar (this works, if I allow, my app adds the calendar):
AccessCalendar accessCalendar = new AccessCalendar();
if(accessCalendar.requestCalendarPermissions(mContext, this)){
/**
* calendar read and write permissions not allowed: explain why needed
*/
Log.d(TAG, "calendar read and write permissions not allowed: explain why needed");
ConstraintLayout constraintLayout = (ConstraintLayout) findViewById(R.id.constraintLayout);
Snackbar.make(constraintLayout, R.string.write_calendar_permission_explanation, Snackbar.LENGTH_LONG).show();
DialogFragment permissionDialog = new CalendarPermissionExplanationFragment();
try {
permissionDialog.show(getSupportFragmentManager(), "CalendarPermissionExplanationFragment");
}catch (Exception e){
Log.d(TAG, "exception e is: " + e);
}
}else{
/**
* calendar read and write permissions allowed! No need to explain
*/
Log.d(TAG, "calendar read and write permissions allowed! No need to explain");
}
AccessCalendar.requestCalendarPermissions is (pretty much plagarized from Request App Permissions):
public boolean requestCalendarPermissions(Context context, Activity activity){
Log.d(TAG, "Entered: requestCalendarPermissions");
boolean explain = false;
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALENDAR)
!= PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_CALENDAR) != PackageManager.PERMISSION_GRANTED ) {
// Permission is not granted
Log.d(TAG, "read and write permission not granted");
if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.READ_CALENDAR) &&
ActivityCompat.shouldShowRequestPermissionRationale(activity,
Manifest.permission.WRITE_CALENDAR)) {
Log.d(TAG, "shouldShowRequestPermissionRationale is true");
// 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.
Toast.makeText(context, R.string.write_calendar_permission_explanation, Toast.LENGTH_LONG).show();
explain = true;
} else {
Log.d(TAG, "shouldShowRequestPermissionRationale is false");
// No explanation needed; request the permission
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR},
MY_PERMISSIONS_REQUEST_CALENDAR);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}else{
//permission is granted, so set permission to true
Log.d(TAG, "read and write calendar permissions granted");
}
return explain;
}
Due to some problems, I am forced to use Toast to provide an explanation. I am now presented with the initial permissions dialog who's request attempt, Deny or Allow, is handled by MainActivity.onRequestPermissionsResult():
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Log.d(TAG, "Entered: onRequestPermissionsResult");
Log.d(TAG, "requestCode is: " + requestCode);
Log.d(TAG, "permissions is: " + permissions);
Log.d(TAG, "grantResults is: " + grantResults);
int cntPermissions = grantResults.length;
if(cntPermissions > 0) {
for (int i = 0; i < cntPermissions; i++) {
Log.d(TAG, "permissions[" + i + "] is: " + permissions[i]);
}
}
int cntGrantResults = grantResults.length;
if(cntGrantResults > 0) {
for (int i = 0; i < cntGrantResults; i++) {
Log.d(TAG, "grantResults[" + i + "] is: " + grantResults[i]);
}
}
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_CALENDAR:
Log.d(TAG, "Entered: case MY_PERMISSIONS_REQUEST_CALENDAR");
if(cntPermissions > 0) {
if(permissions[1].equals("android.permission.WRITE_CALENDAR") && grantResults[1] == 0){
Toast.makeText(this, R.string.write_calendar_permission, Toast.LENGTH_LONG).show();
AccessCalendar accessCalendar = new AccessCalendar();
accessCalendar.createCalendar(mContext, this);
//get calendar information again to see if petrecords calendar was created
Log.d(TAG, "get the calendars in the system to see if petrecords now exists");
accessCalendar.getCalendars(mContext, this);
}else{
Toast.makeText(this, R.string.error_no_write_calendar_permission, Toast.LENGTH_LONG).show();
Log.d(TAG, "create alertdialog to explain why the permission is required");
}
}else{
Log.d(TAG, "no permissions returned");
}
break;
default:
Log.d(TAG, "illegal requestCode value");
break;
}
return;
}
In that case, a new calendar is created. Otherwise, the user proceeds after Denying. Later, the user is presented with Appointments and may, at that point, desire to add an appointment via my app and so clicks the Appointment tab and then the Manage Appointments button. At that point, precisely the same code is entered to check calendar permissions as shown above.
At that point I expect to be presented with the secondary permissions dialog, but no, all I get is my explanation. I would also expect to see the secondary permissions dialog when I relaunch my app after initially Denying, but no.
So, why doesn't Android ever present the secondary permissions dialog?
The shouldShowRequestPermissionRationale() method implies that the permission was rejected before and that you should explain why you're asking for the permissions.
For this you should use a Dialog or Snackbar with an action the user can use to trigger the permission request again.
If you're app doesn't work without this permission, you might want to show a bigger screen explaining that the app doesn't work without.
You could even ignore the shouldShowRequestPermissionRationale() flag and just show the permission request again and again. That's very annoying though.
I am working on Account manager. I want to check account is exists or not.
private static final String TAG = "UserAccountUtil";
public static Account getAccount(Context context) {
if (ActivityCompat.checkSelfPermission(context, android.Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "GET_ACCOUNTS not present.");
}
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccountsByType(Constant.ACCOUNT_TYPE);
if (accounts.length > 0) {
Log.d(TAG, "GET_ACCOUNTS present..."+accounts[0]);
return accounts[0];
} else {
Log.d(TAG, "GET_ACCOUNTS not present...");
return null;
}
}
It always returns null or "GET_ACCOUNTS not present." in logs. I have added in manifest also.I am asking for run time permission also.
GET_ACCOUNTS--> Beginning with Android 6.0 (API level 23), if an app shares the
signature of the authenticator that manages an account, it does not
need "GET_ACCOUNTS" permission to read information about that account.
On Android 5.1 and lower, all apps need "GET_ACCOUNTS" permission to
read information about any account.The GET_ACCOUNTS permission is now Dead
You can use READ_CONTACTS permission instead of.
Check to Build.VERSION.SDK_INT
DEMO
if (accounts.length > 0 && android.os.Build.VERSION.SDK_INT<23 ) {
Log.d(TAG, "GET_ACCOUNTS present..."+accounts[0]);
return accounts[0];
} else {
Log.d(TAG, "GET_ACCOUNTS not present...");
return null;
}
I am writing an app to send msg over TCP Socket. I am struggling to get access to the internet permission. (API 26 is the target)
socket EACCESS permission denied
I have setup in my Manfest :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.seb.sebastien.opengardenirc">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.persmission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
As I am using the API26, I have to add a permission check in the code to make sure it works fine:
if (shouldAskPermission()) {
Log.d(TAG, "Permission is required");
String[] PERMISSIONS_STORAGE = {
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_WIFI_STATE
};
int permission_internet = ActivityCompat.checkSelfPermission(this, Manifest.permission.INTERNET);
int permission_network = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE);
int permission_wifi = ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE);
Log.d(TAG, "Package Manager: " + PackageManager.PERMISSION_GRANTED);
Log.d(TAG, "INTERNET : " + permission_internet);
Log.d(TAG, "NETWORK : " + permission_network);
Log.d(TAG, "WIFI : " + permission_wifi);
if ((permission_internet != PackageManager.PERMISSION_GRANTED)
|| (permission_network != PackageManager.PERMISSION_GRANTED)
|| (permission_wifi != PackageManager.PERMISSION_GRANTED)){
Log.d(TAG, "Asking for permission");
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
this,
PERMISSIONS_STORAGE,
REQUEST_CONNECTION_PERMISSION
);
} else {
Toast.makeText(MainActivity.this, "Permission (already) Granted!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Permission already granted");
startTcpInAThread("str");
}
}
And I have also the method to catch the onRequestPermissionsResult.
private boolean shouldAskPermission(){
return(Build.VERSION.SDK_INT> Build.VERSION_CODES.LOLLIPOP_MR1);
}
#Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case REQUEST_CONNECTION_PERMISSION:
Log.d(TAG, "Permission granted result : " + grantResults[0]);
Log.d(TAG, "Permission granted result : " + grantResults[1]);
Log.d(TAG, "Permission granted result : " + grantResults[2]);
boolean accepted = (grantResults[0]== PackageManager.PERMISSION_GRANTED)
&& (grantResults[1]== PackageManager.PERMISSION_GRANTED)
&& (grantResults[2]== PackageManager.PERMISSION_GRANTED);
if(accepted) {
startTcpInAThread("str");
} else {
Toast.makeText(getApplicationContext(), "Permissions issues!!!!", Toast.LENGTH_SHORT).show();
}
break;
}
}
First things is that when checking the permission, I can see that android.persmission.INTERNETis not granted. Good thing is that it's going to call the request permission method ActivityCompat.requestPermissions
I was expecting a Dialog box showing up but my understanding is that the dlgbox only show up for some on the permission requests some other do not need to ask.
My concerns is that when I got onRequestPermissionsResultthe permission is still not granted.
Anybody know how to grant the permission to internet ?
I have also pay attention to not run the network access in the same thread.
Regards
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.