Sie sind auf Seite 1von 13

hermosaprogramacion.com http://www.hermosaprogramacion.

com/2014/11/acceder-los-contactos-de-android/

Acceder A Los Contactos De Android Con El Contacts Provider


Este artículo ha sido creado con el fin de administrar los datos nativos de nuestros Contactos en Android a través
del componente Contacts Provider.

A lo largo del temario, aprenderás de que forma está estructurada la información entre aplicaciones.

Verás como obtener acceso a dicha información y finalmente tendrás acceso a un ejemplo completo para
consultar la información de los contactos.

¿Qué es un Content Provider?


Recuerda que cuando viste los componentes de una aplicación Android , se estudió el concepto de Content
Provider (“Proveedor de Contenido”). Se había dicho que es un mecanismo de almacenamiento de datos, usado
para compartir información persistente entre procesos de forma aislada. Esto permite al programador dotar de un
buen nivel de seguridad en las bases de datos de sus aplicaciones.

En Android existen varios Content Providers predeterminados cuyo propósito es intercambiar información entre
sus aplicaciones nativas. El mas común es el Contacts Provider, el cual permite obtener los datos de la
aplicación de contactos de nuestro teléfono. No obstante, existen diferentes tipos para compartir imágenes,
audio, video, etc.

Acceder a los datos de un ContentProvider


Para acceder a los datos soportados por un Content Provider se debe usar un componente llamado
ContentResolver (“Resolutor de Contenido”).

Un Content Resolver es un objeto que permite consultar, insertar, eliminar y modificar los datos de un Content
Provider.

Debido a que varias aplicaciones pueden acceder a un mismo Content Provider a la vez, el Content resolver
gestiona por nosotros una petición estilo cliente hacia la instancia de la aplicación proveedora, para obtener la
información.

Para acceder a los dato de un ContentProvider debes asigna un permiso tu aplicación. Esto se hace añadiendo
un elemento <uses-permission> a tu AndroidManifest.xml con la orden correspondiente según como haya sido
construido el provider.

Al igual que cuando usábamos la clase SQLiteDataBase con bases de datos en SQLite , un ContentResolver te
permite implementar métodos query(), insert(), update() y delete() para operar los tados del ContentProvider.

Por ejemplo…

Si deseas consultar los registros de tus contactos telefónicos, lo primero que debes hacer es obtener el Content
Resolver asociado a tu aplicación con el método getContentResolver().

Luego de ello puedes emplear el método query() especificando el ContentProvider a consultar, el nombre de las
columnas, la condición y argumentos de la sentencia WHERE y hasta la forma en que se ordenarán los
resultados finales.

contactsCursor = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, // URI de contenido para los contactos
projection, // Columnas a seleccionar
selectionClause // Condición del WHERE
selectionArgs, // Valores de la condición
sortOrder); // ORDER BY columna [ASC|DESC]

El primer parámetro hace referencia al nombre de la tabla que vamos a consultar dentro del ContentProvider de
los contactos, cuyo tipo es Uri.

Pero…¿Por qué usar una URI para especificar el nombre de la tabla?…y…¿Qué es ContactsContract?

Usando URIs de contenido


Las URIs de contenido le indican a los Content Resolvers en que Content Provider debe buscar una tabla
determinada, a través de esquema “content://”. Por ejemplo, la URI de contenido de la anterior consulta se ve de
esta forma:

content://com.android.contacts/contacts

Normalmente la estructura de una URI de contenido está dividida en tres partes significativas como se ve en el
siguiente ejemplo:

Esquema: La cadena “content://” es una constante para establecer que el origen de datos vendrá de un
Content Provider.
autoridad: Es una cadena única que identifica al Content Provider para su uso. Cuando creas tus propios
Content Providers normalmente se recomienda usar el nombre del paquete al que pertenece para
diferenciarlos de los demas.
ruta: Es un conjunto de segmentos separados por barras oblicuas (‘/’) que guían al Content Resolver
hacia la ubicación lógica de los datos dentro del Content Provider.
id: Identificador numérico (en la mayoría de los casos es la llave primaria) asociado a un solo registro que
se encuentra en la ruta establecida del Content Provider. Es muy útil cuando deseamos acceder a una
sola fila.

