package com.zegoggles.smssync.mail; import android.annotation.TargetApi; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.provider.ContactsContract; import android.text.TextUtils; import android.util.Log; import org.jetbrains.annotations.NotNull; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import static com.zegoggles.smssync.App.LOCAL_LOGV; import static com.zegoggles.smssync.App.TAG; import static com.zegoggles.smssync.mail.MessageConverter.ECLAIR_CONTENT_URI; public class PersonLookup { private static final boolean NEW_CONTACT_API = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR; private static final String[] PHONE_PROJECTION = getPhoneProjection(); // PhoneLookup.CONTENT_FILTER_URI private static final Uri ECLAIR_CONTENT_FILTER_URI = Uri.parse("content://com.android.contacts/phone_lookup"); private static final int MAX_PEOPLE_CACHE_SIZE = 500; // simple LRU cache private final Map<String, PersonRecord> mPeopleCache = new LinkedHashMap<String, PersonRecord>(MAX_PEOPLE_CACHE_SIZE + 1, .75F, true) { @Override public boolean removeEldestEntry(Map.Entry<String, PersonRecord> eldest) { return size() > MAX_PEOPLE_CACHE_SIZE; } }; private final ContentResolver mResolver; public PersonLookup(ContentResolver resolver) { mResolver = resolver; Log.d(TAG, String.format(Locale.ENGLISH, "using %s contacts API", NEW_CONTACT_API ? "new" : "old")); } /* Look up a person */ @SuppressWarnings("deprecation") public @NotNull PersonRecord lookupPerson(final String address) { if (TextUtils.isEmpty(address)) { return new PersonRecord(0, null, null, "-1"); } else if (!mPeopleCache.containsKey(address)) { Uri personUri = Uri.withAppendedPath(NEW_CONTACT_API ? ECLAIR_CONTENT_FILTER_URI : android.provider.Contacts.Phones.CONTENT_FILTER_URL, Uri.encode(address)); Cursor c = mResolver.query(personUri, PHONE_PROJECTION, null, null, null); final PersonRecord record; if (c != null && c.moveToFirst()) { long id = c.getLong(c.getColumnIndex(PHONE_PROJECTION[0])); String number = NEW_CONTACT_API ? address : c.getString(c.getColumnIndex(PHONE_PROJECTION[2])); record = new PersonRecord( id, c.getString(c.getColumnIndex(PHONE_PROJECTION[1])), getPrimaryEmail(id), number ); } else { if (LOCAL_LOGV) Log.v(TAG, "Looked up unknown address: " + address); record = new PersonRecord(0, null, null, address); } mPeopleCache.put(address, record); if (c != null) c.close(); } return mPeopleCache.get(address); } @TargetApi(Build.VERSION_CODES.ECLAIR) @SuppressWarnings("deprecation") private String getPrimaryEmail(final long personId) { if (personId <= 0) { return null; } String primaryEmail = null; // Get all e-mail addresses for that person. Cursor c; int columnIndex; if (NEW_CONTACT_API) { c = mResolver.query( ECLAIR_CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Email.DATA}, ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = ?", new String[]{String.valueOf(personId)}, ContactsContract.CommonDataKinds.Email.IS_PRIMARY + " DESC"); columnIndex = c != null ? c.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA) : -1; } else { c = mResolver.query( android.provider.Contacts.ContactMethods.CONTENT_EMAIL_URI, new String[]{ android.provider.Contacts.ContactMethods.DATA }, android.provider.Contacts.ContactMethods.PERSON_ID + " = ?", new String[]{String.valueOf(personId)}, android.provider.Contacts.ContactMethods.ISPRIMARY + " DESC"); columnIndex = c != null ? c.getColumnIndex(android.provider.Contacts.ContactMethods.DATA) : -1; } // Loop over cursor and find a Gmail address for that person. // If there is none, pick first e-mail address. while (c != null && c.moveToNext()) { String e = c.getString(columnIndex); if (primaryEmail == null) { primaryEmail = e; } if (isGmailAddress(e)) { primaryEmail = e; break; } } if (c != null) c.close(); return primaryEmail; } // Returns whether the given e-mail address is a Gmail address or not. private static boolean isGmailAddress(String email) { return email != null && (email.toLowerCase(Locale.ENGLISH).endsWith("gmail.com") || email.toLowerCase(Locale.ENGLISH).endsWith("googlemail.com")); } @TargetApi(Build.VERSION_CODES.ECLAIR) @SuppressWarnings("deprecation") private static String[] getPhoneProjection() { return NEW_CONTACT_API ? new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME} : new String[]{ android.provider.Contacts.Phones.PERSON_ID, android.provider.Contacts.People.NAME, android.provider.Contacts.Phones.NUMBER }; } }