blob: 0750a1de821552ac4e3c7d069a89a094cbce982b [file] [log] [blame]
Daniel Lehmannfbb87632011-09-30 20:54:15 -07001/*
2 * Copyright (C) 2010 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
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080017package com.android.contacts.quickcontact;
18
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080019import android.content.ContentUris;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.PackageManager;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080023import android.graphics.drawable.Drawable;
24import android.net.Uri;
Dmitri Plotnikov15dcf1d2010-12-09 17:12:54 -080025import android.net.WebAddress;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080026import android.provider.ContactsContract.CommonDataKinds.Im;
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -070027import android.provider.ContactsContract.Data;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080028import android.text.TextUtils;
29import android.util.Log;
30
Chiao Cheng3a8df862012-09-04 16:30:17 -070031import com.android.contacts.common.CallUtil;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070032import com.android.contacts.ContactsUtils;
33import com.android.contacts.R;
Chiao Chengd7ca03e2012-10-24 15:14:08 -070034import com.android.contacts.common.MoreContactUtils;
Chiao Cheng428f0082012-11-13 18:38:56 -080035import com.android.contacts.common.model.account.AccountType.EditType;
Maurice Chu851222a2012-06-21 11:43:08 -070036import com.android.contacts.model.dataitem.DataItem;
Chiao Cheng428f0082012-11-13 18:38:56 -080037import com.android.contacts.common.model.dataitem.DataKind;
Maurice Chu851222a2012-06-21 11:43:08 -070038import com.android.contacts.model.dataitem.EmailDataItem;
39import com.android.contacts.model.dataitem.ImDataItem;
40import com.android.contacts.model.dataitem.PhoneDataItem;
41import com.android.contacts.model.dataitem.SipAddressDataItem;
42import com.android.contacts.model.dataitem.StructuredPostalDataItem;
43import com.android.contacts.model.dataitem.WebsiteDataItem;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070044import com.android.contacts.util.PhoneCapabilityTester;
45import com.android.contacts.util.StructuredPostalUtils;
46
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080047/**
48 * Description of a specific {@link Data#_ID} item, with style information
49 * defined by a {@link DataKind}.
50 */
51public class DataAction implements Action {
52 private static final String TAG = "DataAction";
53
54 private final Context mContext;
55 private final DataKind mKind;
56 private final String mMimeType;
57
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080058 private CharSequence mBody;
Daniel Lehmannedb576a2011-07-27 16:45:13 -070059 private CharSequence mSubtitle;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080060 private Intent mIntent;
Daniel Lehmannedb576a2011-07-27 16:45:13 -070061 private Intent mAlternateIntent;
Katherine Kuanee05dcd2011-10-05 20:18:12 -070062 private int mAlternateIconDescriptionRes;
Daniel Lehmannedb576a2011-07-27 16:45:13 -070063 private int mAlternateIconRes;
Daniel Lehmann9daca142011-12-20 11:41:22 +020064 private int mPresence = -1;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080065
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080066 private Uri mDataUri;
Daniel Lehmann0f78e8b2010-11-24 17:32:03 -080067 private long mDataId;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080068 private boolean mIsPrimary;
69
70 /**
71 * Create an action from common {@link Data} elements.
72 */
Chiao Cheng47b6f702012-09-07 17:28:17 -070073 public DataAction(Context context, DataItem item, DataKind kind) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080074 mContext = context;
Chiao Cheng47b6f702012-09-07 17:28:17 -070075 mKind = kind;
Maurice Chu851222a2012-06-21 11:43:08 -070076 mMimeType = item.getMimeType();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080077
Daniel Lehmannedb576a2011-07-27 16:45:13 -070078 // Determine type for subtitle
79 mSubtitle = "";
Chiao Cheng47b6f702012-09-07 17:28:17 -070080 if (item.hasKindTypeColumn(kind)) {
81 final int typeValue = item.getKindTypeColumn(kind);
Daniel Lehmannedb576a2011-07-27 16:45:13 -070082
Maurice Chu851222a2012-06-21 11:43:08 -070083 // get type string
Chiao Cheng47b6f702012-09-07 17:28:17 -070084 for (EditType type : kind.typeList) {
Maurice Chu851222a2012-06-21 11:43:08 -070085 if (type.rawValue == typeValue) {
86 if (type.customColumn == null) {
87 // Non-custom type. Get its description from the resource
88 mSubtitle = context.getString(type.labelRes);
89 } else {
90 // Custom type. Read it from the database
91 mSubtitle = item.getContentValues().getAsString(type.customColumn);
Daniel Lehmannedb576a2011-07-27 16:45:13 -070092 }
Maurice Chu851222a2012-06-21 11:43:08 -070093 break;
Daniel Lehmannedb576a2011-07-27 16:45:13 -070094 }
95 }
Daniel Lehmannaf8e3862010-11-19 15:38:44 -080096 }
97
Maurice Chu851222a2012-06-21 11:43:08 -070098 mIsPrimary = item.isSuperPrimary();
Yorke Leeb2b435a2012-11-12 16:47:06 -080099 mBody = item.buildDataStringForDisplay(context, kind);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800100
Maurice Chu851222a2012-06-21 11:43:08 -0700101 mDataId = item.getId();
102 mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, mDataId);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800103
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700104 final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
105 final boolean hasSms = PhoneCapabilityTester.isSmsIntentRegistered(mContext);
106
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800107 // Handle well-known MIME-types with special care
Maurice Chu851222a2012-06-21 11:43:08 -0700108 if (item instanceof PhoneDataItem) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800109 if (PhoneCapabilityTester.isPhone(mContext)) {
Maurice Chu851222a2012-06-21 11:43:08 -0700110 PhoneDataItem phone = (PhoneDataItem) item;
111 final String number = phone.getNumber();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800112 if (!TextUtils.isEmpty(number)) {
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700113
Chiao Cheng3a8df862012-09-04 16:30:17 -0700114 final Intent phoneIntent = hasPhone ? CallUtil.getCallIntent(number)
Daisuke Miyakawafadd5e12011-12-01 17:34:18 -0800115 : null;
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700116 final Intent smsIntent = hasSms ? new Intent(Intent.ACTION_SENDTO,
Chiao Cheng3a8df862012-09-04 16:30:17 -0700117 Uri.fromParts(CallUtil.SCHEME_SMSTO, number, null)) : null;
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700118
119 // Configure Icons and Intents. Notice actionIcon is already set to the phone
120 if (hasPhone && hasSms) {
121 mIntent = phoneIntent;
122 mAlternateIntent = smsIntent;
Chiao Cheng47b6f702012-09-07 17:28:17 -0700123 mAlternateIconRes = kind.iconAltRes;
124 mAlternateIconDescriptionRes = kind.iconAltDescriptionRes;
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700125 } else if (hasPhone) {
126 mIntent = phoneIntent;
127 } else if (hasSms) {
128 mIntent = smsIntent;
129 }
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800130 }
131 }
Maurice Chu851222a2012-06-21 11:43:08 -0700132 } else if (item instanceof SipAddressDataItem) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800133 if (PhoneCapabilityTester.isSipPhone(mContext)) {
Maurice Chu851222a2012-06-21 11:43:08 -0700134 final SipAddressDataItem sip = (SipAddressDataItem) item;
135 final String address = sip.getSipAddress();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800136 if (!TextUtils.isEmpty(address)) {
Chiao Cheng3a8df862012-09-04 16:30:17 -0700137 final Uri callUri = Uri.fromParts(CallUtil.SCHEME_SIP, address, null);
138 mIntent = CallUtil.getCallIntent(callUri);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800139 // Note that this item will get a SIP-specific variant
140 // of the "call phone" icon, rather than the standard
141 // app icon for the Phone app (which we show for
142 // regular phone numbers.) That's because the phone
143 // app explicitly specifies an android:icon attribute
144 // for the SIP-related intent-filters in its manifest.
145 }
146 }
Maurice Chu851222a2012-06-21 11:43:08 -0700147 } else if (item instanceof EmailDataItem) {
148 final EmailDataItem email = (EmailDataItem) item;
149 final String address = email.getData();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800150 if (!TextUtils.isEmpty(address)) {
Chiao Cheng3a8df862012-09-04 16:30:17 -0700151 final Uri mailUri = Uri.fromParts(CallUtil.SCHEME_MAILTO, address, null);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800152 mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
153 }
154
Maurice Chu851222a2012-06-21 11:43:08 -0700155 } else if (item instanceof WebsiteDataItem) {
156 final WebsiteDataItem website = (WebsiteDataItem) item;
157 final String url = website.getUrl();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800158 if (!TextUtils.isEmpty(url)) {
Dmitri Plotnikov15dcf1d2010-12-09 17:12:54 -0800159 WebAddress webAddress = new WebAddress(url);
160 mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800161 }
162
Maurice Chu851222a2012-06-21 11:43:08 -0700163 } else if (item instanceof ImDataItem) {
164 ImDataItem im = (ImDataItem) item;
165 final boolean isEmail = im.isCreatedFromEmail();
166 if (isEmail || im.isProtocolValid()) {
167 final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800168
169 if (isEmail) {
170 // Use Google Talk string when using Email, and clear data
171 // Uri so we don't try saving Email as primary.
Daniel Lehmann9daca142011-12-20 11:41:22 +0200172 mSubtitle = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK,
173 null);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800174 mDataUri = null;
175 }
176
Maurice Chu851222a2012-06-21 11:43:08 -0700177 String host = im.getCustomProtocol();
178 String data = im.getData();
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800179 if (protocol != Im.PROTOCOL_CUSTOM) {
180 // Try bringing in a well-known host for specific protocols
181 host = ContactsUtils.lookupProviderNameFromId(protocol);
182 }
183
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -0700184 if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800185 final String authority = host.toLowerCase();
Chiao Cheng3a8df862012-09-04 16:30:17 -0700186 final Uri imUri = new Uri.Builder().scheme(CallUtil.SCHEME_IMTO).authority(
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800187 authority).appendPath(data).build();
188 mIntent = new Intent(Intent.ACTION_SENDTO, imUri);
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -0700189
190 // If the address is also available for a video chat, we'll show the capability
191 // as a secondary action.
Maurice Chu851222a2012-06-21 11:43:08 -0700192 final int chatCapability = im.getChatCapability();
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -0700193 final boolean isVideoChatCapable =
194 (chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
195 final boolean isAudioChatCapable =
196 (chatCapability & Im.CAPABILITY_HAS_VOICE) != 0;
197 if (isVideoChatCapable || isAudioChatCapable) {
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -0700198 mAlternateIntent = new Intent(
199 Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
Katherine Kuanee05dcd2011-10-05 20:18:12 -0700200 if (isVideoChatCapable) {
201 mAlternateIconRes = R.drawable.sym_action_videochat_holo_light;
202 mAlternateIconDescriptionRes = R.string.video_chat;
203 } else {
204 mAlternateIconRes = R.drawable.sym_action_audiochat_holo_light;
205 mAlternateIconDescriptionRes = R.string.audio_chat;
206 }
Daisuke Miyakawaf31df5d2011-08-02 15:37:50 -0700207 }
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800208 }
209 }
Maurice Chu851222a2012-06-21 11:43:08 -0700210 } else if (item instanceof StructuredPostalDataItem) {
211 StructuredPostalDataItem postal = (StructuredPostalDataItem) item;
212 final String postalAddress = postal.getFormattedAddress();
Makoto Onukibfb59d82011-09-30 16:34:38 -0700213 if (!TextUtils.isEmpty(postalAddress)) {
214 mIntent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
215 }
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800216 }
217
218 if (mIntent == null) {
219 // Otherwise fall back to default VIEW action
Dmitri Plotnikov1b89adc2010-12-09 17:05:54 -0800220 mIntent = new Intent(Intent.ACTION_VIEW);
Maurice Chu851222a2012-06-21 11:43:08 -0700221 mIntent.setDataAndType(mDataUri, item.getMimeType());
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800222 }
223
Adam Powell8ca93ed2012-04-23 13:28:28 -0700224 mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800225 }
226
Daniel Lehmann9daca142011-12-20 11:41:22 +0200227 @Override
228 public int getPresence() {
229 return mPresence;
230 }
231
232 public void setPresence(int presence) {
233 mPresence = presence;
234 }
235
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800236 @Override
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700237 public CharSequence getSubtitle() {
238 return mSubtitle;
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800239 }
240
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800241 @Override
242 public CharSequence getBody() {
243 return mBody;
244 }
245
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800246 @Override
247 public String getMimeType() {
248 return mMimeType;
249 }
250
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800251 @Override
252 public Uri getDataUri() {
253 return mDataUri;
254 }
255
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800256 @Override
Daniel Lehmann0f78e8b2010-11-24 17:32:03 -0800257 public long getDataId() {
258 return mDataId;
259 }
260
Daniel Lehmann0f78e8b2010-11-24 17:32:03 -0800261 @Override
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800262 public Boolean isPrimary() {
263 return mIsPrimary;
264 }
265
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800266 @Override
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700267 public Drawable getAlternateIcon() {
268 if (mAlternateIconRes == 0) return null;
269
Makoto Onuki82a4f442012-05-07 17:18:33 -0700270 final String resourcePackageName = mKind.resourcePackageName;
271 if (resourcePackageName == null) {
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700272 return mContext.getResources().getDrawable(mAlternateIconRes);
273 }
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800274
275 final PackageManager pm = mContext.getPackageManager();
Makoto Onuki82a4f442012-05-07 17:18:33 -0700276 return pm.getDrawable(resourcePackageName, mAlternateIconRes, null);
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800277 }
278
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800279 @Override
Katherine Kuanee05dcd2011-10-05 20:18:12 -0700280 public String getAlternateIconDescription() {
281 if (mAlternateIconDescriptionRes == 0) return null;
282 return mContext.getResources().getString(mAlternateIconDescriptionRes);
283 }
284
285 @Override
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800286 public Intent getIntent() {
287 return mIntent;
288 }
289
Daniel Lehmannedb576a2011-07-27 16:45:13 -0700290 @Override
291 public Intent getAlternateIntent() {
292 return mAlternateIntent;
293 }
294
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800295 @Override
Jay Shraunerad29eae2013-01-08 11:42:17 -0800296 public void collapseWith(Action other) {
297 // No-op
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800298 }
299
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800300 @Override
301 public boolean shouldCollapseWith(Action t) {
302 if (t == null) {
303 return false;
304 }
305 if (!(t instanceof DataAction)) {
306 Log.e(TAG, "t must be DataAction");
307 return false;
308 }
Daniel Lehmann69fad282011-08-28 21:15:27 -0700309 DataAction that = (DataAction)t;
Chiao Chengd7ca03e2012-10-24 15:14:08 -0700310 if (!MoreContactUtils.shouldCollapse(mMimeType, mBody, that.mMimeType, that.mBody)) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800311 return false;
312 }
Daniel Lehmann69fad282011-08-28 21:15:27 -0700313 if (!TextUtils.equals(mMimeType, that.mMimeType)
314 || !ContactsUtils.areIntentActionEqual(mIntent, that.mIntent)) {
Daniel Lehmannaf8e3862010-11-19 15:38:44 -0800315 return false;
316 }
317 return true;
318 }
319}