3

I am a little bit confuse about the how to use Data.HAS_PHONE_NUMBER. I have inserted contacts along with some additional Data and I would like to retrieve some of those contacts.

If I'm running the following code eveything is fine:

Uri uri = Data.CONTENT_URI;
String[] projection = new String[]{Data.CONTACT_ID, Data.DISPLAY_NAME };
String selection = Data.DATA4+" = ?";
String[] selectionArgs = new String[] {MY_VALUE};


Cursor truContactCursor = mContext.getContentResolver().query(uri, projection, selection, selectionArgs, null);

Now, I would like to know if those contacts have a phone number so I added HAS_PHONE_NUMBER into the projection like this:

String[] projection = new String[]{Data.CONTACT_ID, Data.DISPLAY_NAME, Data.HAS_PHONE_NUMBER };

When running the query I got the following execption:

java.lang.IllegalArgumentException: Invalid column has_phone_number

Why can I not access to HAS_PHONE_NUMBER? There is no problem with Data.DISPLAY_NAME which is in the same table. How are we suppose to use Data.HAS_PHONE_NUMBER then?

Thanks for your answer

om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
JimBoy
  • 106
  • 1
  • 4

3 Answers3

0

Add "Data.MIMETYPE=ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE" to the selection statement.

The result cursor will include only the rows which have a phone number.

Tip. There is the case: several numbers in one contact. If you want all the numbers to be queried, add "ContactsContract.Data.DATA1" (Which means phone number) to the projection statement.

0

I encountered this same problem, and the only other reference to the problem I have found is another stackoverflow question.

I am planning on writing my own ContentProvider to do the "join" through programmatic means. That is, do the original query against the Data.CONTENT_URI but without the Data.HAS_PHONE_NUMBER projection, and then requery the given contact for the actual value of Data.HAS_PHONE_NUMBER. This surely lacks the performance of an actual DB join (being an n+1-type of select), but will provide the desired/expected functionality. This extra processing could be made conditional upon the OS level in order to maintain the efficiency on correctly functioning OS versions.

Given yulistic's answer above and my own experience, it would appear to be a bug in some versions of Android that this implicit join is not done. My Android v2.3.7 phone crashes with the same error you receive when Data.HAS_PHONE_NUMBER is in the projection, whereas my Android v4.2.2 tablet does not crash.

I have entered an Android Bug against the issue: https://code.google.com/p/android/issues/detail?id=54095

Rob

Community
  • 1
  • 1
0

Use HAS_PHONE_NUMBER is used for checking whether an contact has at least one phone number.example:

ContentResolver cr = getContentResolver();  
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if(cursor.getCount()>0){
while (cursor.moveToNext()) {
String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));id
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
if(cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))>0){
//Query phone here. 
}

or add in projection:

String [] projection = {ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.HAS_PHONE_NUMBER}; 
ρяσѕρєя K
  • 132,198
  • 53
  • 198
  • 213
  • Thanks for you answer. Yes I understand that I can use Contacts.HAS_PHONE_NUMBER from Contacts.CONTENT_URI. My question was how to use Data.HAS_PHONE_NUMBER with Data.CONTENT_URI. If we are not suppose to access Data.HAS_PHONE_NUMBER from the Data table then this constante should not exist. And there is clearly an implicit join between Data and Contacts because I can access to Data.DISPLAY_NAME. So why can I not access to Data.HAS_PHONE_NUMBER when Data.DISPLAY_NAME is fine. – JimBoy Mar 16 '12 at 11:12