public
static
Intent createJoinContactsIntent(Context context,
long
contactId1,
long
contactId2,
boolean
contactWritable,
Class<?> callbackActivity, String callbackAction) {
Intent serviceIntent =
new
Intent(context, ContactSaveService.
class
);
serviceIntent.setAction(ContactSaveService.ACTION_JOIN_CONTACTS);
serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_ID1, contactId1);
serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_ID2, contactId2);
serviceIntent.putExtra(ContactSaveService.EXTRA_CONTACT_WRITABLE, contactWritable);
Intent callbackIntent =
new
Intent(context, callbackActivity);
callbackIntent.setAction(callbackAction);
serviceIntent.putExtra(ContactSaveService.EXTRA_CALLBACK_INTENT, callbackIntent);
return
serviceIntent;
}
private
interface
JoinContactQuery {
String[] PROJECTION = {
RawContacts._ID,
RawContacts.CONTACT_ID,
RawContacts.NAME_VERIFIED,
RawContacts.DISPLAY_NAME_SOURCE,
};
String SELECTION = RawContacts.CONTACT_ID +
"=? OR "
+ RawContacts.CONTACT_ID +
"=?"
;
int
_ID =
0
;
int
CONTACT_ID =
1
;
int
NAME_VERIFIED =
2
;
int
DISPLAY_NAME_SOURCE =
3
;
}
private
void
joinContacts(Intent intent) {
long
contactId1 = intent.getLongExtra(EXTRA_CONTACT_ID1, -
1
);
long
contactId2 = intent.getLongExtra(EXTRA_CONTACT_ID2, -
1
);
boolean
writable = intent.getBooleanExtra(EXTRA_CONTACT_WRITABLE,
false
);
if
(contactId1 == -
1
|| contactId2 == -
1
) {
Log.e(TAG,
"Invalid arguments for joinContacts request"
);
return
;
}
final
ContentResolver resolver = getContentResolver();
Cursor c = resolver.query(RawContacts.CONTENT_URI,
JoinContactQuery.PROJECTION,
JoinContactQuery.SELECTION,
new
String[]{String.valueOf(contactId1), String.valueOf(contactId2)},
null
);
long
rawContactIds[];
long
verifiedNameRawContactId = -
1
;
try
{
int
maxDisplayNameSource = -
1
;
rawContactIds =
new
long
[c.getCount()];
for
(
int
i =
0
; i < rawContactIds.length; i++) {
c.moveToPosition(i);
long
rawContactId = c.getLong(JoinContactQuery._ID);
rawContactIds[i] = rawContactId;
int
nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if
(nameSource > maxDisplayNameSource) {
maxDisplayNameSource = nameSource;
}
}
if
(writable) {
for
(
int
i =
0
; i < rawContactIds.length; i++) {
c.moveToPosition(i);
if
(c.getLong(JoinContactQuery.CONTACT_ID) == contactId1) {
int
nameSource = c.getInt(JoinContactQuery.DISPLAY_NAME_SOURCE);
if
(nameSource == maxDisplayNameSource
&& (verifiedNameRawContactId == -
1
|| c.getInt(JoinContactQuery.NAME_VERIFIED) !=
0
)) {
verifiedNameRawContactId = c.getLong(JoinContactQuery._ID);
}
}
}
}
}
finally
{
c.close();
}
ArrayList<ContentProviderOperation> operations =
new
ArrayList<ContentProviderOperation>();
for
(
int
i =
0
; i < rawContactIds.length; i++) {
for
(
int
j =
0
; j < rawContactIds.length; j++) {
if
(i != j) {
buildJoinContactDiff(operations, rawContactIds[i], rawContactIds[j]);
}
}
}
if
(verifiedNameRawContactId != -
1
) {
Builder builder = ContentProviderOperation.newUpdate(
ContentUris.withAppendedId(RawContacts.CONTENT_URI, verifiedNameRawContactId));
builder.withValue(RawContacts.NAME_VERIFIED,
1
);
operations.add(builder.build());
}
boolean
success =
false
;
try
{
resolver.applyBatch(ContactsContract.AUTHORITY, operations);
showToast(R.string.contactsJoinedMessage);
success =
true
;
}
catch
(RemoteException e) {
Log.e(TAG,
"Failed to apply aggregation exception batch"
, e);
showToast(R.string.contactSavedErrorToast);
}
catch
(OperationApplicationException e) {
Log.e(TAG,
"Failed to apply aggregation exception batch"
, e);
showToast(R.string.contactSavedErrorToast);
}
Intent callbackIntent = intent.getParcelableExtra(EXTRA_CALLBACK_INTENT);
if
(success) {
Uri uri = RawContacts.getContactLookupUri(resolver,
ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactIds[
0
]));
callbackIntent.setData(uri);
}
deliverCallback(callbackIntent);
}
/**
* Construct a {@link AggregationExceptions#TYPE_KEEP_TOGETHER} ContentProviderOperation.
*/
private
void
buildJoinContactDiff(ArrayList<ContentProviderOperation> operations,
long
rawContactId1,
long
rawContactId2) {
Builder builder =
ContentProviderOperation.newUpdate(AggregationExceptions.CONTENT_URI);
builder.withValue(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID1, rawContactId1);
builder.withValue(AggregationExceptions.RAW_CONTACT_ID2, rawContactId2);
operations.add(builder.build());
}