android-갤러리에 이미지 저장


91

이미지 갤러리가있는 앱이 있고 사용자가 자신의 갤러리에 저장할 수 있기를 바랍니다. 이를 허용하기 위해 단일 음성 "저장"으로 옵션 메뉴를 만들었지 만 문제는 ... 갤러리에 이미지를 어떻게 저장할 수 있습니까?

이것은 내 코드입니다.

@Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle item selection
            switch (item.getItemId()) {
            case R.id.menuFinale:

                imgView.setDrawingCacheEnabled(true);
                Bitmap bitmap = imgView.getDrawingCache();
                File root = Environment.getExternalStorageDirectory();
                File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");
                try 
                {
                    file.createNewFile();
                    FileOutputStream ostream = new FileOutputStream(file);
                    bitmap.compress(CompressFormat.JPEG, 100, ostream);
                    ostream.close();
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                }



                return true;
            default:
                return super.onOptionsItemSelected(item);
            }
        }

코드의이 부분을 잘 모르겠습니다.

File root = Environment.getExternalStorageDirectory();
                File file = new File(root.getAbsolutePath()+"/DCIM/Camera/img.jpg");

갤러리에 저장하는 것이 맞습니까? 불행히도 코드가 작동하지 않습니다.


이 문제를 해결 했습니까? u는 나와 함께 주를 기쁘게 할 수
user3233280


파일을 저장하는 데 여전히 문제가있는 경우 URL에 "?", ":"및 "-"와 같은 잘못된 문자가 포함되어 있기 때문일 수 있습니다. 이러한 문자를 제거하면 작동합니다. 이것은 외부 장치 및 Android 에뮬레이터에서 흔히 발생하는 오류입니다. 자세한 내용은 여기에서 확인하세요 : stackoverflow.com/questions/11394616/…
ChallengeAccepted

허용 대답은 약간은 2019 년에 구식이되어 여기 업데이트 답을 작성했습니다 : stackoverflow.com/questions/36624756/...
바오 레이를

답변:


168
MediaStore.Images.Media.insertImage(getContentResolver(), yourBitmap, yourTitle , yourDescription);

이전 코드는 갤러리 끝에 이미지를 추가합니다. 시작 또는 다른 메타 데이터에 나타나도록 날짜를 수정하려면 아래 코드를 참조하십시오 (Cortesy of SK, samkirton ).

https://gist.github.com/samkirton/0242ba81d7ca00b475b9

/**
 * Android internals have been modified to store images in the media folder with 
 * the correct date meta data
 * @author samuelkirton
 */
public class CapturePhotoUtils {

    /**
     * A copy of the Android internals  insertImage method, this method populates the 
     * meta data with DATE_ADDED and DATE_TAKEN. This fixes a common problem where media 
     * that is inserted manually gets saved at the end of the gallery (because date is not populated).
     * @see android.provider.MediaStore.Images.Media#insertImage(ContentResolver, Bitmap, String, String)
     */
    public static final String insertImage(ContentResolver cr, 
            Bitmap source, 
            String title, 
            String description) {

        ContentValues values = new ContentValues();
        values.put(Images.Media.TITLE, title);
        values.put(Images.Media.DISPLAY_NAME, title);
        values.put(Images.Media.DESCRIPTION, description);
        values.put(Images.Media.MIME_TYPE, "image/jpeg");
        // Add the date meta data to ensure the image is added at the front of the gallery
        values.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
        values.put(Images.Media.DATE_TAKEN, System.currentTimeMillis());

        Uri url = null;
        String stringUrl = null;    /* value to be returned */

        try {
            url = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

            if (source != null) {
                OutputStream imageOut = cr.openOutputStream(url);
                try {
                    source.compress(Bitmap.CompressFormat.JPEG, 50, imageOut);
                } finally {
                    imageOut.close();
                }

                long id = ContentUris.parseId(url);
                // Wait until MINI_KIND thumbnail is generated.
                Bitmap miniThumb = Images.Thumbnails.getThumbnail(cr, id, Images.Thumbnails.MINI_KIND, null);
                // This is for backward compatibility.
                storeThumbnail(cr, miniThumb, id, 50F, 50F,Images.Thumbnails.MICRO_KIND);
            } else {
                cr.delete(url, null, null);
                url = null;
            }
        } catch (Exception e) {
            if (url != null) {
                cr.delete(url, null, null);
                url = null;
            }
        }

        if (url != null) {
            stringUrl = url.toString();
        }

        return stringUrl;
    }

