1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 17 package com.example.android.samplesync.platform; 18 19 import android.content.ContentProviderOperation; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.net.Uri; 23 import android.provider.ContactsContract; 24 import android.provider.ContactsContract.Data; 25 import android.provider.ContactsContract.RawContacts; 26 import android.provider.ContactsContract.CommonDataKinds.Email; 27 import android.provider.ContactsContract.CommonDataKinds.Phone; 28 import android.provider.ContactsContract.CommonDataKinds.StructuredName; 29 import android.text.TextUtils; 30 import android.util.Log; 31 32 import com.example.android.samplesync.Constants; 33 import com.example.android.samplesync.R; 34 35 /** 36 * Helper class for storing data in the platform content providers. 37 */ 38 public class ContactOperations { 39 40 private final ContentValues mValues; 41 private ContentProviderOperation.Builder mBuilder; 42 private final BatchOperation mBatchOperation; 43 private final Context mContext; 44 private boolean mYield; 45 private long mRawContactId; 46 private int mBackReference; 47 private boolean mIsNewContact; 48 49 /** 50 * Returns an instance of ContactOperations instance for adding new contact 51 * to the platform contacts provider. 52 * 53 * @param context the Authenticator Activity context 54 * @param userId the userId of the sample SyncAdapter user object 55 * @param accountName the username of the current login 56 * @return instance of ContactOperations 57 */ createNewContact(Context context, int userId, String accountName, BatchOperation batchOperation)58 public static ContactOperations createNewContact(Context context, 59 int userId, String accountName, BatchOperation batchOperation) { 60 return new ContactOperations(context, userId, accountName, 61 batchOperation); 62 } 63 64 /** 65 * Returns an instance of ContactOperations for updating existing contact in 66 * the platform contacts provider. 67 * 68 * @param context the Authenticator Activity context 69 * @param rawContactId the unique Id of the existing rawContact 70 * @return instance of ContactOperations 71 */ updateExistingContact(Context context, long rawContactId, BatchOperation batchOperation)72 public static ContactOperations updateExistingContact(Context context, 73 long rawContactId, BatchOperation batchOperation) { 74 return new ContactOperations(context, rawContactId, batchOperation); 75 } 76 ContactOperations(Context context, BatchOperation batchOperation)77 public ContactOperations(Context context, BatchOperation batchOperation) { 78 mValues = new ContentValues(); 79 mYield = true; 80 mContext = context; 81 mBatchOperation = batchOperation; 82 } 83 ContactOperations(Context context, int userId, String accountName, BatchOperation batchOperation)84 public ContactOperations(Context context, int userId, String accountName, 85 BatchOperation batchOperation) { 86 this(context, batchOperation); 87 mBackReference = mBatchOperation.size(); 88 mIsNewContact = true; 89 mValues.put(RawContacts.SOURCE_ID, userId); 90 mValues.put(RawContacts.ACCOUNT_TYPE, Constants.ACCOUNT_TYPE); 91 mValues.put(RawContacts.ACCOUNT_NAME, accountName); 92 mBuilder = 93 newInsertCpo(RawContacts.CONTENT_URI, true).withValues(mValues); 94 mBatchOperation.add(mBuilder.build()); 95 } 96 ContactOperations(Context context, long rawContactId, BatchOperation batchOperation)97 public ContactOperations(Context context, long rawContactId, 98 BatchOperation batchOperation) { 99 this(context, batchOperation); 100 mIsNewContact = false; 101 mRawContactId = rawContactId; 102 } 103 104 /** 105 * Adds a contact name 106 * 107 * @param name Name of contact 108 * @param nameType type of name: family name, given name, etc. 109 * @return instance of ContactOperations 110 */ addName(String firstName, String lastName)111 public ContactOperations addName(String firstName, String lastName) { 112 mValues.clear(); 113 if (!TextUtils.isEmpty(firstName)) { 114 mValues.put(StructuredName.GIVEN_NAME, firstName); 115 mValues.put(StructuredName.MIMETYPE, 116 StructuredName.CONTENT_ITEM_TYPE); 117 } 118 if (!TextUtils.isEmpty(lastName)) { 119 mValues.put(StructuredName.FAMILY_NAME, lastName); 120 mValues.put(StructuredName.MIMETYPE, 121 StructuredName.CONTENT_ITEM_TYPE); 122 } 123 if (mValues.size() > 0) { 124 addInsertOp(); 125 } 126 return this; 127 } 128 129 /** 130 * Adds an email 131 * 132 * @param new email for user 133 * @return instance of ContactOperations 134 */ addEmail(String email)135 public ContactOperations addEmail(String email) { 136 mValues.clear(); 137 if (!TextUtils.isEmpty(email)) { 138 mValues.put(Email.DATA, email); 139 mValues.put(Email.TYPE, Email.TYPE_OTHER); 140 mValues.put(Email.MIMETYPE, Email.CONTENT_ITEM_TYPE); 141 addInsertOp(); 142 } 143 return this; 144 } 145 146 /** 147 * Adds a phone number 148 * 149 * @param phone new phone number for the contact 150 * @param phoneType the type: cell, home, etc. 151 * @return instance of ContactOperations 152 */ addPhone(String phone, int phoneType)153 public ContactOperations addPhone(String phone, int phoneType) { 154 mValues.clear(); 155 if (!TextUtils.isEmpty(phone)) { 156 mValues.put(Phone.NUMBER, phone); 157 mValues.put(Phone.TYPE, phoneType); 158 mValues.put(Phone.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 159 addInsertOp(); 160 } 161 return this; 162 } 163 164 /** 165 * Adds a profile action 166 * 167 * @param userId the userId of the sample SyncAdapter user object 168 * @return instance of ContactOperations 169 */ addProfileAction(long userId)170 public ContactOperations addProfileAction(long userId) { 171 mValues.clear(); 172 if (userId != 0) { 173 mValues.put(SampleSyncAdapterColumns.DATA_PID, userId); 174 mValues.put(SampleSyncAdapterColumns.DATA_SUMMARY, mContext 175 .getString(R.string.profile_action)); 176 mValues.put(SampleSyncAdapterColumns.DATA_DETAIL, mContext 177 .getString(R.string.view_profile)); 178 mValues.put(Data.MIMETYPE, SampleSyncAdapterColumns.MIME_PROFILE); 179 addInsertOp(); 180 } 181 return this; 182 } 183 184 /** 185 * Updates contact's email 186 * 187 * @param email email id of the sample SyncAdapter user 188 * @param uri Uri for the existing raw contact to be updated 189 * @return instance of ContactOperations 190 */ updateEmail(String email, String existingEmail, Uri uri)191 public ContactOperations updateEmail(String email, String existingEmail, 192 Uri uri) { 193 if (!TextUtils.equals(existingEmail, email)) { 194 mValues.clear(); 195 mValues.put(Email.DATA, email); 196 addUpdateOp(uri); 197 } 198 return this; 199 } 200 201 /** 202 * Updates contact's name 203 * 204 * @param name Name of contact 205 * @param existingName Name of contact stored in provider 206 * @param nameType type of name: family name, given name, etc. 207 * @param uri Uri for the existing raw contact to be updated 208 * @return instance of ContactOperations 209 */ updateName(Uri uri, String existingFirstName, String existingLastName, String firstName, String lastName)210 public ContactOperations updateName(Uri uri, String existingFirstName, 211 String existingLastName, String firstName, String lastName) { 212 Log.i("ContactOperations", "ef=" + existingFirstName + "el=" 213 + existingLastName + "f=" + firstName + "l=" + lastName); 214 mValues.clear(); 215 if (!TextUtils.equals(existingFirstName, firstName)) { 216 mValues.put(StructuredName.GIVEN_NAME, firstName); 217 } 218 if (!TextUtils.equals(existingLastName, lastName)) { 219 mValues.put(StructuredName.FAMILY_NAME, lastName); 220 } 221 if (mValues.size() > 0) { 222 addUpdateOp(uri); 223 } 224 return this; 225 } 226 227 /** 228 * Updates contact's phone 229 * 230 * @param existingNumber phone number stored in contacts provider 231 * @param phone new phone number for the contact 232 * @param uri Uri for the existing raw contact to be updated 233 * @return instance of ContactOperations 234 */ updatePhone(String existingNumber, String phone, Uri uri)235 public ContactOperations updatePhone(String existingNumber, String phone, 236 Uri uri) { 237 if (!TextUtils.equals(phone, existingNumber)) { 238 mValues.clear(); 239 mValues.put(Phone.NUMBER, phone); 240 addUpdateOp(uri); 241 } 242 return this; 243 } 244 245 /** 246 * Updates contact's profile action 247 * 248 * @param userId sample SyncAdapter user id 249 * @param uri Uri for the existing raw contact to be updated 250 * @return instance of ContactOperations 251 */ updateProfileAction(Integer userId, Uri uri)252 public ContactOperations updateProfileAction(Integer userId, Uri uri) { 253 mValues.clear(); 254 mValues.put(SampleSyncAdapterColumns.DATA_PID, userId); 255 addUpdateOp(uri); 256 return this; 257 } 258 259 /** 260 * Adds an insert operation into the batch 261 */ addInsertOp()262 private void addInsertOp() { 263 if (!mIsNewContact) { 264 mValues.put(Phone.RAW_CONTACT_ID, mRawContactId); 265 } 266 mBuilder = 267 newInsertCpo(addCallerIsSyncAdapterParameter(Data.CONTENT_URI), 268 mYield); 269 mBuilder.withValues(mValues); 270 if (mIsNewContact) { 271 mBuilder 272 .withValueBackReference(Data.RAW_CONTACT_ID, mBackReference); 273 } 274 mYield = false; 275 mBatchOperation.add(mBuilder.build()); 276 } 277 278 /** 279 * Adds an update operation into the batch 280 */ addUpdateOp(Uri uri)281 private void addUpdateOp(Uri uri) { 282 mBuilder = newUpdateCpo(uri, mYield).withValues(mValues); 283 mYield = false; 284 mBatchOperation.add(mBuilder.build()); 285 } 286 newInsertCpo(Uri uri, boolean yield)287 public static ContentProviderOperation.Builder newInsertCpo(Uri uri, 288 boolean yield) { 289 return ContentProviderOperation.newInsert( 290 addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield); 291 } 292 newUpdateCpo(Uri uri, boolean yield)293 public static ContentProviderOperation.Builder newUpdateCpo(Uri uri, 294 boolean yield) { 295 return ContentProviderOperation.newUpdate( 296 addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield); 297 } 298 newDeleteCpo(Uri uri, boolean yield)299 public static ContentProviderOperation.Builder newDeleteCpo(Uri uri, 300 boolean yield) { 301 return ContentProviderOperation.newDelete( 302 addCallerIsSyncAdapterParameter(uri)).withYieldAllowed(yield); 303 304 } 305 addCallerIsSyncAdapterParameter(Uri uri)306 private static Uri addCallerIsSyncAdapterParameter(Uri uri) { 307 return uri.buildUpon().appendQueryParameter( 308 ContactsContract.CALLER_IS_SYNCADAPTER, "true").build(); 309 } 310 311 } 312