I am working on android application in which I need to ask a user for Contact permission before uploading contacts. Below is the code which I am using for Contacts Permission for Build.VERSION.SDK_INT >= Build.VERSION_CODES.M.
But the problem is I need to ask for the Contact Permission every time even below to Android M always. How to ask for Contact Permission which should work on all SDK Versions?
private void getContact(){
// Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
// startActivityForResult(intent, PICK_CONTACT);
}
public void askForContactPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_CONTACTS)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Contacts access needed");
builder.setPositiveButton(android.R.string.ok, null);
builder.setMessage("please confirm Contacts access");//TODO put real question
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(
new String[]
{Manifest.permission.READ_CONTACTS}
, PERMISSION_REQUEST_CONTACT);
}
});
builder.show();
// 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(this,
new String[]{Manifest.permission.READ_CONTACTS},
PERMISSION_REQUEST_CONTACT);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}else{
getContact();
}
}
else{
getContact();
}
}
int PERMISSION_REQUEST_CONTACT = 1;
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// getContact();
Toast.makeText(getApplicationContext(),"Permission is Done",Toast.LENGTH_LONG).show();
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
Toast.makeText(getApplicationContext(),"No permission for contacts",Toast.LENGTH_LONG).show();
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Create a method for showing a permission request dialog, that always shows the dialog, but only calls the permission API on Android M and above:
public void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Contacts access needed");
builder.setPositiveButton(android.R.string.ok, null);
builder.setMessage("please confirm Contacts access");
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// Only call the permission request api on Android M
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSION_REQUEST_CONTACT);
}
}
});
builder.show();
}
Then on Android M and above, only call it when needed, below M, always call it:
public void askForContactPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_CONTACTS)) {
showDialog();
}
}
} else {
showDialog();
}
}
Related
I'm working on checking and getting permission from user with API level 23 and above. So here is a confusing thing for me, android.com says:
shouldShowRequestPermissionRationale() method returns true if the app has requested this permission previously and the user denied the request.
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
in other side it gives following code for checking permission and request permission if its neccessery
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// 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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
else scope in above example runs if user doesn't allow permission and check Don't Ask Again, Right? So with this code user never being asked for permission at first time run. I tested that code and the result is what I expected.
So How could I request permission for first time run and do something if user previously denied my request and do something if user deny my request and check Don't Ask Again?
You can do the following.
Ask permission every time by only checking that permission is not granted already. Don't handle the "Don't ask again" in this method. (if user checks "Don't ask again" the OS will automatically handle and will not ask for permission again and will give a call back of permission denied)
Handle the ActivityCompat.shouldShowRequestPermissionRationale() in the call back method onRequestPermissionsResult().
Here is my code in which I am asking for permission everytime
public void checkAndAskCameraPermission() {
if (ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(context,
new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_ID);
}
}
This is how I handles the call back
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case CAMERA_PERMISSION_REQUEST_ID: {
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
// Do something if permission is not granted and the user has also checked the **"Don't ask again"**
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
// Do something if permission not granted
}
}
}
}
first check if the permission is granted then do what you need
else if permission is denied then check weather you should request the permission you need or not through shouldShowRequestPermissionRationale.
if shouldShowRequestPermissionRationale return false then you can just show a message to the user to told them to enable the permission manually.
other then if shouldShowRequestPermissionRationale return true then request the permission and get the result of granting permission in onRequestPermissionsResult
update , this is just a simple code to show the steps:
if (checkSelfPermission == granted){
// do what you want
} else if (shouldShowRequestPermissionRationale == true) {
// you can request the permission you want from the user, then check whether permission granted or not inside onRequestPermissionsResult method
} else {
// here you know the permission is not granted , and also the user check on "Dont ask Again!" checkbox, so all you can to do is just tell the user to enable the permission manually from app permissions through Toast message or any thing else
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initilize your views
if(iscontactsAllowed){
// do your code here
} else {
requestcontactsPermission();
}
}
private void requestcontactsPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.READ_CONTACTS)) {
//If the user has denied the permission previously your code will come to this block
//Here you can explain why you need this permission
//Explain here why you need this permission
Log.d("scancode", "denied permission before");
}
Log.d("perm", "fourth");
//And finally ask for the permission
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_CONTACTS}, READ_CONTACTS_CODE /*can be any interge */);
}
private boolean iscontactsAllowed() {
//Getting the permission status
int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS);
//If permission is granted returning true
if (result == PackageManager.PERMISSION_GRANTED)
return true;
//If permission is not granted returning false
return false;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
//Checking the request code of our request
if(requestCode == READ_CONTACTS_CODE){
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// you have the permission call yur method here
} else {
// permission denied show user why you need it or ask again by calling reuestpermission if you need the permission
}
}
#ArtinArtin I have expanded on #salmanyahya updated simple code and provided my logic with Alert Dialog's and one Snackbar (not a big fan of Snackbar's) any way see if this helps
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
//.... write file into storage ...
System.out.println("SDK > BuildVersion TRUE");
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 666); // Comment 26
System.out.println("go to requestPermissions");
}
}
onLoad();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 666: // Allowed was selected so Permission granted
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Snackbar s = Snackbar.make(findViewById(android.R.id.content),"Permission Granted",Snackbar.LENGTH_LONG);
View snackbarView = s.getView();
TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
textView.setTextColor(Color.RED);
textView.setTextSize(18);
textView.setMaxLines(6);
s.show();
// do your work here
} else if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
// User selected the Never Ask Again Option Change settings in app settings manually
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Change Permissions in Settings");
alertDialogBuilder
.setMessage("" +
"\nClick SETTINGS to Manually Set\n"+"Permissions to use Database Storage")
.setCancelable(false)
.setPositiveButton("SETTINGS", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 1000); // Comment 3.
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
} else {
// User selected Deny Dialog to EXIT App ==> OR <== RETRY to have a second chance to Allow Permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("Second Chance");
alertDialogBuilder
.setMessage("Click RETRY to Set Permissions to Allow\n\n"+"Click EXIT to the Close App")
.setCancelable(false)
.setPositiveButton("RETRY", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//ActivityCompat.requestPermissions((Activity) context, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, Integer.parseInt(WRITE_EXTERNAL_STORAGE));
Intent i = new Intent(MainActivity.this,MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
})
.setNegativeButton("EXIT", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
break;
}};
This code helps to handles the run time permission Management in Android
public String storagePermissions = Manifest.permission.READ_EXTERNAL_STORAGE;
private static final int REQUEST_ACCESS =101;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(checkSelfPermission(storagePermissions)== PackageManager.PERMISSION_GRANTED){
result(); // result is your block of code
}else {
requestPermissions(new String[]{storagePermissions},REQUEST_ACCESS);
}
}
else{
result(); //so if user is lower than api verison M, no permission is requested
}
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setTitle("Hi User..")
.setPositiveButton("Ok", okListener)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) { //idea calling showMessage funtion again
Snackbar mySnackbar = Snackbar.make( findViewById(R.id.coordinatorlayout),"You Press Cancel.. ", Snackbar.LENGTH_INDEFINITE);
mySnackbar.setAction("Exit", new cancelButton());
mySnackbar.show();
}
})
.create()
.show();
}
private void result(){
//your code
}
#RequiresApi(api = Build.VERSION_CODES.M)
public class NeverAskAgain implements View.OnClickListener{
#Override
public void onClick(View view)
{
goToSettings();
}
}
#RequiresApi(api = Build.VERSION_CODES.M)
private void goToSettings() {
Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName()));
finish();
myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityForResult(myAppSettings, REQUEST_APP_SETTINGS);
}
public class cancelButton implements View.OnClickListener{
#Override
public void onClick(View view){
Toast.makeText(MainActivity.this,"To use this app , you must grant storage permission",Toast.LENGTH_SHORT);
finish();
}
}
#Override
#RequiresApi(api = Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode,permissions,grantResults);
switch(requestCode) {
case REQUEST_ACCESS:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission is granted
result();
break;
}
else if (!shouldShowRequestPermissionRationale(permissions[0])){
showMessageOKCancel("You choose Never Ask Again,option",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Snackbar mySnackbar = Snackbar.make(findViewById(R.id.coordinatorlayout), "Permission=>Storage=>On", Snackbar.LENGTH_INDEFINITE);
mySnackbar.setAction("Settings", new NeverAskAgain());
mySnackbar.show();
}
});
break;
}
else {
showMessageOKCancel("You Denid permission Request..",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{storagePermissions}, REQUEST_ACCESS);
}
});
break;
}
}
}
What I have found is that shouldShowRequestPermissionRationale only returns true if the user has denied permission (at least once) and not selected "Don't Ask Again". Meaning, it won't be displayed on the first time the permission is requested either.
Previously the below code works fine even on The Marshmellow but yesterday i got this eror first time Screen Overlay Detected while i am getting the Run time Location permission and during onPause() it W/Activity: Can reqeust only one set of permissions at a time and after that crash please help me i even follow so many answers but none is solved my problem.
Code:
OnCreate :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isGooglePlayServicesAvailable()) {
Toast.makeText(getApplicationContext(),"Install Google Play Service",Toast.LENGTH_SHORT).show();
finish();
}
Boolean bool = checkPermission();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Log.e("overlayPro", String.valueOf(Settings.canDrawOverlays(this)));
}
setContentView(R.layout.activity_find_service_providers);
linearLayout =(LinearLayout)findViewById(R.id.linearlayout);
Intent intent = getIntent();
if(null!=intent.getExtras()) {
//get Intent value
}
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
onStart() :
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkPermission()) {
mapFrag.getMapAsync(this);
if (!Utility.isLocationEnabled(getApplicationContext())) {
setingsrequest();
}
} else {
checkLocationPermission();
}
}
else if (!Utility.isLocationEnabled(getApplicationContext())){
mapFrag.getMapAsync(this);
setingsrequest();
}
else {
mapFrag.getMapAsync(this);
}
}
checkPermission() :
private boolean checkPermission() {
return ( ContextCompat.checkSelfPermission(getApplicationContext(),Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
}
settingRequest():
public void setingsrequest()
{
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true); //this is the key ingredient
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
linearLayout.setVisibility(View.VISIBLE);
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(FindServiceProviders.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
break;
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PERM_REQUEST_CODE_DRAW_OVERLAYS) {
if (android.os.Build.VERSION.SDK_INT >= 23) { //Android M Or Over
if (!Settings.canDrawOverlays(this)) {
Log.e("overlayResult","false");
// ADD UI FOR USER TO KNOW THAT UI for SYSTEM_ALERT_WINDOW permission was not granted earlier...
}
}
}
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
linearLayout.setVisibility(View.VISIBLE);
mapFrag.getMapAsync(this);
break;
case Activity.RESULT_CANCELED:
//setingsrequest();//keep asking if imp or do whatever
finish();
break;
}
break;
}
}
checkLocationPermission()
private void checkLocationPermission() {
if (!checkPermission()) {
// 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, R.style.MyDialogTheme)
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(FindServiceProviders.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
})
.create()
.show();
} else {
Log.e("overlay","detected but Request New Permission");
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String permissions[],#NonNull 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 (checkPermission()) {
//allowed
Log.e("allowed", String.valueOf(permissions));
if (!Utility.isLocationEnabled(getApplicationContext())) {
setingsrequest();
}
if (mGoogleApiClient == null) {
buildGoogleApiClient();
}
mapFrag.getMapAsync(this);
}else{
//set to never ask again
Log.e("set to never ask again", String.valueOf(permissions));
//do something here.
}
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
checkLocationPermission();
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Updated Code :
#Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults) {
switch (permsRequestCode) {
case R_PERM: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
PermHandling();
}
else if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
//Previously Permission Request was cancelled with 'Dont Ask Again',
// Redirect to Settings after showing Information about why you need the permission
AlertDialog.Builder builder = new AlertDialog.Builder(TestActivity.this,R.style.MyDialogTheme);
builder.setTitle("Need Storage Permission");
builder.setMessage("This app needs storage permission.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
sentToSettings = true;
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
// Toast.makeText(getBaseContext(), "Go to Permissions to Grant Storage", Toast.LENGTH_LONG).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
}
else {
new AlertDialog.Builder(this,R.style.MyDialogTheme)
.setTitle("Location Permission Needed")
.setMessage("This app needs the Location permission, please accept to use location functionality")
.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(TestActivity.this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
R_PERM );
}
})
.create()
.show();
}
return;
}
}
}
In onActivityResult :
if (requestCode == REQUEST_PERMISSION_SETTING) {
if (ActivityCompat.checkSelfPermission(TestActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
proceedAfterPermission();
}
}
I am working on a demo application that ask run time permission on android
Marshmallow . I just when when user denial the permission user get an alert dialog again again or at least five clicks . If he denied more than five time application would stop.
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getSupportActionBar();
if(null != actionBar){
actionBar.hide();
}
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_INTERNET);
}
htmlWebView = (WebView)findViewById(R.id.webView);
assert htmlWebView != null;
WebSettings webSetting = htmlWebView.getSettings();
webSetting.setJavaScriptEnabled(true);
webSetting.setDisplayZoomControls(true);
htmlWebView.setWebViewClient(new CustomWebViewClient());
htmlWebView.loadUrl("https://inducesmile.com/blog");
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_INTERNET) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
//start audio recording or whatever you planned to do
}else if (grantResults[0] == PackageManager.PERMISSION_DENIED){
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.RECORD_AUDIO)) {
//Show an explanation to the user *asynchronously*
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("This permission is important to record audio.")
.setTitle("Important permission required");
builder.setNegativeButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_INTERNET);
dialog.dismiss();
}
}
);
builder.show();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_INTERNET);
}else{
//Never ask again and handle your app without permission.
}
}
}
}
Thanks for any help .
try this code:
int count =0;
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case REQUEST_INTERNET: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//do your task here
} else {
permission_denied();
}
break;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
public void permission_denied() {
// permission was not granted
//permission is denied (this is the first time, when "never ask again" is not checked) so ask again explaining the usage of permission
// shouldShowRequestPermissionRationale will return true
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.RECORD_AUDIO)) {
showDialogOK("This permission is important to record audio.",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
//user enables permisssion do your task..
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
if(count==5){
finish();
//finish activity
}
else{
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.RECORD_AUDIO}, REQUEST_INTERNET);
++count;
}
break;
}
}
});
} //permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(getApplicationContext(), "Go to settings and enable record audio permissions", Toast.LENGTH_LONG).show();
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(Mainactivity.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
If user press Never ask again.. permission dialog will not show again
This is expected behaviour.
From the documentation:
When the system asks the user to grant a permission, the user has the
option of telling the system not to ask for that permission again. In
that case, any time an app uses requestPermissions() to ask for that
permission again, the system immediately denies the request. The
system calls your onRequestPermissionsResult() callback method and
passes PERMISSION_DENIED, the same way it would if the user had
explicitly rejected your request again. This means that when you call
requestPermissions(), you cannot assume that any direct interaction
with the user has taken place.
see this also:Does checking the Never ask again box when asking for a runtime permission disable future dialogs?
I am trying to access the users locations and just sorting out the permission side of things. So my understanding is that on 23 and above regardless of the manifest the user must grant permission.
So I have it in the manifest like this for older versions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
For the newer >= 23 I am testing like this before showing a dialog:
// Check for runtime location permissions
private boolean hasRunTimeLocationPermission() {
int courseLocationPermission = ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.ACCESS_COARSE_LOCATION);
return (courseLocationPermission == PackageManager.PERMISSION_GRANTED );
}
The way I understood it that should return false the first time but it is returning true.
Does the user actually have to disable location services or is it considered 'dangerous" and it have to be approved the first time?
Also I am using a new emulator api 23, when I look into location permissions it says no apps have requested location.
Thanks for your help
Try this.
// Check for runtime location permissions
private boolean hasRunTimeLocationPermission() {
int courseLocationPermission = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_COARSE_LOCATION);
return (courseLocationPermission == PackageManager.PERMISSION_GRANTED );
}
TRY THIS:
private boolean hasRunTimeLocationPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
{
return false;
}
else
{
return true;
}
}
Check permissions like this :-
Check permissions like this :-
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
//Show Information about why you need the permission
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Need Location Permission");
builder.setMessage("This app needs location permission.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, ACCESS_COARSE_LOCATION_CONSTANT);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
} else if (permissionStatus.getBoolean(Manifest.permission.ACCESS_COARSE_LOCATION,false)) {
//Previously Permission Request was cancelled with 'Dont Ask Again',
// Redirect to Settings after showing Information about why you need the permission
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Need Location Permission");
builder.setMessage("This app needs location permission.");
builder.setPositiveButton("Grant", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
sentToSettings = true;
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, REQUEST_PERMISSION_SETTING);
Toast.makeText(getBaseContext(), "Go to Permissions to Grant Location", Toast.LENGTH_LONG).show();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
} else {
//just request the permission
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, ACCESS_COARSE_LOCATION_CONSTANT);
}
SharedPreferences.Editor editor = permissionStatus.edit();
editor.putBoolean(Manifest.permission.ACCESS_COARSE_LOCATION,true);
editor.commit();
} else {
//You already have the permission, just go ahead.
proceedAfterPermission();
}
Add this to Manifest even for api>23
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
And then ask for runtime permissions like this :-
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
1);
And to handle the restults, use this:-
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// 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 {
// permission denied, boo!
Toast.makeText(MainActivity.this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show();
}
return;
}
}
}
I want to check how new permission model works so in app's settings I disable Contacts. Then I go to app and try to read Contacts and ... it kinda works:
try {
Uri result = data.getData();
int contentIdx;
cursor = getContentResolver().query(result, null, null, null, null);
contentIdx = cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
if(cursor.moveToFirst()) {
content = cursor.getInt(contentIdx);
}
if(content > 0) {
contentIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
if(cursor.moveToFirst()) {
name = cursor.getString(contentIdx);
}
contentIdx = cursor.getColumnIndex(BaseColumns._ID);
if(cursor.moveToFirst()) {
content = cursor.getLong(contentIdx);
}
cursor = managedQuery(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, new String[] { Phone.NUMBER }, Data.CONTACT_ID + "=?", new String[] { String.valueOf(content) }, null);
if(cursor.moveToFirst()) {
number = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
}
}
} catch (Exception e) {
//SecurityException
}
I'm able to read Contact's Name
when I try to read Contact's Number SecurityException is thrown
java.lang.SecurityException: Permission Denial: reading com.android.providers.contacts.HtcContactsProvider2 uri content://com.android.contacts/data/phones from pid=20123, uid=10593 requires android.permission.READ_CONTACTS, or grantUriPermission()
Why is that?
Related stuff: Contact data leakage via pick activities
Android marshmallow have new permissions system.
You need to request permissions at run time.
http://developer.android.com/training/permissions/requesting.html.
Example:
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.tv_contact:{
askForContactPermission();
break;
}
}
}
private void getContact(){
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, PICK_CONTACT);
}
public void askForContactPermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(getActivity(),Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
Manifest.permission.READ_CONTACTS)) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Contacts access needed");
builder.setPositiveButton(android.R.string.ok, null);
builder.setMessage("please confirm Contacts access");//TODO put real question
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#TargetApi(Build.VERSION_CODES.M)
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(
new String[]
{Manifest.permission.READ_CONTACTS}
, PERMISSION_REQUEST_CONTACT);
}
});
builder.show();
// 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(getActivity(),
new String[]{Manifest.permission.READ_CONTACTS},
PERMISSION_REQUEST_CONTACT);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}else{
getContact();
}
}
else{
getContact();
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CONTACT: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getContact();
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
ToastMaster.showMessage(getActivity(),"No permission for contacts");
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}