Asif Shiraz
Asif Shiraz

Reputation: 874

Where is address field in android ContactsContract

I'm trying to retrieve the address of a contact using the activity's content resolver. There is no Address field anywhere. I tried ContactsContract.CommonDataKinds.StructuredPostal.STREET but it also gives me a different value. Please see the screen shot of how the field looks like in android which I'm trying to retrieve.

In my code below, I'm iterating through all values in the CONTENT_URI for 'John Doe', but this address, "Slaughter Lane" never shows up i.e. my breakpoint at the Timber log command 'Found the address' is never hit.

fun getContact(activity: FragmentActivity, name: String): Contact? {
    var contact = Contact()
    val cr : ContentResolver = activity.contentResolver
    var selectionArgs: Array<String> = arrayOf("John Doe")
    val cursor = cr.query(
        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
        null,
        "DISPLAY_NAME = ?",
        selectionArgs,
        ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC"
    )
    if (cursor != null) {
        try {
            while (cursor.moveToNext()) {
                cursor.columnNames.forEach {
                    var stringValue: String? = cursor.getString(cursor.getColumnIndex(it))
                    if (stringValue!=null) {
                        if (stringValue.contains("Slaughter")){
                            Timber.i("Found the address");
                        }
                    }
                }
            }
        } finally {
            cursor.close()
        }
    }
    return if (contact.name != null) contact else null
}

screen shot

Upvotes: 2

Views: 574

Answers (2)

Alireza Lorestani
Alireza Lorestani

Reputation: 153

fun getAddress(rawContactId: Long): String? {
        val contentResolver = context.contentResolver
        val projection: Array<out String> = arrayOf(
            ContactsContract.Data.CONTACT_ID,
            ContactsContract.Data.MIMETYPE,
            ContactsContract.Data.DATA1,
            ContactsContract.Data.DATA2,
        )
        val selection = "${ContactsContract.Data.CONTACT_ID} = ?"
        val selectionArgs: Array<String> = arrayOf("")
        selectionArgs[0] = rawContactId.toString()
        val cursor = contentResolver.query(
            ContactsContract.Data.CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            null
        )
        var address: String? = null

        cursor?.apply {
            while (moveToNext()) {
                if (rawContactId == getLong(getColumnIndex(ContactsContract.Data.CONTACT_ID))) {
                    val mimeType: String = getString(getColumnIndex(ContactsContract.Data.MIMETYPE))
                    if (mimeType == ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
                        address = getString(getColumnIndex(ContactsContract.Data.DATA1))

                }
            }
        }
        cursor?.close()

        return address
    }

Upvotes: 1

marmor
marmor

Reputation: 28199

The code you posted doesn't show how you're trying to access StructuredPostal.STREET, but I think I understand how you tried to do it.

When you query over Phone.CONTENT_URI you will only receive general contact info (such as Data.CONTACT_ID and Data.DISPLAY_NAME) plus phone specific columns (such as Phone.NUMBER), because each row will be of mimetype Phone.CONTENT_ITEM_TYPE.

You can't get address info from that query.

If you need multiple types of information (like phone AND address), you need to query over the more generic Data.CONTENT_URI uri, and then use the Data.MIMETYPE to figure out what type of row is this, phone, address, or something else... you can limit the types of rows you receive by adding a selection over Data.MIMETYPE.

Here's example code (in java):

String[] projection = {Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1, Data.DATA2, Data.DATA3};

// query only phones and addresses
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "', '" + StructuredPostal.CONTENT_ITEM_TYPE + "')";
ContentResolver cr = getContentResolver();
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);

while (cur != null && cur.moveToNext()) {
    long id = cur.getLong(0);
    String name = cur.getString(1); // full name
    String mime = cur.getString(2); // type of data (phone / address)
    String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234

    String kind = "unknown";

    switch (mime) {
        case Phone.CONTENT_ITEM_TYPE: 
            kind = "phone"; 
            break;
        case StructuredPostal.CONTENT_ITEM_TYPE: 
            kind = "address";
            break;
    }
    Log.d(TAG, "got " + id + ", " + name + ", " + kind + " - " + data);
}
cur.close();

you may get multiple phones and addresses for the same contact, so if you need it per contact you should add a HashMap from id to the data you need.

Upvotes: 0

Related Questions