Como ves, el uso de URIs de contenido te facilita todo el trabajo a la hora de acceder a la información de otras
aplicaciones, evitándonos el desarrollo de mecanismos complejos.

Esta es la razón por la cual se le denomina Resolutor de Contenido a este objeto, ya que es el encargado de
parsear la URI y darse a la búsqueda de la información. ¡Una grandiosa labor!

Pero de nada nos serviría esta información si no conocemos la forma en que están estructuradas las bases de
datos de los contactos. Por esta razón es importante comprender el siguiente tema.

¿Cuál es la utilidad del Contacts Provider en Android?


Construir el esquema de una base de datos es de suma importancia para acceder a la información de forma
significativa. En nuestra caso, deseamos saber como están organizados los datos de la aplicación de contacto en
Android.

Este esquema esta definido a través de un componente llamado Contacts Provider, el cual es un Content
Provider que alberga toda la información de las personas que tenemos guardadas en nuestro dispositivo.

El Contacts Provider utiliza la clase ContactsContract para definir las constantes que modelan la base de datos
de los contactos. Podría llegar a pensarse que esta clase contiene solo la definición de una sola tabla con todos
los datos, pero no es así. Muchos programadores se confunden debido a que la información de una sola persona
esta fragmentada en un modelo de tres capas.

Veamos un pequeño diagrama:

La anterior ilustración te indica que los datos de un contacto esta distribuida en tres tablas con un propósito
distinto. Veamos de que se trata:

Contacts: Dentro de esta tabla están definidas las constantes necesarias para representar los datos una
persona basados en diferentes cuentas.
RawContacts: Aquí se añaden los datos asociados de un contacto con una cuenta de algún servicio.
Data: Almacena información mucho mas detallada del contacto como direcciones de email, teléfonos,
direcciones, campos personalizados, etc.

Las relaciones entre las tres tablas se basan en una cardinalidad 1:N. Donde un contacto puede tener una o mas
cuentas de servicios. Y a su vez, cada cuenta puede tener asociada uno o mas tipos de datos.

Consultar los datos de un Contacto en Android


Antes de consultar los datos de los contactos, es necesario que agregues el siguiente permiso a tu aplicación:

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

Supongo que intuyes que para obtener los datos mas relevantes de un contacto te debes enfocar en la tabla
ContactsContract.Data. Así que solo debes encontrar el nombre de las columnas que vas a consultar y listo.

Pero existe una característica un poco confusa. La tabla Data almacena información de distinta naturaleza. Es
decir, puede tener un registro almacene el teléfono del contacto y otra que almacene el nombre del contacto.

Esta rara particularidad es posible gracias a un conjunto de 15 columnas genéricas que guardan cualquier tipo
de información. Observa una simplificación personalizada de como se vería la tabla Data con algunos datos de
ejemplo:

_ID MYMETYPE DATA1 DATA2 … DATA15

1 NOMBRE Carlos Jimenez Mr. – –


2 TELEFONO 3294831 DOMICILIO – –

3 EMAIL carlangas@mail.com TRABAJO – –

La tabla anterior no es un fiel reflejo del verdadero aspecto de Data, pero es un buen ejemplo para comprender
su esencia. Si te fijas, existe un identificador (_ID) que diferecia cada fila, también está el tipo de registro
(MYMETYPE) de la fila y luego sigue un conjunto de 15 filas genéricas con los datos específicos.

A simple vista se nota que los registros no son homogéneos, porque es una tabla que almacena información
variada en las columnas. Por ejemplo, el registro tipo NOMBRE guarda el nombre del contacto en DATA1, pero
el registro tipo EMAIL guarda la dirección de correo electrónico en esa misma columna.

