I get null pointer exception at cursor moveToFirst() when retrieving contacts phone number on Lollipop devices but in other OS version it working fine.
Exception occur at pCur.moveToFirst(); under the getContact() method
please see my code:
public class MyService extends Service {
public static Context mContext;
LinkedHashMap<String, String> name = new LinkedHashMap<String, String>();
HashMap<String, String> contactDetails = new HashMap<String, String>();
HashMap<String, Bitmap> image = new HashMap<String, Bitmap>();
private Cursor pCur, contactsCursor;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String[] PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY,
Contacts.DISPLAY_NAME_PRIMARY, Contacts.PHOTO_THUMBNAIL_URI,
Contacts.SORT_KEY_PRIMARY };
String SELECTION = Contacts.DISPLAY_NAME_PRIMARY + "<>''" + " AND "
+ Contacts.IN_VISIBLE_GROUP + "=1" + " AND "
+ Contacts.HAS_PHONE_NUMBER;
String SORT_ORDER = Contacts.SORT_KEY_ALTERNATIVE;
contactsCursor = getContentResolver().query(Contacts.CONTENT_URI,
PROJECTION, SELECTION, null, SORT_ORDER);
StoreCursor.qcursor = contactsCursor;
Log.e("cur", "cur" + StoreCursor.qcursor.getCount());
getContact();
return START_STICKY;
}
private void getContact() {
Log.e("result cursor", "" + contactsCursor.getCount());
String displayName;
String contactId;
contactsCursor.moveToFirst();
do {
displayName = contactsCursor.getString(2);
contactId = contactsCursor.getString(0);
// Log.e("disName & id", displayName + " "+contactId);
pCur = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[] { contactId }, null);
String cPN = "";
pCur.moveToFirst(); // NullPointerException occur here.
do {
int phoneType = pCur
.getInt(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));
String phoneNumber = pCur
.getString(pCur
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
switch (phoneType) {
case Phone.TYPE_MOBILE:
cPN = cPN + "(mobile number)" + phoneNumber + "\n";
break;
case Phone.TYPE_HOME:
cPN = cPN + "(home number)" + phoneNumber + "\n";
break;
case Phone.TYPE_WORK:
cPN = cPN + "(work number)" + phoneNumber + "\n";
break;
case Phone.TYPE_OTHER:
cPN = cPN + "(other number)" + phoneNumber + "\n";
break;
default:
break;
}
} while (pCur.moveToNext());
name.put(contactId, displayName);
Log.e("displayName", displayName);
StoreCursor.name = name;
contactDetails.put(contactId, cPN);
StoreCursor.contactDetails = contactDetails;
String photo = contactsCursor.getString(3) + "~";
// Log.e("photo url", photo);
if (photo.length() > 6) {
openPhoto(Long.valueOf(contactId), displayName);
}
} while (contactsCursor.moveToNext());
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
That's an easy one:
If pCur.moveToFirst(); throws a NullPointerException, this means that pCur is null. Since pCur is only set in one place,
pCur = getContentResolver().query(...);
this means that your call to ContentResolver.query returns null.
Now the real question is: Why does ContentResolver.query return null? That's a good question, and I suggest that you ask it as a new question here on SO. Be sure to include all relevant information, i.e.:
which URL are you trying to resolve,
which parameters do you use and where to you get them from,
etc.
Ideally, you should add a minimal complete example to your new question (note that your current code snippet is neither minimal nor complete).
Related
I need (for practicing reasons) to change all the contacts to be starred. So I use this code to read all the contacts in a thread:
Looper.prepare(); //To avoid error: Can't create handler inside thread that has not called Looper.prepare
CursorLoader oCursorLoader = new CursorLoader(ContextoGlobal, ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
Cursor oCursor = oCursorLoader.loadInBackground();
int contactId = oCursor.getColumnIndex(ContactsContract.Contacts._ID);
contactId = oCursor.getColumnIndex(ContactsContract.RawContacts._ID);
int starred = oCursor.getColumnIndex(ContactsContract.Contacts.STARRED);
int number = oCursor.getColumnIndex(ContactsContract.Contacts.Data.DATA1);
int name = oCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
oCursor.moveToFirst();
if(oCursor.isAfterLast()==false) {
do {
String sId = oCursor.getString(contactId);
String phNumber = oCursor.getString(number);
String phName = oCursor.getString(name);
String sStarred = oCursor.getString(starred);
String s = sId + "\n" + phName + "\n" + phNumber + "\nStarred: " + sStarred;
} while (oCursor.moveToNext());
}
This code works and iterates through all the contacts in the device, displaying if they are starred or not.
My problem comes when I want to modify the starred field in the loop:
...
do {
String sId = oCursor.getString(contactId);
String phNumber = oCursor.getString(number);
String phName = oCursor.getString(name);
String sStarred = oCursor.getString(starred);
String s = sId + "\n" + phName + "\n" + phNumber + "\nStarred: " + sStarred;
ChangeStarred(sId, true); <-- HERE!!!!!!!!
} while (oCursor.moveToNext());
...
This is the ChangeStarred() function:
private boolean ChangeStarred(String sContactId, boolean bStarred){
ContentValues values = new ContentValues();
if(bStarred==true)
values.put(ContactsContract.Contacts.STARRED, 1);
else
values.put(ContactsContract.Contacts.STARRED, 0);
//int iAffectedRows = ContextoGlobal.getContentResolver().update(ContactsContract.Contacts.CONTENT_URI, values, ContactsContract.Contacts._ID + "= ?", new String[] { sContactId });
int iAffectedRows = ContextoGlobal.getContentResolver().update(ContactsContract.Contacts.CONTENT_URI, values, ContactsContract.RawContacts._ID + "= ?", new String[] { sContactId });
if(iAffectedRows == 0)
return false;
return true;
}
This function always returns FALSE. No rows are updated.
As you can see in the code comments, I have tried with Contacts._ID and RawContacts._ID
I also have WRITE_CONTACTS permission granted.
This is how I solved:
Looper.prepare(); //To avoid error: Can't create handler inside thread that has not called Looper.prepare
CursorLoader oCursorLoader = new CursorLoader(ContextoGlobal, ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
Cursor oCursor = oCursorLoader.loadInBackground();
int contactId = oCursor.getColumnIndex(ContactsContract.Contacts._ID);
int starred = oCursor.getColumnIndex(ContactsContract.Contacts.STARRED);
int name = oCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
oCursor.moveToFirst();
if(oCursor.isAfterLast()==false) {
do {
String sId = oCursor.getString(contactId);
String phName = oCursor.getString(name);
String sStarred = oCursor.getString(starred);
String s = sId + "\n" + phName + "\n" + "\nStarred: " + sStarred;
ChangeStarred(sId, true);
} while (oCursor.moveToNext());
}
And the ChangeStarred() function:
private boolean ChangeStarred(String sContactId, boolean bStarred) {
ContentValues contentValues = new ContentValues();
if(bStarred==true)
contentValues.put(ContactsContract.Contacts.STARRED, 1);
else
contentValues.put(ContactsContract.Contacts.STARRED, 0);
int iAffectedRows = ContextoGlobal.getContentResolver().update(ContactsContract.Contacts.CONTENT_URI, contentValues, ContactsContract.Contacts._ID + "=" + sContactId, null);
if(iAffectedRows > 0)
return true;
return false;
}
I am unable to get all contact ids from the RawContacts table
private void displayAllContactsByType(String accountName)
{//e.g accountName="WHATSAPP"
Cursor rawCursor = null;
rawCursor = cResolver.query(
ContactsContract.RawContacts.CONTENT_URI,
new String[]{ContactsContract.RawContacts.CONTACT_ID},
ContactsContract.RawContacts.ACCOUNT_NAME + "= ?",
new String[]{accountName},
ContactsContract.Contacts.DISPLAY_NAME_PRIMARY + " COLLATE LOCALIZED ASC");
rawCursor.moveToFirst();
int contactIdColumn = rawCursor.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID);
int rawCursorCount = rawCursor.getCount();
int total = 1;
Utils.Log("Raw Size", " " + rawCursorCount);//rawCursorCount is correct here
while (rawCursor.moveToNext()) {
Long contactId = rawCursor.getLong(contactIdColumn);
publishProgress(((total * 100) / rawCursorCount));
progressBar.setProgressNumberFormat("" + total + "/" + rawCursorCount);
storeContactDetails(contactId, accountName);
++total;
//I am facing problem in this method only below code is just for understanding.
}
}
Contact ids are passed to the below method with account name to get the contact details from respective id but contact ids are less compare to the log //Utils.Log("Raw Size", " " + rawCursorCount).
private void storeContactDetails(Long id, String accountName) {
Cursor phones = null;
String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Phone.HAS_PHONE_NUMBER,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.Contacts.LOOKUP_KEY,
"account_name",
Phone.TYPE
};
//Cursor c=cResolver.query(ContactsContract.Data.CONTENT_URI,projection,ContactsContract.Data.RAW_CONTACT_ID + " = ?",new String[]{String.valueOf(id)} ,null);
phones = cResolver.query(Phone.CONTENT_URI,
projection,
Phone.CONTACT_ID + " = ?",
new String[]{String.valueOf(id)},
null);
phones.moveToFirst();
getResultsFromPhoneCursor(phones, accountName);
}
public void getResultsFromPhoneCursor(Cursor phones, String accountName) {
int colorcounter = 0;
String[] colorcounter_array = {"#91A46B", "#8BB6B5", "#CAA973", "#8DA6C8", "#D19B8D"};
int color_string;
String email_Id = "";
String contactType = "";
try {
contactId = 0;
String hasPhone = "";
display_name = "";
phoneNumber = "";
contactId = phones.getLong(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
display_name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)).trim();
hasPhone = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.HAS_PHONE_NUMBER));
if (hasPhone.equalsIgnoreCase("1"))
hasPhone = "true";
else
hasPhone = "false";
if (Boolean.parseBoolean(hasPhone)) {
do {
this.accountName = phones.getString(phones.getColumnIndex("account_name"));
phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
int type = phones.getInt(phones.getColumnIndex(Phone.TYPE));
switch (type) {
case Phone.TYPE_HOME:
contactType = "HOME";
break;
case Phone.TYPE_MOBILE:
contactType = "MOBILE";
break;
case Phone.TYPE_WORK:
contactType = "WORK";
break;
}
String lookupKey = phones.getString(phones.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
if (colorcounter < 5) {
color_string = Color.parseColor(colorcounter_array[colorcounter]);
colorcounter++;
} else {
colorcounter = 0;
color_string = Color.parseColor(colorcounter_array[colorcounter]);
colorcounter++;
}
Cursor emails = cResolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{ContactsContract.CommonDataKinds.Email.DATA},
ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null);
while (emails.moveToNext()) {
email_Id = emails.getString(emails
.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));
}
emails.close();
if (this.accountName.equalsIgnoreCase(accountName)) {
if (!contactList.contains(new ContactsWrapper(contactId, display_name, phoneNumber, lookupKey, false, color_string, email_Id, contactType)))
contactList.add(new ContactsWrapper(contactId, display_name, phoneNumber, lookupKey, false, color_string, email_Id, contactType));
}
}
while (phones.moveToNext());
phones.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
please help me to solve this case or suggest any other ways to get the contact_ids . Thanks in Advance.
The problem is that you are loosing the first contact you fetch from the db.
The statement rawCursor.moveToFirst(); positions the cursor on the first available result record. The, when you want to iterate over the results, you call rawCursor.moveToNext() inside your loop. The loop condition is executed before it's body, so, you end up moving the cursor to the second row, loosing the first record.
You can fix this by getting rid of rawCursor.moveToFirst().
I am fetching contacts from android and storing it in a database. Tested it on a emulator and it was working. But when I tested the app on my phone I got duplicate entries of contacts who were using Whatsapp. Below is the code snippet.
class LoadContactAsync extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
Cursor people = getContentResolver()
.query(ContactsContract.Contacts.CONTENT_URI, null, null, null,
"UPPER(" + ContactsContract.Contacts.DISPLAY_NAME
+ ") ASC");
while (people.moveToNext()) {
final String contactId = people.getString(people
.getColumnIndex(ContactsContract.Contacts._ID));
final String contactName = people
.getString(people
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
final String image_uri = people
.getString(people
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
final String hasPhone = people
.getString(people
.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if ((Integer.parseInt(hasPhone) > 0)) {
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null,
"UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
while (phones.moveToNext()) {
final String phoneNumber = phones
.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
db.addContact(new Contact(contactName, phoneNumber, image_uri));
}
phones.close();
}
}
people.close();
return null;
}
#Override
protected void onPostExecute(String s) {
pd.dismiss();
showToast("Contacts Added Successfully");
db.close();
}
#Override
protected void onPreExecute() {
pd = ProgressDialog.show(MainActivity.this, "Please Wait...",
"Fetching One Time Contacts", true, false);
}
}
Here is the screenshot
With No Whatsapp installed
With No Whatsapp installed
With Whatsapp Installed
With Whatsapp Installed
Any help will be greatly appreciated.
Thanks
If you don't want to use database to avoid duplicate entries, use below code
private HashMap<String, ContactModel> getContactsList() {
String[] projection = new String[]{ContactsContract.Contacts._ID, ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER, ContactsContract.CommonDataKinds.Phone.PHOTO_URI};
Cursor phones = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, null, null,
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC");
String lastPhoneName = " ";
if (phones.getCount() > 0) {
while (phones.moveToNext()) {
String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
String contactId = phones.getString(phones.getColumnIndex(ContactsContract.Contacts._ID));
String photoUri = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.PHOTO_URI));
if (!name.equalsIgnoreCase(lastPhoneName)) {
lastPhoneName = name;
contactDetail.put(contactId, new ContactModel(contactId, name, phoneNumber, photoUri));
Log.d("getContactsList", name + "---" + phoneNumber + " -- " + contactId + " -- " + photoUri);
}
}
}
phones.close();
return contactDetail;
}
For someone who might face same error.. This did the trick for me.. Make Phone Number column as unique in your database table..
#Override
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "("
+ KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
+ KEY_PH_NO + " TEXT UNIQUE," + KEY_IMAGE + " TEXT" + ")";
db.execSQL(CREATE_CONTACTS_TABLE);
}
Store all contact data's in one array list (which include duplicate),
ArrayList mDetailsArrayList =new ArrayList<>();
then in postExecute remove duplicate entries using method removeDuplicates();
private ArrayList<Contact> removeDuplicate(ArrayList<Contact> contactArrayList){
Set set = new TreeSet(new Comparator() {
#Override
public int compare(Object lhs, Object rhs) {
if (lhs instanceof Contact && rhs instanceof Contact) {
if (((Contact) lhs).getContactName().equalsIgnoreCase(((Contact) rhs).getContactName())) {
return 0;
}
}
return 1;
}
});
set.addAll(contactArrayList);
System.out.println("\nAfter removing duplicates\n");
final ArrayList newList = new ArrayList(set);
System.out.println(set);
return newList;
}
Now this returned array list will hold real data's
I have made an app in which I need all the contacts available in the phone-book. I display these numbers in a list.The app works fine but some times the app force closes because the cursor returns null.This does not happens always but it happens some times.Now how do I handle this ????
Code
public static JSONArray getAllContactList(Context context) {
Cursor c = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
alAllContacts = new ArrayList<ContactModel>();
while (!(c == null) && c.moveToNext()) {
String id = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
String number = c.getString(c.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (number.equalsIgnoreCase("1")) {
// Cursor phones = getActivity().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
// ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = '" + id + "'", null, null);
Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null);
while (phones.moveToNext()) {
String contactName = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String contactNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactNumber = contactNumber.replace("+", "");
if (contactNumber.length() > 10) {
contactNumber = contactNumber.substring(2);
}
// contactNumber.replace("+91", "");
alAllContacts.add(new ContactModel(contactName, contactNumber));
//
}
}
}
c.close();
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < alAllContacts.size(); i++) {
jsonArray.put(alAllContacts.get(i).getJSONObject());
}
return jsonArray;
}
the logcat says that i am getting null pointer at this line
while (phones.moveToNext()) {
Also some times i get force close because by dialog is running,So is my code for showing the progress bar correct
public static void showProgress(Context context, String msg, boolean isVisible) {
if (progressDialog == null) {
progressDialog = new ProgressDialog(context);
progressDialog.setMessage(msg);
progressDialog.setCancelable(false);
}
if (isVisible) {
progressDialog.show();
} else if (isVisible == false) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
}
I use this code for getting all contacts and it does the job.
private static void backupContacts(Context context) {
String[] pCurProjection = new String[]{
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL,
ContactsContract.CommonDataKinds.Phone.IS_PRIMARY
};
String contactSelection = ContactsContract.Contacts.IN_VISIBLE_GROUP + " = '1'";
String[] contactProjection = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME
};
Cursor contactCursor = context.getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI,
contactProjection,
contactSelection,
null,
ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
int contactId;
String contactName;
if (null != contactCursor) {
while (contactCursor.moveToNext()) {
contactId = contactCursor.getInt(
contactCursor.getColumnIndex(ContactsContract.Contacts._ID));
contactName = contactCursor.getString(
contactCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
System.out.println(contactId + ": " + contactName);
Cursor pCur = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
pCurProjection,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{String.valueOf(contactId)},
null);
if (null != pCur) {
while (pCur.moveToNext()) {
int id = pCur.getColumnIndex(
ContactsContract.CommonDataKinds.Phone._ID);
String number = (pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
String type = pCur.getString(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE));//this line returns Null but it does not effect on the code(Does not Throws NullPointerException). if you found fix for it please let me know
int isPrimary = pCur.getInt(
pCur.getColumnIndex(ContactsContract.CommonDataKinds.Phone.IS_PRIMARY));
System.out.println(id + ": " + number + "\n" + type + "\n" + isPrimary);
}
pCur.close();
}
}
contactCursor.close();
}
}
if you have any question let me know :)
I was recently playing around with some code that goes through my contacts and creates an identicon for any contact that does not have a photo set. For the most part this ended up working quite well but for some reason I have a handful of contacts that will not update. Log output says it is creating the photo. The update() returns 1 indicating 1 row was updated and stepping through the code for a contact that never seems to show the new photo looks good.
The fact that only a select few are not updating is what is really bugging me and I'm guessing there must be something I am doing wrong or missing here.
private void processContacts() {
Cursor cursor = getContacts();
Log.d(TAG, "Processing " + cursor.getCount() + " contacts");
while(cursor.moveToNext()) {
final long contactId = cursor.getLong(0);
final String name = cursor.getString(1);
if (!TextUtils.isEmpty(name)) {
final Uri contactUri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
contactId);
if(ContactsContract.Contacts.openContactPhotoInputStream(getContentResolver(),
contactUri, true) == null) {
Log.d(TAG, String.format("Creating identicon for %s", name));
generateIdenticon(contactId, name);
} else {
Log.i(TAG, String.format("%s already has a contact photo", name));
}
}
}
cursor.close();
}
private Cursor getContacts() {
Uri uri = ContactsContract.Contacts.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
String sortOrder = ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC";
return getContentResolver().query(uri, projection, null, null, sortOrder);
}
private void generateIdenticon(long contactId, String name) {
if (!TextUtils.isEmpty(name)) {
updateNotification(getString(R.string.identicons_creation_service_running_title),
String.format(getString(R.string.identicons_creation_service_contact_summary),
name));
final byte[] hash = Identicon.generateHash(name);
final byte[] identicon = Identicon.generateIdenticonByteArray(hash);
if (identicon == null) {
Log.e(TAG, "generateIdenticon() - identicon for " + name + " is null!");
} else {
if (!setContactPhoto(getContentResolver(), identicon, contactId)) {
Log.e(TAG, "Unable to save identicon for " + name);
}
}
}
}
private boolean setContactPhoto(ContentResolver resolver, byte[] bytes, long personId) {
ContentValues values = new ContentValues();
int photoRow = -1;
String where = ContactsContract.Data.RAW_CONTACT_ID + " == " +
String.valueOf(personId) + " AND " + ContactsContract.Data.MIMETYPE + "=='" +
ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor cursor = resolver.query(
ContactsContract.Data.CONTENT_URI,
null,
where,
null,
null);
int idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Data._ID);
if(cursor.moveToFirst()){
photoRow = cursor.getInt(idIdx);
}
cursor.close();
values.put(ContactsContract.Data.RAW_CONTACT_ID, personId);
values.put(ContactsContract.Data.IS_PRIMARY, 1);
values.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes);
values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
if (photoRow >= 0) {
final int rowsUpdated = resolver.update(ContactsContract.Data.CONTENT_URI,
values, ContactsContract.Data._ID + "=" + photoRow, null);
return rowsUpdated >= 1;
} else {
final Uri uri = resolver.insert(ContactsContract.Data.CONTENT_URI, values);
return uri != null && !TextUtils.isEmpty(uri.toString());
}
}
All this is being done inside a background service and all my contacts are synced via google. One last thing to note is that these select contacts always return null when I call ContactsContract.Contacts.openContactPhotoInputStream() to see if a photo is available (even after I've attempted to update the photo).
Any help or insight about what may be going on is greatly appreciated.