blob: 091f37a547f2530d30371d33d89acbbabf8388f7 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.loaderapp.model;
import com.android.loaderapp.R;
import com.android.loaderapp.model.EntityDelta.ValuesDelta;
import com.google.android.collect.Lists;
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
import java.util.ArrayList;
public class GoogleSource extends FallbackSource {
public static final String ACCOUNT_TYPE = "com.google";
public GoogleSource(String resPackageName) {
this.accountType = ACCOUNT_TYPE;
this.resPackageName = null;
this.summaryResPackageName = resPackageName;
}
@Override
protected void inflate(Context context, int inflateLevel) {
inflateStructuredName(context, inflateLevel);
inflateNickname(context, inflateLevel);
inflatePhone(context, inflateLevel);
inflateEmail(context, inflateLevel);
inflateStructuredPostal(context, inflateLevel);
inflateIm(context, inflateLevel);
inflateOrganization(context, inflateLevel);
inflatePhoto(context, inflateLevel);
inflateNote(context, inflateLevel);
inflateWebsite(context, inflateLevel);
inflateEvent(context, inflateLevel);
// TODO: GOOGLE: GROUPMEMBERSHIP
setInflatedLevel(inflateLevel);
}
@Override
protected DataKind inflateStructuredName(Context context, int inflateLevel) {
return super.inflateStructuredName(context, inflateLevel);
}
@Override
protected DataKind inflateNickname(Context context, int inflateLevel) {
return super.inflateNickname(context, inflateLevel);
}
@Override
protected DataKind inflatePhone(Context context, int inflateLevel) {
final DataKind kind = super.inflatePhone(context, ContactsSource.LEVEL_MIMETYPES);
if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
kind.typeColumn = Phone.TYPE;
kind.typeList = Lists.newArrayList();
kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
kind.typeList.add(buildPhoneType(Phone.TYPE_OTHER));
kind.typeList.add(buildPhoneType(Phone.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
Phone.LABEL));
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
}
return kind;
}
@Override
protected DataKind inflateEmail(Context context, int inflateLevel) {
final DataKind kind = super.inflateEmail(context, ContactsSource.LEVEL_MIMETYPES);
if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
kind.typeColumn = Email.TYPE;
kind.typeList = Lists.newArrayList();
kind.typeList.add(buildEmailType(Email.TYPE_HOME));
kind.typeList.add(buildEmailType(Email.TYPE_WORK));
kind.typeList.add(buildEmailType(Email.TYPE_OTHER));
kind.typeList.add(buildEmailType(Email.TYPE_CUSTOM).setSecondary(true).setCustomColumn(
Email.LABEL));
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(Email.DATA, R.string.emailLabelsGroup, FLAGS_EMAIL));
}
return kind;
}
@Override
protected DataKind inflateStructuredPostal(Context context, int inflateLevel) {
return super.inflateStructuredPostal(context, inflateLevel);
}
@Override
protected DataKind inflateIm(Context context, int inflateLevel) {
return super.inflateIm(context, inflateLevel);
}
@Override
protected DataKind inflateOrganization(Context context, int inflateLevel) {
return super.inflateOrganization(context, inflateLevel);
}
@Override
protected DataKind inflatePhoto(Context context, int inflateLevel) {
return super.inflatePhoto(context, inflateLevel);
}
@Override
protected DataKind inflateNote(Context context, int inflateLevel) {
return super.inflateNote(context, inflateLevel);
}
@Override
protected DataKind inflateWebsite(Context context, int inflateLevel) {
return super.inflateWebsite(context, inflateLevel);
}
// TODO: this should come from resource in the future
// Note that frameworks/base/core/java/android/pim/vcard/ContactStruct.java also wants
// this String.
private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts";
public static final void attemptMyContactsMembership(EntityDelta state, Context context) {
final ValuesDelta stateValues = state.getValues();
stateValues.setFromTemplate(true);
final String accountName = stateValues.getAsString(RawContacts.ACCOUNT_NAME);
final String accountType = stateValues.getAsString(RawContacts.ACCOUNT_TYPE);
attemptMyContactsMembership(state, accountName, accountType, context, true);
}
public static final void createMyContactsIfNotExist(Account account, Context context) {
attemptMyContactsMembership(null, account.name, account.type, context, true);
}
/**
*
* @param allowRecur If the group is created between querying/about to create, we recur. But
* to prevent excess recursion, we provide a flag to make sure we only do the recursion loop
* once
*/
private static final void attemptMyContactsMembership(EntityDelta state,
final String accountName, final String accountType, Context context,
boolean allowRecur) {
final ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(Groups.CONTENT_URI,
new String[] {Groups.TITLE, Groups.SOURCE_ID, Groups.SHOULD_SYNC},
Groups.ACCOUNT_NAME + " =? AND " + Groups.ACCOUNT_TYPE + " =?",
new String[] {accountName, accountType}, null);
boolean myContactsExists = false;
long assignToGroupSourceId = -1;
while (cursor.moveToNext()) {
if (GOOGLE_MY_CONTACTS_GROUP.equals(cursor.getString(0))) {
myContactsExists = true;
}
if (assignToGroupSourceId == -1 && cursor.getInt(2) != 0) {
assignToGroupSourceId = cursor.getInt(1);
}
if (myContactsExists && assignToGroupSourceId != -1) {
break;
}
}
if (myContactsExists && state == null) {
return;
}
try {
final ContentValues values = new ContentValues();
values.put(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
if (!myContactsExists) {
// create the group if it doesn't exist
final ContentValues newGroup = new ContentValues();
newGroup.put(Groups.TITLE, GOOGLE_MY_CONTACTS_GROUP);
newGroup.put(Groups.ACCOUNT_NAME, accountName);
newGroup.put(Groups.ACCOUNT_TYPE, accountType);
newGroup.put(Groups.GROUP_VISIBLE, "1");
ArrayList<ContentProviderOperation> operations =
new ArrayList<ContentProviderOperation>();
operations.add(ContentProviderOperation
.newAssertQuery(Groups.CONTENT_URI)
.withSelection(Groups.TITLE + "=?",
new String[] { GOOGLE_MY_CONTACTS_GROUP })
.withExpectedCount(0).build());
operations.add(ContentProviderOperation
.newInsert(Groups.CONTENT_URI)
.withValues(newGroup)
.build());
try {
ContentProviderResult[] results = resolver.applyBatch(
ContactsContract.AUTHORITY, operations);
values.put(GroupMembership.GROUP_ROW_ID, ContentUris.parseId(results[1].uri));
} catch (RemoteException e) {
throw new IllegalStateException("Problem querying for groups", e);
} catch (OperationApplicationException e) {
// the group was created after the query but before we tried to create it
if (allowRecur) {
attemptMyContactsMembership(
state, accountName, accountType, context, false);
}
return;
}
} else {
if (assignToGroupSourceId != -1) {
values.put(GroupMembership.GROUP_SOURCE_ID, assignToGroupSourceId);
} else {
// there are no Groups to add this contact to, so don't apply any membership
// TODO: alert user that their contact will be dropped?
}
}
if (state != null) {
state.addEntry(ValuesDelta.fromAfter(values));
}
} finally {
cursor.close();
}
}
@Override
public int getHeaderColor(Context context) {
return 0xff89c2c2;
}
@Override
public int getSideBarColor(Context context) {
return 0xff5bb4b4;
}
}