Tu te preguntarás como hacer para manejar esta extraña manera de almacenamiento de datos, ¿no es cierto?,
pues veamos la respuesta.

Recuerda que antes de ejecutar una consulta con el método query(), debemos construir la sentencia SQL. Así
que lo primero es identificar cuales son las columnas a consultar. Pero, debido a que no todos los tipos de
registros asociados a un contacto usan la misma cantidad de datos para representar la información, entonces te
ves en la obligación de consultar las 15 columnas:

String projection =
{
Data._ID,
Data.MIMETYPE,
Data.DATA1,
Data.DATA2,
Data.DATA3,
Data.DATA4,
Data.DATA5,
Data.DATA6,
Data.DATA7,
Data.DATA8,
Data.DATA9,
Data.DATA10,
Data.DATA11,
Data.DATA12,
Data.DATA13,
Data.DATA14,
Data.DATA15
};

Luego debemos especificar de qué usuario vamos a consultar dicha información. Eso se logra condicionando
con un WHERE los registros, de tal forma que elijamos solo los registros relacionados a el identificador del
contacto deseado.

String selectionClause = Contacts.LOOKUP_KEY+" = ? ";


String selectionArgs[] = new String[]{ contactId };

Aunque la tabla Contacts tiene una llave primaria llamada _ID, la columna Contacts.LOOKUP_KEY también
puede usarse como llave primaria. La diferencia está en que LOOKUP_KEY permite hallar el contacto incluso si
se modifica en tiempo real como consecuencia de una agregación o sincronización de productos Google.

Se usa el placeholder ‘?’ para generalizar la sentencia y reemplazarlo luego por los argumentos. En este caso el
argumento se compone del valor arbitrario de una variable hipotética llamada contactId.

Y luego si deseas puedes establecer la forma en que se ordenarán los registros.


Veamos un ejemplo de como organizarlos por tipo:

String sortOrder = Data.MIMETYPE;

Finalmente juntas todas las piezas y las empleas en la consulta junto al URI de la tabla Data:

contactsCursor = getContentResolver().query(
ContactsContract.Data.CONTENT_URI,
projection,
selectionClause
selectionArgs,
sortOrder);

Consultas al Contacts Provider con la clase CommonDataKinds

Existe una forma mucho mas cómoda de elegir las columnas del Contacts Provider que deseamos consultar. Se
trata de la clase ContactsContract.CommonDataKinds. Esta clase te provee varias clases anidadas que asignan
un alias a las columnas de cada tipo de registro.

Por ejemplo, si quieres referirte solo al nombre de tu contacto, entonces usas el alias DISPLAY_NAME de la
clase CommonDataKinds.StructuredName o si deseas saber el email usas ADDRESS de
CommonDataKinds.Email. Ambas columnas representan el DATA1 de un registro tipo nombre y tipo email.

Usar estas clases te facilita la escritura y compresión de las consultas a realizar sobre la tabla Data ( Aprender
más sobre la clase CommonDataKinds).

Veamos un ejemplo para consultar el nombre y el teléfono de los contactos. Lo primero es crear la proyección de
aquellas columnas que vamos a necesitar:

String[] projection =
{
Phone._ID,
Phone.NUMBER
};

Ahora se deben establecer los criterios de selección para buscar solo aquellos registros telefónicos. Para ello
realizamos una comparación entre MIMETYPE y la constante CONTENT_ITEM_TYPE de Phone que representa
un registro con datos telefónicos.

String selectionClause =
Data.LOOKUP_KEY + " = ?" +
" AND " +
Data.MIMETYPE + " = " +
"'" + Phone.CONTENT_ITEM_TYPE + "'";

String[] selectionArgs = { contactId };

La clase Data tiene un acceso a la columna LOOKUP_KEY de la tabla Contacts. Esto se debe a que las
consultas de información requieren joins para obtener los datos correctos, por lo que ContactsContract
implementa todas estas operaciones de forma implícita y así ahorrar al programador el cruce entre tablas.

