Вот мое решение:
Скачать файл с Glide
public void downloadFile(Context context, String url){
String mimeType = getMimeType(url);
Glide.with(context).asFile().load(url).listener(new RequestListener<File>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<File> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(File resource, Object model, Target<File> target, DataSource dataSource, boolean isFirstResource) {
saveFile(context,resource, mimeType);
return false;
}
}).submit();
}
Получить файл mimeType
public static String getMimeType(String url) {
String mimeType = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
return mimeType;
}
и сохранить файл на внешний хранилище
public Uri saveFile(Context context, File file, String mimeType) {
String folderName = "Pictures";
String extension = ".jpg";
if(mimeType.endsWith("gif")){
extension = ".gif";
}else if(mimeType.startsWith("image/")){
extension = ".jpg";
}else if(mimeType.startsWith("video/")){
extension = ".mp4";
folderName = "Movies";
}else if(mimeType.startsWith("audio/")){
extension = ".mp3";
folderName = "Music";
}else if(mimeType.endsWith("pdf")){
extension = ".pdf";
folderName = "Documents";
}
if (android.os.Build.VERSION.SDK_INT >= 29) {
ContentValues values = new ContentValues();
values.put(MediaStore.Files.FileColumns.MIME_TYPE, mimeType);
values.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000);
values.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis());
values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, folderName);
values.put(MediaStore.Files.FileColumns.IS_PENDING, true);
values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, "file_" + System.currentTimeMillis() + extension);
Uri uri = null;
if(mimeType.startsWith("image/")){
uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
}else if(mimeType.startsWith("video/")){
uri = context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}else if(mimeType.startsWith("audio/")){
uri = context.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
}else if(mimeType.endsWith("pdf")){
uri = context.getContentResolver().insert(MediaStore.Files.getContentUri("external"), values);
}
if (uri != null) {
try {
saveFileToStream(context.getContentResolver().openInputStream(Uri.fromFile(file)), context.getContentResolver().openOutputStream(uri));
values.put(MediaStore.Video.Media.IS_PENDING, false);
context.getContentResolver().update(uri, values, null, null);
return uri;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
return null;
}
сохранить файл в поток
private void saveFileToStream(InputStream input, OutputStream outputStream) throws IOException {
try {
try (OutputStream output = outputStream ){
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} catch (IOException e) {
e.printStackTrace();
}
} finally {
input.close();
}
}
Я пробовал с эмулятором Android 29. Работает нормально.
Примечание : getExternalStorageDirectory () устарел на уровне API 29. Для улучшения конфиденциальности пользователей прямой доступ к общим / внешним устройствам хранения не рекомендуется. Когда приложение предназначается для Build.VERSION_CODES.Q, путь, возвращаемый этим методом, больше не доступен напрямую для приложений. Приложения могут по-прежнему получать доступ к содержимому, хранящемуся в общем / внешнем хранилище, путем перехода на другие альтернативы, такие как Context # getExternalFilesDir (String), MediaStore или Intent # ACTION_OPEN_DOCUMENT.