Android 11 公共目录Download文件操作
2022-01-12 本文已影响0人
我家猫猫不睡觉
因公司需求在不申请读写权限的情况下 下载和上传Download里面的文件。
这里采取SAF方式
一:选择文件上传
- 创建指定文件夹
创建文件夹我是直接用绝对路径创建的,文件夹可以创建成功。但是不可这么创建文件,开始直接下载文件到download文件夹 稍过一会文件就会被自动删除。
public static final String DOWNLOAD_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/JoyStarManager";
if (CommonUtils.isFirstStart()) {
File downloadFile = new File(Configs.DOWNLOAD_PATH);
if (!downloadFile.exists()) {
downloadFile.mkdir();
}
}
- 打开指定文件夹目录 获取文件的uri
public static final String DOWNLOAD_URI = "content://com.android.externalstorage.documents/tree/primary%3ADownload%2FJoyStarManager";
Uri mDocumentDownloadUri = Uri.parse(Configs.DOWNLOAD_URI);
getDownloadDirFiles(SCAN_IMG_IN_DOWNLOAD, mDocumentDownloadUri);
private void getDownloadDirFiles(int scanType, Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
try {
final int takeFlags = getIntent().getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(uri, takeFlags);
DocumentFile documentFile = DocumentFile.fromTreeUri(this, uri);
DocumentFile[] documentFiles = documentFile.listFiles();
mLocalFileInfos = new ArrayList<>();
LocalFileInfo fileInfo;
for (DocumentFile file : documentFiles) {
Uri fileUri = file.getUri();
String path = fileUri.getPath();
String fileType = FileUtil.getFileType(path);
switch (scanType) {
case SCAN_IMG_IN_DOWNLOAD:
if (fileType.equals(Configs.JPG) || fileType.equals(Configs.PNG)) {
fileInfo = new LocalFileInfo();
fileInfo.setUri(fileUri.toString());
fileInfo.setName(file.getName());
fileInfo.setType(fileType);
mLocalFileInfos.add(fileInfo);
}
break;
case SCAN_ZIP_IN_DOWNLOAD:
if (fileType.equals(Configs.ZIP) && path.endsWith(Configs.ZIP)) {
fileInfo = new LocalFileInfo();
fileInfo.setUri(fileUri.toString());
fileInfo.setName(file.getName());
fileInfo.setType(fileType);
mLocalFileInfos.add(fileInfo);
} else if (fileType.equals(Configs.RAR)) {
fileInfo = new LocalFileInfo();
fileInfo.setName(file.getName());
fileInfo.setUri(fileUri.toString());
fileInfo.setType(fileType);
mLocalFileInfos.add(fileInfo);
}
break;
case SCAN_ZIP_APK_IN_DOWNLOAD:
if (fileType.equals(Configs.ZIP) || fileType.equals(Configs.RAR)) {
fileInfo = new LocalFileInfo();
fileInfo.setName(file.getName());
fileInfo.setUri(fileUri.toString());
fileInfo.setType(fileType);
mLocalFileInfos.add(fileInfo);
}
break;
}
mAdapter.setData(mLocalFileInfos);
}
} catch (SecurityException e) {
//转换成可以使用的路径uri
Uri useUri = DocumentFile.fromTreeUri(this, mDocumentDownloadUri).getUri();
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
//打开指定路径文件夹
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, useUri);
//申请这个文件夹的读写权限
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(intent, SCAN_DOWNLOAD_CALL_BACK);
// Uri useUri = DocumentFile.fromTreeUri(this, mDocumentDownloadUri).getUri();
// Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
// //文档需要是可以打开的
// intent.addCategory(Intent.CATEGORY_OPENABLE);
// intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, useUri);
// //指定文档的minitype为text类型
// intent.setType("*/*");
// //是否支持多选,默认不支持
// intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false);
// startActivityForResult(intent, SCAN_DOWNLOAD_CALL_BACK);
}
}
}
// 获取文件的Uri
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
protected void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data == null || resultCode != RESULT_OK) {
// 用户未选择任何文件,直接返回
return;
}
if (requestCode == SCAN_DOWNLOAD_CALL_BACK) {
Uri uri = data.getData();
switch (mUploadType) {
case Configs.UPLOAD_NO_ZIP:
getDownloadDirFiles(SCAN_IMG_IN_DOWNLOAD, uri);
break;
case Configs.SET_INFO_TYPE_APK:
getDownloadDirFiles(SCAN_ZIP_APK_IN_DOWNLOAD, uri);
break;
default:
getDownloadDirFiles(SCAN_ZIP_IN_DOWNLOAD, uri);
}
final int takeFlags = data.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getContentResolver().takePersistableUriPermission(uri, takeFlags);
}
}
- 上传
retrofit2 可以直接用流上传
private void addApkInfo() {
mProgressbar.setVisibility(View.VISIBLE);
Map<String, RequestBody> params = new HashMap<>();
params.put("aaa", toRequestBody(aaa));
params.put("bbb", toRequestBody(bbb));
params.put("ccc", toRequestBody(ccc));
params.put("ddd", toRequestBody(ddd));
params.put("eee", toRequestBody(eee));
try {
//获得输入流
InputStream is = getContentResolver().openInputStream(mUri);
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);//表单类型
RequestBody requestBody = new ProgressRequestBody(is, MediaType.parse("multipart/form-data"), new UploadListener() {
@Override
public void onProgressUpdate(int percentage) {
mProgressbar.setProgress(percentage);
}
@Override
public void onError() {
}
@Override
public void onFinish() {
}
});
//zzz是接口的参数名
builder.addFormDataPart("zzz", Uri.encode(mLocalFileInfo.getName()), requestBody);
List<MultipartBody.Part> parts = builder.build().parts();
NetworkManager.getInstance().create(Api.class)
.addApp(params, parts)
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(retrofit2.Call<ResponseBody> call, Response<ResponseBody> response) {
mProgressbar.setVisibility(View.GONE);
@Override
public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
mProgressbar.setVisibility(View.GONE);
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private RequestBody toRequestBody(String value) {
return RequestBody.create(MediaType.parse("multipart/form-data"), value);
}
//附上ProgressRequestBody 代码
public class ProgressRequestBody extends RequestBody {
private File mFile;
private InputStream mFis;
private MediaType mMediaType;
private UploadListener mListener;
private int mEachBufferSize = 2048;
public ProgressRequestBody(final File file, final MediaType mediaType, final UploadListener listener) {
mFile = file;
mMediaType = mediaType;
mListener = listener;
}
public ProgressRequestBody(final InputStream fis, final MediaType mediaType, final UploadListener listener) {
mFis = fis;
mMediaType = mediaType;
mListener = listener;
}
@Override
public MediaType contentType() {
return mMediaType;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = 0;
InputStream in = null;
if (mFile != null) {
fileLength = mFile.length();
in = new FileInputStream(mFile);
} else {
fileLength = mFis.available();
in = mFis;
}
byte[] buffer = new byte[mEachBufferSize];
long uploaded = 0;
try {
int read;
Handler handler = new Handler(Looper.getMainLooper());
while ((read = in.read(buffer)) != -1) {
// update progress on UI thread
handler.post(new ProgressUpdater(uploaded, fileLength));
uploaded += read;
sink.write(buffer, 0, read);
}
} finally {
in.close();
}
}
private class ProgressUpdater implements Runnable {
private long mUploaded;
private long mTotal;
public ProgressUpdater(long uploaded, long total) {
mUploaded = uploaded;
mTotal = total;
}
@Override
public void run() {
mListener.onProgressUpdate((int) (100 * mUploaded / mTotal));
}
}
public interface UploadListener {
void onProgressUpdate(int percentage);
void onError();
void onFinish();
}
二:下载文件到公共目录
原本是准备也采用retrofit2 直接下载到download文件夹里
写了一半后 老板说直接下载到本地然后复制到download文件夹