您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页Android高版本解决java.io.File访问Android/data

Android高版本解决java.io.File访问Android/data

来源:华佗小知识
package io.creator.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.documentfile.provider.DocumentFile;

import java.io.ByteArrayOutputStream;;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

/*
*作者:姚赞丰
*日期:2022-07-13
*解决android11及以上设备无法使用java.io.File访问Android/data
*/

public class File extends java.io.File {

    public final static String STORAGE_PATH = Environment.getExternalStorageDirectory().getPath();
    public final static String STORAGE_DATA_PATH = STORAGE_PATH + "/Android/data";

    //排序
    public final static int SORT_TYPE_NAME = 0;
    public final static int SORT_TYPE_SIZE = 1;
    public final static int SORT_TYPE_TIME = 2;
    
    private static Activity activity;
    private String path;
    private boolean useRoot = false;
    private Document document;
    private DocumentFile documentFile;
    
    
    public File(String path) {
        this(path,true);
    }

    public File(String path,boolean createDocumentFile) {
        super(path);
        initFile(path);
        if(createDocumentFile) {
            initDocumentFile(null);
        }
    }

    public File(String path,DocumentFile documentFile) {
        super(path);
        initFile(path);
        initDocumentFile(documentFile);
    }

    void initFile(String path) {
        this.path = path;
        if (this.path.endsWith("/")) {
            this.path = this.path.substring(0, this.path.length() - 1);
        }
    }

    void initDocumentFile(DocumentFile documentFile) {
        document = new Document(path);
        if(documentFile == null) {
            this.documentFile = document.findDataDocumentFile();
        } else {
            this.documentFile = documentFile;
        }
    }

    public static Activity getActivity() {
        return activity;
    }
    
    public static void setActivity(Activity activity) {
        File.activity = activity;
    }

