¿Cómo llamar a la lista de contactos de Android?

131

Estoy creando una aplicación de Android y necesito llamar a la lista de contactos del teléfono. Necesito llamar a la función de lista de contactos, elegir un contacto y luego volver a mi aplicación con el nombre del contacto. Aquí está el código que obtuve en Internet, pero no funciona.

import android.app.ListActivity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Contacts.People;
import android.view.View;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;

public class Contacts extends ListActivity {

    private ListAdapter mAdapter;
    public TextView pbContact;
    public static String PBCONTACT;
    public static final int ACTIVITY_EDIT=1;
    private static final int ACTIVITY_CREATE=0;

    // Called when the activity is first created. 
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        Cursor C = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
        startManagingCursor(C);

        String[] columns = new String[] {People.NAME};
        int[] names = new int[] {R.id.row_entry};

        mAdapter = new SimpleCursorAdapter(this, R.layout.mycontacts, C, columns, names);
        setListAdapter(mAdapter);
    } // end onCreate()
    // Called when contact is pressed
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        Cursor C = (Cursor) mAdapter.getItem(position);
        PBCONTACT = C.getString(C.getColumnIndex(People.NAME));

        // RHS 05/06
        //pbContact = (TextView) findViewById(R.id.myContact);
        //pbContact.setText(new StringBuilder().append("b"));

        Intent i = new Intent(this, NoteEdit.class);
        startActivityForResult(i, ACTIVITY_CREATE);
    }
}
Tam N.
fuente
Podría usted fijar la sección de código para incluir la primera parte del código: import android.app.ListActivity ...
David Glass
1.6 y 2.2 Ejemplos de esto: coderanch.com/t/512048/Android/Mobile/Contact-API
Blundell
tratar extractora de contactos androide . Una pequeña biblioteca simple y fácil de usar
nitesh

Respuestas:

250

No estoy 100% seguro de lo que se supone que debe hacer su código de muestra, pero el siguiente fragmento debería ayudarlo a 'llamar a la función de lista de contactos, elegir un contacto y luego regresar a [su] aplicación con el nombre del contacto'.

Hay tres pasos para este proceso.

1. Permisos

Agregue un permiso para leer datos de contactos al manifiesto de su aplicación.

<uses-permission android:name="android.permission.READ_CONTACTS"/>

2. Llamar al selector de contactos

Dentro de su Actividad, cree una Intención que le pida al sistema que encuentre una Actividad que pueda realizar una acción PICK de los elementos en el URI de Contactos.

Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);

Llamada startActivityForResult, pasando este Intento (y un entero de código de solicitud, PICK_CONTACTen este ejemplo). Esto hará que Android inicie una Actividad que esté registrada para admitir ACTION_PICKen el People.CONTENT_URI, y luego regrese a esta Actividad cuando se haga (o cancele) la selección.

startActivityForResult(intent, PICK_CONTACT);

3. Escuchando el resultado

También en su Actividad, anule el onActivityResultmétodo para escuchar el retorno de la Actividad 'seleccionar un contacto' que inició en el paso 2. Debe verificar que el código de solicitud devuelto coincida con el valor que espera y que el código de resultado sea RESULT_OK.

Puede obtener el URI del contacto seleccionado llamando getData()al parámetro Intento de datos . Para obtener el nombre del contacto seleccionado, debe usar ese URI para crear una nueva consulta y extraer el nombre del cursor devuelto.

@Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
  super.onActivityResult(reqCode, resultCode, data);

  switch (reqCode) {
    case (PICK_CONTACT) :
      if (resultCode == Activity.RESULT_OK) {
        Uri contactData = data.getData();
        Cursor c =  getContentResolver().query(contactData, null, null, null, null);
        if (c.moveToFirst()) {
          String name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
          // TODO Whatever you want to do with the selected contact name.
        }
      }
      break;
  }
}

Código fuente completo: tutorials-android.blogspot.com (cómo llamar a la lista de contactos de Android) .

