-
안드로이드 13에서 갤러리에서 사진 선택 크러시프로그래밍/ 안드로이드어플만들기 2023. 9. 2. 19:56728x90반응형
릴리즈된 앱에서 갤러리에서 사전 선택할 때 안드로이드13에서만 아래와 같은 에러 발생함.
에러 발생 부분
Fatal Exception: java.lang.RuntimeException Failure delivering result ResultInfo{who=null, request=2010, result=-1, data=Intent { flg=0x41 clip={image/* video/* {U(content)}} }} to activity {.MainActivity}: java.lang.IllegalArgumentException: Invalid URI: content://media/picker/0/com.android.providers.media.photopicker/media/1000018248
혹시 권한 이슈인가 해서 안드로이드 13부터 세분화된 권한을 추가하고 런타임시 권한 요청하도록 아래와 같이 수정하였다.
기존 앱 권한 부분 ( manifest 파일 )
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
안드로이드 13부터 읽기 권한이 세분화 되어서 이미지에만 따로 권한을 추가로 설정하였다.
수정한 앱 권한 부분 ( manifest 파일 )
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <!-- Required only if your app needs to access images or photos that other apps created. --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
기존 앱 권한 체크 부분
public void checkPermissions(){ if (Build.VERSION.SDK_INT >= 23) { if (checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { String[] permission_list = new String[]{Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }; ActivityCompat.requestPermissions(this, permission_list, 1); } } }
수정한 앱 권한 체크 부분
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { if (checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED ) { String[] permission_list = new String[0]; permission_list = new String[]{Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.READ_MEDIA_IMAGES }; ActivityCompat.requestPermissions(this, permission_list, 1); } }
권한 체크하는 부분에서 안드로이드 13을 체크해서 그 이상이면 새로운 권한으로 요청하도록 조건을 추가하였다.
그러나 사진 선택시 동일한 에러코드로 종료 되어서 결국 사진 선택 코드를 수정해야 할 거 같아
안드로이드13에 새로 추가된 PhotoPicker 기능을 사용해보기로 함.
기존 코드 확인
사진 관련 부분 코드를 수정하기 전에 기존 코드 내용을 확인해보았다.
갤러리 아이콘을 클릭했을 때 실행하는 기존 함수이다.
private void runGallery() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); startActivityForResult(intent, GALLERY_PICK_IMAGE_MULTIPLE); }
암묵적 Intent를 실행하고 그 결과를 startActivityForResult에 전달한다.
Intent는 메시징 객체로, 다른 앱 구성 요소로부터 작업을 요청하는 데 사용할 수 있다.
참고로 startActiviry와 startActivityForResult 에 대한 차이는 아래와 같다.
startActivity : 새 액티비티를 열어줌 (단방향)
startActivityForResult : 새 액티비티를 열어줌 + 결과값 전달 (쌍방향)
requestCode : 여러 액티비티를 쓰는 경우, 어떤 액티비인지 식별하는 값
resultCode : 새 액티비티에서 리턴하는 값
수정된 코드
우선 photo picker 에서 사용할 requestCode 값을 코드에 추가한다.
requestCode는 여러 액티비티를 쓰는 경우, 어떤 액티비인지 식별하는 값이고,
int 값으로 코드에서 설정해주면 된다.
public final static int PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE = 2011;
그리고 안드로이드 13일 경우 처리 분기를 아래와 같이 추가하였다.
private void runGallery() { Log.d(TAG, "runGallery: 실행 "); if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { // Launches photo picker in multi-select mode. // This means that user can select multiple photos/videos, up to the limit // specified by the app in the extra (10 in this example). final int maxNumPhotosAndVideos = 10; Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); intent.setType("image/*"); intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxNumPhotosAndVideos); startActivityForResult(intent, PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE); } else { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); startActivityForResult(intent, GALLERY_PICK_IMAGE_MULTIPLE); } }
마지막으로 호출한 액티비티가 종료될 때 실행되는 함수인 onActivityResult에
관련 처리 부분을 위에서 설정한 requestCode와 resultCode 를 사용하여 분기로 추가한다.
리턴된 Uri 값들을 Uri 배열로 받아서 전달하도록 수정하였다.
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == PHOTO_PICKER_MULTI_SELECT_REQUEST_CODE && resultCode == RESULT_OK) { // Get photo picker response for multi select Uri[] results = new Uri[data.getClipData().getItemCount()]; for (int i = 0; i < data.getClipData().getItemCount(); i++) { results[i] = data.getClipData().getItemAt(i).getUri(); } //롤리팝에서는 콜백(filePathCallbackLollipop)을 초기화 해주지 않는다면, 사진 선택 화면을 호출해도 다시 나타나지 않는다. filePathCallbackLollipop.onReceiveValue(results); filePathCallbackLollipop = null; } } ... }
마지막으로 포토피커는 미디어 라이브러리 액세스 권한을 요구하지 않아서
위에서 추가했었던 READ_EXTERNAL_STORAGE 권한 요청하는 부분을 다시 원복하였다.
if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) { if (checkSelfPermission(Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED || checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ) { String[] permission_list = new String[0]; permission_list = new String[]{Manifest.permission.INTERNET, Manifest.permission.CAMERA, Manifest.permission.ACCESS_NETWORK_STATE }; ActivityCompat.requestPermissions(this, permission_list, 1); } }
이제 갤러리에서 사진 선택 시 아무 문제없이 잘 올라가는 것을 확인하였다.
실서비스에서 문제가 발생하고 있어서 테스트를 진행하고 바로 업데이트 하려고 했는데,
테스트 중에 안드로이드 13에서 fcm 푸시 메세지가 안되는 문제를 또 발생했다.
안드로이드 13에서 또 관련 부분이 업뎃되었나보다...
이제 그만 좀 해......
참고
https://developer.android.com/guide/components/intents-filters?hl=kohttps://developer.android.com/training/data-storage/shared/media?hl=ko
https://salmonpack.tistory.com/46
https://developer.android.com/about/versions/13/features/photopicker?hl=ko
728x90반응형'프로그래밍 > 안드로이드어플만들기' 카테고리의 다른 글