Storage Access Frameworkは、システム選択ダイアログを通じてファイルやドキュメントに安全にアクセスするためのAndroidフレームワークです。ストレージ読み取りの広範な権限を要求する代わりに、アプリはユーザーが選択したファイルへのURIリンクを受け取ります。Android Developers(2026)によると、SAFはDocumentProviderを介してローカルストレージ、クラウドサービスのGoogle Drive、Dropboxをサポートしています。このフレームワークはAndroid 4.4で導入され、Android 10以降ドキュメントを扱う標準となりました。
主要ポイント
Storage Access Frameworkは、システムダイアログを通じてドキュメントを選択および作成するための統一インターフェースを提供するAndroid SDKの一部です。SAFはファイルの物理的な場所を抽象化します:アプリはファイルがローカルディスク、Google Drive、Dropboxのどこから読み取られているかを認識しません。
SAFアーキテクチャには3つのコンポーネントがあります:リクエストを開始するクライアントアプリ、標準的なファイル選択ダイアログであるシステムピッカー、特定のストレージのファイルへのアクセスを実装するコンテンツプロバイダであるDocumentProviderです。ユーザーはデータソースに関係なく統一されたインターフェースを表示します。
SAFはAndroid 4.4(API 19)から利用可能です。当初はドキュメントのみをサポートしていましたが、Android 5.0でACTION_OPEN_DOCUMENT_TREEによるディレクトリのサポートが追加されました。Android 10以降、SAFはアプリ固有ストレージ外のファイルにアクセスする推奨方法となりました。
SAFは、ACTION_OPEN_DOCUMENTアクションを持つIntentを介してシステムファイル選択ダイアログを起動します。ユーザーは利用可能なソース(内部ストレージ、Google Drive、Dropbox、その他登録されたプロバイダ)のリストを表示します。ファイル選択後、システムは一時的なアクセス権を持つcontent URIを返します。
content URIの形式はcontent://com.android.externalstorage.documents/document/primary/Download/file.pdfです。file:// URIとは異なり、content URIは実際のファイルパスを公開せず、DocumentProviderを介して動作します。アプリは取得したURIを使用してContentResolver.openInputStreamを介してファイルを読み取ります。
システムピッカーは自動的にMIMEタイプによるファイルの検索、並べ替え、フィルタリングをサポートします。開発者はIntent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*"))を介して必要なタイプを指定し、ピッカーは関連するファイルのみを表示します。
デフォルトでは、URIはアプリの再起動またはデバイスの再起動まで有効です。長期アクセスのために、アプリはtakePersistableUriPermissionを要求します。これにより、ダイアログで再選択することなく、後続の起動でファイルを読み取ることができます。
SAFは、ファイルを操作するための3つの主要なアクション(開く、作成する、フォルダツリーを選択する)を提供します。ACTION_OPEN_DOCUMENTは既存のファイルを選択するためにシステムピッカーを開きます。ACTION_CREATE_DOCUMENTは新しいファイルを作成します。ユーザーはダイアログに名前を入力し、アプリは書き込み用のURIを受け取ります。
ACTION_OPEN_DOCUMENT_TREEは、ディレクトリ全体を選択し、その中のすべてのファイルへのアクセスを取得できます。これはファイルマネージャー、バックアップアプリ、同期ツールで使用されます。アプリはディレクトリURIを受け取り、DocumentFileを介してコンテンツを再帰的に列挙できます。
| アクション | 目的 | フラグ |
|---|---|---|
| ACTION_OPEN_DOCUMENT | 既存のファイルを選択 | READ_FLAG |
| ACTION_CREATE_DOCUMENT | 新しいファイルを作成 | WRITE_FLAG |
| ACTION_OPEN_DOCUMENT_TREE | ディレクトリを選択 | READ + WRITE |
各アクションに対して、MIMEタイプはEXTRA_MIME_TYPESを介して指定されます。複数のタイプ("application/pdf"、"image/*"、"text/plain")を指定できます。タイプが指定されていない場合、ピッカーはすべてのファイルを表示します。
Persistent URI permissionsは、現在のセッション終了後もファイルへのアクセスを維持できるSAFのメカニズムです。このフラグがない場合、URIはアプリの再起動までのみ有効です。アプリはREADフラグとWRITEフラグとともにFLAG_GRANT_PERSISTABLE_URI_PERMISSIONフラグを要求します。
権限を保存するには、ContentResolver.takePersistableUriPermissionメソッドを使用します。システムはURIを特別なレジストリに保存し、次回のアプリ起動時にアクセスを復元します。アプリがURIへの永続的アクセスを持っているかどうかを確認するには、ContentResolver.persistedUriPermissionsを使用します。
ユーザーは設定→アプリ→権限から保存された権限を取り消すことができます。アプリはファイルへのアクセスが予期せず失われたシナリオを処理する必要があります。作業を開始する前にContentResolver.openInputStreamを介してアクセスを確認し、SecurityExceptionを適切に処理することをお勧めします。
SAFは標準のIntentを介して起動されます。コードは最小限です:ACTION_OPEN_DOCUMENTでIntentを作成し、MIMEタイプを指定し、ActivityResultContracts.StartActivityForResultを介して起動します。ファイル選択後、callbackはdata.dataでURIを受け取り、それを読み取りに使用します。
val pickFile = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
result.data?.data?.let { uri ->
val inputStream = contentResolver?.openInputStream(uri)
// read from inputStream
}
}
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
setType("application/pdf")
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
pickFile.launch(intent)
新しいファイルに書き込むには、ACTION_CREATE_DOCUMENTを使用します。IntentはMIMEタイプとEXTRA_TITLEを介したファイル名を受け入れます。フォルダを選択して確認した後、ユーザーはURIを返し、アプリはContentResolver.openOutputStreamを介してデータを書き込みます。システムは自動的に選択された場所にファイルを作成します。
SAFは、従来のREAD_EXTERNAL_STORAGEとはセキュリティに対する根本的に異なるアプローチで異なります。一度にストレージ全体へのアクセスを要求する代わりに、SAFは特定のファイルへのアクセスのみを要求します。これにより攻撃対象領域が最小限に抑えられ、ユーザーの信頼が高まります。
READ_EXTERNAL_STORAGEは、他のアプリの写真やドキュメントを含む、デバイス上のすべてのファイルへのアクセスを許可します。Android 10+では、このアプローチは制限されています。対照的に、SAFはユーザーが選択したファイルへのアクセスのみを提供し、ファイルごとに明示的な確認を必要とします。バッチメディア操作にはMediaStoreを、個別のドキュメントにはSAFを使用してください。
SAFの主な欠点は、各ファイルを個別に選択する必要があることです。一括操作(バックアップ、フォルダ同期)には、ACTION_OPEN_DOCUMENT_TREEを使用します。これにより、選択したディレクトリ内のすべてのファイルへのアクセスが許可されます。解決策はシナリオによって異なります:SAFはユーザー選択に最適で、MediaStoreはプログラムによるメディアアクセスに最適です。
よくある質問
Storage Access Frameworkは、システム選択ダイアログを通じて安全なファイルアクセスを提供するAndroidフレームワークです。アプリはストレージ読み取りの広範な権限を要求せずに、選択されたファイルのcontent URIを受け取ります。
ACTION_OPEN_DOCUMENTでIntentを作成し、setTypeでMIMEタイプを指定し、ActivityResultContractsを介して起動します。コールバックでdata.dataからURIを取得し、ContentResolver.openInputStreamを介して読み取ります。
Persistent URI permissionsは、アプリ再起動後もURIへのアクセスを維持するメカニズムです。FLAG_GRANT_PERSISTABLE_URI_PERMISSIONフラグとtakePersistableUriPermissionメソッドを介して要求されます。
SAFは任意のMIMEタイプ(application/pdf、image/*、text/plain、application/zipなど)をサポートしています。タイプはEXTRA_MIME_TYPES配列を使用してIntent.putExtraを介して指定されます。
SAFは、ユーザーがシステムダイアログを通じて個別のファイルを選択するために設計されています。MediaStoreは、ユーザーの操作なしでメディアデータベースを介してデバイス上のすべてのメディアファイルへのプログラムによるアクセスを提供します。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。