diff options
| author | Chiao Cheng <chiaocheng@google.com> | 2013-03-20 17:22:06 -0700 |
|---|---|---|
| committer | Chiao Cheng <chiaocheng@google.com> | 2013-04-08 14:52:16 -0700 |
| commit | 0a010aef7fcaa8f94ca6072d45a9d9f2d935366e (patch) | |
| tree | b0b9a7b1ecc2046eab5d50d0f33dd95c1aa3222d /samples | |
| parent | a5e017432a4cdbc50872394c0d0c7be475a50890 (diff) | |
| download | android_development-0a010aef7fcaa8f94ca6072d45a9d9f2d935366e.tar.gz android_development-0a010aef7fcaa8f94ca6072d45a9d9f2d935366e.tar.bz2 android_development-0a010aef7fcaa8f94ca6072d45a9d9f2d935366e.zip | |
Adding example of querying for contact changes.
Bug: 8182147
Change-Id: I40a2b95b9e6ac0705b863e0e41f84654dfddaf5c
Diffstat (limited to 'samples')
| -rw-r--r-- | samples/ApiDemos/AndroidManifest.xml | 7 | ||||
| -rw-r--r-- | samples/ApiDemos/res/values/strings.xml | 2 | ||||
| -rw-r--r-- | samples/ApiDemos/src/com/example/android/apis/content/ChangedContacts.java | 348 |
3 files changed, 357 insertions, 0 deletions
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml index ff44b0e95..960bdef9d 100644 --- a/samples/ApiDemos/AndroidManifest.xml +++ b/samples/ApiDemos/AndroidManifest.xml @@ -1168,6 +1168,13 @@ </intent-filter> </activity> + <activity android:name=".content.ChangedContacts" android:label="@string/activity_changed_contact"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.SAMPLE_CODE"/> + </intent-filter> + </activity> + <activity android:name=".content.InstallApk" android:label="@string/activity_install_apk" android:enabled="@bool/atLeastHoneycombMR2"> <intent-filter> diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml index c9c347eab..ff4b89871 100644 --- a/samples/ApiDemos/res/values/strings.xml +++ b/samples/ApiDemos/res/values/strings.xml @@ -450,6 +450,8 @@ <string name="pick_phone">Pick a Phone</string> <string name="pick_address">Pick an Address</string> + <string name="activity_changed_contact">Content/Provider/Changed Contacts</string> + <string name="activity_install_apk">Content/Packages/Install Apk</string> <!-- ============================== --> diff --git a/samples/ApiDemos/src/com/example/android/apis/content/ChangedContacts.java b/samples/ApiDemos/src/com/example/android/apis/content/ChangedContacts.java new file mode 100644 index 000000000..412a3c6dc --- /dev/null +++ b/samples/ApiDemos/src/com/example/android/apis/content/ChangedContacts.java @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2013 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.example.android.apis.content; + +import android.app.Activity; +import android.app.LoaderManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.CursorLoader; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.Loader; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.database.CursorWrapper; +import android.os.Bundle; +import android.provider.ContactsContract; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CursorAdapter; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; + +/** + * Demonstrates selecting contacts that have changed since a certain time. + */ +public class ChangedContacts extends Activity implements LoaderManager.LoaderCallbacks<Cursor> { + + private static final String CLASS = ChangedContacts.class.getSimpleName(); + + private static final String PREF_KEY_CHANGE = "timestamp_change"; + private static final String PREF_KEY_DELETE = "timestamp_delete"; + + private static final int ID_CHANGE_LOADER = 1; + private static final int ID_DELETE_LOADER = 2; + + /** + * To see this in action, "clear data" for the contacts storage app in the system settings. + * Then come into this app and hit any of the delta buttons. This will cause the contacts + * database to be re-created. + */ + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Toast toast = Toast.makeText(context, "Contacts database created.", Toast.LENGTH_SHORT); + toast.show(); + } + }; + + private DeleteAdapter mDeleteAdapter; + private ChangeAdapter mChangeAdapter; + private long mSearchTime; + private TextView mDisplayView; + private ListView mList; + private Button mDeleteButton; + private Button mChangeButton; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mDeleteAdapter = new DeleteAdapter(this, null, 0); + mChangeAdapter = new ChangeAdapter(this, null, 0); + + LinearLayout main = new LinearLayout(this); + main.setOrientation(LinearLayout.VERTICAL); + + mChangeButton = new Button(this); + mChangeButton.setText("Changed since " + getLastTimestamp(0, PREF_KEY_CHANGE)); + mChangeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + changeClick(); + } + }); + + mDeleteButton = new Button(this); + mDeleteButton.setText("Deleted since " + getLastTimestamp(0, PREF_KEY_DELETE)); + mDeleteButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + deleteClick(); + } + }); + + main.addView(mChangeButton); + main.addView(mDeleteButton); + + mDisplayView = new TextView(this); + mDisplayView.setPadding(5, 5, 5, 5); + main.addView(mDisplayView); + + mList = new ListView(this); + mList.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); + main.addView(mList); + + setContentView(main); + } + + @Override + protected void onResume() { + super.onResume(); + IntentFilter filter = new IntentFilter(); + filter.addAction(ContactsContract.Intents.CONTACTS_DATABASE_CREATED); + registerReceiver(mReceiver, filter); + } + + @Override + protected void onPause() { + super.onPause(); + unregisterReceiver(mReceiver); + } + + private void changeClick() { + mChangeAdapter.swapCursor(null); + LoaderManager manager = getLoaderManager(); + manager.destroyLoader(ID_DELETE_LOADER); + manager.restartLoader(ID_CHANGE_LOADER, null, this); + } + + private void deleteClick() { + mChangeAdapter.swapCursor(null); + LoaderManager manager = getLoaderManager(); + manager.destroyLoader(ID_CHANGE_LOADER); + manager.restartLoader(ID_DELETE_LOADER, null, this); + } + + private void saveLastTimestamp(long time, String key) { + SharedPreferences pref = getSharedPreferences(CLASS, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = pref.edit(); + editor.putLong(key, time); + editor.commit(); + } + + private long getLastTimestamp(long time, String key) { + SharedPreferences pref = getSharedPreferences(CLASS, Context.MODE_PRIVATE); + return pref.getLong(key, time); + } + + @Override + public Loader<Cursor> onCreateLoader(int id, Bundle args) { + switch(id) { + case ID_CHANGE_LOADER: + return getChangeLoader(); + case ID_DELETE_LOADER: + return getDeleteLoader(); + } + return null; + } + + private CursorLoader getChangeLoader() { + String[] projection = new String[]{ + ContactsContract.Data._ID, + ContactsContract.Data.CONTACT_ID, + ContactsContract.Data.DISPLAY_NAME, + ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP + }; + + mSearchTime = getLastTimestamp(0, PREF_KEY_CHANGE); + + String selection = ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP + " > ?"; + String[] bindArgs = new String[]{mSearchTime + ""}; + return new CursorLoader(this, ContactsContract.Data.CONTENT_URI, projection, + selection, bindArgs, ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP + + " desc, " + ContactsContract.Data.CONTACT_ID + " desc"); + } + + private CursorLoader getDeleteLoader() { + String[] projection = new String[]{ + ContactsContract.DeletedContacts.CONTACT_ID, + ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP + }; + + mSearchTime = getLastTimestamp(0, PREF_KEY_DELETE); + + String selection = ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP + " > ?"; + String[] bindArgs = new String[]{mSearchTime + ""}; + return new CursorLoader(this, ContactsContract.DeletedContacts.CONTENT_URI, projection, + selection, bindArgs, ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP + + " desc"); + } + + @Override + public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) { + long timestamp = 0; + + + switch (cursorLoader.getId()) { + case ID_CHANGE_LOADER: + mDisplayView.setText(data.getCount() + " change(s) since " + mSearchTime); + mList.setAdapter(mChangeAdapter); + mChangeAdapter.swapCursor(data); + + // Save the largest timestamp returned. Only need the first one due to the sort + // order. + if (data.moveToNext()) { + timestamp = data.getLong(data.getColumnIndex( + ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP)); + data.moveToPrevious(); + } + if (timestamp > 0) { + saveLastTimestamp(timestamp, PREF_KEY_CHANGE); + mChangeButton.setText("Changed since " + timestamp); + } + break; + case ID_DELETE_LOADER: + mDisplayView.setText(data.getCount() + " delete(s) since " + mSearchTime); + mList.setAdapter(mDeleteAdapter); + mDeleteAdapter.swapCursor(new DeleteCursorWrapper(data)); + if (data.moveToNext()) { + timestamp = data.getLong(data.getColumnIndex( + ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP)); + data.moveToPrevious(); + } + if (timestamp > 0) { + saveLastTimestamp(timestamp, PREF_KEY_DELETE); + mDeleteButton.setText("Deleted since " + timestamp); + } + break; + } + } + + @Override + public void onLoaderReset(Loader<Cursor> cursorLoader) { + mDisplayView.setText(""); + switch (cursorLoader.getId()) { + case ID_CHANGE_LOADER: + mChangeAdapter.swapCursor(null); + break; + case ID_DELETE_LOADER: + mDeleteAdapter.swapCursor(null); + break; + } + } + + private class DeleteCursorWrapper extends CursorWrapper { + + /** + * Creates a cursor wrapper. + * + * @param cursor The underlying cursor to wrap. + */ + public DeleteCursorWrapper(Cursor cursor) { + super(cursor); + } + + @Override + public int getColumnIndexOrThrow(String columnName) { + if (columnName.equals("_id")) { + return super.getColumnIndex(ContactsContract.DeletedContacts.CONTACT_ID); + } + return super.getColumnIndex(columnName); + } + } + + private static class DeleteAdapter extends CursorAdapter { + + private Context mContext; + + public DeleteAdapter(Context context, Cursor c, int flags) { + super(context, c, flags); + this.mContext = context; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + LinearLayout item = new LinearLayout(mContext); + item.addView(buildText(context)); + item.addView(buildText(context)); + return item; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + LinearLayout item = (LinearLayout) view; + String id = cursor.getString(cursor.getColumnIndex( + ContactsContract.DeletedContacts.CONTACT_ID)); + String timestamp = cursor.getString(cursor.getColumnIndex( + ContactsContract.DeletedContacts.CONTACT_DELETED_TIMESTAMP)); + + setText(item.getChildAt(0), id); + setText(item.getChildAt(1), timestamp); + } + } + + private static class ChangeAdapter extends CursorAdapter { + + private Context mContext; + + public ChangeAdapter(Context context, Cursor c, int flags) { + super(context, c, flags); + mContext = context; + } + + @Override + public View newView(Context context, Cursor cursor, ViewGroup parent) { + LinearLayout item = new LinearLayout(mContext); + item.addView(buildText(context)); + item.addView(buildText(context)); + item.addView(buildText(context)); + return item; + } + + @Override + public void bindView(View view, Context context, Cursor cursor) { + LinearLayout item = (LinearLayout) view; + + String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.CONTACT_ID)); + String name = cursor.getString(cursor.getColumnIndex( + ContactsContract.Data.DISPLAY_NAME)); + String timestamp = cursor.getString(cursor.getColumnIndex( + ContactsContract.Data.CONTACT_LAST_UPDATED_TIMESTAMP)); + + setText(item.getChildAt(0), id); + setText(item.getChildAt(1), name); + setText(item.getChildAt(2), timestamp); + } + } + + private static void setText(View view, String value) { + TextView text = (TextView) view; + text.setText(value); + } + + private static TextView buildText(Context context) { + TextView view = new TextView(context); + view.setPadding(3, 3, 3, 3); + return view; + } +} |
