From f0aa20423f58f5859e3533509eebe8a9caa13a9a Mon Sep 17 00:00:00 2001 From: Flavio Lerda Date: Mon, 13 Jun 2011 14:50:38 +0100 Subject: If the loader is cancelled, show an empty list. Currently, the adapter fails with a NullPointerException while trying to iterate through the cursor; instead, we can simply show an empty list of contacts in that case. Bug:4597448 Change-Id: Ibd91bded0f77fd8f9f040f7f6af12f6c863c6370 --- .../android/contacts/list/StrequentAdapter.java | 30 ++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/com/android/contacts/list/StrequentAdapter.java b/src/com/android/contacts/list/StrequentAdapter.java index 4c6109abf..fc7a944f3 100644 --- a/src/com/android/contacts/list/StrequentAdapter.java +++ b/src/com/android/contacts/list/StrequentAdapter.java @@ -61,20 +61,24 @@ public class StrequentAdapter extends BaseAdapter implements OnClickListener { mAllEntries = new ArrayList(); mMostFrequentCount = mStarredCount = 0; - while (cursor.moveToNext()) { - StrequentEntry contact = new StrequentEntry(); - - contact.id = cursor.getLong(StrequentMetaDataLoader.CONTACT_ID); - contact.photoId = cursor.getLong(StrequentMetaDataLoader.PHOTO_ID); - contact.name = cursor.getString(StrequentMetaDataLoader.DISPLAY_NAME); - - // Adding Starred Contact - if (cursor.getInt(StrequentMetaDataLoader.STARRED) == 1) { - mStarredCount++; - } else { - mMostFrequentCount++; + // If the loader was canceled we will be given a null cursor. + // In that case, show an empty list of contacts. + if (cursor != null) { + while (cursor.moveToNext()) { + StrequentEntry contact = new StrequentEntry(); + + contact.id = cursor.getLong(StrequentMetaDataLoader.CONTACT_ID); + contact.photoId = cursor.getLong(StrequentMetaDataLoader.PHOTO_ID); + contact.name = cursor.getString(StrequentMetaDataLoader.DISPLAY_NAME); + + // Adding Starred Contact + if (cursor.getInt(StrequentMetaDataLoader.STARRED) == 1) { + mStarredCount++; + } else { + mMostFrequentCount++; + } + mAllEntries.add(contact); } - mAllEntries.add(contact); } this.notifyDataSetChanged(); } -- cgit v1.2.3 From 0090d0dcdf2bebed3d379806f6a9daeef57ccff1 Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Thu, 14 Jul 2011 12:24:02 -0700 Subject: Fix bug 5031013 Crash after searching a contact from... Only in onDestroy() mActionBarAdapter can be null because we may finish() People activity in configureContentView() before initializing mActionBarAdapter when redirecting to another activity. Change-Id: Ibf4417b2604a4b85944a23022aef578ec94faaf9 --- src/com/android/contacts/activities/PeopleActivity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java index b0844e9ff..ed37806b4 100644 --- a/src/com/android/contacts/activities/PeopleActivity.java +++ b/src/com/android/contacts/activities/PeopleActivity.java @@ -390,7 +390,11 @@ public class PeopleActivity extends ContactsActivity @Override protected void onDestroy() { - mActionBarAdapter.setListener(null); + // mActionBarAdapter will be null here when redirecting to another activity in + // configureContentView(). + if (mActionBarAdapter != null) { + mActionBarAdapter.setListener(null); + } super.onDestroy(); } -- cgit v1.2.3 From 29766609c8c52bb1323082f595065e8130619475 Mon Sep 17 00:00:00 2001 From: Katherine Kuan Date: Thu, 21 Jul 2011 12:04:56 -0700 Subject: Don't commit transactions after onSaveInstanceState() - On the tablet portrait view, once the contact details are loaded, a runnable is posted to a handler to properly setup the fragments (by showing/hiding the ContactDetailFragment or ViewPager/Tab carousel) - Since it's posted to a handler, we need to make sure that onSaveInstanceState has not already been called or at least allow the fragment transaction to be lost if it has been - Prevent the runnable from doing anything if the activity is already destroyed Bug: 5011890 Change-Id: Ib43278f21eee390202ffe4b7ed4057482c34e61c --- src/com/android/contacts/activities/PeopleActivity.java | 13 +++++++++++++ .../contacts/detail/ContactDetailLayoutController.java | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java index 6d031e9c3..579c833ad 100644 --- a/src/com/android/contacts/activities/PeopleActivity.java +++ b/src/com/android/contacts/activities/PeopleActivity.java @@ -180,6 +180,14 @@ public class PeopleActivity extends ContactsActivity */ private boolean mFragmentInitialized; + /** + * Whether or not the activity is destroyed. This flag is needed to ensure that the + * {@link Handler} does not execute any {@link FragmentTransaction}s in {@link Runnable}s + * after the activity is destroyed. + * TODO: Figure out a way to get rid of the {@link Handler} or make the operation safe. + */ + private boolean mIsActivityDestroyed = false; + /** Sequential ID assigned to each instance; used for logging */ private final int mInstanceId; private static final AtomicInteger sNextInstanceId = new AtomicInteger(); @@ -463,6 +471,7 @@ public class PeopleActivity extends ContactsActivity @Override protected void onDestroy() { + mIsActivityDestroyed = true; // mActionBarAdapter will be null here when redirecting to another activity in // configureContentView(). if (mActionBarAdapter != null) { @@ -1005,6 +1014,10 @@ public class PeopleActivity extends ContactsActivity mHandler.post(new Runnable() { @Override public void run() { + // Don't continue setting up the detail page if the activity is destroyed. + if (mIsActivityDestroyed) { + return; + } if (!mContactDetailLayoutController.isInitialized()) { mContactDetailLayoutController.setContactDetailFragment( mContactDetailFragment); diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java index 826d72009..dda388412 100644 --- a/src/com/android/contacts/detail/ContactDetailLayoutController.java +++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java @@ -161,7 +161,12 @@ public class ContactDetailLayoutController { throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode); } - ft.commit(); + // If the activity has already saved its state, then allow this fragment + // transaction to be dropped because there's nothing else we can do to update the UI. + // The fact that the contact URI has already been saved by the activity means we can + // restore this later. + // TODO: Figure out if this is really the solution we want. + ft.commitAllowingStateLoss(); } private void showContactWithoutUpdates() { @@ -182,7 +187,12 @@ public class ContactDetailLayoutController { throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode); } - ft.commit(); + // If the activity has already saved its state, then allow this fragment + // transaction to be dropped because there's nothing else we can do to update the UI. + // The fact that the contact URI has already been saved by the activity means we can + // restore this later. + // TODO: Figure out if this is really the solution we want. + ft.commitAllowingStateLoss(); } public void onSaveInstanceState(Bundle outState) { -- cgit v1.2.3 From c8307a123b5af7851ce38fe0e7ea5a80667341e9 Mon Sep 17 00:00:00 2001 From: Daisuke Miyakawa Date: Fri, 22 Jul 2011 09:05:37 -0700 Subject: Fix IllegalArgumentException problem onOptionsItemSelected() will be called with menu_call_settings_call_log, which should be just ignored. Change-Id: I93cc049159afbd8ddabeb1d06a29e443f6acbf63 --- src/com/android/contacts/calllog/CallLogFragment.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/com/android/contacts/calllog/CallLogFragment.java b/src/com/android/contacts/calllog/CallLogFragment.java index f61f1de1e..f83938a92 100644 --- a/src/com/android/contacts/calllog/CallLogFragment.java +++ b/src/com/android/contacts/calllog/CallLogFragment.java @@ -1012,7 +1012,10 @@ public class CallLogFragment extends ListFragment implements ViewPagerVisibility mCallLogQueryHandler.fetchVoicemailOnly(); return true; } - + case R.id.menu_call_settings_call_log: { + // Intent is already set. + return false; + } default: throw new IllegalArgumentException("unknown menu item: " + item.getItemId()); } -- cgit v1.2.3 From 7a96d83b0669e486b00780a3fc8cb7281bb653cd Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Tue, 16 Aug 2011 12:47:27 -0700 Subject: Fix NPE caused by Id96aea69 I added an explicit null check for account type, but null was actually used for the fallback account type. Bug 5171336 Change-Id: Ia0b98d0e9451eb3fc33d52db09feaff390875e33 --- src/com/android/contacts/model/AccountTypeWithDataSet.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/com/android/contacts/model/AccountTypeWithDataSet.java b/src/com/android/contacts/model/AccountTypeWithDataSet.java index d5cdbdddc..f1b2344fa 100644 --- a/src/com/android/contacts/model/AccountTypeWithDataSet.java +++ b/src/com/android/contacts/model/AccountTypeWithDataSet.java @@ -25,16 +25,14 @@ import android.text.TextUtils; * Encapsulates an "account type" string and a "data set" string. */ public class AccountTypeWithDataSet { - /** account type will never be null. */ + /** account type. Can be null for fallback type. */ public final String accountType; /** dataSet may be null, but never be "". */ public final String dataSet; private AccountTypeWithDataSet(String accountType, String dataSet) { - if (accountType == null) throw new NullPointerException(); - - this.accountType = accountType; + this.accountType = TextUtils.isEmpty(accountType) ? null : accountType; this.dataSet = TextUtils.isEmpty(dataSet) ? null : dataSet; } @@ -53,7 +51,8 @@ public class AccountTypeWithDataSet { @Override public int hashCode() { - return Objects.hashCode(accountType) ^ (dataSet == null ? 0 : Objects.hashCode(dataSet)); + return (accountType == null ? 0 : accountType.hashCode()) + ^ (dataSet == null ? 0 : dataSet.hashCode()); } @Override -- cgit v1.2.3 From b570809826a40ed5bf1337ffd0c1c08832c46979 Mon Sep 17 00:00:00 2001 From: Daniel Lehmann Date: Thu, 18 Aug 2011 14:06:44 -0700 Subject: Replace the is_profile hack by a worse hack, which is at least way faster Bug:5134056 Change-Id: I7b9f419ee552a7d0c592f836355234ad6e34e221 --- src/com/android/contacts/list/DefaultContactListAdapter.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java index bb49027df..007af6ce9 100644 --- a/src/com/android/contacts/list/DefaultContactListAdapter.java +++ b/src/com/android/contacts/list/DefaultContactListAdapter.java @@ -186,7 +186,7 @@ public class DefaultContactListAdapter extends ContactListAdapter { break; } case ContactListFilter.FILTER_TYPE_ACCOUNT: { - // TODO: avoid the use of private API + // TODO (stopship): avoid the use of private API selection.append( Contacts._ID + " IN (" + "SELECT DISTINCT " + RawContacts.CONTACT_ID @@ -201,7 +201,11 @@ public class DefaultContactListAdapter extends ContactListAdapter { } else { selection.append(" AND " + RawContacts.DATA_SET + " IS NULL"); } - selection.append(" OR " + Contacts.IS_USER_PROFILE + "=1)"); + // TODO (stopship): And also this private API, which is even worse + selection.append(") OR " + Contacts._ID + "=(" + + "SELECT contact_id " + + "FROM raw_contacts rc inner join accounts a" + + " ON a.profile_raw_contact_id = rc._id)"); break; } case ContactListFilter.FILTER_TYPE_GROUP: { -- cgit v1.2.3 From e881545d364229fe0bd8c04489cc8a394e040deb Mon Sep 17 00:00:00 2001 From: Justin Ho Date: Fri, 9 Sep 2011 08:59:24 -0700 Subject: Updated Contacts widget dimens Bug: 5278970 Change-Id: I482433cbef14fc917d5bff8460151ee7d46a861e --- res/xml/social_widget_info.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/xml/social_widget_info.xml b/res/xml/social_widget_info.xml index a7bece6dc..1003c62cd 100644 --- a/res/xml/social_widget_info.xml +++ b/res/xml/social_widget_info.xml @@ -17,8 +17,8 @@