# 시작하며
학교에서 진행하는 프로젝트에서 필요한 메인기능에 디자인을 입히기전 간단한 프로토 타입을 만들었다.
# 원인 분석
- A액티비티 : 리사이클러뷰에서 사진 선택
- 새로운 액티비티(B)가 열림( 진짜 구현해야할 앱에서는 여기서 추가적인 기능이 수행 됨)
- B액티비티에서 SAF을 이용해서 갤러리 접근 및 사진 uri를 가져옴
- B액티비티에서 이미지 uri가 잘 가져왔는지 이미지 뷰에 set시켜 확인
- A액티비티의 각각의 리사이클러뷰까지 이미지가 잘 넘어와짐
- A액티비티에서 저장하기를 누르면 파이어베이스 스토리지에 이미지가 저장되고 저장된 이미지 리소스 URL값을 가져와야함 but ERROR
# 에러 발생
이미지 저장을 누르는 시점에서
위와 같은 에러가 발생한다.
Permission Denial: opening provider com.android.providers.media.MediaDocumentProvider
requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs
정말 구글이랑 스택오버플로우 다 뒤져봤다... 일단 거기서 한계점을 맡고 왜 오류가 나는지에 대해서 알아봐야할것 같았다.
먼저 권한오류이기때문에 내가 권한을 줬는지 체크해봤다. 권한은 다 잘 줬다.
# 에러찾기
위 글을 참고했다. 일단 uri자체가 계속해서 존재하는 그러한 건 아니라는 말이다. 권한이 생각보다 짧기때문에 그 권한을 늘려줘야 한다는 말인듯 싶었다.
저기 적혀있는 해결책은 일단 안됐다. 그래도 왜 일어나는지 알았다.
# 해결
그렇다면 권한을 늘려줘야한다. 첫번째로는 SAF로 갤러리에서 uri를 받아올때 권한을 늘려줄 것인가 ? 두번째로는 B->A액티비티로 넘겨줄때 권한을 늘려줄것인가이다. 첫번째로 해봤을때는 안됐다. 그래서 두번째방식을 도전해보기로 했다.
startActivity(new Intent(this, Something.class).setData(uri).addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION));
원래는 인탠트간 uri를 넘겨줄때 putExtra를 이용하거나 getParcelableExtra을 사용했는데, 위 스택오버플로우에서 위와 같은 방법으로 addFlag로 FLAG_GRANT_READ_URI_PERMISSION로 주라고 했다. 그래서 코드를 조금 수정했다.
>> 보낼때
val intent = Intent(this, MainActivity::class.java).apply {
data = selectedImageURI
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
putExtra(MainActivity.STRING_INTENT_ITEM_FROM_RECOMMEND_KEY, itemName)
}
setResult(Activity.RESULT_OK, intent)
if (!isFinishing) finish()
data에다가 uri를 담아 보내주고 거기에 addFlag해줘서 권한 연장을 해줬다.
>> 받을때
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val uri = result.data?.data
val itemName = result.data?.getStringExtra(STRING_INTENT_ITEM_FROM_RECOMMEND_KEY)
if (uri == null) {
Log.d(TAG, "uri값을 가져오지 못했습니다")
return@registerForActivityResult
}
>> SAF로 이미지 열때
private fun getImageFromGallery() {
Toast.makeText(this, " 갤러리로 이동합니다!!", Toast.LENGTH_SHORT).show()
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) // 이걸 ACTION_GET_CONTENT에서 바꿔줌
intent.type = "image/*"
startActivityForResult(intent, 2000)
}
# 결론
uri에는 권한이 존재하지만 그건 일시적임.
늘려줘야함.
보낼때 늘려주자