내 앱의 갤러리 (SD 카드)에서 이미지를 선택하는 방법은 무엇입니까?


343

이 질문은 원래 Android 1.6에 대해 요청되었습니다.

내 앱에서 사진 옵션을 작업 중입니다.

내 활동에 버튼과 ImageView가 있습니다. 버튼을 클릭하면 갤러리로 리디렉션되어 이미지를 선택할 수 있습니다. 선택한 이미지가 내 ImageView에 나타납니다.


1
이 답변을보고, 나는 또한 파일 관리자에서 선택을 처리하기 위해 개선 된 코드를 게시했습니다 stackoverflow.com/questions/2169649/…
mad

답변:


418

거의 5 년 후 업데이트 된 답변 :

다양한 소스의 이미지가 때로는 즉, 다른 콘텐츠 URI를 반환으로 원래의 대답의 코드는 더 이상 안정적으로 작동하지 않습니다 content://보다는 file://. 더 나은 솔루션은 단순히을 사용 context.getContentResolver().openInputStream(intent.getData())하는 것입니다.을 선택하면 원하는대로 처리 할 수있는 InputStream이 반환됩니다.

예를 들어, BitmapFactory.decodeStream()옵션 및 inSampleSize 필드를 사용하여 큰 이미지를 다운 샘플링하고 메모리 문제를 피할 수 있으므로이 상황에서 완벽하게 작동합니다.

그러나 Google 드라이브와 같은 것은 실제로 다운로드되지 않은 이미지에 URI를 반환합니다. 따라서 백그라운드 스레드에서 getContentResolver () 코드를 수행해야합니다.


원래 답변 :

다른 답변은 의도를 보내는 방법을 설명했지만 응답을 처리하는 방법을 잘 설명하지 못했습니다. 이를 수행하는 방법에 대한 샘플 코드는 다음과 같습니다.

protected void onActivityResult(int requestCode, int resultCode, 
       Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case REQ_CODE_PICK_IMAGE:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};

            Cursor cursor = getContentResolver().query(
                               selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);
            cursor.close();


            Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
        }
    }
}

그런 다음 "yourSelectedImage"에 선택한 이미지를 저장하여 원하는 작업을 수행 할 수 있습니다. 이 코드는 ContentResolver 데이터베이스에서 이미지의 위치를 ​​가져 와서 작동하지만 자체로는 충분하지 않습니다. 각 이미지에는 파일 경로에서 '마지막으로 수정 한 날짜', 사진이 촬영 된 위치의 GPS 좌표에 이르기까지 약 18 열의 정보가 있지만 실제로는 많은 필드가 사용되지는 않습니다.

실제로 다른 필드가 필요하지 않으므로 시간을 절약하기 위해 커서 검색은 필터를 사용하여 수행됩니다. 필터는 원하는 열 이름 인 MediaStore.Images.Media.DATA를 경로로 지정한 다음 해당 문자열 []을 커서 쿼리에 제공하여 작동합니다. 커서 쿼리는 경로와 함께 반환되지만 columnIndex코드 를 사용할 때까지 어떤 열에 있는지 알 수 없습니다 . 필터링 프로세스에서 사용되는 것과 동일한 이름을 기준으로 열 수를 가져옵니다. 일단 그것을 얻으면 마지막으로 줄의 마지막 줄을 사용하여 이미지를 비트 맵으로 디코딩 할 수 있습니다.


4
cursor.moveToFirst ()의 존재 여부를 확인해야합니다. if (cursor.moveToFirst ()) {커서 데이터로 무언가 수행}
mishkin

14
커서 대신 다음과 같은 방식으로 이미지를 가져와야합니다. Bitmap b = MediaStore.Images.Media.getBitmap (this.getContentResolver (), selectedImage);
Luigi Agosti

4
Luigi, 비트 맵이 큰 경우 MediaStore.Images.Media.getBitmap ()으로 인해 OutOfMemory 예외가 발생할 수 있습니다. Steve의 방법을 사용하면 이미지를 메모리에로드하기 전에 이미지를 축소 할 수 있습니다.
Frank Harper

9
이것은 나를 위해 작동하지 않습니다, cursor.getString (columnIndex);
Alexis Pautrot

9
이 방법에주의 : 사용자가 picasa 앨범 또는 Google+ 사진 앱에서 사진을 선택하면 파일 이름이 '널'이됩니다.
Ciske Boekelo

315
private static final int SELECT_PHOTO = 100;

의도 시작

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);    

공정 결과

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
        }
    }
}

또는 OutOfMemory 오류를 피하기 위해 이미지를 다운 샘플링 할 수도 있습니다.

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 140;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
               || height_tmp / 2 < REQUIRED_SIZE) {
                break;
            }
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);

    }

