Permissions obtained Event Handling in Android API level >=23 - android

I have implemented Requesting permissions at Runtime but I am not sure when I can call method that needs the permissions.
I can not call the method immediately because user needs time for press "Yes" button in permission dialog.
It will be very useful to handle onPermissionsObtained event but I can not find any similar to that.
How to deal with that?
See my code for example
private void startBuildInCameraActivity(View v) {
if ((ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA)
!= PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)) {
requestPermissions();
//TODO init onPermissionObtained event handler here instead "return"
return;
}
startCamera();
}
The problem is User needs to call startBuildInCameraActivity twice if he has not permissions. Otherwise startCamera() will be never called.

Thanks, #Drez 21.
The solution is to make class implemented FragmentCompat.OnRequestPermissionsResultCallback and then:
private void startBuildInCameraActivity(View v) {
if ((ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)) {
requestPermissions();
} else {
startCamera();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
ErrorDialog.newInstance(getString(R.string.permissions_needs))
.show(getChildFragmentManager(), FRAGMENT_DIALOG);
} else {
startCamera();
}
}
This class has already implemented this behavior - use it for example.

Related

How to ask permissions only once?

I have a method in the beginning of the activity to ask the permissions, but in the code when I want to get location coordinates, appear a error about permissions request.
This is for Android SDK 28.0.2. I've tried adding the permissions requeste in all lines that I request for coordinates.
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
checkPermissions();
...
}
public void myPosition() {
//One of lines where appear the error
Location loca = locaMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loca != null) {
mapCamera(loca.getLatitude(), loca.getLongitude());
pass = true;
savePosition(loca);
}
}
private void checkPermissions() {
if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}
}
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case 1: {
if (!(grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
//Show error
finish();
}
}
}
}
I want do this permissions check only once. But now I see the following error:
Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException

Android permissionCheck not working

