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
本站由北京市万商天勤律师事务所王兴未律师提供法律服务