Add support for the syncMailboxStatus/syncMailboxListStatus callback

* Allows UI to show proper progress indications depending on the status
  of a particular mailbox (running, finished, or error state)
This commit is contained in:
Marc Blank 2009-07-30 13:08:06 -07:00
parent 90ed7a4e23
commit 85ef72b2ce
3 changed files with 110 additions and 20 deletions

View File

@ -81,7 +81,7 @@ public class EasSyncService extends InteractiveSyncService {
MailboxColumns.SYNC_INTERVAL + " IN (" + Account.CHECK_INTERVAL_PING +
',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.SERVER_ID + "!=\"" +
Eas.ACCOUNT_MAILBOX + '\"';
static private final int CHUNK_SIZE = 16 * 1024;
// Reasonable default
@ -136,6 +136,7 @@ public class EasSyncService extends InteractiveSyncService {
mStop = true;
}
@Override
public int getSyncStatus() {
return 0;
}
@ -143,6 +144,7 @@ public class EasSyncService extends InteractiveSyncService {
/* (non-Javadoc)
* @see com.android.exchange.SyncService#validateAccount(java.lang.String, java.lang.String, java.lang.String, int, boolean, android.content.Context)
*/
@Override
public void validateAccount(String hostAddress, String userName, String password, int port,
boolean ssl, Context context) throws MessagingException {
try {
@ -217,23 +219,17 @@ public class EasSyncService extends InteractiveSyncService {
private void doStatusCallback(long messageId, long attachmentId, int status) {
try {
IEmailServiceCallback cb = SyncManager.getCallback();
if (cb != null) {
cb.loadAttachmentStatus(messageId, attachmentId, status, 0);
}
} catch (RemoteException e2) {
SyncManager.callback().loadAttachmentStatus(messageId, attachmentId, status, 0);
} catch (RemoteException e) {
// No danger if the client is no longer around
}
}
private void doProgressCallback(long messageId, long attachmentId, int progress) {
try {
IEmailServiceCallback cb = SyncManager.getCallback();
if (cb != null) {
cb.loadAttachmentStatus(messageId, attachmentId, EmailServiceStatus.IN_PROGRESS,
progress);
}
} catch (RemoteException e2) {
SyncManager.callback().loadAttachmentStatus(messageId, attachmentId,
EmailServiceStatus.IN_PROGRESS, progress);
} catch (RemoteException e) {
// No danger if the client is no longer around
}
}
@ -371,14 +367,14 @@ public class EasSyncService extends InteractiveSyncService {
return us;
}
private HttpURLConnection setupEASCommand(String method, String cmd, String extra)
private HttpURLConnection setupEASCommand(String method, String cmd, String extra)
throws IOException {
try {
String us = makeUriString(cmd, extra);
URL u = new URL(us);
HttpURLConnection uc = (HttpURLConnection)u.openConnection();
HttpURLConnection.setFollowRedirects(true);
if (mSsl) {
((HttpsURLConnection)uc).setHostnameVerifier(new AllowAllHostnameVerifier());
}
@ -431,7 +427,16 @@ public class EasSyncService extends InteractiveSyncService {
* @throws EasParserException
*/
public void runMain() throws IOException, EasParserException {
// Initialize exit status to success
mExitStatus = EmailServiceStatus.SUCCESS;
try {
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, EmailServiceStatus.IN_PROGRESS, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
if (mAccount.mSyncKey == null) {
mAccount.mSyncKey = "0";
userLog("Account syncKey RESET");
@ -487,10 +492,20 @@ public class EasSyncService extends InteractiveSyncService {
} else if (encoding.equalsIgnoreCase("chunked")) {
// TODO We don't handle this yet
}
} else if (code == HttpURLConnection.HTTP_UNAUTHORIZED ||
code == HttpURLConnection.HTTP_FORBIDDEN) {
mExitStatus = AbstractSyncService.EXIT_LOGIN_FAILURE;
} else {
userLog("FolderSync response error: " + code);
}
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, mExitStatus, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
// Wait for push notifications.
String threadName = Thread.currentThread().getName();
try {
@ -504,7 +519,15 @@ public class EasSyncService extends InteractiveSyncService {
}
}
}
} catch (MalformedURLException e) {
} catch (IOException e) {
// We catch this here to send the folder sync status callback
// A folder sync failed callback will get sent from run()
try {
SyncManager.callback()
.syncMailboxListStatus(mAccount.mId, EmailServiceStatus.CONNECTION_ERROR, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
throw new IOException();
}
}
@ -850,6 +873,12 @@ public class EasSyncService extends InteractiveSyncService {
mUserName = ha.mLogin;
mPassword = ha.mPassword;
try {
SyncManager.callback().syncMailboxStatus(mMailboxId, EmailServiceStatus.IN_PROGRESS, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
// Make sure account and mailbox are always the latest from the database
mAccount = Account.restoreAccountWithId(mContext, mAccount.mId);
mMailbox = Mailbox.restoreMailboxWithId(mContext, mMailbox.mId);
@ -887,6 +916,27 @@ public class EasSyncService extends InteractiveSyncService {
} finally {
userLog(mMailbox.mDisplayName + ": sync finished");
SyncManager.done(this);
try {
int status;
switch (mExitStatus) {
case EXIT_IO_ERROR:
status = EmailServiceStatus.CONNECTION_ERROR;
break;
case EXIT_DONE:
status = EmailServiceStatus.SUCCESS;
break;
case EXIT_LOGIN_FAILURE:
status = EmailServiceStatus.LOGIN_FAILED;
break;
default:
status = EmailServiceStatus.REMOTE_EXCEPTION;
break;
}
SyncManager.callback().syncMailboxStatus(mMailboxId, status, 0);
} catch (RemoteException e1) {
// Don't care if this fails
}
}
}
}

View File

@ -30,6 +30,7 @@ public interface EmailServiceStatus {
public static final int FOLDER_NOT_RENAMED = 0x13;
public static final int FOLDER_NOT_CREATED = 0x14;
public static final int REMOTE_EXCEPTION = 0x15;
public static final int LOGIN_FAILED = 0x16;
// Maybe we should automatically retry these?
public static final int CONNECTION_ERROR = 0x20;

View File

@ -100,6 +100,48 @@ public class SyncManager extends Service implements Runnable {
new HashMap<Long, PendingIntent>();
static private WakeLock mWakeLock = null;
/**
* Proxy that can be used by various sync adapters to call into SyncManager's callback system.
* Used this way: SyncManager.callback().callbackMethod(args...);
* The proxy wraps checking for existence of a SyncManager instance and an active callback.
* Failures of these callbacks can be safely ignored.
*/
static private final IEmailServiceCallback.Stub sCallbackProxy =
new IEmailServiceCallback.Stub() {
public void loadAttachmentStatus(long messageId, long attachmentId, int statusCode,
int progress) throws RemoteException {
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.loadAttachmentStatus(messageId, attachmentId, statusCode, progress);
}
}
public void sendMessageStatus(long messageId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.sendMessageStatus(messageId, statusCode, progress);
}
}
public void syncMailboxListStatus(long accountId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.syncMailboxListStatus(accountId, statusCode, progress);
}
}
public void syncMailboxStatus(long mailboxId, int statusCode, int progress)
throws RemoteException{
IEmailServiceCallback cb = INSTANCE == null ? null: INSTANCE.mCallback;
if (cb != null) {
cb.syncMailboxListStatus(mailboxId, statusCode, progress);
}
}
};
/**
* Create the binder for EmailService implementation here. These are the calls that are
* defined in AbstractSyncService. Only validate is now implemented; loadAttachment currently
@ -372,11 +414,8 @@ public class SyncManager extends Service implements Runnable {
}
}
static public IEmailServiceCallback getCallback() {
if (INSTANCE != null) {
return INSTANCE.mCallback;
}
return null;
static public IEmailServiceCallback callback() {
return sCallbackProxy;
}
static public AccountList getAccountList() {