Reto Meier
fuente
41
parece que gran parte de este código ha quedado en desuso con las API de Android recientes. ¿Alguien tiene una versión actualizada?
yamspog
P: Si deseo iniciar una subactividad al elegir un contacto (para que podamos hacer una copia de seguridad de la lista de contactos nuevamente), ¿Intent.ACTION_PICK aún funcionaría? Estoy empezando a pensar que tengo que rodar mi propio cursor y usar setListAdapter, como en la pregunta principal. Hmm ...
Joe D'Andrea
66
Aquí no pasa nada ... no necesita el permiso de contacto READ ya que el usuario tiene el control aquí. La aplicación en sí no lee internamente los contactos, sino que muestra una lista de contactos. Solo cuando el usuario selecciona un contacto (acción manual) es la aplicación capaz de recuperar un conjunto limitado de datos asociados con esa información de contacto.
ddewaele 05 de
1
Pude permitir al usuario elegir un contacto sin permiso de READ en mi teléfono Android 4.0+ pero no en 1.6. ¿Alguien sabe en qué versión surgió esta funcionalidad?
amit
1
PICK_CONTACT está fallando para mí. ¿Cómo lo inicializaste?
user3104760
67

Lo hago de esta manera para la versión Android 2.2 Froyo: básicamente uso eclipse para crear una clase como: clase pública SomePickContactName extiende la actividad

luego inserte este código. Recuerde agregar las variables de clase privada y CONSTANTES a los que se hace referencia en mi versión del código:

protected void onCreate(Bundle savedInstanceState) 
{
  super.onCreate(savedInstanceState);       
  Intent intentContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI); 
  startActivityForResult(intentContact, PICK_CONTACT);
}//onCreate

public void onActivityResult(int requestCode, int resultCode, Intent intent) 
{

  if (requestCode == PICK_CONTACT)
  {         
    getContactInfo(intent);         
    // Your class variables now have the data, so do something with it. 
  }
}//onActivityResult

protected void getContactInfo(Intent intent)
{

   Cursor cursor =  managedQuery(intent.getData(), null, null, null, null);      
   while (cursor.moveToNext()) 
   {           
       String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
       name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); 

       String hasPhone = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));

       if ( hasPhone.equalsIgnoreCase("1"))
           hasPhone = "true";
       else
           hasPhone = "false" ;

       if (Boolean.parseBoolean(hasPhone)) 
       {
        Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID +" = "+ contactId,null, null);
        while (phones.moveToNext()) 
        {
          phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        }
        phones.close();
       }

       // Find Email Addresses
       Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId,null, null);
       while (emails.moveToNext()) 
       {
        emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
       }
       emails.close();

    Cursor address = getContentResolver().query(
                ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,
                null,
                ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID + " = " + contactId,
                null, null);
    while (address.moveToNext()) 
    { 
      // These are all private class variables, don't forget to create them.
      poBox      = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POBOX));
      street     = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET));
      city       = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
      state      = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
      postalCode = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE));
      country    = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
      type       = address.getString(address.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.TYPE));
    }  //address.moveToNext()   
  }  //while (cursor.moveToNext())        
   cursor.close();
}//getContactInfo
Colin MacKenzie - III
fuente
la aplicación se bloquea cuando se intenta recibir un correo electrónico por segunda vez. Editar: si alguien más obtiene el mismo error, simplemente elimine "cursor.close ();" stackoverflow.com/questions/9696868/…
alicanbatur
14

Si busca una solución API de nivel 5 con la API ContactsContract, puede modificar ligeramente el código anterior con lo siguiente:

  Intent intent = new Intent(Intent.ACTION_PICK);
  intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
  startActivityForResult(intent, PICK_CONTACT);

Y luego en onActivityResult use el nombre de la columna:

  ContactsContract.Contacts.DISPLAY_NAME
Papi
fuente
1
¿Qué hay para mostrar los números de teléfono de contacto?
Usman Masood
No hay tales clases en Android 1.6. He encontrado nombres similares en Contacts.ContactMethods pero solo tengo excepciones (no puedo encontrar dicha actividad). Pero el código de Reto funciona bien
davs
8

