PageRenderTime 1ms CodeModel.GetById 28ms app.highlight 10ms RepoModel.GetById 0ms app.codeStats 0ms

/core/java/android/widget/QuickContactBadge.java

https://github.com/Kali-/android_frameworks_base
Java | 302 lines | 202 code | 37 blank | 63 comment | 48 complexity | 9e4387e59d7f8b74823064a8a5639543 MD5 | raw file
  1/*
  2 * Copyright (C) 2009 The Android Open Source Project
  3 *
  4 * Licensed under the Apache License, Version 2.0 (the "License");
  5 * you may not use this file except in compliance with the License.
  6 * You may obtain a copy of the License at
  7 *
  8 *      http://www.apache.org/licenses/LICENSE-2.0
  9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS,
 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 * See the License for the specific language governing permissions and
 14 * limitations under the License.
 15 */
 16
 17package android.widget;
 18
 19import com.android.internal.R;
 20
 21import android.content.AsyncQueryHandler;
 22import android.content.ContentResolver;
 23import android.content.Context;
 24import android.content.Intent;
 25import android.content.res.TypedArray;
 26import android.database.Cursor;
 27import android.graphics.Canvas;
 28import android.graphics.drawable.Drawable;
 29import android.net.Uri;
 30import android.provider.ContactsContract.CommonDataKinds.Email;
 31import android.provider.ContactsContract.Contacts;
 32import android.provider.ContactsContract.Intents;
 33import android.provider.ContactsContract.PhoneLookup;
 34import android.provider.ContactsContract.QuickContact;
 35import android.provider.ContactsContract.RawContacts;
 36import android.util.AttributeSet;
 37import android.view.View;
 38import android.view.View.OnClickListener;
 39
 40/**
 41 * Widget used to show an image with the standard QuickContact badge
 42 * and on-click behavior.
 43 */
 44public class QuickContactBadge extends ImageView implements OnClickListener {
 45    private Uri mContactUri;
 46    private String mContactEmail;
 47    private String mContactPhone;
 48    private Drawable mOverlay;
 49    private QueryHandler mQueryHandler;
 50    private Drawable mDefaultAvatar;
 51
 52    protected String[] mExcludeMimes = null;
 53
 54    static final private int TOKEN_EMAIL_LOOKUP = 0;
 55    static final private int TOKEN_PHONE_LOOKUP = 1;
 56    static final private int TOKEN_EMAIL_LOOKUP_AND_TRIGGER = 2;
 57    static final private int TOKEN_PHONE_LOOKUP_AND_TRIGGER = 3;
 58
 59    static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
 60        RawContacts.CONTACT_ID,
 61        Contacts.LOOKUP_KEY,
 62    };
 63    static final int EMAIL_ID_COLUMN_INDEX = 0;
 64    static final int EMAIL_LOOKUP_STRING_COLUMN_INDEX = 1;
 65
 66    static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
 67        PhoneLookup._ID,
 68        PhoneLookup.LOOKUP_KEY,
 69    };
 70    static final int PHONE_ID_COLUMN_INDEX = 0;
 71    static final int PHONE_LOOKUP_STRING_COLUMN_INDEX = 1;
 72
 73    public QuickContactBadge(Context context) {
 74        this(context, null);
 75    }
 76
 77    public QuickContactBadge(Context context, AttributeSet attrs) {
 78        this(context, attrs, 0);
 79    }
 80
 81    public QuickContactBadge(Context context, AttributeSet attrs, int defStyle) {
 82        super(context, attrs, defStyle);
 83
 84        TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
 85        mOverlay = styledAttributes.getDrawable(
 86                com.android.internal.R.styleable.Theme_quickContactBadgeOverlay);
 87        styledAttributes.recycle();
 88
 89        mQueryHandler = new QueryHandler(mContext.getContentResolver());
 90        setOnClickListener(this);
 91    }
 92
 93    @Override
 94    protected void drawableStateChanged() {
 95        super.drawableStateChanged();
 96        if (mOverlay != null && mOverlay.isStateful()) {
 97            mOverlay.setState(getDrawableState());
 98            invalidate();
 99        }
100    }
101
102    /** This call has no effect anymore, as there is only one QuickContact mode */
103    @SuppressWarnings("unused")
104    public void setMode(int size) {
105    }
106
107    @Override
108    protected void onDraw(Canvas canvas) {
109        super.onDraw(canvas);
110
111        if (!isEnabled()) {
112            // not clickable? don't show triangle
113            return;
114        }
115
116        if (mOverlay == null || mOverlay.getIntrinsicWidth() == 0 ||
117                mOverlay.getIntrinsicHeight() == 0) {
118            // nothing to draw
119            return;
120        }
121
122        mOverlay.setBounds(0, 0, getWidth(), getHeight());
123
124        if (mPaddingTop == 0 && mPaddingLeft == 0) {
125            mOverlay.draw(canvas);
126        } else {
127            int saveCount = canvas.getSaveCount();
128            canvas.save();
129            canvas.translate(mPaddingLeft, mPaddingTop);
130            mOverlay.draw(canvas);
131            canvas.restoreToCount(saveCount);
132        }
133    }
134
135    /** True if a contact, an email address or a phone number has been assigned */
136    private boolean isAssigned() {
137        return mContactUri != null || mContactEmail != null || mContactPhone != null;
138    }
139
140    /**
141     * Resets the contact photo to the default state.
142     */
143    public void setImageToDefault() {
144        if (mDefaultAvatar == null) {
145            mDefaultAvatar = getResources().getDrawable(R.drawable.ic_contact_picture);
146        }
147        setImageDrawable(mDefaultAvatar);
148    }
149
150    /**
151     * Assign the contact uri that this QuickContactBadge should be associated
152     * with. Note that this is only used for displaying the QuickContact window and
153     * won't bind the contact's photo for you. Call {@link #setImageDrawable(Drawable)} to set the
154     * photo.
155     *
156     * @param contactUri Either a {@link Contacts#CONTENT_URI} or
157     *            {@link Contacts#CONTENT_LOOKUP_URI} style URI.
158     */
159    public void assignContactUri(Uri contactUri) {
160        mContactUri = contactUri;
161        mContactEmail = null;
162        mContactPhone = null;
163        onContactUriChanged();
164    }
165
166    /**
167     * Assign a contact based on an email address. This should only be used when
168     * the contact's URI is not available, as an extra query will have to be
169     * performed to lookup the URI based on the email.
170     *
171     * @param emailAddress The email address of the contact.
172     * @param lazyLookup If this is true, the lookup query will not be performed
173     * until this view is clicked.
174     */
175    public void assignContactFromEmail(String emailAddress, boolean lazyLookup) {
176        mContactEmail = emailAddress;
177        if (!lazyLookup) {
178            mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
179                    Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
180                    EMAIL_LOOKUP_PROJECTION, null, null, null);
181        } else {
182            mContactUri = null;
183            onContactUriChanged();
184        }
185    }
186
187    /**
188     * Assign a contact based on a phone number. This should only be used when
189     * the contact's URI is not available, as an extra query will have to be
190     * performed to lookup the URI based on the phone number.
191     *
192     * @param phoneNumber The phone number of the contact.
193     * @param lazyLookup If this is true, the lookup query will not be performed
194     * until this view is clicked.
195     */
196    public void assignContactFromPhone(String phoneNumber, boolean lazyLookup) {
197        mContactPhone = phoneNumber;
198        if (!lazyLookup) {
199            mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
200                    Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
201                    PHONE_LOOKUP_PROJECTION, null, null, null);
202        } else {
203            mContactUri = null;
204            onContactUriChanged();
205        }
206    }
207
208    private void onContactUriChanged() {
209        setEnabled(isAssigned());
210    }
211
212    @Override
213    public void onClick(View v) {
214        if (mContactUri != null) {
215            QuickContact.showQuickContact(getContext(), QuickContactBadge.this, mContactUri,
216                    QuickContact.MODE_LARGE, mExcludeMimes);
217        } else if (mContactEmail != null) {
218            mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, mContactEmail,
219                    Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
220                    EMAIL_LOOKUP_PROJECTION, null, null, null);
221        } else if (mContactPhone != null) {
222            mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, mContactPhone,
223                    Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
224                    PHONE_LOOKUP_PROJECTION, null, null, null);
225        } else {
226            // If a contact hasn't been assigned, don't react to click.
227            return;
228        }
229    }
230
231    /**
232     * Set a list of specific MIME-types to exclude and not display. For
233     * example, this can be used to hide the {@link Contacts#CONTENT_ITEM_TYPE}
234     * profile icon.
235     */
236    public void setExcludeMimes(String[] excludeMimes) {
237        mExcludeMimes = excludeMimes;
238    }
239
240    private class QueryHandler extends AsyncQueryHandler {
241
242        public QueryHandler(ContentResolver cr) {
243            super(cr);
244        }
245
246        @Override
247        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
248            Uri lookupUri = null;
249            Uri createUri = null;
250            boolean trigger = false;
251
252            try {
253                switch(token) {
254                    case TOKEN_PHONE_LOOKUP_AND_TRIGGER:
255                        trigger = true;
256                        createUri = Uri.fromParts("tel", (String)cookie, null);
257
258                        //$FALL-THROUGH$
259                    case TOKEN_PHONE_LOOKUP: {
260                        if (cursor != null && cursor.moveToFirst()) {
261                            long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
262                            String lookupKey = cursor.getString(PHONE_LOOKUP_STRING_COLUMN_INDEX);
263                            lookupUri = Contacts.getLookupUri(contactId, lookupKey);
264                        }
265
266                        break;
267                    }
268                    case TOKEN_EMAIL_LOOKUP_AND_TRIGGER:
269                        trigger = true;
270                        createUri = Uri.fromParts("mailto", (String)cookie, null);
271
272                        //$FALL-THROUGH$
273                    case TOKEN_EMAIL_LOOKUP: {
274                        if (cursor != null && cursor.moveToFirst()) {
275                            long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
276                            String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
277                            lookupUri = Contacts.getLookupUri(contactId, lookupKey);
278                        }
279                        break;
280                    }
281                }
282            } finally {
283                if (cursor != null) {
284                    cursor.close();
285                }
286            }
287
288            mContactUri = lookupUri;
289            onContactUriChanged();
290
291            if (trigger && lookupUri != null) {
292                // Found contact, so trigger QuickContact
293                QuickContact.showQuickContact(getContext(), QuickContactBadge.this, lookupUri,
294                        QuickContact.MODE_LARGE, mExcludeMimes);
295            } else if (createUri != null) {
296                // Prompt user to add this person to contacts
297                final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, createUri);
298                getContext().startActivity(intent);
299            }
300        }
301    }
302}