android10以上,访问Android/data文件

自从android10使用分区存储后,文件的操作显得更为复杂,幸运的是,谷歌为我们提供许多操作简单的api,这篇文章主要讲的是android除沙盒目录和共享目录外其他目录的操作

android10以上,如果想要获取其他文件,最简单的方法是申请MANAGE_EXTERNAL_STORAGE权限,获取该权限之后,任何文件都可以正常操作,然后你就不用往下看了……

由于registerForActivityResult()正式版已发布很久,并且官方为registerForActivityResult提供了许多简便易用的api,这里获取文件的方法使用registerForActivityResult

如果找不到registerForActivityResult,你需要将activity版本提升到1.2.0,fragment版本提升到1.3.0以上

打开文件选择器


        //打开文件选择器,选择txt文件      
        val select = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->

        }
        //txt的mimeType,其他文件的则使用相对应的type,比如pdf,则传application/pdf,图片文件传image/*
        select.launch("text/plain")


        //多选文件:
        val select =
            registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { list ->
            }

        select.launch("text/plain")

        
        //多类型多文件
        registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()){
            
        }.launch(arrayOf("mimeType1","mimeType2"))
        
        //多类型单文件
        registerForActivityResult(ActivityResultContracts.OpenDocument()){
            
        }.launch(arrayOf("mimeType1","mimeType2"))

文件夹操作

//打开文件夹选择器
    private val select = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) {
        
    }

select.launch(null)

//获取到文件夹uri后,如果需要遍例文件夹下所有文件:

        val tree = DocumentFile.fromTreeUri(this,文件夹uri)
        if(tree != null){
            val uris = tree.listFiles()
            uris.forEach {
                //该文件夹下文件uri
                it.uri
            }
        }

DocumentFile操作访问文件效率远远不及file操作,如果只是一个文件倒没什么,但如果是个文件夹,里面上百个文件,那么访问速度慢的问题就体现出来了,这时可以将获取到的文件夹uri转成file再操作,这种方法目前还可以用,但我不知道什么时候谷歌会把这方便禁掉

注:需要requestLegacyExternalStorage="true" 和READ_EXTERNAL_STORAGE权限

fun getTreeFile(context: Context, uri: Uri): File? {
    val docId = DocumentsContract.getTreeDocumentId(uri)
    val split = docId.split(":")
    val type = split[0]
    if(type.equals("primary",true)){
        return runCatching { File("${Environment.getExternalStorageDirectory()}/${split[1]}") }.getOrNull()
    }else{
        val manager = context.getSystemService(Context.STORAGE_SERVICE) as StorageManager
        val storageVolumeClazz = Class.forName("android.os.storage.StorageVolume")
        val getVolumeList: Method = manager.javaClass.getMethod("getVolumeList")
        val getUuid = storageVolumeClazz.getMethod("getUuid")
        val getState = storageVolumeClazz.getMethod("getState")
        val getPath = storageVolumeClazz.getMethod("getPath")
        val result = getVolumeList.invoke(manager)
        val length = Array.getLength(result)
        for (i in 0 until length){
            val ele = Array.get(result,i)
            if(Environment.MEDIA_MOUNTED == getState.invoke(ele) || Environment.MEDIA_MOUNTED_READ_ONLY == getState.invoke(ele)){
                val uuid = getUuid.invoke(ele) as? String
                if(uuid == type){
                    return runCatching { File("${getPath.invoke(ele)}/${split[1]}") }.getOrNull()
                }
            }
        }
    }
    return null
}

外部文件夹访问权限

访问文件夹,也是需要访问权限的,一般来说,通过文件管理器获取的uri,会在获取的时候得到授权,这个权限会直到你的应用重启时才失效,如果你需要永久保留这个文件夹的使用权限,可以通过这段代码申请:

 applicationContext.contentResolver.takePersistableUriPermission(
            需要保留访问权限的uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION
        )

Android中,可以通过File类或者FileProvider来访问/storage/emulated/0/Android/data目录下的文件。这个目录是应用程序的私有外部存储目录,每个应用程序都有自己的文件夹,其他应用程序无法直接访问。 使用File类访问文件的步骤如下: 1. 获取外部存储的根目录路径: ```java String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath(); ``` 2. 构建文件路径: ```java String filePath = rootPath + "/Android/data/your_package_name/files/your_file_name"; ``` 其中,your_package_name是你的应用程序包名,your_file_name是你要访问文件名。 3. 创建File对象并进行操作: ```java File file = new File(filePath); // 进行文件的读写操作 ``` 如果你需要在应用程序之间共享文件,可以使用FileProvider来提供访问权限。具体步骤如下: 1. 在AndroidManifest.xml文件中添加FileProvider的配置: ```xml <provider android:name="androidx.core.content.FileProvider" android:authorities="your_authority" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ``` 其中,your_authority是一个唯一的字符串,用于标识你的FileProvider。 2. 在res/xml目录下创建file_paths.xml文件,并添加以下内容: ```xml <paths> <external-path name="external_files" path="Android/data/your_package_name/files/" /> </paths> ``` 其中,your_package_name是你的应用程序包名。 3. 构建文件URI并进行操作: ```java File file = new File(getExternalFilesDir(null), "your_file_name"); Uri fileUri = FileProvider.getUriForFile(context, "your_authority", file); // 进行文件的读写操作 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值