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?
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With