March 5, 2014

How to read WhatsApp contacts in your android app using Content Providers?

Today everyone wants to make their App as much socially integrated as possible. WhatsApp is the most popular messaging app available out there in the market but unfortunately WhatsApp does not provide any APIs for the integration of other apps. But most people want to enable their apps to send messages via Whatsapp ( i.e. directly; not via implicit intents or choosers).

We all know that Whatsapp stores its contacts in the phone's contact book. Hence if the Whatsapp contacts are stored in the contact book then other apps should be able to view them. Whatsapp doesn't have its own Content Provider but because the contacts are stored in the phone then we should be able to view them with the help of ContactsContract content provider.

Now different people may have different ways of accessing the Whatsapp contacts and there may be better ways of doing what I am trying to do but here is what I did to do the same.

How Whatsapp stores contacts in android phones?

To understand how whatsapp organizes ites contacts go here.

First we will need the following permission in the AndroidManifest.xml in order to read these contacts:

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

I am showing all the Whatsapp contacts in a custom ListView with two TextViews. Touching on any item in this list view will open the chat thread for that contact.

whatsapp_list_item.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView 
        android:id="@+id/txtName"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        style="?android:attr/textAppearanceMedium" />
    
    <TextView 
        android:id="@+id/txtNumber"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content" />

</LinearLayout>

activity_whats_app_contacts.xml


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".WhatsAppContacts" >

    <ListView
        android:id="@+id/listWhatsAppContacts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

WhatsAppContacts.java


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.Activity;
import android.content.ActivityNotFoundException;
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.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class WhatsAppContacts extends Activity {

    private ArrayList<Map<String, String>> contacts;
    private ListView contactsListView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_whats_app_contacts);
        
        contactsListView = (ListView) findViewById(R.id.listWhatsAppContacts);
        
        // Create a progress bar to display while the list loads
        ProgressBar progressBar = new ProgressBar(this);
        progressBar.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT));
        progressBar.setIndeterminate(true);
        contactsListView.setEmptyView(progressBar);

        // Must add the progress bar to the root of the layout
        ViewGroup root = (ViewGroup) findViewById(android.R.id.content);
        root.addView(progressBar);
        
        String[] from = { "name" , "number" };
        int[] to = { R.id.txtName, R.id.txtNumber };
        
        contacts = fetchWhatsAppContacts();
        
        SimpleAdapter adapter = new SimpleAdapter(this, contacts, R.layout.whatsapp_list_item, from, to);
        contactsListView.setAdapter(adapter);
        
        contactsListView.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                try{
                    Uri uri = Uri.parse("smsto:"+ contacts.get(arg2).get("number").toString());
                    Intent i = new Intent(Intent.ACTION_SENDTO, uri);
                    i.setPackage("com.whatsapp");
                    startActivity(i);
                }catch (ActivityNotFoundException e) {
                    Toast.makeText(getApplicationContext(), "no whatsapp!", Toast.LENGTH_SHORT).show();
                    Log.e("Intent", e.getMessage());
                }
            }
        });
        
    }
    
    private HashMap<String, String> putData(String name, String number) {
        HashMap<String, String> item = new HashMap<String, String>();
        item.put("name", name);
        item.put("number", number);
        return item;
      }
    
    private ArrayList<Map<String, String>> fetchWhatsAppContacts(){
        
        ArrayList<Map<String, String>> list = new ArrayList<Map<String,String>>();
        
        final String[] projection={
                ContactsContract.Data.CONTACT_ID,
                ContactsContract.Data.MIMETYPE,
                "account_type",
                ContactsContract.Data.DATA3,
                };
        final String selection= ContactsContract.Data.MIMETYPE+" =? and account_type=?";
        final String[] selectionArgs = {
                "vnd.android.cursor.item/vnd.com.whatsapp.profile",
                "com.whatsapp"
                };
        ContentResolver cr = getContentResolver();
        Cursor c = cr.query(
                ContactsContract.Data.CONTENT_URI,
                projection,
                selection,
                selectionArgs,
                null);
        while(c.moveToNext()){
            String id=c.getString(c.getColumnIndex(ContactsContract.Data.CONTACT_ID));
            String number=c.getString(c.getColumnIndex(ContactsContract.Data.DATA3));
            String name="";
            Cursor mCursor=getContentResolver().query(
                    ContactsContract.Contacts.CONTENT_URI,
                    new String[]{ContactsContract.Contacts.DISPLAY_NAME},
                    ContactsContract.Contacts._ID+" =?",
                    new String[]{id},
                    null);
            while(mCursor.moveToNext()){
                name=mCursor.getString(mCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
            }
            mCursor.close();
            list.add(putData(name, number));
        }
        Log.v("WhatsApp", "Total WhatsApp Contacts: "+c.getCount());
        c.close();
        return list;
    }

}


Feel free to post your comments, queries  and suggestions. Cheers.... :)

7 comments:

  1. i want to share text using action sendto

    ReplyDelete
  2. Very nice Post .. very well guided to
    also nice post about how to read whatsup Contact

    Can you kindly post code about how one can add his own icon & contact of person like whats up add into our contact list ,
    you guided well on how but can you post code for same how exactly one can achive it .
    Like if we using contact details to send sms , or call or to send email without intent ot without chooser as whats up does by directly writing into contact. can you post code for same about how to achieve this ..

    Thanking you..

    ReplyDelete
  3. Very nice post. Thank you.
    Where did you got those whatsapp content URIs?

    ReplyDelete
  4. Is there a Way to get the photo of a Whatsapp contact using the same content provider?

    ReplyDelete
  5. How can we get WhatsApp groups and broadcast group details or names in our app through intent.

    ReplyDelete
  6. pp_list_item.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18





    <TextView
    android:id="@+id/txtNumber"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content

    ReplyDelete
  7. What's working of this project is it a kind of what's app notifier app

    ReplyDelete