Adaptation Rules for Android10 Partitioned Storage

  • 2021-12-12 09:50:37
  • OfStack

Directory store permissions Internal storage external storage adaptation

Storage permissions

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

With these permissions, access to external storage is restricted, and only files in its own directory and files in the public body can be accessed

Internal storage external storage

内部存储 外部存储 备注
英文名称 Internal storage External storage
版本变更 不变 4.4之前,外部存储仅仅代表SD卡之类的移动存储设备,4.4之后包括内置的外部存储和SD卡(部分手机没有提供SD卡的卡槽,就只有内置的外部存储)
查看方法 用模拟器+adb shell 进入 或者是Android Studio Devices File Explorer 1般的文档管理App 都能看 用 su root 命令给模拟器加权限
组成成分 System/:存放系用数据 data/: 存放应用相关数据 vendor/:用于存放厂商客制化的数据等 私有存储区:android/ 文件夹下,是应用的私有存储区域 公共存储区域:Movie、Download、 DCIM、 Picture、Documents、Ringtones、Music、 Alarms
存储内容 db share preference files cache 等 开发者自己需要存储的数据 如视频文件、音频文件、或者1些表格 日志文件 内部存储小而且宝贵我们基本上不要操作它,需要存储的都存储在外部存储
获取路径方法 Environment.getDataDirectory() Context.getFileDir() Environment.getExternalStorageDirectory() (traget>=30,已废弃) Context.getExternalFilesDir() 基本上Context的方法获取的都是应用的私有存储路径 E nvironment的方法获取的都是根目录
应用卸载时 私有路径下的文件全部删除 即:data/user/0/packageName/ 私有路径下的文件全部删除 即:android/data/packageName/ 公共存储区域不变动

Adaptation

Get an external storage folder

//  If there is no  fileDirName  Folders are created automatically 
val file:File = context.getExternalFileDir("fileDirName") // fileDirName  Folder name 
// /storage/emulated/0/Android/data/packageName/files/fileDirName
Create an external storage file

  val appFileDirName = applicationContext.getExternalFilesDir("fileDirName")?.absolutePath
  val newFile = File(appFileDirName, "temp.txt")
  val fileWriter = FileWriter(newFile)
  fileWriter.write("test information")
  fileWriter.flush()
  fileWriter.close()
Create a file path under the public directory of external storage

    /**
     * @param fileName  File name 
     * @param relativePath  Contains sub-paths under a media 
     */
    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  
      	// Because the external storage space is located on a physical volume that the user may be able to remove, the application special is attempted to read from the external storage space 
      	// Verify that the volume is accessible before you write application-specific data to external storage. 
      	// You can do this by calling the  Environment.getExternalStorageState()  Query the status of the volume. If the returned status is  MEDIA_MOUNTED You can read and write application-specific files in external storage. 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)
        }
    }

    /**
     * @param context  Context 
     * @param insertUri  Storage Uri
     * @param inputStream  File output stream 
     */
    fun saveFile(context: Context, insertUri: Uri?, inputStream: InputStream?) {
        insertUri ?: return
        inputStream ?: 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()
    }

    /**
     * @param context  Context 
     * @param insertUri  Storage Uri
     * @param sourceFile  Resource file 
     */
    fun saveFile(context: Context, insertUri: Uri?, sourceFile: File?) {
        insertUri ?: return
        sourceFile ?: 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()
    }
Read external storage public directory files

    /**
     *  Get the file output stream  by uri
     * @param context  Context 
     * @param uri  File path 
     */
    fun getInputStreamByUri(context: Context, uri: Uri?): InputStream? {
        uri ?: return null
        val openFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")
        return FileInputStream(openFileDescriptor?.fileDescriptor)
    }

The above is the Android10 partition storage use summary of the details, more information about the use of Android10 partition storage please pay attention to other related articles on this site!


Related articles: