blob: 07c3e4b6734077108c99f4d4448c1dc5abd7b27c [file] [log] [blame]
Evan Millare727f182009-08-27 11:15:55 -07001/*
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 android.content.AsyncQueryHandler;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.res.TypedArray;
24import android.database.Cursor;
Mark Wagnerf5935a92009-09-22 13:49:26 -070025import android.graphics.drawable.Drawable;
Evan Millare727f182009-08-27 11:15:55 -070026import android.net.Uri;
27import android.provider.ContactsContract.Contacts;
28import android.provider.ContactsContract.Intents;
29import android.provider.ContactsContract.PhoneLookup;
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -070030import android.provider.ContactsContract.QuickContact;
Dmitri Plotnikovea367472009-09-18 15:04:58 -070031import android.provider.ContactsContract.RawContacts;
Evan Millare727f182009-08-27 11:15:55 -070032import android.provider.ContactsContract.CommonDataKinds.Email;
33import android.util.AttributeSet;
34import android.view.View;
35import android.view.View.OnClickListener;
Mark Wagnerb2c64292009-09-28 16:39:20 -070036import com.android.internal.R;
Evan Millare727f182009-08-27 11:15:55 -070037
38/**
Evan Millarc1a2a822009-09-29 18:02:06 -070039 * Widget used to show an image with the standard QuickContact badge
Evan Millare727f182009-08-27 11:15:55 -070040 * and on-click behavior.
Evan Millare727f182009-08-27 11:15:55 -070041 */
Evan Millarc1a2a822009-09-29 18:02:06 -070042public class QuickContactBadge extends ImageView implements OnClickListener {
Evan Millare727f182009-08-27 11:15:55 -070043
44 private Uri mContactUri;
45 private String mContactEmail;
46 private String mContactPhone;
47 private int mMode;
48 private QueryHandler mQueryHandler;
Mark Wagnerf5935a92009-09-22 13:49:26 -070049 private Drawable mBadgeBackground;
Mark Wagnerb2c64292009-09-28 16:39:20 -070050 private Drawable mNoBadgeBackground;
Evan Millare727f182009-08-27 11:15:55 -070051
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;
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -070058 static final private int TOKEN_CONTACT_LOOKUP_AND_TRIGGER = 4;
Evan Millare727f182009-08-27 11:15:55 -070059
60 static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
Dmitri Plotnikovea367472009-09-18 15:04:58 -070061 RawContacts.CONTACT_ID,
Evan Millare727f182009-08-27 11:15:55 -070062 Contacts.LOOKUP_KEY,
63 };
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -070064 static final int EMAIL_ID_COLUMN_INDEX = 0;
65 static final int EMAIL_LOOKUP_STRING_COLUMN_INDEX = 1;
Evan Millare727f182009-08-27 11:15:55 -070066
67 static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
68 PhoneLookup._ID,
69 PhoneLookup.LOOKUP_KEY,
70 };
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -070071 static final int PHONE_ID_COLUMN_INDEX = 0;
72 static final int PHONE_LOOKUP_STRING_COLUMN_INDEX = 1;
Evan Millare727f182009-08-27 11:15:55 -070073
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -070074 static final String[] CONTACT_LOOKUP_PROJECTION = new String[] {
75 Contacts._ID,
76 Contacts.LOOKUP_KEY,
77 };
78 static final int CONTACT_ID_COLUMN_INDEX = 0;
79 static final int CONTACT_LOOKUPKEY_COLUMN_INDEX = 1;
Evan Millare727f182009-08-27 11:15:55 -070080
81
Evan Millarc1a2a822009-09-29 18:02:06 -070082 public QuickContactBadge(Context context) {
Evan Millare727f182009-08-27 11:15:55 -070083 this(context, null);
84 }
85
Evan Millarc1a2a822009-09-29 18:02:06 -070086 public QuickContactBadge(Context context, AttributeSet attrs) {
Evan Millare727f182009-08-27 11:15:55 -070087 this(context, attrs, 0);
88 }
89
Evan Millarc1a2a822009-09-29 18:02:06 -070090 public QuickContactBadge(Context context, AttributeSet attrs, int defStyle) {
Evan Millare727f182009-08-27 11:15:55 -070091 super(context, attrs, defStyle);
92
93 TypedArray a =
94 context.obtainStyledAttributes(attrs,
Evan Millarc1a2a822009-09-29 18:02:06 -070095 com.android.internal.R.styleable.QuickContactBadge, defStyle, 0);
Evan Millare727f182009-08-27 11:15:55 -070096
Evan Millarc1a2a822009-09-29 18:02:06 -070097 mMode = a.getInt(com.android.internal.R.styleable.QuickContactBadge_quickContactWindowSize,
Evan Millare3ec9972009-09-30 19:37:36 -070098 QuickContact.MODE_MEDIUM);
Evan Millare727f182009-08-27 11:15:55 -070099
100 a.recycle();
101
102 init();
Mark Wagnerf5935a92009-09-22 13:49:26 -0700103
104 mBadgeBackground = getBackground();
Evan Millare727f182009-08-27 11:15:55 -0700105 }
106
107 private void init() {
108 mQueryHandler = new QueryHandler(mContext.getContentResolver());
109 setOnClickListener(this);
110 }
111
112 /**
Evan Millare3ec9972009-09-30 19:37:36 -0700113 * Set the QuickContact window mode. Options are {@link QuickContact#MODE_SMALL},
114 * {@link QuickContact#MODE_MEDIUM}, {@link QuickContact#MODE_LARGE}.
115 * @param size
116 */
117 public void setMode(int size) {
118 mMode = size;
119 }
120
121 /**
Evan Millarc1a2a822009-09-29 18:02:06 -0700122 * Assign the contact uri that this QuickContactBadge should be associated
123 * with. Note that this is only used for displaying the QuickContact window and
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700124 * won't bind the contact's photo for you.
Evan Millare727f182009-08-27 11:15:55 -0700125 *
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700126 * @param contactUri Either a {@link Contacts#CONTENT_URI} or
127 * {@link Contacts#CONTENT_LOOKUP_URI} style URI.
Evan Millare727f182009-08-27 11:15:55 -0700128 */
129 public void assignContactUri(Uri contactUri) {
130 mContactUri = contactUri;
Mark Wagnerf5935a92009-09-22 13:49:26 -0700131 mContactEmail = null;
132 mContactPhone = null;
133 onContactUriChanged();
134 }
135
136 private void onContactUriChanged() {
137 if (mContactUri == null && mContactEmail == null && mContactPhone == null) {
Mark Wagnerb2c64292009-09-28 16:39:20 -0700138 if (mNoBadgeBackground == null) {
Evan Millarc1a2a822009-09-29 18:02:06 -0700139 mNoBadgeBackground = getResources().getDrawable(R.drawable.quickcontact_nobadge);
Mark Wagnerb2c64292009-09-28 16:39:20 -0700140 }
141 setBackgroundDrawable(mNoBadgeBackground);
Mark Wagnerf5935a92009-09-22 13:49:26 -0700142 } else {
143 setBackgroundDrawable(mBadgeBackground);
144 }
Evan Millare727f182009-08-27 11:15:55 -0700145 }
146
147 /**
148 * Assign a contact based on an email address. This should only be used when
149 * the contact's URI is not available, as an extra query will have to be
150 * performed to lookup the URI based on the email.
151 *
152 * @param emailAddress The email address of the contact.
153 * @param lazyLookup If this is true, the lookup query will not be performed
154 * until this view is clicked.
155 */
156 public void assignContactFromEmail(String emailAddress, boolean lazyLookup) {
157 mContactEmail = emailAddress;
158 if (!lazyLookup) {
159 mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, null,
160 Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
161 EMAIL_LOOKUP_PROJECTION, null, null, null);
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700162 } else {
163 mContactUri = null;
Mark Wagnerf5935a92009-09-22 13:49:26 -0700164 onContactUriChanged();
Evan Millare727f182009-08-27 11:15:55 -0700165 }
166 }
167
168 /**
169 * Assign a contact based on a phone number. This should only be used when
170 * the contact's URI is not available, as an extra query will have to be
171 * performed to lookup the URI based on the phone number.
172 *
173 * @param phoneNumber The phone number of the contact.
174 * @param lazyLookup If this is true, the lookup query will not be performed
175 * until this view is clicked.
176 */
177 public void assignContactFromPhone(String phoneNumber, boolean lazyLookup) {
178 mContactPhone = phoneNumber;
179 if (!lazyLookup) {
180 mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, null,
181 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
182 PHONE_LOOKUP_PROJECTION, null, null, null);
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700183 } else {
184 mContactUri = null;
Mark Wagnerf5935a92009-09-22 13:49:26 -0700185 onContactUriChanged();
Evan Millare727f182009-08-27 11:15:55 -0700186 }
187 }
188
Evan Millare727f182009-08-27 11:15:55 -0700189 public void onClick(View v) {
Evan Millare727f182009-08-27 11:15:55 -0700190 if (mContactUri != null) {
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -0700191 mQueryHandler.startQuery(TOKEN_CONTACT_LOOKUP_AND_TRIGGER, null,
192 mContactUri,
193 CONTACT_LOOKUP_PROJECTION, null, null, null);
Evan Millare727f182009-08-27 11:15:55 -0700194 } else if (mContactEmail != null) {
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700195 mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP_AND_TRIGGER, mContactEmail,
Evan Millare727f182009-08-27 11:15:55 -0700196 Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(mContactEmail)),
197 EMAIL_LOOKUP_PROJECTION, null, null, null);
198 } else if (mContactPhone != null) {
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700199 mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP_AND_TRIGGER, mContactPhone,
Evan Millare727f182009-08-27 11:15:55 -0700200 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, mContactPhone),
201 PHONE_LOOKUP_PROJECTION, null, null, null);
202 } else {
203 // If a contact hasn't been assigned, don't react to click.
204 return;
205 }
206 }
207
208 /**
209 * Set a list of specific MIME-types to exclude and not display. For
210 * example, this can be used to hide the {@link Contacts#CONTENT_ITEM_TYPE}
211 * profile icon.
212 */
213 public void setExcludeMimes(String[] excludeMimes) {
214 mExcludeMimes = excludeMimes;
215 }
216
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700217 private void trigger(Uri lookupUri) {
Evan Millare3ec9972009-09-30 19:37:36 -0700218 QuickContact.showQuickContact(getContext(), this, lookupUri, mMode, mExcludeMimes);
Evan Millare727f182009-08-27 11:15:55 -0700219 }
220
221 private class QueryHandler extends AsyncQueryHandler {
222
223 public QueryHandler(ContentResolver cr) {
224 super(cr);
225 }
226
227 @Override
228 protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700229 Uri lookupUri = null;
230 Uri createUri = null;
Evan Millare727f182009-08-27 11:15:55 -0700231 boolean trigger = false;
232
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700233 try {
Evan Millare727f182009-08-27 11:15:55 -0700234 switch(token) {
235 case TOKEN_PHONE_LOOKUP_AND_TRIGGER:
236 trigger = true;
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700237 createUri = Uri.fromParts("tel", (String)cookie, null);
238
Evan Millare727f182009-08-27 11:15:55 -0700239 case TOKEN_PHONE_LOOKUP: {
240 if (cursor != null && cursor.moveToFirst()) {
241 long contactId = cursor.getLong(PHONE_ID_COLUMN_INDEX);
242 String lookupKey = cursor.getString(PHONE_LOOKUP_STRING_COLUMN_INDEX);
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700243 lookupUri = Contacts.getLookupUri(contactId, lookupKey);
Evan Millare727f182009-08-27 11:15:55 -0700244 }
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700245
Evan Millare727f182009-08-27 11:15:55 -0700246 break;
247 }
248 case TOKEN_EMAIL_LOOKUP_AND_TRIGGER:
249 trigger = true;
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700250 createUri = Uri.fromParts("mailto", (String)cookie, null);
251
Evan Millare727f182009-08-27 11:15:55 -0700252 case TOKEN_EMAIL_LOOKUP: {
253 if (cursor != null && cursor.moveToFirst()) {
254 long contactId = cursor.getLong(EMAIL_ID_COLUMN_INDEX);
255 String lookupKey = cursor.getString(EMAIL_LOOKUP_STRING_COLUMN_INDEX);
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700256 lookupUri = Contacts.getLookupUri(contactId, lookupKey);
Evan Millare727f182009-08-27 11:15:55 -0700257 }
258 }
Tadashi G. Takaoka01fd4e12009-10-01 18:10:46 -0700259
260 case TOKEN_CONTACT_LOOKUP_AND_TRIGGER: {
261 if (cursor != null && cursor.moveToFirst()) {
262 long contactId = cursor.getLong(CONTACT_ID_COLUMN_INDEX);
263 String lookupKey = cursor.getString(CONTACT_LOOKUPKEY_COLUMN_INDEX);
264 lookupUri = Contacts.getLookupUri(contactId, lookupKey);
265 trigger = true;
266 }
267
268 break;
269 }
Evan Millare727f182009-08-27 11:15:55 -0700270 }
271 } finally {
272 if (cursor != null) {
273 cursor.close();
274 }
275 }
276
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700277 mContactUri = lookupUri;
Mark Wagnerf5935a92009-09-22 13:49:26 -0700278 onContactUriChanged();
Jeff Sharkey0050ee32009-09-17 16:11:32 -0700279
280 if (trigger && lookupUri != null) {
281 // Found contact, so trigger track
282 trigger(lookupUri);
283 } else if (createUri != null) {
284 // Prompt user to add this person to contacts
285 final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, createUri);
286 getContext().startActivity(intent);
Evan Millare727f182009-08-27 11:15:55 -0700287 }
288 }
289 }
290}