preface

Android devices offer partitioned storage above Sdk29, similar to the iOS sandbox. Application If the App version is 29 or later, partition storage needs to be adapted

Specific adaptations are as follows

Store permissions

Android Q still uses READ_EXTRNAL_STORAGE and WRITE_EXTRNAL_STORAGE as storage-related runtime permissions but now even

With these permissions, access to external storage is limited to files in your own directory and files in the public body

Internal storage External storage

Internal storage External storage note
English names Internal storage External storage
Version changes The same Before 4.4, external storage only represented mobile storage devices such as SD cards. After 4.4, it included internal external storage and SD cards (some phones do not provide SD card slots, so only internal external storage).
Check the method Enter with emulator + ADB shell or Android Studio Devices File Explorer Any general document management App can read it Add permissions to the emulator using the su root command
composition System/: stores department data. Data /: stores application-related data. Vendor /: Stores customized data Private Storage Area: Under the Android/folder, is the private storage area of the application. Public Storage areas: Movie, Download, DCIM, Picture, Documents, Ringtones, Music, and Alarms
Store content Db Share Preference Files cache The developer needs to store his own data such as video files, audio files, or some tabular log files Internal storage is small and precious and we basically don’t manipulate it, everything that needs to be stored is stored in external storage
Get path method Environment.getDataDirectory() Context.getFileDir() Environment. External.getexternalstoragedirectory () (traget > = 30, has been abandoned) Context. GetExternalFilesDir () Basically, the Context method gets the private storage path of the application. E The nvironment method gets the root directory
Application uninstallation All files in the private path are deleted, that is, data/user/0/packageName/ Delete all private directory files Namely: the android/data/packageName/public storage area does not change

adapter

  • Gets the external storage folder

    // The fileDirName folder is created automatically if there is no fileDirName folder in the current directory
    val file:File = context.getExternalFileDir("fileDirName") // fileDirName Specifies the folder name
    // /storage/emulated/0/Android/data/packageName/files/fileDirName
    Copy the code
  • Create external storage files

      val appFileDirName = applicationContext.getExternalFilesDir("fileDirName")? .absolutePathval newFile = File(appFileDirName, "temp.txt")
      val fileWriter = FileWriter(newFile)
      fileWriter.write("test information")
      fileWriter.flush()
      fileWriter.close()
    Copy the code
  • Create a file path in a public directory for external storage

    
        / * * *@paramFileName fileName *@paramRelativePath contains subpaths */ for a medium
        fun insertFileIntroMediaStore(
            context: Context,
            fileName: String,
            relativePath: String
        ): Uri? {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
                return null
            }
            val contentResolver = context.contentResolver
            val values = ContentValues()
            values.put(MediaStore.Downloads.DISPLAY_NAME, fileName)
            values.put(MediaStore.Downloads.MIME_TYPE, "text/plain")
            values.put(MediaStore.Downloads.RELATIVE_PATH, relativePath)
          	// Verify the availability of storage space
          	// Trying to read the application file from the external storage space because the external storage space is on a physical volume that the user might be able to remove
          	// Before writing application-specific data to the external storage space, check whether the volume is accessible.
          	/ / you can call Environment. GetExternalStorageState () query the status of the volume. If MEDIA_MOUNTED is returned, you can read and write application-specific files in the external storage space. If the returned status is MEDIA_MOUNTED_READ_ONLY, you can only read these files.
            val externalStorageState = Environment.getExternalStorageState()
            return if (externalStorageState.equals(Environment.MEDIA_MOUNTED)) {
                contentResolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
            } else {
                contentResolver.insert(MediaStore.Downloads.INTERNAL_CONTENT_URI, values)
            }
        }
    
        / * * *@paramContext *@paramInsertUri stores Uri *@paramInputStream File output stream */
        fun saveFile(context: Context, insertUri: Uri? , inputStream:InputStream?).{ insertUri ? :returninputStream ? :return
            val resolver = context.contentResolver
            val out = resolver.openOutputStream(insertUri)
            var read: Int
            val buffer = ByteArray(1024)
            while(inputStream.read(buffer).also { read = it } ! = -1) {
                out? .write(buffer) } inputStream.close()out? .flush()out? .close() }/ * * *@paramContext *@paramInsertUri stores Uri *@paramSourceFile Resource file */
        fun saveFile(context: Context, insertUri: Uri? , sourceFile:File?).{ insertUri ? :returnsourceFile ? :return
            val inputStream = FileInputStream(sourceFile)
            val resolver = context.contentResolver
            val out = resolver.openOutputStream(insertUri)
            var read: Int
            val buffer = ByteArray(1024)
            while(inputStream.read(buffer).also { read = it } ! = -1) {
                out? .write(buffer) } inputStream.close()out? .flush()out? .close() }Copy the code
  • Read external storage public directory files

        /** * get the file output stream by uri *@paramContext *@paramUri File path */
        fun getInputStreamByUri(context: Context, uri: Uri?).: InputStream? { uri ? :return null
            val openFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")
            returnFileInputStream(openFileDescriptor? .fileDescriptor) }Copy the code