1

I'm making this on my own with help from the interwebs and a lot of reference to a few books. The code below pulls a specific contact's name and phone number and it works (sweet). My question is about the selection and selectionArgs. How do I add in a query for email?

I don't understand all the equal signs and the AND withing quotations, so if you can point me to where I can learn more about the language used in 'selection' rather than just giving me the answer in code, that'd also help me tremendously.

Thanks in advance

import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.TextView;

/**
 * Created by Pete on 6/19/13.
 */
public class ContactDetails extends Activity {

    TextView tvContactName, tvPhoneNum, tvPhoneType, tvPhoneFull,
            tvEmailAdd, tvEmailType, tvEmailFull,
            tvAddress, tvAddType, tvAddFull;

    String contactId, contactName, phoneType, phoneFull, phoneNum1,
            emailAdd, emailType, emailFull,
            address, addType, addFull;    

    //Contact List query arguments
    Uri uri;
    String[] projection, selectionArgs;
    String selection, sortOrder;

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

        contactId = getIntent().getStringExtra("contactId");
        contactName = getIntent().getStringExtra("contactName");

        queryArgs();

        // Create cursor searching for data associated with contactId
        if (contactId != null) {
            // Return all the PHONE data for the contact            
            Cursor cursor = getContentResolver().query(
                    uri, projection, selection, selectionArgs, sortOrder);

            //Get the indexes of the required columns           
            while (cursor.moveToNext()) {
                // Extract the name
                contactName = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
                tvContactName.setText(contactName);
                // Extract the phone number
                phoneFull = cursor.getString(
                        cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                tvPhoneFull.setText(phoneFull);
            }
            cursor.close();
        }        
    }

    public void initialize() {
        tvContactName = (TextView)findViewById(R.id.tvContactName);
        tvPhoneNum = (TextView)findViewById(R.id.tvPhoneNum);
        tvPhoneType = (TextView)findViewById(R.id.tvPhoneType);
        tvPhoneFull = (TextView)findViewById(R.id.tvPhoneFull);
        tvEmailAdd = (TextView)findViewById(R.id.tvEmailAdd);
        tvEmailType = (TextView)findViewById(R.id.tvEmailType);
        tvEmailFull = (TextView)findViewById(R.id.tvEmailFull);
        tvAddress = (TextView)findViewById(R.id.tvAddress);
        tvAddType = (TextView)findViewById(R.id.tvAddType);
        tvAddFull = (TextView)findViewById(R.id.tvAddFull);
    }

    public void queryArgs() {
        // Cursor query arguments
        uri = ContactsContract.Data.CONTENT_URI;
        projection = new String[] {
                ContactsContract.Data.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER
        };
        selection = ContactsContract.Data.CONTACT_ID + " = " + contactId + " AND " + 
                    ContactsContract.Data.MIMETYPE + " = " + 
                    ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'";
        selectionArgs = null;;
        sortOrder = null;
    }

    public void setTextValues() {
        tvContactName.setText(contactName);
        tvPhoneNum.setText(phoneNum1);
        tvPhoneType.setText(phoneType);
        tvPhoneFull.setText(phoneFull);
        tvEmailAdd.setText(emailAdd);
        tvEmailType.setText(emailType);
        tvEmailFull.setText(emailFull);
        tvAddress.setText(address);
        tvAddType.setText(addType);
        tvAddFull.setText(addFull);
    }
}

edit: I tried out Sandy09's idea (minus what I believe is a typo after cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

Now I'm getting this error, and when I recopy my code, I get it still (minus the thread reference). All help is appreciated:

