167 lines
7.3 KiB
Java
167 lines
7.3 KiB
Java
/* 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.exchange.provider;
|
|
|
|
import com.android.email.EmailAddressAdapter;
|
|
import com.android.email.R;
|
|
import com.android.email.provider.EmailContent.Account;
|
|
import com.android.email.provider.EmailContent.HostAuth;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.database.Cursor;
|
|
import android.database.MatrixCursor;
|
|
import android.database.MergeCursor;
|
|
import android.net.Uri;
|
|
import android.util.Log;
|
|
import android.view.View;
|
|
import android.widget.AutoCompleteTextView;
|
|
import android.widget.TextView;
|
|
|
|
public class GalEmailAddressAdapter extends EmailAddressAdapter {
|
|
private static final String TAG = "GalAdapter";
|
|
// Don't run GAL query until there are 3 characters typed
|
|
private static final int MINIMUM_GAL_CONSTRAINT_LENGTH = 3;
|
|
// Tag in the placeholder
|
|
public static final String SEARCHING_TAG = "_SEARCHING_";
|
|
|
|
Activity mActivity;
|
|
AutoCompleteTextView mAutoCompleteTextView;
|
|
Account mAccount;
|
|
boolean mAccountHasGal;
|
|
|
|
public GalEmailAddressAdapter(Activity activity, AutoCompleteTextView actv) {
|
|
super(activity);
|
|
mActivity = activity;
|
|
mAutoCompleteTextView = actv;
|
|
mAccount = null;
|
|
mAccountHasGal = false;
|
|
}
|
|
|
|
/**
|
|
* Set the account ID when known. Not used for generic contacts lookup; Use when
|
|
* linking lookup to specific account.
|
|
*/
|
|
@Override
|
|
public void setAccount(Account account) {
|
|
mAccount = account;
|
|
mAccountHasGal = false;
|
|
}
|
|
|
|
/**
|
|
* TODO: This should be the general purpose placeholder
|
|
* TODO: String (possibly with account name)
|
|
*/
|
|
public static Cursor getProgressCursor() {
|
|
MatrixCursor c = new MatrixCursor(ExchangeProvider.GAL_PROJECTION);
|
|
c.newRow().add(ExchangeProvider.GAL_START_ID).add("Searching ").add(SEARCHING_TAG);
|
|
return c;
|
|
}
|
|
|
|
/**
|
|
* Sniff the provided account and if it's EAS, record "mAccounthHasGal". If not,
|
|
* clear mAccount so we just ignore it.
|
|
*/
|
|
private void checkGalAccount(Account account) {
|
|
HostAuth ha = HostAuth.restoreHostAuthWithId(mActivity, account.mHostAuthKeyRecv);
|
|
if (ha != null) {
|
|
if ("eas".equalsIgnoreCase(ha.mProtocol)) {
|
|
mAccountHasGal = true;
|
|
return;
|
|
}
|
|
}
|
|
// for any reason, we could not identify a GAL account, so clear mAccount
|
|
// and we'll never check this again
|
|
mAccount = null;
|
|
mAccountHasGal = false;
|
|
}
|
|
|
|
@Override
|
|
public Cursor runQueryOnBackgroundThread(final CharSequence constraint) {
|
|
// One time (and not in the UI thread) - check the account and see if it support GAL
|
|
// If not, clear it so we never bother again
|
|
if (mAccount != null && mAccountHasGal == false) {
|
|
checkGalAccount(mAccount);
|
|
}
|
|
// Get the cursor from ContactsProvider
|
|
Cursor initialCursor = super.runQueryOnBackgroundThread(constraint);
|
|
// If we don't have an account or we don't have a constraint that's long enough, just return
|
|
if (mAccountHasGal &&
|
|
constraint != null && constraint.length() >= MINIMUM_GAL_CONSTRAINT_LENGTH) {
|
|
// Note that the "progress" line could (should) be implemented as a header rather than
|
|
// as a row in the list. The current implementation is placeholder.
|
|
MergeCursor mc =
|
|
new MergeCursor(new Cursor[] {initialCursor, getProgressCursor()});
|
|
// We need another copy of the original cursor for our MergeCursor
|
|
// because changeCursor closes the original!
|
|
// TODO: Avoid this - getting the contacts cursor twice is bad news.
|
|
// We're probably not handling the filter UI properly.
|
|
final Cursor contactsCursor = super.runQueryOnBackgroundThread(constraint);
|
|
new Thread(new Runnable() {
|
|
public void run() {
|
|
// Uri format is account/constraint/timestamp
|
|
Uri galUri =
|
|
ExchangeProvider.GAL_URI.buildUpon()
|
|
.appendPath(Long.toString(mAccount.mId))
|
|
.appendPath(constraint.toString())
|
|
.appendPath(((Long)System.currentTimeMillis()).toString()).build();
|
|
Log.d(TAG, "Query: " + galUri);
|
|
// Use ExchangeProvider to get the results of the GAL query
|
|
final Cursor galCursor =
|
|
mContentResolver.query(galUri, ExchangeProvider.GAL_PROJECTION,
|
|
null, null, null);
|
|
// A null cursor means that our query has been superceded by a later one
|
|
if (galCursor == null) return;
|
|
// We need to change cursors on the UI thread
|
|
mActivity.runOnUiThread(new Runnable() {
|
|
public void run() {
|
|
// Create a new cursor putting together local and GAL results and
|
|
// use it in the adapter
|
|
MergeCursor mergeCursor =
|
|
new MergeCursor(new Cursor[] {contactsCursor, galCursor});
|
|
changeCursor(mergeCursor);
|
|
// Call AutoCompleteTextView's onFilterComplete method with count
|
|
mAutoCompleteTextView.onFilterComplete(mergeCursor.getCount());
|
|
}});
|
|
}}).start();
|
|
return mc;
|
|
}
|
|
// Return right away with the ContactsProvider result
|
|
return initialCursor;
|
|
}
|
|
|
|
// TODO - we cannot assume that contacts ID's will not overlap with GAL_START_ID
|
|
// need to do this in a different way, based on more direct knowledge of our cursor
|
|
@Override
|
|
public final void bindView(View view, Context context, Cursor cursor) {
|
|
if (cursor.getLong(ID_INDEX) == ExchangeProvider.GAL_START_ID) {
|
|
((TextView)view.findViewById(R.id.account)).setText(cursor.getString(NAME_INDEX));
|
|
view.findViewById(R.id.status_divider).setVisibility(View.VISIBLE);
|
|
view.findViewById(R.id.address).setVisibility(View.GONE);
|
|
view.findViewById(R.id.progress).setVisibility(
|
|
cursor.getString(DATA_INDEX).equals(SEARCHING_TAG) ?
|
|
View.VISIBLE : View.GONE);
|
|
} else {
|
|
((TextView)view.findViewById(R.id.text1)).setText(cursor.getString(NAME_INDEX));
|
|
((TextView)view.findViewById(R.id.text2)).setText(cursor.getString(DATA_INDEX));
|
|
view.findViewById(R.id.address).setVisibility(View.VISIBLE);
|
|
view.findViewById(R.id.status_divider).setVisibility(View.GONE);
|
|
}
|
|
}
|
|
|
|
|
|
}
|