Aquí está el fragmento de código para obtener contacto:

package com.contact;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class GetContactDemoActivity extends Activity implements OnClickListener {

private Button btn = null;
private TextView txt = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    btn = (Button) findViewById(R.id.button1);
    txt = (TextView) findViewById(R.id.textView1);

    btn.setOnClickListener(this);
}

@Override
public void onClick(View arg0) {
    if (arg0 == btn) {
        try {
            Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
            startActivityForResult(intent, 1);
        } catch (Exception e) {
            e.printStackTrace();
            Log.e("Error in intent : ", e.toString());
        }
    }
}

@Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
    super.onActivityResult(reqCode, resultCode, data);

    try {
        if (resultCode == Activity.RESULT_OK) {
            Uri contactData = data.getData();
            Cursor cur = managedQuery(contactData, null, null, null, null);
            ContentResolver contect_resolver = getContentResolver();

            if (cur.moveToFirst()) {
                String id = cur.getString(cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
                String name = "";
                String no = "";

                Cursor phoneCur = contect_resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[] { id }, null);

                if (phoneCur.moveToFirst()) {
                    name = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    no = phoneCur.getString(phoneCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                }

                Log.e("Phone no & name :***: ", name + " : " + no);
                txt.append(name + " : " + no + "\n");

                id = null;
                name = null;
                no = null;
                phoneCur = null;
            }
            contect_resolver = null;
            cur = null;
            //                      populateContacts();
        }
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
        Log.e("IllegalArgumentException :: ", e.toString());
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("Error :: ", e.toString());
    }
}

}

Mayur Bhola
fuente
6
        Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
        while (phones.moveToNext())
        {
        String Name=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)
        String Number=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        }
Maidul
fuente
5
public void onActivityResult(int requestCode, int resultCode, Intent intent) 
{
  if (requestCode == PICK_CONTACT && intent != null) //here check whether intent is null R not
  {  
  }
}

porque sin seleccionar ningún contacto dará una excepción. así que mejor verificar esta condición.

Kiran Kala
fuente
5

El código completo se da a continuación.

    package com.testingContect;

    import android.app.Activity;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.provider.ContactsContract;
    import android.provider.Contacts.People;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;

    public class testingContect extends Activity implements OnClickListener{
    /** Called when the activity is first created. */

    EditText ed;
    Button bt;
    int PICK_CONTACT;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        bt=(Button)findViewById(R.id.button1);
        ed =(EditText)findViewById(R.id.editText1);
        ed.setOnClickListener(this);
        bt.setOnClickListener(this);


    }

    @Override
    public void onClick(View v) {

        switch(v.getId())
        {
        case R.id.button1:

            break;
        case R.id.editText1:
             Intent intent = new Intent(Intent.ACTION_PICK);
              intent.setType(ContactsContract.Contacts.CONTENT_TYPE);
              startActivityForResult(intent, PICK_CONTACT);


            break;

        }

    }
    public void onActivityResult(int requestCode, int resultCode, Intent intent) 
    {

      if (requestCode == PICK_CONTACT)
      {         
          Cursor cursor =  managedQuery(intent.getData(), null, null, null, null);
          cursor.moveToNext();
          String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
           String  name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME)); 

          Toast.makeText(this, "Contect LIST  =  "+name, Toast.LENGTH_LONG).show(); 
      }
    }//onActivityResult
}//class ends
LISTA DE CONTACTOS DE ANDROID
fuente
1
¿Dónde se inicializa PICK_CONTACT?
Edward Falk
1
Es para ser declarada en la parte superior de la clase de actividad: private static final int PICK_CONTACT = 1;.
Omar
3

Para mi sorpresa, no necesita el permiso de usuario CONTACT_READ para leer los nombres y alguna información básica (¿Fue el contacto destacado, cuál fue la última vez que llamó?) Sin embargo, necesita permiso para leer los detalles del contacto como el número de teléfono.

Vicky Singh
fuente
3

