파일 프로바이더는 ContentProvider의 자손으로,
파일 Uri를 "file:///"대신 "content://"으로 만들어 관리하기 위해 사용되는 친구이다.
contentUri를 사용하는 이유는, 파일을 Uri로 공유하면서 다른 앱에 권한을 주려고 할 때, 파일의 권한을 바꿔버리면 내가 원했던 그 앱 말고도 다른 앱들에게도 권한이 주어지기 때문이라고 한다. Content Uri를 사용하게 되면, Intent의 flag를 설정하여 일시적인 권한을 줄 수 있게 된다. 또한 해당 권한은 전달받은 Activity가 스택에 존재할 동안 혹은 전달받은 Service가 running인 동안만 유지된다.
Android 7.0(24)부터 Intent로 FileUri를 보내는 것이 금지되었다(FileUriExposedException).
별다른 필요가 없다면 androidx에서 제공하는 FileProvider클래스를 그대로 사용하여도 되지만, 커스터마이징이 필요하다면 FileProvider의 자손 클래스를 만들어서 필요한 함수들을 override하여 사용할 수 있다.
class CustomFileProvider : FileProvider(R.xml.file_paths){
...
}
FileProvider를 사용하기 위해 Manifest에 등록할 필요가 있다.
<provider
android:name="com.sample.CustomFileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
android:exported="false"는 무조건 명시하여야 하는 변수이다. 왜냐하면 true가 기본값으로 설정된 버전도 있기 때문이다.
res/xml 폴더를 만든 후 해당 폴더에 "file_paths"라는 xml파일을 만들어서 사용한다. 어디 예시를 보든 다 그렇게 되어 있는 것으로 보아 국룰인 것으로 보인다. (안드로이드 공식마저 이렇게 되어 있다.)
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!--Context.getFilesDir()-->
<files-path name="name" path="." />
<!--getCacheDir()-->
<cache-path name="name" path="." />
<!--Environment.getExternalStorageDirectory()-->
<external-path name="name" path="." />
<!--Context.getExternalFilesDir(null)-->
<external-files-path name="name" path="."/>
<!--Context.getExternalCacheDir()-->
<external-cache-path name="name" path="."/>
<!--only available on API 21+ devices.-->
<!--Context.getExternalMediaDirs()-->
<external-media-path name="name" path="."/>
...
</paths>
File imagePath = new File(Context.getFilesDir(), "images");
File newFile = new File(imagePath, "default_image.jpg");
Uri contentUri = getUriForFile(
getContext(),"
com.mydomain.fileprovider",
newFile
);
[출처] https://aroundck.tistory.com/7287
//support Android (4.1(16) ~ 5.1(22))
intent.setClipData(ClipData.newRawUri("", contentUri));
// set flag to grant permission
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
);
[참고자료]
https://developer.android.com/reference/androidx/core/content/FileProvider
https://aroundck.tistory.com/7287
https://mixup.tistory.com/98