diff --git a/k9mail/src/main/java/foundation/e/mail/controller/MessagingController.java b/k9mail/src/main/java/foundation/e/mail/controller/MessagingController.java index 9c1210f4a70bd8fba466015f016754f4a773183d..f79d8071012c57d30c5562a3e5f6549d868e1e54 100644 --- a/k9mail/src/main/java/foundation/e/mail/controller/MessagingController.java +++ b/k9mail/src/main/java/foundation/e/mail/controller/MessagingController.java @@ -34,6 +34,7 @@ import java.util.concurrent.atomic.AtomicInteger; import android.accounts.AccountManager; import android.annotation.SuppressLint; +import android.app.NotificationManager; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -185,7 +186,7 @@ public class MessagingController { @VisibleForTesting MessagingController(Context context, NotificationController notificationController, - Contacts contacts, TransportProvider transportProvider) { + Contacts contacts, TransportProvider transportProvider) { this.context = context; this.notificationController = notificationController; this.contacts = contacts; @@ -259,7 +260,7 @@ public class MessagingController { } private void putCommand(BlockingQueue queue, String description, MessagingListener listener, - Runnable runnable, boolean isForeground) { + Runnable runnable, boolean isForeground) { int retries = 10; Exception e = null; while (retries-- > 0) { @@ -330,7 +331,7 @@ public class MessagingController { } private void setFlagInCache(final Account account, final List messageIds, - final Flag flag, final boolean newState) { + final Flag flag, final boolean newState) { EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(), context); String columnName = LocalStore.getColumnNameForFlag(flag); @@ -339,7 +340,7 @@ public class MessagingController { } private void removeFlagFromCache(final Account account, final List messageIds, - final Flag flag) { + final Flag flag) { EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(), context); String columnName = LocalStore.getColumnNameForFlag(flag); @@ -347,7 +348,7 @@ public class MessagingController { } private void setFlagForThreadsInCache(final Account account, final List threadRootIds, - final Flag flag, final boolean newState) { + final Flag flag, final boolean newState) { EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(), context); String columnName = LocalStore.getColumnNameForFlag(flag); @@ -356,7 +357,7 @@ public class MessagingController { } private void removeFlagForThreadsFromCache(final Account account, final List messageIds, - final Flag flag) { + final Flag flag) { EmailProviderCache cache = EmailProviderCache.getCache(account.getUuid(), context); String columnName = LocalStore.getColumnNameForFlag(flag); @@ -390,7 +391,7 @@ public class MessagingController { * TODO this needs to cache the remote folder list */ public void listFoldersSynchronous(final Account account, final boolean refreshRemote, - final MessagingListener listener) { + final MessagingListener listener) { for (MessagingListener l : getListeners(listener)) { l.listFoldersStarted(account); } @@ -576,7 +577,7 @@ public class MessagingController { } public Future searchRemoteMessages(final String acctUuid, final String folderName, final String query, - final Set requiredFlags, final Set forbiddenFlags, final MessagingListener listener) { + final Set requiredFlags, final Set forbiddenFlags, final MessagingListener listener) { Timber.i("searchRemoteMessages (acct = %s, folderName = %s, query = %s)", acctUuid, folderName, query); return threadPool.submit(new Runnable() { @@ -589,7 +590,7 @@ public class MessagingController { @VisibleForTesting void searchRemoteMessagesSynchronous(final String acctUuid, final String folderName, final String query, - final Set requiredFlags, final Set forbiddenFlags, final MessagingListener listener) { + final Set requiredFlags, final Set forbiddenFlags, final MessagingListener listener) { final Account acct = Preferences.getPreferences(context).getAccount(acctUuid); if (listener != null) { @@ -654,7 +655,7 @@ public class MessagingController { } public void loadSearchResults(final Account account, final String folderName, final List messages, - final MessagingListener listener) { + final MessagingListener listener) { threadPool.execute(new Runnable() { @Override public void run() { @@ -688,7 +689,7 @@ public class MessagingController { } private void loadSearchResultsSynchronous(List messages, LocalFolder localFolder, Folder remoteFolder, - MessagingListener listener) throws MessagingException { + MessagingListener listener) throws MessagingException { final FetchProfile header = new FetchProfile(); header.add(FetchProfile.Item.FLAGS); header.add(FetchProfile.Item.ENVELOPE); @@ -728,7 +729,7 @@ public class MessagingController { * Start background synchronization of the specified folder. */ public void synchronizeMailbox(final Account account, final String folder, final MessagingListener listener, - final Folder providedRemoteFolder) { + final Folder providedRemoteFolder) { putBackground("synchronizeMailbox", listener, new Runnable() { @Override public void run() { @@ -745,7 +746,7 @@ public class MessagingController { */ @VisibleForTesting void synchronizeMailboxSynchronous(final Account account, final String folder, final MessagingListener listener, - Folder providedRemoteFolder) { + Folder providedRemoteFolder) { Folder remoteFolder = null; LocalFolder tLocalFolder = null; @@ -1026,7 +1027,7 @@ public class MessagingController { * to treat Pop3 and Imap the same in this code. */ private boolean verifyOrCreateRemoteSpecialFolder(Account account, String folder, Folder remoteFolder, - MessagingListener listener) throws MessagingException { + MessagingListener listener) throws MessagingException { if (folder.equals(account.getTrashFolderName()) || folder.equals(account.getSentFolderName()) || folder.equals(account.getDraftsFolderName())) { @@ -1048,26 +1049,18 @@ public class MessagingController { * Fetches the messages described by inputMessages from the remote store and writes them to * local storage. * - * @param account - * The account the remote store belongs to. - * @param remoteFolder - * The remote folder to download messages from. - * @param localFolder - * The {@link LocalFolder} instance corresponding to the remote folder. - * @param inputMessages - * A list of messages objects that store the UIDs of which messages to download. - * @param flagSyncOnly - * Only flags will be fetched from the remote store if this is {@code true}. - * @param purgeToVisibleLimit - * If true, local messages will be purged down to the limit of visible messages. - * + * @param account The account the remote store belongs to. + * @param remoteFolder The remote folder to download messages from. + * @param localFolder The {@link LocalFolder} instance corresponding to the remote folder. + * @param inputMessages A list of messages objects that store the UIDs of which messages to download. + * @param flagSyncOnly Only flags will be fetched from the remote store if this is {@code true}. + * @param purgeToVisibleLimit If true, local messages will be purged down to the limit of visible messages. * @return The number of downloaded messages that are not flagged as {@link Flag#SEEN}. - * * @throws MessagingException */ private int downloadMessages(final Account account, final Folder remoteFolder, - final LocalFolder localFolder, List inputMessages, - boolean flagSyncOnly, boolean purgeToVisibleLimit) throws MessagingException { + final LocalFolder localFolder, List inputMessages, + boolean flagSyncOnly, boolean purgeToVisibleLimit) throws MessagingException { final Date earliestDate = account.getEarliestPollDate(); Date downloadStarted = new Date(); // now @@ -1198,12 +1191,12 @@ public class MessagingController { } private void evaluateMessageForDownload(final Message message, final String folder, - final LocalFolder localFolder, - final Folder remoteFolder, - final Account account, - final List unsyncedMessages, - final List syncFlagMessages, - boolean flagSyncOnly) throws MessagingException { + final LocalFolder localFolder, + final Folder remoteFolder, + final Account account, + final List unsyncedMessages, + final List syncFlagMessages, + boolean flagSyncOnly) throws MessagingException { if (message.isSet(Flag.DELETED)) { Timber.v("Message with uid %s is marked as deleted", message.getUid()); @@ -1257,12 +1250,12 @@ public class MessagingController { } private void fetchUnsyncedMessages(final Account account, final Folder remoteFolder, - List unsyncedMessages, - final List smallMessages, - final List largeMessages, - final AtomicInteger progress, - final int todo, - FetchProfile fp) throws MessagingException { + List unsyncedMessages, + final List smallMessages, + final List largeMessages, + final AtomicInteger progress, + final int todo, + FetchProfile fp) throws MessagingException { final String folder = remoteFolder.getName(); final Date earliestDate = account.getEarliestPollDate(); @@ -1313,13 +1306,13 @@ public class MessagingController { } private void downloadSmallMessages(final Account account, final Folder remoteFolder, - final LocalFolder localFolder, - List smallMessages, - final AtomicInteger progress, - final int unreadBeforeStart, - final AtomicInteger newMessages, - final int todo, - FetchProfile fp) throws MessagingException { + final LocalFolder localFolder, + List smallMessages, + final AtomicInteger progress, + final int unreadBeforeStart, + final AtomicInteger newMessages, + final int todo, + FetchProfile fp) throws MessagingException { final String folder = remoteFolder.getName(); Timber.d("SYNC: Fetching %d small messages for folder %s", smallMessages.size(), folder); @@ -1379,13 +1372,13 @@ public class MessagingController { } private void downloadLargeMessages(final Account account, final Folder remoteFolder, - final LocalFolder localFolder, - List largeMessages, - final AtomicInteger progress, - final int unreadBeforeStart, - final AtomicInteger newMessages, - final int todo, - FetchProfile fp) throws MessagingException { + final LocalFolder localFolder, + List largeMessages, + final AtomicInteger progress, + final int unreadBeforeStart, + final AtomicInteger newMessages, + final int todo, + FetchProfile fp) throws MessagingException { final String folder = remoteFolder.getName(); Timber.d("SYNC: Fetching large messages for folder %s", folder); @@ -1465,11 +1458,11 @@ public class MessagingController { */ FetchProfile fp = new FetchProfile(); fp.add(FetchProfile.Item.BODY_SANE); - /* - * TODO a good optimization here would be to make sure that all Stores set - * the proper size after this fetch and compare the before and after size. If - * they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED - */ + /* + * TODO a good optimization here would be to make sure that all Stores set + * the proper size after this fetch and compare the before and after size. If + * they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED + */ remoteFolder.fetch(Collections.singletonList(message), fp, null); @@ -1481,15 +1474,15 @@ public class MessagingController { // Certain (POP3) servers give you the whole message even when you ask for only the first x Kb if (!message.isSet(Flag.X_DOWNLOADED_FULL)) { - /* - * Mark the message as fully downloaded if the message size is smaller than - * the account's autodownload size limit, otherwise mark as only a partial - * download. This will prevent the system from downloading the same message - * twice. - * - * If there is no limit on autodownload size, that's the same as the message - * being smaller than the max size - */ + /* + * Mark the message as fully downloaded if the message size is smaller than + * the account's autodownload size limit, otherwise mark as only a partial + * download. This will prevent the system from downloading the same message + * twice. + * + * If there is no limit on autodownload size, that's the same as the message + * being smaller than the max size + */ if (account.getMaximumAutoDownloadMessageSize() == 0 || message.getSize() < account.getMaximumAutoDownloadMessageSize()) { localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true); @@ -1503,10 +1496,10 @@ public class MessagingController { } private void refreshLocalMessageFlags(final Account account, final Folder remoteFolder, - final LocalFolder localFolder, - List syncFlagMessages, - final AtomicInteger progress, - final int todo + final LocalFolder localFolder, + List syncFlagMessages, + final AtomicInteger progress, + final int todo ) throws MessagingException { final String folder = remoteFolder.getName(); @@ -1734,7 +1727,7 @@ public class MessagingController { String rUid = remoteFolder.getUidFromMessageId(localMessage); if (rUid != null) { Timber.w("Local message has flag %s already set, and there is a remote message with uid %s, " + - "assuming message was already copied and aborting this copy", + "assuming message was already copied and aborting this copy", X_REMOTE_COPY_STARTED, rUid); String oldUid = localMessage.getUid(); @@ -1827,13 +1820,13 @@ public class MessagingController { } private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, boolean isCopy, - List uids) { + List uids) { PendingCommand command = PendingMoveOrCopy.create(srcFolder, destFolder, isCopy, uids); queuePendingCommand(account, command); } private void queueMoveOrCopy(Account account, String srcFolder, String destFolder, - boolean isCopy, List uids, Map uidMap) { + boolean isCopy, List uids, Map uidMap) { if (uidMap == null || uidMap.isEmpty()) { queueMoveOrCopy(account, srcFolder, destFolder, isCopy, uids); } else { @@ -1855,7 +1848,7 @@ public class MessagingController { @VisibleForTesting void processPendingMoveOrCopy(Account account, String srcFolder, String destFolder, Collection uids, - boolean isCopy, Map newUidMap) throws MessagingException { + boolean isCopy, Map newUidMap) throws MessagingException { Folder remoteSrcFolder = null; Folder remoteDestFolder = null; LocalFolder localDestFolder; @@ -1951,7 +1944,7 @@ public class MessagingController { } private void queueSetFlag(final Account account, final String folderName, - final boolean newState, final Flag flag, final List uids) { + final boolean newState, final Flag flag, final List uids) { putBackground("queueSetFlag " + account.getDescription() + ":" + folderName, null, new Runnable() { @Override public void run() { @@ -2081,7 +2074,7 @@ public class MessagingController { } public void setFlag(final Account account, final List messageIds, final Flag flag, - final boolean newState) { + final boolean newState) { setFlagInCache(account, messageIds, flag, newState); @@ -2094,7 +2087,7 @@ public class MessagingController { } public void setFlagForThreads(final Account account, final List threadRootIds, - final Flag flag, final boolean newState) { + final Flag flag, final boolean newState) { setFlagForThreadsInCache(account, threadRootIds, flag, newState); @@ -2107,7 +2100,7 @@ public class MessagingController { } private void setFlagSynchronous(final Account account, final List ids, - final Flag flag, final boolean newState, final boolean threadedList) { + final Flag flag, final boolean newState, final boolean threadedList) { LocalStore localStore; try { @@ -2170,19 +2163,14 @@ public class MessagingController { * The {@link Message} objects passed in are updated to reflect the new flag state. *

* - * @param account - * The account the folder containing the messages belongs to. - * @param folderName - * The name of the folder. - * @param messages - * The messages to change the flag for. - * @param flag - * The flag to change. - * @param newState - * {@code true}, if the flag should be set. {@code false} if it should be removed. + * @param account The account the folder containing the messages belongs to. + * @param folderName The name of the folder. + * @param messages The messages to change the flag for. + * @param flag The flag to change. + * @param newState {@code true}, if the flag should be set. {@code false} if it should be removed. */ public void setFlag(Account account, String folderName, List messages, Flag flag, - boolean newState) { + boolean newState) { // TODO: Put this into the background, but right now some callers depend on the message // objects being modified right after this method returns. Folder localFolder = null; @@ -2230,19 +2218,14 @@ public class MessagingController { /** * Set or remove a flag for a message referenced by message UID. * - * @param account - * The account the folder containing the message belongs to. - * @param folderName - * The name of the folder. - * @param uid - * The UID of the message to change the flag for. - * @param flag - * The flag to change. - * @param newState - * {@code true}, if the flag should be set. {@code false} if it should be removed. + * @param account The account the folder containing the message belongs to. + * @param folderName The name of the folder. + * @param uid The UID of the message to change the flag for. + * @param flag The flag to change. + * @param newState {@code true}, if the flag should be set. {@code false} if it should be removed. */ public void setFlag(Account account, String folderName, String uid, Flag flag, - boolean newState) { + boolean newState) { Folder localFolder = null; try { LocalStore localStore = account.getLocalStore(); @@ -2271,7 +2254,7 @@ public class MessagingController { } public void loadMessageRemotePartial(final Account account, final String folder, - final String uid, final MessagingListener listener) { + final String uid, final MessagingListener listener) { put("loadMessageRemotePartial", listener, new Runnable() { @Override public void run() { @@ -2282,7 +2265,7 @@ public class MessagingController { //TODO: Fix the callback mess. See GH-782 public void loadMessageRemote(final Account account, final String folder, - final String uid, final MessagingListener listener) { + final String uid, final MessagingListener listener) { put("loadMessageRemote", listener, new Runnable() { @Override public void run() { @@ -2292,7 +2275,7 @@ public class MessagingController { } private boolean loadMessageRemoteSynchronous(final Account account, final String folder, - final String uid, final MessagingListener listener, final boolean loadPartialFromSearch) { + final String uid, final MessagingListener listener, final boolean loadPartialFromSearch) { Folder remoteFolder = null; LocalFolder localFolder = null; try { @@ -2408,7 +2391,7 @@ public class MessagingController { } public void loadAttachment(final Account account, final LocalMessage message, final Part part, - final MessagingListener listener) { + final MessagingListener listener) { put("loadAttachment", listener, new Runnable() { @Override @@ -2462,8 +2445,8 @@ public class MessagingController { * attempt to send the message. */ public void sendMessage(final Account account, - final Message message, - MessagingListener listener) { + final Message message, + MessagingListener listener) { try { LocalStore localStore = account.getLocalStore(); LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderName()); @@ -2498,7 +2481,7 @@ public class MessagingController { * Attempt to send any messages that are sitting in the Outbox. */ public void sendPendingMessages(final Account account, - MessagingListener listener) { + MessagingListener listener) { putBackground("sendPendingMessages", listener, new Runnable() { @Override public void run() { @@ -2695,7 +2678,7 @@ public class MessagingController { } private void moveOrDeleteSentMessage(Account account, LocalStore localStore, - LocalFolder localFolder, LocalMessage message) throws MessagingException { + LocalFolder localFolder, LocalMessage message) throws MessagingException { if (!account.hasSentFolder()) { Timber.i("Account does not have a sent mail folder; deleting sent message"); message.setFlag(Flag.DELETED, true); @@ -2714,7 +2697,7 @@ public class MessagingController { } private void handleSendFailure(Account account, Store localStore, Folder localFolder, Message message, - Exception exception, boolean permanentFailure) throws MessagingException { + Exception exception, boolean permanentFailure) throws MessagingException { Timber.e(exception, "Failed to send message"); @@ -2742,7 +2725,7 @@ public class MessagingController { } public void getAccountStats(final Context context, final Account account, - final MessagingListener listener) { + final MessagingListener listener) { threadPool.execute(new Runnable() { @Override @@ -2759,7 +2742,7 @@ public class MessagingController { } public void getSearchAccountStats(final SearchAccount searchAccount, - final MessagingListener listener) { + final MessagingListener listener) { threadPool.execute(new Runnable() { @Override @@ -2770,7 +2753,7 @@ public class MessagingController { } public AccountStats getSearchAccountStatsSynchronous(final SearchAccount searchAccount, - final MessagingListener listener) { + final MessagingListener listener) { Preferences preferences = Preferences.getPreferences(context); LocalSearch search = searchAccount.getRelatedSearch(); @@ -2838,7 +2821,7 @@ public class MessagingController { } public void getFolderUnreadMessageCount(final Account account, final String folderName, - final MessagingListener l) { + final MessagingListener l) { Runnable unreadRunnable = new Runnable() { @Override public void run() { @@ -2891,7 +2874,7 @@ public class MessagingController { } public void moveMessages(final Account srcAccount, final String srcFolder, - List messageReferences, final String destFolder) { + List messageReferences, final String destFolder) { actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() { @Override public void act(final Account account, LocalFolder messageFolder, final List messages) { @@ -2908,7 +2891,7 @@ public class MessagingController { } public void moveMessagesInThread(Account srcAccount, final String srcFolder, - final List messageReferences, final String destFolder) { + final List messageReferences, final String destFolder) { actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() { @Override public void act(final Account account, LocalFolder messageFolder, final List messages) { @@ -2930,12 +2913,12 @@ public class MessagingController { } public void moveMessage(final Account account, final String srcFolder, final MessageReference message, - final String destFolder) { + final String destFolder) { moveMessages(account, srcFolder, Collections.singletonList(message), destFolder); } public void copyMessages(final Account srcAccount, final String srcFolder, - final List messageReferences, final String destFolder) { + final List messageReferences, final String destFolder) { actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() { @Override public void act(final Account account, LocalFolder messageFolder, final List messages) { @@ -2950,7 +2933,7 @@ public class MessagingController { } public void copyMessagesInThread(Account srcAccount, final String srcFolder, - final List messageReferences, final String destFolder) { + final List messageReferences, final String destFolder) { actOnMessageGroup(srcAccount, srcFolder, messageReferences, new MessageActor() { @Override public void act(final Account account, LocalFolder messageFolder, final List messages) { @@ -2971,13 +2954,13 @@ public class MessagingController { } public void copyMessage(final Account account, final String srcFolder, final MessageReference message, - final String destFolder) { + final String destFolder) { copyMessages(account, srcFolder, Collections.singletonList(message), destFolder); } private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder, - final List inMessages, final String destFolder, final boolean isCopy) { + final List inMessages, final String destFolder, final boolean isCopy) { try { LocalStore localStore = account.getLocalStore(); @@ -3101,7 +3084,7 @@ public class MessagingController { actOnMessagesGroupedByAccountAndFolder(messages, new MessageActor() { @Override public void act(final Account account, final LocalFolder messageFolder, - final List accountMessages) { + final List accountMessages) { suppressMessages(account, accountMessages); putBackground("deleteThreads", null, new Runnable() { @@ -3153,7 +3136,7 @@ public class MessagingController { @Override public void act(final Account account, final LocalFolder messageFolder, - final List accountMessages) { + final List accountMessages) { suppressMessages(account, accountMessages); putBackground("deleteMessages", null, new Runnable() { @@ -3177,7 +3160,7 @@ public class MessagingController { @Override public void act(final Account account, final LocalFolder messageFolder, - final List accountMessages) { + final List accountMessages) { putBackground("debugClearLocalMessages", null, new Runnable() { @Override @@ -3197,8 +3180,8 @@ public class MessagingController { } private void deleteMessagesSynchronous(final Account account, final String folder, - final List messages, - MessagingListener listener) { + final List messages, + MessagingListener listener) { LocalFolder localFolder = null; LocalFolder localTrashFolder = null; try { @@ -3272,7 +3255,7 @@ public class MessagingController { queueSetFlag(account, folder, true, Flag.DELETED, syncedMessageUids); } else { queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, - syncedMessageUids, uidMap); + syncedMessageUids, uidMap); } processPendingCommands(account); } else if (account.getDeletePolicy() == DeletePolicy.MARK_AS_READ) { @@ -3399,14 +3382,10 @@ public class MessagingController { *

*

Note: Currently this is only the case for POP3 accounts.

* - * @param account - * The account to check. - * + * @param account The account to check. * @return {@code true} if the account only has a local Trash folder that is not synchronized * with a folder on the server. {@code false} otherwise. - * - * @throws MessagingException - * In case of an error. + * @throws MessagingException In case of an error. */ private boolean isTrashLocalOnly(Account account) throws MessagingException { // TODO: Get rid of the tight coupling once we properly support local folders @@ -3469,8 +3448,8 @@ public class MessagingController { private boolean hasPasswordUpdate(Account account, String deviceAccountEmailId, String deviceAccountPassword) { - try { - String[] emailParts = EmailHelper.splitEmail(deviceAccountEmailId); + try { + String[] emailParts = EmailHelper.splitEmail(deviceAccountEmailId); AccountSetupPresenter.Provider provider = findProviderForDomain(context, emailParts[1]); if (provider != null) { @@ -3482,15 +3461,14 @@ public class MessagingController { deviceAccountTransportUri.equals(account.getTransportUri())) { return false; } - } - } - catch (Exception e) { + } + } catch (Exception e) { Timber.e(e, "Error while trying to initialise account configuration."); - } + } return true; } - private static AccountSetupPresenter.Provider findProviderForDomain(Context context, + private static AccountSetupPresenter.Provider findProviderForDomain(Context context, String domain) { try { XmlResourceParser xml = context.getResources().getXml(foundation.e.mail.R.xml.providers); @@ -3594,7 +3572,7 @@ public class MessagingController { return new ArrayList<>(Arrays.asList(incomingUri.toString(), outgoingUri.toString())); } - private boolean isAccountSignedInOnDevice(AccountManager accountManager, Account account){ + private boolean isAccountSignedInOnDevice(AccountManager accountManager, Account account) { try { android.accounts.Account[] eeloAccounts = getEeloAccountsOnDevice(accountManager); android.accounts.Account[] googleAccounts = getGoogleAccountsOnDevice(accountManager); @@ -3604,7 +3582,7 @@ public class MessagingController { for (android.accounts.Account eeloAccount : eeloAccounts) { String emailId = accountManager.getUserData(eeloAccount, ACCOUNT_EMAIL_ADDRESS_KEY); - if (account.getEmail().equals(emailId) && !hasPasswordUpdate(account, + if (account.getEmail().equals(emailId) && !hasPasswordUpdate(account, emailId, accountManager.getPassword(eeloAccount))) { accountIsSignedInOnDevice = true; break; @@ -3623,8 +3601,7 @@ public class MessagingController { return true; } } - } - catch (SecurityException e) { + } catch (SecurityException e) { e.printStackTrace(); } return false; @@ -3644,8 +3621,7 @@ public class MessagingController { MAIL_CONTENT_AUTHORITY)) { account.setFolderPushMode(Account.FolderMode.FIRST_CLASS); return true; - } - else { + } else { account.setFolderPushMode(Account.FolderMode.NONE); return false; } @@ -3659,16 +3635,14 @@ public class MessagingController { MAIL_CONTENT_AUTHORITY)) { account.setFolderPushMode(Account.FolderMode.FIRST_CLASS); return true; - } - else { + } else { account.setFolderPushMode(Account.FolderMode.NONE); return false; } } } } - } - catch (SecurityException e) { + } catch (SecurityException e) { e.printStackTrace(); } return false; @@ -3679,9 +3653,9 @@ public class MessagingController { * are checked. */ public void checkMail(final Context context, final Account account, - final boolean ignoreLastCheckedTime, - final boolean useManualWakeLock, - final MessagingListener listener) { + final boolean ignoreLastCheckedTime, + final boolean useManualWakeLock, + final MessagingListener listener) { TracingWakeLock twakeLock = null; if (useManualWakeLock) { @@ -3714,13 +3688,12 @@ public class MessagingController { } for (final Account account : accounts) { - if (account.isDeviceAccount()) { + if (account.isDeviceAccount()) { if (isAccountSignedInOnDevice(AccountManager.get(context), account) && isSyncEnabled(AccountManager.get(context), account)) { checkMailForAccount(context, account, ignoreLastCheckedTime, listener); } - } - else { + } else { checkMailForAccount(context, account, ignoreLastCheckedTime, listener); } } @@ -3750,8 +3723,8 @@ public class MessagingController { private void checkMailForAccount(final Context context, final Account account, - final boolean ignoreLastCheckedTime, - final MessagingListener listener) { + final boolean ignoreLastCheckedTime, + final MessagingListener listener) { if (!account.isAvailable(context)) { Timber.i("Skipping synchronizing unavailable account %s", account.getDescription()); return; @@ -3859,7 +3832,7 @@ public class MessagingController { if (!ignoreLastCheckedTime && tLocalFolder.getLastChecked() > (System.currentTimeMillis() - accountInterval)) { Timber.v("Not running Command for folder %s, previously synced @ %tc which would " + - "be too recent for the account period", + "be too recent for the account period", folder.getName(), folder.getLastChecked()); return; } @@ -4057,11 +4030,8 @@ public class MessagingController { /** * Save a draft message. * - * @param account - * Account we are saving for. - * @param message - * Message to save. - * + * @param account Account we are saving for. + * @param message Message to save. * @return Message representing the entry in the local store. */ public Message saveDraft(final Account account, final Message message, long existingDraftId, boolean saveRemotely) { @@ -4262,7 +4232,7 @@ public class MessagingController { } public void messagesArrived(final Account account, final Folder remoteFolder, final List messages, - final boolean flagSyncOnly) { + final boolean flagSyncOnly) { Timber.i("Got new pushed email messages for account %s, folder %s", account.getDescription(), remoteFolder.getName()); diff --git a/k9mail/src/main/java/foundation/e/mail/notification/AuthenticationErrorNotifications.java b/k9mail/src/main/java/foundation/e/mail/notification/AuthenticationErrorNotifications.java index ca4a5975b88b4b43efe5e6ba4bf0691410db6006..d1cdcdd6e9e99685181e2f196d02c73da66442f0 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/AuthenticationErrorNotifications.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/AuthenticationErrorNotifications.java @@ -32,7 +32,7 @@ class AuthenticationErrorNotifications { String title = context.getString(R.string.notification_authentication_error_title); String text = context.getString(R.string.notification_authentication_error_text, account.getDescription()); - NotificationCompat.Builder builder = controller.createNotificationBuilder() + NotificationCompat.Builder builder = controller.createNotificationBuilder(account) .setSmallIcon(R.drawable.notification_icon_warning) .setWhen(System.currentTimeMillis()) .setAutoCancel(true) diff --git a/k9mail/src/main/java/foundation/e/mail/notification/BaseNotifications.java b/k9mail/src/main/java/foundation/e/mail/notification/BaseNotifications.java index c3cb6f40f27b64e3059ad74f7a3d7c685ddf40ac..15e7d0713e79d0a23a34a90872aa77b5c2411432 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/BaseNotifications.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/BaseNotifications.java @@ -1,8 +1,14 @@ package foundation.e.mail.notification; +import android.app.NotificationChannel; +import android.app.NotificationChannelGroup; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.support.annotation.RequiresApi; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat.BigTextStyle; import android.support.v4.app.NotificationCompat.Builder; @@ -12,25 +18,38 @@ import foundation.e.mail.K9; import foundation.e.mail.K9.NotificationQuickDelete; import foundation.e.mail.R; +import static foundation.e.mail.notification.NotificationController.channelDescription; +import static foundation.e.mail.notification.NotificationController.channelId; +import static foundation.e.mail.notification.NotificationController.channelName; + abstract class BaseNotifications { protected final Context context; protected final NotificationController controller; protected final NotificationActionCreator actionCreator; - + NotificationManager mNotificationManager; protected BaseNotifications(NotificationController controller, NotificationActionCreator actionCreator) { this.context = controller.getContext(); this.controller = controller; this.actionCreator = actionCreator; + mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } protected NotificationCompat.Builder createBigTextStyleNotification(Account account, NotificationHolder holder, - int notificationId) { + int notificationId) { String accountName = controller.getAccountName(account); NotificationContent content = holder.content; String groupKey = NotificationGroupKeys.getGroupKey(account); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + mNotificationManager.createNotificationChannel(mailNotificationChannel(account)); + mNotificationManager.createNotificationChannelGroup( + new NotificationChannelGroup(account.getUuid(), account.getName()) + ); + } + NotificationCompat.Builder builder = createAndInitializeNotificationBuilder(account) .setTicker(content.summary) .setGroup(groupKey) @@ -51,7 +70,7 @@ abstract class BaseNotifications { } protected NotificationCompat.Builder createAndInitializeNotificationBuilder(Account account) { - return controller.createNotificationBuilder() + return controller.createNotificationBuilder(account) .setSmallIcon(getNewMailNotificationIcon()) .setColor(account.getChipColor()) .setWhen(System.currentTimeMillis()) @@ -71,4 +90,17 @@ abstract class BaseNotifications { private int getNewMailNotificationIcon() { return R.drawable.notification_icon_new_mail; } + + + @RequiresApi(api = Build.VERSION_CODES.O) + private NotificationChannel mailNotificationChannel(Account account) { + NotificationChannel notificationChannel = new + NotificationChannel(channelId + account.getUuid(), channelName, NotificationManager.IMPORTANCE_DEFAULT); + notificationChannel.enableLights(true); + notificationChannel.setDescription(channelDescription); + notificationChannel.setLightColor(Color.RED); + notificationChannel.enableVibration(true); + return notificationChannel; + } + } diff --git a/k9mail/src/main/java/foundation/e/mail/notification/CertificateErrorNotifications.java b/k9mail/src/main/java/foundation/e/mail/notification/CertificateErrorNotifications.java index 4690c1501887b9ada2ed6b39724c434801b14f07..f843d0bfe3ed73d7397f3e9fec12868f412d0213 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/CertificateErrorNotifications.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/CertificateErrorNotifications.java @@ -31,7 +31,7 @@ class CertificateErrorNotifications { String title = context.getString(R.string.notification_certificate_error_title, account.getDescription()); String text = context.getString(R.string.notification_certificate_error_text); - NotificationCompat.Builder builder = controller.createNotificationBuilder() + NotificationCompat.Builder builder = controller.createNotificationBuilder(account) .setSmallIcon(getCertificateErrorNotificationIcon()) .setWhen(System.currentTimeMillis()) .setAutoCancel(true) diff --git a/k9mail/src/main/java/foundation/e/mail/notification/LockScreenNotification.java b/k9mail/src/main/java/foundation/e/mail/notification/LockScreenNotification.java index affd568d66f99a848ab85fad88ebcb2c464def8b..cb05fdd67522b04deada52e0c8b1477a354c1cba 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/LockScreenNotification.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/LockScreenNotification.java @@ -95,7 +95,7 @@ class LockScreenNotification { String title = context.getResources().getQuantityString(R.plurals.notification_new_messages_title, newMessages, newMessages); - return controller.createNotificationBuilder() + return controller.createNotificationBuilder(account) .setSmallIcon(R.drawable.notification_icon_new_mail) .setColor(account.getChipColor()) .setNumber(unreadCount) diff --git a/k9mail/src/main/java/foundation/e/mail/notification/NotificationController.java b/k9mail/src/main/java/foundation/e/mail/notification/NotificationController.java index 82ec9062214c5573ea9d71fb746ff4c7b738cebf..50e762f84761891d58619afa84479dafa3fcddc3 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/NotificationController.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/NotificationController.java @@ -23,7 +23,10 @@ public class NotificationController { static final int NOTIFICATION_LED_BLINK_SLOW = 0; static final int NOTIFICATION_LED_BLINK_FAST = 1; static final int NOTIFICATION_LED_FAILURE_COLOR = 0xffff0000; - + //Notification channel + static final String channelId = "mail_channel_id_"; + static final String channelName = "mail_channel"; + static final String channelDescription = "mail_channel_description"; private final Context context; private final NotificationManagerCompat notificationManager; @@ -33,7 +36,6 @@ public class NotificationController { private final SendFailedNotifications sendFailedNotifications; private final NewMailNotifications newMailNotifications; - public static NotificationController newInstance(Context context) { Context appContext = context.getApplicationContext(); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(appContext); @@ -114,7 +116,7 @@ public class NotificationController { } void configureNotification(NotificationCompat.Builder builder, String ringtone, long[] vibrationPattern, - Integer ledColor, int ledSpeed, boolean ringAndVibrate) { + Integer ledColor, int ledSpeed, boolean ringAndVibrate) { if (K9.isQuietTime()) { return; @@ -137,6 +139,7 @@ public class NotificationController { ledOnMS = NOTIFICATION_LED_ON_TIME; ledOffMS = NOTIFICATION_LED_OFF_TIME; } else { + ledOnMS = NOTIFICATION_LED_FAST_ON_TIME; ledOffMS = NOTIFICATION_LED_FAST_OFF_TIME; } @@ -158,7 +161,8 @@ public class NotificationController { return notificationManager; } - NotificationCompat.Builder createNotificationBuilder() { - return new NotificationCompat.Builder(context); + NotificationCompat.Builder createNotificationBuilder(Account account) { + return new NotificationCompat.Builder(context, channelId + account.getUuid()); } + } diff --git a/k9mail/src/main/java/foundation/e/mail/notification/SendFailedNotifications.java b/k9mail/src/main/java/foundation/e/mail/notification/SendFailedNotifications.java index 0063ea1ad7b0650c121bddcf4c8bda14422ae630..259a73a93a7300ec9937ff43e221310d852a088f 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/SendFailedNotifications.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/SendFailedNotifications.java @@ -33,7 +33,7 @@ class SendFailedNotifications { PendingIntent folderListPendingIntent = actionBuilder.createViewFolderListPendingIntent( account, notificationId); - NotificationCompat.Builder builder = controller.createNotificationBuilder() + NotificationCompat.Builder builder = controller.createNotificationBuilder(account) .setSmallIcon(getSendFailedNotificationIcon()) .setWhen(System.currentTimeMillis()) .setAutoCancel(true) diff --git a/k9mail/src/main/java/foundation/e/mail/notification/SyncNotifications.java b/k9mail/src/main/java/foundation/e/mail/notification/SyncNotifications.java index 652b97417b94cd959a67f01b55ed5a3881648397..d7410e3fb2dd7031d67100438a611fb78c29ee5d 100644 --- a/k9mail/src/main/java/foundation/e/mail/notification/SyncNotifications.java +++ b/k9mail/src/main/java/foundation/e/mail/notification/SyncNotifications.java @@ -37,7 +37,7 @@ class SyncNotifications { PendingIntent showMessageListPendingIntent = actionBuilder.createViewFolderPendingIntent( account, outboxFolderName, notificationId); - NotificationCompat.Builder builder = controller.createNotificationBuilder() + NotificationCompat.Builder builder = controller.createNotificationBuilder(account) .setSmallIcon(R.drawable.ic_notify_check_mail) .setWhen(System.currentTimeMillis()) .setOngoing(true) @@ -75,7 +75,7 @@ class SyncNotifications { PendingIntent showMessageListPendingIntent = actionBuilder.createViewFolderPendingIntent( account, folderName, notificationId); - NotificationCompat.Builder builder = controller.createNotificationBuilder() + NotificationCompat.Builder builder = controller.createNotificationBuilder(account) .setSmallIcon(R.drawable.ic_notify_check_mail) .setWhen(System.currentTimeMillis()) .setOngoing(true)