# 시작하며
학교에서 진행하는 프로젝트에서 필요한 메인기능에 디자인을 입히기전 간단한 프로토 타입을 만들었다.
# 원인 분석
- 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
정말 구글이랑 스택오버플로우 다 뒤져봤다... 일단 거기서 한계점을 맡고 왜 오류가 나는지에 대해서 알아봐야할것 같았다.
먼저 권한오류이기때문에 내가 권한을 줬는지 체크해봤다. 권한은 다 잘 줬다.
# 에러찾기
TIL:SAF URI 권한 유지 · lsm
Written by LSM on April 08, 2020 TIL:SAF URI 권한 유지 SAF URI 권한 유지 ACTION_OPEN_DOCUMENT 인텐트를 통해서 받은 uri를 다른 Activity에서 다시 사용하려 하니 다음과 같은 에러를 받았다. Permission Denial: opening pr
songmilee.github.io
위 글을 참고했다. 일단 uri자체가 계속해서 존재하는 그러한 건 아니라는 말이다. 권한이 생각보다 짧기때문에 그 권한을 늘려줘야 한다는 말인듯 싶었다.
저기 적혀있는 해결책은 일단 안됐다. 그래도 왜 일어나는지 알았다.
# 해결
그렇다면 권한을 늘려줘야한다. 첫번째로는 SAF로 갤러리에서 uri를 받아올때 권한을 늘려줄 것인가 ? 두번째로는 B->A액티비티로 넘겨줄때 권한을 늘려줄것인가이다. 첫번째로 해봤을때는 안됐다. 그래서 두번째방식을 도전해보기로 했다.
Grant Uri permission to another activity
I'm trying to get image from device gallery and then show it in another activity. Code in my activity: private void startGallery() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); ...
stackoverflow.com
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에는 권한이 존재하지만 그건 일시적임.
늘려줘야함.
보낼때 늘려주자