Android Developers
AI-assisted summary of Preparing for scoped storage (Android Dev Summit '19) — original source. Check the original for full context.
Source published:
Key ideas
- Android 10 introduced Scoped Storage to isolate app data and clean up external storage, with 98% of apps targeting Android 10 adopting it without declaring the temporary legacy opt-out flag. (5:23)
- Apps can contribute to shared media collections (Images, Video, Audio) and the Downloads folder without any runtime permissions, but reading third-party files outside media collections requires the Storage Access Framework (SAF). (2:05)
- In response to developer feedback, the next Android release will reintroduce direct POSIX file path access for reading media by routing calls through MediaStore under the hood, alongside batch dialogs for modifying third-party files. (14:37)
- Apps requiring broad filesystem access, such as file managers and backup utilities, will require a dedicated Special App Access permission subject to a Google Play declaration and review process. (19:52)
Detailed notes
## Background Published on YouTube by the Android Developers channel on October 24, 2019, this Android Dev Summit '19 session is presented by Android Framework team members Roxanna Aliabadi, Zimuzo Ezeozue, and Yacine Rezgui. The presentation provides a roadmap and practical guide for developers adapting to the scoped storage architecture introduced in Android 10.
## TL;DR The speakers detail the shift to Scoped Storage in Android 10, explaining how the platform restricts broad disk access to protect user privacy, prevent orphaned files, and sandbox application data. In response to community feedback on early disruption, the team outlines key adjustments planned for the subsequent Android release, such as bridging POSIX file paths to MediaStore, enabling batch edit consent dialogs, and establishing a Google Play-governed access path for dedicated file managers. Practical code walkthroughs demonstrate how to query media via ContentResolver, handle permission challenges through RecoverableSecurityException, and integrate the Storage Access Framework for document picking without requesting broad storage permissions.
## Atmosphere & style The talk maintains a pragmatic, responsive, and reassuring tone as the speakers directly acknowledge the disruption caused by early Scoped Storage rollouts and emphasize how developer feedback shaped subsequent platform changes. Roxanna Aliabadi and Zimuzo Ezeozue provide structured, high-level architectural clarity before Yacine Rezgui leads an earnest, code-focused demonstration with relatable live-stage moments. The session feels like an open engineering dialogue, balancing firm platform privacy mandates with an accommodating attitude toward practical developer workflows.
## Bulletin - [05:23](https://www.youtube.com/watch?v=UnJ3amzJM94&t=323s) Android 10 introduced Scoped Storage to isolate app data and clean up external storage, with 98% of apps targeting Android 10 adopting it without declaring the temporary legacy opt-out flag. - [02:05](https://www.youtube.com/watch?v=UnJ3amzJM94&t=125s) Apps can contribute to shared media collections (Images, Video, Audio) and the Downloads folder without any runtime permissions, but reading third-party files outside media collections requires the Storage Access Framework (SAF). - [14:37](https://www.youtube.com/watch?v=UnJ3amzJM94&t=877s) In response to developer feedback, the next Android release will reintroduce direct POSIX file path access for reading media by routing calls through MediaStore under the hood, alongside batch dialogs for modifying third-party files. - [19:52](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1192s) Apps requiring broad filesystem access, such as file managers and backup utilities, will require a dedicated Special App Access permission subject to a Google Play declaration and review process.
## Key takeaways - [00:00](https://www.youtube.com/watch?v=UnJ3amzJM94&t=0s) Historically, roughly half of all Android apps requested broad storage permissions, leading to scattered, orphaned files on external storage when apps were uninstalled. - [02:05](https://www.youtube.com/watch?v=UnJ3amzJM94&t=125s) Scoped Storage is anchored on three core principles: better file attribution, protecting private app data, and safeguarding user data such as private photos and tax forms. - [02:05](https://www.youtube.com/watch?v=UnJ3amzJM94&t=125s) Apps have unrestricted, permissionless access to their own app-specific directories on both internal storage and SD cards under Android 10. - [13:11](https://www.youtube.com/watch?v=UnJ3amzJM94&t=791s) Accessing EXIF geographic location coordinates requires the ACCESS_MEDIA_LOCATION runtime permission, preventing unauthorized tracking via shared photos. - [13:11](https://www.youtube.com/watch?v=UnJ3amzJM94&t=791s) Developers can invoke MediaStore.setRequireOriginal() to ensure bit-for-bit fidelity and avoid silent stripping of sensitive image metadata. - [05:23](https://www.youtube.com/watch?v=UnJ3amzJM94&t=323s) The requestLegacyExternalStorage manifest flag was introduced as a temporary bridge for Android 10, but Google announced it will be fully deprecated in future releases. - [05:23](https://www.youtube.com/watch?v=UnJ3amzJM94&t=323s) Scoped Storage enforcement in the subsequent release will be tied strictly to targetSdkVersion rather than being forced universally across all installed legacy apps. - [10:06](https://www.youtube.com/watch?v=UnJ3amzJM94&t=606s) The legacy WRITE_EXTERNAL_STORAGE permission is slated for deprecation and will effectively function as a synonym for read access to media files. - [14:37](https://www.youtube.com/watch?v=UnJ3amzJM94&t=877s) Direct POSIX file path I/O acts as an internal delegation wrapper over MediaStore, introducing minor overhead on file open calls while preserving all MediaStore security rules. - [28:33](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1713s) Modifying or deleting media owned by another app triggers a RecoverableSecurityException, which provides a PendingIntent to display a user consent prompt. - [18:11](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1091s) The upcoming platform release will introduce bulk consent dialogs, eliminating the need to pop individual confirmation dialogs for each file edit. - [19:52](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1192s) The Storage Access Framework's ACTION_OPEN_DOCUMENT_TREE intent will explicitly block user selection of root storage directories, the Downloads directory, and Android/data. - [30:15](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1815s) Document-based workflows like email attachments should rely on SAF intents (such as ACTION_OPEN_DOCUMENT and ACTION_CREATE_DOCUMENT) instead of asking for runtime storage permissions. - [30:15](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1815s) Permissions obtained via the system file picker are temporary across device reboots unless explicitly retained using takePersistableUriPermission(). - [33:12](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1992s) Hardcoded file paths must be avoided in favor of building Content URIs dynamically using platform constants and MediaStore IDs.
## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=UnJ3amzJM94&t=0s) Introduction to Scoped Storage and the Problem with Shared Storage
Roxanna Aliabadi, a product manager on the Android Framework team, introduces the session alongside colleagues Zimuzo Ezeozue and Yacine Rezgui. In Android 10, the team unveiled a fundamental architectural shift known as Scoped Storage to reform how apps interact with on-device files. To establish context, Roxanna distinguishes between private and shared storage. Private storage consists of dedicated app directories located at `Android/data/<package_name>` on internal storage, which remain completely hidden from any other application, regardless of whether that other app holds storage permissions. Everything outside these boundaries—including media collections and external directories residing on SD cards—constitutes shared storage.
Historically, roughly half of all Android apps requested the broad storage permission. However, the vast majority of these applications never actually required such sweeping authority. Roxanna observes that most were merely executing simple tasks such as picking a profile photo in a social app or downloading an email attachment. Giving applications unconstrained write access created a severe file-hygiene crisis across the ecosystem: apps frequently scattered miscellaneous files across external storage and left them stranded upon uninstallation. These orphaned files accumulated over time, consuming crucial space on devices where end users were already struggling with low disk capacity.
```mermaid flowchart TD accTitle: Android Storage Architecture Comparison accDescr: Contrasts private app storage with shared storage, illustrating access controls and legacy sprawl issues.
subgraph Private["Private Internal Storage"] P1["android/data/package_name"] P2["Only accessible to owning app"] P1 --- P2 end
subgraph Shared["Shared External Storage"] S1["Organized Media (Images, Video, Audio)"] S2["Downloads Collection"] S3["SD Card App Directories"] S4["Unorganized Disk Space (Scattered files)"] end
Private -.->|"Isolated from other apps"| Shared ```
[02:05](https://www.youtube.com/watch?v=UnJ3amzJM94&t=125s) Design Principles and Android 10 Implementations
To eliminate indiscriminate disk access while still satisfying real application requirements, the Android team designed Scoped Storage around three core principles: better attribution, protecting app data, and protecting user data. Better attribution ensures the operating system explicitly tracks which application created each file, simplifying user storage management and ensuring that when an application is uninstalled, its lingering data is automatically purged unless the user chooses to retain it. Protecting app data involves closing access loopholes so external app directories on SD cards cannot be casually snooped on by other software. Protecting user data ensures sensitive files—such as personal photos downloaded from private chats or tax returns saved as PDFs—are completely shielded from third-party apps holding standard storage permissions.
Under Android 10 Scoped Storage, applications receive unrestricted, permissionless access to their own internal and external package directories, meaning writing to an app-specific SD card folder no longer requires any manifest storage permission. Additionally, apps can contribute new files directly into organized shared collections (Images, Video, Audio, and the new Downloads collection) without requesting any user permission. The traditional runtime storage permission has been redefined: granting it no longer gives a blanket view of the file system, but instead provides read access strictly to media collections. Furthermore, because EXIF metadata can reveal sensitive personal locations, Android 10 introduces the `ACCESS_MEDIA_LOCATION` permission; if an application fails to declare and obtain this permission, geographic coordinates are automatically stripped whenever it reads media files.
- Reading general documents (such as PDF files) requires delegating access through the system picker via the Storage Access Framework (SAF). - Writing files outside of dedicated app sandboxes or organized media collections requires user selection via the system file picker. - System picker requirements ensure the user retains complete agency over where unorganized files are placed on disk.
[05:23](https://www.youtube.com/watch?v=UnJ3amzJM94&t=323s) Ecosystem Feedback, Legacy Flags, and the Next Android Release
When Scoped Storage was introduced during the early beta phase of Android 10, the team initially enforced it across all applications regardless of their `targetSdkVersion`. The developer community pushed back vigorously, emphasizing that such an enormous architectural disruption was impossible to adopt within the beta timeline. In response, Google added the `requestLegacyExternalStorage` manifest attribute, allowing apps targeting Android 10 to temporarily opt out and preserve legacy storage behavior. Roxanna notes that among apps targeting Android 10, 98% did not declare this legacy flag, validating that the scoped model meets the needs of mainstream apps.
> “This shows us that the changes we introduced with Scoped Storage are acceptable to most developers.” — Roxanna Aliabadi
Nevertheless, the framework team recognized that many applications had not yet migrated to Android 10, and the remaining 2% represented critical use cases facing real friction. Developers highlighted several recurring pain points: 1. **File paths and native code:** Android 10 broke support for standard POSIX file paths and C/C++ native libraries when interacting with media files. 2. **Heavy-duty storage apps:** Utilities like file managers and backup/restore suites struggled with SAF, reporting severe performance bottlenecks when traversing deeply nested folder trees, alongside awkward user onboarding flows that required users to select disk roots manually. 3. **Muddled permission semantics:** The storage permission meant media-only access for updated apps, but wide-open disk access for un-migrated apps, confusing users and developers alike.
To avoid developers writing code for Android 10 that they would have to undo immediately afterward, Roxanna outlines upcoming storage changes planned for the subsequent Android release. The system permission dialog will visually distinguish whether an app is receiving media-only access or broad storage access. Native code and file paths are returning for reading media files, and APIs for editing or deleting files created by other apps will be streamlined with bulk operations. For specialized utilities like file managers, Android is introducing a dedicated "Special App Access" broad-storage permission subject to Google Play approval. Furthermore, SAF will block users from granting access to raw external app directories, closing an ongoing privacy leak. Critically, the team decided to enforce Scoped Storage based on `targetSdkVersion` rather than applying it universally across all installed apps:
> “Last year, we did say that we would be enforcing this regardless of target SDK for all apps on the next release of Android. But really, we think that the best thing for the users is to introduce these changes gradually.” — Roxanna Aliabadi
[10:06](https://www.youtube.com/watch?v=UnJ3amzJM94&t=606s) Media Collections and Permissions Deep Dive
Zimuzo Ezeozue takes over to detail the technical mechanics of media collections across Android 10 and the subsequent platform release. Since Android's earliest days, shared media has been organized into Audio, Images, and Video tables. Under Android 10, any application can insert new files into these collections without requesting runtime storage permissions. An application also retains implicit, unrestricted edit and deletion rights over any media files it contributed itself.
Reading media files authored by other applications still requires the `READ_EXTERNAL_STORAGE` permission. Looking ahead to the next Android release, the legacy `WRITE_EXTERNAL_STORAGE` permission will be deprecated, acting merely as a synonym for read access to media files. Modifying or deleting media that belongs to other applications is strictly prohibited unless explicit user consent is granted through a system confirmation dialog. As Zimuzo emphasizes, this prevents rogue or buggy applications from altering or deleting precious user pictures without their clear knowledge and approval.
[11:30](https://www.youtube.com/watch?v=UnJ3amzJM94&t=690s) Permission Strings and the Downloads Collection
Depending on the target SDK version of an application, users will encounter two different permission strings when storage access is requested. If an app targets the upcoming Android release, the system presents a modernized permission string that explicitly asks only for access to media files on external storage. Conversely, applications targeting older releases will continue to display the legacy storage permission prompt that requests broad access to the entire external storage. This distinction is designed so that “users will understand how much access your app is requesting.”
Android 10 also introduced a dedicated Downloads collection designed specifically for sharing non-media files across applications. Contributing files to this collection, as well as updating or deleting files that your own app contributed, requires no permissions whatsoever. Accessing non-media files contributed by third-party applications, however, differs fundamentally from media handling: the standard `READ_EXTERNAL_STORAGE` permission grants zero access to non-media files created by other apps. To access those files, an app must trigger the system picker via the Storage Access Framework (SAF) APIs. Once a user explicitly chooses a file or folder through SAF, the app receives full read, edit, and delete permissions for that selection without requiring subsequent consent prompts. This strict boundary protects sensitive user documents, such as bank statements, from unwarranted inspection.
```mermaid flowchart TD accTitle: Accessing Non-Media Files Flowchart accDescr: Decision flow showing how an app accesses non-media files depending on whether it owns the file.
Start["Access Non-Media File"] --> Owner{"App contributed file?"} Owner -- "Yes" --> Direct["Full Read / Edit / Delete\n(No permissions required)"] Owner -- "No" --> SAF["Storage Access Framework\n(Launch system file picker)"] SAF --> UserGrant["User explicitly selects file"] UserGrant --> FullAccess["Full Read / Edit / Delete Granted\n(No further consent needed)"] ```
[13:11](https://www.youtube.com/watch?v=UnJ3amzJM94&t=791s) Sensitive Metadata Redaction and MediaStore.setRequireOriginal
Protecting sensitive user data stands as a core priority on Android. Starting in Android 10, the platform transparently strips sensitive metadata—most notably geographic location coordinates—whenever an app inspects media files that were contributed by other applications. If an application legitimately requires location tags or similar EXIF information, it must declare and request the `ACCESS_MEDIA_LOCATION` runtime permission alongside `READ_EXTERNAL_STORAGE`.
Even though `ACCESS_MEDIA_LOCATION` is a runtime permission, it does not show up as a toggle in the system Settings UI. Furthermore, holding `READ_EXTERNAL_STORAGE` does not guarantee that location access will be granted. Zimuzo Ezeozue warns that this caveat is “especially true on enterprise devices where a device policy client can modify or change permissions requested by other apps.” For applications where bit-for-bit fidelity is critical, developers can invoke `MediaStore.setRequireOriginal()`. This API ensures that the app either receives the exact original byte stream from the storage media or throws an exception if redaction would have taken place, preventing subtle corruption or silent data loss in workflows that rely on unaltered image buffers.
- `ACCESS_MEDIA_LOCATION` must be defined in the app manifest and requested at runtime. - The permission has no user-facing toggle inside the standard system Settings app. - `MediaStore.setRequireOriginal()` guarantees either unredacted original bytes or an explicit exception.
[14:37](https://www.youtube.com/watch?v=UnJ3amzJM94&t=877s) File Path Access and Performance Tradeoffs
Android 10 initially locked down direct file path access across common shared directories to satisfy privacy benchmarks. However, the engineering team realized that migrating legacy codebases all at once proved painful. Zimuzo Ezeozue explains: “However, after going through the developer feedback, we saw that this required a lot of effort from you to adopt straight away. And in the next Android release, we will likely do this work for you.” Although MediaStore remains the strongly recommended path forward, Google recognizes that many apps rely on third-party C and C++ native libraries that operate strictly on POSIX file paths.
```mermaid flowchart LR accTitle: File Path Delegation to MediaStore accDescr: Architecture showing how POSIX file path calls delegate to MediaStore under the hood.
subgraph NativeApp["Application Layer"] FP["File Path / POSIX I/O\n(C / C++ / java.io.File)"] MS["MediaStore API Direct"] end
subgraph PlatformLayer["Android Platform Layer"] Bridge["Internal Delegation Layer\n(Path mapping & security checks)"] MediaStoreEngine["MediaStore Engine"] end
FP --> Bridge Bridge --> MediaStoreEngine MS --> MediaStoreEngine ```
Under the hood, all file path I/O calls are transparently delegated to MediaStore, acting essentially as a convenience wrapper. Consequently, using direct file paths confers no feature advantage and introduces a minor performance penalty. All standard MediaStore rules apply to file path operations: - Media items must reside in their designated directory types (e.g., audio files cannot be placed in the `Pictures/` folder). - Reading third-party media through file paths still mandates `READ_EXTERNAL_STORAGE`. - Location redaction still occurs unless `ACCESS_MEDIA_LOCATION` is active. - Non-media files (such as PDFs) must be written exclusively to `Download/`. - Accessing non-media files generated by other apps through file paths still requires initial authorization via SAF. - Files created via file paths are properly attributed to the calling app and count against its storage quota.
While internal benchmarks covering sequential and random I/O demonstrate that the overhead of file path delegation is negligible at low I/O rates, opening files and reading the initial bytes remains computationally expensive. Zimuzo Ezeozue cautions developers against thrashing file descriptors: “So if you're going to use file paths, please try to avoid opening and closing the same file multiple times.” Apps performing high-throughput I/O—in the neighborhood of hundreds of megabytes per second—are invited to consult directly with the storage team at the conference sandbox.
[18:11](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1091s) User Consent for Media Modifications and Batching Improvements
Under Android 10, modifying or deleting media files created by other apps mandates explicit user consent obtained through a system dialog triggered by MediaStore. Once the user approves, the platform issues a callback, after which the application can edit or delete the file using either MediaStore APIs or standard file paths. Attempting to bypass this dialog by modifying third-party media directly through file paths will fail immediately without prompting the user.
To streamline the user experience, the next Android version addresses a major community request by introducing batch modification requests:
> “So now you can batch multiple edit requests in one dialog instead of popping one dialog per request, as it was in the case of Android 10.” — Zimuzo Ezeozue
While developers retain the option to copy a shared file into their app-specific external directory to perform one-off edits, this pattern is discouraged for general use because it bloats disk usage and clutters the user's storage.
[19:52](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1192s) SAF Restrictions, Special App Access, and the Legacy Flag Deprecation
Roxanna Aliabadi returns to outline further refinements to shared storage access. Because some applications abused `ACTION_OPEN_DOCUMENT_TREE` to gain sweeping access over external storage, the platform is tightening the user experience for directory pickers. In the upcoming release of Android, `ACTION_OPEN_DOCUMENT_TREE` will prevent users from selecting the storage root, the entire `Download/` directory, or any directory located under `Android/data/`. Applications can still use document pickers to access individual files located within the Downloads directory, but they can no longer acquire blanket authorization for the whole directory tree.
```mermaid flowchart TD accTitle: SAF Tree Restrictions and Special App Access accDescr: Structural rules for directory selections under ACTION_OPEN_DOCUMENT_TREE and exceptions for whitelisted tools.
subgraph SAFTreeRestrictions["ACTION_OPEN_DOCUMENT_TREE Blocklist"] R1["Storage Root (/) - BLOCKED"] R2["Android/data/ - BLOCKED"] R3["Downloads/ Folder - BLOCKED"] AllowedDoc["Individual file selection via SAF - ALLOWED"] end
subgraph SpecialAccessPath["Special App Access (Broad Storage)"] Form["Play Console Declaration Form"] --> Review{"Google Play Whitelist"} Review -- "Approved" --> UserGrantPrompt["User Grants Broad Access"] UserGrantPrompt --> UnfilteredMS["Unfiltered MediaStore\n(Includes Non-Media Files)"] UserGrantPrompt --> DeniedAppDirs["External App Dirs (Android/data/)\nSTILL BLOCKED"] end ```
For applications whose core functionality fundamentally depends on broad filesystem access—such as dedicated file managers or backup and restore solutions—Google is introducing a special app access permission. To obtain this capability, developers must submit a formal declaration form via the Google Play Developer Console:
> “Only apps that can prove this need will be granted this access.” — Roxanna Aliabadi
Whitelisted applications that receive the user's approval get an unfiltered view of MediaStore, including non-media files. However, this grant does not extend to the private external app directories of other apps (`Android/data/`), which remain protected. Roxanna Aliabadi clarifies that “this access will not be granted for apps that simply want to create their own file picking experience. Those apps should use the system picker.”
Finally, Aliabadi addresses the migration timeline. The `requestLegacyExternalStorage` manifest attribute introduced in Android 10 as a transitional escape hatch will be completely retired in future versions. Developers are advised to test Scoped Storage behaviors immediately and migrate any orphaned documents or media files residing outside the standard organized directories into app-specific storage before targeting Android 10, or they will lose access to those files entirely.
[23:35](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1415s) Scoped Storage Summary and Upcoming Changes
Roxanna Aliabadi recaps the state of Scoped Storage introduced in Android 10 along with features arriving in the next Android version. Under the current Android 10 model, media files can be contributed to shared storage without requesting any permissions, and non-media files can be contributed straight to the `Downloads` directory. However, reading non-media files is guarded: apps cannot simply scan them directly and must instead route file-reading through the system picker using Storage Access Framework (SAF) APIs. Furthermore, accessing sensitive location metadata embedded in images and videos requires apps to explicitly request the `ACCESS_MEDIA_LOCATION` permission.
Looking ahead to the subsequent release of Android, Aliabadi announces that file path access will be reintroduced specifically for reading media. The platform will also revamp the Media Modification APIs by adding support for bulk operations. Concurrently, the team plans to restrict the Storage Access Framework so users can no longer grant access to broad shared storage roots or sensitive directories. For specialized applications such as file managers, a dedicated app access mechanism will be established, gated by Google Play whitelisting. As Roxanna Aliabadi emphasizes when describing the roadmap, “And all this will be enforced by target SDK.” She then hands the presentation over to Yacine Rezgui to walk through concrete development use cases.
- Media can be contributed without storage permissions. - Non-media contributions go to the `Downloads` collection; reading non-media files mandates the Storage Access Framework. - Reading EXIF geolocation metadata requires the runtime permission `ACCESS_MEDIA_LOCATION`. - The upcoming Android release will reintroduce direct file path read access for media and bulk modification prompts. - Storage Access Framework will restrict user selection of broad root directories and sensitive folders. - Play Store whitelisting will govern special broad-access permissions for approved categories.
---
[24:59](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1499s) Querying Media with the MediaStore API
Yacine Rezgui takes over to demonstrate practical code patterns, acknowledging that picking the correct storage API can be daunting: “So as Roxy and Zim mentioned, we're simplifying the developer experience on Scoped Storage. But with all these APIs, it may not be easy to figure out which one you should use in your application.” To clarify, Rezgui introduces the first scenario: a media player application that needs to discover, display, and play all video files located on the user's device. For this requirement, developers should rely on the `MediaStore` API. `MediaStore` maintains an indexed catalog of media files, which provides strong performance benefits for discoverability compared to manually traversing directory trees.
Because this media player accesses files created by other apps on the device, it must declare the `READ_EXTERNAL_STORAGE` permission in `AndroidManifest.xml`. Querying `MediaStore` is done via `ContentResolver`, which exposes an interface structured much like a traditional SQL query. The caller defines a projection to specify the desired columns, supplies selection arguments to filter the rows, and sets an ordering clause.
```mermaid flowchart TD accTitle: MediaStore Query Flow accDescr: Flow diagram showing how a media app queries the MediaStore via ContentResolver to retrieve video items.
subgraph Preparation ["1. Query Configuration"] A["Set Projection<br>(ID, Display Name, Duration, Size)"] B["Define Filter Clause<br>(Duration ≥ 5 minutes)"] C["Specify Sort Order<br>(By Duration)"] end
subgraph Execution ["2. Resolution"] D["ContentResolver.query(...)<br>against Video Content URI"] E["Return Cursor"] end
subgraph Processing ["3. Result Processing"] F["Cache Column Indices"] G["Iterate Cursor Rows"] H["Append ID to Base URI<br>Build Item Content URI"] end
Preparation --> D D --> E E --> F F --> G G --> H ```
In the media player implementation, the projection selects the unique ID column (`_ID`), display name, duration, and file size from the `MediaStore.Video.Media` column contract. Rezgui shows how to filter for videos lasting five minutes or longer, noting that because duration is stored in milliseconds, the query argument must convert minutes to milliseconds accordingly. The query executes against the external `MediaStore` video content URI and sorts the results by duration.
When consuming the returned `Cursor`, Rezgui catches a brief slip (“We need to-- sorry. My bad.”) before explaining best practices for performance: index lookups must be cached outside the row iteration loop so the app avoids repeated index fetches and prevents runtime exceptions if a column is missing. As the app loops through each cursor row, it takes the base external content URI for videos and appends the specific media ID to construct the exact content URI for playback and UI binding.
---
[28:33](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1713s) Editing Media and Handling User Consent
Rezgui moves to the second scenario: a photo editing application. This type of application not only creates brand-new images but also edits or deletes images captured or saved by other apps. Because the application manipulates media outside its own attribution footprint, it still requires the `READ_EXTERNAL_STORAGE` runtime permission. When modifying or deleting an image owned by another application, the operating system intervenes to ensure security by prompting the user for approval. Rezgui highlights an upcoming platform enhancement: “From the next Android release, you will be able to bulk all of those requests within a single dialog.”
If the photo app provides features that depend on where an image was taken, the developer must explicitly request the `ACCESS_MEDIA_LOCATION` permission to read EXIF GPS metadata. Rezgui warns developers never to treat this permission as guaranteed: “Remember that you have to double check if you still have access to this media location. You should not assume having it all the time.”
```mermaid flowchart LR accTitle: Media Modification Exception Flow accDescr: Flowchart illustrating the RecoverableSecurityException handling loop when modifying another app's media file.
A["Open FileDescriptor<br>(Write Mode)"] --> B{"Owned by<br>another app?"} B -- "No" --> C["Perform Edit / Delete"] B -- "Yes" --> D["RecoverableSecurityException"] D --> E["Extract PendingIntent"] E --> F["Launch System Consent Dialog"] F --> G{"User Consents?"} G -- "Yes" --> H["Re-open FileDescriptor<br>Complete Operation"] G -- "No" --> I["Abort Operation"] ```
The underlying code flow for editing third-party media involves attempting to open the target file's file descriptor in write mode (`"w"`). If the app lacks write privileges for that specific file, the system throws a `RecoverableSecurityException`. Within this exception object, the platform provides a `PendingIntent`. The application triggers this intent to display the system confirmation dialog to the user. Once the user approves the prompt, the application re-opens the file descriptor, which now grants read/write access to complete the modification.
---
[30:15](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1815s) Productivity Apps and Storage Access Framework (SAF)
The third use case centers on productivity software, such as an email client that needs to attach arbitrary documents—PDFs, ZIP archives, or text files—to an outgoing message. In this situation, apps should use the Storage Access Framework (SAF). A major advantage of SAF is that the app does not need to ask the user for broad runtime storage permissions in the manifest. The framework provides a unified interface across local storage and cloud providers: “Locally or remotely, the API is abstracting all the complexity for you, so you just consume it in the same way, whether it's on the device or remotely.”
Interactions are driven by system intents that display the built-in document picker: - `ACTION_OPEN_DOCUMENT`: Launches the system picker to let the user select a single file. - `ACTION_OPEN_DOCUMENT_TREE`: Prompts the user to grant access to an entire directory hierarchy. - `ACTION_CREATE_DOCUMENT`: Prompts the user to pick a destination folder and file name to save a new file.
Rezgui explains that access granted via these picker intents is temporary by default; it persists only until the device reboots. If an app needs long-term access, it must call `takePersistableUriPermission()` on the returned URI, while still handling cases where the underlying file might be deleted later by the user.
To attach a PDF to an email, the app fires `ACTION_OPEN_DOCUMENT`, adds `Intent.CATEGORY_OPENABLE` to ensure it only retrieves actual openable streams (filtering out virtual entries like contact or calendar cards), and sets the MIME type specifically to `application/pdf`. The returned URI can then be previewed using the `PdfRenderer` API before sending the message.
Conversely, to save an email attachment to local disk, the app uses `ACTION_CREATE_DOCUMENT`. This intent takes parameters similar to document opening, alongside an optional `EXTRA_TITLE` extra containing a default suggested file name, which the user can alter inside the system save dialog. Once selected, the app opens an output stream or writable file descriptor to write out the attachment bytes.
---
[33:12](https://www.youtube.com/watch?v=UnJ3amzJM94&t=1992s) Best Practices, Enterprise Access, and Wrap-Up
Rezgui outlines Google's vision for the storage ecosystem, stressing that the platform is committed to user privacy: “We want our ecosystem of applications to thrive with a privacy first approach.” Applications that have legitimate requirements for broad storage visibility—such as full backup solutions or standalone file managers—will have access to an unfiltered view of the `MediaStore` API. However, this level of access requires a privileged permission that must be submitted to and approved by Google Play via the Play Console, mirroring the strict review process already applied to SMS and call log permissions.
For everyday development, Rezgui warns against legacy file-handling habits: “But among our recommendations, one of them is do not use hardcoded path. The path may change between different versions, or the dile may be deleted or moved to a different folder.” Instead of assuming absolute file system locations, developers must combine the platform base content URIs with appended entity IDs.
Developers are encouraged to explore the official GitHub samples illustrating each Scoped Storage pattern and to test their code by setting `targetSdkVersion` to Android 10 (`29`) directly in Android Studio. Rezgui highlights that Scoped Storage remains an evolving API shaped heavily by feedback from the community: “If you have a specific use case that our API is not covering yet, please find a bug or an issue on our bug tracker to help us making a better Scoped Storage for you.”
Rezgui closes the session by inviting attendees to visit the sandbox booth to talk directly with product engineers. Displaying a slide with a survey URL on screen, he urges the audience with a smile: “You can take pictures. I will wait a quick moment there. I want to see phones.” After allowing attendees a moment to snap photos of the link, he thanks the crowd as the presentation concludes.
## Notable quotes > [33:32](https://www.youtube.com/watch?v=UnJ3amzJM94&t=2012s) We want our ecosystem of applications to thrive with a privacy first approach. — Yacine Rezgui
## Mentioned Roxanna Aliabadi, Zimuzo Ezeozue, Yacine Rezgui, Android, Android 10, Scoped Storage, Storage Access Framework, MediaStore, Google Play, Google Play Console, ContentResolver, PdfRenderer, Android Studio, GitHub
## Video description Plan overview and best practice guide to the new storage model in Android 10.
Presented by: Roxanna Aliabadi, Zimuzo Ezeozue, Yacine Rezgui
Android Dev Summit '19 all sessions playlist → https://goo.gle/ADS19allsessions
Subscribe to the Android Developers channel! → https://goo.gle/AndroidDevs
Check out the photo album → http://goo.gle/ADS19Photos
#AndroidDevSummit event: Android Dev Summit 2019; re_ty: Publish; product: Android - General; fullname: Roxanna Aliabadi, Yacine Rezgui, Zimuzo Ezeozue;
[Source](https://www.youtube.com/watch?v=UnJ3amzJM94)