how to save image in DCIM folder of external SDCARD in android 11?
Asked Answered
R

1

0

i am saving image in DCIM folder of internal storage by using below code:

    public Uri saveBitmap(@NonNull final Context context, @NonNull final Bitmap bitmap,
                      @NonNull final Bitmap.CompressFormat format,
                      @NonNull final String mimeType,
                      @NonNull final String displayName) throws IOException {

    final ContentValues values = new ContentValues();
    values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName);
    values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
    values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);

    final ContentResolver resolver = context.getContentResolver();
    Uri uri = null;

    try {
        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        uri = resolver.insert(contentUri, values);

        if (uri == null)
            throw new IOException("Failed to create new MediaStore record.");

        try (final OutputStream stream = resolver.openOutputStream(uri)) {
            if (stream == null)
                throw new IOException("Failed to open output stream.");
         
            if (!bitmap.compress(format, 95, stream))
                throw new IOException("Failed to save bitmap.");
        }

        return uri;
    }
    catch (IOException e) {

        if (uri != null) {
            // Don't leave an orphan entry in the MediaStore
            resolver.delete(uri, null, null);
        }

        throw e;
    }
}

now i want to save image in DCIM folder of external SDCARD but i don't know how to do it.

i know that i have to made changes in this line :

values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);

but Environment.DIRECTORY_DCIM always return DCIM Folder of internal storage.

Rhonda answered 31/5, 2021 at 12:29 Comment(3)
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; You only have to change that collection. MediaStore.Images.Media.getContentUri(name) With name for example a value like 1CD3-23ED (or 1cd3-23ed) obtained from MediaStore.getExternalVolumeNames(context);Haught
know that i have to made changes in this line : No. As that is all relative.Haught
Environment.DIRECTORY_DCIM always return DCIM Folder of internal storage. No. It's just equal to "DCIM".Haught
M
1

You need to obtain the existing Volumes using the new MediaStore.getExternalVolumeNames API method, introduced in API 29.

The next example obtains the list of volumes, and tries all of them, prioritizing first any attached SD-card and finally using internal storage if no SD-cards are found or fail to save.

You don't need to make any changes to the RELATIVE_PATH content value, as such is relative to the selected volume.

Also note that I've changed saveBitmap with a Nullable return, instead of throwing an exception on failure. Change this according to your requirements.

@NonNull
private List<Uri> getContentUris(@NonNull final Context context) {

    final List<String> allVolumes = new ArrayList<>();

    // Add the internal storage volumes as last resort.
    // These will be kept at the bottom of the list if
    // any SD-card volumes are found
    allVolumes.add(MediaStore.VOLUME_EXTERNAL_PRIMARY);
    allVolumes.add(MediaStore.VOLUME_EXTERNAL);

    // Obtain the list of volume name candidates

    final Set<String> externalVolumeNames = MediaStore.getExternalVolumeNames(context);

    for (final String entry : externalVolumeNames) {
        // If the volume is "not" already cached in the list,
        // then is an SD-card, so prioritize it by adding it 
        // at the top of the list
        if (!allVolumes.contains(entry))
            allVolumes.add(0, entry);
    }

    // Finally resolve the target Image content Uris

    final List<Uri> output = new ArrayList<>();

    for (final String entry : allVolumes) {
        output.add(MediaStore.Images.Media.getContentUri(entry));
    }

    return output;
}

@Nullable
public Uri saveBitmap(@NonNull final Context context, @NonNull final Bitmap bitmap,
                      @NonNull final Bitmap.CompressFormat format,
                      @NonNull final String mimeType,
                      @NonNull final String displayName) {

    final ContentValues values = new ContentValues();
    values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName);
    values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
    values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);

    final ContentResolver resolver = context.getContentResolver();
    final List<Uri> contentUriList = getContentUris(context);

    for (final Uri contentUri : contentUriList) {
       
        Uri uri = null;

        try {
            uri = resolver.insert(contentUri, values);

            if (uri == null)
                throw new IOException("Failed to create new MediaStore record.");

            try (final OutputStream stream = resolver.openOutputStream(uri)) {
                if (stream == null)
                    throw new IOException("Failed to open output stream.");

                if (!bitmap.compress(format, 95, stream))
                    throw new IOException("Failed to save bitmap.");
            }

            return uri;
        }
        catch (IOException e) {
            Log.w(TAG, "Failed to save in volume: " + contentUri);

            if (uri != null) {
                // Don't leave an orphan entry in the MediaStore
                resolver.delete(uri, null, null);
            }

            // Do not throw, and try the next volume
        }
    }

    return null;
}
Marten answered 1/6, 2021 at 9:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.