AndroidManifest.xml :
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Code :
button.setOnClickListener {
var permissionCheck = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
toast("success")
} else {
toast("fail")}}
Why does this return "fail" ?
For Android 6.0+ or targetSdk=23 you have to consider asking for run-time permissions. The permissions android.permission.ACCESS_FINE_LOCATION is considered dangerous so you have to ask for it at run-time. See Normal and Dangerous Permissions for an overview.
What you have to do is to ask it at run-time e.g.
from the developer guidelines
// 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.
}
}
Read more here at Requesting Permissions at Run Time
In this case you should request the permission like:ActivityCompat.requestPermissions(thisActivity,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE);
and you should get an answer in onRequestPermissionsResult callback.
Then, if the user grant the permission, at the next time you will use the checkSelfPermission method you will get success.
For more details read this: https://developer.android.com/training/permissions/requesting.html
It seems you are using target sdk >=23 and run app on device with api level also >=23. So since api 23 there is new flow to recive permissions. Permissions are divided into two categories, normal and dangerous. Dangerous permissions should be asked in runtime like this:
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_LOCATION);
This will show system dialog for user:
So result of user's selections will be returned to public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
With request code that you passed in ActivityCompat.requestPermissions, in my case it is MY_PERMISSIONS_REQUEST_LOCATION
Permissions' names will be in String permissions[] and user's selections will be accordingly in int[] grantResults, with can be PackageManager.PERMISSION_GRANTED or PERMISSION_DENIED.
Also it's good to explain to user why you need that permission before asking it.
See more here:Requesting Permissions at Run Time
You can check Permission after/in Android 6.0
public class MainActivity extends AppCompatActivity {
private final int PERMISSIONS_CODE = 1001;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION,}, PERMISSIONS_CODE);
} else {
// You can do you operation directly. If you added permissions in AndroidManifest...
// Or visit following link to read about permission check.
// https://stackoverflow.com/questions/7203668/how-permission-can-be-checked-at-runtime-without-throwing-securityexception
}
}
});
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case PERMISSIONS_CODE:
if (grantResults.length > 0 && grantResults[grantResults.length-1] == PackageManager.PERMISSION_GRANTED) {
Log.d("permission", "accepted");
} else {
Log.d("permission", "denied");
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
break;
}
}
}
Happy coding...
for Android 6.0 and your targetSdkVersion >=23 , you should ask permission at run time,I have two advise:
1、you can change your targetSdkVersion in model gradle file,eg:
targetSdkVersion=22
but,I don't recommend use this method.
2、this return 'fail' mean you don't have this permission,your should
consider if your have request but user refuse,in this your can show a dialog to tell use ,why you need this perssion,and then request the permession you want,you can use this code below:
private boolean check(){
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED){
//you have this permession
return true;
}else{
//don't hava permession ,you shoud check if you can request
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
//the use refuse you request this permission ,the system well't show request dialog,you shoul show a dialog tu explain why you need this permission
//and guide he go to system setting open this permission.
}else {
// you can request permission direct
//requestCode is a integer code,that you can use is in onRequestPermissionsResult
ActivityCompat.requestPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION, requestCode);
}
}
return false;
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//in this you can listen the request result
if(grantResults[0]==PackageManager.PERMISSION_GRANTED){
//user Agree permission
}else{
//user reject permission
}
}
I'm sorry,I only know java,so,this code is jave. hope this can help you to deal this problem.
Requesting permissions is too confusing for me, EasyPermissions solved all my problems
Manifest :
compile 'pub.devrel:easypermissions:0.4.2'
Code :
button.setOnClickListener {
if (EasyPermissions.hasPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
toast("yes !")
} else {
EasyPermissions.requestPermissions(this, getString(R.string.location_perm), 1, Manifest.permission.ACCESS_FINE_LOCATION )
}}
worked perfect first try
public static int CAMERA_PERMISSSION_CODE = 1;
public static int STORAGE_PERMISSSION_CODE = 2;
public static int FINE_LOCATION_PERMISSSION_CODE = 3;
public static int COARSE_LOCATION_PERMISSSION_CODE = 3;
public static int READ_PHONESTATE_PERMISSSION_CODE = 4;
private void askForunTimePermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(PermissionsActivity.this,
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSSION_CODE);
} else if (ContextCompat.checkSelfPermission(PermissionsActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, STORAGE_PERMISSSION_CODE);
} else if (ContextCompat.checkSelfPermission(PermissionsActivity.this,
Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, FINE_LOCATION_PERMISSSION_CODE);
} else if (ContextCompat.checkSelfPermission(PermissionsActivity.this,
Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, COARSE_LOCATION_PERMISSSION_CODE);
} else if (ContextCompat.checkSelfPermission(PermissionsActivity.this,
Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, READ_PHONESTATE_PERMISSSION_CODE);
} else {
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
try {
if (requestCode == CAMERA_PERMISSSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
askForunTimePermissions();
} else {
askForunTimePermissions();
}
} else if (requestCode == STORAGE_PERMISSSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
askForunTimePermissions();
} else {
askForunTimePermissions();
}
} else if (requestCode == FINE_LOCATION_PERMISSSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
askForunTimePermissions();
} else {
askForunTimePermissions();
}
} else if (requestCode == COARSE_LOCATION_PERMISSSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
askForunTimePermissions();
} else {
askForunTimePermissions();
}
} else if (requestCode == READ_PHONESTATE_PERMISSSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
askForunTimePermissions();
} else {
askForunTimePermissions();
}
}
} catch (Exception e) {
Toast.makeText(PermissionsActivity.this, "No permission requests matched", Toast.LENGTH_SHORT).show();
}
}
//call this method where u want
askForunTimePermissions();
To check Location Permission via PermissionChecker.checkSelfPermission, you need to enable Location first. Otherwise PermissionChecker.checkSelfPermission will always return -2.

Android requestPermission Dialog not showing up

