FileProvider

KEH·2025년 1월 12일
post-thumbnail

안드로이드 어플리케이션에서 이미지, 비디오, pdf 와 같은 문서 파일을 생성하거나 불러오는 기능을 종종 마주치게 됩니다.
파일에 접근하기 위해서는 파일의 경로를 알아야 하고, 파일을 생성하기 위해서는 생성할 경로를 지정해야 합니다.
안드로이드에서는 Uri 가 파일의 경로 역할을 합니다.

URI 또는 Uniform Resource Identifier는 인터넷이나 개인 인트라넷에서 리소스를 고유하게 식별하는 문자열입니다. Android에서는 파일, 이미지, 동영상과 같은 앱 내의 리소스를 찾는 데 URI를 사용합니다.

File Uri, Content Uri

안드로이드에서 UriFile UriContent Uri 가 있습니다.

File Uri 는 우리가 개발하는 앱에서 파일에 접근하기 위해 권한을 변경하면 우리 앱에서 뿐만 아니라 다른 앱에서도 파일 접근이 가능하게 됩니다. Urifile:/// 로 시작합니다.

Content Uri임시 쓰기, 읽기 접근 권한을 부여할 수 있고, Uri 를 전달할 때 Intent.setFlags() 함수를 호출하여 권한을 부여합니다. File Uri 와 다르게 임시 권한으로써 전달한 Activity 가 스택에 활성화 되어 있을 때 혹은 서비스가 실행중일 때만 권한이 적용됩니다. Uricontent:// 로 시작합니다.

FileProvider

Android 24 버전부터 안전한 파일 접근을 위해 Content Uri 를 사용해야 하며 FileProvider 를 통하여 Content Uri 에 접근할 수 있습니다.

FileProvider 를 사용하는 방법에 대해 알아보겠습니다.

FileProvider 클래스 선언

원하는 경로에 FileProvider 클래스를 상속받는 커스텀 FileProvider 클래스를 선언합니다.

class MyFileProvider: FileProvider() {
}

AndroidManifest.xml 에 FileProvider 등록

android:nameMyFileProvider 를 등록합니다.
android:authorities 에 URI 권한 이름을 설정합니다. 주로 ${도메인}.fileprovider 를 사용합니다.

<manifest>
   ...
   <application>
       ...
       <provider
           android:name="com.sample.MyFileProvider"
           android:authorities="com.mydomain.fileprovider"
           android:exported="false"
           android:grantUriPermissions="true">
           ...
       </provider>
       ...
   </application>
</manifest>

file_paths.xml 작성

FileProvider미리 설정한 디렉토리 경로에 존재하는 파일만 Content Uri 를 생성할 수 있습니다.
file_paths.xml 에 접근하고자 하는 디렉토리 경로를 설정합니다.
file_paths.xml 경로는 src > main > res > xml > file.paths.xml 입니다.

xml 태그는 접근하고자 하는 디렉토리에 따라 달라집니다.
예를 들어 Context.filesDir 디렉토리에 접근하고 싶으면 아래와 같이 설정하고

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

Context.getExternalFilesDir(String?) 디렉토리에 접근하고 싶으면 아래와 같이 설정합니다.

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

name 속성은 path 값을 Content Uri 에 공개하는 대신 사용할 이름입니다.
path 속성은 FileProvider 가 접근할 수 있는 하위 디렉토리 경로입니다.

예를 들어 Context.getExternalFilesDir(type: String?) 의 루트 경로는 /storage/emulated/0/Android/data/<package_name>/files/ 입니다.

만약 file_paths.xml 를 이렇게 설정했다면 파일의 절대 경로와 Content Uri 는 아래와 같습니다.

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

절대 경로: /storage/emulated/0/Android/data/<package_name>/files/hello/<파일명>
Content Uri: content://<android:authorities>/Test/<파일명>

AndroidManifest.xml 에 file_paths.xml 등록

이전 FileProvider 를 등록했던 곳에 file_paths.xml 를 설정하는 코드를 추가합니다.

<manifest>
   ...
   <application>
       ...
       <provider
           android:name="com.sample.MyFileProvider"
           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>
       ...
   </application>
</manifest>

예제

com.galaxy.study 패키지명으로 프로젝트에서 텍스트 파일을 생성하고, 텍스트 파일의 Content Uri 를 출력해봅시다.

FileProvider 클래스 선언

FileProvider 클래스를 상속하는 GalaxyFileProvider 클래스를 작성합니다.

class GalaxyFileProvider: FileProvider() {
}

AndroidManifest.xml 에 FileProvider 등록

android:nameGalaxyFileProvider 클래스를 등록합니다.
android:authoritiescom.galaxy.study.fileprovider 으로 권한 이름을 설정합니다.

<provider
	android:name="com.galaxy.study.GalaxyFileProvider"
    android:authorities="com.galaxy.study.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
</provider>

file_paths.xml 작성

텍스트 파일을 외부 디렉토리 경로에 생성할 것이므로 external-files-path 태그를 사용합니다.
텍스트 파일의 경로는 외부 디렉토리의 text 하위 디렉토리에 생성할 것이므로 path/text 를 작성하고, Content Uri 에는 Galaxy 로 표출되도록 합니다.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="Galaxy" path="/text" />
</paths>

AndroidManifest.xml 에 file_paths.xml 등록

<provider
	android:name="com.galaxy.study.GalaxyFileProvider"
    android:authorities="com.galaxy.study.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
  	<meta-data
		android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

텍스트 파일 생성

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val txtFile: File = File.createTempFile(
            "JPEG_${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))}_",
            ".txt",
            baseContext.getExternalFilesDir("text"),
        )
        
        //...
    }
}

baseContext.getExternalFilesDir("text") 로 하여 외부 디렉토리 하위 /text 경로에 파일을 생성합니다.
/text 디렉토리를 제외하고 외부 디렉토리 어떤 곳에도 FileProvider 는 접근 권한이 없습니다.

텍스트 파일 Uri 출력

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val txtFile: File = File.createTempFile(
            "JPEG_${LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))}_",
            ".txt",
            baseContext.getExternalFilesDir("text"),
        )
        val txtFileUri: Uri = FileProvider.getUriForFile(baseContext, "com.galaxy.study.fileprovider", txtFile)
        Log.d("[TEST] KEH", "txtFileUri: $txtFileUri")
    }
}

FileProvider.getUriForFile() 함수로 텍스트 파일의 Content Uri 를 확인할 수 있습니다.

로그값을 통해 원하는 경로에 텍스트 파일이 생성된 것을 확인할 수 있습니다.

txtFileUri: content://com.galaxy.study.fileprovider/Galaxy/JPEG_20250112_211013_5567873940185002516.txt


Android 공식문서 > FileProvider

profile
:P

0개의 댓글