YD_S 개발로그
article thumbnail
Published 2023. 9. 12. 21:03
Android - FileProvider Android

1. FileProvider란?

  • FileProvider는 4대 컴포넌트 중 하나인 ContentProvider의 하위 클래스입니다. 파일만을 공유하고자 한다면 간단하게 사용할 수 있다는 장접이 있습습니다.
  • Android 12부터 Scope Storage 정책으로 인해 공유 외장 저장소 영역외엔 접근이 불가능해졌기에 안전하게 FileProvider를 사용해 공유합니다.

 

2. 사용법

AndroidManifest.xml 설정

  • authorities는 FileProvider의 고유한 식별자 역할하므로 개발자가 원하는 값을 작성해도 된다.
<application>
<!-- ... 다른 앱 설정 ... -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>

 

file_paths.xml 설정

  • res/xml 폴더에 file_paths.xml 파일을 생성합니다.
  • name 값은 개발자가 임의로 지정할 수 있습니다. (File URI 변환 시 지정된 name 값으로 변환됩니다.)
  • 태그 별 파일 경로가 다르므로 공유하고 싶은 경로만 사용하면 됩니다.
<?xml version="1.0" encoding="utf-8"?>
<paths>
// images/
<files-path name="my_images" path="images/"/>
// Context.getFilesDir()
<files-path name="name" path="path" />
// getCacheDir()
<cache-path name="name" path="path" />
// Environment.getExternalStorageDirectory()
<external-path name="name" path="path" />
//Context.getExternalFilesDir(null)
<external-files-path name="name" path="path"/>
// Context.getExternalCacheDir()
<external-cache-path name="name" path="path"/>
// Context.getExternalMediaDirs()
<external-media-path name="name" path="path"/>
</paths>
view raw file_paths.xml hosted with ❤ by GitHub

kotlin

  • 예제에서  작성된 FileProvider.getUriForFile 메소드의 "com.example.myapp.fileprovider" 값은 AndroidManifest.xml 에서 지정한 authorities 값입니다. 반드시 authorities는 동일해야합니다.
  • grantUriPermission 메소드를 사용해 File URI의 권한을 부여해줘야 타 앱에서 해당 URI를 접근할 수 있습니다.
import androidx.core.content.FileProvider
// 파일을 공유할 파일 경로
val fileToShare = File(filesDir, "example.txt")
// FileProvider를 사용하여 파일의 Uri를 가져옵니다.
val fileUri = FileProvider.getUriForFile(this, "com.example.myapp.fileprovider", fileToShare)
// File URI를 사용할 수 있도록 권한을 부여해줍니다.
applicationContext.grantUriPermission("공유할 앱의 패키지명", fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
// 파일을 공유할 Intent 생성
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_STREAM, fileUri)
}
// 다른 앱에게 파일 공유 Intent를 보냅니다.
startActivity(Intent.createChooser(intent, "Share File"))
view raw file_share.kt hosted with ❤ by GitHub

3. Android 13 이상부터 안되는 이슈

  • Android 12 이하에는 잘 동작하는데 13 이상부터 동작되지 않는 현상이 있습니다.
  • Android13 이상부터는 AndroidManifest.xml에 <queries> 태그를 추가해 어느 앱을 대상으로 공유할 것인지 명시해줘야합니다.

File URI를 전달할 A앱의 AndroidManifest.xml에 File URI를 전달받을 B앱의 패키지 명을 명시합니다.

<queries>
<package android:name="app.b.package" />
</queries>

 

반대로 File URI를 전달받을 B앱의 AndroidManifest.xml에서 A앱의  패키지 명을 명시합니다.

<queries>
<package android:name="app.a.package" />
</queries>

 

Reference

https://stackoverflow.com/questions/76101296/android-13-fileprovider-unable-to-access-file-descriptor-from-uri-despite-grant

 

Android 13 FileProvider: Unable to access file descriptor from URI despite granting temporary permissions

For some time we have been using the FileProvider APIs to reading/writing a file in App A's internal data directory (/data/data/app.a.package/files/someFile) from App B using a BroadcastReceiver. ...

stackoverflow.com

 

profile

YD_S 개발로그

@YD_S

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!