diff --git a/samples/SampleSyncAdapter/AndroidManifest.xml b/samples/SampleSyncAdapter/AndroidManifest.xml index 285abfba8..48f6fadcd 100644 --- a/samples/SampleSyncAdapter/AndroidManifest.xml +++ b/samples/SampleSyncAdapter/AndroidManifest.xml @@ -45,8 +45,12 @@ android:name="android.permission.READ_SYNC_SETTINGS" /> + + - + execute() { + List resultUris = new ArrayList(); if (mOperations.size() == 0) { - return result; + return resultUris; } // Apply the mOperations to the content provider try { ContentProviderResult[] results = mResolver.applyBatch(ContactsContract.AUTHORITY, mOperations); - if ((results != null) && (results.length > 0)) - result = results[0].uri; + if ((results != null) && (results.length > 0)){ + for (int i = 0; i < results.length; i++){ + resultUris.add(results[i].uri); + } + } } catch (final OperationApplicationException e1) { Log.e(TAG, "storing contact data failed", e1); } catch (final RemoteException e2) { Log.e(TAG, "storing contact data failed", e2); } mOperations.clear(); - return result; + return resultUris; } } diff --git a/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java b/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java index 6b2dfb14c..5b09eb165 100644 --- a/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java +++ b/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java @@ -24,7 +24,10 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; +import android.content.res.AssetFileDescriptor; import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Email; @@ -38,8 +41,14 @@ import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.Settings; import android.provider.ContactsContract.StatusUpdates; +import android.provider.ContactsContract.StreamItemPhotos; +import android.provider.ContactsContract.StreamItems; import android.util.Log; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -234,6 +243,43 @@ public class ContactManager { batchOperation.execute(); } + /** + * Demonstrate how to add stream items and stream item photos to a raw + * contact. This just adds items for all of the contacts for this sync + * adapter with some locally created text and an image. You should check + * for stream items on the server that you are syncing with and use the + * text and photo data from there instead. + * + * @param context The context of Authenticator Activity + * @param rawContacts The list of users we want to update + */ + public static void addStreamItems(Context context, List rawContacts, + String accountName, String accountType) { + final ContentResolver resolver = context.getContentResolver(); + final BatchOperation batchOperation = new BatchOperation(context, resolver); + String text = "This is a test stream item!"; + String message = "via SampleSyncAdapter"; + for (RawContact rawContact : rawContacts) { + addContactStreamItem(context, lookupRawContact(resolver, + rawContact.getServerContactId()), accountName, accountType, + text, message, batchOperation ); + } + List streamItemUris = batchOperation.execute(); + + // Stream item photos are added after the stream items that they are + // associated with, using the stream item's ID as a reference. + + for (Uri uri : streamItemUris){ + // All you need is the ID of the stream item, which is the last index + // path segment returned by getPathSegments(). + long streamItemId = Long.parseLong(uri.getPathSegments().get( + uri.getPathSegments().size()-1)); + addStreamItemPhoto(context, resolver, streamItemId, accountName, + accountType, batchOperation); + } + batchOperation.execute(); + } + /** * After we've finished up a sync operation, we want to clean up the sync-state * so that we're ready for the next time. This involves clearing out the 'dirty' @@ -518,7 +564,7 @@ public class ContactManager { * But it's a useful demo to see how it's done. * * @param context the Authenticator Activity context - * @param rawContact the contact who's status we should update + * @param rawContact the contact whose status we should update * @param batchOperation allow us to batch together multiple operations */ private static void updateContactStatus(Context context, RawContact rawContact, @@ -549,6 +595,59 @@ public class ContactManager { } } + /** + * Adds a stream item to a raw contact. The stream item is usually obtained + * from the server you are syncing with, but we create it here locally as an + * example. + * + * @param context the Authenticator Activity context + * @param rawContactId the raw contact ID that the stream item is associated with + * @param accountName the account name of the sync adapter + * @param accountType the account type of the sync adapter + * @param text the text of the stream item + * @param comments the comments for the stream item, such as where the stream item came from + * @param batchOperation allow us to batch together multiple operations + */ + private static void addContactStreamItem(Context context, long rawContactId, + String accountName, String accountType, String text, String comments, + BatchOperation batchOperation) { + + final ContentValues values = new ContentValues(); + final ContentResolver resolver = context.getContentResolver(); + if (rawContactId > 0){ + values.put(StreamItems.RAW_CONTACT_ID, rawContactId); + values.put(StreamItems.TEXT, text); + values.put(StreamItems.TIMESTAMP, System.currentTimeMillis()); + values.put(StreamItems.COMMENTS, comments); + values.put(StreamItems.ACCOUNT_NAME, accountName); + values.put(StreamItems.ACCOUNT_TYPE, accountType); + + batchOperation.add(ContactOperations.newInsertCpo( + StreamItems.CONTENT_URI, false, true).withValues(values).build()); + } + } + + private static void addStreamItemPhoto(Context context, ContentResolver + resolver, long streamItemId, String accountName, String accountType, + BatchOperation batchOperation){ + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), + R.raw.img1); + bitmap.compress(Bitmap.CompressFormat.JPEG, 30, stream); + byte[] photoData = stream.toByteArray(); + + final ContentValues values = new ContentValues(); + values.put(StreamItemPhotos.STREAM_ITEM_ID, streamItemId); + values.put(StreamItemPhotos.SORT_INDEX, 1); + values.put(StreamItemPhotos.PHOTO, photoData); + values.put(StreamItems.ACCOUNT_NAME, accountName); + values.put(StreamItems.ACCOUNT_TYPE, accountType); + + batchOperation.add(ContactOperations.newInsertCpo( + StreamItems.CONTENT_PHOTO_URI, false, true).withValues(values).build()); + } + /** * Clear the local system 'dirty' flag for a contact. * diff --git a/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java b/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java index 0f570cd32..8aa078481 100644 --- a/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java +++ b/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java @@ -32,6 +32,7 @@ import android.content.AbstractThreadedSyncAdapter; import android.content.ContentProviderClient; import android.content.Context; import android.content.SyncResult; +import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -115,8 +116,21 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter { // 2-way contact sync providers - it's more likely that one-way // sync providers (IM clients, social networking apps, etc) would // use this feature. + ContactManager.updateStatusMessages(mContext, updatedContacts); + // This is a demo of how you can add stream items for contacts on + // the client. This probably won't apply to + // 2-way contact sync providers - it's more likely that one-way + // sync providers (IM clients, social networking apps, etc) would + // use this feature. This is only supported in ICS MR1 or above. + + if (Build.VERSION.SDK_INT >= + Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + ContactManager.addStreamItems(mContext, updatedContacts, + account.name, account.type); + } + // Save off the new sync marker. On our next sync, we only want to receive // contacts that have changed since this sync... setServerSyncMarker(account, newSyncState); @@ -168,3 +182,4 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter { mAccountManager.setUserData(account, SYNC_MARKER_KEY, Long.toString(marker)); } } +