    /**
     * A copy of the Android internals StoreThumbnail method, it used with the insertImage to
     * populate the android.provider.MediaStore.Images.Media#insertImage with all the correct
     * meta data. The StoreThumbnail method is private so it must be duplicated here.
     * @see android.provider.MediaStore.Images.Media (StoreThumbnail private method)
     */
    private static final Bitmap storeThumbnail(
            ContentResolver cr,
            Bitmap source,
            long id,
            float width, 
            float height,
            int kind) {

        // create the matrix to scale it
        Matrix matrix = new Matrix();

        float scaleX = width / source.getWidth();
        float scaleY = height / source.getHeight();

        matrix.setScale(scaleX, scaleY);

        Bitmap thumb = Bitmap.createBitmap(source, 0, 0,
            source.getWidth(),
            source.getHeight(), matrix,
            true
        );

        ContentValues values = new ContentValues(4);
        values.put(Images.Thumbnails.KIND,kind);
        values.put(Images.Thumbnails.IMAGE_ID,(int)id);
        values.put(Images.Thumbnails.HEIGHT,thumb.getHeight());
        values.put(Images.Thumbnails.WIDTH,thumb.getWidth());

        Uri url = cr.insert(Images.Thumbnails.EXTERNAL_CONTENT_URI, values);

        try {
            OutputStream thumbOut = cr.openOutputStream(url);
            thumb.compress(Bitmap.CompressFormat.JPEG, 100, thumbOut);
            thumbOut.close();
            return thumb;
        } catch (FileNotFoundException ex) {
            return null;
        } catch (IOException ex) {
            return null;
        }
    }
}

22
이것은 이미지를 저장하지만 카메라로 사진을 찍으면 상단에 저장되지만 갤러리의 끝까지 저장됩니다. 갤러리 상단에 이미지를 저장하려면 어떻게해야합니까?
eric.itzhak

19
또한 manifext.xml에 <uses-permission android : name = "android.permission.WRITE_EXTERNAL_STORAGE"/>를 추가해야합니다.
Kyle Clegg

3
내부적으로 insertImage는 날짜 메타 데이터를 추가하지 않기 때문에 이미지는 갤러리 상단에 저장되지 않습니다. 이 GIST를 참조하십시오 : gist.github.com/0242ba81d7ca00b475b9.git insertImage 메소드의 정확한 사본이지만 갤러리 전면에 이미지가 추가되도록 날짜 메타 날짜를 추가합니다.
S-K '

1
@ S-K '그 URL에 액세스 할 수 없습니다. 업데이트 해 주시면 두 가지 옵션이 모두 포함되도록 답변을 업데이트하겠습니다. 건배
sfratini


48

사실, 당신은 어디에서나 사진을 저장할 수 있습니다. 다른 애플리케이션이 액세스 할 수 있도록 공용 공간에 저장하려면 다음 코드를 사용하십시오.

storageDir = new File(
    Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES
    ), 
    getAlbumName()
);

사진이 앨범으로 이동하지 않습니다. 이렇게하려면 스캔을 호출해야합니다.

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

https://developer.android.com/training/camera/photobasics.html#TaskGallery 에서 자세한 정보를 찾을 수 있습니다.


1
이것은 전체 구현을 변경할 필요가없고 앱에 대한 사용자 지정 폴더를 만들 수 있기 때문에 아주 간단한 솔루션입니다.
Hugo Gresse 2015 년

2
파일 만 스캔 할 수있는 경우 브로드 캐스트를 보내는 것은 리소스 낭비 일 수 있습니다. stackoverflow.com/a/5814533/43051 .
Jérémy Reynaud

2
실제로 비트 맵을 어디로 전달합니까?
Daniel Reyhanian

22

Marshmallow와 Lollipop에서이 작업을 수행하기 위해 많은 시도를했습니다. 마지막으로 저장된 사진을 DCIM 폴더로 옮겼습니다 (새 Google 포토 앱은이 폴더 안에 분명히있는 경우에만 이미지를 스캔합니다)

public static File createImageFile() throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
         .format(System.currentTimeInMillis());
    File storageDir = new File(Environment
         .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/Camera/");
    if (!storageDir.exists())
        storageDir.mkdirs();
    File image = File.createTempFile(
            timeStamp,                   /* prefix */
            ".jpeg",                     /* suffix */
            storageDir                   /* directory */
    );
    return image;
}

그런 다음 Google Developers 사이트에서도 찾을 수있는 파일 스캔을위한 표준 코드입니다 .

