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

URI 또는 Uniform Resource Identifier는 인터넷이나 개인 인트라넷에서 리소스를 고유하게 식별하는 문자열입니다. Android에서는 파일, 이미지, 동영상과 같은 앱 내의 리소스를 찾는 데 URI를 사용합니다.
안드로이드에서 Uri 는 File Uri 와 Content Uri 가 있습니다.
File Uri 는 우리가 개발하는 앱에서 파일에 접근하기 위해 권한을 변경하면 우리 앱에서 뿐만 아니라 다른 앱에서도 파일 접근이 가능하게 됩니다. Uri 는 file:/// 로 시작합니다.
Content Uri 는 임시 쓰기, 읽기 접근 권한을 부여할 수 있고, Uri 를 전달할 때 Intent.setFlags() 함수를 호출하여 권한을 부여합니다. File Uri 와 다르게 임시 권한으로써 전달한 Activity 가 스택에 활성화 되어 있을 때 혹은 서비스가 실행중일 때만 권한이 적용됩니다. Uri 는 content:// 로 시작합니다.
Android 24 버전부터 안전한 파일 접근을 위해 Content Uri 를 사용해야 하며 FileProvider 를 통하여 Content Uri 에 접근할 수 있습니다.
FileProvider 를 사용하는 방법에 대해 알아보겠습니다.
원하는 경로에 FileProvider 클래스를 상속받는 커스텀 FileProvider 클래스를 선언합니다.
class MyFileProvider: FileProvider() {
}
android:name 에 MyFileProvider 를 등록합니다.
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>
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/<파일명>
이전 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 클래스를 상속하는 GalaxyFileProvider 클래스를 작성합니다.
class GalaxyFileProvider: FileProvider() {
}
android:name 에 GalaxyFileProvider 클래스를 등록합니다.
android:authorities 에 com.galaxy.study.fileprovider 으로 권한 이름을 설정합니다.
<provider
android:name="com.galaxy.study.GalaxyFileProvider"
android:authorities="com.galaxy.study.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
</provider>
텍스트 파일을 외부 디렉토리 경로에 생성할 것이므로 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>
<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 는 접근 권한이 없습니다.
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