android


Android shouldShowRequestPermissionRationale has a bug?


I think there is a bug shouldShowRequestPermissionRationale
Code is...
#Override
protected void onResume() {
super.onResume();
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED &&
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION) ||
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
new AlertDialog.Builder(this)....show();
} else {
// do something...
}
Installed the app first, We do not allow the permission. So when onResume is called, AlertDialog should appears. But it's not appear...
If we go into the setting of the app, and allow the permission. So We play the app code(// do something). Again, we go into the setting of the app, Deny the permission. And we restart the app, AlertDialog appears.
Why the app runs like this ?
From Developers Docs :
shouldShowRequestPermissionRationale()
This method returns true if the app has requested this permission previously and the user denied the request.
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 issue is that you haven't requested the permission before using
ActivityCompat.requestPermissions();
Hence its not showing the dialog.
When you manually give permission or deny permission from Settings its assumed that you denied the permission and thats why it showing the Alert Dialog.
Worked with Gmail API and found another option in its sample code regarding Android permissions. You may want to use EasyPermissions which was provided by Google itself, to, as said, "Simplify Android M system permissions".
Check this implementation. is working pretty good for me. basically you check the permissions in the checkPermissions() method passing a list of permissions. You check the result of the permission request on onRequestPermissionsResult(). The implementation lets u address both case when user selects "never ask again" or not. In this implementation, in case se selects "never ask again", the dialog has an option to take him to the App Settings Activity.
All this code is inside my fragment. I was thinking that would be better to create a specialised class to do this, like a PermissionManager, but i'm not sure about it.
/**
* responsible for checking if permissions are granted. In case permissions are not granted, the user will be requested and the method returns false. In case we have all permissions, the method return true.
* The response of the request for the permissions is going to be handled in the onRequestPermissionsResult() method
* #param permissions list of permissions to be checked if are granted onRequestPermissionsResult().
* #param requestCode request code to identify this request in
* #return true case we already have all permissions. false in case we had to prompt the user for it.
*/
private boolean checkPermissions(List<String> permissions, int requestCode) {
List<String> permissionsNotGranted = new ArrayList<>();
for (String permission : permissions) {
if (ContextCompat.checkSelfPermission(getActivity(), permission) != PackageManager.PERMISSION_GRANTED)
permissionsNotGranted.add(permission);
}
//If there is any permission we don't have (it's going to be in permissionsNotGranted List) , we need to request.
if (!permissionsNotGranted.isEmpty()) {
requestPermissions(permissionsNotGranted.toArray(new String[permissionsNotGranted.size()]), requestCode);
return false;
}
return true;
}
/**
* called after permissions are requested to the user. This is called always, either
* has granted or not the permissions.
* #param requestCode int code used to identify the request made. Was passed as parameter in the
* requestPermissions() call.
* #param permissions Array containing the permissions asked to the user.
* #param grantResults Array containing the results of the permissions requested to the user.
*/
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case YOUR_REQUEST_CODE: {
boolean anyPermissionDenied = false;
boolean neverAskAgainSelected = false;
// Check if any permission asked has been denied
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
anyPermissionDenied = true;
//check if user select "never ask again" when denying any permission
if (!shouldShowRequestPermissionRationale(permissions[i])) {
neverAskAgainSelected = true;
}
}
}
if (!anyPermissionDenied) {
// All Permissions asked were granted! Yey!
// DO YOUR STUFF
} else {
// the user has just denied one or all of the permissions
// use this message to explain why he needs to grant these permissions in order to proceed
String message = "";
DialogInterface.OnClickListener listener = null;
if (neverAskAgainSelected) {
//This message is displayed after the user has checked never ask again checkbox.
message = getString(R.string.permission_denied_never_ask_again_dialog_message);
listener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//this will be executed if User clicks OK button. This is gonna take the user to the App Settings
startAppSettingsConfigActivity();
}
};
} else {
//This message is displayed while the user hasn't checked never ask again checkbox.
message = getString(R.string.permission_denied_dialog_message);
}
new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
.setMessage(message)
.setPositiveButton(getString(R.string.label_Ok), listener)
.setNegativeButton(getString(R.string.label_cancel), null)
.create()
.show();
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
/**
* start the App Settings Activity so that the user can change
* settings related to the application such as permissions.
*/
private void startAppSettingsConfigActivity() {
final Intent i = new Intent();
i.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + getActivity().getPackageName()));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
getActivity().startActivity(i);
}
Understand the control flow of runtime permissions
if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_DENIED &&
ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION) ||
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
//Block1
} else {
//Block2
}
}else{
//Do something here
}
there are the cases when Block1 and Block2 will be call
case 1: when every we try to show permission popup for the first time (permission dialog will not display never ask again check box) Block2 will be called.
case 2: If user Deny first time, if you call the same code from next time (second time onward) Block1 will be called and shows dialog with never ask again check box.
case 3: If you check never ask again then from that time if you execute the same code it will call Block2 but not display dialog/popup directly it will trigger DENY automatically and onRequestPermissionsResult method will fire with deny.

Related Links

How to load image from writeable folder and assign to ImageView in Android?
EditText updates items on ListView with TextWatcher
FTDriver.java mDevice null error
How to use Android NavigationDrawer to create other fragments?
Android Studio resource not found after duplicate
ListView scroll position jumps to first element after notifydatasetchanged
Finger print lock in Android
Why doesn't my BTLE virtual beacon show in Chrome?
Android View Id's
Xamarin Costs to Publish on Google Play Store
UnsupportedOperationException on TextInputLayout when type count exceeded counterMaxLength
set an image background on a scrolling activity
Scale my item image to fit the screen properly
There are app requesting if any other app request internet?
Mapbox for Android: Changing color of a marker's icon
How to implements Native Ad by Google on RecyclerView Android?

Categories

HOME
google-app-engine
microsoftgraph
gridview
nvd3.js
dns
youtube-data-api-v3
saml-2.0
package
can
cq5
cakephp-3.4
square
lanczos
reactive-programming
github-enterprise
project-intu
line
3nf
android-intent
coin3d
linear-algebra
glyphicons
wolframalpha
windows-xp
breadth-first-search
gulp-watch
strongname
siri
google-cloud-print
stackexchange
handler
cppreference
calculation
dotspatial
gitlab-api
powershell-ise
left-join
jmockit
roblox
latitude-longitude
connection-pool
password-protection
signals-slots
stringtokenizer
wmp
contract
signal-strength
mesosphere
lampp
amq
template-toolkit
jtree
django-1.10
reachability
cudd
jodd
cfchart
angular-ui-typeahead
cda
createprocess
ellucian-scribe
nupic
asyncdisplaykit
gocql
coda
vacuum
graphics2d
mraid
deform
build-script
ray
radiant
renderer
accesscontrolexception
gwt-openlayers
gd-graph
windows-phone-8-sdk
model-driven-development
ice-cube
stacky
booksleeve
robotlegs
pstack
database-create
window-decoration
kqueue
winmain
update-statement
django-paypal
load-time
jqueryform
alsb
entitykey
wspbuilder

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App