Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot find Facebook contacts in RawContacts

I'm trying to build a contacts-managing application. On my phone I have contacts from a couple of accounts including Facebook and HTC Facebook. For some reason I cannot retrieve these contacts from the RawContacts table of ContactsContract:

managedQuery(ContactsContract.RawContacts.CONTENT_URI, new String[] {
    ContactsContract.RawContacts._ID,
    ContactsContract.RawContacts.CONTACT_ID,
    ContactsContract.RawContacts.ACCOUNT_NAME,
    ContactsContract.RawContacts.ACCOUNT_TYPE,
}, ContactsContract.RawContacts.ACCOUNT_TYPE + " = 'com.facebook.auth.login'", null, null)

This query returns no results. If I repace the account type with com.htc.socialnetwork.facebook, I still get no results. There are many Facebook contacts on my phone; how to retrieve them?

like image 255
Fixpoint Avatar asked May 17 '11 23:05

Fixpoint


3 Answers

I think I found the answer here: How to get a contact's facebook id or url from native contacts / content resolver?

Seems that access to Facebook contacts is restricted.

like image 199
Fixpoint Avatar answered Nov 13 '22 09:11

Fixpoint


Yes, the Facebook contacts are secured, but can be hijacked with a little sneaky SQLite Injection. NO- I am not going to post here on this page, but is there any reason you do not just use Facebook authentication and get the contacts THAT way? The Facebook contacts don't really have anything useful in them anyway, and it is just more secure and more likely to work ALL the

like image 33
roger l Avatar answered Nov 13 '22 10:11

roger l


There is definitely no way to do this in a standard way. So, we must use an SQLi injection (as roger commented) in order to be able to hack the contacts database and get the Facebook avatars. The following code works on most Motorolas, which use Motoblur, on Android 2.2 or higher:

public static Bitmap loadFacebookAvatar(Context context, long personId) {
    String[] rawProjection = {ContactsContract.RawContacts._ID};
    String contactIdAssertion = ContactsContract.RawContacts.CONTACT_ID + " = " + personId;
    String rawWhere = new StringBuilder()
            .append(contactIdAssertion).append(") UNION ALL SELECT ")
            .append(ContactsContract.RawContacts._ID).append(" FROM view_raw_contacts WHERE (")
            .append(contactIdAssertion).toString();
    Cursor query = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
            rawProjection,
            rawWhere, null, null);
    if (query != null && query.moveToFirst()) {
        do {
            long id = query.getLong(query.getColumnIndex(ContactsContract.RawContacts._ID));
            String[] projection = {ContactsContract.CommonDataKinds.Photo.PHOTO};
            Uri uri = ContactsContract.Data.CONTENT_URI;

            String mimeTypeAssertion = ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
            String photoAssertion = ContactsContract.CommonDataKinds.Photo.PHOTO + " IS NOT NULL";
            String rawContactIdAssertion = ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID + " = " + id;

            String where = new StringBuilder().append(mimeTypeAssertion).append(" AND ")
                    .append(photoAssertion).append(" AND ").append(rawContactIdAssertion)
                    .append(") UNION ALL SELECT ").append(ContactsContract.CommonDataKinds.Photo.PHOTO)
                    .append(" FROM view_data WHERE (").append(photoAssertion).append(" AND ")
                    .append(rawContactIdAssertion).toString();

            Cursor photoQuery = context.getContentResolver().query(uri, projection, where, null, null);
            if (photoQuery != null && photoQuery.moveToFirst()) {
                do {
                    byte[] photoData = photoQuery.getBlob(photoQuery.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO));
                    if (photoData != null) {
                        return BitmapFactory.decodeByteArray(photoData, 0, photoData.length, null);
                    }
                } while (photoQuery.moveToNext());
            }
        } while (query.moveToNext());
    }
    return null;
}

For other handsets you must get the contacts database and analyze it in order to determine how to apply the SQL Injection, which requires a rooted phone.

like image 5
Cristian Avatar answered Nov 13 '22 09:11

Cristian