Overview of partitioned storage
Before Android 10, Android file storage was like a garbage can. Once an app obtained the WRITE_EXTERNAL_STORAGE permission of the storage space, it could create files arbitrarily, which was difficult to manage. The user experience is also particularly poor. When you open the file manager, you will find that it is impossible to find a specific file.
1.1 Partition Storage Principles
To better manage your files, reduce clutter and enhance privacy, Android Q introduces partitioned storage. The external storage space has been redesigned to be divided into private and public shared applications. An application can Access only its own private space or Access shared resource directories through the MediaStore API and Storage Access Framework.
Partitioned storage redesigns file storage by following three main principles:
-
Record file source: The system records the application that creates the file. Applications can read and write the file without permission.
The owner_package_name field is added to the MediaStore database to record which application file belongs to. After the application is uninstalled, the owner_package_name field will be empty. That is, after the uninstallation and reinstallation, the previously created file does not belong to the application and requires related storage permission to read and write the file again
-
Application data protection: The access to external storage space is restricted. Applications can only access their own private space or shared space. Even after obtaining read and write permissions, they cannot access the private space of other applications.
-
User data protection: When users download files, such as email attachments with sensitive information, these files should not be visible to other applications. Added restrictions on Access to FILES such as PDF, Office, and DOC. Even if you have applied for Storage permission, you cannot Access files such as PDF, Office, and DOC created by other applications through MediaStore. You need to select files using the Storage Access Framework. To gain access
The newer the Android system, the more it depends on the purpose of the file rather than its location to determine the application’s ability to access the file
1.2 Compatibility and Judgment of storage Modes
- When targetSdk <= 28, the application uses traditional storage.
- When targetSdk <= 29, this can be added in the Application TAB of the application manifest
android:requestLegacyExternalStorage="true"
To disable the partition storage function and continue to use the traditional access mode. - When targetSdk>>=30, Android forces partition storage and cannot close it.
- Can be achieved by
Environment.isExternalStorageLegacy()
Check the running mode of the application storage. True indicates that the application storage runs in traditional compatible mode. False indicates that the application storage runs in partitioned storage mode
Note: when modifying the requestLegacyExternalStorage attribute values, must want to uninstall the old APK, reinstall will only take effect
Impact of storage space
Android provides two types of physical storage locations: internal storage and external storage. On most devices, internal storage is smaller than external storage. However, internal storage space is always available on all devices, making it more reliable for storing the data on which applications depend.
Removable volumes (such as SD cards) belong to external storage space in the file system. It’s a lot of space, and most smartphones today have it, but for compatibility, you can also check if the space is available when using the relevant API. Environment.getExternalStorageState()
// Can read and write
fun isExternalStorageWritable(a): Boolean {
return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
}
// Is it readable
fun isExternalStorageReadable(a): Boolean {
return Environment.getExternalStorageState() in
setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
}
Copy the code
Before writing to the storage, you need to know how much space is available on the device; if not, an exception will be thrown. However, the memory of smart devices is also relatively large, this part can refer to Google to query the available space
2.1 Internal Storage Space
When you open Android Studio’s Device File Explorer, you can see the app’s internal space directory: /data/data/ package name /
The internal storage space itself is designed to protect app privacy. This part is not changing. Applications can read and write files from these directories without any system permissions. Other applications cannot access files stored in the internal storage space.
Internal storage space provides directories for applications. One directory is designed for the application’s persistent files, while the other contains the application’s cache files. The internal storage space is application-specific and the File API can be used normally, so as long as the path is obtained, it can be used freely:
-
Persistent File root directory File: context.filesdir (), /data/data/ package name /files/
-
Cache File root directory File: : context.cachedir (), /data/data/ package name /cache/
Android also provides some handy apis for creating and deleting files: context.openFileOutput(filename, Context.mode_private), context.openFileInput(filename), context.filelist (), context.getdir (dirName, The Context. MODE_PRIVATE), the Context. DelefteFile (fileName)
Note: after uninstalling the APP, the system will automatically remove these directories to free up space!!
2.2 External Storage Space
/ storage/emulated / 0 / Android/data/package name
The external storage space of The Android system is redesigned. The external storage space is divided into private directories and shared directories.
- Application private directory: Stores application private data. The external storage application private directory corresponds to the Android/data/ package name
- Shared directory: Stores files accessible to other applications, including media files, document files, and other files, corresponding to devices such as DCIM, Pictures, Alarms, Music, Notifications,Podcasts, Ringtones, Movies, and Download.
2.2.1 Application Private Space
As before, no permissions are required to access application private space under its own external storage. As with the interior, there is a directory designed for the application’s persistent files, and another directory containing the application’s cache files. The file-related API is also available, so you can play with it as long as you get the path.
Note the following differences: After the partitioned storage feature is enabled, an application can access only its own private space, but cannot access other applications’ private space even after the storage permission is granted
Another difference from internal space is that external storage space can be removed or multiple, so an array is returned, and the first element in the array is treated as the primary external storage volume. Use the volume unless it is full or unavailable.
- Persistent files:
getExternalFilesDirs(@NonNull Context context, @Nullable String type)
, type Can be transmitted according to the file typePredefined subdirectory constants, such as imagesEnvironment.DIRECTORY_PICTURES
, return/ storage/emulated / 0 / Android/data/files/Pictures/package name
. Or pass NULL to return directly/ storage/emulated / 0 / Android/data/files/package name
- Cached files:
ContextCompat.getExternalCacheDirs(context)
./ storage/emulated / 0 / Android/data/cache/package name
Note: after uninstalling the APP, the system will automatically remove these directories to free up space!!
Impact of shared storage space
If user data is or should be accessible to other applications and can be saved even after the user uninstalls the application, use shared storage space.
Type of shared files, including media files, document files, and other files, corresponding to DCIM, Pictures, Alarms, Music, Notifications,Podcasts, Ringtones, Movies, and Download directories. Android provides apis for obtaining this type of shareable data file Uri:
- Media content: Available
MediaStore
API to access this content - Documents and other files: The system has a special directory for other file types, such as PDF documents and books in EPUB format. The application can be used
Storage Access Framework
Access these files.
For shared files,. A path that could have been obtained using data Column and manipulated using the File API will now return a failure. After the partition storage feature is enabled, the application can only use the API provided by the system to request the Uri of the corresponding file, and use the Uri to generate FileDescriptor and InputStream to read and write files. (In short, the main problem of adding, deleting, and modifying shared files is to obtain the Uri.)
Note: Android 11 also allows access via a path, which is automatically redirected to a Uri.
val resolver = applicationContext.contentResolver
/ / read
resolver.openFileDescriptor(content-uri, "r")? .use { pfd ->
val inputStream = FileInputStream(pfd.fileDescriptor)
}
resolver.openInputStream(content-uri).use { stream ->
}
/ / write
resolver.openFileDescriptor(content-uri, "w")? .use { pfd ->
val outputStream = FileOutputStream(pfd.fileDescriptor)
}
resolver.openOutputStream(content-uri).use { stream ->
}
/ / bitmap images
BitmapFactory.decodeFileDescriptor(pfd.fileDescriptor)
Copy the code
3.1 MediaStore API
For the MediaStrore API, see Google’s official guide. The uri is obtained from the contentResolver, so we won’t introduce it here. photo
3.1.1 MediaStore overview
The Android system automatically scans the external storage space and adds media files to the predefined Images, Videos, Audio files, and Downloaded Files by type. Android Q uses mediastore. Images, mediastore. Video, mediastore. Audio, and mediastore. Downloads to access file resources in a shared directory. The following table shows the directories corresponding to predefined collections:
The media type | Uri | Create a directory by default | Allow directory creation |
---|---|---|---|
Image | content://media/external/images/media | Pictures | DCIM,Pictures |
Audio | content://media/external/audio/media | Music | Alarms,Music,Notifications,Podcasts,Ringtones |
Video | content://media/external/video/media | Movies | DCIM,Movies |
Download | content://media/external/downloads | Download | Download |
Note: the MediaStore. Downloads. EXTERNAL_CONTENT_URI Android10 version of new API, used to create, access to the media files
3.1.1 Changes to MediaStore
- The MediaStore API does not need to apply for storage permission to create files in the specified directory of the shared directory or to access the application to create files.
- If the MediaStore API is used to access media files (such as images, audio files, and videos) created in the shared directory by other applications, you need to apply for the storage permission. If you do not apply for the storage permission, the Uri of the file cannot be queried through the ContentResolver. If the Uri is obtained through other methods, an exception will be thrown if the file is read or created.
- The MediaStore API cannot access non-media files (PDF, Office, doc, TXT, etc.) created by other applications. The only way to Access non-media files created by other apps in Android 10 is to use the document selector provided by the Storage Access Framework.
3.1.2 Where can I Store files created using apis? How do I customize locations?
When creating a file through the MediaStore API, the file will be saved to the corresponding type of directory by default, such as Pictures/ directory, you can check the table default directory and allowed directory.
You can use the MediaStore. XXX. Media. RELATIVE_PATH themselves specified storage directory or subdirectory, such as: ContentValues. Put (MediaStore. Images. Media. RELATIVE_PATH, Environment. DIRECTORY_PICTURES + “/ custom subdirectory”), The file will be placed in the Pictures/ custom subdirectory /; Or use the contentValues. Put (MediaStore. Images. Media. RELATIVE_PATH, Environment. DIRECTORY_DCIM), put the file in DCIM /
Note: Each type has a corresponding directory that can be created, otherwise failure will be returned. Specific directories can be created to view the table
3.2 Storage Access Framework
The SAF framework enables users to interact with system selectors to select document providers and specific documents and other files for your application to create, open, or modify. Since the user participates in the file selection, this mechanism does not require any system permissions.
The application calls ACTION_CREATE_DOCUMENT, ACTION_OPEN_DOCUMENT, and ACTION_OPEN_DOCUMENT_TREE Intent to retrieve the Document provider file. And receives the Uri of the selected file returned in the onActivityResult interface. In addition, when you configure an intent, you should specify the file name and MIME type, and you can also use EXTRA_INITIAL_URI Intent Extra as needed to specify the URI of the file or directory that the file selector should display when it first loads.
This section, too, remains unchanged. See the official guide: Accessing documents and other files from shared storage
3.2.1 Obtaining Persistent Rights
For URI permissions obtained through the SAF framework, you can apply for persistent permissions without having to re-request each time you restart the phone.
contentResolver.takePersistableUriPermission(
documentUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION
)
Copy the code
4 Storage Features Overview of Android version differences
photo
4.1 Other changes: Picture position information
Some photos include location information in the metadata so users can see where the photo was taken. Because this location information is sensitive, Android 10 hides it from applications that use partitioned storage by default.
If your app needs to access the location of a photo:
- Request in the application manifest
ACCESS_MEDIA_LOCATION
permissions - By calling the
setRequireOriginal()
, fromMediaStore
Object gets the exact bytes of the photo and passes in the photo’s URI
Get the position information in the picture
Five update
5.1 Android 10 partition Storage bug
Android 10 uses the Media Media API to delete a media file. It simply removes the index from the MediaStore database. It does not actually delete the physical file on the physical storage, and as soon as the phone restarts, the index is added again. issue
This requirement is also relatively rare, but just happened to be detected by testing. I checked online and found that the problem did exist, so Android 11 can be removed normally. If there is any solution, please kindly point it out!!
5.2 Storage Changes in Android 11
5.2.1 Allow to continue using the original file path
You can use the file path again, and the system automatically redirects it to a Uri
5.2.2 Adding batch Operations
In Android 10, an application must be individually acknowledged by the user for each file it requests to edit or delete from MediaStore. In Android 11, apps can request to modify or delete multiple media files at once.
Mainly through the following new batch operation API
methods | instructions |
---|---|
MediaStore.createDeleteRequest (resolver, uris) | Batch delete (not put in recycle bin) |
MediaStore.createFavoriteRequest(resolver, uris) | Batch collection |
MediaStore.createTrashRequest (resolver, uris) | Bulk transfer to recycle bin |
MediaStore.createWriteRequest(resolver, uris) | Obtain the write permission in batches |
val uris = ...
val pi = MediaStore.createWriteRequest(contentResolver,
uris)
startIntentSenderForResult(pi.intentSender, REQUEST_CODE, null.0.0.0)
/ /
override fun onActivityResult(xxx) {
when (requestCode) {
REQUEST_CODE ->
if (resultCode == Activity.RESULT_OK) {
// Get permission and continue
} else {
// The user denied permission
}
}
}
Copy the code
Vi Reference Links
- Google Guide: Apply data and files
- Android 10 partition storage introduction and Baidu APP adaptation practice
- The storage mechanism in Android 11 has been updated
- storage-samples
Seven ❤️ about me
Study + record + discuss + summarize
- If you find this post helpful, please like it and follow it (👍).
- About error correction and suggestions: Welcome to share the record directly in the message (🌹)