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

Google Analytics Android Real Time
Helper Activity to display Fragment?
I want to change .android folder [duplicate]
How set height to spinner in action bar
How to disable the automatic saving and loading of the screen state by android when I return to my previously opened app?
Prevent IME (Soft keyboard) from leaving the application
How to set the affinity of a task on a single core of multi-core GPGPU (Android)
Regarding your app is statically linking against a version of OpenSSL
I want to return to a previous activity, even though I have code in it that skips it
How to obtain transaction id or other information in paypal mobile SDK
Android Toolbar Navigation icon doesnt change back to “3 lines” icon when returning to main screen
Bitmap decodeResource - out-of-memory crash on Samsung S5
Disable all MapView gestures and add an OnClickListener to the MapView
Android Activity container not replaced
Show “Loading…” dialog in onCreateView
Android - Remove deceleration of fling in Scroller

Categories

HOME
eclipse
phpword
assembly
twitter-bootstrap-3
3d
scripting
interpolation
crystal-lang
vert.x
flume
special-characters
performancepoint
syntaxnet
reactive-programming
distribution
text-mining
libusb
sse
drive
undertow
backpack-for-laravel
react-toolbox
inno-download-plugin
onload
fat
android-sharedpreferences
shared
jackson-modules
progress-bar
linked-data
rpgle
winexe
testcomplete
boost-asio
mobx
recurring-events
mustache
cognos-bi
sammy.js
reactjs.net
sharepoint-workflow
microsoft-metro
wc
ovf
clarifai
gitlist
wcftestclient
google-cse
modelsim
opengl-4
rackspace-cloud
offline.js
gets
node-request
stax
flex-monkey
dimension
appscale
freepbx
spreadjs
yajsw
ellucian-scribe
blitline
piracy-prevention
sciruby
qt5.2
ess
morton-number
include-guards
mod-proxy
haskell-warp
skspritenode
mraid
node-serialport
diff3
shopizer
dot.js
phpldapadmin
showdialog
imagefilter
nsmenu
mobility
ss7
personalization
mutual-authentication
square-bracket
sbcl
android-icons
stacky
preload
wimax
zope.interface
thttpd
lambdaj
appjs
multiplexing
oracle-enterprise-linux
window-decoration
flex-mobile
webdev.webserver
timthumb
codebase
isapi-extension
wordprocessingml
soappy

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