Finalmente implementas un tipo de orden, en este caso es descendente:

String sortOrder = Phone.TYPE + " DESC ";

Aunque la clase CommonDataKinds nos provee sobrenombres para las columnas, consultar tipos mezclados es
confuso. Es preferible consultar cada tipo de información individualmente, es decir, si deseas manipular los datos
del nombre y del email, entonces primero haz una selección individual para los datos del nombre y luego realiza
otra para los del email.

Insertar datos de un Contacto


Para insertar un contacto usaremos el método insert() de ContentResolver. Primero crea un contenedor de
valores estructurados y luego añade los valores relacionados a los nombres de las columnas de la tabla Data. A
continuación se muestra un ejemplo de inserción de un email:

ContentValues values = new ContentValues();


values.put(Data.RAW_CONTACT_ID, rawContactId);
values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
values.put(Email.ADDRESS, "carlangas@mail.com");
values.put(Email.TYPE, Phone.TYPE_PHONE);
Uri uri = getContentResolver().insert(Data.CONTENT_URI, values);

Es importante referenciar la inserción a través de la URI de contenido de la tabla Data y además consultar
previamente el identificador (Data.RAW_CONTACT_ID) de aquella cuenta del contacto en la que se insertará el
email.

Si en algún momento deseas insertar, modificar o eliminar varios registros al tiempo emplea la clase
ContentProviderOperation. Esta clase permite abrir transacciones para procesos largos junto al método
applyBatch() de ContentResolver.

El uso de este mecanismo aumenta la velocidad de la operación y ademas mantiene la consistencia de datos
evitando la perdida de información (ver Propiedades de una transacción ).

Veamos un ejemplo de inserción:

ArrayList<ContentProviderOperation> ops =
new ArrayList<ContentProviderOperation>();

ops.add(ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValue(Data.RAW_CONTACT_ID, rawContactId)
.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE)
.withValue(Email.ADDRESS, "carlangas@mail.com")
.withValue(Phone.TYPE, Phone.TYPE_HOME)
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

La manera de crear la operación es muy parecida a el método insert(). Con el método newInsert() se le indica al
ContentProviderOperation que se creará una inserción. Luego añades al espacio los valores con sus respectivas
claves a través del método withValue().

Lo siguiente es hacer efectiva la sentencia con el método build() y finalmente ejecutas el método applyBatch()
para iniciar la transacción. applyBatch() recibe la autoridad del ContentProvider a modificar y una instancia de la
operación.

Modificar datos un Contacto


Aunque podemos emplear el método update(), es preferible seguir realizando las operaciones con la clase
ContentProviderOperation. Por lo que debes emplear el método newUpdate(), el cual recibe los valores nuevos
relacionados con la clave y las características condicionales de la sentencia WHERE, para modificar los registros
necesarios.

Por ejemplo, si quisiéramos cambiar el nombre de un contacto haríamos lo siguiente:


ArrayList<ContentProviderOperation> ops =
new ArrayList<ContentProviderOperation>();

ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
.withSelection(Data._ID + "=?", new String[]{String.valueOf(rowId)})
.withValue(StructuredName.DISPLAY_NAME, "Roberto gonzales")
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

Usa el método withSelection() para implementar la condición, donde el primer valor es la clausula y el segundo
son los argumentos a reemplazar. El ejemplo muestra que se modificarán la fila cuyo atributo _ID sea igual al
valor de la variable rowId.

Eliminar datos de un Contacto


Eliminar un contacto es muy parecido a modificarlo, solo que esta vez no establecemos valores, si no que
especificamos el identificador de aquella fila a descartar del Contacts Provider. Usa el método newDelete()
acompañado de withSelection():

ArrayList<ContentProviderOperation> ops =
new ArrayList<ContentProviderOperation>();

