I have set up:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
in the manifest. But the app has still problems writing to external storage.
Looking in application manager the storage permission for the app is thinned off. How to enable it? And why is this happening this now? Is it because of a new android version?
Settings->Applications->Application Manager-><App name>->Permissions
try this to get runtime permission:
if (ContextCompat.checkSelfPermission(sendNotificationActivity.this,Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
{
if (!ActivityCompat.shouldShowRequestPermissionRationale(sendNotificationActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(sendNotificationActivity.this);
alertBuilder.setCancelable(true);
alertBuilder.setTitle("Permission necessary");
alertBuilder.setMessage("Storage Permission is needed for sending Image.");
alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse("package:" + activity.getPackageName()));
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(intent);
}
});
AlertDialog alert = alertBuilder.create();
alert.show();
} else {
ActivityCompat.requestPermissions(sendNotificationActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 541);
}
}
else {
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, 2);
}
}
And override this:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
switch (requestCode) {
case 541: {
for( int i = 0; i < permissions.length; i++ ) {
if( grantResults[i] == PackageManager.PERMISSION_GRANTED ) {
Log.d("Permissions CAMERA", "Permission Granted: " + permissions[i]);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri(photoFileName));
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, 1);
}
} else if( grantResults[i] == PackageManager.PERMISSION_DENIED ) {
Log.d( "Permissions CAMERA", "Permission Denied: " + permissions[i] );
}
}
break;
}
default: {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
break;
}
}
Related
I am trying to save some arrays in an application to use them in other platform (C++) are serialized. I use a pick method to let the user choose the file name and directory, but first I am trying to define the root directory like this, since the handling of the Create Document needs Android 10 to start in the proper defined directory:
'''
String a = getExternalStorageDirectory().getPath();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
String public_dir = "sistemaderiegoandroid_arduino" + MyDocuments.fileSeparator;
file = new File(a, public_dir);
file.setWritable(true);
if (!file.mkdirs()) {
file.mkdir();
}
;
DocumentsContract.createDocument(context.getContentResolver(), DocumentsContract.buildRootUri(MyDocuments.AUTORITY,MyDocuments.ROOT), DocumentsContract.Document.MIME_TYPE_DIR,MyDocuments.INITIALURI);
fileUri = DocumentsContract.buildDocumentUri(MyDocuments.AUTORITY,MyDocuments.INITIALURI);
} catch (Exception e) {
errorMsg(MyDocuments.falloCrear + e.toString());
}
}else{
file = new File(a);
file.setWritable(true);
};
String StfileR = "arduino_data_resumen.bin";
String StfileT = "arduino_data_tiempo.bin";
String StfileH = "arduino_data_humedad.bin";
String StfileL = "arduino_data_luz.bin";
try{
createFile(fileUri, StfileT, CREATE_FILE_T);
createFile(fileUri, StfileL, CREATE_FILE_L);
createFile(fileUri, StfileH, CREATE_FILE_H);
createFile(fileUri, StfileR, CREATE_FILE_R);
} catch (Exception e) {
errorMsg(MyDocuments.falloCrear + e.toString());
}
try {
allData.saveData(context);
} catch (Exception e) {
errorMsg(MyDocuments.falloGrabar + e.toString());
}
private void createFile(Uri pickerInitialUri, String file_name, int result_option_Flag) {
//DocumentsUI
Intent intent = new Intent(ACTION_CREATE_DOCUMENT);
intent.setType(MyDocuments.MINETYPE);
intent.putExtra(Intent.EXTRA_TITLE, file_name);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, RESULT_OK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri);
intent.putExtra(Intent.EXTRA_RETURN_RESULT, RESULT_OK);
}
// intent.putExtra(DocumentsContract.EXTRA_EXCLUDE_SELF,true);
startActivityForResult(intent, result_option_Flag);
};
'''
The permission in the manifest are:
'''
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission-sdk-23 android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission-sdk-23 android:name="android.permission.READ_EXTERNAL_STORAGE"/>
'''
and the provider is:
'''
<provider
android:name="com.sistemaderiegoandroid_arduino.MyDocuments"
android:authorities="com.sistemaderiegoandroid_arduino.documents"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
<intent-filter>
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
'''
To save the data in the file I use a FileDescriptor with the method getContentResolver().openFileDescriptor MODE_APPEND, this gives a ParcelFileDescriptor and with the method getFileDescriptor() I make the FileOuputStream like this:
'''
FileDescriptor fdR = null;
parcelFileDescriptorL = getContentResolver().openFileDescriptor(fileNameL, "MODE_APPEND", null);
fdL = parcelFileDescriptorL.getFileDescriptor();
arduinoDataL = new FileOutputStream(fdL);
serializatorDataL = new ObjectOutputStream(arduinoDataL);
for (int i = 0; i < allData.arrayDatosLuz.length; i++) {
serializatorDataL.writeObject(allData.arrayDatosLuz[i]);
serializatorDataL.flush();
fdL.sync();
}
;
serializatorDataL.close();
'''
The complete package is here:
https://github.com/DarioLobos/sistemariego
I added this grant permission request but anyway the phone don't ask for the permissions. I reset, in the applications manager of the phone the caches of restriction and permits, anyway don't ask for grant them when I install the program. Other application don't have problems while are installing and the phone request grant permissions.
'''
int granted = PackageManager.PERMISSION_GRANTED;
grantRequested =
ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;
if ((grantRequested)) {
if ((ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED)) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(grantDialog).setMessage(R.string.requestWriteSetting);
alertDialogBuilder.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (callBackFlag == 0) {
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
startActivity(intent);
callBackFlag++;
int granted = PackageManager.PERMISSION_GRANTED;
if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) == granted) {
grantRequested =
ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;
if (grantRequested) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN}, RESULT_OK);
} else {
if (grantRequested) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
alertDialogBuilder.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainActivity.this.finish();
System.exit(0);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
}
} else {
dialog.dismiss();
alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
alertDialogBuilder.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainActivity.this.finish();
System.exit(0);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
}
});
}
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
boolean grantChecker = false;
if (grantResults.length > 0) {
grantChecker = true;
for (int i = 0; grantResults.length > i; i++) {
boolean a = grantResults[i] == PackageManager.PERMISSION_GRANTED;
grantChecker = grantChecker & a;
}
}
if (requestCode != RESULT_OK) {
int granted = PackageManager.PERMISSION_GRANTED;
if (!grantChecker & (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_SETTINGS) == granted)) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ResumenFragment.errorMsg(permitHandling);
ActivityCompat.requestPermissions(this,
new String[]{
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN}, RESULT_OK);
} else {
grantRequested =
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH) != granted |
ContextCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_ADMIN) != granted;
if (grantRequested) {
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle(exit).setMessage(R.string.permitNotGranted);
alertDialogBuilder.setCancelable(false)
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
MainActivity.this.finish();
System.exit(0);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
;
}
}
}
'''
The Intents for result for OPENDOCUMENT and CREATEDOCUMENT give the information about the picked file in the overrided method onActivityResult. There using intent.getData() if obtained the URI for the file, then using contentResolver.openFileDescriptor can be open and with the method getFileDescriptor() do a FileOutputStream or FileInputStream sync. Like This:
'''
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent resultData) {
if (resultCode == Activity.RESULT_OK) {
// The result data contains a URI for the document or directory that
// the user selected.
if (resultData != null) {
Uri uriData = resultData.getData();
// String fileId =DocumentsContract.getDocumentId(uriData);
if (requestCode == CREATE_FILE_L) {
Data.fileNameL = uriData;
}
if (requestCode == CREATE_FILE_H) {
Data.fileNameH = uriData;
}
if (requestCode == CREATE_FILE_R) {
Data.fileNameR = uriData;
}
if (requestCode == CREATE_FILE_T) {
Data.fileNameR = uriData;
}
if (requestCode == PICK_FILE_T) {
Data.fileNameT = uriData;
}
if (requestCode == PICK_FILE_L) {
Data.fileNameL = uriData;
}
if (requestCode == PICK_FILE_H) {
Data.fileNameH = uriData;
}
if (requestCode == PICK_FILE_R) {
Data.fileNameR = uriData;
'''
I NEED TO KNOW THE PROPER WAY TO DEFINE THE ROOT DIRECTORY AND THE DIRECTORY DOWNLOAD AND THE THE PICK UP NAME AND DIRECTORY COLLECTED FROM THE INTENT RESULT. I did plenty trials without solution any help is welcome.
This issue happens when I deliberately don't do anything when the permission request screen pops up, the app will just crash after a few seconds.
The permission requests pop up after transitioned from another activity (LoginActivity) to MapsActivity.
LoginActivity
if statement to check the validity
if valid
Intent intent = new Intent(LoginActivity.this,MapActivity.class);
startActivity(intent);
finish();
MapActivity
...
public void onMapReady(GoogleMap map) {
mMap = map;
getLocationPermission();
updateLocationUI();
getDeviceLocation();
}
private void getLocationPermission() {
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
Just realised how to solve this with a simpled solution lmao...
In my original code, I have onRequestPermissionResult() already btw.
MapActivity
private boolean mLocationPermissionGranted;
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
updateLocationUI();
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
...
getLocationPermission();
if(mLocationPermissionGranted){
updateLocationUI();
getDeviceLocation();
}
}
No more crashing now :)
i am checking the permission this way and this is working properly try this :-
if (checkLocationPermission()) {
Log.e("Tag", "Camera and External storage Permission's are allowed");
} else {
requestLocationPermission();
}
this is the method checkLocationPermission:-
private boolean checkLocationPermission() {
int result = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
return false;
}
}
this is request method for location:-
private void requestLocationPermission() {
if (ActivityCompat.shouldShowRequestPermissionRationale
(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.DialogTheme);
alertDialog.setMessage("You Have To Give Permission From Your Device Setting To go in Setting Please Click on Settings Button");
alertDialog.setCancelable(false);
alertDialog.setPositiveButton("Go To Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
});
alertDialog.show();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1012);
}
}
and finally onRequestPermissionsResult:-
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this, R.style.DialogTheme);
alertDialog.setMessage("You Have To Give Permission From Your Device Setting To go in Setting Please Click on Settings Button");
alertDialog.setCancelable(false);
alertDialog.setPositiveButton("Go To Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}
});
alertDialog.show();
}else{
// do your stuff in case accept permission
}
}
In Android the Camera action show a error:
java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=android/com.android.internal.app.ResolverActivity } from ProcessRecord{beb99ec 32121:com.android.hawee/u0a369} (pid=32121, uid=10369) with revoked permission android.permission.CAMERA
at android.os.Parcel.readException(Parcel.java:1620)
I request permission on manifest as follows
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And on chooserDialog on click of camera
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constants.CAMERA_CAPTURE_PERMISSIONS_REQUEST_CODE);
} else {
Intent camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
activity.startActivityForResult(camera, Constants.IMAGE_CAPTURE_CAMERA);
}
On activity
#SuppressLint("NewApi")
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frameContainer);
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
And on Fragment
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (requestCode == Constants.CAMERA_CAPTURE_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Intent camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(camera, Constants.IMAGE_CAPTURE_CAMERA);
} else {
new CommonDialogOK(getActivity(), getString(R.string.Sorry), getString(R.string.Permissions_Not_Granted));
}
} else if (requestCode == Constants.PICK_IMAGE_PERMISSIONS_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent gallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(gallery, Constants.IMAGE_CAPTURE_GALLERY);
} else {
new CommonDialogOK(getActivity(), getString(R.string.Sorry), getString(R.string.Permissions_Not_Granted));
}
}
}
But on click from ChooserDialog always get above error.
How can i ask permission for write to external and Image capture at same time.
If camera n external storage both are required for your app you should || them in if condition.
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constants.CAMERA_CAPTURE_PERMISSIONS_REQUEST_CODE);
} else {
Intent camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
activity.startActivityForResult(camera, Constants.IMAGE_CAPTURE_CAMERA);
}
Try this :-
public static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
in onCreate()
private void checkAndroidVersion() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkAndRequestPermissions();
}
}
This method
private boolean checkAndRequestPermissions() {
int camera = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.CAMERA);
int wtite = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
int read = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE);
List<String> listPermissionsNeeded = new ArrayList<>();
if (wtite != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (camera != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.CAMERA);
}
if (read != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(getActivity(), listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
then use this
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
Log.d("in fragment on request", "Permission callback called-------");
switch (requestCode) {
case REQUEST_ID_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<>();
// Initialize the map with both permissions
perms.put(Manifest.permission.CAMERA, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.WRITE_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
perms.put(Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
// Fill with actual results from user
if (grantResults.length > 0) {
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
// Check for both permissions
if (perms.get(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
&& perms.get(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED && perms.get(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
Log.d("in fragment on request", "CAMERA & WRITE_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE permission granted");
// process the normal flow
//else any one or both the permissions are not granted
} else {
Log.d("in fragment on request", "Some permissions are not granted ask again ");
//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
//show the dialog or snackbar saying its necessary and try again otherwise proceed with setup.
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.CAMERA) || ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) {
showDialogOK("Camera and Storage Permission required for this app",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
checkAndRequestPermissions();
break;
case DialogInterface.BUTTON_NEGATIVE:
// proceed with logic by disabling the related features or quit the app.
break;
}
}
});
}
//permission is denied (and never ask again is checked)
//shouldShowRequestPermissionRationale will return false
else {
Toast.makeText(getActivity(), "Go to settings and enable permissions", Toast.LENGTH_LONG)
.show();
// //proceed with logic by disabling the related features or quit the app.
}
}
}
}
}
}
private void showDialogOK(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", okListener)
.create()
.show();
}
And Finally on button click when u save profile or so
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkAndRequestPermissions()) {
}
else {
// do your stuff here
}
} else {
// do your stuff here
}
Try this code:
For Checking permission I created a separate class as below:
public class MarshMallowPermission {
public static final int RECORD_PERMISSION_REQUEST_CODE = 1;
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
public static final int CAMERA_PERMISSION_REQUEST_CODE = 3;
Activity activity;
public MarshMallowPermission(Activity activity) {
this.activity = activity;
}
public boolean checkPermissionForRecord(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkPermissionForExternalStorage(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public boolean checkPermissionForCamera(){
int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
public void requestPermissionForRecord(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.RECORD_AUDIO)){
Toast.makeText(activity, "Microphone permission needed for recording. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.RECORD_AUDIO},RECORD_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForExternalStorage(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(activity, "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
}
}
public void requestPermissionForCamera(){
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA)){
Toast.makeText(activity, "Camera permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(activity,new String[]{Manifest.permission.CAMERA},CAMERA_PERMISSION_REQUEST_CODE);
}
}
}
Then
MarshMallowPermission marshMallowPermission = new
MarshMallowPermission(this);
public void getPhotoFromCamera() {
if (!marshMallowPermission.checkPermissionForCamera()) {
marshMallowPermission.requestPermissionForCamera();
} else {
if (!marshMallowPermission.checkPermissionForExternalStorage()) {
marshMallowPermission.requestPermissionForExternalStorage();
} else {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File mediaStorageDir = new File(
Environment.getExternalStorageDirectory()
+ File.separator
+ getString(R.string.directory_name_corp_chat)
+ File.separator
+ getString(R.string.directory_name_images)
);
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
try {
mediaFile = File.createTempFile(
"IMG_" + timeStamp, /* prefix */
".jpg", /* suffix */
mediaStorageDir /* directory */
);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mediaFile));
startActivityForResult(takePictureIntent, PICK_FROM_CAMERA);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The answer needs more upvotes and should be the official answer about permissions with camera, the other answers don't solved the problem on Android 10.
And how we know, the answers/codes that work on new versions works on olders.
Help us to index this answer:
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, Constants.CAMERA_CAPTURE_PERMISSIONS_REQUEST_CODE);
} else {
Intent camera = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
activity.startActivityForResult(camera, Constants.IMAGE_CAPTURE_CAMERA);
}
Check permission dialog box appears again and again inspite of giving permission and clicking all dialog box as accept it closes the app.
I have a helper method (copied from here) to check multiple permissions and see if any of them are not granted.
public static boolean hasPermissions(Context context, String... permissions) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && 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 = {Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.CAMERA};
if(!hasPermissions(this, PERMISSIONS)){
Log.d("permission","permission");
ActivityCompat.requestPermissions(this, PERMISSIONS, PERMISSION_ALL);
}
I want it to load the same activity i.e. the MainActivity after granting permission.
Can anyone point why the permission is being asked multiple times.
Kind of late to this Party but give this code a try
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 666); // Comment 26
}
}
onAvail();
onLoad();
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 666: // User selected Allowed 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();
snackbarView.setBackgroundColor(Color.WHITE);
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
// User selected the Never Ask Again Option Change settings in app settings manually
} else if (Build.VERSION.SDK_INT >= 23 && !shouldShowRequestPermissionRationale(permissions[0])) {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this, R.style.MyAlertDialogStyle);
alertDialogBuilder.setTitle("Change Permissions in Settings");
alertDialogBuilder
.setMessage("Click SETTINGS to Manually Set\n\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);
}
});
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, R.style.MyAlertDialogStyle);
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) {
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;
}};
Just check that the permission you have mentioned here
String[] PERMISSIONS = {Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.CAMERA};
should be given in manifest file.
Please do the following changes in the corresponding places.
if (hasPermissions(this, PERMISSIONS)) {
// you have permissions
//Do your work.
}
replace **hasPermissions()** method with following code
public static boolean hasPermissions(Context context, String... permissions) {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null && permissions != null) {
for (String permission : permissions) {
result = ContextCompat.checkSelfPermission(context, permission);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(permission);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), PERMISSION_ALL);
return false;
}
}
return true;
}
replace **onRequestPermissionsResult()** with following code
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
Log.d("requestCode", String.valueOf(requestCode));
switch (requestCode) {
case PERMISSION_ALL: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
//Do your work.
Toast.makeText(MainActivity.this, "Permission Recieved", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Until you grant the permission, we cannot proceed further", Toast.LENGTH_SHORT).show();
}
}
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
I know this question has been asked number of times but none of the methods are working for me. I have a v4.nested fragment and I am calling requestPermission but I don't even get the dialog to show and hence onRequestPermissionsResult is not getting called. I have tried call the onRequestPermissionsResult in both my Activity and Fragment but nothing is working. I am using appcompat-v7:23.3.0 so I was expecting the dialog and hence the result. Any help? Thanks
Code
public void ask(){
Log.e("Here", "Permission");
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) ==
PackageManager.PERMISSION_GRANTED) {
Log.e("Here", "Granted");
if (what == 1){
PackageManager pm = getActivity().getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getActivity().startActivityForResult(i, CAMERA_PIC_REQUEST);
} else {
Toast.makeText(getActivity(), "Can't detect Camera on device", Toast.LENGTH_LONG).show();
}
}
else{
Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
getActivity().startActivityForResult(i, RESULT_LOAD_IMAGE);
}
}
else{
Log.e("Here", "Ask");
if (useRuntimePermissions()) {
if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
showMessageOKCancel("You need to allow access to Device Storage",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 3);
Log.e("A", "ash");
}
});
} else {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},2);
Log.e("B", "Should be Asked by now");
}
}
}
}
private boolean useRuntimePermissions() {
return(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new android.support.v7.app.AlertDialog.Builder(getActivity())
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
#Override
public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
Log.e("Hehe", "results"+String.valueOf(requestCode));
switch (requestCode) {
case CAM_REQUEST: {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (what == 1){
PackageManager pm = getActivity().getPackageManager();
if (pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getActivity().startActivityForResult(i, CAMERA_PIC_REQUEST);
} else {
Toast.makeText(getActivity(), "Can't detect Camera on device", Toast.LENGTH_LONG).show();
}
}
else{
Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
getActivity().startActivityForResult(i, RESULT_LOAD_IMAGE);
}
}
else {
Toast.makeText(getActivity(), "Camera Request not granted. Please enable it at App Settings", Toast.LENGTH_LONG).show();
}
return;
}
}
}
The ask() method is called from a button tap onsetClickListener and LogA and LogB are logging but the permission dialog doesn't show.