8
작은 100px x 100px 이미지 뷰에 1.5MB jpeg를 넣으면 VM 메모리 부족 오류가 발생했습니다. 다운 샘플링은 그 문제를 해결 :-)
누군가 어딘가에

1
안녕하세요. 두 스트림 모두 닫혀서는 안됩니까?
Denis Kniazhev 2016

안녕하세요 @siamii .. 당신의 코드를 따랐습니다 ..하지만 그것은 부분적으로 나를 위해 일하고 있습니다. : :( 캡쳐 된 이미지 섹션 아래 갤러리에서 이미지를 선택하면 json 오류가 발생하지만 블루투스 섹션 아래 갤러리에서 이미지가 선택되면 이미지가 액세스되어 서버로 전송됩니다 ..이 링크를 확인하고 나에게 해결책을 제안하십시오 ... stackoverflow.com/questions/29234409/image-is-not-uploaded
Prabs

스케일 찾기에 관한 섹션은 다음과 같이 쓸 수 있습니다.int scale = 1; for ( ; bfOptions.outWidth / scale > TARGET_SIZE && bfOptions.outWidth > TARGET_SIZE; scale*=2);
The_Rafi

@siamii이 메소드를 어디서 어떻게 호출하는지 -------- decodeUri
Akshay Kumar

87

결과를 얻으려면 갤러리 의도를 시작해야합니다.

Intent i = new Intent(Intent.ACTION_PICK,
               android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE); 

그런 다음 에서을 onActivityForResult호출 intent.getData()하여 이미지의 Uri를 가져옵니다. 그런 다음 ContentProvider에서 이미지를 가져와야합니다.


ACTION_PICK은 다른 두 가지 답변에 사용 된 ACTION_GET_CONTENT와 어떻게 다릅니 까?
펭귄 359

4
ACTION_PICK을 사용하면 특정 URI를 지정하고 ACTION_GET_CONTENT를 사용하면 mime_type을 지정합니다. 질문은 특별히 모든 이미지가 아닌 SDCARD의 이미지이므로 ACTION_PICK을 사용했습니다.
로비 연못

2
멋있는. 이것은 내가 필요하고 :) 너희들이 물건을 찾을 수있는 곳에서 매력 : 원더처럼 일을 정확히입니다
Jayshil 데이브

@WilliamKinaan ACTIVITY_SELECT_IMAGE는 수신 할 결과를 식별하기 위해 지정하는 int 값입니다. 그런 다음 onActivityResult (int requestCode, int resultCode, Intent data)에 'requestCode'로 다시 전송됩니다.
Fydo

@Fydo 나는 나중에, 감사합니다
William Kinaan

22

다음은 이미지 및 비디오에 대해 테스트 된 코드이며, 19 미만 및 19 초과의 모든 API에서도 작동합니다.

영상:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("image/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 10);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 10);
                    }

비디오:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("video/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 20);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 20);
                    }    

.

     @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {               
            if (requestCode == 10) {
                Uri selectedImageUri = data.getData();
                String selectedImagePath = getRealPathFromURI(selectedImageUri);
            } else if (requestCode == 20) {
                Uri selectedVideoUri = data.getData();
                String selectedVideoPath = getRealPathFromURI(selectedVideoUri);
            }
        }
     }

     public String getRealPathFromURI(Uri uri) {
            if (uri == null) {
                return null;
            }
            String[] projection = {MediaStore.Images.Media.DATA};
            Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null) {
                int column_index = cursor
                        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            return uri.getPath();
        }

14

갤러리를 시작하고 사용자가 이미지를 선택할 수있게하려면 다음을 수행하십시오.

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMAGE_PICK);

그런 다음 onActivityResult()ImageView에서 이미지를 설정하기 위해 반환되는 이미지의 URI를 사용하십시오.


3
Android 4.4 기기에서는 작동하지 않습니다. 최근 문서 화면이 시작됩니다.
Noundla Sandeep

2
여기 킷캣에 대한 수정은 다음과 같습니다 stackoverflow.com/a/26690628/860488
모르 텐 Holmgaard

11
public class EMView extends Activity {
ImageView img,img1;
int column_index;
  Intent intent=null;
// Declare our Views, so we can access them later
String logo,imagePath,Logo;
Cursor cursor;
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;

 String selectedImagePath;
//ADDED
 String filemanagerstring;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    img= (ImageView)findViewById(R.id.gimg1);



    ((Button) findViewById(R.id.Button01))
    .setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {

            // in onCreate or any event where your want the user to
            // select a file
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);


        }
    });
}