Tenga cuidado al trabajar con la lista de contactos de Android.

La lectura de la lista de contactos en los métodos anteriores funciona en la mayoría de los dispositivos Android, excepto HTC One y Sony Xperia. Perdí mis seis semanas tratando de descubrir qué está mal!

La mayoría de los tutoriales disponibles en línea son casi similares: primero lea "TODOS" los contactos, luego muéstrese Listviewcon ArrayAdapter. Esta no es una solución eficiente en memoria. En lugar de buscar soluciones en otros sitios web primero, eche un vistazo a developer.android.com. Si alguna solución no está disponible en developer.android.com, debería buscar en otro lugar.

La solución es usar en CursorAdapterlugar de ArrayAdapterrecuperar la lista de contactos. El uso ArrayAdapterfuncionaría en la mayoría de los dispositivos, pero no es eficiente. Las CursorAdapterrecupera sólo una parte de la lista de contactos en tiempo de ejecución mientras el ListViewse está desplazando.

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    ...
    // Gets the ListView from the View list of the parent activity
    mContactsList =
        (ListView) getActivity().findViewById(R.layout.contact_list_view);
    // Gets a CursorAdapter
    mCursorAdapter = new SimpleCursorAdapter(
            getActivity(),
            R.layout.contact_list_item,
            null,
            FROM_COLUMNS, TO_IDS,
            0);
    // Sets the adapter for the ListView
    mContactsList.setAdapter(mCursorAdapter);
}

Recuperando una lista de contactos: Recuperando una lista de contactos

Adnan
fuente
1

Estoy usando este método para leer Contactos

public static List<ContactItem> readPhoneContacts(Context context) {
        List<ContactItem> contactItems = new ArrayList<ContactItem>();
        try {
            Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null,
                    null, null, "upper("+ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + ") ASC");

            /*context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                    null,
                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID+ " = ?",
                    new String[] { id },
                    ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC");*/

            Integer contactsCount = cursor.getCount(); // get how many contacts you have in your contacts list
            if (contactsCount > 0) {
                while (cursor.moveToNext()) {

                    String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
                    String contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
                    if (Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))) > 0) {
                        ContactItem contactItem = new ContactItem();
                        contactItem.setContactName(contactName);
                        //the below cursor will give you details for multiple contacts
                        Cursor pCursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
                                ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
                                new String[]{id}, null);
                        // continue till this cursor reaches to all phone numbers which are associated with a contact in the contact list
                        while (pCursor.moveToNext()) {
                            int phoneType = pCursor.getInt(pCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
                            //String isStarred      = pCur.getString(pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.STARRED));
                            String phoneNo = pCursor.getString(pCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                            //you will get all phone numbers according to it's type as below switch case.
                            //Logs.e will print the phone number along with the name in DDMS. you can use these details where ever you want.
                            switch (phoneType) {
                                case Phone.TYPE_MOBILE:
                                    contactItem.setContactNumberMobile(phoneNo);
                                    Log.e(contactName + ": TYPE_MOBILE", " " + phoneNo);
                                    break;
                                case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
                                    contactItem.setContactNumberMobile(phoneNo);
                                    Log.e(contactName + ": TYPE_HOME", " " + phoneNo);
                                    break;
                                case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
                                    contactItem.setContactNumberMobile(phoneNo);
                                    Log.e(contactName + ": TYPE_WORK", " " + phoneNo);
                                    break;
                                case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE:
                                    contactItem.setContactNumberMobile(phoneNo);
                                    Log.e(contactName + ": TYPE_WORK_MOBILE", " " + phoneNo);
                                    break;
                                case Phone.TYPE_OTHER:
                                    contactItem.setContactNumberMobile(phoneNo);
                                    Log.e(contactName + ": TYPE_OTHER", " " + phoneNo);
                                    break;
                                default:
                                    break;
                            }
                        }
                        contactItem.setSelectedAddress(getContactPostalAddress(pCursor));
                        pCursor.close();
                        contactItems.add(contactItem);
                    }

                }
                cursor.close();
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }


        return contactItems;
    }//loadContacts
