본문 바로가기
개발/안드로이드

[Android] FileProvider :: android.os.FileUriExposedException

by darksilber 2019. 6. 11.
반응형

출처: https://gogorchg.tistory.com/entry/Android-FileProvider-androidosFileUriExposedException [항상 초심으로]

 

File 경로를 Uri로 변경하고자 할 경우 아래와 같이 이용한다.

 

Uri.parse(File 경로)

 

앱 내부로 이용하는 것은 문제가 없지만,

MediaPlayer나 Intent로써 다른 앱으로 값을 전달하고자 할 경우,

아래와 같은 Exception이 발생한다.

 

android.os.FileUriExposedException

 

이 Exception은

build.gradle에 targetSdkVersion이 24 이상으로 설정 되어 있을 경우 발생 한다.

 

그 이유는 앱과 앱간의 파일 공유를 진행할 시, 보안이 강화 되었기 때문이다.

이 문제를 해결하기 위해선 FileProvider를 이용하여 임시 권한을 할당해줘야 한다.

 

1. res/xml/provider_paths.xml

 

xml을 통하여 권한을 주고자 하는 폴더를 지정할 수가 있습니다.

기본 형태는 아래와 같습니다.

내장인지 외장인지, 데이터 영역인지 캐쉬영역인지 기본 위치를 지정하고,

path를 통하여 세세한 경로를 지정할 수가 있습니다.

1

2

3

4

5

6

7

8

<?xml version="1.0" encoding="utf-8"?>

<paths>

<files-path name="name" path="path" />

<cache-path name="name" path="path" />

<external-path name="name" path="path" />

<external-files-path name="name" path="path" />

<external-cache-path name="name" path="path" />

</paths>

Colored by Color Scripter

cs

https://developer.android.com/reference/android/support/v4/content/FileProvider.html

 

아래는 내장캐쉬영역에 images 폴더에 권한을 준다는 설정이다.

1

2

3

4

<?xml version="1.0" encoding="utf-8"?>

<paths>

<cache-path name="images" path="./images" />

</paths>

Colored by Color Scripter

cs

 

 

 

2. AndroidManifest.xml

 

xml로 지정한 path를 AndroidManifest에 지정 시켜 줍니다.

1

2

3

4

5

6

7

8

9

<provider

android:name="android.support.v4.content.FileProvider"

android:authorities="${applicationId}.fileprovider"

android:exported="false"

android:grantUriPermissions="true">

<meta-data

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/provider_paths" />

</provider>

Colored by Color Scripter

cs

 

3. FileProvider 사용

 

이 소스는 참고용으로 중요한 부분은 FileProvider.getUriForFile 함수이다.

이전에는 이 부분을 말했듯이 Uri.parse를 이용하였었다.

 

audio 파일을 다른 앱에서 실행하도록 던지는 소스이다.

val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(
FileProvider.getUriForFile(this, applicationContext.packageName + ".fileprovider", File(filePath))
, "audio/*")
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivity(intent)

 

보시면 하시겠지만 또한 중요한 부분은 FLAG_GRANT_READ_URI_PERMISSION 권한을 줘야지만 사용할 수 있다.

"너에게는 이 파일을 읽을 수 있게 해줄께!" 라는 의미인거죠.

당연히 쓰기 권한도 있구요. (FLAG_GRANT_WRITE_URI_PERMISSION )

 

참조 : https://stackoverflow.com/a/38858040



반응형

댓글