Introduction to Data Storage

The name of the role Detailed instructions
Application-specific storage space Stores application-specific files Dedicated storage Space Dedicated directories can be created for users on internal storage and external storage. These directories can be used to store files that cannot be accessed by other usersFile apiAccess: Files are deleted after the application is uninstalled. No permission is required for access
Shared storage Stores data shared by all applications Stores files that your application intends to share with other applications, including media, documents, and other files, and can be usedMediaStoreapiIf yes, data still exists after the application is uninstalled. To access the data, you need to apply for storage permission

Use of external storage space

Use external dedicated storage space

In android4.4 to android9, applications are allocated external storage space that can be accessed without permission. If an application wants to access other applications’ external storage space (partitioned storage), it needs to apply for permission.

On android10 and above, the external storage space of an app becomes the private space of the app, and no app can access the exclusive storage space of another app

  1. features

External exclusive storage space is located in the external storage of the application. We can access the external exclusive storage space without applying for permission. External exclusive storage space can be deleted after the application is uninstalled. Media files in a dedicated space directory should not normally be included in media applications such as albums (i.e. albums will not display images from this directory) (our custom image picker should not scan images from this directory either)

In versions below android10, this directory is visible to all apps

  1. access

Obtain directory path:

  • GetExternalFilesDir (” “) : / storage/emulated / 0 / Android/data/com. Ananananzhuo. Storage10demo/files

  • GetExternalFilesDirs () : Gets the list of all files in the directory

  1. Use the demo
File = file (getExternalFilesDir("")," android.txt ") val fos = FileOutputStream(file) fos.write(" ".tobyteArray (charsets.utF_8)) fos.close()Copy the code

The code above will be in the external exclusive store directory (/ storage/emulated / 0 / Android/data/com. Ananananzhuo. Storage10demo/files) create a safely in Android. TXT file, Here we do not claim and apply for any permissions. After executing the code, go to the file selector to see the following display:

Access to non-private directories in external storage must be declared for permission. Let’s write a negative case

  1. code
ItemData (title = "access external storage", {val file = file (Environment. External.getexternalstoragedirectory () absolutePath) val fileAn = File(File," absolutePath ") logEE(file.absolutePath) val fos = FileOutputStream(fileAn) fos.write(" ".tobytearray (charsets.utf_8)) fos.close()} ".tobytearray (charsets.utf_8))Copy the code
  1. The crash log indicates that the user has no permission

Store media files in a media folder in an external storage directory

Store the images in the images folder

  1. code
val picFile = getExternalFilesDir(Environment.DIRECTORY_PICTURES)? .apply { if (! exists()) { mkdirs() } } val file = File(picFile,"pic.jpg") FileOutputStream(file).apply { write(12) flush() close() }Copy the code
  1. The results of

File saved successfully

There are other options for media folders:

  • Environment.DIRECTORY_MOVIES
  • Environment.DIRECTORY_DOWNLOADS
  • Environment.DIRECTORY_DOCUMENTS
  • Environment.DIRECTORY_SCREENSHOTS

When storing media, we should try to use the string constants in the Environment to obtain the media file directory

Android10 above and can use the Environment. External.getexternalstoragedirectory access file

Above android10 version could not use external.getexternalstoragedirectory API file operation, because the API has been deleted, below android10 can continue to use the API

So how should we access this part of the files for versions higher than android10? Don’t worry, more on shared storage later

  1. code

  1. rendering

Android10 or above how to get the ordinary directory in the SD card picture

We can use SAF to get ordinary directory images (i.e. non-exclusive directory, non-shared directory images) on android11 or above.

The method in this example does not work on android10 or younger (forced use will crash)

  1. code
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_directory_scan11) findViewById<Button>(R.id.btn_secletdirectory).setOnClickListener { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) intent.addCategory(Intent.CATEGORY_OPENABLE) intent.type = "image/jpeg" startActivityForResult(intent, }} Override Fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent? { super.onActivityResult(requestCode, resultCode, data) data? .data? .let {iv.setimageuri (it)// Process image via URL}}Copy the code
  1. The effect

Internal storage

Operate on internal storage using openFileOutput and openFileInput

Store a file in the files directory of internal storage

  1. code
OpenFileOutput (" openFileoutput.txt "), MODE_PRIVATE).apply {write("openFileOutput method input stream ".tobyteArray (charsets.utF_8)) flush() close()}Copy the code
  1. Check the file after the execution

The openFileInput method is used in the same way as openFileOutput

FileList Obtains the paths of all files in the internal storage

  1. code
{fileList().foreach {logEE(" $it")}}) {fileList().foreach {logEE(" $it")}})Copy the code
  1. The output log
