Use Storage Access Framework to save attachments
This commit is contained in:
parent
ffc69c9f34
commit
c2e80122f7
7 changed files with 48 additions and 381 deletions
|
@ -1,62 +0,0 @@
|
|||
package com.fsck.k9.cache;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import android.content.Context;
|
||||
import timber.log.Timber;
|
||||
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
|
||||
|
||||
public class TemporaryAttachmentStore {
|
||||
private static final String TEMPORARY_ATTACHMENT_DIRECTORY = "attachments";
|
||||
private static final long MAX_FILE_AGE = 12 * 60 * 60 * 1000; // 12h
|
||||
|
||||
public static File getFile(Context context, String attachmentName) {
|
||||
File directory = getTemporaryAttachmentDirectory(context);
|
||||
String filename = FileHelper.sanitizeFilename(attachmentName);
|
||||
return new File(directory, filename);
|
||||
}
|
||||
|
||||
public static File getFileForWriting(Context context, String attachmentName) throws IOException {
|
||||
File directory = createOrCleanAttachmentDirectory(context);
|
||||
String filename = FileHelper.sanitizeFilename(attachmentName);
|
||||
return new File(directory, filename);
|
||||
}
|
||||
|
||||
private static File createOrCleanAttachmentDirectory(Context context) throws IOException {
|
||||
File directory = getTemporaryAttachmentDirectory(context);
|
||||
if (directory.exists()) {
|
||||
cleanOldFiles(directory);
|
||||
} else {
|
||||
if (!directory.mkdir()) {
|
||||
throw new IOException("Couldn't create temporary attachment store: " + directory.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
private static File getTemporaryAttachmentDirectory(Context context) {
|
||||
return new File(context.getExternalCacheDir(), TEMPORARY_ATTACHMENT_DIRECTORY);
|
||||
}
|
||||
|
||||
private static void cleanOldFiles(File directory) {
|
||||
File[] files = directory.listFiles();
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
long cutOffTime = System.currentTimeMillis() - MAX_FILE_AGE;
|
||||
for (File file : files) {
|
||||
if (file.lastModified() < cutOffTime) {
|
||||
if (file.delete()) {
|
||||
Timber.d("Deleted from temporary attachment store: %s", file.getName());
|
||||
} else {
|
||||
Timber.w("Couldn't delete from temporary attachment store: %s", file.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,167 +0,0 @@
|
|||
package com.fsck.k9.ui.helper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.text.InputType;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.fsck.k9.ui.R;
|
||||
|
||||
public class FileBrowserHelper {
|
||||
/**
|
||||
* A string array that specifies the name of the intent to use, and the scheme to use with it
|
||||
* when setting the data for the intent.
|
||||
*/
|
||||
private static final String[][] PICK_DIRECTORY_INTENTS = {
|
||||
{ "org.openintents.action.PICK_DIRECTORY", "file://" }, // OI File Manager (maybe others)
|
||||
{ "com.estrongs.action.PICK_DIRECTORY", "file://" }, // ES File Explorer
|
||||
{ Intent.ACTION_PICK, "folder://" }, // Blackmoon File Browser (maybe others)
|
||||
{ "com.androidworkz.action.PICK_DIRECTORY", "file://" }
|
||||
}; // SystemExplorer
|
||||
|
||||
private static FileBrowserHelper sInstance;
|
||||
|
||||
/**
|
||||
* callback class to provide the result of the fallback textedit path dialog
|
||||
*/
|
||||
public interface FileBrowserFailOverCallback {
|
||||
/**
|
||||
* the user has entered a path
|
||||
* @param path the path as String
|
||||
*/
|
||||
void onPathEntered(String path);
|
||||
/**
|
||||
* the user has cancel the inputtext dialog
|
||||
*/
|
||||
void onCancel();
|
||||
}
|
||||
/**
|
||||
* factory method
|
||||
*
|
||||
*/
|
||||
private FileBrowserHelper() {
|
||||
}
|
||||
public synchronized static FileBrowserHelper getInstance() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new FileBrowserHelper();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* tries to open known filebrowsers.
|
||||
* If no filebrowser is found and fallback textdialog is shown
|
||||
* @param c the context as activity
|
||||
* @param startPath: the default value, where the filebrowser will start.
|
||||
* if startPath = null => the default path is used
|
||||
* @param requestcode: the int you will get as requestcode in onActivityResult
|
||||
* (only used if there is a filebrowser installed)
|
||||
* @param callback: the callback (only used when no filebrowser is installed.
|
||||
* if a filebrowser is installed => override the onActivtyResult Method
|
||||
*
|
||||
* @return true: if a filebrowser has been found (the result will be in the onActivityResult
|
||||
* false: a fallback textinput has been shown. The Result will be sent with the callback method
|
||||
*
|
||||
*
|
||||
*/
|
||||
public boolean showFileBrowserActivity(Activity c, File startPath, int requestcode, FileBrowserFailOverCallback callback) {
|
||||
boolean success = false;
|
||||
|
||||
if (startPath == null) {
|
||||
startPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
}
|
||||
|
||||
int listIndex = 0;
|
||||
do {
|
||||
String intentAction = PICK_DIRECTORY_INTENTS[listIndex][0];
|
||||
String uriPrefix = PICK_DIRECTORY_INTENTS[listIndex][1];
|
||||
Intent intent = new Intent(intentAction);
|
||||
intent.setData(Uri.parse(uriPrefix + startPath.getPath()));
|
||||
|
||||
try {
|
||||
c.startActivityForResult(intent, requestcode);
|
||||
success = true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// Try the next intent in the list
|
||||
listIndex++;
|
||||
}
|
||||
} while (!success && (listIndex < PICK_DIRECTORY_INTENTS.length));
|
||||
|
||||
if (listIndex == PICK_DIRECTORY_INTENTS.length) {
|
||||
//No Filebrowser is installed => show a fallback textdialog
|
||||
showPathTextInput(c, startPath, callback);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public boolean showFileBrowserActivity(Fragment c, File startPath, int requestcode, FileBrowserFailOverCallback callback) {
|
||||
boolean success = false;
|
||||
|
||||
if (startPath == null) {
|
||||
startPath = startPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
}
|
||||
|
||||
int listIndex = 0;
|
||||
do {
|
||||
String intentAction = PICK_DIRECTORY_INTENTS[listIndex][0];
|
||||
String uriPrefix = PICK_DIRECTORY_INTENTS[listIndex][1];
|
||||
Intent intent = new Intent(intentAction);
|
||||
intent.setData(Uri.parse(uriPrefix + startPath.getPath()));
|
||||
|
||||
try {
|
||||
c.startActivityForResult(intent, requestcode);
|
||||
success = true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// Try the next intent in the list
|
||||
listIndex++;
|
||||
}
|
||||
} while (!success && (listIndex < PICK_DIRECTORY_INTENTS.length));
|
||||
|
||||
if (listIndex == PICK_DIRECTORY_INTENTS.length) {
|
||||
//No Filebrowser is installed => show a fallback textdialog
|
||||
showPathTextInput(c.getActivity(), startPath, callback);
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private void showPathTextInput(final Activity c, final File startPath, final FileBrowserFailOverCallback callback) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(c);
|
||||
|
||||
alert.setTitle(c.getString(R.string.attachment_save_title));
|
||||
alert.setMessage(c.getString(R.string.attachment_save_desc));
|
||||
final EditText input = new EditText(c);
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
if (startPath != null)
|
||||
input.setText(startPath.toString());
|
||||
alert.setView(input);
|
||||
|
||||
alert.setPositiveButton(c.getString(R.string.okay_action), new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
String path = input.getText().toString();
|
||||
callback.onPathEntered(path);
|
||||
}
|
||||
});
|
||||
|
||||
alert.setNegativeButton(c.getString(R.string.cancel_action),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
callback.onCancel();
|
||||
}
|
||||
});
|
||||
|
||||
alert.show();
|
||||
}
|
||||
}
|
|
@ -1,33 +1,26 @@
|
|||
package com.fsck.k9.ui.messageview;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import timber.log.Timber;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.ui.R;
|
||||
import com.fsck.k9.cache.TemporaryAttachmentStore;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.SimpleMessagingListener;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
|
@ -35,7 +28,9 @@ import com.fsck.k9.mailstore.AttachmentViewInfo;
|
|||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.LocalPart;
|
||||
import com.fsck.k9.provider.AttachmentTempFileProvider;
|
||||
import com.fsck.k9.ui.R;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class AttachmentController {
|
||||
|
@ -43,14 +38,12 @@ public class AttachmentController {
|
|||
private final MessagingController controller;
|
||||
private final MessageViewFragment messageViewFragment;
|
||||
private final AttachmentViewInfo attachment;
|
||||
private final DownloadManager downloadManager;
|
||||
|
||||
|
||||
AttachmentController(MessagingController controller, DownloadManager downloadManager,
|
||||
MessageViewFragment messageViewFragment, AttachmentViewInfo attachment) {
|
||||
AttachmentController(MessagingController controller, MessageViewFragment messageViewFragment,
|
||||
AttachmentViewInfo attachment) {
|
||||
this.context = messageViewFragment.getApplicationContext();
|
||||
this.controller = controller;
|
||||
this.downloadManager = downloadManager;
|
||||
this.messageViewFragment = messageViewFragment;
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
@ -63,8 +56,12 @@ public class AttachmentController {
|
|||
}
|
||||
}
|
||||
|
||||
public void saveAttachmentTo(String directory) {
|
||||
saveAttachmentTo(new File(directory));
|
||||
public void saveAttachmentTo(Uri documentUri) {
|
||||
if (!attachment.isContentAvailable()) {
|
||||
downloadAndSaveAttachmentTo((LocalPart) attachment.part, documentUri);
|
||||
} else {
|
||||
saveLocalAttachmentTo(documentUri);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadAndViewAttachment(LocalPart localPart) {
|
||||
|
@ -76,12 +73,12 @@ public class AttachmentController {
|
|||
});
|
||||
}
|
||||
|
||||
private void downloadAndSaveAttachmentTo(LocalPart localPart, final File directory) {
|
||||
private void downloadAndSaveAttachmentTo(LocalPart localPart, final Uri documentUri) {
|
||||
downloadAttachment(localPart, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
messageViewFragment.refreshAttachmentThumbnail(attachment);
|
||||
saveLocalAttachmentTo(directory);
|
||||
saveLocalAttachmentTo(documentUri);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -111,46 +108,15 @@ public class AttachmentController {
|
|||
new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void saveAttachmentTo(File directory) {
|
||||
boolean isExternalStorageMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||
if (!isExternalStorageMounted) {
|
||||
String message = context.getString(R.string.message_view_status_attachment_not_saved);
|
||||
displayMessageToUser(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachment.size > directory.getFreeSpace()) {
|
||||
String message = context.getString(R.string.message_view_status_no_space);
|
||||
displayMessageToUser(message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!attachment.isContentAvailable()) {
|
||||
downloadAndSaveAttachmentTo((LocalPart) attachment.part, directory);
|
||||
} else {
|
||||
saveLocalAttachmentTo(directory);
|
||||
}
|
||||
private void saveLocalAttachmentTo(Uri documentUri) {
|
||||
new SaveAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, documentUri);
|
||||
}
|
||||
|
||||
private void saveLocalAttachmentTo(File directory) {
|
||||
new SaveAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, directory);
|
||||
}
|
||||
|
||||
private File saveAttachmentWithUniqueFileName(File directory) throws IOException {
|
||||
String filename = FileHelper.sanitizeFilename(attachment.displayName);
|
||||
File file = FileHelper.createUniqueFile(directory, filename);
|
||||
|
||||
writeAttachmentToStorage(file);
|
||||
|
||||
addSavedAttachmentToDownloadsDatabase(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private void writeAttachmentToStorage(File file) throws IOException {
|
||||
InputStream in = context.getContentResolver().openInputStream(attachment.internalUri);
|
||||
private void writeAttachment(Uri documentUri) throws IOException {
|
||||
ContentResolver contentResolver = context.getContentResolver();
|
||||
InputStream in = contentResolver.openInputStream(attachment.internalUri);
|
||||
try {
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
OutputStream out = contentResolver.openOutputStream(documentUri);
|
||||
try {
|
||||
IOUtils.copy(in, out);
|
||||
out.flush();
|
||||
|
@ -162,17 +128,8 @@ public class AttachmentController {
|
|||
}
|
||||
}
|
||||
|
||||
private void addSavedAttachmentToDownloadsDatabase(File file) {
|
||||
String fileName = file.getName();
|
||||
String path = file.getAbsolutePath();
|
||||
long fileLength = file.length();
|
||||
String mimeType = attachment.mimeType;
|
||||
|
||||
downloadManager.addCompletedDownload(fileName, fileName, true, mimeType, path, fileLength, true);
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private Intent getBestViewIntentAndSaveFile() {
|
||||
private Intent getBestViewIntent() {
|
||||
Uri intentDataUri;
|
||||
try {
|
||||
intentDataUri = AttachmentTempFileProvider.createTempUriForContentUri(context, attachment.internalUri);
|
||||
|
@ -187,53 +144,25 @@ public class AttachmentController {
|
|||
IntentAndResolvedActivitiesCount resolvedIntentInfo;
|
||||
String mimeType = attachment.mimeType;
|
||||
if (MimeUtility.isDefaultMimeType(mimeType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(intentDataUri, inferredMimeType);
|
||||
resolvedIntentInfo = getViewIntentForMimeType(intentDataUri, inferredMimeType);
|
||||
} else {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(intentDataUri, mimeType);
|
||||
resolvedIntentInfo = getViewIntentForMimeType(intentDataUri, mimeType);
|
||||
if (!resolvedIntentInfo.hasResolvedActivities() && !inferredMimeType.equals(mimeType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(intentDataUri, inferredMimeType);
|
||||
resolvedIntentInfo = getViewIntentForMimeType(intentDataUri, inferredMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolvedIntentInfo.hasResolvedActivities()) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(
|
||||
intentDataUri, MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
resolvedIntentInfo = getViewIntentForMimeType(intentDataUri, MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
|
||||
Intent viewIntent;
|
||||
if (resolvedIntentInfo.hasResolvedActivities() && resolvedIntentInfo.containsFileUri()) {
|
||||
try {
|
||||
File tempFile = TemporaryAttachmentStore.getFileForWriting(context, displayName);
|
||||
writeAttachmentToStorage(tempFile);
|
||||
viewIntent = createViewIntentForFileUri(resolvedIntentInfo.getMimeType(), Uri.fromFile(tempFile));
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "Error while saving attachment to use file:// URI with ACTION_VIEW Intent");
|
||||
viewIntent = createViewIntentForAttachmentProviderUri(intentDataUri, MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
} else {
|
||||
viewIntent = resolvedIntentInfo.getIntent();
|
||||
}
|
||||
|
||||
return viewIntent;
|
||||
return resolvedIntentInfo.getIntent();
|
||||
}
|
||||
|
||||
private IntentAndResolvedActivitiesCount getBestViewIntentForMimeType(Uri contentUri, String mimeType) {
|
||||
private IntentAndResolvedActivitiesCount getViewIntentForMimeType(Uri contentUri, String mimeType) {
|
||||
Intent contentUriIntent = createViewIntentForAttachmentProviderUri(contentUri, mimeType);
|
||||
int contentUriActivitiesCount = getResolvedIntentActivitiesCount(contentUriIntent);
|
||||
|
||||
if (contentUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
File tempFile = TemporaryAttachmentStore.getFile(context, attachment.displayName);
|
||||
Uri tempFileUri = Uri.fromFile(tempFile);
|
||||
Intent fileUriIntent = createViewIntentForFileUri(mimeType, tempFileUri);
|
||||
int fileUriActivitiesCount = getResolvedIntentActivitiesCount(fileUriIntent);
|
||||
|
||||
if (fileUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(fileUriIntent, fileUriActivitiesCount);
|
||||
}
|
||||
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
|
@ -248,14 +177,6 @@ public class AttachmentController {
|
|||
return intent;
|
||||
}
|
||||
|
||||
private Intent createViewIntentForFileUri(String mimeType, Uri uri) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
addUiIntentFlags(intent);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void addUiIntentFlags(Intent intent) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||
}
|
||||
|
@ -294,14 +215,6 @@ public class AttachmentController {
|
|||
public boolean hasResolvedActivities() {
|
||||
return activitiesCount > 0;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return intent.getType();
|
||||
}
|
||||
|
||||
public boolean containsFileUri() {
|
||||
return "file".equals(intent.getData().getScheme());
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewAttachmentAsyncTask extends AsyncTask<Void, Void, Intent> {
|
||||
|
@ -313,7 +226,7 @@ public class AttachmentController {
|
|||
|
||||
@Override
|
||||
protected Intent doInBackground(Void... params) {
|
||||
return getBestViewIntentAndSaveFile();
|
||||
return getBestViewIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -334,7 +247,7 @@ public class AttachmentController {
|
|||
}
|
||||
}
|
||||
|
||||
private class SaveAttachmentAsyncTask extends AsyncTask<File, Void, File> {
|
||||
private class SaveAttachmentAsyncTask extends AsyncTask<Uri, Void, Boolean> {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
|
@ -342,20 +255,21 @@ public class AttachmentController {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected File doInBackground(File... params) {
|
||||
protected Boolean doInBackground(Uri... params) {
|
||||
try {
|
||||
File directory = params[0];
|
||||
return saveAttachmentWithUniqueFileName(directory);
|
||||
Uri documentUri = params[0];
|
||||
writeAttachment(documentUri);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Timber.e(e, "Error saving attachment");
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(File file) {
|
||||
protected void onPostExecute(Boolean success) {
|
||||
messageViewFragment.enableAttachmentButtons(attachment);
|
||||
if (file == null) {
|
||||
if (!success) {
|
||||
displayAttachmentNotSavedMessage();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
|
@ -47,8 +46,6 @@ import com.fsck.k9.mailstore.AttachmentViewInfo;
|
|||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.ui.R;
|
||||
import com.fsck.k9.ui.helper.FileBrowserHelper;
|
||||
import com.fsck.k9.ui.helper.FileBrowserHelper.FileBrowserFailOverCallback;
|
||||
import com.fsck.k9.ui.messageview.CryptoInfoDialog.OnClickShowCryptoKeyListener;
|
||||
import com.fsck.k9.ui.messageview.MessageCryptoPresenter.MessageCryptoMvpView;
|
||||
import com.fsck.k9.ui.settings.account.AccountSettingsActivity;
|
||||
|
@ -63,7 +60,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
|
||||
private static final int ACTIVITY_CHOOSE_FOLDER_MOVE = 1;
|
||||
private static final int ACTIVITY_CHOOSE_FOLDER_COPY = 2;
|
||||
private static final int ACTIVITY_CHOOSE_DIRECTORY = 3;
|
||||
private static final int REQUEST_CODE_CREATE_DOCUMENT = 3;
|
||||
|
||||
public static final int REQUEST_MASK_LOADER_HELPER = (1 << 8);
|
||||
public static final int REQUEST_MASK_CRYPTO_PRESENTER = (1 << 9);
|
||||
|
@ -455,16 +452,9 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
// launched through the MessageList activity, and delivered back via onPendingIntentResult()
|
||||
|
||||
switch (requestCode) {
|
||||
case ACTIVITY_CHOOSE_DIRECTORY: {
|
||||
if (data != null) {
|
||||
// obtain the filename
|
||||
Uri fileUri = data.getData();
|
||||
if (fileUri != null) {
|
||||
String filePath = fileUri.getPath();
|
||||
if (filePath != null) {
|
||||
getAttachmentController(currentAttachmentViewInfo).saveAttachmentTo(filePath);
|
||||
}
|
||||
}
|
||||
case REQUEST_CODE_CREATE_DOCUMENT: {
|
||||
if (data != null && data.getData() != null) {
|
||||
getAttachmentController(currentAttachmentViewInfo).saveAttachmentTo(data.getData());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -819,21 +809,16 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF
|
|||
@Override
|
||||
public void onSaveAttachment(final AttachmentViewInfo attachment) {
|
||||
currentAttachmentViewInfo = attachment;
|
||||
FileBrowserHelper.getInstance().showFileBrowserActivity(MessageViewFragment.this, null,
|
||||
ACTIVITY_CHOOSE_DIRECTORY, new FileBrowserFailOverCallback() {
|
||||
@Override
|
||||
public void onPathEntered(String path) {
|
||||
getAttachmentController(attachment).saveAttachmentTo(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.setType(attachment.mimeType);
|
||||
intent.putExtra(Intent.EXTRA_TITLE, attachment.displayName);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
|
||||
startActivityForResult(intent, REQUEST_CODE_CREATE_DOCUMENT);
|
||||
}
|
||||
|
||||
private AttachmentController getAttachmentController(AttachmentViewInfo attachment) {
|
||||
return new AttachmentController(mController, downloadManager, this, attachment);
|
||||
return new AttachmentController(mController, this, attachment);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.fsck.k9.ui.settings
|
||||
|
||||
import com.fsck.k9.ui.helper.FileBrowserHelper
|
||||
import com.fsck.k9.helper.NamedThreadFactory
|
||||
import com.fsck.k9.ui.account.AccountsLiveData
|
||||
import com.fsck.k9.ui.settings.account.AccountSettingsDataStoreFactory
|
||||
|
@ -14,7 +13,6 @@ val settingsUiModule = applicationContext {
|
|||
bean { AccountsLiveData(get()) }
|
||||
viewModel { SettingsViewModel(get()) }
|
||||
|
||||
bean { FileBrowserHelper.getInstance() }
|
||||
bean { GeneralSettingsDataStore(get(), get(), get("SaveSettingsExecutorService")) }
|
||||
bean("SaveSettingsExecutorService") {
|
||||
Executors.newSingleThreadExecutor(NamedThreadFactory("SaveSettings"))
|
||||
|
|
|
@ -292,8 +292,7 @@ Please submit bug reports, contribute new features and ask questions at
|
|||
<string name="message_view_bcc_label">Bcc:</string>
|
||||
<string name="message_view_attachment_view_action">Open</string>
|
||||
<string name="message_view_attachment_download_action">Save</string>
|
||||
<string name="message_view_status_attachment_not_saved">Unable to save attachment to SD card.</string>
|
||||
<string name="message_view_status_no_space">The attachment could not be saved as there is not enough space.</string>
|
||||
<string name="message_view_status_attachment_not_saved">Unable to save attachment.</string>
|
||||
<string name="message_view_show_pictures_action">Show pictures</string>
|
||||
<string name="message_view_no_viewer">Unable to find viewer for <xliff:g id="mimetype">%s</xliff:g>.</string>
|
||||
<string name="message_view_download_remainder">Download complete message</string>
|
||||
|
|
|
@ -2,7 +2,7 @@ buildscript {
|
|||
ext {
|
||||
buildConfig = [
|
||||
'compileSdk': 27,
|
||||
'minSdk': 15,
|
||||
'minSdk': 19,
|
||||
'buildTools': '27.0.3'
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in a new issue