06-22 04:45:56.316: E/AndroidRuntime(8818): FATAL EXCEPTION: Thread-273
06-22 04:45:56.316: E/AndroidRuntime(8818): android.database.sqlite.SQLiteException: unrecognized token: "'vnd.android.cursor.item/phone_v2))" (code 1): , while compiling: SELECT DISTINCT display_name, data1 FROM view_data data WHERE (1) AND ((contact_id = 1 AND mimetype = 'vnd.android.cursor.item/phone_v2))
06-22 04:45:56.316: E/AndroidRuntime(8818):     at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:181)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:137)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at android.content.ContentProviderProxy.query(ContentProviderNative.java:366)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at android.content.ContentResolver.query(ContentResolver.java:372)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at android.content.ContentResolver.query(ContentResolver.java:315)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at sat.tuts4mobile.customlistview.ContactDetails$1.run(ContactDetails.java:42)
06-22 04:45:56.316: E/AndroidRuntime(8818):     at java.lang.Thread.run(Thread.java:856)
Psest328
  • 6,575
  • 11
  • 55
  • 90
  • The language used in the where clause leans heavily on SQL. I don't think the ContentProvider supports much more than `AND` and `OR` though. – 323go Jun 22 '13 at 04:35
  • I was hoping that was the case, but when I tried: ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + " AND " + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + "'"; I ended up getting nothing, so I know there's more to it – Psest328 Jun 22 '13 at 04:43
  • Oh, I see your problem now. The query you wrote is incorrect. I'll post a corrected one in answer. – 323go Jun 22 '13 at 04:52

2 Answers2

1

Android prefer to run the data-base operations on new thread(task) to avoid the ANR dialog, write your query on new thread,

For email you can refer this. for all providers go through android doc.

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    initialize();
            contactId = getIntent().getStringExtra("contactId");
            contactName = getIntent().getStringExtra("contactName");
            new Thread(new Runnable() {
                @Override
            public void run() {
            queryArgs();
            if (contactId != null) {
            Cursor cursor = getContentResolver().query(uri, projection,
                            selection, selectionArgs, sortOrder);
            while (cursor.moveToNext()) {
                    contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
                        tvContactName.setText(contactName);
                        // Extract the phone number
                        phoneFull += cursor.getString(cursor
                                .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER))
                                + " ,";
                    }

                    tvPhoneFull.post(new Runnable() {
                        @Override
                        public void run() {
                        tvPhoneFull.setText(phoneFull); 
                        }
                    });

                    cursor.close();
                }
            }
        }).start();

    }
Community
  • 1
  • 1
Sandeep P
  • 4,291
  • 2
  • 26
  • 45
1

Thanks for clarifying what you were having trouble with. So yes,

selection = ContactsContract.Data.CONTACT_ID + " = " + contactId + " AND " + 
                ContactsContract.Data.MIMETYPE + " = " + 
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "'";

selects phone numbers. Well, almost -- it's missing a ' prior to CONTENT_ITEM_TYPE.

In order to extend this, you need to add an additional check, like so:

selection = ContactsContract.Data.CONTACT_ID + " = " + contactId + " AND (" + 
                ContactsContract.Data.MIMETYPE + " = '" + 
                ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' OR " +
                ContactsContract.Data.MIMETYPE + " = '" + 
                ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE + "')";

This will translate into something like --

CONTACT_ID = 123 AND ( MIMETYPE = 'Phone' OR MIMETYPE = 'Email' )

While it's proper Android programming to use the contract classes, as you do, it does make for horrible readability and trouble-shooting.

323go
  • 14,143
  • 6
  • 33
  • 41
  • yeah, sorry. while I"m learning, I find it easier to keep everything in different compartments until I get used to it. I'm heading to bed so I'll try that out in the morning. Am I right in thinking that I also need to add to the projection:ContactsContract.CommonDataKinds.Email.ADDRESS ? – Psest328 Jun 22 '13 at 05:23
  • 1
    No reason to be sorry -- it's just normal to overlook a missing single-quote in the midst of all that mess. You're not doing anything wrong here. And yes, you'd need to extend your projection to include the columns you'd like to see. Good night! – 323go Jun 22 '13 at 05:24