Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime permissions - External Storage permission #3

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 39 additions & 14 deletions k9mail/src/main/java/com/fsck/k9/activity/Accounts.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
Expand Down Expand Up @@ -115,6 +117,19 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
private static final int DIALOG_RECREATE_ACCOUNT = 3;
private static final int DIALOG_NO_FILE_MANAGER = 4;

private static final int ACTIVITY_REQUEST_PICK_SETTINGS_FILE = 1;
private static final int ACTIVITY_REQUEST_SAVE_SETTINGS_FILE = 2;
private static final int EXPORT_SAVE_PERMISSION = 100;

private static String ACCOUNT_STATS = "accountStats";
private static String STATE_UNREAD_COUNT = "unreadCount";
private static String SELECTED_CONTEXT_ACCOUNT = "selectedContextAccount";
private static final String STATE_EXPORT_GLOBAL_SETTINGS = "exportGlobalSettings";
private static final String STATE_EXPORT_ACCOUNTS = "exportAccountUuids";

public static final String EXTRA_STARTUP = "startup";
public static final String ACTION_IMPORT_SETTINGS = "importSettings";

/*
* Must be serializable hence implementation class used for declaration.
*/
Expand Down Expand Up @@ -147,10 +162,10 @@ public class Accounts extends K9ListActivity implements OnItemClickListener {
* @see #onRetainNonConfigurationInstance()
*/
private NonConfigurationInstance mNonConfigurationInstance;
private boolean exportIncludeGlobals;
private Account exportAccount;


private static final int ACTIVITY_REQUEST_PICK_SETTINGS_FILE = 1;
private static final int ACTIVITY_REQUEST_SAVE_SETTINGS_FILE = 2;

class AccountsHandler extends Handler {
private void setViewTitle() {
Expand Down Expand Up @@ -209,7 +224,8 @@ public void run() {
stats.size = newSize;
}
String toastText = getString(R.string.account_size_changed, account.getDescription(),
SizeFormatter.formatSize(getApplication(), oldSize), SizeFormatter.formatSize(getApplication(), newSize));
SizeFormatter.formatSize(getApplication(), oldSize),
SizeFormatter.formatSize(getApplication(), newSize));

Toast toast = Toast.makeText(getApplication(), toastText, Toast.LENGTH_LONG);
toast.show();
Expand Down Expand Up @@ -330,17 +346,6 @@ public void synchronizeMailboxFailed(Account account, String folder,

};

private static String ACCOUNT_STATS = "accountStats";
private static String STATE_UNREAD_COUNT = "unreadCount";
private static String SELECTED_CONTEXT_ACCOUNT = "selectedContextAccount";
private static final String STATE_EXPORT_GLOBAL_SETTINGS = "exportGlobalSettings";
private static final String STATE_EXPORT_ACCOUNTS = "exportAccountUuids";


public static final String EXTRA_STARTUP = "startup";

public static final String ACTION_IMPORT_SETTINGS = "importSettings";


public static void listAccounts(Context context) {
Intent intent = new Intent(context, Accounts.class);
Expand Down Expand Up @@ -1918,7 +1923,27 @@ public void onClick(View v) {

}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] result){
super.onRequestPermissionsResult(requestCode, permissions, result);

if(requestCode == EXPORT_SAVE_PERMISSION && result[0] == PackageManager.PERMISSION_GRANTED){
performExport(exportIncludeGlobals, exportAccount);
}
}

public void onExport(final boolean includeGlobals, final Account account) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && this.checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
exportIncludeGlobals = includeGlobals;
exportAccount = account;
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, EXPORT_SAVE_PERMISSION);
} else {
performExport(includeGlobals, account);
}
}

