Add support for "load more" for Imap2

* Use new attribute in services.xml to indicate support
* Initial implementation

Change-Id: Ia8709d606d521c6d495c343a47ee074b5024d340
This commit is contained in:
Marc Blank 2012-08-23 19:40:47 -07:00
parent e714bb9d15
commit b82ae909d7
9 changed files with 137 additions and 2 deletions

View File

@ -632,6 +632,21 @@
/>
</service>
<service
android:name=".service.LegacyImap2AuthenticatorService"
android:exported="false"
android:enabled="true"
>
<intent-filter>
<action
android:name="android.accounts.AccountAuthenticator" />
</intent-filter>
<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/authenticator_legacy_imap2"
/>
</service>
</application>
<!-- Legacy permissions, etc. can go here -->

View File

@ -63,6 +63,7 @@
email:usesSmtp="true"
email:offerLocalDeletes="true"
email:inferPrefix="pop"
email:offerLoadMore="true"
/>
<emailservice
email:protocol="imap2"
@ -82,6 +83,7 @@
email:offerPrefix="true"
email:syncChanges="true"
email:inferPrefix="imap"
email:offerLoadMore="true"
/>
<emailservice
email:protocol="eas"

View File

@ -64,5 +64,5 @@ interface IEmailService {
// API level 3
int getCapabilities(in Account acct);
void serviceUpdated(String emailAddress);
void serviceUpdated(String emailAddress);
}

View File

@ -42,6 +42,7 @@
<attr name="syncCalendar" format="boolean"/>
<attr name="usesAutodiscover" format="boolean"/>
<attr name="offerLookback" format="boolean"/>
<attr name="offerLoadMore" format="boolean"/>
<attr name="defaultLookback">
<enum name="auto" value="-2"/>
<enum name="days1" value="1"/>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright (c) 2009, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<!-- The attributes in this XML file provide configuration information -->
<!-- for the Account Manager. -->
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.android.imap2"
android:icon="@mipmap/ic_launcher_mail"
android:smallIcon="@drawable/stat_notify_email_generic"
android:label="@string/exchange_name"
android:accountPreferences="@xml/account_preferences"
/>

View File

@ -26,6 +26,7 @@ import android.database.Cursor;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
import android.os.RemoteException;
import android.util.Log;
@ -1999,6 +2000,60 @@ public class Imap2SyncService extends AbstractSyncService {
}
}
/**
* Add "more" UIDs to the server list (when the user explicitly asks for more)
*
* @param serverList the list of server UIDs
* @param howManyMore how many additional messages we want to load
* @return an updated list of server UIDs
* @throws IOException
*/
private int[] handleLoadMore(int[] serverList, int howManyMore) throws IOException {
// User has asked for more; find the oldest message
Arrays.sort(serverList);
int oldest = serverList[serverList.length - 1];
// Get its current sequence number
String tag = writeCommand(mWriter, "uid fetch " + oldest + " (UID)");
// IMAP_OK if we want it to work
if (readResponse(mReader, tag, "FETCH").equals(IMAP_OK)) {
String line = mImapResponse.get(0);
Parser lp = new Parser(line.substring(2));
// Last one we want is one before this message
int end = lp.parseInteger() - 1;
// First one is end - 9 (we want 10)
int start = end - 9;
if (start < 1) {
start = 1;
}
if (end > 0) {
// Get the uid's of the messages to load
tag = writeCommand(mWriter, "uid search " + start + ":" + end);
// IMAP_OK if we want it to work
if (readResponse(mReader, tag, "SEARCH").equals(IMAP_BAD)) {
int[] moreServerList;
// Parse the list
if (mImapResponse.isEmpty()) {
// Just return the original list
return serverList;
} else {
String msgs = mImapResponse.get(0);
// Length of "* search"
Parser p = new Parser(msgs, 8);
moreServerList = p.gatherInts();
int[] completeList = new int[serverList.length + moreServerList.length];
System.arraycopy(serverList, 0, completeList, 0, serverList.length);
System.arraycopy(moreServerList, 0, completeList, serverList.length,
moreServerList.length);
return completeList;
}
}
}
}
// In worst case, just return the original list
return serverList;
}
private void sync () throws IOException {
mThread = Thread.currentThread();
@ -2064,6 +2119,12 @@ public class Imap2SyncService extends AbstractSyncService {
return;
}
// See if we need extra messages; start by restoring the mailbox
mMailbox = Mailbox.restoreMailboxWithId(mContext, mMailboxId);
if (mMailbox.mVisibleLimit > 0) {
serverList = handleLoadMore(serverList, mMailbox.mVisibleLimit);
}
Arrays.sort(serverList);
int[] deviceList = getUidList(null);
Reconciled r =

View File

@ -2689,7 +2689,7 @@ outer:
String protocol = Account.getProtocol(context, mailbox.mAccountKey);
EmailServiceInfo info = EmailServiceUtils.getServiceInfo(context, protocol);
// All folders support delete
if (info != null && !info.offerLookback) {
if (info != null && info.offerLoadMore) {
// "load more" is valid for protocols not supporting "lookback"
values.put(UIProvider.FolderColumns.LOAD_MORE_URI,
uiUriString("uiloadmore", mailboxId));

View File

@ -176,6 +176,7 @@ public class EmailServiceUtils {
public int defaultSyncInterval;
public String inferPrefix;
public boolean requiresAccountUpdate;
public boolean offerLoadMore;
public String toString() {
StringBuilder sb = new StringBuilder("Protocol: ");
@ -279,6 +280,7 @@ public class EmailServiceUtils {
protected Void doInBackground(Void... params) {
disableComponent(mContext, LegacyEmailAuthenticatorService.class);
disableComponent(mContext, LegacyEasAuthenticatorService.class);
disableComponent(mContext, LegacyImap2AuthenticatorService.class);
return null;
}
}
@ -525,6 +527,8 @@ public class EmailServiceUtils {
info.defaultSyncInterval =
ta.getInteger(R.styleable.EmailServiceInfo_defaultSyncInterval, 15);
info.inferPrefix = ta.getString(R.styleable.EmailServiceInfo_inferPrefix);
info.offerLoadMore =
ta.getBoolean(R.styleable.EmailServiceInfo_offerLoadMore, false);
// Must have either "class" (local) or "intent" (remote)
if (klass != null) {

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.email.service;
/**
* This service needs to be declared separately from the base service
*/
public class LegacyImap2AuthenticatorService extends AuthenticatorService {
}