with the following code for 59 contacts i got the following results on the emulator:
D ╔══════ query execution stats ═══════
D ║ got 59 contacts
D ║ query took 0.012 s (12 ms)
D ╚════════════════════════════════════
ok, that was the best time, but the average is 25-35 ms (for 59 contacts), add the following code in some onClick callback and run in several times in order to get the average time, in your case you should get 30 * 700 / 59 = ~300-400 ms, not 3 seconds, let alone one minute ;)
it uses Uri set to Contactables.CONTENT_URI added in API level 18 but you can use ContactsContract.Data.CONTENT_URI when building for pre 18 API devices
List<AddressBookContact> list = new LinkedList<AddressBookContact>();
LongSparseArray<AddressBookContact> array = new LongSparseArray<AddressBookContact>();
long start = System.currentTimeMillis();
String[] projection = {
ContactsContract.Data.MIMETYPE,
ContactsContract.Data.CONTACT_ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Contactables.DATA,
ContactsContract.CommonDataKinds.Contactables.TYPE,
};
String selection = ContactsContract.Data.MIMETYPE + " in (?, ?)";
String[] selectionArgs = {
ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
};
String sortOrder = ContactsContract.Contacts.SORT_KEY_ALTERNATIVE;
Uri uri = ContactsContract.CommonDataKinds.Contactables.CONTENT_URI;
// we could also use Uri uri = ContactsContract.Data.CONTENT_URI;
// ok, let's work...
Cursor cursor = getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
final int mimeTypeIdx = cursor.getColumnIndex(ContactsContract.Data.MIMETYPE);
final int idIdx = cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
final int nameIdx = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
final int dataIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.DATA);
final int typeIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Contactables.TYPE);
while (cursor.moveToNext()) {
long id = cursor.getLong(idIdx);
AddressBookContact addressBookContact = array.get(id);
if (addressBookContact == null) {
addressBookContact = new AddressBookContact(id, cursor.getString(nameIdx), getResources());
array.put(id, addressBookContact);
list.add(addressBookContact);
}
int type = cursor.getInt(typeIdx);
String data = cursor.getString(dataIdx);
String mimeType = cursor.getString(mimeTypeIdx);
if (mimeType.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
// mimeType == ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE
addressBookContact.addEmail(type, data);
} else {
// mimeType == ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
addressBookContact.addPhone(type, data);
}
}
long ms = System.currentTimeMillis() - start;
cursor.close();
// done!!! show the results...
int i = 1;
for (AddressBookContact addressBookContact : list) {
Log.d(TAG, "AddressBookContact #" + i++ + ": " + addressBookContact.toString(true));
}
final String cOn = "<b><font color='#ff9900'>";
final String cOff = "</font></b>";
Spanned l1 = Html.fromHtml("got " + cOn + array.size() + cOff + " contacts<br/>");
Spanned l2 = Html.fromHtml("query took " + cOn + ms / 1000f + cOff + " s (" + cOn + ms + cOff + " ms)");
Log.d(TAG, "
╔══════ query execution stats ═══════" );
Log.d(TAG, "║ " + l1);
Log.d(TAG, "║ " + l2);
Log.d(TAG, "╚════════════════════════════════════" );
SpannableStringBuilder msg = new SpannableStringBuilder().append(l1).append(l2);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
TextView tv = new TextView(this);
tv.setTextSize(20);
tv.setBackgroundColor(0xff000033);
tv.setPadding(24, 8, 24, 24);
tv.setText(msg);
ll.addView(tv);
ListView lv = new ListView(this);
lv.setAdapter(new ArrayAdapter<AddressBookContact>(this, android.R.layout.simple_list_item_1, list));
ll.addView(lv);
new AlertDialog.Builder(this).setView(ll).setPositiveButton("close", null).create().show();
the helper AddressBookContact
class:
class AddressBookContact {
private long id;
private Resources res;
private String name;
private LongSparseArray<String> emails;
private LongSparseArray<String> phones;
AddressBookContact(long id, String name, Resources res) {
this.id = id;
this.name = name;
this.res = res;
}
@Override
public String toString() {
return toString(false);
}
public String toString(boolean rich) {
SpannableStringBuilder builder = new SpannableStringBuilder();
if (rich) {
builder.append("id: ").append(Long.toString(id))
.append(", name: ").append("u001b[1m").append(name).append("u001b[0m");
} else {
builder.append(name);
}
if (phones != null) {
builder.append("
phones: ");
for (int i = 0; i < phones.size(); i++) {
int type = (int) phones.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Phone.getTypeLabel(res, type, ""))
.append(": ")
.append(phones.valueAt(i));
if (i + 1 < phones.size()) {
builder.append(", ");
}
}
}
if (emails != null) {
builder.append("
emails: ");
for (int i = 0; i < emails.size(); i++) {
int type = (int) emails.keyAt(i);
builder.append(ContactsContract.CommonDataKinds.Email.getTypeLabel(res, type, ""))
.append(": ")
.append(emails.valueAt(i));
if (i + 1 < emails.size()) {
builder.append(", ");
}
}
}
return builder.toString();
}
public void addEmail(int type, String address) {
if (emails == null) {
emails = new LongSparseArray<String>();
}
emails.put(type, address);
}
public void addPhone(int type, String number) {
if (phones == null) {
phones = new LongSparseArray<String>();
}
phones.put(type, number);
}
}