Q: How do I properly download an image to my camera roll? So I'm trying do download an image from an URL this image on a button onClickEvent but for some reason it keeps telling me to add the android.permission.WRITE_EXTERNAL_STORAGE permission even though I've added it to my manifest.

I'm using API 19

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"
    tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

This is how I'm trying to download it
this.btnDownload.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        //Download image
        imageToRoll();
        Toast.makeText(DisplayItemActivity.this, "Done!", Toast.LENGTH_SHORT).show();
    }
});

private void imageToRoll(){
    imageView.buildDrawingCache();
    Bitmap image = imageView.getDrawingCache();  // Gets the Bitmap
    MediaStore.Images.Media.insertImage(getContentResolver(), image, "imageName" , "testerDescription");  // Saves the image.
}

And here is the exception
E/MediaStore: Failed to insert image
    java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=16101, uid=10189 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission()
        at android.os.Parcel.createException(Parcel.java:1953)
        at android.os.Parcel.readException(Parcel.java:1921)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
        at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
        at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
        at android.content.ContentResolver.insert(ContentResolver.java:1611)
        at android.provider.MediaStore$Images$Media.insertImage(MediaStore.java:1019)
        at com.name.namee.ui.DisplayItemActivity.imageToRoll(DisplayItemActivity.java:102)
        at com.name.namee.ui.DisplayItemActivity.access$000(DisplayItemActivity.java:40)
        at com.name.namee.ui.DisplayItemActivity$1.onClick(DisplayItemActivity.java:91)
        at android.view.View.performClick(View.java:6663)
        at android.view.View.performClickInternal(View.java:6635)
        at android.view.View.access$3100(View.java:794)
        at android.view.View$PerformClick.run(View.java:26199)
        at android.os.Handler.handleCallback(Handler.java:907)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:216)
        at android.app.ActivityThread.main(ActivityThread.java:7625)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)


A: Since Android 6.0, WRITE_EXTERNAL_STORAGE is a "dangerous" permission, so users have to accept them at runtime, and your app has to ask them in the proper way.
For these kind of permissions, it's not enough to just write the permission in the Manifest, but you have to write all the logic to ask the permission at runtime.
It's not difficult, just read this official guide:
https://developer.android.com/training/permissions/requesting
and exactly here you can read about dangerous permissions:
https://developer.android.com/guide/topics/permissions/overview.html#dangerous-permission-prompt

A: try this :
 if (Build.VERSION.SDK_INT >= 19
                && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                    1);
        }else{
 imageToRoll();
}

@Override
public void onRequestPermissionsResult(final int requestCode, @NonNull final String[] permissions, @NonNull final int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
             imageToRoll();
        } 
    }
}

