diff --git a/samples/SampleSyncAdapter/AndroidManifest.xml b/samples/SampleSyncAdapter/AndroidManifest.xml
index 25e9e9926..285abfba8 100644
--- a/samples/SampleSyncAdapter/AndroidManifest.xml
+++ b/samples/SampleSyncAdapter/AndroidManifest.xml
@@ -46,7 +46,7 @@
-
+
-
-
-
-
-
-
-
-
-
-
+ android:name=".activites.InviteContactActivity"
+ android:theme="@android:style/Theme.Dialog">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/SampleSyncAdapter/res/drawable/border.xml b/samples/SampleSyncAdapter/res/drawable/border.xml
deleted file mode 100644
index ab71f2c28..000000000
--- a/samples/SampleSyncAdapter/res/drawable/border.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/SampleSyncAdapter/res/drawable/done_menu_icon.png b/samples/SampleSyncAdapter/res/drawable/done_menu_icon.png
deleted file mode 100644
index 3468bbd5f..000000000
Binary files a/samples/SampleSyncAdapter/res/drawable/done_menu_icon.png and /dev/null differ
diff --git a/samples/SampleSyncAdapter/res/layout-xlarge/editor.xml b/samples/SampleSyncAdapter/res/layout-xlarge/editor.xml
deleted file mode 100644
index 3b7d97b4c..000000000
--- a/samples/SampleSyncAdapter/res/layout-xlarge/editor.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/SampleSyncAdapter/res/layout-xlarge/editor_header.xml b/samples/SampleSyncAdapter/res/layout-xlarge/editor_header.xml
deleted file mode 100644
index 648e6f98d..000000000
--- a/samples/SampleSyncAdapter/res/layout-xlarge/editor_header.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/SampleSyncAdapter/res/layout/editor_fields.xml b/samples/SampleSyncAdapter/res/layout/editor_fields.xml
deleted file mode 100644
index 31d0128c1..000000000
--- a/samples/SampleSyncAdapter/res/layout/editor_fields.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/SampleSyncAdapter/res/layout/editor.xml b/samples/SampleSyncAdapter/res/layout/invite_contact_activity.xml
similarity index 60%
rename from samples/SampleSyncAdapter/res/layout/editor.xml
rename to samples/SampleSyncAdapter/res/layout/invite_contact_activity.xml
index a0c36d2fa..1e09d5be1 100644
--- a/samples/SampleSyncAdapter/res/layout/editor.xml
+++ b/samples/SampleSyncAdapter/res/layout/invite_contact_activity.xml
@@ -18,19 +18,15 @@
-->
-
-
-
-
-
-
\ No newline at end of file
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+
+
diff --git a/samples/SampleSyncAdapter/res/layout/login_activity.xml b/samples/SampleSyncAdapter/res/layout/login_activity.xml
index 7408ffe97..6c93f9073 100644
--- a/samples/SampleSyncAdapter/res/layout/login_activity.xml
+++ b/samples/SampleSyncAdapter/res/layout/login_activity.xml
@@ -55,7 +55,8 @@
android:scrollHorizontally="true"
android:capitalize="none"
android:autoText="false"
- android:inputType="textEmailAddress" />
+ android:inputType="textEmailAddress"
+ android:text="user" />
+ android:inputType="textPassword"
+ android:text="test" />
+
+
+
+
+
diff --git a/samples/SampleSyncAdapter/res/layout/view_stream_item_activity.xml b/samples/SampleSyncAdapter/res/layout/view_stream_item_activity.xml
new file mode 100644
index 000000000..a04d07fe2
--- /dev/null
+++ b/samples/SampleSyncAdapter/res/layout/view_stream_item_activity.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
diff --git a/samples/SampleSyncAdapter/res/layout/view_stream_item_photo_activity.xml b/samples/SampleSyncAdapter/res/layout/view_stream_item_photo_activity.xml
new file mode 100644
index 000000000..ddc09d098
--- /dev/null
+++ b/samples/SampleSyncAdapter/res/layout/view_stream_item_photo_activity.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
diff --git a/samples/SampleSyncAdapter/res/menu/edit.xml b/samples/SampleSyncAdapter/res/menu/edit.xml
deleted file mode 100644
index 1227584ea..000000000
--- a/samples/SampleSyncAdapter/res/menu/edit.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
diff --git a/samples/SampleSyncAdapter/res/values/strings.xml b/samples/SampleSyncAdapter/res/values/strings.xml
index 7ac95f586..22fe14ec7 100644
--- a/samples/SampleSyncAdapter/res/values/strings.xml
+++ b/samples/SampleSyncAdapter/res/values/strings.xml
@@ -109,4 +109,34 @@
Add to Sample SyncAdaper
+
+ Congratulations! The user wants to add the contact
+ to the amazing Sample SyncAdapter social network. If this was a real app, it should now
+ make best efforts to add the contact to this network. This would probably involve
+ looking up the person on the network, inviting if he is not there already and syncing
+ the new contact down.
+
+ Ideally, when the user gets back to the People app, the new contact should already
+ be there, enriching the original contact.
+
+ This is the information we got to lookup the contact:
+
+
+ Show sample group details
+
+
+ This would now show the details of the group.
+
+ This is the group uri:
+
+
+ This would now show the details of the stream item.
+
+ This is the uri of the stream item:
+
+
+ This would now show the details of the stream item photo.
+
+ This is the uri of the photo:
+
\ No newline at end of file
diff --git a/samples/SampleSyncAdapter/res/values/styles.xml b/samples/SampleSyncAdapter/res/values/styles.xml
deleted file mode 100644
index 074613e40..000000000
--- a/samples/SampleSyncAdapter/res/values/styles.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
- #ffffff
- #cccccc
-
-
diff --git a/samples/SampleSyncAdapter/res/xml-v11/contacts.xml b/samples/SampleSyncAdapter/res/xml-v11/contacts.xml
index 62dfa8009..48cf503c6 100644
--- a/samples/SampleSyncAdapter/res/xml-v11/contacts.xml
+++ b/samples/SampleSyncAdapter/res/xml-v11/contacts.xml
@@ -19,8 +19,6 @@
-
{
-
- @Override
- protected Cursor doInBackground(Uri... params) {
- // Our background task is to load the contact from the Contacts provider
- return getContentResolver().query(params[0], EditorQuery.PROJECTION, null, null, null);
- }
-
- @Override
- protected void onPostExecute(Cursor cursor) {
- if (cursor == null) return;
- // After we've successfully loaded the contact, call back into
- // the ContactEditorActivity so we can update the UI
- try {
- onRawContactEntityLoaded(cursor);
- } finally {
- cursor.close();
- }
- }
- }
-
- /**
- * Represents an asynchronous task used to save a new contact
- * into the contacts database.
- */
- public class InsertContactTask extends AsyncTask {
-
- @Override
- protected Uri doInBackground(RawContact... params) {
- try {
- final RawContact rawContact = params[0];
- final Context context = getApplicationContext();
- final ContentResolver resolver = getContentResolver();
- final BatchOperation batchOperation = new BatchOperation(context, resolver);
- ContactManager.addContact(context, mAccountName, rawContact, false, batchOperation);
- Uri rawContactUri = batchOperation.execute();
-
- // Convert the raw contact URI to a contact URI
- if (rawContactUri != null) {
- return RawContacts.getContactLookupUri(resolver, rawContactUri);
- } else {
- Log.e(TAG, "Could not save new contact");
- return null;
- }
- } catch (Exception e) {
- Log.e(TAG, "An error occurred while saving new contact", e);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Uri result) {
- // Tell the UI that the contact has been successfully saved
- onContactSaved(result);
- }
- }
-
-
- /**
- * Represents an asynchronous task used to save an updated contact
- * into the contacts database.
- */
- public class UpdateContactTask extends AsyncTask {
-
- @Override
- protected Uri doInBackground(RawContact... params) {
- try {
- final RawContact rawContact = params[0];
- final Context context = getApplicationContext();
- final ContentResolver resolver = getContentResolver();
- final BatchOperation batchOperation = new BatchOperation(context, resolver);
- ContactManager.updateContact(context, resolver, rawContact, false, false, false,
- false, rawContact.getRawContactId(), batchOperation);
- batchOperation.execute();
-
- // Convert the raw contact URI to a contact URI
- return RawContacts.getContactLookupUri(resolver, mRawContactUri);
- } catch (Exception e) {
- Log.e(TAG, "Could not save changes", e);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Uri result) {
- // Tell the UI that the contact has been successfully saved
- onContactSaved(result);
- }
- }
-
- /**
- * Loads contact information by a lookup URI.
- */
- public class LoadContactTask extends AsyncTask {
-
- @Override
- protected Cursor doInBackground(Uri... params) {
- return getContentResolver().query(params[0], ContactQuery.PROJECTION, null, null, null);
- }
-
- @Override
- protected void onPostExecute(Cursor cursor) {
- if (cursor == null) return;
- try {
- onContactEntityLoaded(cursor);
- } finally {
- cursor.close();
- }
- }
- }
-}
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 035c9766f..6b2dfb14c 100644
--- a/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java
+++ b/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactManager.java
@@ -34,6 +34,7 @@ import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.Settings;
import android.provider.ContactsContract.StatusUpdates;
@@ -54,6 +55,41 @@ public class ContactManager {
private static final String TAG = "ContactManager";
+ public static final String SAMPLE_GROUP_NAME = "Sample Group";
+
+ public static long ensureSampleGroupExists(Context context, Account account) {
+ final ContentResolver resolver = context.getContentResolver();
+
+ // Lookup the sample group
+ long groupId = 0;
+ final Cursor cursor = resolver.query(Groups.CONTENT_URI, new String[] { Groups._ID },
+ Groups.ACCOUNT_NAME + "=? AND " + Groups.ACCOUNT_TYPE + "=? AND " +
+ Groups.TITLE + "=?",
+ new String[] { account.name, account.type, SAMPLE_GROUP_NAME }, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ groupId = cursor.getLong(0);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+
+ if (groupId == 0) {
+ // Sample group doesn't exist yet, so create it
+ final ContentValues contentValues = new ContentValues();
+ contentValues.put(Groups.ACCOUNT_NAME, account.name);
+ contentValues.put(Groups.ACCOUNT_TYPE, account.type);
+ contentValues.put(Groups.TITLE, SAMPLE_GROUP_NAME);
+ contentValues.put(Groups.GROUP_IS_READ_ONLY, true);
+
+ final Uri newGroupUri = resolver.insert(Groups.CONTENT_URI, contentValues);
+ groupId = ContentUris.parseId(newGroupUri);
+ }
+ return groupId;
+ }
+
/**
* Take a list of updated contacts and apply those changes to the
* contacts database. Typically this list of contacts would have been
@@ -67,7 +103,7 @@ public class ContactManager {
* sync request.
*/
public static synchronized long updateContacts(Context context, String account,
- List rawContacts, long lastSyncMarker) {
+ List rawContacts, long groupId, long lastSyncMarker) {
long currentSyncMarker = lastSyncMarker;
final ContentResolver resolver = context.getContentResolver();
@@ -112,7 +148,7 @@ public class ContactManager {
Log.d(TAG, "In addContact");
if (!rawContact.isDeleted()) {
newUsers.add(rawContact);
- addContact(context, account, rawContact, true, batchOperation);
+ addContact(context, account, rawContact, groupId, true, batchOperation);
}
}
// A sync adapter should batch operations on multiple contacts,
@@ -235,12 +271,13 @@ public class ContactManager {
* @param context the Authenticator Activity context
* @param accountName the account the contact belongs to
* @param rawContact the sample SyncAdapter User object
+ * @param groupId the id of the sample group
* @param inSync is the add part of a client-server sync?
* @param batchOperation allow us to batch together multiple operations
* into a single provider call
*/
public static void addContact(Context context, String accountName, RawContact rawContact,
- boolean inSync, BatchOperation batchOperation) {
+ long groupId, boolean inSync, BatchOperation batchOperation) {
// Put the data in the contacts provider
final ContactOperations contactOp = ContactOperations.createNewContact(
@@ -252,6 +289,7 @@ public class ContactManager {
.addPhone(rawContact.getCellPhone(), Phone.TYPE_MOBILE)
.addPhone(rawContact.getHomePhone(), Phone.TYPE_HOME)
.addPhone(rawContact.getOfficePhone(), Phone.TYPE_WORK)
+ .addGroupMembership(groupId)
.addAvatar(rawContact.getAvatarUrl());
// If we have a serverId, then go ahead and create our status profile.
diff --git a/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactOperations.java b/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactOperations.java
index cb8e97b8e..1445e55dd 100644
--- a/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactOperations.java
+++ b/samples/SampleSyncAdapter/src/com/example/android/samplesync/platform/ContactOperations.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
@@ -185,6 +186,20 @@ public class ContactOperations {
return this;
}
+ /**
+ * Adds a group membership
+ *
+ * @param id The id of the group to assign
+ * @return instance of ContactOperations
+ */
+ public ContactOperations addGroupMembership(long groupId) {
+ mValues.clear();
+ mValues.put(GroupMembership.GROUP_ROW_ID, groupId);
+ mValues.put(GroupMembership.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE);
+ addInsertOp();
+ return this;
+ }
+
public ContactOperations addAvatar(String avatarUrl) {
if (avatarUrl != null) {
byte[] avatarBuffer = NetworkUtilities.downloadAvatar(avatarUrl);
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 0ca8dee5b..0f570cd32 100644
--- a/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java
+++ b/samples/SampleSyncAdapter/src/com/example/android/samplesync/syncadapter/SyncAdapter.java
@@ -15,6 +15,15 @@
*/
package com.example.android.samplesync.syncadapter;
+import com.example.android.samplesync.Constants;
+import com.example.android.samplesync.client.NetworkUtilities;
+import com.example.android.samplesync.client.RawContact;
+import com.example.android.samplesync.platform.ContactManager;
+
+import org.apache.http.ParseException;
+import org.apache.http.auth.AuthenticationException;
+import org.json.JSONException;
+
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorException;
@@ -27,18 +36,7 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
-import com.example.android.samplesync.Constants;
-import com.example.android.samplesync.client.NetworkUtilities;
-import com.example.android.samplesync.client.RawContact;
-import com.example.android.samplesync.platform.ContactManager;
-
-import org.apache.http.ParseException;
-import org.apache.http.auth.AuthenticationException;
-import org.json.JSONException;
-
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
/**
@@ -91,6 +89,9 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
final String authtoken = mAccountManager.blockingGetAuthToken(account,
Constants.AUTHTOKEN_TYPE, NOTIFY_AUTH_FAILURE);
+ // Make sure that the sample group exists
+ final long groupId = ContactManager.ensureSampleGroupExists(mContext, account);
+
// Find the local 'dirty' contacts that we need to tell the server about...
// Find the local users that need to be sync'd to the server...
dirtyContacts = ContactManager.getDirtyContacts(mContext, account);
@@ -106,6 +107,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
long newSyncState = ContactManager.updateContacts(mContext,
account.name,
updatedContacts,
+ groupId,
lastSyncMarker);
// This is a demo of how you can update IM-style status messages