ZOFTINO.COM android and web dev tutorials

Android Contacts Search Using SearchView

If you need to provide contacts search functionality in your application, you can do so using SearchView and contact content provider. As user types into search view, you can query contact content provider, get contacts matching the search string and display the results as suggestions dropdown or in ListView.

On clicking one of the search results in suggestion dropdown or list view, you can display contact details. In this tutorial, you can learn how to implement contact search functionality in android.

Read contact content provider and reading and writing data to it article for more information on contact content provider.

To know more about SearchView and how to implement search, read implementing search in android using search view and implementing search dropdown suggestion articles.

android search searchview example

Activity

import android.Manifest;

import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;

import android.support.v4.app.ActivityCompat;
import android.support.v4.widget.SimpleCursorAdapter;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import zoftino.com.androidsearch.contacts.ContactsAdapter;

public class ContactsSearchActivity extends AppCompatActivity {
    private static final int REQUEST_PERMISSION = 1;

    private SearchView searchView;
    private ListView contactsList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.contacts_search_layout);

        Toolbar myToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(myToolbar);

        contactsList = findViewById(R.id.contact_list);

        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_CONTACTS,
                            Manifest.permission.WRITE_CONTACTS}, REQUEST_PERMISSION);

        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_menu, menu);

        searchView = (SearchView) menu.findItem(R.id.action_search)
                .getActionView();

        searchView.setSubmitButtonEnabled(true);
        searchView.setOnQueryTextListener(onQueryTextListener);

        return super.onCreateOptionsMenu(menu);
    }

    private SearchView.OnQueryTextListener onQueryTextListener =
            new SearchView.OnQueryTextListener() {
                @Override
                public boolean onQueryTextSubmit(String query) {
                    Cursor contacts = getListOfContactNames(query);
                    String[] cursorColumns = {
                                    ContactsContract.Contacts.DISPLAY_NAME_PRIMARY };
                    int[] viewIds = {R.id.tv_name};

                    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(
                            ContactsSearchActivity.this,
                            R.layout.contact_item_layout,
                            contacts,
                            cursorColumns,
                            viewIds,
                            0);

                    contactsList.setAdapter(simpleCursorAdapter);
                    contactsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> adapterView,
                                                View view, int i, long l) {
                            //get contact details and display
                            TextView tv = view.findViewById(R.id.tv_name);
                            Toast.makeText(ContactsSearchActivity.this,
                                    "Selected Contact "+tv.getText(),
                                    Toast.LENGTH_LONG).show();
                        }
                    });
                    return true;
                }

                @Override
                public boolean onQueryTextChange(String newText) {
                    Cursor contacts = getListOfContactNames(newText);
                    ContactsAdapter cursorAdapter = new ContactsAdapter
                            (ContactsSearchActivity.this, contacts, searchView);
                    searchView.setSuggestionsAdapter(cursorAdapter);
                    return true;
                }
            };

    public Cursor getListOfContactNames(String searchText) {

        Cursor cur = null;
        ContentResolver cr = getContentResolver();

        String[] mProjection = {ContactsContract.Contacts._ID,
                        ContactsContract.Contacts.LOOKUP_KEY,
                ContactsContract.Contacts.HAS_PHONE_NUMBER,
                ContactsContract.Contacts.DISPLAY_NAME_PRIMARY};

        Uri uri = ContactsContract.Contacts.CONTENT_URI;

        String selection = ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " LIKE ?";
        String[] selectionArgs = new String[]{"%"+searchText+"%"};

        cur = cr.query(uri, mProjection, selection, selectionArgs, null);

        return cur;
    }

}

Activity Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ContactsSearchActivity">
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <ListView
        android:id="@+id/contact_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"/>
</android.support.constraint.ConstraintLayout>

Custom Cursor Adapter

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.support.v4.widget.CursorAdapter;
import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import zoftino.com.androidsearch.R;

public class ContactsAdapter extends CursorAdapter {
    private LayoutInflater mLayoutInflater;
    private Context mContext;
    private SearchView searchView;

    public ContactsAdapter(Context context, Cursor cursor, SearchView sv) {
        super(context, cursor, false);
        mContext = context;
        searchView = sv;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View v = mLayoutInflater.inflate(R.layout.contact_item_layout, parent, false);
        return v;
    }

    @Override
    public void bindView(View view, final Context context, Cursor cursor) {

        String name = cursor.getString(cursor.getColumnIndex(
                ContactsContract.Contacts.DISPLAY_NAME_PRIMARY));
        String phone = cursor.getString(cursor.getColumnIndex(
                ContactsContract.Contacts.HAS_PHONE_NUMBER));

        String hasPhone = "Has Phone Number";
        if(phone.equals(0)){
            hasPhone = "Without Phone Number";
        }

        TextView nameTv =  view.findViewById(R.id.tv_name);
        nameTv.setText(name);

        TextView phoneNo = view.findViewById(R.id.tv_phone);
        phoneNo.setText(hasPhone);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TextView pName = (TextView) view.findViewById(R.id.tv_name);
                searchView.setIconified(true);
                //get contact details and display
                Toast.makeText(context, "Selected Contact "+pName.getText(),
                        Toast.LENGTH_LONG).show();

            }
        });
    }
}

Contact Item Layout

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginRight="16dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
    <TextView
        android:id="@+id/tv_phone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_name"/>
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:background="@color/colorAccent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_phone"/>
</android.support.constraint.ConstraintLayout>