Android10及以上访问公有目录 您所在的位置:网站首页 共享文件user在哪个目录下打开的 Android10及以上访问公有目录

Android10及以上访问公有目录

2024-06-09 07:06| 来源: 网络整理| 查看: 265

公有目录指的是系统根目录下的Download、DCIM、Documents、Screenshots、Music等文件夹。

本文说的访问是指:列举出某一公有目录下的所有文件、删除某个文件、保存文件到某个公有目录等意思。

Android10以下按原来的File(path)方式,本文不表。

Android10及以上可以使用MediaStore访问公有目录。如果我们在公有目录下只操作自己应用生成的文件,是不需要申请文件读写权限的。另外,公有目录下的文件在APP卸载后不会被删除,也能被其他应用访问(仅限于媒体类型的文件)。(其他应用只能read,不能write)

下面是关于Android10及以上存储权限的说明:(官方说明:https://developer.android.com/training/data-storage?hl=zh-cn)

WRITE_EXTERNAL_STORAGE在Android11已过时,不要再去申请这个。

Android10及以上是新版的权限MANAGE_EXTERNAL_STORAGE。但是如果你要在Google Play上架,且你的APP不是文件管理器之类的应用,那么建议查看一下Google Play的政策说明:https://support.google.com/googleplay/android-developer/answer/9956427。代码里Android Stuido也提示说Most apps are not allowed to use MANAGE_EXTERNAL_STORAGE。

READ_EXTERNAL_STORAGE读取权限。如果你需要读取别的应用保存在公有目录下的文件(仅限于媒体文件,无法读取到其他类型的。。),则需要动态申请这个权限;如果读取的是自己应用保存的文件,即便是公有目录,也不需要申请这个权限(ps:有个场景需要读取权限:应用卸载后,之前创建的文件会变成“无主”文件,以后应用重新安装是需要读取权限的。大白话就是:应用卸载重装后,之前的文件不属于你了,现在你去读取,相当于是读别人的文件,所以要读取权限)。

下面的代码都是以Download文件夹为例的,不再特别说明。如果需要操作其他文件夹,改一下Uri即可。

私有目录文件复制到公有目录 /** * 复制私有目录的文件到公有Download目录 * @param context 上下文 * @param oldPath 私有目录的文件路径 * @param targetDirName 公有目录下的目标文件夹名字。比如传test,则会复制到Download/test目录下。另外如果Download目录下test文件夹不存在,会自动创建。 * @return 公有目录的uri,为空则代表复制失败 */ @RequiresApi(Build.VERSION_CODES.Q) fun copyFileToDownloadDir(context: Context,oldPath: String,targetDirName:String): Uri? { try { val oldFile = File(oldPath) //设置目标文件的信息 val values = ContentValues() values.put(MediaStore.Images.Media.DESCRIPTION, "This is a file.") values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, oldFile.name) values.put(MediaStore.Files.FileColumns.TITLE, oldFile.name) values.put(MediaStore.Files.FileColumns.MIME_TYPE, getMimeType(oldPath)) val relativePath = Environment.DIRECTORY_DOWNLOADS + File.separator + targetDirName values.put(MediaStore.Images.Media.RELATIVE_PATH, relativePath) val downloadUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI val resolver = context.contentResolver val insertUri = resolver.insert(downloadUri, values) if (insertUri != null) { val fos = resolver.openOutputStream(insertUri) if (fos != null) { val fis = FileInputStream(oldFile) fis.copyTo(fos) fis.close() fos.close() return insertUri } } } catch (e: Exception) { e.printStackTrace() } return null } fun getMimeType(path: String?): String { var mime = "*/*" path ?: return mime val mmr = MediaMetadataRetriever() try { mmr.setDataSource(path) mime = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE) ?: mime } catch (e: Exception) { e.printStackTrace() } finally { mmr.release() } return mime } 查询公有目录下的文件 /** * 获取公有Download目录下的文件 * @param dirName Download目录下的下一级文件夹的名字 * @return 文件的uri集合 */ @RequiresApi(Build.VERSION_CODES.Q) fun listFiles(context: Context, dirName: String): List { val resultList = ArrayList() try { val resolver = context.contentResolver val downloadUri = MediaStore.Downloads.EXTERNAL_CONTENT_URI val resultCursor = resolver?.query( downloadUri, null, MediaStore.Files.FileColumns.BUCKET_DISPLAY_NAME + "=?", arrayOf(dirName), null ) if (resultCursor != null) { val fileIdIndex = resultCursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID) // val fileNameIndex = resultCursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DISPLAY_NAME) while (resultCursor.moveToNext()) { val fileId = resultCursor.getLong(fileIdIndex) //文件名 // val fileName = resultCursor.getString(fileNameIndex) val pathUri = downloadUri.buildUpon().appendPath("$fileId").build() resultList.add(pathUri) } resultCursor.close() } } catch (e: Exception) { e.printStackTrace() } return resultList } 删除公有目录下的文件 /** * 删除公有目录的文件。(自己应用创建的文件才有权限删除) */ @RequiresApi(Build.VERSION_CODES.Q) fun deleteFile(context: Context, fileUri: Uri) { try { context.contentResolver?.delete(fileUri, null, null) } catch (e: Exception) { e.printStackTrace() } } 公有目录文件复制到私有目录 /** * 公有目录文件复制到私有目录 * @param fileUri 公有目录文件的uri * @param privatePath 私有目录的路径 */ fun copyToPrivateDir(context: Context,fileUri:Uri,privatePath:String){ try { val fis = FileInputStream(context.contentResolver.openFileDescriptor(fileUri,"r")?.fileDescriptor) fis.copyTo(FileOutputStream(privatePath)) fis.close() }catch (e:Exception){ e.printStackTrace() } }

上面用到的api,导包如下:

import android.content.ContentValues import android.content.Context import android.media.MediaMetadataRetriever import android.net.Uri import android.os.Build import android.os.Environment import android.provider.MediaStore import androidx.annotation.RequiresApi import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.lang.Exception


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有