OSDN Git Service

Converting CallerInfo to new Contacts API.
authorDmitri Plotnikov <dplotnikov@google.com>
Wed, 19 Aug 2009 22:56:30 +0000 (15:56 -0700)
committerDmitri Plotnikov <dplotnikov@google.com>
Wed, 19 Aug 2009 23:31:01 +0000 (16:31 -0700)
core/java/android/pim/ContactsAsyncHelper.java
core/java/android/provider/ContactsContract.java
telephony/java/com/android/internal/telephony/CallerInfo.java
telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java

index a21281e..342d208 100644 (file)
@@ -27,8 +27,7 @@ import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
+import android.provider.ContactsContract.Contacts;
 import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
@@ -39,35 +38,35 @@ import java.io.InputStream;
  * Helper class for async access of images.
  */
 public class ContactsAsyncHelper extends Handler {
-    
+
     private static final boolean DBG = false;
     private static final String LOG_TAG = "ContactsAsyncHelper";
-    
+
     /**
      * Interface for a WorkerHandler result return.
      */
     public interface OnImageLoadCompleteListener {
         /**
          * Called when the image load is complete.
-         * 
+         *
          * @param imagePresent true if an image was found
-         */  
+         */
         public void onImageLoadComplete(int token, Object cookie, ImageView iView,
                 boolean imagePresent);
     }
-     
+
     // constants
     private static final int EVENT_LOAD_IMAGE = 1;
     private static final int DEFAULT_TOKEN = -1;
-    
+
     // static objects
     private static Handler sThreadHandler;
     private static ContactsAsyncHelper sInstance;
-    
+
     static {
         sInstance = new ContactsAsyncHelper();
     }
-    
+
     private static final class WorkerArgs {
         public Context context;
         public ImageView view;
@@ -78,12 +77,12 @@ public class ContactsAsyncHelper extends Handler {
         public OnImageLoadCompleteListener listener;
         public CallerInfo info;
     }
-    
+
     /**
-     * public inner class to help out the ContactsAsyncHelper callers 
-     * with tracking the state of the CallerInfo Queries and image 
+     * public inner class to help out the ContactsAsyncHelper callers
+     * with tracking the state of the CallerInfo Queries and image
      * loading.
-     * 
+     *
      * Logic contained herein is used to remove the race conditions
      * that exist as the CallerInfo queries run and mix with the image
      * loads, which then mix with the Phone state changes.
@@ -94,11 +93,11 @@ public class ContactsAsyncHelper extends Handler {
         public static final int DISPLAY_UNDEFINED = 0;
         public static final int DISPLAY_IMAGE = -1;
         public static final int DISPLAY_DEFAULT = -2;
-        
+
         // State of the image on the imageview.
         private CallerInfo mCurrentCallerInfo;
         private int displayMode;
-        
+
         public ImageTracker() {
             mCurrentCallerInfo = null;
             displayMode = DISPLAY_UNDEFINED;
@@ -107,17 +106,17 @@ public class ContactsAsyncHelper extends Handler {
         /**
          * Used to see if the requested call / connection has a
          * different caller attached to it than the one we currently
-         * have in the CallCard. 
+         * have in the CallCard.
          */
         public boolean isDifferentImageRequest(CallerInfo ci) {
             // note, since the connections are around for the lifetime of the
-            // call, and the CallerInfo-related items as well, we can 
+            // call, and the CallerInfo-related items as well, we can
             // definitely use a simple != comparison.
             return (mCurrentCallerInfo != ci);
         }
-        
+
         public boolean isDifferentImageRequest(Connection connection) {
-            // if the connection does not exist, see if the 
+            // if the connection does not exist, see if the
             // mCurrentCallerInfo is also null to match.
             if (connection == null) {
                 if (DBG) Log.d(LOG_TAG, "isDifferentImageRequest: connection is null");
@@ -133,57 +132,58 @@ public class ContactsAsyncHelper extends Handler {
             }
             return runQuery;
         }
-        
+
         /**
-         * Simple setter for the CallerInfo object. 
+         * Simple setter for the CallerInfo object.
          */
         public void setPhotoRequest(CallerInfo ci) {
-            mCurrentCallerInfo = ci; 
+            mCurrentCallerInfo = ci;
         }
-        
+
         /**
-         * Convenience method used to retrieve the URI 
-         * representing the Photo file recorded in the attached 
-         * CallerInfo Object. 
+         * Convenience method used to retrieve the URI
+         * representing the Photo file recorded in the attached
+         * CallerInfo Object.
          */
         public Uri getPhotoUri() {
             if (mCurrentCallerInfo != null) {
-                return ContentUris.withAppendedId(People.CONTENT_URI, 
+                return ContentUris.withAppendedId(Contacts.CONTENT_URI,
                         mCurrentCallerInfo.person_id);
             }
-            return null; 
+            return null;
         }
-        
+
         /**
-         * Simple setter for the Photo state. 
+         * Simple setter for the Photo state.
          */
         public void setPhotoState(int state) {
             displayMode = state;
         }
-        
+
         /**
-         * Simple getter for the Photo state. 
+         * Simple getter for the Photo state.
          */
         public int getPhotoState() {
             return displayMode;
         }
     }
-    
+
     /**
-     * Thread worker class that handles the task of opening the stream and loading 
+     * Thread worker class that handles the task of opening the stream and loading
      * the images.
      */
     private class WorkerHandler extends Handler {
         public WorkerHandler(Looper looper) {
             super(looper);
         }
-        
+
+        @Override
         public void handleMessage(Message msg) {
             WorkerArgs args = (WorkerArgs) msg.obj;
-            
+
             switch (msg.arg1) {
                 case EVENT_LOAD_IMAGE:
-                    InputStream inputStream = Contacts.People.openContactPhotoInputStream(
+                    InputStream inputStream = Contacts.openContactPhotoInputStream(
                             args.context.getContentResolver(), args.uri);
                     if (inputStream != null) {
                         args.result = Drawable.createFromStream(inputStream, args.uri.toString());
@@ -192,22 +192,22 @@ public class ContactsAsyncHelper extends Handler {
                                 " token: " + msg.what + " image URI: " + args.uri);
                     } else {
                         args.result = null;
-                        if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 + 
-                                " token: " + msg.what + " image URI: " + args.uri + 
+                        if (DBG) Log.d(LOG_TAG, "Problem with image: " + msg.arg1 +
+                                " token: " + msg.what + " image URI: " + args.uri +
                                 ", using default image.");
                     }
                     break;
                 default:
             }
-            
-            // send the reply to the enclosing class. 
+
+            // send the reply to the enclosing class.
             Message reply = ContactsAsyncHelper.this.obtainMessage(msg.what);
             reply.arg1 = msg.arg1;
             reply.obj = msg.obj;
             reply.sendToTarget();
         }
     }
-    
+
     /**
      * Private constructor for static class
      */
@@ -216,14 +216,14 @@ public class ContactsAsyncHelper extends Handler {
         thread.start();
         sThreadHandler = new WorkerHandler(thread.getLooper());
     }
-    
+
     /**
      * Convenience method for calls that do not want to deal with listeners and tokens.
      */
-    public static final void updateImageViewWithContactPhotoAsync(Context context, 
+    public static final void updateImageViewWithContactPhotoAsync(Context context,
             ImageView imageView, Uri person, int placeholderImageResource) {
         // Added additional Cookie field in the callee.
-        updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context, 
+        updateImageViewWithContactPhotoAsync (null, DEFAULT_TOKEN, null, null, context,
                 imageView, person, placeholderImageResource);
     }
 
@@ -231,24 +231,24 @@ public class ContactsAsyncHelper extends Handler {
      * Convenience method for calls that do not want to deal with listeners and tokens, but have
      * a CallerInfo object to cache the image to.
      */
-    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context, 
+    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, Context context,
             ImageView imageView, Uri person, int placeholderImageResource) {
         // Added additional Cookie field in the callee.
-        updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context, 
+        updateImageViewWithContactPhotoAsync (info, DEFAULT_TOKEN, null, null, context,
                 imageView, person, placeholderImageResource);
     }
 
-    
+
     /**
      * Start an image load, attach the result to the specified CallerInfo object.
      * Note, when the query is started, we make the ImageView INVISIBLE if the
      * placeholderImageResource value is -1.  When we're given a valid (!= -1)
      * placeholderImageResource value, we make sure the image is visible.
      */
-    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token, 
-            OnImageLoadCompleteListener listener, Object cookie, Context context, 
+    public static final void updateImageViewWithContactPhotoAsync(CallerInfo info, int token,
+            OnImageLoadCompleteListener listener, Object cookie, Context context,
             ImageView imageView, Uri person, int placeholderImageResource) {
-        
+
         // in case the source caller info is null, the URI will be null as well.
         // just update using the placeholder image in this case.
         if (person == null) {
@@ -257,10 +257,10 @@ public class ContactsAsyncHelper extends Handler {
             imageView.setImageResource(placeholderImageResource);
             return;
         }
-        
+
         // Added additional Cookie field in the callee to handle arguments
         // sent to the callback function.
-        
+
         // setup arguments
         WorkerArgs args = new WorkerArgs();
         args.cookie = cookie;
@@ -270,15 +270,15 @@ public class ContactsAsyncHelper extends Handler {
         args.defaultResource = placeholderImageResource;
         args.listener = listener;
         args.info = info;
-        
+
         // setup message arguments
         Message msg = sThreadHandler.obtainMessage(token);
         msg.arg1 = EVENT_LOAD_IMAGE;
         msg.obj = args;
-        
-        if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri + 
+
+        if (DBG) Log.d(LOG_TAG, "Begin loading image: " + args.uri +
                 ", displaying default image for now.");
-        
+
         // set the default image first, when the query is complete, we will
         // replace the image with the correct one.
         if (placeholderImageResource != -1) {
@@ -287,11 +287,11 @@ public class ContactsAsyncHelper extends Handler {
         } else {
             imageView.setVisibility(View.INVISIBLE);
         }
-        
+
         // notify the thread to begin working
         sThreadHandler.sendMessage(msg);
     }
-    
+
     /**
      * Called when loading is done.
      */
@@ -316,21 +316,21 @@ public class ContactsAsyncHelper extends Handler {
                     args.view.setVisibility(View.VISIBLE);
                     args.view.setImageResource(args.defaultResource);
                 }
-                
+
                 // Note that the data is cached.
                 if (args.info != null) {
                     args.info.isCachedPhotoCurrent = true;
                 }
-                
+
                 // notify the listener if it is there.
                 if (args.listener != null) {
-                    if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() + 
+                    if (DBG) Log.d(LOG_TAG, "Notifying listener: " + args.listener.toString() +
                             " image: " + args.uri + " completed");
                     args.listener.onImageLoadComplete(msg.what, args.cookie, args.view,
                             imagePresent);
                 }
                 break;
-            default:    
+            default:
         }
     }
 }
index 37191f5..5932040 100644 (file)
@@ -19,15 +19,21 @@ package android.provider;
 import android.accounts.Account;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.database.Cursor;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
 import android.text.TextUtils;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
 /**
  * The contract between the contacts provider and applications. Contains definitions
  * for the supported URIs and columns.
@@ -299,6 +305,55 @@ public final class ContactsContract {
              */
             public static final String CONTENT_DIRECTORY = "suggestions";
         }
+
+        /**
+         * Returns a URI that can be used to retrieve the contact's default photo.
+         *
+         * @param contactUri the contact whose photo should be used
+         */
+        public static Uri getPhotoUri(ContentResolver cr, Uri contactUri) {
+            long photoId = -1;
+            Cursor cursor = cr.query(contactUri, new String[]{Contacts.PHOTO_ID}, null, null, null);
+            try {
+                if (!cursor.moveToNext()) {
+                    return null;
+                }
+
+                if (cursor.isNull(0)) {
+                    return null;
+                }
+
+                photoId = cursor.getLong(0);
+            } finally {
+                cursor.close();
+            }
+
+            return ContentUris.withAppendedId(ContactsContract.Data.CONTENT_URI, photoId);
+        }
+
+        /**
+         * Opens an InputStream for the person's default photo and returns the
+         * photo as a Bitmap stream.
+         *
+         * @param contactUri the contact whose photo should be used
+         */
+        public static InputStream openContactPhotoInputStream(ContentResolver cr, Uri contactUri) {
+            Uri photoUri = getPhotoUri(cr, contactUri);
+            Cursor cursor = cr.query(photoUri,
+                    new String[]{ContactsContract.CommonDataKinds.Photo.PHOTO}, null, null, null);
+            try {
+                if (!cursor.moveToNext()) {
+                    return null;
+                }
+                byte[] data = cursor.getBlob(0);
+                if (data == null) {
+                    return null;
+                }
+                return new ByteArrayInputStream(data);
+            } finally {
+                cursor.close();
+            }
+        }
     }
 
     private interface RawContactsColumns {
index afc8b62..bda2d22 100644 (file)
@@ -20,9 +20,8 @@ import android.content.Context;
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.provider.Contacts;
-import android.provider.Contacts.People;
-import android.provider.Contacts.Phones;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.text.TextUtils;
 import android.telephony.TelephonyManager;
 import android.telephony.PhoneNumberUtils;
@@ -134,44 +133,39 @@ public class CallerInfo {
                 int columnIndex;
 
                 // Look for the name
-                columnIndex = cursor.getColumnIndex(People.NAME);
+                columnIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
                 if (columnIndex != -1) {
                     info.name = cursor.getString(columnIndex);
                 }
 
                 // Look for the number
-                columnIndex = cursor.getColumnIndex(Phones.NUMBER);
+                columnIndex = cursor.getColumnIndex(PhoneLookup.NUMBER);
                 if (columnIndex != -1) {
                     info.phoneNumber = cursor.getString(columnIndex);
                 }
 
                 // Look for the label/type combo
-                columnIndex = cursor.getColumnIndex(Phones.LABEL);
+                columnIndex = cursor.getColumnIndex(PhoneLookup.LABEL);
                 if (columnIndex != -1) {
-                    int typeColumnIndex = cursor.getColumnIndex(Phones.TYPE);
+                    int typeColumnIndex = cursor.getColumnIndex(PhoneLookup.TYPE);
                     if (typeColumnIndex != -1) {
                         info.numberType = cursor.getInt(typeColumnIndex);
                         info.numberLabel = cursor.getString(columnIndex);
-                        info.phoneLabel = Contacts.Phones.getDisplayLabel(context,
+                        info.phoneLabel = Phone.getDisplayLabel(context,
                                 info.numberType, info.numberLabel)
                                 .toString();
                     }
                 }
 
                 // Look for the person ID
-                columnIndex = cursor.getColumnIndex(Phones.PERSON_ID);
+                columnIndex = cursor.getColumnIndex(PhoneLookup._ID);
                 if (columnIndex != -1) {
                     info.person_id = cursor.getLong(columnIndex);
-                } else {
-                    columnIndex = cursor.getColumnIndex(People._ID);
-                    if (columnIndex != -1) {
-                        info.person_id = cursor.getLong(columnIndex);
-                    }
                 }
 
                 // look for the custom ringtone, create from the string stored
                 // in the database.
-                columnIndex = cursor.getColumnIndex(People.CUSTOM_RINGTONE);
+                columnIndex = cursor.getColumnIndex(PhoneLookup.CUSTOM_RINGTONE);
                 if ((columnIndex != -1) && (cursor.getString(columnIndex) != null)) {
                     info.contactRingtoneUri = Uri.parse(cursor.getString(columnIndex));
                 } else {
@@ -180,7 +174,7 @@ public class CallerInfo {
 
                 // look for the send to voicemail flag, set it to true only
                 // under certain circumstances.
-                columnIndex = cursor.getColumnIndex(People.SEND_TO_VOICEMAIL);
+                columnIndex = cursor.getColumnIndex(PhoneLookup.SEND_TO_VOICEMAIL);
                 info.shouldSendToVoicemail = (columnIndex != -1) &&
                         ((cursor.getInt(columnIndex)) == 1);
                 info.contactExists = true;
@@ -256,8 +250,7 @@ public class CallerInfo {
             }
         }
 
-        Uri contactUri = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL,
-                                              Uri.encode(number));
+        Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number);
 
         CallerInfo info = getCallerInfo(context, contactUri);
 
index f81f42a..ef456f0 100644 (file)
@@ -24,7 +24,7 @@ import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.provider.Contacts;
+import android.provider.ContactsContract.PhoneLookup;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
@@ -303,7 +303,7 @@ public class CallerInfoAsyncQuery {
     public static CallerInfoAsyncQuery startQuery(int token, Context context, String number,
             OnQueryCompleteListener listener, Object cookie) {
         //contruct the URI object and start Query.
-        Uri contactRef = Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, number);
+        Uri contactRef = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number);
 
         CallerInfoAsyncQuery c = new CallerInfoAsyncQuery();
         c.allocate(context, contactRef);