    //父级文件夹存在则创建文件夹
    @Override
    public boolean mkdir() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            androidx.documentfile.provider.DocumentFile documentFile = Document.formTreeDocumentFile(STORAGE_DATA_PATH);
            String[] dataPathArray = path.replace(STORAGE_DATA_PATH + "/", "").split("/");
            String dataPath = "";
            int index = 0;
            androidx.documentfile.provider.DocumentFile parentDocumentFile = null;
            for (String name : dataPathArray) {
                dataPath = dataPath + name + "/";
                if(path.equals(STORAGE_DATA_PATH)) {
                    return true;
                }

                if(parentDocumentFile == null) {
                    if((parentDocumentFile = documentFile.findFile(name)) == null) {
                        //没有该文件夹
                        break;
                    } else {
                        if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length) {
                            documentFile = parentDocumentFile;
                            return documentFile.isDirectory() && documentFile.exists();
                        }
                    }
                } else {
                    if(parentDocumentFile.findFile(name) == null) {
                        //没有该文件夹
                        if((STORAGE_DATA_PATH + "/" + dataPath).equals(getParentPath() + "/" + name + "/")) {
                            documentFile = parentDocumentFile.createDirectory(name);
                            return documentFile.isDirectory() && documentFile.exists();
                        } else {
                            break;
                        }

                    } else {
                        if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length ) {
                            documentFile = parentDocumentFile;
                            return documentFile.isDirectory() && documentFile.exists();
                        } else {
                            if(parentDocumentFile.findFile(name) == null) {
                                parentDocumentFile = parentDocumentFile.createDirectory(name);
                                documentFile = parentDocumentFile;
                            } else {
                                parentDocumentFile = parentDocumentFile.findFile(name);
                            }
                        }
                    }
                }
                index++;
            }
            return false;
        } else {
            return super.mkdir();
        }
    }

    //创建文件夹
    @Override
    public boolean mkdirs() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            androidx.documentfile.provider.DocumentFile documentFile = Document.formTreeDocumentFile(STORAGE_DATA_PATH);
            String[] dataPathArray = path.replace(STORAGE_DATA_PATH + "/", "").split("/");
            String dataPath = "";
            int index = 0;
            androidx.documentfile.provider.DocumentFile parentDocumentFile = null;
            for (String name : dataPathArray) {
                dataPath = dataPath + name + "/";
                if(path.equals(STORAGE_DATA_PATH)) {
                    return true;
                }

                if(parentDocumentFile == null) {
                    if((parentDocumentFile = documentFile.findFile(name)) == null) {
                        //没有该文件
                        parentDocumentFile = documentFile.createDirectory(name);
                    }
                    if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length) {
                        //找到文件
                        this.documentFile = parentDocumentFile;
                        return parentDocumentFile.isDirectory() && parentDocumentFile.exists();
                    }
                } else {
                    if(parentDocumentFile.findFile(name) == null) {
                        //没有该文件
                        parentDocumentFile = parentDocumentFile.createDirectory(name);
                        this.documentFile = parentDocumentFile;
                    } else {
                        parentDocumentFile = parentDocumentFile.findFile(name);
                    }
                    if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length ) {
                        //找到文件
                        this.documentFile = parentDocumentFile;
                        return parentDocumentFile.isDirectory() && parentDocumentFile.exists();
                    } else {
                        if(parentDocumentFile.findFile(name) != null) {
                            parentDocumentFile = parentDocumentFile.findFile(name);
                        }

                    }
                }
                index++;
            }
            return false;
        } else {
            return super.mkdirs();
        }
    }

    //创建空文件
    @Override
    public boolean createNewFile() throws IOException {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            File file = new File(getParentPath());
            if(file.getDocumentFile() == null) {
                //创建父级文件夹
                if(file.mkdirs() && file.getDocumentFile() != null) {
                    if((documentFile = file.getDocumentFile().findFile(getName())) == null) {
                        documentFile = file.getDocumentFile().createFile(null,getName());
                        return documentFile.isFile() && documentFile.exists();
                    } else {
                        return documentFile.isFile() && documentFile.exists();
                    }
                }
            } else {
                documentFile = file.getDocumentFile().findFile(getName());
                if (documentFile == null) {
                    documentFile = file.getDocumentFile().createFile(null, getName());
                }
                return documentFile.isFile() && documentFile.exists();
            }
        } else {
            return super.createNewFile();
        }
        return false;
    }

    @Override
    public boolean isFile() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.isFile();
        } else {
            return super.isFile();
        }
    }

    @Override
    public boolean isDirectory() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.isDirectory();
        } else {
            return super.isDirectory();
        }
    }


    @Override
    public boolean canRead() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.canRead();
        } else {
            return super.canRead();
        }
    }

    @Override
    public boolean canWrite() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.canWrite();
        } else {
            return super.canWrite();
        }
    }

    @Override
    public boolean exists() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.exists();
        } else {
            return super.exists();
        }
    }

    @Override
    public long length() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            if(documentFile != null) {
                return documentFile.length();
            }
        } else {
            return super.length();
        }
        return -1;
    }

    public String readText() {
        return readText("UTF-8");
    }

    public String readText(String encoding) {
        try {
            return new String(getBytes(),encoding);
        } catch (Exception exception) {
            return null;
        }
    }

    public boolean writeBytes(byte[] bytes) {
        try {
            getOutputStream().write(bytes);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }

    public boolean writeText(String content) {
        return writeText(content, "UTF-8");
    }

    public boolean writeText(String content,String encoding) {
        try {
            return writeBytes(content.getBytes(encoding));
        } catch (Exception exception) {
            return false;
        }
    }

    @Nullable
    @Override
    public File[] listFiles() {
        File[] fileArray = new File[0];
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            if(documentFile != null && documentFile.isDirectory()) {
                DocumentFile[] documentFiles = documentFile.listFiles();
                fileArray = new File[documentFiles.length];
                int index= 0;
                for (DocumentFile documentFile : documentFiles) {
                    fileArray[index] = new File(getAbsolutePath() + "/" + documentFile.getName(),documentFile);
                    index++;
                }
            }
        } else {
            java.io.File[] files = super.listFiles();
            fileArray = new File[files.length];
            int index= 0;
            for (java.io.File file : files) {
                fileArray[index] = new File(getAbsolutePath() + "/" + file.getName(),false);
                index++;
            }

        }
        return fileArray;
    }

    public File[] listFiles(int sortType) {
        File[] files  = listFiles();
        sort(files,sortType);
        return files;
    }

    //上次修改时间(毫秒)
    @Override
    public long lastModified() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            if(documentFile != null) {
                return documentFile.lastModified();
            }
        } else {
            return super.lastModified();
        }
        return -1;
    }


    //删除
    @Override
    public boolean delete() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
            return documentFile != null && documentFile.delete();
        } else {
            return super.delete();
        }
    }



    @Nullable
    public String getParentPath() {
        return super.getParentFile().getAbsolutePath();
    }

    @NonNull
    @Override
    public String getName() {
        return super.getName();
    }

    public byte[] getBytes() {
        return inputToBytes(getInputStream());
    }

    public InputStream getInputStream() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
                return documentFile != null ? activity.getContentResolver().openInputStream(documentFile.getUri()) : null;
            } else{
                return new FileInputStream(getAbsolutePath());
            }
        } catch (Exception exception) {
            return null;
        }
    }

    public OutputStream getOutputStream() {
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && path.startsWith(STORAGE_DATA_PATH)) {
                return documentFile != null ? activity.getContentResolver().openOutputStream(documentFile.getUri()) : null;
            } else{
                return new FileOutputStream(getAbsolutePath());
            }
        } catch (Exception exception) {
            return null;
        }
    }

    public String getAbsolutePath() {
        if (path.startsWith("@")) {
            //assets目录
            return path.substring(1);
        } else if (path.startsWith("$")) {
            //私有目录(可设置执行权限)
            return activity.getFilesDir() + "/" + path.substring(1);
        } else if (path.startsWith("#")) {
            //私有目录(不可设置执行权限)
            return STORAGE_DATA_PATH + "/" + activity.getPackageName() + "/" + path.substring(1);
        } else if (path.startsWith("%")) {
            //设备内部存储目录
            return STORAGE_PATH + "/" + path.substring(1);
        } else {
            return path;
        }
    }

    public DocumentFile getDocumentFile() {
        return documentFile;
    }

    void sort(File[] files, int type) {
        Collections.sort(Arrays.asList(files), new Comparator<File>() {
            @Override
            public int compare(File file1,File file2) {
                if (type == SORT_TYPE_TIME) {
                    //按照时间排序
                    long diff = file1.lastModified() - file2.lastModified();
                    if (diff > 0) {
                        return 1;
                    } else if (diff == 0) {
                        return 0;
                    } else {
                        return -1;
                    }
                } else if (type == SORT_TYPE_SIZE) {
                    //按照文件大小排序
                    long diff = file1.length() - file2.length();
                    if (diff > 0) {
                        return 1;
                    } else if (diff == 0) {
                        return 0;
                    } else {
                        return -1;
                    }
                } else if (type == SORT_TYPE_NAME) {
                    //按照名称排序
                    return file1.getName().compareTo(file2.getName());
                }
                return 0;
            }
            @Override
            public boolean equals(Object obj) {
                return true;
            }
        });

    }

    //输入流转字节
    byte[] inputToBytes(InputStream input) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        int n = 0;
        byte[] bytes = new byte[1024 * 4];
        while (true) {
            try {
                if (!(-1 != (n = input.read(bytes)))) break;
            } catch (Exception exception) {
            }
            output.write(bytes, 0, n);
        }
        return output.toByteArray();
    }


    public static class Document {

        public final static String CONTEXT_TREE = "content://com.android.externalstorage.documents/tree/primary%3A";
        public final static String CONTEXT_TREE_DOCUMENT = "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3A";

        String path;

        public Document(String path) {
            this.path = new File(path,false).getAbsolutePath();
        }

        public static androidx.documentfile.provider.DocumentFile formSingleDocumentFile(String path) {
            path = (path.endsWith("/") ? path.substring(0, path.length() - 1) :path)
                    .replace(STORAGE_PATH, "").replace("/", "%2F");
            return androidx.documentfile.provider.DocumentFile.fromSingleUri(activity, Uri.parse(CONTEXT_TREE_DOCUMENT + path));
        }

        public static androidx.documentfile.provider.DocumentFile formTreeDocumentFile(String path) {
            path = (path.endsWith("/") ? path.substring(0, path.length() - 1) :path)
                    .replace(STORAGE_PATH, "").replace("/", "%2F");
            return androidx.documentfile.provider.DocumentFile.fromTreeUri(activity, Uri.parse(CONTEXT_TREE_DOCUMENT + path.replace(STORAGE_PATH, "").replace("/", "%2F")));
        }

        //获取目录权限状态
        public boolean getDirPermissionStatus() {
            String urlString = this.path;
            if (urlString != null) {
                urlString = this.path.startsWith(STORAGE_PATH) ? this.path.replace(STORAGE_PATH + "/", "") : this.path;
                urlString = urlString.endsWith("/") ? urlString.substring(0, urlString.length() - 1) : urlString;
                urlString = !urlString.startsWith(CONTEXT_TREE) ? urlString.replaceAll("/", "%2F") : urlString;
                urlString = !urlString.startsWith(CONTEXT_TREE) ? CONTEXT_TREE + urlString : urlString;
                for (UriPermission persistedUriPermission : activity.getContentResolver().getPersistedUriPermissions()) {
                    System.out.println(persistedUriPermission.getUri().toString() + ":" + urlString);
                    if (persistedUriPermission.isReadPermission() && persistedUriPermission.getUri().toString().equals(urlString)) {
                        return true;
                    }
                }
            }
            return false;
        }

        public Uri getUri() {
            return Uri.parse(CONTEXT_TREE_DOCUMENT + path.replace("/storage/emulated/0/", "").replace("/", "%2F"));
        }
        //文件对象
        public androidx.documentfile.provider.DocumentFile formSingleDocumentFile() {
            path = (path.endsWith("/") ? path.substring(0, path.length() - 1) :path)
                    .replace(STORAGE_PATH, "").replace("/", "%2F");
            return androidx.documentfile.provider.DocumentFile.fromSingleUri(activity, Uri.parse(CONTEXT_TREE_DOCUMENT + path));
        }

        //目录对象
        public androidx.documentfile.provider.DocumentFile formTreeDocumentFile() {
            path = (path.endsWith("/") ? path.substring(0, path.length() - 1) :path)
                    .replace(STORAGE_PATH, "").replace("/", "%2F");
            return androidx.documentfile.provider.DocumentFile.fromTreeUri(activity, Uri.parse(CONTEXT_TREE_DOCUMENT + path.replace(STORAGE_PATH, "").replace("/", "%2F")));

        }

        //获取目录权限
        public void getDirPermission() {
            Intent intent = new Intent("android.intent.action.OPEN_DOCUMENT_TREE");
            intent.addFlags(
                    Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                            | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,getUri());
            }
            activity.startActivityForResult(intent, 0);
        }


        //保存权限
        @SuppressLint("WrongConstant")
        public boolean saveDirPermission(Intent data) {
            boolean result = false;
            if (data != null) {
                Uri uri;
                if ((uri = data.getData()) != null) {
                    activity.getContentResolver().takePersistableUriPermission(uri, data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
                }
            }
            result = true;
            return result;
        }

        public androidx.documentfile.provider.DocumentFile findDataDocumentFile() {
            androidx.documentfile.provider.DocumentFile result = null;
            androidx.documentfile.provider.DocumentFile documentFile = formTreeDocumentFile(STORAGE_DATA_PATH);
            String[] dataPathArray = path.replace(STORAGE_DATA_PATH + "/", "").split("/");
            String dataPath = "";
            int index = 0;
            androidx.documentfile.provider.DocumentFile parentDocumentFile = null;
            for (String name : dataPathArray) {
                dataPath = dataPath + name + "/";
                if(path.equals(STORAGE_DATA_PATH)) {
                    return documentFile;
                }

                if(parentDocumentFile == null) {
                    if((parentDocumentFile = documentFile.findFile(name)) == null) {
                        //没有该文件
                        break;
                    } else {
                        if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length) {
                            return parentDocumentFile;
                        }
                    }
                } else {
                    if(parentDocumentFile.findFile(name) == null) {
                        //没有该文件
                        break;
                    } else {
                        if(name.equals(parentDocumentFile.getName()) && (index + 1) == dataPathArray.length ) {
                            return parentDocumentFile;
                        } else {

                            if(parentDocumentFile.findFile(name) != null) {
                                parentDocumentFile = parentDocumentFile.findFile(name);
                                if(dataPathArray.length == (index + 1)) {
                                    return parentDocumentFile;
                                }


                            }
                        }
                    }
                }
                index++;
            }
            return null;

        }

    }
}

