Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 737edf36 authored by cketti's avatar cketti
Browse files

Use new contacts API on Android 2.0, 2.0.1, and 2.1 devices with additional...

Use new contacts API on Android 2.0, 2.0.1, and 2.1 devices with additional code to match by phonetic names.

Fixes issue 2906
parent de9f04ea
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -45,14 +45,18 @@ public abstract class Contacts
            int sdkVersion = Integer.parseInt(Build.VERSION.SDK);

            String className = null;
            /*
             * The new API appeared in Eclair, but it supported phonetic names in Froyo.
             * Therefore we employ the old API in Eclair.
             */
            if (sdkVersion <= Build.VERSION_CODES.ECLAIR_MR1)
            if (sdkVersion <= Build.VERSION_CODES.DONUT)
            {
                className = "com.fsck.k9.helper.ContactsSdk3_4";
            }
            else if (sdkVersion <= Build.VERSION_CODES.ECLAIR_MR1)
            {
                /*
                 * The new API was introduced with SDK 5. But Android versions < 2.2
                 * need some additional code to be able to search for phonetic names.
                 */
                className = "com.fsck.k9.helper.ContactsSdk5p";
            }
            else
            {
                className = "com.fsck.k9.helper.ContactsSdk5";
+5 −5
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ public class ContactsSdk5 extends com.fsck.k9.helper.Contacts
     * The order in which the search results are returned by
     * {@link #searchContacts(CharSequence)}.
     */
    private static final String SORT_ORDER =
    protected static final String SORT_ORDER =
        Email.TIMES_CONTACTED + " DESC, " +
        Contacts.DISPLAY_NAME + ", " +
        Email._ID;
@@ -35,7 +35,7 @@ public class ContactsSdk5 extends com.fsck.k9.helper.Contacts
     * {@link com.fsck.k9.EmailAddressAdapter} or more specificly by
     * {@link android.widget.ResourceCursorAdapter}.
     */
    private static final String PROJECTION[] =
    protected static final String PROJECTION[] =
    {
        Email._ID,
        Contacts.DISPLAY_NAME,
@@ -47,19 +47,19 @@ public class ContactsSdk5 extends com.fsck.k9.helper.Contacts
     * Index of the name field in the projection. This must match the order in
     * {@link #PROJECTION}.
     */
    private static final int NAME_INDEX = 1;
    protected static final int NAME_INDEX = 1;

    /**
     * Index of the email address field in the projection. This must match the
     * order in {@link #PROJECTION}.
     */
    private static final int EMAIL_INDEX = 2;
    protected static final int EMAIL_INDEX = 2;

    /**
     * Index of the contact id field in the projection. This must match the order in
     * {@link #PROJECTION}.
     */
    private static final int CONTACT_ID_INDEX = 3;
    protected static final int CONTACT_ID_INDEX = 3;


    public ContactsSdk5(final Context context)
+115 −0
Original line number Diff line number Diff line
package com.fsck.k9.helper;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;

/**
 * Access the contacts on the device using the API introduced with SDK 5.
 * Use some additional code to make search work with phonetic names.
 *
 * Android versions >= 2.2 (Froyo) support searching for phonetic names
 * out of the box (see {@link ContactsSdk5}).
 *
 * @see android.provider.ContactsContract
 */
public class ContactsSdk5p extends ContactsSdk5
{
    public ContactsSdk5p(final Context context)
    {
        super(context);
    }

    @Override
    public Cursor searchContacts(final CharSequence constraint)
    {
        if (constraint == null)
        {
            return null;
        }

        // Lookup using Email.CONTENT_FILTER_URI to get matching contact ids.
        // This does all sorts of magic we don't want to replicate.
        final String filter = constraint.toString();
        final Uri uri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, Uri.encode(filter));
        final Cursor cursor = mContentResolver.query(
                                    uri,
                                    new String[] {Email.CONTACT_ID},
                                    null,
                                    null,
                                    null);

        final StringBuilder matches = new StringBuilder();
        if ((cursor != null) && (cursor.getCount() > 0))
        {
            boolean first = true;
            while (cursor.moveToNext())
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    matches.append(",");
                }
                matches.append(cursor.getLong(0));
            }
            cursor.close();
        }

        // Find contacts with email addresses that have been found using
        // Email.CONTENT_FILTER_URI above or ones that have a matching phonetic name.
        final String where = Data.MIMETYPE + " = '" + Email.CONTENT_ITEM_TYPE + "'" +
                " AND " +
                "(" +
                // Match if found by Email.CONTENT_FILTER_URI
                Email.CONTACT_ID + " IN (" + matches.toString() + ")" +
                " OR " +
                // Match if phonetic given name starts with "constraint"
                StructuredName.PHONETIC_GIVEN_NAME + " LIKE ?" +
                " OR " +
                // Match if phonetic given name contains a word that starts with "constraint"
                StructuredName.PHONETIC_GIVEN_NAME + " LIKE ?" +
                " OR " +
                // Match if phonetic middle name starts with "constraint"
                StructuredName.PHONETIC_MIDDLE_NAME + " LIKE ?" +
                " OR " +
                // Match if phonetic middle name contains a word that starts with "constraint"
                StructuredName.PHONETIC_MIDDLE_NAME + " LIKE ?" +
                " OR " +
                // Match if phonetic family name starts with "constraint"
                StructuredName.PHONETIC_FAMILY_NAME + " LIKE ?" +
                " OR " +
                // Match if phonetic family name contains a word that starts with "constraint"
                StructuredName.PHONETIC_FAMILY_NAME + " LIKE ?" +
                ")";
        final String filter1 = constraint.toString() + "%";
        final String filter2 = "% " + filter1;
        final String[] args = new String[] {filter1, filter2, filter1, filter2, filter1, filter2};
        final Cursor c = mContentResolver.query(
                             Email.CONTENT_URI,
                             PROJECTION,
                             where,
                             args,
                             SORT_ORDER);

        if (c != null)
        {
            /*
             * To prevent expensive execution in the UI thread:
             * Cursors get lazily executed, so if you don't call anything on
             * the cursor before returning it from the background thread you'll
             * have a complied program for the cursor, but it won't have been
             * executed to generate the data yet. Often the execution is more
             * expensive than the compilation...
             */
            c.getCount();
        }

        return c;
    }
}