Messaging: Migrate attachments to MediaStore
* Saving them doesn't work otherwise * We don't have to care about MediaScanner and DownloadManager anymore that way, either Fixes: https://gitlab.com/LineageOS/issues/android/-/issues/8573 Change-Id: I7a3b1dc6916feff4849bdfa2b8937460c32bc5a2 Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com> (cherry picked from commit 93bd39838d4a395dd710796b0e71ada1ec1f5ff2)
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 The Android Open Source Project
|
* Copyright (C) 2015 The Android Open Source Project
|
||||||
* Copyright (C) 2024 The LineageOS Project
|
* Copyright (C) 2024-2025 The LineageOS Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
package com.android.messaging.ui.conversation;
|
package com.android.messaging.ui.conversation;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.DownloadManager;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
@@ -36,6 +37,7 @@ import android.os.Environment;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.provider.MediaStore;
|
||||||
import android.support.v7.mms.pdu.ContentType;
|
import android.support.v7.mms.pdu.ContentType;
|
||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -1295,16 +1297,22 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void onExecute() {
|
protected void onExecute() {
|
||||||
final File appDir = new File(Environment.getExternalStoragePublicDirectory(
|
final String appDir = Environment.DIRECTORY_PICTURES
|
||||||
Environment.DIRECTORY_PICTURES),
|
+ File.separator
|
||||||
mContext.getResources().getString(R.string.app_name));
|
+ mContext.getResources().getString(R.string.app_name);
|
||||||
final File downloadDir = Environment.getExternalStoragePublicDirectory(
|
final String downloadDir = Environment.DIRECTORY_DOWNLOADS;
|
||||||
Environment.DIRECTORY_DOWNLOADS);
|
final ContentResolver resolver = mContext.getContentResolver();
|
||||||
for (final AttachmentToSave attachment : mAttachmentsToSave) {
|
for (final AttachmentToSave attachment : mAttachmentsToSave) {
|
||||||
final boolean isImageOrVideo = ContentType.isImageType(attachment.contentType)
|
final boolean isImageOrVideo = ContentType.isImageType(attachment.contentType)
|
||||||
|| ContentType.isVideoType(attachment.contentType);
|
|| ContentType.isVideoType(attachment.contentType);
|
||||||
attachment.persistedUri = UriUtil.persistContent(attachment.uri,
|
ContentValues values = new ContentValues();
|
||||||
isImageOrVideo ? appDir : downloadDir, attachment.contentType);
|
values.put(MediaStore.MediaColumns.MIME_TYPE, attachment.contentType);
|
||||||
|
values.put(MediaStore.MediaColumns.RELATIVE_PATH, isImageOrVideo ?
|
||||||
|
appDir : downloadDir);
|
||||||
|
attachment.persistedUri = resolver.insert(isImageOrVideo
|
||||||
|
? MediaStore.Images.Media.EXTERNAL_CONTENT_URI
|
||||||
|
: MediaStore.Downloads.EXTERNAL_CONTENT_URI, values);
|
||||||
|
UriUtil.persistContent(mContext, attachment.uri, attachment.persistedUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1319,35 +1327,12 @@ public class ConversationFragment extends Fragment implements ConversationDataLi
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inform MediaScanner about the new file
|
|
||||||
final Intent scanFileIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
|
|
||||||
scanFileIntent.setData(attachment.persistedUri);
|
|
||||||
mContext.sendBroadcast(scanFileIntent);
|
|
||||||
|
|
||||||
if (ContentType.isImageType(attachment.contentType)) {
|
if (ContentType.isImageType(attachment.contentType)) {
|
||||||
imageCount++;
|
imageCount++;
|
||||||
} else if (ContentType.isVideoType(attachment.contentType)) {
|
} else if (ContentType.isVideoType(attachment.contentType)) {
|
||||||
videoCount++;
|
videoCount++;
|
||||||
} else {
|
} else {
|
||||||
otherCount++;
|
otherCount++;
|
||||||
// Inform DownloadManager of the file so it will show in the "downloads" app
|
|
||||||
final DownloadManager downloadManager =
|
|
||||||
(DownloadManager) mContext.getSystemService(
|
|
||||||
Context.DOWNLOAD_SERVICE);
|
|
||||||
final String filePath = attachment.persistedUri.getPath();
|
|
||||||
final File file = new File(filePath);
|
|
||||||
|
|
||||||
if (file.exists()) {
|
|
||||||
downloadManager.addCompletedDownload(
|
|
||||||
file.getName() /* title */,
|
|
||||||
mContext.getString(
|
|
||||||
R.string.attachment_file_description) /* description */,
|
|
||||||
true /* isMediaScannerScannable */,
|
|
||||||
attachment.contentType,
|
|
||||||
file.getAbsolutePath(),
|
|
||||||
file.length(),
|
|
||||||
false /* showNotification */);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -258,14 +258,12 @@ public class UriUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist a piece of content from the given sourceUri, byte by byte to the
|
* Persist a piece of content from the given sourceUri, byte by byte to the
|
||||||
* specified output directory.
|
* specified targetUri.
|
||||||
* @return the output Uri if the operation succeeded, or null if failed.
|
|
||||||
*/
|
*/
|
||||||
@DoesNotRunOnMainThread
|
@DoesNotRunOnMainThread
|
||||||
public static Uri persistContent(
|
public static void persistContent(
|
||||||
final Uri sourceUri, final File outputDir, final String contentType) {
|
final Context context, final Uri sourceUri, final Uri targetUri) {
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
final Context context = Factory.get().getApplicationContext();
|
|
||||||
try {
|
try {
|
||||||
if (UriUtil.isLocalResourceUri(sourceUri)) {
|
if (UriUtil.isLocalResourceUri(sourceUri)) {
|
||||||
inputStream = context.getContentResolver().openInputStream(sourceUri);
|
inputStream = context.getContentResolver().openInputStream(sourceUri);
|
||||||
@@ -273,13 +271,12 @@ public class UriUtil {
|
|||||||
// The content is remote. Download it.
|
// The content is remote. Download it.
|
||||||
inputStream = getInputStreamFromRemoteUri(sourceUri);
|
inputStream = getInputStreamFromRemoteUri(sourceUri);
|
||||||
if (inputStream == null) {
|
if (inputStream == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return persistContent(inputStream, outputDir, contentType);
|
copyContent(context, inputStream, targetUri);
|
||||||
} catch (final Exception ex) {
|
} catch (final Exception ex) {
|
||||||
LogUtil.e(LogUtil.BUGLE_TAG, "Error while retrieving media ", ex);
|
LogUtil.e(LogUtil.BUGLE_TAG, "Error while retrieving media ", ex);
|
||||||
return null;
|
|
||||||
} finally {
|
} finally {
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user