kotlin使用方法: 

在您的Activity中设置File.activity

在类变量中声明变量类型

var document: File.Document? = null
var document: File.Document? = null

class * : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {

        document = File.Document(File.STORAGE_DATA_PATH)
            if(!document!!.dirPermissionStatus) {
            document!!.getDirPermission()
        }

        var file = File(File.STORAGE_PATH)
        for(file2 in file.listFiles(File.SORT_TYPE_NAME)!!) {
            System.out.println(file2.name)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(document!!.saveDirPermission(data)) {
//保存权限成功
        } else {
}
    }
}

 最后说一下这个代码块真的一般般啊!!!

//新增的几个新方法
readText() //获取文件文本内容
readText("UTF-8") //使用指定编码获取文件文本内容
writeBytes() //写入字节
writeText("内容") //写入文本
writeText("内容","UTF-8")//使用指定编码写入文本
listFiles()获取当前文件夹列表
listFiles(File.SORT_TYPE_NAME)使用指定排序方式获取当前文件夹列表(SORT_TYPE_NAME,SORT_SIZE,SORT_TYPE_TIME)名称,大小,类型
getBytes//获取当前文件字节
getInputStream()//获取当前文件输入流
getOutoutStream()//获取文件输出流
//有时间再更新,凌晨了睡觉睡觉

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务