Android: 批量添加数千个电话本联系人
Android: Add thousands of contacts in phonebook in bulk
想通过 Android 中的内容提供商在电话簿中添加数千个联系人。
我已经通过以下方式实现了添加联系人:
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
int rawContactID = ops.size();
// Adding insert operation to operations list
// to insert a new raw contact in the table ContactsContract.RawContacts
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
// Adding insert operation to operations list
// to insert display name in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getContactName())
.build());
// Adding insert operation to operations list
// to insert Mobile Number in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, contact.phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build());
// Adding insert operation to operations list
// to insert Home Email in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, contact.email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_HOME)
.build());
try {
// Executing all the insert operations as a single database transaction
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
每 1000 个联系人大约需要 175 秒。
当我使用线程池 10 的执行程序服务时,每 1000 个联系人仍然需要大约 155 秒。 (效率不高)
有没有其他方法可以更快地保存联系人?
好的,您的代码的优点在于您可以分批应用您的操作。
关于您的代码的不是最佳的事情是您的批次非常小,每个 4 个操作。
您可以改为收集更大的批次(我建议每批约 500 个,但您可以玩这个数字。
这是一些未经测试的代码:
private static final int BATCH_SIZE = 500;
private void addThousandContacts() {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
addSingleContact(ops);
if (ops.size() >= BATCH_SIZE) {
try {
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
ops.clear(); // remove all applied operations and start a new batch
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
}
}
}
private void addSingleContact(ArrayList<ContentProviderOperation> ops) {
int rawInsertIndex = ops.size();
// Adding insert operation to operations list
// to insert a new raw contact in the table ContactsContract.RawContacts
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
// Adding insert operation to operations list
// to insert display name in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawInsertIndex) // tells the system the index of the operation that contains the current RawContactId
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getContactName())
.build());
... // add more operations email, phone, etc.
}
想通过 Android 中的内容提供商在电话簿中添加数千个联系人。
我已经通过以下方式实现了添加联系人:
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
int rawContactID = ops.size();
// Adding insert operation to operations list
// to insert a new raw contact in the table ContactsContract.RawContacts
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
// Adding insert operation to operations list
// to insert display name in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getContactName())
.build());
// Adding insert operation to operations list
// to insert Mobile Number in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, contact.phone)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
.build());
// Adding insert operation to operations list
// to insert Home Email in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, contact.email)
.withValue(ContactsContract.CommonDataKinds.Email.TYPE, ContactsContract.CommonDataKinds.Email.TYPE_HOME)
.build());
try {
// Executing all the insert operations as a single database transaction
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
每 1000 个联系人大约需要 175 秒。
当我使用线程池 10 的执行程序服务时,每 1000 个联系人仍然需要大约 155 秒。 (效率不高)
有没有其他方法可以更快地保存联系人?
好的,您的代码的优点在于您可以分批应用您的操作。 关于您的代码的不是最佳的事情是您的批次非常小,每个 4 个操作。
您可以改为收集更大的批次(我建议每批约 500 个,但您可以玩这个数字。
这是一些未经测试的代码:
private static final int BATCH_SIZE = 500;
private void addThousandContacts() {
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
addSingleContact(ops);
if (ops.size() >= BATCH_SIZE) {
try {
contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
ops.clear(); // remove all applied operations and start a new batch
} catch (RemoteException e) {
e.printStackTrace();
} catch (OperationApplicationException e) {
e.printStackTrace();
}
}
}
}
private void addSingleContact(ArrayList<ContentProviderOperation> ops) {
int rawInsertIndex = ops.size();
// Adding insert operation to operations list
// to insert a new raw contact in the table ContactsContract.RawContacts
ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
.build());
// Adding insert operation to operations list
// to insert display name in the table ContactsContract.Data
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawInsertIndex) // tells the system the index of the operation that contains the current RawContactId
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getContactName())
.build());
... // add more operations email, phone, etc.
}