blob: 5a49c77d85834ed3699c171a88b969b6cfe97e00 [file] [log] [blame]
/*
* Copyright (C) 2010 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.quickcontact;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.Data;
import android.telecom.PhoneAccount;
import android.text.TextUtils;
import android.util.Log;
import com.android.contacts.R;
import com.android.contacts.common.CallUtil;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.model.account.AccountType.EditType;
import com.android.contacts.common.model.dataitem.DataItem;
import com.android.contacts.common.model.dataitem.DataKind;
import com.android.contacts.common.model.dataitem.EmailDataItem;
import com.android.contacts.common.model.dataitem.ImDataItem;
import com.android.contacts.common.model.dataitem.PhoneDataItem;
import com.android.contacts.common.model.dataitem.SipAddressDataItem;
import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
import com.android.contacts.common.model.dataitem.WebsiteDataItem;
import com.android.contacts.quickcontact.WebAddress.ParseException;
import com.android.contacts.util.PhoneCapabilityTester;
import com.android.contacts.util.StructuredPostalUtils;
/**
* Description of a specific {@link Data#_ID} item, with style information
* defined by a {@link DataKind}.
*/
public class DataAction implements Action {
private static final String TAG = "DataAction";
private final Context mContext;
private final DataKind mKind;
private final String mMimeType;
private final Integer mTimesUsed;
private final Long mLastTimeUsed;
private CharSequence mBody;
private CharSequence mSubtitle;
private Intent mIntent;
private Intent mAlternateIntent;
private int mAlternateIconDescriptionRes;
private int mAlternateIconRes;
private int mPresence = -1;
private Uri mDataUri;
private long mDataId;
private boolean mIsPrimary;
private boolean mIsSuperPrimary;
/**
* Create an action from common {@link Data} elements.
*/
public DataAction(Context context, DataItem item, DataKind kind) {
mContext = context;
mKind = kind;
mMimeType = item.getMimeType();
mTimesUsed = item.getTimesUsed();
mLastTimeUsed = item.getLastTimeUsed();
// Determine type for subtitle
mSubtitle = "";
if (item.hasKindTypeColumn(kind)) {
final int typeValue = item.getKindTypeColumn(kind);
// get type string
for (EditType type : kind.typeList) {
if (type.rawValue == typeValue) {
if (type.customColumn == null) {
// Non-custom type. Get its description from the resource
mSubtitle = context.getString(type.labelRes);
} else {
// Custom type. Read it from the database
mSubtitle = item.getContentValues().getAsString(type.customColumn);
}
break;
}
}
}
mIsPrimary = item.isPrimary();
mIsSuperPrimary = item.isSuperPrimary();
mBody = item.buildDataStringForDisplay(context, kind);
mDataId = item.getId();
mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, mDataId);
final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
final ComponentName smsComponent = PhoneCapabilityTester.getSmsComponent(mContext);
final boolean hasSms = (smsComponent != null);
// Handle well-known MIME-types with special care
if (item instanceof PhoneDataItem) {
if (PhoneCapabilityTester.isPhone(mContext)) {
PhoneDataItem phone = (PhoneDataItem) item;
final String number = phone.getNumber();
if (!TextUtils.isEmpty(number)) {
final Intent phoneIntent = hasPhone ? CallUtil.getCallIntent(number)
: null;
Intent smsIntent = null;
if (hasSms) {
smsIntent = new Intent(Intent.ACTION_SENDTO,
Uri.fromParts(ContactsUtils.SCHEME_SMSTO, number, null));
smsIntent.setComponent(smsComponent);
}
// Configure Icons and Intents. Notice actionIcon is already set to the phone
if (hasPhone && hasSms) {
mIntent = phoneIntent;
mAlternateIntent = smsIntent;
mAlternateIconRes = kind.iconAltRes;
mAlternateIconDescriptionRes = kind.iconAltDescriptionRes;
} else if (hasPhone) {
mIntent = phoneIntent;
} else if (hasSms) {
mIntent = smsIntent;
}
}
}
} else if (item instanceof SipAddressDataItem) {
if (PhoneCapabilityTester.isSipPhone(mContext)) {
final SipAddressDataItem sip = (SipAddressDataItem) item;
final String address = sip.getSipAddress();
if (!TextUtils.isEmpty(address)) {
final Uri callUri = Uri.fromParts(PhoneAccount.SCHEME_SIP, address, null);
mIntent = CallUtil.getCallIntent(callUri);
// Note that this item will get a SIP-specific variant
// of the "call phone" icon, rather than the standard
// app icon for the Phone app (which we show for
// regular phone numbers.) That's because the phone
// app explicitly specifies an android:icon attribute
// for the SIP-related intent-filters in its manifest.
}
}
} else if (item instanceof EmailDataItem) {
final EmailDataItem email = (EmailDataItem) item;
final String address = email.getData();
if (!TextUtils.isEmpty(address)) {
final Uri mailUri = Uri.fromParts(ContactsUtils.SCHEME_MAILTO, address, null);
mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
}
} else if (item instanceof WebsiteDataItem) {
final WebsiteDataItem website = (WebsiteDataItem) item;
final String url = website.getUrl();
if (!TextUtils.isEmpty(url)) {
try {
final WebAddress webAddress = new WebAddress(url);
mIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(webAddress.toString()));
} catch (ParseException e) {
mIntent = null;
}
}
} else if (item instanceof ImDataItem) {
ImDataItem im = (ImDataItem) item;
final boolean isEmail = im.isCreatedFromEmail();
if (isEmail || im.isProtocolValid()) {
final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
if (isEmail) {
// Use Google Talk string when using Email, and clear data
// Uri so we don't try saving Email as primary.
mSubtitle = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK,
null);
mDataUri = null;
}
String host = im.getCustomProtocol();
String data = im.getData();
if (protocol != Im.PROTOCOL_CUSTOM) {
// Try bringing in a well-known host for specific protocols
host = ContactsUtils.lookupProviderNameFromId(protocol);
}
if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
final String authority = host.toLowerCase();
final Uri imUri = new Uri.Builder().scheme(ContactsUtils.SCHEME_IMTO).authority(
authority).appendPath(data).build();
mIntent = new Intent(Intent.ACTION_SENDTO, imUri);
// If the address is also available for a video chat, we'll show the capability
// as a secondary action.
final int chatCapability = im.getChatCapability();
final boolean isVideoChatCapable =
(chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0;
final boolean isAudioChatCapable =
(chatCapability & Im.CAPABILITY_HAS_VOICE) != 0;
if (isVideoChatCapable || isAudioChatCapable) {
mAlternateIntent = new Intent(
Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
if (isVideoChatCapable) {
mAlternateIconRes = R.drawable.sym_action_videochat_holo_light;
mAlternateIconDescriptionRes = R.string.video_chat;
} else {
mAlternateIconRes = R.drawable.sym_action_audiochat_holo_light;
mAlternateIconDescriptionRes = R.string.audio_chat;
}
}
}
}
} else if (item instanceof StructuredPostalDataItem) {
StructuredPostalDataItem postal = (StructuredPostalDataItem) item;
final String postalAddress = postal.getFormattedAddress();
if (!TextUtils.isEmpty(postalAddress)) {
mIntent = StructuredPostalUtils.getViewPostalAddressIntent(postalAddress);
}
}
if (mIntent == null) {
// Otherwise fall back to default VIEW action
mIntent = new Intent(Intent.ACTION_VIEW);
mIntent.setDataAndType(mDataUri, item.getMimeType());
}
mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
}
@Override
public int getPresence() {
return mPresence;
}
public void setPresence(int presence) {
mPresence = presence;
}
@Override
public CharSequence getSubtitle() {
return mSubtitle;
}
@Override
public CharSequence getBody() {
return mBody;
}
@Override
public String getMimeType() {
return mMimeType;
}
@Override
public Uri getDataUri() {
return mDataUri;
}
@Override
public long getDataId() {
return mDataId;
}
@Override
public boolean isPrimary() {
return mIsPrimary;
}
@Override
public boolean isSuperPrimary() {
return mIsSuperPrimary;
}
@Override
public Drawable getAlternateIcon() {
if (mAlternateIconRes == 0) return null;
final String resourcePackageName = mKind.resourcePackageName;
if (resourcePackageName == null) {
return mContext.getResources().getDrawable(mAlternateIconRes);
}
final PackageManager pm = mContext.getPackageManager();
return pm.getDrawable(resourcePackageName, mAlternateIconRes, null);
}
@Override
public String getAlternateIconDescription() {
if (mAlternateIconDescriptionRes == 0) return null;
return mContext.getResources().getString(mAlternateIconDescriptionRes);
}
@Override
public Intent getIntent() {
return mIntent;
}
@Override
public Intent getAlternateIntent() {
return mAlternateIntent;
}
@Override
public void collapseWith(Action other) {
// No-op
}
@Override
public boolean shouldCollapseWith(Action t, Context context) {
if (t == null) {
return false;
}
if (!(t instanceof DataAction)) {
Log.e(TAG, "t must be DataAction");
return false;
}
DataAction that = (DataAction)t;
if (!MoreContactUtils.shouldCollapse(mMimeType, mBody, that.mMimeType, that.mBody)) {
return false;
}
if (!TextUtils.equals(mMimeType, that.mMimeType)
|| !ContactsUtils.areIntentActionEqual(mIntent, that.mIntent)) {
return false;
}
return true;
}
@Override
public Integer getTimesUsed() {
return mTimesUsed;
}
@Override
public Long getLastTimeUsed() {
return mLastTimeUsed;
}
}