调用DocumentUI申请权限
Android R实现访问外部存储的Android/data方案

申请权限选择的目录树后,后续所以文件操作都需要按照此目录树为基础做文件操作

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 API

https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile

DocumentFile API的使用

// 包名/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) {
            e.printStackTrace();
    return allFile;

DocumentFile报错

Permission Denial: writing com.android.externalstorage.ExternalStorageProvider uri content:

原因:授权的Uri和使用时调用的Uri不匹配

Eureka涉及到的参数配置项数量众多,它的很多功能都是通过参数配置来实现的,了解这些参数的含义有助于我们更好的应用Eureka的各种功能,下面对Eureka的配置项做具体介绍,供大家参考。 Eureka客户端配置 1、RegistryFetchIntervalSe...
一、在application.properties文件中配置数据库连接 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # %2b表示+号的意思 spring.datasource.url=dbc:mysql://localhost:3306/bootvue202?serverTimezone=GMT%2b8 spring.datasource.username=root spring.datasource.password=7568
Spring Boot 提供了大量的自动配置,极大地简化了spring 应用的开发过程,当用户创建了一个 Spring Boot 项目后,即使不进行任何配置,该项目也能顺利的运行起来。当然,用户也可以根据自身的需要使用配置文件修改 Spring Boot 的默认设置。 SpringBoot 默认使用以下 2 种全局的配置文件,其文件名是固定的。 application.properties application.yml application.properties与 application.y..