ops.add(ContentProviderOperation.newDelete(Data.CONTENT_URI)
.withSelection(Data._ID + "=?", new String[]{String.valueOf(rowId)})
.build());
getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);

Ejemplo: Enviar un Mensaje de Texto a un Contacto


En esta sección veremos como se construye una aplicación que envíe un Mensaje de texto a un contacto en
Android. La idea es utilizar lo aprendido a lo largo del articulo para solucionar los requerimientos. La siguiente es
una imagen que muestra el funcionamiento de la aplicación, a la cual se le denominó “ReportMe”:

ReportMe tiene un sola actividad principal denominada Main. Su


diseño es sencillo, tiene dos TextViews para mostrar el nombre y
teléfono móvil del contacto. Ademas un ImageView que proyecta la
foto del contacto, si es que tiene una.

Puedes decargar el proyecto completo desde aquí:

Descargar Código

Apóyanos con una señal en tu red social favorita y consigue el


código completo.

Me gusta
Tweet
+1 Google

La selección del contacto se realiza a través del botón “Seleccionar


Contacto”, el cual inicia la aplicación Contactos para la respectiva
selección. Una vez seleccionado, con el botón “Enviar”, enviamos el
siguiente mensaje de texto: “Estamos aprendiendo a Desarrollar en
Android” al número móvil del contacto.

Comencemos por comprender como se inicia la actividad de la


aplicación Contactos.

Usar un Intent para seleccionar Contactos de Android

Si recuerdas el tutorial sobre Intents en Android , tendrás claro que a través de ellos podemos iniciar actividades
de aplicaciones externas. De momento necesitamos iniciar la actividad de selección de la aplicación contactos. Y
que al ser seleccionado un contacto, se obtenga la información de dicho contacto para procesarla en ReportMe.

Toda esto debe suceder cuando presiones el botón “Seleccionar Contacto”, por lo que se debe implementar un
método para el procesamiento de la escucha de clics. Como bien sabes, esto se hace con la interfaz
OnClickListener y sobrescribiendo el método callback onClick(). Pero esta vez seremos más prácticos.

Usaremos el atributo android:onClick para el botón selectionButton . Su función es relacionar al View con un
método que se ejecutará cuando este sea presionado. Esta propiedad te permite ahorrarte la implementación de
la escucha y evitar complicaciones.

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Seleccionar Contacto"
android:id="@+id/selectionButton"
<strong>android:onClick="initPickContacts"</strong>
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp" />

android:onClick tiene asignado un método llamado initPickContacts() para la escucha de clicks. Para que
funcione como se desea, el método debe recibir un parámetro de tipo View y así recibir la instancia del botón
seleccionado.

Dentro de initPickContacts() crearemos un Intent explícito a través de la URI de contenido de la tabla


ContactsContract.Contacts. El objetivo es enviar una acción de tipo ACTION_PICK, para que posibilite iniciar la
actividad de selección de contactos. Luego con la creación del Intent ejecutaremos la actividad con la espera del
resultado de vuelta a través del método startActivityForResult():

public void initPickContacts(View v){


/*
Crear un intent para seleccionar un contacto del dispositivo
*/
Intent i = new Intent(Intent.ACTION_PICK,
ContactsContract.Contacts.CONTENT_URI);

/*
Iniciar la actividad esperando respuesta a través
del canal PICK_CONTACT_REQUEST
*/
startActivityForResult(i, PICK_CONTACT_REQUEST);
}

El siguiente paso es extraer los datos del intent de respuesta dentro del método onActivityResult(), luego de que
sea seleccionado el contacto. Para ello usaremos el método getData() del intent de respuesta. Este método
retorna en la URI de contenido específica para el contacto seleccionado, por lo que tendría una forma como esta:

content://com.android.contacts/contacts/lookup/0r1-39273F2F4B492F512F3D43/1

La anterior Uri te provee la LOOKUP_KEY relacionada al _ID del contacto. Evita perder este valor en el método y
almacenalo en una variable global de tipo Uri:

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


