package org.mots.haxsync.utilities;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.mots.haxsync.services.ContactsSyncAdapterService;
import org.mots.haxsync.services.ContactsSyncAdapterService.SyncEntry;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.util.Log;
public class ContactUtil {
public static class Contact{
public long ID;
public String name;
public String accountType;
}
public static class Photo{
public byte[] data;
public String url;
public long timestamp;
}
public static final String TAG = "ContactUtil";
private static HashMap<String, Drawable> accountIcons = new HashMap<String, Drawable>();
public static Contact getMergedContact(Context c, long contactID, Account account){
Uri ContactUri = RawContacts.CONTENT_URI.buildUpon()
.appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type)
.build();
Cursor cursor = c.getContentResolver().query(ContactUri, new String[] { BaseColumns._ID, RawContacts.DISPLAY_NAME_PRIMARY}, RawContacts.CONTACT_ID +" = '" + contactID + "'", null, null);
if (cursor.getCount() > 0){
cursor.moveToFirst();
Contact contact = new Contact();
contact.ID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID));
contact.name = cursor.getString(cursor.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY));
cursor.close();
return contact;
}
cursor.close();
return null;
}
private static void fillIcons(Context c){
AccountManager am = AccountManager.get(c);
AuthenticatorDescription[] auths = am.getAuthenticatorTypes();
PackageManager pm = c.getPackageManager();
for (AuthenticatorDescription auth : auths){
accountIcons.put(auth.type, pm.getDrawable(auth.packageName, auth.iconId, null));
/* Log.i("Account:", auth.type);
Log.i("pkg:", auth.packageName);
Log.i("icon:", String.valueOf(auth.smallIconId));*/
}
}
public static List<HashMap<String, Object>> getMergedContacts(Context c, long rawContactID){
Cursor cursor = c.getContentResolver().query(RawContacts.CONTENT_URI, new String[] { RawContacts.CONTACT_ID}, RawContacts._ID +" = '" + rawContactID + "'", null, null);
ArrayList<HashMap<String, Object>> contacts = new ArrayList<HashMap<String, Object>>();
if (cursor.getCount() > 0){
cursor.moveToFirst();
long contactID = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));
Cursor c2 = c.getContentResolver().query(RawContacts.CONTENT_URI, new String[] { BaseColumns._ID, RawContacts.DISPLAY_NAME_PRIMARY, RawContacts.ACCOUNT_TYPE}, RawContacts.CONTACT_ID +" = '" + contactID + "'" + " AND " + BaseColumns._ID + " != " +rawContactID , null, null);
while(c2.moveToNext()){
HashMap<String, Object> contact = new HashMap<String, Object>();
contact.put("name", c2.getString(c2.getColumnIndex(RawContacts.DISPLAY_NAME_PRIMARY)));
contact.put("id", c2.getString(c2.getColumnIndex(BaseColumns._ID)));
Drawable icon;
//todo: cache this shit
fillIcons(c);
try{
icon = accountIcons.get(c2.getString(c2.getColumnIndex(RawContacts.ACCOUNT_TYPE)));
} catch (Exception e){
fillIcons(c);
icon = accountIcons.get(c2.getString(c2.getColumnIndex(RawContacts.ACCOUNT_TYPE)));
}
contact.put("icon", icon);
contacts.add(contact);
}
c2.close();
}
cursor.close();
return contacts;
}
public static void merge(Context c, long id1, long id2){
Log.i("MERGING", id1 +","+id2);
ContentValues values = new ContentValues();
values.put(ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, id1);
values.put(ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, id2);
values.put(ContactsContract.AggregationExceptions.TYPE,ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER);
c.getContentResolver().update(ContactsContract.AggregationExceptions.CONTENT_URI, values, null, null);
}
private static Set<Long> getRawContacts(Context c, long contactID, long rawContactID){
HashSet<Long> ids = new HashSet<Long>();
Cursor c2 = c.getContentResolver().query(RawContacts.CONTENT_URI, new String[] { BaseColumns._ID}, RawContacts.CONTACT_ID +" = '" + contactID + "'" + " AND " + BaseColumns._ID + " != " +rawContactID , null, null);
while (c2.moveToNext()){
ids.add(c2.getLong(c2.getColumnIndex(BaseColumns._ID)));
}
c2.close();
return ids;
}
public static Set<Long> getRawContacts(ContentResolver c, long rawContactID, String accountType){
HashSet<Long> ids = new HashSet<Long>();
Cursor cursor = c.query(RawContacts.CONTENT_URI, new String[] { RawContacts.CONTACT_ID}, RawContacts._ID +" = '" + rawContactID + "'", null, null);
if (cursor.getCount() > 0){
cursor.moveToFirst();
long contactID = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));
// Log.i("QUERY", RawContacts.CONTACT_ID +" = '" + contactID + "'" + " AND " + BaseColumns._ID + " != " +rawContactID + " AND " + RawContacts.ACCOUNT_TYPE + " = '" + accountType+"'");
Cursor c2 = c.query(RawContacts.CONTENT_URI, new String[] { BaseColumns._ID}, RawContacts.CONTACT_ID +" = '" + contactID + "'" + " AND " + BaseColumns._ID + " != " +rawContactID + " AND " + RawContacts.ACCOUNT_TYPE + " = '" + accountType+"'", null, null);
// Log.i("CURSOR SIZE", String.valueOf(c2.getCount()));
while (c2.moveToNext()){
ids.add(c2.getLong(c2.getColumnIndex(BaseColumns._ID)));
}
c2.close();
}
cursor.close();
return ids;
}
public static void mergeWithContact(Context c, long rawContactID, long contactID){
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
Set<Long> ids = getRawContacts(c, contactID, rawContactID);
for (long id: ids){
ContentProviderOperation.Builder builder = ContentProviderOperation
.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI);
builder.withValue(
ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, rawContactID);
builder.withValue(
ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, id);
builder.withValue(
ContactsContract.AggregationExceptions.TYPE,ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER);
operationList.add(builder.build());
}
if(operationList.size() > 0)
try {
c.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void seperate(Context c, long rawContactID){
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
Cursor cursor = c.getContentResolver().query(RawContacts.CONTENT_URI, new String[] { RawContacts.CONTACT_ID}, RawContacts._ID +" = '" + rawContactID + "'", null, null);
if (cursor.moveToFirst()){
long contactID = cursor.getLong(cursor.getColumnIndex(RawContacts.CONTACT_ID));
Set<Long> ids = getRawContacts(c, contactID, rawContactID);
for (long id: ids){
ContentProviderOperation.Builder builder = ContentProviderOperation
.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI);
builder.withValue(
ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, rawContactID);
builder.withValue(
ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, id);
builder.withValue(
ContactsContract.AggregationExceptions.TYPE,ContactsContract.AggregationExceptions.TYPE_KEEP_SEPARATE);
operationList.add(builder.build());
}
if(operationList.size() > 0)
try {
c.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
cursor.close();
}
public static Photo getPhoto(ContentResolver c, long rawContactId){
Photo photo = new Photo();
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Cursor c1 = c.query(ContactsContract.Data.CONTENT_URI, new String[] {ContactsContract.CommonDataKinds.Photo.PHOTO, ContactsContract.Data.SYNC2, ContactsContract.Data.SYNC3 }, where , null, null);
if (c1.getCount() > 0){
c1.moveToLast();
photo.data = c1.getBlob(c1.getColumnIndex(ContactsContract.CommonDataKinds.Photo.PHOTO));
photo.timestamp = Long.valueOf(c1.getString(c1.getColumnIndex(ContactsContract.Data.SYNC2)));
photo.url = c1.getString(c1.getColumnIndex(ContactsContract.Data.SYNC3));
}
c1.close();
return photo;
}
public static void updateContactPhoto(ContentResolver c, long rawContactId, Photo pic, boolean primary){
ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
//insert new picture
try {
if(pic.data != null) {
//delete old picture
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE + "'";
Log.i(TAG, "Deleting picture: "+where);
ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI);
builder.withSelection(where, null);
operationList.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValue(ContactsContract.CommonDataKinds.Photo.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, pic.data);
builder.withValue(ContactsContract.Data.SYNC2, String.valueOf(pic.timestamp));
builder.withValue(ContactsContract.Data.SYNC3, pic.url);
if (primary)
builder.withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
operationList.add(builder.build());
}
c.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e("ERROR:" , e.toString());
}
}
public static void removeBirthdays(Context c, long rawContactId){
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE
+ "' AND " + ContactsContract.CommonDataKinds.Event.TYPE + " = '" + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY + "'";
c.getContentResolver().delete(ContactsContract.Data.CONTENT_URI, where, null);
}
public static void removeEmails(Context c, long rawContactId){
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE+ "'";
c.getContentResolver().delete(ContactsContract.Data.CONTENT_URI, where, null);
}
public static void addEmail(Context c, long rawContactId, String email){
DeviceUtil.log(c, "adding email", email);
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE+ "'";
Cursor cursor = c.getContentResolver().query(ContactsContract.Data.CONTENT_URI, new String[] { RawContacts.CONTACT_ID}, where, null, null);
if (cursor.getCount() == 0){
ContentValues contentValues = new ContentValues();
//op.put(ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID, );
contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
contentValues.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email);
c.getContentResolver().insert(ContactsContract.Data.CONTENT_URI, contentValues);
}
cursor.close();
}
public static void addBirthday(long rawContactId, String birthday){
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE
+ "' AND " + ContactsContract.CommonDataKinds.Event.TYPE + " = '" + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY + "'";
Cursor cursor = ContactsSyncAdapterService.mContentResolver.query(ContactsContract.Data.CONTENT_URI, null, where, null, null);
int count = cursor.getCount();
cursor.close();
if (count <= 0){
ContentValues contentValues = new ContentValues();
contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
contentValues.put(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY);
contentValues.put(ContactsContract.CommonDataKinds.Event.START_DATE, birthday);
try {
ContactsSyncAdapterService.mContentResolver.insert(ContactsContract.Data.CONTENT_URI, contentValues);
// mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
e.printStackTrace();
//Log.e("ERROR:" , e.^);
}
}
}
public static void removeContactLocations(Context c, Account account){
ContactsSyncAdapterService.mContentResolver = c.getContentResolver();
HashMap<String, ContactsSyncAdapterService.SyncEntry> localContacts = ContactsSyncAdapterService.getLocalContacts(account);
for (ContactsSyncAdapterService.SyncEntry s : localContacts.values()){
ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI, ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + "' AND " + ContactsContract.Data.RAW_CONTACT_ID + " = " + s.raw_id, null);
}
}
public static void updateContactLocation(long rawContactId, String country, String region, String city){
if ((country == null || country.equals("")) && (region == null || region.equals("")) && (city == null || city.equals(""))){
return;
}
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE + "'";
String[] projection = {ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, ContactsContract.CommonDataKinds.StructuredPostal.REGION, ContactsContract.CommonDataKinds.StructuredPostal.CITY};
Cursor cursor = ContactsSyncAdapterService.mContentResolver.query(ContactsContract.Data.CONTENT_URI, projection, where, null, null);
boolean insert = false;
if (cursor.getCount() == 0){
insert = true;
} else{
cursor.moveToFirst();
String oldCountry = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY));
String oldRegion = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION));
String oldCity = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY));
if ((oldCountry != null && !oldCountry.equals(country)) || (oldRegion != null && !oldRegion.equals(region)) || (oldCity != null && oldCity.equals(city))){
ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI, where, null);
insert = true;
}
}
cursor.close();
if (insert){
ContentValues contentValues = new ContentValues();
//op.put(ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID, );
contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
if (country != null && ! country.equals("")){
contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, country);
} if (region != null && ! region.equals("")){
contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, region);
} if (city != null && ! city.equals("")){
contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, city);
}
try {
ContactsSyncAdapterService.mContentResolver.insert(ContactsContract.Data.CONTENT_URI, contentValues);
// mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
e.printStackTrace();
//Log.e("ERROR:" , e.^);
}
}
}
public static void updateContactLocation(long rawContactId, String location){
if ((location == null || location.equals(""))){
return;
}
String where = ContactsContract.Data.RAW_CONTACT_ID + " = '" + rawContactId
+ "' AND " + ContactsContract.Data.MIMETYPE + " = '" + StructuredPostal.CONTENT_ITEM_TYPE + "'";
String[] projection = {StructuredPostal.FORMATTED_ADDRESS};
Cursor cursor = ContactsSyncAdapterService.mContentResolver.query(ContactsContract.Data.CONTENT_URI, projection, where, null, null);
boolean insert = false;
if (cursor.getCount() == 0){
insert = true;
} else{
cursor.moveToFirst();
String oldloc = cursor.getString(cursor.getColumnIndex(StructuredPostal.FORMATTED_ADDRESS));
if ((oldloc == null) || (!oldloc.equals(location))){
ContactsSyncAdapterService.mContentResolver.delete(ContactsContract.Data.CONTENT_URI, where, null);
insert = true;
}
}
cursor.close();
if (insert){
ContentValues contentValues = new ContentValues();
//op.put(ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID, );
contentValues.put(ContactsContract.Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
contentValues.put(StructuredPostal.FORMATTED_ADDRESS, location);
try {
ContactsSyncAdapterService.mContentResolver.insert(ContactsContract.Data.CONTENT_URI, contentValues);
// mContentResolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (Exception e) {
e.printStackTrace();
//Log.e("ERROR:" , e.^);
}
}
}
}