Zar E Ahmer
fuente
1

hola tengo un código para guardar el contacto en su base de datos por preferencia compartida aquí está mi código

public class Main22Activity extends AppCompatActivity {
    EditText nameInput,phoneInput;
    TextView LargeText;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main22);
        nameInput = (EditText) findViewById(R.id.nameInput);
        phoneInput = (EditText) findViewById(R.id.phoneInput);

        LargeText = (TextView) findViewById(R.id.textView2);
    }

    public void saveInfo (View view){
        SharedPreferences sharedPref = getSharedPreferences("nameInfo" , Context.MODE_PRIVATE);
        SharedPreferences.Editor editor= sharedPref.edit();
        editor.putString("name", nameInput.getText().toString());
        editor.putString("phone", phoneInput.getText().toString());
        editor.apply();
        Toast.makeText(this, "Saved", Toast.LENGTH_LONG).show();
    }

    public void displayData(View view){
        SharedPreferences sharedPref = getSharedPreferences("nameInfo" , Context.MODE_PRIVATE);
        String name = sharedPref.getString("name", "");
        String ph = sharedPref.getString ("phone","");
        LargeText.setText(name + " " + ph);
    }
}
Abhishek
fuente
0
-> Add a permission to read contacts data to your application manifest.

<uses-permission android:name="android.permission.READ_CONTACTS"/>

-> Use Intent.Action_Pick in your Activity like below

Intent contactPickerIntent = new Intent(Intent.ACTION_PICK,
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
        startActivityForResult(contactPickerIntent, RESULT_PICK_CONTACT);

-> Then Override the onActivityResult()

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // check whether the result is ok
        if (resultCode == RESULT_OK) {
            // Check for the request code, we might be usign multiple startActivityForReslut
            switch (requestCode) {
            case RESULT_PICK_CONTACT:
               Cursor cursor = null;
        try {
            String phoneNo = null ;
            String name = null;           
            Uri uri = data.getData();            
            cursor = getContentResolver().query(uri, null, null, null, null);
            cursor.moveToFirst();           
            int  phoneIndex =cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
            phoneNo = cursor.getString(phoneIndex); 

            textView2.setText(phoneNo);
        } catch (Exception e) {
            e.printStackTrace();
        }
                break;
            }
        } else {
            Log.e("MainActivity", "Failed to pick contact");
        }
    }

This will work check it out
Ravi
fuente
0

Yo uso el codigo proporcionado por @Colin MacKenzie - III. ¡Muchas gracias!

Para alguien que está buscando un reemplazo de'QuiteRed 'obsoleto':

Primero, suponiendo que use v4 support lib:

import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;

2do:

your_(activity)_class implements LoaderManager.LoaderCallbacks<Cursor>

3ro

// temporarily store the 'data.getData()' from onActivityResult
private Uri tmp_url;

4º, anular devoluciones de llamada:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // create the loader here!
    CursorLoader cursorLoader = new CursorLoader(this, tmp_url, null, null, null, null);
    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    getContactInfo(cursor); // here it is!
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
}

5to:

public void initLoader(Uri data){
    // will be used in onCreateLoader callback
    this.tmp_url = data;
    // 'this' is an Activity instance, implementing those callbacks
    this.getSupportLoaderManager().initLoader(0, null, this);
}

6º, el código anterior , excepto que cambio el parámetro de firma de Intent a Cursor:

protected void getContactInfo(Cursor cursor)
{

   // Cursor cursor =  managedQuery(intent.getData(), null, null, null, null);      
   while (cursor.moveToNext()) 
   {
        // same above ...
   } 

7º, llame a initLoader:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (PICK_CONTACT == requestCode) {
        this.initLoader(data.getData(), this);
    }
}

8º, no olvides este fragmento de código

    Intent intentContact = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
    this.act.startActivityForResult(intentContact, PICK_CONTACT);

Referencias

Fundamentos de Android: cargar datos correctamente

Inicializando un cargador en una actividad

Yang
fuente