private void performExport(final boolean includeGlobals, final Account account) {
// TODO, prompt to allow a user to choose which accounts to export
ArrayList<String> accountUuids = null;
if (account != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.io.OutputStream;
import java.util.List;

import android.Manifest;
import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
import android.content.Context;
Expand All @@ -16,6 +17,7 @@
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.WorkerThread;
import timber.log.Timber;
Expand Down Expand Up @@ -119,7 +121,7 @@ private void viewLocalAttachment() {
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);
String message = context.getString(R.string.message_view_status_external_storage_not_mounted);
displayMessageToUser(message);
return;
}
Expand All @@ -142,6 +144,11 @@ private void saveLocalAttachmentTo(File directory) {
}

private File saveAttachmentWithUniqueFileName(File directory) throws IOException {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
messageViewFragment.getActivity().checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
return null;
}
String filename = FileHelper.sanitizeFilename(attachment.displayName);
File file = FileHelper.createUniqueFile(directory, filename);

Expand All @@ -154,6 +161,7 @@ private File saveAttachmentWithUniqueFileName(File directory) throws IOException

private void writeAttachmentToStorage(File file) throws IOException {
InputStream in = context.getContentResolver().openInputStream(attachment.internalUri);

try {
OutputStream out = new FileOutputStream(file);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Collections;
import java.util.Locale;

import android.Manifest;
import android.app.Activity;
import android.app.DialogFragment;
import android.app.DownloadManager;
Expand All @@ -13,7 +14,9 @@
import android.content.Intent;
import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
Expand Down Expand Up @@ -65,6 +68,8 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF

public static final int REQUEST_MASK_LOADER_HELPER = (1 << 8);
public static final int REQUEST_MASK_CRYPTO_PRESENTER = (1 << 9);
private static final int ATTACHMENT_SAVE_PERMISSION_DEFAULT = 400;
private static final int ATTACHMENT_SAVE_PERMISSION_CHOOSE = 401;

public static final int PROGRESS_THRESHOLD_MILLIS = 500 * 1000;

Expand Down Expand Up @@ -826,27 +831,55 @@ public void onViewAttachment(AttachmentViewInfo attachment) {
getAttachmentController(attachment).viewAttachment();
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] result){
super.onRequestPermissionsResult(requestCode, permissions, result);
if(requestCode == ATTACHMENT_SAVE_PERMISSION_DEFAULT && result[0] == PackageManager.PERMISSION_GRANTED){
saveAttachment(currentAttachmentViewInfo);
} else if (requestCode == ATTACHMENT_SAVE_PERMISSION_CHOOSE && result[0] == PackageManager.PERMISSION_GRANTED){
saveAttachmentChoose(currentAttachmentViewInfo);
}
}

@Override
public void onSaveAttachment(AttachmentViewInfo attachment) {
currentAttachmentViewInfo = attachment;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getActivity().checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, ATTACHMENT_SAVE_PERMISSION_DEFAULT);
} else {
saveAttachment(attachment);
}
}

private void saveAttachment(AttachmentViewInfo attachment) {
getAttachmentController(attachment).saveAttachment();
}

@Override
public void onSaveAttachmentToUserProvidedDirectory(final AttachmentViewInfo attachment) {
currentAttachmentViewInfo = attachment;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && getActivity().checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, ATTACHMENT_SAVE_PERMISSION_CHOOSE);
} else {
saveAttachmentChoose(attachment);
}
}

private void saveAttachmentChoose(final AttachmentViewInfo attachment) {
FileBrowserHelper.getInstance().showFileBrowserActivity(MessageViewFragment.this, null,
ACTIVITY_CHOOSE_DIRECTORY, new FileBrowserFailOverCallback() {
@Override
public void onPathEntered(String path) {
getAttachmentController(attachment).saveAttachmentTo(path);
}
ACTIVITY_CHOOSE_DIRECTORY, new FileBrowserFailOverCallback() {
@Override
public void onPathEntered(String path) {
getAttachmentController(attachment).saveAttachmentTo(path);
}

@Override
public void onCancel() {
// Do nothing
}
});
@Override
public void onCancel() {
// Do nothing
}
});
}

private AttachmentController getAttachmentController(AttachmentViewInfo attachment) {
Expand Down
2 changes: 2 additions & 0 deletions k9mail/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ Please submit bug reports, contribute new features and ask questions at
<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_error">An error occurred while saving the attachment</string>
<string name="message_view_status_external_storage_not_mounted">Unable to access device storage.</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>
Expand Down