【问题标题】:How to convert a SIM-card contact to be Google/device account instead?如何将 SIM 卡联系人转换为 Google/设备帐户?
【发布时间】:2017-08-10 20:54:09
【问题描述】:

背景

我正在尝试提供一种简单的方法来将 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. 是否也有请求此类事情的意图(我仍然需要代码,但如果由于某种原因失败,这可能很有用)?

【问题讨论】:

    标签: android android-contacts sim-card


    【解决方案1】:

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

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

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

    【讨论】:

    • 1.这不是我已经使用的吗?请解释如何。 2. 但是交易的意思是我先不想留下Sim-card-contact的痕迹,然后再创建一个新的,不是吗? 3. 你能告诉我怎么做吗?另外,SIM卡联系人不是只有姓名,电子邮件和电话吗? 4. 有道理,但不会比我做的还要长吗?
    • (1) 您将CONTENT_LOOKUP_URIcontactKey 结合使用,我会将其更改为CONTENT_URI w/contactId。 (2) 对我来说,首先添加新数据然后删除陈旧数据听起来更安全,而不是相反 (3) 我会在有时间的时候尝试编写一些代码。是的,但是您在副本中没有考虑到该数据的其他字段
    • 1.我认为查找键最好这样定义,它不会像联系人 ID 那样变化。 2.既然是事务,就应该是安全的(原子操作——全部成功或全部失败)。 3. 谢谢。 Sim 卡联系人中还有哪些其他字段?这些是用户唯一可以设置的,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多