AI 145227: Add callback for push-mode stores to report async updates.

The logic for this is quite simplistic, for now:  When the store
  reports that it has new messages, it triggers a service refresh,
  just as if a pull-mode interval had expired and it is time to
  check the server.
  Note, unfortunately at this time there are no tests, because there
  are not currently any good test seams in MailService.java.
  BUG=1776149

Automated import of CL 145227
This commit is contained in:
Andy Stadler 2009-04-08 18:42:42 -07:00 committed by The Android Open Source Project
parent ea6fea9bb2
commit 8664ecf181
3 changed files with 115 additions and 12 deletions

View File

@ -185,6 +185,27 @@ public abstract class Store {
public abstract void checkSettings() throws MessagingException;
/**
* Enable or disable push mode delivery for a given Store.
*
* <p>For protocols that do not support push mode, be sure that push="true" is not
* set by the stores.xml definition file(s). This function need not be implemented.
*
* <p>For protocols that do support push mode, this will be called at startup (boot) time
* so that the Store can launch its own underlying connection service. It will also be called
* any time the user changes the settings for the account (because the user may switch back
* to polling mode (or disable checking completely).
*
* <p>This API will be called repeatedly, even after push mode has already been started or
* stopped. Stores that support push mode should return quickly if the configuration has not
* changed.
*
* @param enablePushMode start or stop push mode delivery
*/
public void enablePushModeDelivery(boolean enablePushMode) {
// does nothing for non-push protocols
}
/**
* Delete Store and its corresponding resources.
* @throws MessagingException

View File

@ -16,11 +16,14 @@
package com.android.email.mail.exchange;
import com.android.email.Email;
import com.android.email.mail.Folder;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import android.content.Context;
import android.util.Config;
import android.util.Log;
import java.net.URI;
import java.net.URISyntaxException;
@ -36,12 +39,15 @@ import java.util.HashMap;
* to res/xml/stores.xml
*/
public class ExchangeStoreExample extends Store {
public static final String LOG_TAG = "ExchangeStoreExample";
private final Context mContext;
private URI mUri;
private final ExchangeTransportExample mTransport;
private final HashMap<String, Folder> mFolders = new HashMap<String, Folder>();
private boolean mPushModeRunning = false;
/**
* Factory method.
@ -111,6 +117,29 @@ public class ExchangeStoreExample extends Store {
};
}
/**
* For a store that supports push mode, this is the API that enables it or disables it.
* The store should use this API to start or stop its persistent connection service or thread.
*
* <p>Note, may be called multiple times, even after push mode has been started or stopped.
*
* @param enablePushMode start or stop push mode delivery
*/
@Override
public void enablePushModeDelivery(boolean enablePushMode) {
if (Config.LOGD && Email.DEBUG) {
if (enablePushMode && !mPushModeRunning) {
Log.d(Email.LOG_TAG, "start push mode");
} else if (!enablePushMode && mPushModeRunning) {
Log.d(Email.LOG_TAG, "stop push mode");
} else {
Log.d(Email.LOG_TAG, enablePushMode ?
"push mode already started" : "push mode already stopped");
}
}
mPushModeRunning = enablePushMode;
}
/**
* Get class of SettingActivity for this Store class.
* @return Activity class that has class method actionEditIncomingSettings().

View File

@ -16,8 +16,16 @@
package com.android.email.service;
import java.util.ArrayList;
import java.util.HashMap;
import com.android.email.Account;
import com.android.email.Email;
import com.android.email.MessagingController;
import com.android.email.MessagingListener;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.Accounts;
import com.android.email.activity.FolderMessageList;
import com.android.email.mail.MessagingException;
import com.android.email.mail.Store;
import android.app.AlarmManager;
import android.app.Notification;
@ -33,14 +41,8 @@ import android.text.TextUtils;
import android.util.Config;
import android.util.Log;
import com.android.email.Account;
import com.android.email.Email;
import com.android.email.MessagingController;
import com.android.email.MessagingListener;
import com.android.email.Preferences;
import com.android.email.R;
import com.android.email.activity.Accounts;
import com.android.email.activity.FolderMessageList;
import java.util.ArrayList;
import java.util.HashMap;
/**
*/
@ -48,6 +50,8 @@ public class MailService extends Service {
private static final String ACTION_CHECK_MAIL = "com.android.email.intent.action.MAIL_SERVICE_WAKEUP";
private static final String ACTION_RESCHEDULE = "com.android.email.intent.action.MAIL_SERVICE_RESCHEDULE";
private static final String ACTION_CANCEL = "com.android.email.intent.action.MAIL_SERVICE_CANCEL";
private static final String EXTRA_CHECK_ACCOUNT = "com.android.email.intent.extra.ACCOUNT";
private Listener mListener = new Listener();
@ -66,6 +70,21 @@ public class MailService extends Service {
i.setAction(MailService.ACTION_CANCEL);
context.startService(i);
}
/**
* Entry point for asynchronous message services (e.g. push mode) to post notifications of new
* messages. Note: Although this is not a blocking call, it will start the MessagingController
* which will attempt to load the new messages. So the Store should expect to be opened and
* fetched from shortly after making this call.
*
* @param storeUri the Uri of the store that is reporting new messages
*/
public static void actionNotifyNewMessages(Context context, String storeUri) {
Intent i = new Intent(ACTION_CHECK_MAIL);
i.setClass(context, MailService.class);
i.putExtra(EXTRA_CHECK_ACCOUNT, storeUri);
context.startService(i);
}
@Override
public void onStart(Intent intent, int startId) {
@ -84,11 +103,21 @@ public class MailService extends Service {
// accounts that should not have been checked at all.
// Also note: Due to the organization of this service, you must gather the accounts
// and make a single call to controller.checkMail().
// TODO: Notification for single push account will fire up checks on all other
// accounts. This needs to be cleaned up for better efficiency.
String specificStoreUri = intent.getStringExtra(EXTRA_CHECK_ACCOUNT);
ArrayList<Account> accountsToCheck = new ArrayList<Account>();
for (Account account : Preferences.getPreferences(this).getAccounts()) {
if (account.getAutomaticCheckIntervalMinutes() > 0) {
int interval = account.getAutomaticCheckIntervalMinutes();
String storeUri = account.getStoreUri();
if (interval > 0 || (storeUri != null && storeUri.equals(specificStoreUri))) {
accountsToCheck.add(account);
}
// For each account, switch pushmail on or off
enablePushMail(account, interval == Account.CHECK_INTERVAL_PUSH);
}
Account[] accounts = accountsToCheck.toArray(new Account[accountsToCheck.size()]);
controller.checkMail(this, accounts, mListener);
@ -133,7 +162,7 @@ public class MailService extends Service {
int shortestInterval = -1;
for (Account account : Preferences.getPreferences(this).getAccounts()) {
if (account.getAutomaticCheckIntervalMinutes() != -1
if (account.getAutomaticCheckIntervalMinutes() > 0
&& (account.getAutomaticCheckIntervalMinutes() < shortestInterval || shortestInterval == -1)) {
shortestInterval = account.getAutomaticCheckIntervalMinutes();
}
@ -242,4 +271,28 @@ public class MailService extends Service {
stopSelf(mStartId);
}
}
/**
* For any account that wants push mail, get its Store and start the pushmail service.
* This function makes no attempt to optimize, so accounts may have push enabled (or disabled)
* repeatedly, and should handle this appropriately.
*
* @param account the account that needs push delivery enabled
*/
private void enablePushMail(Account account, boolean enable) {
try {
String storeUri = account.getStoreUri();
if (storeUri != null) {
Store store = Store.getInstance(storeUri, this.getBaseContext());
if (store != null) {
store.enablePushModeDelivery(enable);
}
}
} catch (MessagingException me) {
if (Config.LOGD && Email.DEBUG) {
Log.d(Email.LOG_TAG, "Failed to enable push mail for account" + account.getName() +
" with exception " + me.toString());
}
}
}
}