14

I have this code for creating directory for saving pictures:

        File storageDir = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {                
            storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "myphoto");
            if (!storageDir.mkdirs()) {                    
                if (!storageDir.exists()){                       
                    Log.d("photo", "failed to create directory");
                    return null;
                }
            }
        }
        return storageDir;

storeDir returns "/storage/emulated/0/Pictures/myphoto/" below android 6 and on android 6 it returns null.

I have permission <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

buildToolVersion 23 targetSdkVersion 23

How to fix?

Jemshit
  • 9,501
  • 5
  • 69
  • 106
  • "storeDir returns "file:///storage/emulated/0/Pictures/myphoto/" below android 6 and on android 6 it returns "file:///"" -- that code is returning `File` objects, not strings. Beyond that, what is your `targetSdkVersion`? – CommonsWare Aug 26 '15 at 11:34
  • it returns null actually – Jemshit Aug 26 '15 at 11:47

4 Answers4

23

As @CommonsWare answered, there is run-time permission asking concept on Android M, so in new approach, permissions are not asked when installing the app but when trying to use specific feature of phone which requests permission, at run-time. User later can disable permission from phone settings->app->yourapp->permissions as well. So you have to check before doing something with that permission, and ask user:

int REQUEST_WRITE_EXTERNAL_STORAGE=1;
////...
        File storageDir = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            //RUNTIME PERMISSION Android M
            if(PackageManager.PERMISSION_GRANTED==ActivityCompat.checkSelfPermission(context,Manifest.permission.WRITE_EXTERNAL_STORAGE)){
                storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "myPhoto");
            }else{
                requestPermission(context);
            }    

        } 
        return storageDir;
////...
        private static void requestPermission(final Context context){
        if(ActivityCompat.shouldShowRequestPermissionRationale((Activity)context,Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example if the user has previously denied the permission.

            new AlertDialog.Builder(context)
                    .setMessage(context.getResources().getString(R.string.permission_storage))
                    .setPositiveButton(R.string.tamam, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ActivityCompat.requestPermissions((Activity) context,
                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                            REQUEST_WRITE_EXTERNAL_STORAGE);
                }
            }).show();

        }else {
            // permission has not been granted yet. Request it directly.
            ActivityCompat.requestPermissions((Activity)context,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_WRITE_EXTERNAL_STORAGE);
        }
    }

///...

    @Override
    public void onRequestPermissionsResult(int requestCode,String permissions[], int[] grantResults) {
        switch (requestCode) {
            case UtilityPhotoController.REQUEST_WRITE_EXTERNAL_STORAGE: {
                if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(context,
                            getResources().getString(R.string.permission_storage_success),
                            Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(context,
                            getResources().getString(R.string.permission_storage_failure),
                            Toast.LENGTH_SHORT).show();
                    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
                }
                return;
            }
        }
    }
Jemshit
  • 9,501
  • 5
  • 69
  • 106
15

You are running this on an Android 6.0+ environment and you have a targetSdkVersion of 23.

In that case, WRITE_EXTERNAL_STORAGE is part of the Android 6.0 runtime permission system. Either revise your app to participate in this system, or drop your targetSdkVersion below 23.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • i have tested it without permission, no luck – Jemshit Aug 26 '15 at 11:59
  • @JemshitIskenderov: I did not tell you to remove the permission. I told you to revise your app to participate in the Android 6.0 runtime permission system, or to drop your `targetSdkVersion` below 23. – CommonsWare Aug 26 '15 at 12:00
  • what do you mean by "revise your app to participate in the Android 6.0 runtime permission system"? – Jemshit Aug 26 '15 at 12:01
  • 3
    @JemshitIskenderov: I mean what I wrote. There is a link in my answer to [the documentation on the Android 6.0 runtime permission system](http://developer.android.com/preview/features/runtime-permissions.html). It is rather long and involved. My recommendation is that you drop your `targetSdkVersion` below 23 for the time being. – CommonsWare Aug 26 '15 at 12:03
  • Either with permission or without permission it had to work (i have tried both) instead of asking permission at runtime right? Bu it does not. I don't think it is because of permission. – Jemshit Aug 26 '15 at 12:06
  • @JemshitIskenderov: "Either with permission or without permission it had to work (i have tried both) instead of asking permission at runtime right?" -- no, it does not. Please change your `targetSdkVersion` to 22 and include the `` element in your manifest. – CommonsWare Aug 26 '15 at 12:07
  • Ok i see there is new settings for granting permissions to applications on phone settings as well on android m. Just i have to do it programatically – Jemshit Aug 26 '15 at 12:16
  • No CommonsWare you are wrong. I have all permissions set up properly and I still cannot mkdir. How can this possibly be? What is wrong with Android why do they do this to us as developers. The last thing anyone needs is to waste hours trying to figure why they can't make a directory. PATHETIC! – JamisonMan111 Mar 16 '18 at 08:03
  • I have all the permissions needed, and verified and file.mkdir() always comes back false WTFFFFFFFFFFFFFFFFF. How do you write to external storage after api 23? Anyone? – JamisonMan111 Mar 16 '18 at 08:11
  • @JamisonMan111: I suggest that you ask a separate Stack Overflow question, where you provide a [mcve] demonstrating what you tried and what your specific symptoms are. – CommonsWare Mar 16 '18 at 11:05
4

You must get permission for this work like:

enter image description here

for do it impliment this code:

 if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE)
            != PackageManager.PERMISSION_GRANTED) {

        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {

        } else {


            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},23
                    );
        }
    }

good luck!!!

sebenalern
  • 2,515
  • 3
  • 26
  • 36
saeid aslami
  • 121
  • 1
  • 4
0

Try this code.

@Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            if (checkPermission()) {
                                //do your work
                            } else {
                                requestPermission();
                            }
                        }
               }


                protected boolean checkPermission() {
                    int result = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
                    if (result == PackageManager.PERMISSION_GRANTED) {
                        return true;
                    } else {
                        return false;
                    }
                }

                protected void requestPermission() {

                    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                        Toast.makeText(this, "Write External Storage permission allows us to do store images. Please allow this permission in App Settings.", Toast.LENGTH_LONG).show();
                    } else {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 100);
                        }
                    }
                }

            @Override
            public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
                switch (requestCode) {
                    case 100:
                        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                            //do your work
                        } else {
                            Log.e("value", "Permission Denied, You cannot use local drive .");
                        }
                        break;
                }
            }
Kush Patel
  • 1,228
  • 1
  • 13
  • 34