E/ Ananzhuo: File path: Ananandroid openFileoutput.txtCopy the code

GetCacheDir Obtains the internal storage cache file

Files in the internal storage cache may be deleted after the application is uninstalled, or before the application is uninstalled (if internal storage space is insufficient). So we need to check if the file exists before we cache it in internal storage

context.getCacheDir()
Copy the code

Shared Storage Space (Android10 or above)

The media

Android10 + saves media files by type in public directory, you can access media files using MediaStore

The following table lists all shared media file types

The media type location note
The picture Stored in the Pictures and DICM directories, the system stores these files in mediastore.images There is no
video Stores the DICM, Movies, Pictures directories, and the system adds these files to the mediastore.video table There is no
Audio file The files are stored in Alarms, Audiobooks, Music, Notifications, Podcasts, and Ringtones. The system adds these files to the mediastore. Audio table There is no
The download file In the Download directory, the system adds the files to the mediastore.download table Not available on versions younger than android10
Document collection Exists in the mediastore.files table If partitioned storage is used, this collection will only show photos, videos, and audio files created by the application

Enable partition storage permission and media processing

If your application uses partitioned storage, you need to declare the ACCESS_MEDIA_LOCATION permission in your application’s listing and then apply for it at run time. We’ll talk about how to apply

Write a photo album

  1. First, you need to get all the image addresses in the shared storage
private fun getGallaryData(): MutableList<Image> { val cursor = contentResolver.query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, null, null, "${MediaStore.Images.Media.DISPLAY_NAME} ASC" ) val tempdatas = mutableListOf<Image>() cursor? .use { val idColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media._ID) val nameColumn = it.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME) while (it.moveToNext()) { val id = it.getLong(idColumn) val contentUrl = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, Id) val name = it.getString(nameColumn) val image = image (contentUrl, "") tempdatas.add(image) logEE(" filename: ${contentUrl.path}") } it.close() } return tempdatas }Copy the code
  1. Get the image URI in the coroutine and present it to the adapter
private fun initData() { lifecycleScope.launch(Dispatchers.IO) { datas.addAll(getGallaryData()) withContext(Dispatchers.Main) { recycle.adapter? .notifyDataSetChanged() } } }Copy the code
  1. The effect

About MANAGE_EXTERNAL_STORAGE for Android11

The android10 version doesn’t have access to all files, and maybe Google realizes that’s not true, so it’s re-supporting all files in the android11 version

On android11, if you want to scan all files in your app, you can declare MANAGE_EXTERNAL_STORAGE permission

The permission for MANAGE_EXTERNAL_STORAGE needs to be applied with the Intent, which will redirect to a system page to confirm the permission

Note: This method can access files in the shared storage, but not files in the dedicated storage directory (Android/data).

The following method can be used to determine whether MANAGE_EXTERNAL_STORAGE has permission

Environment.isExternalStorageManager()
Copy the code

The permission can be declared as follows:

  1. Permissions are declared in the manifest
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
Copy the code
  1. Application permission code
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
}
Copy the code
  1. Implementation effect

other

permissions

  • Use The shared storage space to access other applications, you need to apply for storage permission. You do not need to apply for storage permission for files created in this installation.

  • If the target version is greater than 9, then we should only apply for permissions in <=9 versions, which can be configured as follows:

maxSdkVersion

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                 android:maxSdkVersion="28" />
Copy the code
  • If your application uses storage compatibility, you still need access to the storage

Storage compatibility means we’re going to upgrade to android10 but don’t want to use partitioned storage for a while

To enable storage compatibility, declare the following configuration in the application tag in the MANIFEST:

android:requestLegacyExternalStorage="true"

Copy the code

Example Switch the status of a media file to be processed

If an application operation is likely to be time-consuming (such as writing to a file), then we should avoid giving other applications the opportunity to process the file while we are working on it. We can through the ContentValue. Put (MediaStore. Audio. Media. IS_PENDING, 1) the value of the tag is set to 1 to obtain this exclusive access. This way, only our application can manipulate the file until our application changes the IS_PENDING value back to 0.

Location information in the photo

Photos in an album may contain sensitive information, such as location information, which is not allowed to be viewed by users by default. If you want to view the information, you need to apply for the ACCESS_MEDIA_LOCATION permission