//UPDATED
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();

            //OI FILE Manager
            filemanagerstring = selectedImageUri.getPath();

            //MEDIA GALLERY
            selectedImagePath = getPath(selectedImageUri);


            img.setImageURI(selectedImageUri);

           imagePath.getBytes();
           TextView txt = (TextView)findViewById(R.id.title);
           txt.setText(imagePath.toString());


           Bitmap bm = BitmapFactory.decodeFile(imagePath);

          // img1.setImageBitmap(bm);



        }

    }

}

//UPDATED!
public String getPath(Uri uri) {
String[] projection = { MediaColumns.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
column_index = cursor
        .getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
 imagePath = cursor.getString(column_index);

return cursor.getString(column_index);
}

}

8
public class BrowsePictureActivity extends Activity {
private static final int SELECT_PICTURE = 1;

private String selectedImagePath;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ((Button) findViewById(R.id.Button01))
            .setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {

                    Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    startActivityForResult(Intent.createChooser(intent,
                            "Select Picture"), SELECT_PICTURE);
                }
            });
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            selectedImagePath = getPath(selectedImageUri);
        }
    }
}

public String getPath(Uri uri) {

        if( uri == null ) {
            return null;
        }

        // this will only work for images selected from gallery
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if( cursor != null ){
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }

        return uri.getPath();
}

}

여기 킷캣에 대한 수정은 다음과 같습니다 stackoverflow.com/a/26690628/860488
모르 텐 Holmgaard

4

어떤 이유로이 스레드의 모든 답변 은 이미지의 실제 경로를 얻은 다음를 사용하여 onActivityResult()수신 된를 후 처리하려고 합니다 .UriBitmapFactory.decodeFile(path)Bitmap

이 단계는 필요하지 않습니다. 이 ImageView클래스에는라는 메소드가 setImageURI(uri)있습니다. 당신의 uri를 전달하면 완료해야합니다.

Uri imageUri = data.getData();
imageView.setImageURI(imageUri);

완전한 작업 예제를 보려면 여기를 살펴보십시오. http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html

PS :
얻기 Bitmap이미지를로드 할 경우 나을 별도의 변수 것은 메모리에 비해 너무 크고, 조작 다운 스케일 방지 할 필요가 OurOfMemoryError@siamii 않음에 도시처럼.


3

chooseImage 메소드를 호출하십시오.

public void chooseImage(ImageView v)
{
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, SELECT_PHOTO);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

    if(imageReturnedIntent != null)
    {
        Uri selectedImage = imageReturnedIntent.getData();
    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK)
        {
            Bitmap datifoto = null;
            temp.setImageBitmap(null);
            Uri picUri = null;
            picUri = imageReturnedIntent.getData();//<- get Uri here from data intent
             if(picUri !=null){
               try {
                   datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(),                                 picUri);
                   temp.setImageBitmap(datifoto);
               } catch (FileNotFoundException e) {
                  throw new RuntimeException(e);
               } catch (IOException e) {
                  throw new RuntimeException(e);
               } catch (OutOfMemoryError e) {
                Toast.makeText(getBaseContext(), "Image is too large. choose other", Toast.LENGTH_LONG).show();
            }

        }
        }
        break;

}
    }
    else
    {
        //Toast.makeText(getBaseContext(), "data null", Toast.LENGTH_SHORT).show();
    }
}

1
#initialize in main activity 
    path = Environment.getExternalStorageDirectory()
            + "/images/make_machine_example.jpg"; #
     ImageView image=(ImageView)findViewById(R.id.image);
 //--------------------------------------------------||

 public void FromCamera(View) {

    Log.i("camera", "startCameraActivity()");
    File file = new File(path);
    Uri outputFileUri = Uri.fromFile(file);
    Intent intent = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, 1);

}

public void FromCard() {
    Intent i = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, 2);
}

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 2 && resultCode == RESULT_OK
            && null != data) {

        Uri selectedImage = data.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();

        bitmap = BitmapFactory.decodeFile(picturePath);
        image.setImageBitmap(bitmap);

        if (bitmap != null) {
            ImageView rotate = (ImageView) findViewById(R.id.rotate);

        }

    } else {

        Log.i("SonaSys", "resultCode: " + resultCode);
        switch (resultCode) {
        case 0:
            Log.i("SonaSys", "User cancelled");
            break;
        case -1:
            onPhotoTaken();
            break;

        }

    }

}

protected void onPhotoTaken() {
    // Log message
    Log.i("SonaSys", "onPhotoTaken");
    taken = true;
    imgCapFlag = true;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(path, options);
    image.setImageBitmap(bitmap);


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