Suspend notifications for currently shown account
We will suspend notifications whenever we display the message list for an account (including "combined inbox"). As soon as the message list is paused, notifications will be resumed. Change-Id: I481a0f59ce68f89c32210d862d0267f3f334063b
This commit is contained in:
parent
ffeb7de284
commit
5701e0a555
|
@ -965,14 +965,21 @@ public abstract class EmailContent {
|
|||
public static final Uri NOTIFIER_URI =
|
||||
Uri.parse(EmailContent.CONTENT_NOTIFIER_URI + "/account");
|
||||
|
||||
// Define all pseudo account IDs here to avoid conflict with one another.
|
||||
/**
|
||||
* Value used by UI to represent "combined view".
|
||||
* Pseudo account ID to represent a "combined account" that includes messages and mailboxes
|
||||
* from all defined accounts.
|
||||
*
|
||||
* NOTE: This must be used only by UI, and mustn't be stored in the database.
|
||||
*
|
||||
* This is defined here to avoid conflict with other pseudo account IDs, if any.
|
||||
* <em>IMPORTANT</em>: This must never be stored to the database.
|
||||
*/
|
||||
public static final long ACCOUNT_ID_COMBINED_VIEW = 0x1000000000000000L;
|
||||
/**
|
||||
* Pseudo account ID to represent "no account". This may be used any time the account ID
|
||||
* may not be known or when we want to specifically select "no" account.
|
||||
*
|
||||
* <em>IMPORTANT</em>: This must never be stored to the database.
|
||||
*/
|
||||
public static final long PSEUDO_ACCOUNT_ID_NONE = -1L;
|
||||
|
||||
// Whether or not the user has asked for notifications of new mail in this account
|
||||
public final static int FLAGS_NOTIFY_NEW_MAIL = 1<<0;
|
||||
|
@ -1120,6 +1127,15 @@ public abstract class EmailContent {
|
|||
Account.CONTENT_URI, Account.CONTENT_PROJECTION, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given account ID is a "normal" account. Normal accounts
|
||||
* always have an ID greater than {@code 0} and not equal to any pseudo account IDs
|
||||
* (such as {@link #ACCOUNT_ID_COMBINED_VIEW})
|
||||
*/
|
||||
public static boolean isNormalAccount(long accountId) {
|
||||
return (accountId > 0L) && (accountId != ACCOUNT_ID_COMBINED_VIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh an account that has already been loaded. This is slightly less expensive
|
||||
* that generating a brand-new account object.
|
||||
|
@ -1217,13 +1233,11 @@ public abstract class EmailContent {
|
|||
mSignature = signature;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the minutes per check (for polling)
|
||||
* TODO define sentinel values for "never", "push", etc. See Account.java
|
||||
*/
|
||||
public int getSyncInterval()
|
||||
{
|
||||
public int getSyncInterval() {
|
||||
return mSyncInterval;
|
||||
}
|
||||
|
||||
|
@ -1232,8 +1246,7 @@ public abstract class EmailContent {
|
|||
* TODO define sentinel values for "never", "push", etc. See Account.java
|
||||
* @param minutes the number of minutes between polling checks
|
||||
*/
|
||||
public void setSyncInterval(int minutes)
|
||||
{
|
||||
public void setSyncInterval(int minutes) {
|
||||
mSyncInterval = minutes;
|
||||
}
|
||||
|
||||
|
@ -1776,6 +1789,7 @@ public abstract class EmailContent {
|
|||
/**
|
||||
* Supports Parcelable
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1785,10 +1799,12 @@ public abstract class EmailContent {
|
|||
*/
|
||||
public static final Parcelable.Creator<EmailContent.Account> CREATOR
|
||||
= new Parcelable.Creator<EmailContent.Account>() {
|
||||
@Override
|
||||
public EmailContent.Account createFromParcel(Parcel in) {
|
||||
return new EmailContent.Account(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailContent.Account[] newArray(int size) {
|
||||
return new EmailContent.Account[size];
|
||||
}
|
||||
|
@ -1797,6 +1813,7 @@ public abstract class EmailContent {
|
|||
/**
|
||||
* Supports Parcelable
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
// mBaseUri is not parceled
|
||||
dest.writeLong(mId);
|
||||
|
@ -2157,10 +2174,12 @@ public abstract class EmailContent {
|
|||
|
||||
public static final Parcelable.Creator<EmailContent.Attachment> CREATOR
|
||||
= new Parcelable.Creator<EmailContent.Attachment>() {
|
||||
@Override
|
||||
public EmailContent.Attachment createFromParcel(Parcel in) {
|
||||
return new EmailContent.Attachment(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailContent.Attachment[] newArray(int size) {
|
||||
return new EmailContent.Attachment[size];
|
||||
}
|
||||
|
@ -2926,6 +2945,7 @@ public abstract class EmailContent {
|
|||
/**
|
||||
* Supports Parcelable
|
||||
*/
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -2935,10 +2955,12 @@ public abstract class EmailContent {
|
|||
*/
|
||||
public static final Parcelable.Creator<EmailContent.HostAuth> CREATOR
|
||||
= new Parcelable.Creator<EmailContent.HostAuth>() {
|
||||
@Override
|
||||
public EmailContent.HostAuth createFromParcel(Parcel in) {
|
||||
return new EmailContent.HostAuth(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmailContent.HostAuth[] newArray(int size) {
|
||||
return new EmailContent.HostAuth[size];
|
||||
}
|
||||
|
@ -2947,6 +2969,7 @@ public abstract class EmailContent {
|
|||
/**
|
||||
* Supports Parcelable
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
// mBaseUri is not parceled
|
||||
dest.writeLong(mId);
|
||||
|
|
|
@ -546,6 +546,7 @@ public class Utility {
|
|||
*/
|
||||
public static void showToast(final Context context, final String message) {
|
||||
getMainThreadHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
@ -624,24 +625,28 @@ public class Utility {
|
|||
}
|
||||
|
||||
private static final CursorGetter<Long> LONG_GETTER = new CursorGetter<Long>() {
|
||||
@Override
|
||||
public Long get(Cursor cursor, int column) {
|
||||
return cursor.getLong(column);
|
||||
}
|
||||
};
|
||||
|
||||
private static final CursorGetter<Integer> INT_GETTER = new CursorGetter<Integer>() {
|
||||
@Override
|
||||
public Integer get(Cursor cursor, int column) {
|
||||
return cursor.getInt(column);
|
||||
}
|
||||
};
|
||||
|
||||
private static final CursorGetter<String> STRING_GETTER = new CursorGetter<String>() {
|
||||
@Override
|
||||
public String get(Cursor cursor, int column) {
|
||||
return cursor.getString(column);
|
||||
}
|
||||
};
|
||||
|
||||
private static final CursorGetter<byte[]> BLOB_GETTER = new CursorGetter<byte[]>() {
|
||||
@Override
|
||||
public byte[] get(Cursor cursor, int column) {
|
||||
return cursor.getBlob(column);
|
||||
}
|
||||
|
@ -925,7 +930,7 @@ public class Utility {
|
|||
} finally {
|
||||
c.close();
|
||||
}
|
||||
} else {
|
||||
} else if (accountId > 0L) {
|
||||
Mailbox mailbox =
|
||||
Mailbox.restoreMailboxOfType(context, accountId, Mailbox.TYPE_INBOX);
|
||||
|
||||
|
|
|
@ -75,8 +75,6 @@ public class NotificationController {
|
|||
/** Selection to retrieve accounts that should we notify user for changes */
|
||||
private final static String NOTIFIED_ACCOUNT_SELECTION =
|
||||
Account.FLAGS + "&" + Account.FLAGS_NOTIFY_NEW_MAIL + " != 0";
|
||||
/** special account ID for the new message notification APIs to specify "all accounts" */
|
||||
private static final long ALL_ACCOUNTS = -1L;
|
||||
|
||||
private static NotificationThread sNotificationThread;
|
||||
private static Handler sNotificationHandler;
|
||||
|
@ -92,6 +90,12 @@ public class NotificationController {
|
|||
/** Maps account id to the message data */
|
||||
private final HashMap<Long, MessageData> mNotificationMap;
|
||||
private ContentObserver mAccountObserver;
|
||||
/**
|
||||
* Suspend notifications for this account. If {@link Account#PSEUDO_ACCOUNT_ID_NONE}, no
|
||||
* account notifications are suspended. If {@link Account#ACCOUNT_ID_COMBINED_VIEW},
|
||||
* notifications for all accounts are suspended.
|
||||
*/
|
||||
private long mSuspendAccountId = Account.PSEUDO_ACCOUNT_ID_NONE;
|
||||
|
||||
/** Constructor */
|
||||
@VisibleForTesting
|
||||
|
@ -192,18 +196,13 @@ public class NotificationController {
|
|||
* notification shown to the user. And, when we start observing database changes, we restore
|
||||
* the saved state.
|
||||
* @param watch If {@code true}, we register observers for all accounts whose settings have
|
||||
* notifications enabled. Otherwise, all observers are unregistered with the database.
|
||||
* notifications enabled. Otherwise, all observers are unregistered.
|
||||
*/
|
||||
public void watchForMessages(final boolean watch) {
|
||||
// Don't create the thread if we're only going to stop watching
|
||||
if (!watch && sNotificationHandler == null) return;
|
||||
if (!watch && sNotificationThread == null) return;
|
||||
|
||||
synchronized(sInstance) {
|
||||
if (sNotificationHandler == null) {
|
||||
sNotificationThread = new NotificationThread();
|
||||
sNotificationHandler = new Handler(sNotificationThread.getLooper());
|
||||
}
|
||||
}
|
||||
ensureHandlerExists();
|
||||
// Run this on the message notification handler
|
||||
sNotificationHandler.post(new Runnable() {
|
||||
@Override
|
||||
|
@ -211,7 +210,7 @@ public class NotificationController {
|
|||
ContentResolver resolver = mContext.getContentResolver();
|
||||
HashMap<Long, long[]> table;
|
||||
if (!watch) {
|
||||
unregisterMessageNotification(ALL_ACCOUNTS);
|
||||
unregisterMessageNotification(Account.ACCOUNT_ID_COMBINED_VIEW);
|
||||
if (mAccountObserver != null) {
|
||||
resolver.unregisterContentObserver(mAccountObserver);
|
||||
mAccountObserver = null;
|
||||
|
@ -219,13 +218,12 @@ public class NotificationController {
|
|||
|
||||
// tear down the event loop
|
||||
sNotificationThread.quit();
|
||||
sNotificationHandler = null;
|
||||
sNotificationThread = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, start new observers for all notified accounts
|
||||
registerMessageNotification(ALL_ACCOUNTS);
|
||||
registerMessageNotification(Account.ACCOUNT_ID_COMBINED_VIEW);
|
||||
// If we're already observing account changes, don't do anything else
|
||||
if (mAccountObserver == null) {
|
||||
mAccountObserver = new AccountContentObserver(sNotificationHandler, mContext);
|
||||
|
@ -235,17 +233,61 @@ public class NotificationController {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily suspend a single account from receiving notifications. NOTE: only a single
|
||||
* account may ever be suspended at a time. So, if this method is invoked a second time,
|
||||
* notifications for the previously suspended account will automatically be re-activated.
|
||||
* @param suspend If {@code true}, suspend notifications for the given account. Otherwise,
|
||||
* re-activate notifications for the previously suspended account.
|
||||
* @param accountId The ID of the account. If this is the special account ID
|
||||
* {@link Account#ACCOUNT_ID_COMBINED_VIEW}, notifications for all accounts are
|
||||
* suspended. If {@code suspend} is {@code false}, the account ID is ignored.
|
||||
*/
|
||||
public void suspendMessageNotification(boolean suspend, long accountId) {
|
||||
if (mSuspendAccountId != Account.PSEUDO_ACCOUNT_ID_NONE) {
|
||||
// we're already suspending an account; un-suspend it
|
||||
mSuspendAccountId = Account.PSEUDO_ACCOUNT_ID_NONE;
|
||||
}
|
||||
if (suspend && accountId != Account.PSEUDO_ACCOUNT_ID_NONE && accountId > 0L) {
|
||||
mSuspendAccountId = accountId;
|
||||
if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
// Only go onto the notification handler if we really, absolutely need to
|
||||
ensureHandlerExists();
|
||||
sNotificationHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (long accountId : mNotificationMap.keySet()) {
|
||||
mNotificationManager.cancel(getNewMessageNotificationId(accountId));
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mNotificationManager.cancel(getNewMessageNotificationId(accountId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the notification handler exists and is ready to handle requests.
|
||||
*/
|
||||
private static synchronized void ensureHandlerExists() {
|
||||
if (sNotificationThread == null) {
|
||||
sNotificationThread = new NotificationThread();
|
||||
sNotificationHandler = new Handler(sNotificationThread.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an observer for changes to the INBOX for the given account. Since accounts
|
||||
* may only have a single INBOX, we will never have more than one observer for an account.
|
||||
* NOTE: This must be called on the notification handler thread.
|
||||
* @param accountId The ID of the account to register the observer for. May be
|
||||
* {@link #ALL_ACCOUNTS} to register observers for all accounts that allow
|
||||
* for user notification.
|
||||
* {@link Account#ACCOUNT_ID_COMBINED_VIEW} to register observers for all
|
||||
* accounts that allow for user notification.
|
||||
*/
|
||||
private void registerMessageNotification(long accountId) {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
if (accountId == ALL_ACCOUNTS) {
|
||||
if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
Cursor c = resolver.query(
|
||||
Account.CONTENT_URI, EmailContent.ID_PROJECTION,
|
||||
NOTIFIED_ACCOUNT_SELECTION, null, null);
|
||||
|
@ -282,12 +324,12 @@ public class NotificationController {
|
|||
* a registered observer, no action is performed. This will not clear any existing notification
|
||||
* for the specified account. Use {@link NotificationManager#cancel(int)}.
|
||||
* NOTE: This must be called on the notification handler thread.
|
||||
* @param accountId The ID of the account to unregister from. May be {@link #ALL_ACCOUNTS} to
|
||||
* unregister all accounts that have observers.
|
||||
* @param accountId The ID of the account to unregister from. To unregister all accounts that
|
||||
* have observers, specify an ID of {@link Account#ACCOUNT_ID_COMBINED_VIEW}.
|
||||
*/
|
||||
private void unregisterMessageNotification(long accountId) {
|
||||
ContentResolver resolver = mContext.getContentResolver();
|
||||
if (accountId == ALL_ACCOUNTS) {
|
||||
if (accountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
// cancel all existing message observers
|
||||
for (MessageData data : mNotificationMap.values()) {
|
||||
ContentObserver observer = data.mObserver;
|
||||
|
@ -303,42 +345,6 @@ public class NotificationController {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the message notification for the given account to the most recent message ID.
|
||||
* This is not complete and will still exhibit the existing (wrong) behaviour of notifying
|
||||
* the user even if the Email UX is visible.
|
||||
* NOTE: Only for short-term legacy support. To be replaced with a way to temporarily stop
|
||||
* notifications for a mailbox.
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public void resetMessageNotification(final long accountId) {
|
||||
synchronized(sInstance) {
|
||||
if (sNotificationHandler == null) {
|
||||
sNotificationThread = new NotificationThread();
|
||||
sNotificationHandler = new Handler(sNotificationThread.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
// Run this on the message notification handler
|
||||
sNotificationHandler.post(new Runnable() {
|
||||
private void resetNotification(long accountId) {
|
||||
if (accountId == ALL_ACCOUNTS) {
|
||||
for (long id : mNotificationMap.keySet()) {
|
||||
resetNotification(id);
|
||||
}
|
||||
} else {
|
||||
Utility.updateLastSeenMessageKey(mContext, accountId);
|
||||
mNotificationManager.cancel(getNewMessageNotificationId(accountId));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
resetNotification(accountId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a picture of the sender of the given message. If no picture is available, returns
|
||||
* {@code null}.
|
||||
|
@ -382,6 +388,7 @@ public class NotificationController {
|
|||
final String subject = message.mSubject;
|
||||
final Bitmap senderPhoto = getSenderPhoto(message);
|
||||
final SpannableString title = getNewMessageTitle(senderName, account.mDisplayName);
|
||||
// TODO Set the intent according to number of unseen messages
|
||||
final Intent intent = Welcome.createOpenAccountInboxIntent(mContext, accountId);
|
||||
final Bitmap largeIcon = senderPhoto != null ? senderPhoto : mGenericSenderIcon;
|
||||
final Integer number = unseenMessageCount > 1 ? unseenMessageCount : null;
|
||||
|
@ -581,7 +588,10 @@ public class NotificationController {
|
|||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
super.onChange(selfChange);
|
||||
if (mAccountId == sInstance.mSuspendAccountId
|
||||
|| sInstance.mSuspendAccountId == Account.ACCOUNT_ID_COMBINED_VIEW) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageData data = sInstance.mNotificationMap.get(mAccountId);
|
||||
if (data == null) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.android.email.Email;
|
|||
import com.android.email.R;
|
||||
import com.android.email.RefreshManager;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.service.MailService;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
|
@ -33,6 +34,7 @@ import android.app.LoaderManager;
|
|||
import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
|
@ -213,6 +215,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
* Called to do initial creation of a fragment. This is called after
|
||||
* {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -239,6 +242,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
return inflater.inflate(R.layout.mailbox_list_fragment, container, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -274,6 +278,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
* Otherwise, only load the list of top-level mailboxes if the account changes.
|
||||
*/
|
||||
// STOPSHIP Make it private once phone activities are gone
|
||||
@SuppressWarnings("unused")
|
||||
void openMailboxes(long accountId, long parentMailboxId) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MailboxListFragment openMailboxes");
|
||||
|
@ -315,6 +320,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
/**
|
||||
* Called when the Fragment is visible to the user.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -326,6 +332,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
/**
|
||||
* Called when the fragment is visible to the user and actively running.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -341,6 +348,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -349,12 +357,12 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
mResumed = false;
|
||||
super.onPause();
|
||||
mSavedListState = getListView().onSaveInstanceState();
|
||||
Utility.updateLastSeenMessageKey(mActivity, mAccountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Fragment is no longer started.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -366,6 +374,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
/**
|
||||
* Called when the fragment is no longer in use.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -374,6 +383,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -384,6 +394,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
outState.putParcelable(BUNDLE_LIST_STATE, getListView().onSaveInstanceState());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void restoreInstanceState(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MailboxListFragment restoreInstanceState");
|
||||
|
@ -392,6 +403,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
mSavedListState = savedInstanceState.getParcelable(BUNDLE_LIST_STATE);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void startLoading() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MailboxListFragment startLoading");
|
||||
|
@ -408,6 +420,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
private class MailboxListLoaderCallbacks implements LoaderCallbacks<Cursor> {
|
||||
private boolean mIsFirstLoad;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -417,6 +430,7 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
return MailboxFragmentAdapter.createLoader(getActivity(), mAccountId, mParentMailboxId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -466,8 +480,15 @@ public class MailboxListFragment extends ListFragment implements OnItemClickList
|
|||
}
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long idDontUseIt /* see MailboxesAdapter */ ) {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* @param doNotUse <em>IMPORTANT</em>: Do not use this parameter. The ID in the list widget
|
||||
* must be a positive value. However, we rely on negative IDs for special mailboxes. Instead,
|
||||
* we use the ID returned by {@link MailboxesAdapter#getId(int)}.
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long doNotUse) {
|
||||
final long id = mListAdapter.getId(position);
|
||||
if (mListAdapter.isAccountRow(position)) {
|
||||
mCallback.onAccountSelected(id);
|
||||
|
|
|
@ -18,11 +18,11 @@ package com.android.email.activity;
|
|||
|
||||
import com.android.email.Controller;
|
||||
import com.android.email.Email;
|
||||
import com.android.email.NotificationController;
|
||||
import com.android.email.R;
|
||||
import com.android.email.RefreshManager;
|
||||
import com.android.email.data.MailboxAccountLoader;
|
||||
import com.android.email.provider.EmailProvider;
|
||||
import com.android.email.service.MailService;
|
||||
import com.android.emailcommon.Logging;
|
||||
import com.android.emailcommon.provider.EmailContent;
|
||||
import com.android.emailcommon.provider.EmailContent.Account;
|
||||
|
@ -37,7 +37,6 @@ import android.app.ListFragment;
|
|||
import android.app.LoaderManager;
|
||||
import android.content.ClipData;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Loader;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
|
@ -238,6 +237,7 @@ public class MessageListFragment extends ListFragment
|
|||
return instance;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -261,6 +261,7 @@ public class MessageListFragment extends ListFragment
|
|||
return root;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -292,6 +293,7 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -300,6 +302,7 @@ public class MessageListFragment extends ListFragment
|
|||
super.onStart();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -307,6 +310,7 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
super.onResume();
|
||||
mResumed = true;
|
||||
adjustMessageNotification(false);
|
||||
|
||||
// If we're recovering from the stopped state, we don't have to reload.
|
||||
// (when mOpenRequested = false)
|
||||
|
@ -315,6 +319,7 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -323,8 +328,10 @@ public class MessageListFragment extends ListFragment
|
|||
mResumed = false;
|
||||
super.onStop();
|
||||
mSavedListState = getListView().onSaveInstanceState();
|
||||
adjustMessageNotification(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -333,6 +340,7 @@ public class MessageListFragment extends ListFragment
|
|||
super.onStop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -349,6 +357,7 @@ public class MessageListFragment extends ListFragment
|
|||
super.onDestroy();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -360,6 +369,7 @@ public class MessageListFragment extends ListFragment
|
|||
outState.putLong(BUNDLE_KEY_SELECTED_MESSAGE_ID, mSelectedMessageId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@VisibleForTesting
|
||||
void restoreInstanceState(Bundle savedInstanceState) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -414,6 +424,7 @@ public class MessageListFragment extends ListFragment
|
|||
* {@link Mailbox#QUERY_ALL_INBOXES}. -1 is not allowed.
|
||||
*/
|
||||
// STOPSHIP Make it private once phone activities are gone
|
||||
@SuppressWarnings("unused")
|
||||
void openMailbox(long mailboxId) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MessageListFragment openMailbox");
|
||||
|
@ -446,10 +457,15 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the account id or -1 if it's unknown yet. It's also -1 if it's a magic mailbox.
|
||||
* Returns the account id of the currently viewed messages. May return
|
||||
* {@link Account#PSEUDO_ACCOUNT_ID_NONE} if the mailbox is not yet known or
|
||||
* {@link Account#ACCOUNT_ID_COMBINED_VIEW} if viewing a combined mailbox.
|
||||
*/
|
||||
public long getAccountId() {
|
||||
return (mMailbox == null) ? -1 : mMailbox.mAccountKey;
|
||||
private long getAccountId() {
|
||||
return (mMailbox == null)
|
||||
? (mMailboxId < Mailbox.NO_MAILBOX)
|
||||
? Account.ACCOUNT_ID_COMBINED_VIEW : Account.PSEUDO_ACCOUNT_ID_NONE
|
||||
: mMailbox.mAccountKey;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -492,6 +508,7 @@ public class MessageListFragment extends ListFragment
|
|||
/**
|
||||
* Called when a message is clicked.
|
||||
*/
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view != mListFooterView) {
|
||||
MessageListItem itemView = (MessageListItem) view;
|
||||
|
@ -593,6 +610,7 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(View view, DragEvent event) {
|
||||
switch(event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_ENDED:
|
||||
|
@ -614,6 +632,7 @@ public class MessageListFragment extends ListFragment
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
if (view != mListFooterView) {
|
||||
// Start drag&drop.
|
||||
|
@ -732,7 +751,7 @@ public class MessageListFragment extends ListFragment
|
|||
return;
|
||||
}
|
||||
long accountId = getAccountId();
|
||||
if (accountId != -1) {
|
||||
if (Account.isNormalAccount(accountId)) {
|
||||
mRefreshManager.refreshMessageList(accountId, mMailboxId, userRequest);
|
||||
}
|
||||
}
|
||||
|
@ -753,7 +772,7 @@ public class MessageListFragment extends ListFragment
|
|||
*/
|
||||
private void onLoadMoreMessages() {
|
||||
long accountId = getAccountId();
|
||||
if (accountId != -1) {
|
||||
if (Account.isNormalAccount(accountId)) {
|
||||
mRefreshManager.loadMoreMessages(accountId, mMailboxId);
|
||||
}
|
||||
}
|
||||
|
@ -794,10 +813,12 @@ public class MessageListFragment extends ListFragment
|
|||
private void toggleRead(Set<Long> selectedSet) {
|
||||
toggleMultiple(selectedSet, new MultiToggleHelper() {
|
||||
|
||||
@Override
|
||||
public boolean getField(long messageId, Cursor c) {
|
||||
return c.getInt(MessagesAdapter.COLUMN_READ) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setField(long messageId, Cursor c, boolean newValue) {
|
||||
boolean oldValue = getField(messageId, c);
|
||||
if (oldValue != newValue) {
|
||||
|
@ -817,10 +838,12 @@ public class MessageListFragment extends ListFragment
|
|||
private void toggleFavorite(Set<Long> selectedSet) {
|
||||
toggleMultiple(selectedSet, new MultiToggleHelper() {
|
||||
|
||||
@Override
|
||||
public boolean getField(long messageId, Cursor c) {
|
||||
return c.getInt(MessagesAdapter.COLUMN_FAVORITE) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setField(long messageId, Cursor c, boolean newValue) {
|
||||
boolean oldValue = getField(messageId, c);
|
||||
if (oldValue != newValue) {
|
||||
|
@ -1058,6 +1081,28 @@ public class MessageListFragment extends ListFragment
|
|||
showNoMessageText(noItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts message notification depending upon the state of the fragment and the currently
|
||||
* viewed mailbox. If the fragment is resumed, notifications for the current mailbox may
|
||||
* be suspended. Otherwise, notifications may be re-activated. Not all mailbox types are
|
||||
* supported for notifications. These include (but are not limited to) special mailboxes
|
||||
* such as {@link Mailbox#QUERY_ALL_DRAFTS}, {@link Mailbox#QUERY_ALL_FAVORITES}, etc...
|
||||
*
|
||||
* @param updateLastSeenKey If {@code true}, the last seen message key for the currently
|
||||
* viewed mailbox will be updated.
|
||||
*/
|
||||
private void adjustMessageNotification(boolean updateLastSeenKey) {
|
||||
if (mMailboxId == Mailbox.QUERY_ALL_INBOXES || mMailboxId > 0) {
|
||||
long id = getAccountId();
|
||||
if (updateLastSeenKey) {
|
||||
Utility.updateLastSeenMessageKey(mActivity, id);
|
||||
}
|
||||
NotificationController notifier = NotificationController.getInstance(mActivity);
|
||||
notifier.suspendMessageNotification(mResumed, id);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void startLoading() {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
Log.d(Logging.LOG_TAG, "MessageListFragment startLoading");
|
||||
|
@ -1079,6 +1124,7 @@ public class MessageListFragment extends ListFragment
|
|||
*/
|
||||
private class MailboxAccountLoaderCallback implements LoaderManager.LoaderCallbacks<
|
||||
MailboxAccountLoader.Result> {
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public Loader<MailboxAccountLoader.Result> onCreateLoader(int id, Bundle args) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -1088,6 +1134,7 @@ public class MessageListFragment extends ListFragment
|
|||
return new MailboxAccountLoader(getActivity().getApplicationContext(), mMailboxId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onLoadFinished(Loader<MailboxAccountLoader.Result> loader,
|
||||
MailboxAccountLoader.Result result) {
|
||||
|
@ -1120,6 +1167,7 @@ public class MessageListFragment extends ListFragment
|
|||
private class MessagesLoaderCallback implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
private boolean mIsFirstLoad;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -1130,6 +1178,7 @@ public class MessageListFragment extends ListFragment
|
|||
return MessagesAdapter.createLoader(getActivity(), mMailboxId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
|
||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||
|
@ -1137,6 +1186,9 @@ public class MessageListFragment extends ListFragment
|
|||
"MessageListFragment onLoadFinished(messages) mailboxId=" + mMailboxId);
|
||||
}
|
||||
|
||||
// Suspend message notifications as long as we're resumed
|
||||
adjustMessageNotification(false);
|
||||
|
||||
// Save list view state (primarily scroll position)
|
||||
final ListView lv = getListView();
|
||||
final Parcelable listState;
|
||||
|
@ -1178,8 +1230,6 @@ public class MessageListFragment extends ListFragment
|
|||
lv.onRestoreInstanceState(listState);
|
||||
}
|
||||
|
||||
resetNewMessageCount(mActivity, mMailboxId, getAccountId());
|
||||
|
||||
// Clear this for next reload triggered by content changed events.
|
||||
mIsFirstLoad = false;
|
||||
|
||||
|
@ -1192,26 +1242,6 @@ public class MessageListFragment extends ListFragment
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the "new message" count.
|
||||
* <ul>
|
||||
* <li>If {@code mailboxId} is {@link Mailbox#QUERY_ALL_INBOXES}, reset the
|
||||
* counts of all accounts.
|
||||
* <li>If {@code mailboxId} is not of a magic inbox (i.e. >= 0) and {@code
|
||||
* accountId} is valid, reset the count of the specified account.
|
||||
* </ul>
|
||||
* TODO Instead of resetting the message count, we should just be suspending the notification
|
||||
* controller for the correct accounts. Need to ensure we resume notifications appropriately.
|
||||
*/
|
||||
private static void resetNewMessageCount(
|
||||
Context context, long mailboxId, long accountId) {
|
||||
if (mailboxId == Mailbox.QUERY_ALL_INBOXES) {
|
||||
MailService.resetNewMessageCount(context, -1);
|
||||
} else if (mailboxId >= 0 && accountId != -1) {
|
||||
MailService.resetNewMessageCount(context, accountId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/hide the "selection" action mode, according to the number of selected messages and
|
||||
* the visibility of the fragment.
|
||||
|
|
|
@ -49,7 +49,7 @@ abstract class UIControllerBase {
|
|||
protected static final String BUNDLE_KEY_MESSAGE_ID = "UIController.state.message_id";
|
||||
|
||||
/** No account selected */
|
||||
static final long NO_ACCOUNT = -1;
|
||||
static final long NO_ACCOUNT = Account.PSEUDO_ACCOUNT_ID_NONE;
|
||||
/** No mailbox selected */
|
||||
static final long NO_MAILBOX = -1;
|
||||
/** No message selected */
|
||||
|
|
|
@ -143,17 +143,6 @@ public class MailService extends Service {
|
|||
context.startService(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset new message counts for one or all accounts. This clears both our local copy and
|
||||
* the values (if any) stored in the account records.
|
||||
*
|
||||
* @param accountId account to clear, or -1 for all accounts
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void resetNewMessageCount(final Context context, final long accountId) {
|
||||
NotificationController.getInstance(context).resetMessageNotification(accountId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for asynchronous message services (e.g. push mode) to post notifications of new
|
||||
* messages. This assumes that the push provider has already synced the messages into the
|
||||
|
@ -162,7 +151,7 @@ public class MailService extends Service {
|
|||
* @param context a context
|
||||
* @param accountId the id of the account that is reporting new messages
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static void actionNotifyNewMessages(
|
||||
Context context, long accountId, List messageIdList) {
|
||||
Intent i = new Intent(ACTION_NOTIFY_MAIL);
|
||||
|
|
Loading…
Reference in New Issue