Android 4.4(API 수준 19)에는 저장소 액세스 프레임워크(SAF)가 도입되었습니다. SAF를 사용하면 사용자가 선호하는 모든 문서 저장소 제공업체에서 문서, 이미지 및 기타 파일을 둘러보고 열 수 있습니다. 표준형의 사용하기 쉬운 UI를 사용하면 사용자가 각종 앱과 제공자에서 일관된 방식으로 파일을 탐색하고 최근 파일에 액세스할 수 있습니다.
클라우드 또는 로컬 저장소 서비스가 이 생태계에 참여하려면 서비스를 캡슐화하는 DocumentsProvider를 구현하면 됩니다. 제공자의 문서에 액세스해야 하는 클라이언트 앱의 경우 단 몇 줄의 코드만으로 SAF와 통합할 수 있습니다.
SAF에는 다음과 같은 항목이 포함됩니다.
문서 제공자: Google Drive와 같은 저장소 서비스가 관리하는 파일을 표시할 수 있는 콘텐츠 제공자입니다. 문서 제공자는 DocumentsProvider 클래스의 서브클래스로 구현됩니다.
문서 제공자 스키마는 일반적인 파일 계층 구조에 기초하지만 문서 제공자가 물리적으로 데이터를 저장하는 방식은 개발자가 결정합니다.
Android 플랫폼에는 여러 가지 내장된 문서 제공자(예: 다운로드, 이미지, 동영상)가 포함됩니다.
선택 도구: 사용자가 클라이언트 앱의 검색 기준을 충족하는 모든 문서 제공자의 문서에 액세스할 수 있는 시스템 UI입니다.
SAF는 다음과 같은 기능을 제공합니다.
사용자가 하나의 앱뿐만 아니라 모든 문서 제공자에서 콘텐츠를 탐색할 수 있습니다.
앱이 문서 제공자가 소유한 문서에 장기적, 지속적 액세스 권한을 가질 수 있습니다. 이 액세스 권한을 통해 사용자는 제공자에서 파일을 추가, 수정, 저장, 삭제할 수 있습니다.
여러 개의 사용자 계정을 지원하며 USB 저장소 제공자와 같은 임시 루트도 지원합니다. 이는 드라이브가 연결되어 있을 때만 나타납니다.
개요
SAF는 DocumentsProvider 클래스의 서브클래스인 콘텐츠 제공자를 중심으로 작동합니다. 데이터는 문서 제공자 내에서 일반적인 파일 계층으로 구조화됩니다.
그림 1. 문서 제공자 데이터 모델. 루트 하나가 하나의 문서를 가리키고, 이는 다시 트리의 팬아웃을 시작합니다.
다음 내용을 참고하세요.
각 문서 제공자는 하나 이상의 루트를 보고합니다. 이 루트는 문서 트리를 탐색하는 시작 지점입니다.
각 루트는 고유한 COLUMN_ROOT_ID가 있고 루트 아래에 있는 콘텐츠를 나타내는 문서 (디렉터리)를 가리킵니다.
기본적으로 루트는 동적으로 움직여 다중 계정, 임시 USB 저장소 기기 또는 사용자 로그인 및 로그아웃과 같은 사용 사례를 지원합니다.
각 루트 아래에 문서가 하나씩 있습니다. 문서는 1부터 N까지의 문서를 가리키는데, 이는 각각 1부터 N까지의 문서를 가리킬 수 있습니다.
각 저장소 백엔드는 고유한 COLUMN_DOCUMENT_ID로 개별 파일과 디렉터리를 참조하는 방법으로 표시합니다.
문서 ID는 고유하며 한 번 발행되고 나면 변경되지 않습니다. 이들은 기기 재부팅을 통괄하여 영구적인 URI 허가에 사용되기 때문입니다.
문서는 열 수 있는 파일이거나(특정 MIME 유형으로) 추가 문서가 들어 있는 디렉터리일 수 있습니다(MIME_TYPE_DIR MIME 유형으로).
문서 제공자 데이터 모델은 일반적인 파일 계층 구조를 기반으로 합니다. 그러나 DocumentsProvider API를 사용하여 이에 액세스할 수 있는 한, 데이터를 원하는 방식으로 물리적으로 저장할 수 있습니다. 예를 들어 데이터를 저장하는 데 태그 기반 클라우드 스토리지를 사용할 수 있습니다.
그림 2는 사진 앱이 SAF를 사용하여 저장된 데이터에 액세스할 수 있는 방법을 보여줍니다.
그림 2. 저장소 액세스 프레임워크 흐름
다음 내용을 참고하세요.
SAF에서는 제공자와 클라이언트가 직접 상호작용하지 않습니다. 클라이언트가 파일과 상호작용하기 위한 권한을 요청합니다(다시 말해, 파일을 읽고, 수정하거나 생성 또는 삭제할 권한을 말합니다).
상호작용은 애플리케이션(이 예시에서는 사진 앱)이 인텐트 ACTION_OPEN_DOCUMENT 또는 ACTION_CREATE_DOCUMENT를 실행하면 시작됩니다.
인텐트에는 기준을 더욱 세분화하는 필터가 포함될 수 있습니다. 예를 들어 '열 수 있는 파일 중에서 '이미지' MIME 유형이 있는 파일을 모두 주세요'라고 할 수 있습니다.
인텐트가 실행되면 시스템 선택도구가 등록된 각 제공자로 이동하여 사용자에게 일치하는 콘텐츠 루트를 보여 줍니다.
선택 도구는 기본 문서 제공자가 매우 다르더라도 사용자에게 문서에 액세스하는 데 쓰는 표준 인터페이스를 제공합니다. 예를 들어 그림 2는 Google 드라이브 제공자, USB 제공자와 클라우드 제공자를 나타낸 것입니다.
그림 3에서 사용자는 이미지 검색에서 열린 선택 도구에서 다운로드 폴더를 선택하고 있습니다. 선택 도구에는 클라이언트 앱에서 사용할 수 있는 모든 루트도 표시됩니다.
그림 3. 다운로드 폴더가 검색 위치로 선택된 선택 도구
사용자가 다운로드 폴더를 선택하면 이미지가 표시됩니다. 그림 4는 이 프로세스의 결과를 보여 줍니다. 이제 사용자는 제공자와 클라이언트 앱이 지원하는 방식으로 이미지와 상호작용할 수 있습니다.
그림 4. 시스템 선택 도구에 표시된, 다운로드 폴더에 저장된 이미지
클라이언트 앱 작성
Android 4.3 이하에서는 앱이 다른 앱에서 파일을 검색할 수 있게 하려면 ACTION_PICK 또는 ACTION_GET_CONTENT와 같은 인텐트를 호출해야 합니다. 그런 다음 사용자는 파일을 선택할 앱을 하나 선택합니다. 선택한 앱은 사용자가 이용 가능한 파일에서 탐색하고 선택할 수 있는 사용자 인터페이스를 제공해야 합니다.
Android 4.4 (API 수준 19) 이상에서는 ACTION_OPEN_DOCUMENT 인텐트를 사용하는 추가 옵션이 있습니다. 이 인텐트는 사용자가 다른 앱에서 제공한 모든 파일을 탐색할 수 있는 시스템 제어 선택 도구 UI를 표시합니다. 이 하나의 UI에서 사용자는 지원되는 모든 앱의 파일을 선택할 수 있습니다.
Android 5.0 (API 수준 21) 이상에서는 ACTION_OPEN_DOCUMENT_TREE 인텐트를 사용할 수도 있습니다. 이 인텐트로 사용자는 클라이언트 앱이 액세스할 디렉터리를 선택할 수 있습니다.
참고: ACTION_OPEN_DOCUMENT는 ACTION_GET_CONTENT를 대체하지 않습니다.
사용할 방법은 앱의 요구사항에 따라 다릅니다.
앱이 데이터를 읽거나 가져오도록 하려면 ACTION_GET_CONTENT를 사용합니다. 이 방식을 사용하면 앱은 데이터 사본(예: 이미지 파일)을 가져오게 됩니다.
앱이 문서 제공자가 소유한 문서에 장기적, 지속적 액세스 권한을 가지기를 바라는 경우에는 ACTION_OPEN_DOCUMENT를 사용합니다. 사용자가 문서 제공자에 저장된 이미지를 수정할 수 있는 사진 편집 앱을 예로 들 수 있습니다.
시스템 선택 도구 UI를 사용하여 파일 및 디렉터리 탐색을 지원하는 방법에 관한 자세한 내용은 문서 및 기타 파일에 액세스하는 방법 가이드를 참고하세요.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[null,null,["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Open files using the Storage Access Framework\n\nAndroid 4.4 (API level 19) introduces the Storage Access Framework (SAF). The SAF\nlets users browse and open documents, images, and other files\nacross all of their preferred document storage providers. A standard, easy-to-use UI\nlets users browse files and access recent files in a consistent way across apps and providers.\n\nCloud or local storage services can participate in this ecosystem by implementing a\n[DocumentsProvider](/reference/android/provider/DocumentsProvider) that encapsulates their services. Client\napps that need access to a provider's documents can integrate with the SAF with a few\nlines of code.\n\nThe SAF includes the following:\n\n- **Document provider:** a content provider that lets a storage service, such as Google Drive, reveal the files it manages. A document provider is implemented as a subclass of the [DocumentsProvider](/reference/android/provider/DocumentsProvider) class. The document-provider schema is based on a traditional file hierarchy, though how your document provider physically stores data is up to you. The Android platform includes several built-in document providers, such as Downloads, Images, and Videos.\n- **Client app:** a custom app that invokes the [ACTION_CREATE_DOCUMENT](/reference/android/content/Intent#ACTION_CREATE_DOCUMENT), [ACTION_OPEN_DOCUMENT](/reference/android/content/Intent#ACTION_OPEN_DOCUMENT), and [ACTION_OPEN_DOCUMENT_TREE](/reference/android/content/Intent#ACTION_OPEN_DOCUMENT_TREE) intent actions and receives the files returned by document providers.\n- **Picker:** a system UI that lets users access documents from all document providers that satisfy the client app's search criteria.\n\nSAF offers the following features:\n\n- Lets users browse content from all document providers, not just a single app.\n- Makes it possible for your app to have long-term, persistent access to documents owned by a document provider. Through this access, users can add, edit, save, and delete files on the provider.\n- Supports multiple user accounts and transient roots such as USB storage providers, which only appear if the drive is plugged in.\n\nOverview\n--------\n\nThe SAF centers around a content provider that is a\nsubclass of the [DocumentsProvider](/reference/android/provider/DocumentsProvider) class. Within a document provider, data is\nstructured as a traditional file hierarchy:\n**Figure 1.** Document provider data model. A root points to a single document, which then starts the fan-out of the tree.\n\nNote the following:\n\n- Each document provider reports one or more *roots* , which are starting points into exploring a tree of documents. Each root has a unique [COLUMN_ROOT_ID](/reference/android/provider/DocumentsContract.Root#COLUMN_ROOT_ID), and it points to a document (a directory) representing the contents under that root. Roots are dynamic by design to support use cases like multiple accounts, transient USB storage devices, or user login and logout.\n- Under each root is a single document. That document points to 1 to *N* documents, each of which in turn can point to 1 to *N* documents.\n- Each storage backend surfaces individual files and directories by referencing them with a unique [COLUMN_DOCUMENT_ID](/reference/android/provider/DocumentsContract.Document#COLUMN_DOCUMENT_ID). Document IDs are unique and don't change once issued, since they are used for persistent URI grants across device reboots.\n- Documents can be either an openable file, with a specific MIME type, or a directory containing additional documents, with the [MIME_TYPE_DIR](/reference/android/provider/DocumentsContract.Document#MIME_TYPE_DIR) MIME type.\n- Each document can have different capabilities, as described by [COLUMN_FLAGS](/reference/android/provider/DocumentsContract.Document#COLUMN_FLAGS). For example, [FLAG_SUPPORTS_WRITE](/reference/android/provider/DocumentsContract.Document#FLAG_SUPPORTS_WRITE), [FLAG_SUPPORTS_DELETE](/reference/android/provider/DocumentsContract.Document#FLAG_SUPPORTS_DELETE), and [FLAG_SUPPORTS_THUMBNAIL](/reference/android/provider/DocumentsContract.Document#FLAG_SUPPORTS_THUMBNAIL). The same `COLUMN_DOCUMENT_ID` can be included in multiple directories.\n\nControl flow\n------------\n\nThe document provider data model is based on a traditional\nfile hierarchy. However, you can physically store your data however you like, as\nlong as you can access it using the [DocumentsProvider](/reference/android/provider/DocumentsProvider)\nAPI. For example, you can use tag-based cloud storage for your data.\n\nFigure 2 shows how a photo app might use the SAF\nto access stored data:\n**Figure 2.** Storage Access Framework flow.\n\nNote the following:\n\n- In the SAF, providers and clients don't interact directly. A client requests permission to interact with files, meaning to read, edit, create, or delete files.\n- The interaction starts when an application, in this example a photo app, fires the intent [ACTION_OPEN_DOCUMENT](/reference/android/content/Intent#ACTION_OPEN_DOCUMENT) or [ACTION_CREATE_DOCUMENT](/reference/android/content/Intent#ACTION_CREATE_DOCUMENT). The intent can include filters to further refine the criteria, such as \"give me all openable files that have the 'image' MIME type.\"\n- Once the intent fires, the system picker goes to each registered provider and shows the user the matching content roots.\n- The picker gives users a standard interface for accessing documents, even when the underlying document providers are very different. For example, figure 2 shows a Google Drive provider, a USB provider, and a cloud provider.\n\nIn Figure 3, the user is selecting the Downloads folder from a picker opened in a search for\nimages. The picker also shows all of the roots available to the client app.\n**Figure 3.** Picker showing Downloads folder selected as a search location.\n\nAfter the user selects the Downloads folder, the images are displayed. Figure\n4 shows the result of this process. The user can now interact with the images\nin the ways that the provider and client app support.\n**Figure 4.** Images stored in the Downloads folder, as viewed in the system picker.\n\nWrite a client app\n------------------\n\nOn Android 4.3 and lower, if you want your app to retrieve a file from another\napp, it must invoke an intent such as [ACTION_PICK](/reference/android/content/Intent#ACTION_PICK)\nor [ACTION_GET_CONTENT](/reference/android/content/Intent#ACTION_GET_CONTENT). The user then selects\na single app from which to pick a file. The selected app must provide a user\ninterface for the user to browse and pick from the available files.\n\nOn Android 4.4 (API level 19) and higher, you have the additional option of using the\n[ACTION_OPEN_DOCUMENT](/reference/android/content/Intent#ACTION_OPEN_DOCUMENT) intent,\nwhich displays a system-controlled picker UI that lets the user\nbrowse all files that other apps have made available. From this single UI, the\nuser can pick a file from any of the supported apps.\n\nOn Android 5.0 (API level 21) and higher, you can also use the\n[ACTION_OPEN_DOCUMENT_TREE](/reference/android/content/Intent#ACTION_OPEN_DOCUMENT_TREE)\nintent, which lets the user choose a directory for a client app to\naccess. \n**Note:** `ACTION_OPEN_DOCUMENT` isn't a replacement for `ACTION_GET_CONTENT`.\nThe one you use depends on the needs of your app:\n\n- Use `ACTION_GET_CONTENT` if you want your app to read or import data. With this approach, the app imports a copy of the data, such as an image file.\n- Use `ACTION_OPEN_DOCUMENT` if you want your app to have long-term, persistent access to documents owned by a document provider. An example is a photo-editing app that lets users edit images stored in a document provider.\n\nFor more information about how to support browsing for files and directories\nusing the system picker UI, see the guide about\n[accessing documents and\nother files](/training/data-storage/shared/documents-files).\n\nAdditional resources\n--------------------\n\nFor more information about document providers, take advantage of the\nfollowing resources:\n\n### Samples\n\n- [StorageProvider](https://github.com/android/storage-samples/tree/main/StorageProvider)\n\n### Videos\n\n- [DevBytes: Android 4.4 Storage Access Framework: Provider](http://www.youtube.com/watch?v=zxHVeXbK1P4)\n- [Virtual Files in the Storage Access Framework](https://www.youtube.com/watch?v=4h7yCZt231Y)"]]