如何将SIM卡联系人转换为谷歌/设备帐户?



Background

我正在尝试提供一种简单的方法来转换SIM卡联系人,成为设备或Google帐户联系人。

问题所在

我尝试直接更新其帐户,并且还尝试执行删除和添加的交易。

两种方式都不起作用。

我希望以原子方式进行,这样如果它失败了,它就不会因此而让地址簿有重复项,或者更糟糕的是,根本没有联系。

我尝试过什么

正如我所写,两种方式都不起作用:

1.尝试直接更新的代码(不执行任何操作(:

public static Uri convertSimCardContactToNormalOne(@NonNull final Context context, @NonNull final String contactKey, @Nullable Account account) {
final ArrayList<ContentProviderOperation> ops = new ArrayList<>();
final Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactKey);
ops.add(ContentProviderOperation.newUpdate(contactUri).withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account == null ? null : account.type)
.withValue(RawContacts.ACCOUNT_NAME, account == null ? null : account.name).build());
final ContentProviderResult[] contentProviderResults;
try {
contentProviderResults = context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Uri uri = contentProviderResults[contentProviderResults.length - 1].uri;
return uri ;
} catch (RemoteException | OperationApplicationException ignored) {
}
return null;
}

2.尝试删除和添加联系人的代码(似乎删除了联系人,但创建了一个空的联系人(:

@RequiresPermission(permission.WRITE_CONTACTS)
public static Uri convertSimCardContactToNormalOne(@NonNull final Context context, @NonNull final String contactKey, @Nullable Account account, @Nullable final String phoneNumber, @Nullable final String contactName, @Nullable final String emailAddress, @Nullable final Bitmap bitmap) {
final Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactKey);
final ArrayList<ContentProviderOperation> ops = new ArrayList<>();
ops.add(ContentProviderOperation.newDelete(contactUri).build());
int rawContactID = 0;
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account == null ? null : account.type)
.withValue(RawContacts.ACCOUNT_NAME, account == null ? null : account.name)
.build());
if (contactName != null)
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.DISPLAY_NAME, contactName)
.build());
if (phoneNumber != null)
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
.withValue(Phone.NUMBER, phoneNumber)
.withValue(Phone.TYPE, CommonDataKinds.Phone.TYPE_MOBILE)
.build());
if (emailAddress != null)
ops.add(ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.DATA, emailAddress)
.withValue(Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, Email.TYPE_HOME).build());
if (bitmap != null && !bitmap.isRecycled()) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
.withValue(ContactsContract.Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE)
.withValue(CommonDataKinds.Photo.PHOTO, stream.toByteArray())
.build());
try {
stream.flush();
} catch (IOException ignored{
}
}
final ContentProviderResult[] contentProviderResults;
try {
contentProviderResults = context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
Uri uri = contentProviderResults[contentProviderResults.length - 1].uri;
return uri ;
} catch (RemoteException | OperationApplicationException ignored) {
}
return null;
}

问题

  1. 我在这里做错了什么?我知道如果它不在事务中,方法 2 将起作用,但现在由于某种原因它不起作用。

  2. 转换此类联系人的最佳方法是什么?

  3. 有没有办法检查单个联系人可用的所有字段,并将它们放入新联系人(转换后的联系人(中?

  4. 是否也有请求这样的事情的意图(我仍然需要代码,但如果由于某种原因失败,这可能很有用(?

我怀疑一种方法是否有效,它可能会导致原始帐户和目标帐户的 SyncProviders 混淆至少可以说,并且可能被认为是数据库对他们的损坏。 SyncAdapter 依赖于内部 SYNC1。SYNC4 字段,我们凡人不理解,你不能依靠相同的RawContact来工作,就像在不同的帐户上一样。

关于方法 2,我会尝试在那里更改一些内容:

  1. 使用contactUri作为Contacts.CONTENT_URI/contactId而不是Contacts.CONTENT_LOOKUP_URI/contactKey,查找 uri 用于通过在数据库上搜索联系人来查找联系人,而不是用于修改目的。
  2. 将删除操作移到末尾。
  3. 除了newInsert的第一个操作外,所有其他操作都应复制所有数据字段,而不仅仅是选定的字段,所有 mimetype 将所有值存储在 DATA1 中。DATA15 可能的字段,特定名称(例如CommonDataKinds.Email.TYPE( 只是某些 DATA 字段的 suger 语法,所以我会在您找到的每个Data条目中.withValue(Data.DATA1, existingData1)行 15 次。
  4. 您可能会发现创建一个帮助程序方法很有用,该方法将返回一个复制了所有 15 个值的新操作,并在循环中调用它,将返回值添加到opsArrayList

最新更新