andorid 10 轻松搞定文件适配

729 阅读2分钟

一 引入分区存储

原因;为了让用户更好地管理自己的文件并减少混乱

内部存储:

获取方式:context.getCacheDir(); 存储路径data/user/0/package/cache ,容量较小,当系统内部存储空间较小时,有被系统删除风险

外部存储:

1.外部私有存储 获取方式Context.getExternalFilesDir()路径:/storage/sdcrad0/Android/data/package/files下

2.外部公共路径存储 通过MediaStore进行增删改查,默认插入路径/storage/sdcrad0/Pictures,可通过指定相对路径指定到Environment.DIRECTORY_DCIM ,Environment.DIRECTORY_MOVIES,等路径;

二 访问权限变更

使用分区存储的应用对自己创建的文件始终拥有读/写权限,无论文件是否位于应用的专有目录内。因此,如果您的应用仅保存和访问自己创建的文件,则无需请求获得READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE权限。不过,若要访问其他应用创建的文件,则必须满足以下两个条件: 您的应用已获得 READ_EXTERNAL_STORAGE 权限。

这些文件位于以下其中一个明确定义的媒体集合中:

照片:存储在MediaStore.Images中。

视频:存储在MediaStore.Video中。

音频文件:存储在MediaStore.Audio中。

那如何访问MediaStore.Download,等路径呢?必须使用存储访问框架 问题,如果想访问其他应用的外部存储得私有目录呢?

三 文件存储方式

1.外部文件公开目录,判断sdcard可否存储:

fun isExternalStorageWritable(): Boolean {
    return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
}
fun isExternalStorageReadable(): Boolean {
     return Environment.getExternalStorageState() in
        setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY)
}

2.保存照片、音频文件或视频剪辑到外部文件公开目录

MedieStore.Image.Media.insertImage:会生成缩略图,全局查询可以查到两张图 contentResover.insert(uri,contentvalues):适用于图片和视频和音频 ACTION_CREATE_DOCUMENTintent:适用于pdf,等其他格式文件,存储访问框架得一部分

3.外部私有目录:getexternalfiledir获取到路径 val file = File(content.getexernalFiledir(null),Enviorment.DIRECTORY_DCIM)

4.文件读写方式:Android q以前使用流,q是使用文件描述符:

常用读写:

fun write(file: File, any: Any, context: Context) {
    val descriptor = getDescriptor(file, context) ?: return
    ObjectOutputStream(FileOutputStream(descriptor.fileDescriptor)).safeUse {
        it.writeObject(any)
    }
    descriptor.safeClose()
}

fun readString(file: File, context: Context): String? {
    val descriptor = getDescriptor(file, context) ?: return null
    FileInputStream(descriptor.fileDescriptor).safeUse { return it.readString() }
    descriptor.safeClose()
    return null
}

private fun getDescriptor(path: File, context: Context): AssetFileDescriptor? {
    val uri = Uri.parse(file.absolutePath)
    return context.contentResolver.openAssetFileDescriptor(uri, "r")
}