【发布时间】:2018-06-07 14:34:59
【问题描述】:
我以编程方式在 Android 通讯录中创建了一个联系人,其中包含姓名和电话号码。现在我想为这个联系人添加一张照片,但我似乎无法正常工作。我没有收到错误消息,但似乎没有添加照片。
如果我创建一个带照片的新联系人,照片会正确添加,我也可以更新此联系人的现有照片。唯一的问题是没有照片的联系人。
我已经阅读了几个解决方案 here 和 here,并根据这些答案尝试了几种变体,但都不起作用。我最好的猜测是我对RAW_CONTACT_ID 做错了什么。谁能找到我的错误?
private void createNewContact()
{
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
builder.withValue(RawContacts.ACCOUNT_TYPE, MY_ACCOUNT_TYPE);
builder.withValue(RawContacts.ACCOUNT_NAME, MY_ACCOUNT_NAME);
ops.add(builder.build());
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(StructuredName.GIVEN_NAME, myName);
ops.add(builder.build());
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
builder.withValue(Phone.TYPE, Phone.TYPE_WORK);
builder.withValue(Phone.NUMBER, myPhoneNumber);
ops.add(builder.build());
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withValueBackReference(Data.RAW_CONTACT_ID, 0);
builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
builder.withValue(Photo.PHOTO, myPhotoByteArray);
ops.add(builder.build());
try
{
context.getContentResolver().applyBatch(AUTHORITY, ops);
}
catch (Exception e)
{
// Handle exception
}
}
private static final String BASIC_SELECTION = RawContacts.ACCOUNT_TYPE + "='" + MY_ACCOUNT_TYPE + "'";
private void editContact() {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI);
builder.withSelection(BASIC_SELECTION + " AND " + Data.MIMETYPE + "='" + StructuredName.CONTENT_ITEM_TYPE + "'", null);
builder.withValue(StructuredName.GIVEN_NAME, myName);
ops.add(builder.build());
builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI);
builder.withSelection(BASIC_SELECTION + " AND " + Data.MIMETYPE + "='" + Phone.CONTENT_ITEM_TYPE + "'" + " AND " + Phone.TYPE + "='" + Phone.TYPE_WORK + "'", null);
builder.withValue(Phone.NUMBER, myPhoneNumber);
ops.add(builder.build());
if (isContactWithoutPhoto())
{
// Contact without photo: insert new photo
// TODO: this part doesn't work yet!
int rawContactId = getRawContactId();
if (rawContactId != -1)
{
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withValue(Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE);
builder.withValue(Photo.PHOTO, myPhotoByteArray);
ops.add(builder.build());
}
}
else
{
// Contact already has a photo: update
builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI);
builder.withSelection(BASIC_SELECTION + " AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", null);
builder.withValue(Photo.PHOTO, myPhotoBytes);
ops.add(builder.build());
}
try
{
context.getContentResolver().applyBatch(AUTHORITY, ops);
}
catch (Exception e)
{
// Handle exception
}
}
private int getRawContactId()
{
int rawContactId = -1;
Cursor cursor = null;
try
{
cursor = App.getContext().getContentResolver().query(RawContacts.CONTENT_URI, null, ACCOUNT_TYPE_SELECTION, null, null);
if (cursor != null && cursor.moveToFirst())
{
rawContactId = cursor.getInt(cursor.getColumnIndex(RawContacts._ID));
}
}
finally
{
if (cursor != null)
{
cursor.close();
}
}
return rawContactId;
}
编辑:
我只需要一个联系人,它是一次创建的,之后只需要定期更新。此联系人保存在类型为 MY_ACCOUNT_TYPE 和名称为 MY_ACCOUNT_NAME 的自行创建的帐户中。因此,builder.withSelection(BASIC_SELECTION 用于每个更新操作,它使用 MY_ACCOUNT_TYPE 而不是 id。
我还尝试在“更新现有联系人的照片”部分添加相同的选择,以更像其他“更新”代码一样实现它,因为我想确保我仅为该单个联系人更新照片:
int rawContactId = getRawContactId();
if (rawContactId != -1)
{
builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
builder.withSelection(BASIC_SELECTION + " AND " + Data.MIMETYPE + "='" + Photo.CONTENT_ITEM_TYPE + "'", null);
builder.withValue(Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(Photo.PHOTO, myPhotoByteArray);
ops.add(builder.build());
在这种情况下,应用程序显然会因错误java.lang.IllegalArgumentException: only updates, deletes, and asserts can have selections 而崩溃。 id 已经使用BASIC_SELECTION 收集,所以我希望无论如何都能以这种方式更新正确的联系人。
如果有人想知道使用了哪些(静态)ContactsContract 导入:
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.PhoneLookup;
import static android.provider.ContactsContract.AUTHORITY;
import static android.provider.ContactsContract.CommonDataKinds.Note;
import static android.provider.ContactsContract.CommonDataKinds.Phone;
import static android.provider.ContactsContract.CommonDataKinds.StructuredName;
import static android.provider.ContactsContract.Data;
import static android.provider.ContactsContract.RawContacts;
【问题讨论】:
-
你能明确说明它是如何不起作用的吗?例如,是否有错误消息?应用程序会崩溃吗?或者照片只是没有出现在联系人上?你怎么知道它失败了?
-
我没有收到错误消息,但似乎没有添加照片。 (我直接编辑了问题)
标签: android android-contacts contactscontract