package cgeo.contacts; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.BaseColumns; import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.util.Log; import android.util.Pair; import android.view.Gravity; import android.widget.Toast; import org.apache.commons.lang3.CharEncoding; import org.apache.commons.lang3.StringUtils; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; public final class ContactsActivity extends Activity { static final String LOG_TAG = "cgeo.contacts"; @Override public void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Uri uri = getIntent().getData(); if (uri == null) { finish(); return; } final String nickName = getParameter(uri, IContacts.PARAM_NAME); if (StringUtils.isEmpty(nickName)) { finish(); return; } // search by nickname, exact List<Pair<Integer, String>> contacts = getContacts(nickName, ContactsContract.Data.CONTENT_URI, ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Nickname.NAME, false); // search by display name, exact if (contacts.isEmpty()) { contacts = getContacts(nickName, ContactsContract.Contacts.CONTENT_URI, BaseColumns._ID, ContactsContract.Contacts.DISPLAY_NAME, false); } // search by contained name parts if (contacts.isEmpty()) { contacts.addAll(getContacts(nickName, ContactsContract.Data.CONTENT_URI, ContactsContract.Data.CONTACT_ID, ContactsContract.CommonDataKinds.Nickname.NAME, true)); contacts.addAll(getContacts(nickName, ContactsContract.Contacts.CONTENT_URI, BaseColumns._ID, ContactsContract.Contacts.DISPLAY_NAME, true)); } if (contacts.isEmpty()) { showToast(getString(R.string.contact_not_found, nickName)); finish(); return; } if (contacts.size() > 1) { selectContact(contacts); } else { final int contactId = contacts.get(0).first; openContactAndFinish(contactId); } } private void selectContact(@NonNull final List<Pair<Integer, String>> contacts) { final List<String> list = new ArrayList<>(); for (final Pair<Integer, String> p : contacts) { list.add(p.second); } final CharSequence[] items = list.toArray(new CharSequence[list.size()]); new AlertDialog.Builder(this) .setTitle(R.string.multiple_matches) .setItems(items, new OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { final int contactId = contacts.get(which).first; dialog.dismiss(); openContactAndFinish(contactId); } }) .setOnCancelListener(new OnCancelListener() { @Override public void onCancel(final DialogInterface dialog) { dialog.dismiss(); finish(); } }) .create().show(); } private void openContactAndFinish(final int id) { final Intent intent = new Intent(Intent.ACTION_VIEW); final Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(id)); intent.setData(uri); startActivity(intent); finish(); } @NonNull private List<Pair<Integer, String>> getContacts(@NonNull final String searchName, final Uri uri, @NonNull final String idColumnName, @NonNull final String selectionColumnName, final boolean like) { final String[] projection = { idColumnName, selectionColumnName, ContactsContract.Contacts.DISPLAY_NAME }; final String selection = selectionColumnName + (like ? " LIKE" : " =") + " ? COLLATE NOCASE"; final String[] selectionArgs = { like ? "%" + searchName + "%" : searchName }; Cursor cursor = null; final List<Pair<Integer, String>> result = new ArrayList<>(); try { cursor = getContentResolver().query(uri, projection, selection, selectionArgs, null); while (cursor != null && cursor.moveToNext()) { final int foundId = cursor.getInt(0); final String foundName = cursor.getString(1); final String displayName = cursor.getString(2); result.add(new Pair<>(foundId, StringUtils.isNotEmpty(displayName) && !StringUtils.equalsIgnoreCase(foundName, displayName) ? foundName + " (" + displayName + ")" : foundName)); } } catch (final Exception e) { Log.e(LOG_TAG, "ContactsActivity.getContactId", e); } finally { if (cursor != null) { cursor.close(); // no Closable Cursor below sdk 16 } } return result; } public void showToast(final String text) { final Toast toast = Toast.makeText(this, text, Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 100); toast.show(); } @NonNull private static String getParameter(@NonNull final Uri uri, @NonNull final String paramKey) { try { final String param = uri.getQueryParameter(paramKey); if (param == null) { return StringUtils.EMPTY; } return URLDecoder.decode(param, CharEncoding.UTF_8).trim(); } catch (final UnsupportedEncodingException e) { Log.e(LOG_TAG, "ContactsActivity.getParameter", e); } return StringUtils.EMPTY; } }