public static void addPicToGallery(Context context, String photoPath) {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(photoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    context.sendBroadcast(mediaScanIntent);
}

이 폴더는 전 세계의 모든 장치에있을 수는 없으며 Marshmallow (API 23)부터는 사용자에게 WRITE_EXTERNAL_STORAGE에 대한 권한을 요청해야합니다.


1
Google 포토에 관한 정보를 제공해 주셔서 감사합니다.
Jérémy Reynaud

1
이것은 잘 설명하는 유일한 해결책입니다. 다른 누구도 파일이 DCIM 폴더에 있어야한다고 언급하지 않았습니다. 감사합니다!!!
Predrag Manojlovic

Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)나를 위해 트릭을했다. 감사!
saltandpepper

2
getExternalStoragePublicDirectory()지금은 API 29 미디어 스토어 MediaStore를 사용하는 필요에되지 않습니다
riggaroo

@riggaroo 예를 바로 레베카는, 내가 최대한 빨리 답을 업데이트합니다
MatPag

13

이 과정 에 따르면 를 수행하는 올바른 방법은 다음과 같습니다.

Environment.getExternalStoragePublicDirectory(
        Environment.DIRECTORY_PICTURES
    )

갤러리 디렉토리의 루트 경로를 제공합니다.


나는이 새로운 코드를 시도하지만 java.lang.NoSuchFieldError 추락 : android.os.Environment.DIRECTORY_PICTURES
기독교 Giupponi을

그래 고마워요, 그럼 안드로이드 2.2 이하로 갤러리에 이미지를 올릴 방법이 없나요?
Christian Giupponi 2012 년

Perfect-Android 개발자 웹 사이트로 직접 연결되는 링크입니다. 이것은 효과가 있었고 간단한 해결책이었습니다.
Phil

1
좋은 답변이지만 일반적으로 갤러리 앱이 새 사진을 인식하도록하기를 원할 것이기 때문에 여기에있는 다른 답변의 "galleryAddPic"메서드를 추가하는 것이 더 좋습니다.
Andrew Koster 19

11
private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(mCurrentPhotoPath);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}

6

카메라 폴더 안에 디렉토리를 생성하고 이미지를 저장할 수 있습니다. 그 후에 간단히 스캔을 수행 할 수 있습니다. 갤러리에 이미지가 즉시 표시됩니다.

String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()+ "/Camera/Your_Directory_Name";
File myDir = new File(root);
myDir.mkdirs();
String fname = "Image-" + image_name + ".png";
File file = new File(myDir, fname);
System.out.println(file.getAbsolutePath());
if (file.exists()) file.delete();
    Log.i("LOAD", root + fname);
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
        out.flush();
        out.close();
    } catch (Exception e) {
       e.printStackTrace();
    }

MediaScannerConnection.scanFile(context, new String[]{file.getPath()}, new String[]{"image/jpeg"}, null);

이 기준에서 이것이 최고의 답변입니다
Noor Hossain

1

나는 똑같은 의심으로 여기에 왔지만 Android 용 Xamarin의 경우 파일을 저장 한 후이 방법을 수행하기 위해 Sigrist 답변을 사용했습니다.

private void UpdateGallery()
{
    Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
    Java.IO.File file = new Java.IO.File(_path);
    Android.Net.Uri contentUri = Android.Net.Uri.FromFile(file);
    mediaScanIntent.SetData(contentUri);
    Application.Context.SendBroadcast(mediaScanIntent);
} 

그리고 그것은 내 문제를 해결했습니다, Thx Sigrist. Xamarin에 대한 answare를 찾지 못했기 때문에 여기에 넣었으며 다른 사람들을 도울 수 있기를 바랍니다.


1

제 경우에는 위의 솔루션이 작동하지 않았습니다. 다음을 수행해야했습니다.

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(f)));

정말 좋은 그것의이 옵션에 대해 알고 있지만, 불행히도 때문에, 안드로이드 6 일부 장치에서 작동하는 ContentProvider것이 바람직 solytion
시아

0
 String filePath="/storage/emulated/0/DCIM"+app_name;
    File dir=new File(filePath);
    if(!dir.exists()){
        dir.mkdir();
    }

이 코드는 onCreate 메서드에 있습니다.이 코드는 app_name의 디렉터리를 생성하기위한 것입니다. 이제이 디렉토리는 Android의 기본 파일 관리자 앱을 사용하여 액세스 할 수 있습니다. 대상 폴더를 설정하는 데 필요한 곳에이 문자열 filePath를 사용하십시오. 나는이 방법이 Android 7에서도 작동한다고 확신합니다. 따라서 다른 버전의 Android에서도 작동 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.