if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
/*
Capturar el valor de la Uri
*/
contactUri = intent.getData();
<strong>/*
Procesar la Uri
*/
renderContact(contactUri);</strong>
}
}
}

El método renderContact() que ves en el código anterior es el encargado de procesar la URI de contenido y
asignar el nombre, el teléfono y la foto a cada view de la actividad Main. Su definición se muestra a continuación:

private void renderContact(Uri uri) {

TextView contactName = (TextView)findViewById(R.id.contactName);


TextView contactPhone = (TextView)findViewById(R.id.contactPhone);
ImageView contactPic = (ImageView)findViewById(R.id.contactPic);

contactName.setText(<strong>getName(uri)</strong>);
contactPhone.setText(<strong>getPhone(uri)</strong>);
contactPic.setImageBitmap(<strong>getPic(uri)</strong>);
}

Ahora solo queda resolver la obtención del nombre, el teléfono y la foto del contacto con los conocimientos que
ya has aprendido en este artículo.

Obtener el nombre de un Contacto

La obtención del nombre se realiza a través de getName(). Este método recibe como parámetro la URI de
contenido que nos entregó la actividad de selección en los contactos. El propósito es consultar la tabla Contacts
el Contacts Provider y obtener el nombre del contacto, que es representado por la columna DISPLAY_NAME:

private String getName(Uri uri) {

/*
Valor a retornar
*/
String name = null;

/*
Obtener una instancia del Content Resolver
*/
ContentResolver contentResolver = getContentResolver();

/*
Cursor para recorrer los datos de la consulta
*/
Cursor c = contentResolver.query(
uri, Contacts.DISPLAY_NAME, null, null, null);

/*
Consultando el primer y único resultado elegido
*/
if(c.moveToFirst()){
name = c.getString(0);
}

/*
Cerramos el cursor
*/
c.close();

return name;
}

Al usar query() para consultar la URI de contenido, el cursor ( Aprende más sobre cursores) resultante tendrá
acceso a solo un registro particular, por lo que empleamos el método moveToFirst() para situarnos sobre él. En
seguida usamos getString() y obtenemos el nombre del contacto para retornarlo.

Es posible consultar el nombre a través de la clase CommonDataKinds.StructuredName, pero como resulta un


proceso mucho más interno, es mejor opción consultar DISPLAY_NAME de la tabla Contacts, ya que también
guarda una instancia simple del nombre.

Obtener el teléfono de un Contacto

El método getPhone() retorna el teléfono móvil del contacto. A diferencia del nombre, la tabla Contacts no trae
una instancia rápida del teléfono, por lo que es necesario realizar un JOIN implícito.

Lo primero que se realiza es una consulta del identificador del contacto retornado. Luego se consulta el teléfono
a través de CommonDataKinds.Phone, usando una condición para solo obtener la fila precisa del contacto
seleccionado. Además de ello debemos asegurarnos que el numero telefónico es de un móvil (TYPE_MOBILE):

private String getPhone(Uri uri) {


/*
Variables temporales para el id y el teléfono
*/
String id = null;
String phone = null;

/************* PRIMERA CONSULTA ************/


/*
Obtener el _ID del contacto
*/
Cursor contactCursor = getContentResolver().query(
uri, new String[]{ContactsContract.Contacts._ID},
null, null, null);

if (contactCursor.moveToFirst()) {
id = contactCursor.getString(0);
}
contactCursor.close();
/************* SEGUNDA CONSULTA ************/
/*
Sentencia WHERE para especificar que solo deseamos
números de telefonía móvil
*/
String selectionArgs =
Phone.CONTACT_ID + " = ? AND " +
Phone.TYPE+"= " +
Phone.TYPE_MOBILE;

/*
Obtener el número telefónico
*/
Cursor phoneCursor = getContentResolver().query(
Phone.CONTENT_URI,
new String[] { Phone.NUMBER },
selectionArgs
,
new String[] { id },
null
);
if (phoneCursor.moveToFirst()) {
phone = phoneCursor.getString(0);
}
phoneCursor.close();

return phone;
}