I am working with a Samsung Galaxy Tab S tablet and try to grant permission to write on the external storage at runtime.
However the dialog to request the permission does not show up. Instead in the code onRequestPermissionResult will be executed instantly with the a PERMISSION_DENIED result. I even tried granting the storage permission manually in the application settings on the device, but even then the result will be PERMISSION_DENIED (grantResults is -1).
My code looks like this:
public class MainActivity extends AppCompatActivity {
public static final int REQUEST_STORAGE_PERMISSION = 225;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= 23) {
if (checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED) {
process();
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_STORAGE_PERMISSION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "Permission Granted", Toast.LENGTH_LONG).show();
process();
} else {
Toast.makeText(getApplicationContext(), "Permission Denied", Toast.LENGTH_LONG).show();
}
}
}
public void process() {
//...
}
}
When starting the application, it will instantly show the "Permission Denied"-Toast, without showing me any dialog before. That happens, even if i grant the Storage-permission manually in the app settings of the tablet.
My manifest-file also contains the permission at the right place (outside of the application tags) as suggested in similar threads.
I tried reinstalling the app and even reset the tablet already, but nothing seems to work.
instead of:
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
it works for fragments
You need to use this: As you are using AppCompatActivity
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION);
EDIT
As you have multiple project module: you need to add permission in both of those Manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Do this thing
private boolean RequestPermissions() {
int camera = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.CAMERA);
int storage = ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(CAMERA);
}
if (storage != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(WRITE_EXTERNAL_STORAGE);
listPermissionsNeeded.add(READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(getActivity(), listPermissionsNeeded.toArray
(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}

How to grant permission for the camera?

I just need a way to get permission for using the camera of the smartphone.
I wrote this code, but the permission request dialog doesn't appear.
in the onCreate:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA}, 1);
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// my code after granted permission
} else {
}
return;
}
}
}
requestPermissions() is not called because "ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)" is true
Step #1: Show some rationale (dialog, snackbar, something inline in your UI, whatever)
Step #2: When the user taps on something specific in that rationale UI (e.g., OK button), call requestPermissions()
Or, if you do not want to show rationale for why you are requesting the permission, do not call shouldShowRequestPermissionRationale().

Android Marshmallow Permission Error

i am adding certain permissions to my app to allow access to camera for example and everything is working fine. but when i minimize the app and disable the permission then open the app, the app crashes without asking me to re-enable the permission(until i close the app and then open it). how can i fix this error so that the app dont crash and ask again for permission or safe restart to ask for permissions.
here is my code
in the main activity:
onCreate:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA},
GlobalVariables.MY_PERMISSIONS_REQUEST_CAMERA);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode)
{
case GlobalVariables.MY_PERMISSIONS_REQUEST_CAMERA:
{
if (grantResults.length <= 0
|| grantResults[0] != PackageManager.PERMISSION_GRANTED) {
globalVariables.ShowOKAlert("Error","Please Accept All Requested Permissions or the app wont function properly",this,false);
}
return;
}
}
}
the activity implements ActivityCompat.OnRequestPermissionsResultCallback
step 1:
String[] permissions = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
};
Step 2:-
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p : permissions) {
result = ContextCompat.checkSelfPermission(this, p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), 100);
return false;
}
return true;
}
Step 3:
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == 100) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// do something
}
return;
}
}
You are checking that permission in onCreate. When you minimize and maximize the app again that method is not called.
Maybe you should check that permission in the extact point where you need it, or at least in onResume which surely is called again when you re-open your app.
Calling it in onResume ensure the app continues to work also if the user disables the permission in another window with the screen splitted (Android N feature).
The easy way to achieve this to use direct static method of ActivityCompat
public static void requestPermissions(final #NonNull Activity activity,
final #NonNull String[] permissions, final int requestCode)
Here you can see what parameters you have required for this
-- Activity Instance
-- String array of permissions
-- a user defined request code
Usage
Define global variables
//Run-time permissions for MarshMallow +
public final String[] PERMISSION_ALL = {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//validateRequestPermissionsRequestCode requires requestCode to be of 8 bits, i.e. range: 0-255.
public final int PERMISSION_REQUEST_CODE = 100;
Finally in your activity oncreate() method you can call static function mentioned above
public class MainActivity extends AppCompatActivity
{
//your code here
#Override
protected void onCreate(Bundle savedInstanceState)
{
//do other code work
super.onCreate(savedInstanceState);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.M)
{
ActivityCompat.requestPermissions(this, PERMISSION_ALL, PERMISSION_REQUEST_CODE);
}
//do other code work
}
//your code here
}
And you are done....
For more Info Click here about Android Permissions At Run Time

Categories

Resources