FrontEnd/Android

[Android] 갤러리에서 사진 선택 기능 구현

Satisfaction 2020. 9. 14. 18:34

내 앱에서 갤러리 앱을 열고 선택한 사진을 내 앱에서 불러오는 기능을 구현한다.

 

파일 읽기 권한 추가

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

먼저 manifest.xml에 다음 권한을 추가하고,

마시멜로 이상의 Android 버전을 타게팅하는 경우 사용자에게 권한을 요청하여 받아낸다.

 

액티비티에서 갤러리 열기 

우선 갤러리를 여는 코드부터 작성해 보자

 

public class SomeActivity extends FragmentActivity{
  //...
  if(PermissionChecker.checkPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)){
    //권한이 확인된 경우 갤러리 오픈
    Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, OPEN_GALLERY); //OPEN_GALLERY는 임의의 requestCode (int)
  }else{
    PermissionChecker.getInst(this).request(this, "사진 업로드를 위해 파일 읽기 권한이 필요합니다", Manifest.permission.READ_EXTERNAL_STORAGE, 0);
  } 
  //...
}

PermissionChecker부분은 설정된 권한을 확인하는 코드이니 알아서 작성하면 되고, 

주목할 부분은 

Intent i = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, OPEN_GALLERY); //OPEN_GALLERY는 임의의 requestCode (int)

이 부분이다.

startActivity가 아닌 startActivityForResult를 사용한 이유는 해당 갤러리에서 사진을 선택하면 갤러리가 닫히고 

내 앱으로는 선택한 사진 정보가 전달되는데 이를 캐치하는 부분이 onActivityResult 이기 때문이다.

 

선택한 사진 정보 로드

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case OPEN_GALLERY:
                if (data != null && resultCode == RESULT_OK) {
                    Uri selectedImage = data.getData();
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};
                    Cursor cursor = getContentResolver().query(selectedImage,
                            filePathColumn, null, null, null);

                    if (cursor == null || cursor.getCount() < 1) {
                        return; // no cursor or no record. DO YOUR ERROR HANDLING
                    }

                    cursor.moveToFirst();
                    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);

                    if (columnIndex < 0) // no column index
                        return; // DO YOUR ERROR HANDLING
					
                    //선택한 파일 경로
                    String picturePath = cursor.getString(columnIndex);
                    

                    cursor.close();
                }
                break;
        }
    }

성공적으로 유저가 사진을 선택했다면 String picturePath까지 내려올 수 있다.

 

이제 선택한 사진의 경로를 알게 되었다.

 

만약 해당 사진의 비트맵 오브젝트를 얻고 싶다면 picturePath 아래에 다음과 같이 추가한다.

Bitmap bitmap = BitmapFactory.decodeFile(picturePath);

얻어온 bitmap 객체를 이미지뷰에 표시하고 싶다면 someImageView.setImageBitmap(bitmap) 처럼 사용할 수도 있다.

 

BitmapFactory.decodeFile() return null (Android 10~)

안드로이드 10 부터 저장소에 접근하는 방식이 바뀌어서 위의 방법대로 했을 경우 bitmap 값에 null이 들어간다.

 

이 경우 manifest.xml의 application 속성에 android:requestLegacyExternalStorage="true" 를 추가한다.

 

그러면 정상적으로 비트맵 객체를 얻어올 수 있다.