Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert Contact (ContactsContract) via Intent with Image (Photo)

There is many Q&A threads, but none of them is providing real answer, or I couldn't find it.

To ensure you, I've searched before asking:

  • Android: set contact photo with ContactsContract insert intent (invalid answer)
  • Insert contact in Android with ContactsContract (accepted answer does not use Intent)
  • Insert a new contact intent (does not touch the problem)
  • How to insert photo in call intent? (is not related)
  • Add a photo to a contact (does not use intent)
    • https://stackoverflow.com/a/8574396/492624 (solution from answer I tried with intent, both PHOTO and DATA15 fields, but not working)
  • http://thinkandroid.wordpress.com/2009/12/30/handling-contact-photos-all-api-levels/ (does not use intent)

So is there anyone, who knows how to use Intent (as in example code) and insert a Photo, which is held in Bitmap ?

Example code I do use now to start dialog intent for user to let him insert or cancel and possibly edit fields before saving:

// PrivateContactClass c;
// Bitmap photo;
Intent inOrUp = new Intent(ContactsContract.Intents.Insert.ACTION, ContactsContract.Contacts.CONTENT_URI);
inOrUp.setType(ContactsContract.Contacts.CONTENT_TYPE);
inOrUp.putExtra(ContactsContract.Intents.Insert.NAME, ModelUtils.formatName(c));
inOrUp.putExtra(ContactsContract.Intents.Insert.PHONE, getPrimaryPhone());
inOrUp.putExtra(ContactsContract.Intents.Insert.TERTIARY_PHONE, c.getMobile());
inOrUp.putExtra(ContactsContract.Intents.Insert.EMAIL, c.getMail());
inOrUp.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, c.getFunction());
inOrUp.putExtra(ContactsContract.Intents.Insert.NOTES, getSummary());
inOrUp.putExtra(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
startActivity(inOrUp);

I have found a solution, thanks to Julien's answer

Not using only intent, as I doubt that we can pass ID of image saved by Data ContentProvider, or pass Bitmap directly within Intent.

Extends from code above

Use startActivityForResult with constant request code

// must be declared in class-context
private static final int CONTACT_SAVE_INTENT_REQUEST = 1;
...
startActivityForResult(inOrUp,CONTACT_SAVE_INTENT_REQUEST);

Add handling result from activity started by Intent

@Override
protected void onActivityResult(int requestCode, int resultCode,
        Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    switch (requestCode) {
    case RESULT_INSERT_CONTACT:
        if (resultCode == RESULT_OK) {
            trySetPhoto();
        }
        break;
    }
}

Add Method to set photo

public boolean setDisplayPhotoByRawContactId(long rawContactId, Bitmap bmp) {
     ByteArrayOutputStream stream = new ByteArrayOutputStream();
     bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
     byte[] byteArray = stream.toByteArray();
     Uri pictureUri = Uri.withAppendedPath(ContentUris.withAppendedId(RawContacts.CONTENT_URI, 
             rawContactId), RawContacts.DisplayPhoto.CONTENT_DIRECTORY);
     try {
         AssetFileDescriptor afd = getContentResolver().openAssetFileDescriptor(pictureUri, "rw");
         OutputStream os = afd.createOutputStream();
         os.write(byteArray);
         os.close();
         afd.close();
         return true;
     } catch (IOException e) {
         e.printStackTrace();
     }
     return false;
 }

Add Method to search for contacts and add contact photos

private void trySetPhoto() {
    // Everything is covered in try-catch, as this method can fail on 
    // low-memory or few NPE
    try {
        // We must have an phone identifier by which we search for
        // format of phone number is not relevant, as ContentProvider will
        // normalize it automatically
        if (c.getMobile() != null) {
            Uri lookup = Uri.withAppendedPath(
                    ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                    Uri.encode(c.getMobile()));
            Cursor c = getContentResolver().query(lookup, null, null, null,
                    null);
            // Remember cursor can be null in some cases
            if (c != null) {
                // we can obtain bitmap just once
                Bitmap photo_bitmap = getPhotoBitmap();
                c.moveToFirst();
                // if there are multiple raw contacts, we want to set the photo for all of them
                while (c.moveToNext()) {
                    setDisplayPhotoByRawContactId(
                            c.getLong(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID)),
                            photo_bitmap);
                }
                // remember to clean up after using cursor
                c.close();
            }
        }
    } catch (Exception e) {
        // Logging procedures
    } catch (Error e) {
        // Logging procedures
    }
}
like image 472
Marek Sebera Avatar asked Feb 22 '13 14:02

Marek Sebera


People also ask

Why do some of my contacts have pictures Android?

Some people add their own profile pics on their Google account. So anyone who has their email address (or number, if it's updated on their Google profile) will be detected by Google and linked to your account. For example if I'm your contact and I updated a profile pic, my pic will be updated on your phone.

How do I open Android contact list?

On your Android phone or tablet, open the Contacts app . Tap a Contact in the list. Select an Option.


2 Answers

Bitmap bit = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); // your image

ArrayList<ContentValues> data = new ArrayList<ContentValues>();

ContentValues row = new ContentValues();
row.put(Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
row.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bitmapToByteArray(bit));
data.add(row);

Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
intent.putParcelableArrayListExtra(Insert.DATA, data);
like image 117
yeo100 Avatar answered Nov 16 '22 01:11

yeo100


This is the same answer as yeo100, but in Kotlin.

//Create Intent - I use ACTION_INSERT_OR_EDIT but you could use ACTION_INSERT
val intent = Intent(Intent.ACTION_INSERT_OR_EDIT).apply {
   type = ContactsContract.Contacts.CONTENT_ITEM_TYPE
}

intent.apply {

   //Add name, phone numbers, etc
   putExtra(ContactsContract.Intents.Insert.NAME, "John Smith")

   ...

   /*
   Start Adding Contact's Photo
   */

   //Get photo from an imageView into a byteArray
   var imageAsBitmap = (myImageView.drawable as BitmapDrawable).bitmap
   val stream = ByteArrayOutputStream()
   imageAsBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream)
   val imageData = stream.toByteArray()

   //Add image data to an Array of ContentValues
   val data = ArrayList<ContentValues>()
   val row = ContentValues()
   row.put(ContactsContract.RawContacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
   row.put(ContactsContract.CommonDataKinds.Photo.PHOTO, imageData)
   data.add(photoRow)

   //Add array to your Intent as data
   putExtra(ContactsContract.Intents.Insert.DATA, data)
}

startActivity(intent)
like image 38
iOS_Mouse Avatar answered Nov 16 '22 01:11

iOS_Mouse