Вставить контакт (ContactsContract) с помощью намерения с изображением (Фото)

Существует много потоков Q & A, но ни один из них не дает реального ответа, или я не смог его найти.

Чтобы убедиться, что я искал, прежде чем спрашивать:

Так есть кто-нибудь, кто знает, как использовать Intent (как в примере кода) и вставить фотографию, которая хранится в Bitmap?

Пример кода, который я использую сейчас, чтобы начать диалог, чтобы пользователь мог вставлять или отменять и, возможно, редактировать поля перед сохранением:

// 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);

Я нашел решение, благодаря ответу Жюльена

Не использовать только намерение, так как я сомневаюсь, что мы можем передать идентификатор изображения, сохраненного Data ContentProvider, или передать Bitmap прямо в Intent.

Продолжается из кода выше

Использовать startActivityForResult с постоянным кодом запроса

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

Добавить результат обработки из активности, запущенной с помощью намерения

@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;
    }
}

Добавить метод установки фотографии

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;
 }

Добавить метод поиска контактов и добавления фотографий контактов

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
    }
}

Ответ 1

чтобы помочь вам, я нашел оригинальную документацию: http://java.llp2.dcc.ufmg.br/apiminer/docs/reference/android/provider/ContactsContract.RawContacts.DisplayPhoto.html

и прочитайте следующее: http://java.llp2.dcc.ufmg.br/apiminer/docs/reference/android/provider/ContactsContract.RawContacts.html

для меня простое решение было бы, если ваш код работает:

startActivityForResult(inOrUp, CODE_INSERT_CONTACT);

Затем в вызове onActivityResult "setDisplayPhotoByRawContactId.":

    /** @return true if picture was changed false otherwise. */
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;
 }

Обычно этот код работает с версией 14 API. Мне пришлось заниматься исследованиями по этой теме.

Вы можете получить rawContactId, как указано в документации:

Uri rawContactUri = RawContacts.URI.buildUpon()
      .appendQueryParameter(RawContacts.ACCOUNT_NAME, accountName)
      .appendQueryParameter(RawContacts.ACCOUNT_TYPE, accountType)
      .build();
long rawContactId = ContentUris.parseId(rawContactUri);

Я не уверен, но документация вам поможет. Извините за мой английский.

Ответ 2

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);

Ответ 3

Принятый ответ не делает то, что задал вопрос.

Обратитесь к @yeo100 answer, который использует ContactsContract.Intents.Insert.DATA (docs - несколько неясно и сложно найти:/), поскольку контактные фотографии сохраняются в таблице данных под определенным типом mimetype:

Data.MIMETYPEContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE

Это сработало для меня, и оно намного опрятно и проще в управлении.

Ответ 4

Попробуйте этот код, чтобы добавить изображение с контактной информацией, используя намерение

 var bit = BitmapFactory.decodeResource(getResources(), R.drawable.yourimagename); // your image
    val data = ArrayList<ContentValues>();
    var row = ContentValues();
    row.put(ContactsContract.Contacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
    val stream = ByteArrayOutputStream()
    bit.compress(Bitmap.CompressFormat.PNG, 100, stream)
    val byteArray = stream.toByteArray()
    bit.recycle()
    row.put(ContactsContract.CommonDataKinds.Photo.PHOTO, byteArray);
    data.add(row)
    var intent = Intent(Intent.ACTION_INSERT, ContactsContract.Contacts.CONTENT_URI);
    intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, data);
    intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
    intent.putExtra(ContactsContract.Intents.Insert.PHONE, phone1);
    intent.putExtra(ContactsContract.Intents.Insert.SECONDARY_PHONE, phone2);
    intent.putExtra(ContactsContract.Intents.Insert.EMAIL, email);
    context.startActivity(intent);