I want to send SMS by android-app, but the permission dialog show before the send a message every time, I supposed to send a message without dialog show after the first permission asked.
My android app is run on mi-8, target SDK-version is 29.
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.SEND_SMS}, 3);
} else if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_PHONE_STATE}, 4);
} else {
sendMsg();
}
I expect the permission dialog did not show when I send a message after the first asked permission, but actual every time show dialog when I send a message .
use this function to check whether you have given the permission if say so you have given as required persmission it will return true flag
check by this way
private boolean checkAndRequestPermissions(){
//add as much as permission you need
int readSMS = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS);
int sendSms = ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS);
List<String> listPermissionsNeeded = new ArrayList<>();
if (readSMS != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_SMS);
}
if (receiveSms != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.RECEIVE_SMS);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]),
REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
check by this way
if (checkAndRequestPermissions()){
sendMsg();
}else{
//do what you want
}
no need to do this by hardcode way
Related
I need 2 permissions for my app= Location and Record Audio. I check, if it was granted, if no, I ask for permission. The code, where I ask for permisssion looks like this=
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// ask for permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListener);
}
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
// ask for permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 2);
}
}
My onRequestPermissionsResult method looks like this=
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListener);
}
}
case 2:
permissionToRecordAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
}
When i install the apk on my phone and change to that activity, where I need this 2 permissions, the app crashes in the background, but the permission windows for location is still open,when I grant it and reopen the app, change to that activity, I just have to give Location permission and everything works fine. Why does my app crash? When I only had location permission, it worked fine, after inserting audio record permission, it closes. When I run this on my emulator, it doesnt crash.
you should requestPermissions once with array of all needed permissions and you have two separated calls - second one will be called, when your app is already in background (because dialog with location permission appeared)
easiest fix would be adding return in proper place for checking is this the case (without stacktrace of exception its hard to guess)
if (Build.VERSION.SDK_INT >= 23) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// ask for permission
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
return; // return in here
} else {
///... rest of code
better approach would be summing up all needed permissions and calling requestPErmissions once
if (Build.VERSION.SDK_INT >= 23) {
boolean needLocPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED;
boolean needAudioPerm = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED;
String[] permsArray = null;
if(needAudioPerm && needLocPerm ){
permsArray = new String[]{Manifest.permission.RECORD_AUDIO,
Manifest.permission.ACCESS_FINE_LOCATION};
}
else if(needAudioPerm){
permsArray = new String[]{Manifest.permission.RECORD_AUDIO};
}
else if(needLocPerm ){
permsArray = new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
}
if(permsArray!=null && permsArray.length>0)
ActivityCompat.requestPermissions(this, permsArray, 123);
else locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, locationListener);
}
after this code improvement you should refactor your onRequestPermissionsResult method and check which permissions were granted (inspect String[] permissions and int[] grantResults arrays)
without a stacktrace of exception this is only guess, besides above problem everything looks fine, but there is a chance your exception is fired by some call made in another method, e.g. onPause
I'm working on an app that collects data for processing, as such it requires multiple dangerous permissions (namely ACCESS_FINE_LOCATION and READ_PHONE_STATE). At the moment it requests one then crashes.
I have tried requesting the permissions separately using ActivityCompat.requestPermissions, and I have tried having both of the permissions in the array. I have also tried using the request codes 0,1 and 7 as I saw these used in different answers to similar questions on this topic, but nothing seems to change.
private void setupPermissions() {
ArrayList<String> permissions = new ArrayList<>();
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.READ_PHONE_STATE);
}
if (permissions.size()>0){
ActivityCompat.requestPermissions(getActivity(), permissions.toArray(new String[permissions.size()]), 7);
}
}
Expected results:
Upon first opening the app both permissions should be requested for, either by two separate dialog boxes (one after the other) or by a multiple page dialog box.
The app should then run as expected
Actual results:
requests the first
allows you to continue with the app
crashes when you try to use a feature that requires the second
reopen app
requests the second
allows app to continue as normal
Call this checkAndRequestPermissions() Method whenevr you want permission
private boolean checkAndRequestPermissions() {
int ACCESS_FINE_LOCATION = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
int READ_PHONE_STATE = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (READ_PHONE_STATE != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_PHONE_STATE);
}
if (ACCESS_FINE_LOCATION != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray
(new String[listPermissionsNeeded.size()]), 101);
return false;
}
return true;
}
Try out the following code
(from this answer)
public static boolean hasPermissions(Context context, String... permissions) {
if (context != null && permissions != null) {
for (String permission : permissions) {
if (ActivityCompat.checkSelfPermission(context, permission) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
int PERMISSION_ALL = 1;
String[] PERMISSIONS = {
android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.READ_PHONESTATE
};
if(!hasPermissions(this, PERMISSIONS)){
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
In my code, I request:
int permissionCheck = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE);
int permissionCheck1 = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS);
int permissionCheck2 = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_CONTACTS);
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_PHONE_STATE}, 0);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, 2);
I also include:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case 0: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_PHONE_STATE}, 0);
}
return;
}
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
// contacts-related task you need to do.
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);
}
return;
}
case 2: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_CONTACTS}, 2);
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
When I run y app, I first get the request, and then, after a secon of not touching anything, my app crashes with the following error:
FATAL EXCEPTION: main
Process: com.example.ortel.tagnet, PID: 28445
java.lang.StackOverflowError: stack size 8MB
at com.example.ortel.tagnet.MainActivityOld.onRequestPermissionsResult(MainActivityOld.java:894)
at android.app.Activity.requestPermissions(Activity.java:4455)
at android.support.v4.app.ActivityCompat.requestPermissions(ActivityCompat.java:507)
at com.example.ortel.tagnet.MainActivityOld.onRequestPermissionsResult(MainActivityOld.java:894)
at android.app.Activity.requestPermissions(Activity.java:4455)
at android.support.v4.app.ActivityCompat.requestPermissions(ActivityCompat.java:507)
at com.example.ortel.tagnet.MainActivityOld.onRequestPermissionsResult(MainActivityOld.java:894)
at android.app.Activity.requestPermissions(Activity.java:4455)
at android.support.v4.app.ActivityCompat.requestPermissions(ActivityCompat.java:507)
at com.example.ortel.tagnet.MainActivityOld.onRequestPermissionsResult(MainActivityOld.java:894)
For Your Information, (MainActivityOld.java:894) is
ActivityCompat.requestPermissions(this, new
String[]{android.Manifest.permission.READ_PHONE_STATE}, 0);
What is happening? It seems that it keeps calling my request.
Shouldn't it wait for my answer?
EDIT: Please Address if you don't know why this is happening.
You can try to request all your permissions at once calling Activity.requestPermissions with input a String[] with all the 3 permission you need to ask, in your code you are actually prompting the system to require the permissions with 3 different dialogues as separate entities, maybe when the second permission request is executed it overrides the first one and create a loop that generate the StackOverflowException.
Example:
List <String> str = new ArrayList <> ();
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
str.add(Manifest.permission.READ_PHONE_STATE);
}
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
str.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
str.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
str.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
str.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (str.size() > 0) {
String[]strings = new String[str.size()];
str.toArray(strings);
ActivityCompat.requestPermissions(StartActivity.this,
strings,
PERMISSION_CODE_STATE);
}
And then in the callback receiving the result to check if you received all the permissions something like that or examine every grantResult manually:
boolean gotPermissions = true;
for (int i : grantResults) {
if (i != PackageManager.PERMISSION_GRANTED) {
gotPermissions = false;
break;
}
}
See this answer.
You have an infinite loop which I'm guessing is caused by someone denying Location permission, and selecting the "Never ask agan" checkbox
So I'm new to Android development and have a basic application that writes to a text file on it's first time loading. But because it is the application's first time loading it must first ask the user for read/write permissions. The problem I have is that the application tries to write the file before it has these permissions. I have the following MainActivity.java class that contains the section of code that requests for permissions:
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Stes fullscreen and removes title
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
setContentView(new Environment(this));
}
}
The constructor for Environment.jar then calls a function that writes the file if it does not yet exist.
But it seems that while the application does request permissions, it doesn't wait to receive these permissions before starting again. Is there any way to get it to wait to recieve the permissions, and if the permissions are not received to close the application?
You should call your Environment constructor only if the Permission is granted. Otherwise you can show an error dialog asking user to first grant permission before proceeding with the app. To check for permission You should request for permission as below -
Bool isPermissionGiven = false;
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED && checkSelfPermission(Manifest.permission. READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
Log.v(TAG,"Permission is granted");
isPermissionGiven = true;
} else {
Log.v(TAG,"Permission is revoked");
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
isPermissionGiven = false;
}
if (isPermissionGiven){
new Environment(this)
}
Then implement onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 0:
boolean isPerpermissionForAllGranted = false;
if (grantResults.length > 0 && permissions.length==grantResults.length) {
for (int i = 0; i < permissions.length; i++){
if (grantResults[i] == PackageManager.PERMISSION_GRANTED){
isPerpermissionForAllGranted=true;
}else{
isPerpermissionForAllGranted=false;
}
}
Log.e("value", "Permission Granted, Now you can use local drive .");
} else {
isPerpermissionForAllGranted=true;
Log.e("value", "Permission Denied, You cannot use local drive .");
}
if(isPerpermissionForAllGranted){
// Do your work here
new Environment(this);
}
break;
}
}
you should implment onRequestPermissionsResult() method
more here https://developer.android.com/training/permissions/requesting.html
Also its a violation of the android rules to terminate the app like that. You should just print something like this app requires this permission to run. Or whatever you want to say and do nothing more if you want but don't terminate the app.
Also be prepared to launch the app no matter what. You can stick in place holder text while you wait like "loading..." and on a successful result update the text.
Currently when asking for run time permission when launching my app for the very first time it prompts the user to use their location. And if you click yes it doesn't enable location like it should.
But if I relaunch the app it enables the location. Any suggestions as to where I can get it to have location enabled on first launch ? The first part of the code is called in OnCreate.
if (ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// 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(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_CODE_ASK_PERMISSIONS) {
if (permissions.length == 1 &&
permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
// Show rationale and request permission.
}
mMap.setMyLocationEnabled(true);
} else {
//permission denied
}
}
}
public void onMapReady(GoogleMap googleMap) {
int permissionCheck = ContextCompat.checkSelfPermission(MapsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION);
If you are testing on an emulator the permission will only be asked on the first run. How to debug Android 6.0 permissions?
Also if you are not completely uninstalling the app and it is being upgraded from a lower SDK or permissions have been set by the user at runtime and made default, then the runtime permissions will not be asked again.
Try completely uninstalling the app, or checking the default settings and clearing them.
Take a closer look at this line
permissions[0] == Manifest.permission.ACCESS_FINE_LOCATION
permissions is a String array meaning that you should compare using equals()
or compareTo() method.
If this code is in a Fragment, OnRequestPermissionResult() won't be called. So setMyLocationEnabled won't be called until you re open the app.
To fix this change:
ActivityCompat.requestPermissions(MapsActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
To:
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_ASK_PERMISSIONS);
ActivityCompat.requestPermissions is for Activities. When you use a Fragment you should call requestPermissions directly.