Fix viewing legacy and raw contact URI on tablet
Bug: 5220640
Change-Id: I85c748389921bdff2639fff5f7713e00ba7f9f8c
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index c9fbeae..c711b6c 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -19,6 +19,7 @@
import com.android.contacts.model.AccountType;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.model.AccountTypeWithDataSet;
+import com.android.contacts.util.ContactLoaderUtils;
import com.android.contacts.util.DataStatus;
import com.android.contacts.util.StreamItemEntry;
import com.android.contacts.util.StreamItemPhotoEntry;
@@ -681,7 +682,8 @@
protected Result doInBackground(Void... args) {
try {
final ContentResolver resolver = getContext().getContentResolver();
- final Uri uriCurrentFormat = ensureIsContactUri(resolver, mLookupUri);
+ final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(
+ resolver, mLookupUri);
Result result = loadContactEntity(resolver, uriCurrentFormat);
if (!result.isNotFound()) {
if (result.isDirectoryEntry()) {
@@ -706,47 +708,6 @@
}
}
- /**
- * Transforms the given Uri and returns a Lookup-Uri that represents the contact.
- * For legacy contacts, a raw-contact lookup is performed.
- * @param resolver
- */
- private Uri ensureIsContactUri(final ContentResolver resolver, final Uri uri) {
- if (uri == null) throw new IllegalArgumentException("uri must not be null");
-
- final String authority = uri.getAuthority();
-
- // Current Style Uri?
- if (ContactsContract.AUTHORITY.equals(authority)) {
- final String type = resolver.getType(uri);
- // Contact-Uri? Good, return it
- if (Contacts.CONTENT_ITEM_TYPE.equals(type)) {
- return uri;
- }
-
- // RawContact-Uri? Transform it to ContactUri
- if (RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
- final long rawContactId = ContentUris.parseId(uri);
- return RawContacts.getContactLookupUri(getContext().getContentResolver(),
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
- }
-
- // Anything else? We don't know what this is
- throw new IllegalArgumentException("uri format is unknown");
- }
-
- // Legacy Style? Convert to RawContact
- final String OBSOLETE_AUTHORITY = "contacts";
- if (OBSOLETE_AUTHORITY.equals(authority)) {
- // Legacy Format. Convert to RawContact-Uri and then lookup the contact
- final long rawContactId = ContentUris.parseId(uri);
- return RawContacts.getContactLookupUri(resolver,
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
- }
-
- throw new IllegalArgumentException("uri authority is unknown");
- }
-
private Result loadContactEntity(ContentResolver resolver, Uri contactUri) {
Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY);
Cursor cursor = resolver.query(entityUri, ContactQuery.COLUMNS, null, null,
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index 2d5fed1..2bde608 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -17,10 +17,10 @@
import com.android.common.widget.CompositeCursorAdapter.Partition;
import com.android.contacts.R;
+import com.android.contacts.util.ContactLoaderUtils;
import com.android.contacts.widget.AutoScrollListView;
import android.app.Activity;
-import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Loader;
@@ -28,6 +28,7 @@
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -92,51 +93,64 @@
private String mPersistentSelectionPrefix = PERSISTENT_SELECTION_PREFIX;
protected OnContactBrowserActionListener mListener;
+ private ContactLookupTask mContactLookupTask;
- /**
- * Refreshes a contact URI: it may have changed as a result of aggregation
- * activity.
- */
- private class ContactUriQueryHandler extends AsyncQueryHandler {
+ private final class ContactLookupTask extends AsyncTask<Void, Void, Uri> {
- public ContactUriQueryHandler(ContentResolver cr) {
- super(cr);
- }
+ private final Uri mUri;
+ private boolean mIsCancelled;
- public void runQuery() {
- startQuery(0, mSelectedContactUri, mSelectedContactUri,
- new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);
+ public ContactLookupTask(Uri uri) {
+ mUri = uri;
}
@Override
- protected void onQueryComplete(int token, Object cookie, Cursor data) {
- long contactId = 0;
- String lookupKey = null;
- if (data != null) {
- if (data.moveToFirst()) {
- contactId = data.getLong(0);
- lookupKey = data.getString(1);
- }
- data.close();
- }
+ protected Uri doInBackground(Void... args) {
+ Cursor cursor = null;
+ try {
+ final ContentResolver resolver = getContext().getContentResolver();
+ final Uri uriCurrentFormat = ContactLoaderUtils.ensureIsContactUri(resolver, mUri);
+ cursor = resolver.query(uriCurrentFormat,
+ new String[] { Contacts._ID, Contacts.LOOKUP_KEY }, null, null, null);
- if (!cookie.equals(mSelectedContactUri)) {
+ if (cursor != null && cursor.moveToFirst()) {
+ final long contactId = cursor.getLong(0);
+ final String lookupKey = cursor.getString(1);
+ if (contactId != 0 && !TextUtils.isEmpty(lookupKey)) {
+ return Contacts.getLookupUri(contactId, lookupKey);
+ }
+ }
+
+ Log.e(TAG, "Error: No contact ID or lookup key for contact " + mUri);
+ return null;
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ public void cancel() {
+ super.cancel(true);
+ // Use a flag to keep track of whether the {@link AsyncTask} was cancelled or not in
+ // order to ensure onPostExecute() is not executed after the cancel request. The flag is
+ // necessary because {@link AsyncTask} still calls onPostExecute() if the cancel request
+ // came after the worker thread was finished.
+ mIsCancelled = true;
+ }
+
+ @Override
+ protected void onPostExecute(Uri uri) {
+ // Make sure the {@link Fragment} is at least still attached to the {@link Activity}
+ // before continuing.
+ if (mIsCancelled || !isAdded() || uri == null) {
return;
}
-
- Uri uri;
- if (contactId != 0 && lookupKey != null) {
- uri = Contacts.getLookupUri(contactId, lookupKey);
- } else {
- uri = null;
- }
-
- onContactUriQueryFinished(uri);
+ mSelectedContactUri = uri;
+ onContactUriQueryFinished(mSelectedContactUri);
}
}
- private ContactUriQueryHandler mQueryHandler;
-
private boolean mDelaySelection;
private Handler getHandler() {
@@ -158,7 +172,6 @@
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mQueryHandler = new ContactUriQueryHandler(activity.getContentResolver());
mPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
restoreFilter();
restoreSelectedUri(false);
@@ -228,12 +241,10 @@
}
protected void refreshSelectedContactUri() {
- if (mQueryHandler == null) {
- return;
+ if (mContactLookupTask != null) {
+ mContactLookupTask.cancel();
}
- mQueryHandler.cancelOperation(0);
-
if (!isSelectionVisible()) {
return;
}
@@ -249,7 +260,8 @@
&& mSelectedContactDirectoryId != Directory.LOCAL_INVISIBLE) {
onContactUriQueryFinished(mSelectedContactUri);
} else {
- mQueryHandler.runQuery();
+ mContactLookupTask = new ContactLookupTask(mSelectedContactUri);
+ mContactLookupTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
}
}
diff --git a/src/com/android/contacts/util/ContactLoaderUtils.java b/src/com/android/contacts/util/ContactLoaderUtils.java
new file mode 100644
index 0000000..91c683f
--- /dev/null
+++ b/src/com/android/contacts/util/ContactLoaderUtils.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 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.android.contacts.util;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.net.Uri;
+import android.provider.Contacts;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.RawContacts;
+
+/**
+ * Utility methods for the {@link ContactLoader}.
+ */
+public final class ContactLoaderUtils {
+
+ /** Static helper, not instantiable. */
+ private ContactLoaderUtils() {}
+
+ /**
+ * Transforms the given Uri and returns a Lookup-Uri that represents the contact.
+ * For legacy contacts, a raw-contact lookup is performed. An {@link IllegalArgumentException}
+ * can be thrown if the URI is null or the authority is not recognized.
+ *
+ * Do not call from the UI thread.
+ */
+ @SuppressWarnings("deprecation")
+ public static Uri ensureIsContactUri(final ContentResolver resolver, final Uri uri)
+ throws IllegalArgumentException {
+ if (uri == null) throw new IllegalArgumentException("uri must not be null");
+
+ final String authority = uri.getAuthority();
+
+ // Current Style Uri?
+ if (ContactsContract.AUTHORITY.equals(authority)) {
+ final String type = resolver.getType(uri);
+ // Contact-Uri? Good, return it
+ if (ContactsContract.Contacts.CONTENT_ITEM_TYPE.equals(type)) {
+ return uri;
+ }
+
+ // RawContact-Uri? Transform it to ContactUri
+ if (RawContacts.CONTENT_ITEM_TYPE.equals(type)) {
+ final long rawContactId = ContentUris.parseId(uri);
+ return RawContacts.getContactLookupUri(resolver,
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
+ }
+
+ // Anything else? We don't know what this is
+ throw new IllegalArgumentException("uri format is unknown");
+ }
+
+ // Legacy Style? Convert to RawContact
+ final String OBSOLETE_AUTHORITY = Contacts.AUTHORITY;
+ if (OBSOLETE_AUTHORITY.equals(authority)) {
+ // Legacy Format. Convert to RawContact-Uri and then lookup the contact
+ final long rawContactId = ContentUris.parseId(uri);
+ return RawContacts.getContactLookupUri(resolver,
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
+ }
+
+ throw new IllegalArgumentException("uri authority is unknown");
+ }
+}