In my activity, I have the following code:
public void myMethod() {
final File root = new File(Environment.getExternalStorageDirectory() + File.separator + "MyDir" + File.separator);
root.mkdirs();
final String fname = "img_" + System.currentTimeMillis() + ".jpg";
outputFileUri = Uri.fromFile(new File(root, fname));
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePhotoIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, outputFileUri);
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 232);
startActivityForResult(takePhotoIntent, 1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 232) {
myMethod();
} else {
System.out.println("returned...");
ImageView imageView = (ImageView) findViewById(R.id.test_image_view);
imageView.setImageURI(outputFileUri);
}
}
My test device is a rooted nexus 6 on Android 6.0.1. When "myMethod" is called, it lets me take the photo, but upon returning to the activity I get the following error:
java.io.FileNotFoundException: /storage/emulated/0/MyDir/img_1466772411267.jpg: open failed: EACCES (Permission denied)
I have the valid permissions declared in my manifest:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"/>
This error happens on the end of the method (I guess because the prior takes some time to throw the error?) Anyway, from what I see, I appear to be doing things the way I should be. Does anything seem off?
Your code will work till Android 5.0 but not in marshmallow os.
As Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app even though you had given permission in manifest file.
So app need to ask permission from user at runtime and if user does not give that permission you will get permission denial error. So you have to manage code for that.
Refer following link for more details:
https://developer.android.com/training/permissions/requesting.html
Runtime Permissions for Android 6.0
private static final int REQUEST_RUNTIME_PERMISSION = 1;
void checkPremission() {
//select which permission you want
final String permission = Manifest.permission.CAMERA;
//final String permission = Manifest.permission.Storage;
// if in fragment use getActivity()
if (ContextCompat.checkSelfPermission(ActivityName.this, permission)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(ActivityName.this, permission)) {
} else {
ActivityCompat.requestPermissions(ActivityName.this, new String[]{android.permission.CAMERA,android.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_RUNTIME_PERMISSION);
}
} else {
// you have permission go ahead
myMethod();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_RUNTIME_PERMISSION:
final int numOfRequest = grantResults.length;
final boolean isGranted = numOfRequest == 1
&& PackageManager.PERMISSION_GRANTED == grantResults[numOfRequest - 1];
if (isGranted) {
// you have permission go ahead
myMethod();
}else{
// you dont have permission show toast
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Related
I am coding an Android app (in Java) which uses OCR to convert handwriting into digital text. I am trying to take the String generated by the OCR function in my code and write it to a text file (the OCR portion is currently working). I would then like to create a folder (in phone's external storage, for example My Files on Samsung) and add the text file to this folder, which contains only the files the user has created (which the user should be able to access and share).
I have conducted some research on writing to phone's external storage (including other StackOverflow questions) but no tutorial has worked for me.
/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
public File writeFolder ()
{
File file = null;
if (isExternalStorageWritable())
{
// Get the directory for the user's public directory.
file = new File(Environment.getExternalStorageDirectory() + File.separator + "OCR Documents");
}
if (!file.mkdirs())
Log.e(LOG_TAG, "Directory not created");
else
System.out.println(file.getAbsolutePath());
return file;
}
The code above is what I have, however after testing it, the AbsolutePath is null. It does not seem to be creating a folder on the phone's external storage. How would I go about this so that a folder is created and I can add files to that folder?
Your code to create the directory is fine.
But there's a chance you're missing permissions due to newer versions of Android requiring a User's consent before you can write files to the external storage.
First, make sure you have this permission in your Manifest.xml:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
Afterwards, since WRITE_EXTERNAL_STORAGE is listed as a Dangerous Permission, as seen here: https://developer.android.com/guide/topics/permissions/overview#normal-dangerous , you'll also need to explicitly request the permission from the user.
Finally, to request the permission:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not 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; 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 {
// Permission has already been granted
}
You'll also need to handle the response of the request:
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// 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 {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request.
}
}
The above code was copied from: https://developer.android.com/training/permissions/requesting
You should read that link more thoroughly since it provides a good explanation of what you need to explain to the user, since users are typically very wary when Apps ask for permissions to modify files in their storage.
You can try this,
private void getWirtePermissionAndCreateDir() {
if (Build.VERSION.SDK_INT < 23) {
createDir();
} else {
final String[] PERMISSIONS_STORAGE = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//Asking request Permissions
ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, 9);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
boolean writeAccepted = false;
switch (requestCode) {
case 9:
writeAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
break;
}
if (writeAccepted) {
createDir();
} else {
Toast.makeText(MainActivity.this, "You don't assign permission.", Toast.LENGTH_LONG).show();
}
}
private void createDir(){
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "OCR Documents");
file.mkdirs();
Toast.makeText(MainActivity.this, file.getAbsolutePath(), Toast.LENGTH_LONG).show();
}
You have to add getWirtePermissionAndCreateDir() instead of writeFolder() in activity body.
Below function will create folder and then create file in that folder and if folder already exists then simply create file.
private FileOutputStream fos;
//Function: create a file in a folder
private boolean createFileInFolder(String fileName, String folderName) {
if (isExternalStorageWritable()) {
String path = Environment.getExternalStorageDirectory() + "/" + folderName;
File folder = new File(path);
if (!folder.exists()) {
folder.mkdirs();
}
txtFile = new File(path, fileName);
try {
fos = new FileOutputStream(txtFile);
return true;
} catch (IOException e) {
Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show();
return false;
}
} else
return false;
}
//Function: IsExternalStorageWritable?
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
You may need to check permissions so also define these functions.
private boolean permission;
private final int MY_PERMISSIONS_REQUEST = 10;
//Function: checkPermission
private void checkPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST);
} else {
permission = true;
}
}
//Function: Permission Request Results
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
permission = true;
} else {
permission = false;
}
return;
}
}
}
In your manifest file don't forget to add this line.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I'm not able to allow the app to write to external storage when other background app like twilight (dims screen) runs in the background. In this case, I can only deny it and it says screen overlay detected. But can't allow.
My code:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
boolean hasPermission = (ContextCompat.checkSelfPermission(Timetable.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
if (!hasPermission) {
ActivityCompat.requestPermissions(Timetable.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
}
Override code:
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
{
case 1: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//Intent i=new Intent(this,Timetable.class);
//startActivity(i);
//reload my activity with permission granted or use the features what required the permission
} else
{
Toast.makeText(Timetable.this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
}
}
}
}
I want it running even if some background apps like twilight are running.
Downloading a certain file using Android's built in Download Manager provides integrity and a more User Friendly approach. Also the requestPermission method should be called before doing that if the devices having Marshmallow and above are to be supported as well.
And about the allow button not working, that issue is because of apps or activities who capture the screen overlay. Like for instance Facebook messenger or any screen dimming apps. Hence to make it robust you need to check the permission everytime you download something.
public void downloadFile(String uRl) {
File direct = new File(Environment.getExternalStorageDirectory()
+ "/" + "MyFolder");
if (!direct.exists()) {
direct.mkdirs();
}
DownloadManager mgr = (DownloadManager) getSystemService(this.DOWNLOAD_SERVICE);
Uri downloadUri = Uri.parse(uRl);
DownloadManager.Request request = new DownloadManager.Request(downloadUri);
request.setAllowedNetworkTypes(
DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
.setTitle("AppNameAsTitle")
.setDescription("Downloaded using My app")
.setDestinationInExternalPublicDir("/MyFolder", "filename.jpg")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
mgr.enqueue(request);
}
#Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
downloadFile(url);
} else {
Toast.makeText(this, "Permission not granted", Toast.LENGTH_SHORT).show();
}
}
I am trying to open the android default video camera from my app, using the following code:
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, 1);
But on my two phones (Samsung Note 2, and Google Pixel), it opens the image camera instead. I have this permission in my manifest:
<uses-permission android:name="android.permission.CAMERA"/>
Any ideas what causes this issue?
I've also requested the permission at runtime.
Add follow permission CAPTURE_SECURE_VIDEO_OUTPUT and CAPTURE_VIDEO_OUTPUT
Android 6.0 and later requieres to ask permissions at run time. Read the official doc here: https://developer.android.com/training/permissions/requesting.html
I hope it helps.
You must add next code. Devices have Android 6.0 or later.
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, 1);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
}
If your the app has the permission for use the STORAGE we open the STORAGE.
If your the app doesn't have permission for use STORAGE, we open system-dialog.
Result from the dialog you can see in the onRequestPermissionsResult. (You must override it on your Activity).
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode == 2) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, 1);
}
}
}
I think you must extract next lines to the private method.
private void takePhoto() {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, 1);
}
For more information see : https://developer.android.com/training/permissions/requesting.html
I have this app that will pick image to gallery and display it to the test using Imageview. My problem is it won't work on Android M. I can pick image but won't show on my test.They say i need to ask permission to access images on android M but don't know how. please help.
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
Type 1- When your app requests permissions, the system presents a dialog box to the user. When the user responds, the system invokes your app's onRequestPermissionsResult() method, passing it the user response. Your app has to override that method to find out whether the permission was granted. The callback is passed the same request code you passed to requestPermissions().
private static final int PICK_FROM_GALLERY = 1;
ChoosePhoto.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick (View v){
try {
if (ActivityCompat.checkSelfPermission(EditProfileActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(EditProfileActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PICK_FROM_GALLERY);
} else {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, PICK_FROM_GALLERY);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], #NonNull int[] grantResults)
{
switch (requestCode) {
case PICK_FROM_GALLERY:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, PICK_FROM_GALLERY);
} else {
//do something like displaying a message that he didn`t allow the app to access gallery and you wont be able to let him select from gallery
}
break;
}
}
Type 2- If you want to give runtime permission back to back in one place then you can follow below link
Android 6.0 multiple permissions
And in Manifest add permission for your requirements
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Note- If Manifest.permission.READ_EXTERNAL_STORAGE produce error then please replace this with android.Manifest.permission.READ_EXTERNAL_STORAGE.
==> If you want to know more about runtime permission then please follow below link
https://developer.android.com/training/permissions/requesting.html
-----------------------------UPDATE 1--------------------------------
Runtime Permission Using EasyPermissions
EasyPermissions is a wrapper library to simplify basic system permissions logic when targeting Android M or higher.
Installation
Add dependency in App level gradle
dependencies {
// For developers using AndroidX in their applications
implementation 'pub.devrel:easypermissions:3.0.0'
// For developers using the Android Support Library
implementation 'pub.devrel:easypermissions:2.0.1'
}
Your Activity (or Fragment) override the onRequestPermissionsResult method:
#Override
public void onRequestPermissionsResult(int requestCode, String[]
permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions,grantResults);
// Forward results to EasyPermissions
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
Request Permissions
private static final int LOCATION_REQUEST = 222;
Call this method
#AfterPermissionGranted(LOCATION_REQUEST)
private void checkLocationRequest() {
String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION};
if (EasyPermissions.hasPermissions(this, perms)) {
// Already have permission, do the thing
// ...
} else {
// Do not have permissions, request them now
EasyPermissions.requestPermissions(this,"Please grant permission",
LOCATION_REQUEST, perms);
}
}
Optionally, for a finer control, you can have your Activity / Fragment implement the PermissionCallbacks interface.
implements EasyPermissions.PermissionCallbacks
#Override
public void onPermissionsGranted(int requestCode, List<String> list) {
// Some permissions have been granted
// ...
}
#Override
public void onPermissionsDenied(int requestCode, List<String> list) {
// Some permissions have been denied
// ...
}
Link -> https://github.com/googlesamples/easypermissions
-----------------------------UPDATE 2 For KOTLIN--------------------------------
Runtime Permission Using florent37
Installation Add dependency in App level gradle
dependency
implementation 'com.github.florent37:runtime-permission-kotlin:1.1.2'
In Code
askPermission(
Manifest.permission.CAMERA,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) {
// camera or gallery or TODO
}.onDeclined { e ->
if (e.hasDenied()) {
AlertDialog.Builder(this)
.setMessage(getString(R.string.grant_permission))
.setPositiveButton(getString(R.string.yes)) { dialog, which ->
e.askAgain()
} //ask again
.setNegativeButton(getString(R.string.no)) { dialog, which ->
dialog.dismiss()
}
.show()
}
if (e.hasForeverDenied()) {
e.goToSettings()
}
}
Link-> https://github.com/florent37/RuntimePermission
public void pickFile() {
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
CAMERA);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
getActivity(),
new String[]{CAMERA},
PERMISSION_CODE
);
return;
}
openCamera();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[],
#NonNull int[] grantResults) {
if (requestCode == PERMISSION_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
openCamera();
}
}
}
private void openCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_CODE);
}
<uses-permission android:name="android.permission.CAMERA" />
Below code is working fine on pre-Marshmallow devices but not in Marshmallow.
These are the permissions in Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Here is the code
public void saveImageToSDCard(Bitmap bitmap) {
File myDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
pref.getGalleryName());
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Wallpaper-" + n + ".jpg";
File file = new File(myDir, fname);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
Uri uri = getImageContentUri(_context,file);
Log.d(TAG, "Wallpaper saved to: " + file.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}
}
And the same code works when I manually allow the storage permission
Here is the solution given by Nitesh Pareek.
private 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;
}
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.
This is why it works in pre-lolipop versions, and doesn't on API 23. Permissions in Android Manifest alone are not enough, you need to add them at runtime as well. Refer here for more details.
give read write permissions on run time for marshmallow or newer version.
Do like below:-
String[] PERMISSIONS = new String[]{ Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!hasPermissions(this, PERMISSIONS)) {
ActivityCompat.requestPermissions(this, PERMISSIONS, 11);
return;
}
private 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;
}
You need to take application permissions at runtime instead of taking when install/update as convention
Beginning in Android 6.0 (API level 23), users grant permissions to
apps while the app is running, not when they install the app. This
approach streamlines the app install process, since the user does not
need to grant permissions when they install or update the app
For more help: Requesting Permissions at Run Time
By focusing on the documentation and after doing some google searches, finally I have compiled the code below to handle runtime permissions efficiently
To make it work, you need to follow the instructions below:
Call this method to check if storage permission is granted by user?
If not, then you need to request for it
public static boolean isStoragePermissionGranted(Activity activity) {
boolean flag = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
flag = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}
return flag;
}
Call this method to request storage permission
public static void requestStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (isStoragePermissionGranted(activity)) {
return;
}
// Fire off an async request to actually get the permission
// This will show the standard permission request dialog UI
activity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE_STORAGE_PERMISSION);
}
}
Implement this method in your activity to handle response of permission callback
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_CODE_STORAGE_PERMISSION:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (grantResults.length > 0) {
if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
boolean shouldShowRationale = shouldShowRequestPermissionRationale(permissions[0]);
if (!shouldShowRationale) {
// user denied flagging NEVER ASK AGAIN, you can either enable some fall back,
// disable features of your app or open another dialog explaining again the permission and directing to
// the app setting
dialogReasonStoragePermissionToSettings(this);
} else if (Manifest.permission.WRITE_EXTERNAL_STORAGE.equals(permissions[0])) {
// user denied WITHOUT never ask again, this is a good place to explain the user
// why you need the permission and ask if he want to accept it (the rationale)
dialogReasonStoragePermission(this);
}
} /*else {
// Do on permission granted work here
}*/
}
}
break;
}
}
public static void dialogReasonStoragePermission(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Retry", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
requestStoragePermission(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
public static void dialogReasonStoragePermissionToSettings(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(activity.getString(R.string.reason_storage_permission));
builder.setCancelable(false);
builder.setPositiveButton("Go to Settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
goToAppDetailsForPermissionSettings(activity);
}
});
builder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private static final int REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING = 3995;
private static void goToAppDetailsForPermissionSettings(Activity activity) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_CODE_APP_DETAILS_PERMISSION_SETTING);
}
I am not providing you direct code for this but here is a reason API level 23 introduce a new Permission structure for more security below is a short but wast description of thing, in documentation here
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
Code is good just you have to put something additional and that is Runtime Permissions for storage.
Read this blog to know everything from deep inside about Runtime Permissions gave me a clear picture about it, hope it helps you too.
Thanks