Obtener la foto de un Contacto

Y finalmente se obtiene la miniatura que tiene el contacto asignada. Este proceso se puede realizar de varias
formas alternas debido a la riqueza del esquema del Contacts Provider. Una de las formas es usar la clase
interna CommonDataKinds.Photo para obtener la secuencia de bytes que representa la foto a través de una
doble consulta.

Otra forma es usar una clase llamada ContactsContract.Contacts.Photo. Esta clase representa un subdirectorio
cuyo fin es guardar datos de la foto. Lo primero que debes hacer es obtener el identificador del contacto y luego
crear una URI que represente el origen de la imagen a través del directorio (Ver más sobre este forma de
obtener la foto de un contacto).

En nuestro caso usaremos otro camino. Para ello usaremos el método openContactPhotoInputStream() de la
clase Contacts, el cual obtiene los datos de la foto del contacto con el CONTENT_URI concatenado a su
identificador. Observa:

private Bitmap getPhoto(Uri uri) {


/*
Foto del contacto y su id
*/
Bitmap photo = null;
String id = null;

/************* CONSULTA ************/


Cursor contactCursor = getContentResolver().query(
uri, new String[]{ContactsContract.Contacts._ID}, null, null,
null);

if (contactCursor.moveToFirst()) {
id = contactCursor.getString(0);
}
contactCursor.close();

/*
Usar el método de clase openContactPhotoInputStream()
*/
try {
InputStream input =
ContactsContract.Contacts.openContactPhotoInputStream(
getContentResolver(),
ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
Long.parseLong(id))
);
if (input != null) {
/*
Dar formato tipo Bitmap a los bytes del BLOB
correspondiente a la foto
*/
photo = BitmapFactory.decodeStream(input);
input.close();
}

} catch (IOException iox) { /* Manejo de errores */ }

return photo;
}

El método openContactPhotoInputStream() retorna en una secuencia de bytes, así que lo guardamos en una
nueva instancia InputStream. Este método recibe la instancia del ContentResolver de la actividad y la URI de
contenido concatenada al identificador del contacto. Para concatenar usa el método estático withAppendedId()
de la clase auxiliar ContentUris.

Luego das formato de Bitmap al BLOB que representa la foto. Para ello usa el método decodeStream() de la
clase auxiliar BitmapFactory.

Enviar mensajes de texto con MsgManager

El MsgManager es un componente que nos permitirá enviar texto hacia otro teléfono móvil. Para acceder a él
debes usar el método estático getDefault():

/*
Creando nuestro gestor de mensajes
*/
SmsManager smsManager = SmsManager.getDefault();

Luego usas el método sendTextMessage() junto a la URI de contenido del teléfono del contacto y la cadena que
representa al mensaje:

/*
Enviando el mensaje
*/
smsManager.sendTextMessage(
getPhone(contactUri),
null,
"¡Estamos aprendiendo a Desarrollar en Android!",
null,
null);

Ahora habilita el envío con el siguiente permiso:

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

Finalmente juntamos estas instrucciones en un método llamado sendMessage() y se lo asignamos al botón de


envío sendButton a traves del archivo de diseño:

public void sendMessage(View v){

/*
Creando nuestro gestor de mensajes
*/
SmsManager smsManager = SmsManager.getDefault();

/*
Enviando el mensaje
*/
smsManager.sendTextMessage(
getPhone(contactUri),
null,
"¡Estamos aprendiendo a Desarrollar en Android!",
null,
null);

Toast.makeText(this, "Mensaje Enviado", Toast.LENGTH_LONG).show();

Y finalmente modifica la propiedad onClick del botón de envío:

android:onClick="sendMessage"

Das könnte Ihnen auch gefallen