mirror of
https://github.com/moparisthebest/k-9
synced 2024-12-24 08:38:51 -05:00
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
This commit is contained in:
parent
de9f04ea0d
commit
737edf369b
@ -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";
|
||||
|
@ -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
src/com/fsck/k9/helper/ContactsSdk5p.java
Normal file
115
src/com/fsck/k9/helper/ContactsSdk5p.java
Normal file
@ -0,0 +1,115 @@
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user