添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
小胡子的大葱  ·  Developer Community·  6 月前    · 
聪明的墨镜  ·  windows.ui.xaml.dll ...·  6 月前    · 
安静的匕首  ·  PostgreSQL Character ...·  8 月前    · 

安卓访问外部存储ExternalStorage,DocumentFile及Uri

2023/02/22 android 共 3892 字,约 12 分钟

关键词 :安卓,权限,ExternalStorage,SDCard

Android R上分区存储的限制得到进一步加强,无论APP的 targetsdkversion 是多少,都将无法访问 Android/data Android/obb 这二个应用私有目录。这无疑对会部分APP的业务场景及用户体验造成冲击,典型的如下:

  • 文件管理类软件:微信、QQ传输的文件无法展示给用户以便捷使用
  • 垃圾清理类软件:清理缓存功能受阻

声明 MANAGE_EXTERNAL_STORAGE 权限可以使用 File 遍历除 Android/data Android/obb 之外的目录。如需确定您的应用是否已获得 MANAGE_EXTERNAL_STORAGE 权限,请调用 Environment.isExternalStorageManager()

android - Delete Audio From Sdcard - Stack Overflow

@Override
public void onActivityResult(int requestCode,int resultCode,Intent resultData) {
    if (resultCode != RESULT_OK)
        return;
    Uri treeUri = resultData.getData();
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
    grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    DocumentFile YourAudioFile=  pickedDir.findFile("YourAudioFileNameGoesHere");
// And here you can delete YourAudioFile or do whatever you want with it

Uri

Uri的构造: “content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3AAndroid%2Fdata”;

外部存储:content://com.android.externalstorage.documents 选择的目录树关键字:/tree/primary 选择的文件关键字:/document/primary

Uri uri = Uri.parse(content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3AAndroid%2Fdata”);

DocumentFile

[DocumentFile Android Developers](https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile)
// 包名/file目录
public static final String NOTE_BOOK_FILES_URI =
            "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3AAndroid%2Fdata%2Fcom.freeme.freemenote%2Ffiles";
//判断文件是否存在 DocumentFile
Uri filesUri = Uri.parse(NOTE_BOOK_FILES_URI);
boolean isExistsFilesDir = DocumentFile.fromSingleUri(mContext, filesUri).exists();
//不存在则创建 packageUri为父目录树
if (!isExistsFilesDir) {
    try {
        filesUri = DocumentsContract.createDocument(mContext.getContentResolver(), packageUri, "vnd.android.document/directory", "files");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
//复制文件 File to DocumentFile DocumentsContract
public static void fileToDocumentFile(Context context, File originFile, String fileName, Uri parentUri) {
    //String fileName = originFile.getName();
    try {
        InputStream in = new FileInputStream(originFile);
        Uri documentFile = DocumentsContract.createDocument(context.getContentResolver(), parentUri, "*/*", fileName);
        //DocumentFile写入流
        OutputStream out = context.getContentResolver().openOutputStream(documentFile);
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        in.close();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
// 读取DocumentFile to File
public static List<File> documentFileToFile(Context context) {
    List<File> allFile = new ArrayList<File>();
    Uri dirUri = Uri.parse(Constant.NOTE_BOOK_FILES_URI);
    DocumentFile documentFile = DocumentFile.fromTreeUri(context, dirUri);
    //遍历DocumentFile
    DocumentFile[] files = documentFile.listFiles();
    LogUtil.d(Constant.TAG, "documentFileToFile files count=" + files.length);
    for (DocumentFile file : files) {
        String fileName = file.getName();
        Uri fileUri = file.getUri();
        LogUtil.d(Constant.TAG, "documentFileToFile fileName=" + fileName + " fileUri=" + fileUri);
        try {
            //DocumentFile输入流
            InputStream in = context.getContentResolver().openInputStream(fileUri);
            File newFile = new File(Constant.BACKUP_DIR_PATH, fileName);
            OutputStream out = new FileOutputStream(newFile);
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            in.close();
            out.close();
            allFile.add(newFile);
        } catch (Exception e) {