/*
* Copyright (C) 2008 Esmertec AG.
* Copyright (C) 2008 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.mms.ui;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.ContactsContract.Profile;
import android.provider.Telephony.Sms;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.HideReturnsTransformationMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.LineHeightSpan;
import android.text.style.StyleSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.mms.MmsApp;
import com.android.mms.R;
import com.android.mms.data.Contact;
import com.android.mms.data.WorkingMessage;
import com.android.mms.model.SlideModel;
import com.android.mms.model.SlideshowModel;
import com.android.mms.transaction.Transaction;
import com.android.mms.transaction.TransactionBundle;
import com.android.mms.transaction.TransactionService;
import com.android.mms.util.DownloadManager;
import com.android.mms.util.ItemLoadedCallback;
import com.android.mms.util.EmojiParser;
import com.android.mms.util.SmileyParser;
import com.android.mms.util.ThumbnailManager.ImageLoaded;
import com.google.android.mms.ContentType;
import com.google.android.mms.pdu.PduHeaders;
/**
* This class provides view of a message in the messages list.
*/
public class MessageListItem extends LinearLayout implements
SlideViewInterface, OnClickListener {
public static final String EXTRA_URLS = "com.android.mms.ExtraUrls";
private static final String TAG = "MessageListItem";
private static final boolean DEBUG = false;
private static final boolean DEBUG_DONT_LOAD_IMAGES = false;
static final int MSG_LIST_EDIT = 1;
static final int MSG_LIST_PLAY = 2;
static final int MSG_LIST_DETAILS = 3;
private View mMmsView;
private ImageView mImageView;
private ImageView mLockedIndicator;
private ImageView mDeliveredIndicator;
private ImageView mDetailsIndicator;
private ImageButton mSlideShowButton;
private TextView mBodyTextView;
private Button mDownloadButton;
private TextView mDownloadingLabel;
private Handler mHandler;
private MessageItem mMessageItem;
private String mDefaultCountryIso;
private TextView mDateView;
public View mMessageBlock;
private QuickContactDivot mAvatar;
static private Drawable sDefaultContactImage;
private Presenter mPresenter;
private int mPosition; // for debugging
private ImageLoadedCallback mImageLoadedCallback;
private boolean mMultiRecipients;
public MessageListItem(Context context) {
super(context);
mDefaultCountryIso = MmsApp.getApplication().getCurrentCountryIso();
if (sDefaultContactImage == null) {
sDefaultContactImage = context.getResources().getDrawable(R.drawable.ic_contact_picture);
}
}
public MessageListItem(Context context, AttributeSet attrs) {
super(context, attrs);
int color = mContext.getResources().getColor(R.color.timestamp_color);
mColorSpan = new ForegroundColorSpan(color);
mDefaultCountryIso = MmsApp.getApplication().getCurrentCountryIso();
if (sDefaultContactImage == null) {
sDefaultContactImage = context.getResources().getDrawable(R.drawable.ic_contact_picture);
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mBodyTextView = (TextView) findViewById(R.id.text_view);
mDateView = (TextView) findViewById(R.id.date_view);
mLockedIndicator = (ImageView) findViewById(R.id.locked_indicator);
mDeliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator);
mDetailsIndicator = (ImageView) findViewById(R.id.details_indicator);
mAvatar = (QuickContactDivot) findViewById(R.id.avatar);
mMessageBlock = findViewById(R.id.message_block);
}
public void bind(MessageItem msgItem, boolean convHasMultiRecipients, int position) {
if (DEBUG) {
Log.v(TAG, "bind for item: " + position + " old: " +
(mMessageItem != null ? mMessageItem.toString() : "NULL" ) +
" new " + msgItem.toString());
}
boolean sameItem = mMessageItem != null && mMessageItem.mMsgId == msgItem.mMsgId;
mMessageItem = msgItem;
mPosition = position;
mMultiRecipients = convHasMultiRecipients;
setLongClickable(false);
setClickable(false); // let the list view handle clicks on the item normally. When
// clickable is true, clicks bypass the listview and go straight
// to this listitem. We always want the listview to handle the
// clicks first.
switch (msgItem.mMessageType) {
case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND:
bindNotifInd();
break;
default:
bindCommonMessage(sameItem);
break;
}
}
public void unbind() {
// Clear all references to the message item, which can contain attachments and other
// memory-intensive objects
if (mImageView != null) {
// Because #setOnClickListener may have set the listener to an object that has the
// message item in its closure.
mImageView.setOnClickListener(null);
}
if (mSlideShowButton != null) {
// Because #drawPlaybackButton sets the tag to mMessageItem
mSlideShowButton.setTag(null);
}
// leave the presenter in case it's needed when rebound to a different MessageItem.
if (mPresenter != null) {
mPresenter.cancelBackgroundLoading();
}
}
public MessageItem getMessageItem() {
return mMessageItem;
}
public void setMsgListItemHandler(Handler handler) {
mHandler = handler;
}
private void bindNotifInd() {
showMmsView(false);
String msgSizeText = mContext.getString(R.string.message_size_label)
+ String.valueOf((mMessageItem.mMessageSize + 1023) / 1024)
+ mContext.getString(R.string.kilobyte);
mBodyTextView.setText(formatMessage(mMessageItem, null,
mMessageItem.mSubject,
mMessageItem.mHighlight,
mMessageItem.mTextContentType));
mDateView.setText(buildTimestampLine(msgSizeText + " " + mMessageItem.mTimestamp));
switch (mMessageItem.getMmsDownloadStatus()) {
case DownloadManager.STATE_DOWNLOADING:
showDownloadingAttachment();
break;
case DownloadManager.STATE_UNKNOWN:
case DownloadManager.STATE_UNSTARTED:
DownloadManager downloadManager = DownloadManager.getInstance();
boolean autoDownload = downloadManager.isAuto();
boolean dataSuspended = (MmsApp.getApplication().getTelephonyManager()
.getDataState() == TelephonyManager.DATA_SUSPENDED);
// If we're going to automatically start downloading the mms attachment, then
// don't bother showing the download button for an instant before the actual
// download begins. Instead, show downloading as taking place.
if (autoDownload && !dataSuspended) {
showDownloadingAttachment();
break;
}
case DownloadManager.STATE_TRANSIENT_FAILURE:
case DownloadManager.STATE_PERMANENT_FAILURE:
default:
setLongClickable(true);
inflateDownloadControls();
mDownloadingLabel.setVisibility(View.GONE);
mDownloadButton.setVisibility(View.VISIBLE);
mDownloadButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mDownloadingLabel.setVisibility(View.VISIBLE);
mDownloadButton.setVisibility(View.GONE);
Intent intent = new Intent(mContext, TransactionService.class);
intent.putExtra(TransactionBundle.URI, mMessageItem.mMessageUri.toString());
intent.putExtra(TransactionBundle.TRANSACTION_TYPE,
Transaction.RETRIEVE_TRANSACTION);
mContext.startService(intent);
}
});
break;
}
// Hide the indicators.
mLockedIndicator.setVisibility(View.GONE);
mDeliveredIndicator.setVisibility(View.GONE);
mDetailsIndicator.setVisibility(View.GONE);
updateAvatarView(mMessageItem.mAddress, false);
}
private String buildTimestampLine(String timestamp) {
if (!mMultiRecipients || mMessageItem.isMe() || TextUtils.isEmpty(mMessageItem.mContact)) {
// Never show "Me" for messages I sent.
return timestamp;
}
// This is a group conversation, show the sender's name on the same line as the timestamp.
return mContext.getString(R.string.message_timestamp_format, mMessageItem.mContact,
timestamp);
}
private void showDownloadingAttachment() {
inflateDownloadControls();
mDownloadingLabel.setVisibility(View.VISIBLE);
mDownloadButton.setVisibility(View.GONE);
}
private void updateAvatarView(String addr, boolean isSelf) {
Drawable avatarDrawable;
if (isSelf || !TextUtils.isEmpty(addr)) {
Contact contact = isSelf ? Contact.getMe(false) : Contact.get(addr, false);
avatarDrawable = contact.getAvatar(mContext, sDefaultContactImage);
if (isSelf) {
mAvatar.assignContactUri(Profile.CONTENT_URI);
} else {
if (contact.existsInDatabase()) {
mAvatar.assignContactUri(contact.getUri());
} else {
mAvatar.assignContactFromPhone(contact.getNumber(), true);
}
}
} else {
avatarDrawable = sDefaultContactImage;
}
mAvatar.setImageDrawable(avatarDrawable);
}
private void bindCommonMessage(final boolean sameItem) {
if (mDownloadButton != null) {
mDownloadButton.setVisibility(View.GONE);
mDownloadingLabel.setVisibility(View.GONE);
}
// Since the message text should be concatenated with the sender's
// address(or name), I have to display it here instead of
// displaying it by the Presenter.
mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
boolean haveLoadedPdu = mMessageItem.isSms() || mMessageItem.mSlideshow != null;
// Here we're avoiding reseting the avatar to the empty avatar when we're rebinding
// to the same item. This happens when there's a DB change which causes the message item
// cache in the MessageListAdapter to get cleared. When an mms MessageItem is newly
// created, it has no info in it except the message id. The info is eventually loaded
// and bindCommonMessage is called again (see onPduLoaded below). When we haven't loaded
// the pdu, we don't want to call updateAvatarView because it
// will set the avatar to the generic avatar then when this method is called again
// from onPduLoaded, it will reset to the real avatar. This test is to avoid that flash.
if (!sameItem || haveLoadedPdu) {
boolean isSelf = Sms.isOutgoingFolder(mMessageItem.mBoxId);
String addr = isSelf ? null : mMessageItem.mAddress;
updateAvatarView(addr, isSelf);
}
// Get and/or lazily set the formatted message from/on the
// MessageItem. Because the MessageItem instances come from a
// cache (currently of size ~50), the hit rate on avoiding the
// expensive formatMessage() call is very high.
CharSequence formattedMessage = mMessageItem.getCachedFormattedMessage();
if (formattedMessage == null) {
formattedMessage = formatMessage(mMessageItem,
mMessageItem.mBody,
mMessageItem.mSubject,
mMessageItem.mHighlight,
mMessageItem.mTextContentType);
mMessageItem.setCachedFormattedMessage(formattedMessage);
}
if (!sameItem || haveLoadedPdu) {
mBodyTextView.setText(formattedMessage);
}
// Debugging code to put the URI of the image attachment in the body of the list item.
if (DEBUG) {
String debugText = null;
if (mMessageItem.mSlideshow == null) {
debugText = "NULL slideshow";
} else {
SlideModel slide = ((SlideshowModel) mMessageItem.mSlideshow).get(0);
if (slide == null) {
debugText = "NULL first slide";
} else if (!slide.hasImage()) {
debugText = "Not an image";
} else {
debugText = slide.getImage().getUri().toString();
}
}
mBodyTextView.setText(mPosition + ": " + debugText);
}
// If we're in the process of sending a message (i.e. pending), then we show a "SENDING..."
// string in place of the timestamp.
if (!sameItem || haveLoadedPdu) {
mDateView.setText(buildTimestampLine(mMessageItem.isSending() ?
mContext.getResources().getString(R.string.sending_message) :
mMessageItem.mTimestamp));
}
if (mMessageItem.isSms()) {
showMmsView(false);
mMessageItem.setOnPduLoaded(null);
} else {
if (DEBUG) {
Log.v(TAG, "bindCommonMessage for item: " + mPosition + " " +
mMessageItem.toString() +
" mMessageItem.mAttachmentType: " + mMessageItem.mAttachmentType +
" sameItem: " + sameItem);
}
if (mMessageItem.mAttachmentType != WorkingMessage.TEXT) {
if (!sameItem) {
setImage(null, null);
}
setOnClickListener(mMessageItem);
drawPlaybackButton(mMessageItem);
} else {
showMmsView(false);
}
if (mMessageItem.mSlideshow == null) {
mMessageItem.setOnPduLoaded(new MessageItem.PduLoadedCallback() {
public void onPduLoaded(MessageItem messageItem) {
if (DEBUG) {
Log.v(TAG, "PduLoadedCallback in MessageListItem for item: " + mPosition +
" " + (mMessageItem == null ? "NULL" : mMessageItem.toString()) +
" passed in item: " +
(messageItem == null ? "NULL" : messageItem.toString()));
}
if (messageItem != null && mMessageItem != null &&
messageItem.getMessageId() == mMessageItem.getMessageId()) {
mMessageItem.setCachedFormattedMessage(null);
bindCommonMessage(true);
}
}
});
} else {
if (mPresenter == null) {
mPresenter = PresenterFactory.getPresenter(
"MmsThumbnailPresenter", mContext,
this, mMessageItem.mSlideshow);
} else {
mPresenter.setModel(mMessageItem.mSlideshow);
mPresenter.setView(this);
}
if (mImageLoadedCallback == null) {
mImageLoadedCallback = new ImageLoadedCallback(this);
} else {
mImageLoadedCallback.reset(this);
}
mPresenter.present(mImageLoadedCallback);
}
}
drawRightStatusIndicator(mMessageItem);
requestLayout();
}
static private class ImageLoadedCallback implements ItemLoadedCallback<ImageLoaded> {
private long mMessageId;
private final MessageListItem mListItem;
public ImageLoadedCallback(MessageListItem listItem) {
mListItem = listItem;
mMessageId = listItem.getMessageItem().getMessageId();
}
public void reset(MessageListItem listItem) {
mMessageId = listItem.getMessageItem().getMessageId();
}
public void onItemLoaded(ImageLoaded imageLoaded, Throwable exception) {
if (DEBUG_DONT_LOAD_IMAGES) {
return;
}
// Make sure we're still pointing to the same message. The list item could have
// been recycled.
MessageItem msgItem = mListItem.mMessageItem;
if (msgItem != null && msgItem.getMessageId() == mMessageId) {
if (imageLoaded.mIsVideo) {
mListItem.setVideoThumbnail(null, imageLoaded.mBitmap);
} else {
mListItem.setImage(null, imageLoaded.mBitmap);
}
}
}
}
@Override
public void startAudio() {
// TODO Auto-generated method stub
}
@Override
public void startVideo() {
// TODO Auto-generated method stub
}
@Override
public void setAudio(Uri audio, String name, Map<String, ?> extras) {
// TODO Auto-generated method stub
}
@Override
public void setImage(String name, Bitmap bitmap) {
showMmsView(true);
try {
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(VISIBLE);
} catch (java.lang.OutOfMemoryError e) {
Log.e(TAG, "setImage: out of memory: ", e);
}
}
private void showMmsView(boolean visible) {
if (mMmsView == null) {
mMmsView = findViewById(R.id.mms_view);
// if mMmsView is still null here, that mean the mms section hasn't been inflated
if (visible && mMmsView == null) {
//inflate the mms view_stub
View mmsStub = findViewById(R.id.mms_layout_view_stub);
mmsStub.setVisibility(View.VISIBLE);
mMmsView = findViewById(R.id.mms_view);
}
}
if (mMmsView != null) {
if (mImageView == null) {
mImageView = (ImageView) findViewById(R.id.image_view);
}
if (mSlideShowButton == null) {
mSlideShowButton = (ImageButton) findViewById(R.id.play_slideshow_button);
}
mMmsView.setVisibility(visible ? View.VISIBLE : View.GONE);
mImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
private void inflateDownloadControls() {
if (mDownloadButton == null) {
//inflate the download controls
findViewById(R.id.mms_downloading_view_stub).setVisibility(VISIBLE);
mDownloadButton = (Button) findViewById(R.id.btn_download_msg);
mDownloadingLabel = (TextView) findViewById(R.id.label_downloading);
}
}
private LineHeightSpan mSpan = new LineHeightSpan() {
@Override
public void chooseHeight(CharSequence text, int start,
int end, int spanstartv, int v, FontMetricsInt fm) {
fm.ascent -= 10;
}
};
TextAppearanceSpan mTextSmallSpan =
new TextAppearanceSpan(mContext, android.R.style.TextAppearance_Small);
ForegroundColorSpan mColorSpan = null; // set in ctor
private CharSequence formatMessage(MessageItem msgItem, String body,
String subject, Pattern highlight,
String contentType) {
SpannableStringBuilder buf = new SpannableStringBuilder();
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(mContext);
boolean enableEmojis = prefs.getBoolean(MessagingPreferenceActivity.ENABLE_EMOJIS, false);
boolean hasSubject = !TextUtils.isEmpty(subject);
SmileyParser parser = SmileyParser.getInstance();
if (hasSubject) {
CharSequence smilizedSubject = parser.addSmileySpans(subject);
if (enableEmojis) {
EmojiParser emojiParser = EmojiParser.getInstance();
smilizedSubject = emojiParser.addEmojiSpans(smilizedSubject);
}
// Can't use the normal getString() with extra arguments for string replacement
// because it doesn't preserve the SpannableText returned by addSmileySpans.
// We have to manually replace the %s with our text.
buf.append(TextUtils.replace(mContext.getResources().getString(R.string.inline_subject),
new String[] { "%s" }, new CharSequence[] { smilizedSubject }));
}
if (!TextUtils.isEmpty(body)) {
// Converts html to spannable if ContentType is "text/html".
if (contentType != null && ContentType.TEXT_HTML.equals(contentType)) {
buf.append("\n");
buf.append(Html.fromHtml(body));
} else {
if (hasSubject) {
buf.append(" - ");
}
CharSequence smileyBody = parser.addSmileySpans(body);
if (enableEmojis) {
EmojiParser emojiParser = EmojiParser.getInstance();
smileyBody = emojiParser.addEmojiSpans(smileyBody);
}
buf.append(smileyBody);
}
}
if (highlight != null) {
Matcher m = highlight.matcher(buf.toString());
while (m.find()) {
buf.setSpan(new StyleSpan(Typeface.BOLD), m.start(), m.end(), 0);
}
}
return buf;
}
private void drawPlaybackButton(MessageItem msgItem) {
switch (msgItem.mAttachmentType) {
case WorkingMessage.SLIDESHOW:
case WorkingMessage.AUDIO:
case WorkingMessage.VIDEO:
// Show the 'Play' button and bind message info on it.
mSlideShowButton.setTag(msgItem);
// Set call-back for the 'Play' button.
mSlideShowButton.setOnClickListener(this);
mSlideShowButton.setVisibility(View.VISIBLE);
setLongClickable(true);
// When we show the mSlideShowButton, this list item's onItemClickListener doesn't
// get called. (It gets set in ComposeMessageActivity:
// mMsgListView.setOnItemClickListener) Here we explicitly set the item's
// onClickListener. It allows the item to respond to embedded html links and at the
// same time, allows the slide show play button to work.
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onMessageListItemClick();
}
});
break;
default:
mSlideShowButton.setVisibility(View.GONE);
break;
}
}
// OnClick Listener for the playback button
@Override
public void onClick(View v) {
sendMessage(mMessageItem, MSG_LIST_PLAY);
}
private void sendMessage(MessageItem messageItem, int message) {
if (mHandler != null) {
Message msg = Message.obtain(mHandler, message);
msg.obj = messageItem;
msg.sendToTarget(); // See ComposeMessageActivity.mMessageListItemHandler.handleMessage
}
}
public void onMessageListItemClick() {
// If the message is a failed one, clicking it should reload it in the compose view,
// regardless of whether it has links in it
if (mMessageItem != null &&
mMessageItem.isOutgoingMessage() &&
mMessageItem.isFailedMessage() ) {
// Assuming the current message is a failed one, reload it into the compose view so
// the user can resend it.
sendMessage(mMessageItem, MSG_LIST_EDIT);
return;
}
// Check for links. If none, do nothing; if 1, open it; if >1, ask user to pick one
final URLSpan[] spans = mBodyTextView.getUrls();
if (spans.length == 0) {
sendMessage(mMessageItem, MSG_LIST_DETAILS); // show the message details dialog
} else if (spans.length == 1) {
spans[0].onClick(mBodyTextView);
} else {
ArrayAdapter<URLSpan> adapter =
new ArrayAdapter<URLSpan>(mContext, android.R.layout.select_dialog_item, spans) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
try {
URLSpan span = getItem(position);
String url = span.getURL();
Uri uri = Uri.parse(url);
TextView tv = (TextView) v;
Drawable d = mContext.getPackageManager().getActivityIcon(
new Intent(Intent.ACTION_VIEW, uri));
if (d != null) {
d.setBounds(0, 0, d.getIntrinsicHeight(), d.getIntrinsicHeight());
tv.setCompoundDrawablePadding(10);
tv.setCompoundDrawables(d, null, null, null);
}
final String telPrefix = "tel:";
if (url.startsWith(telPrefix)) {
if ((mDefaultCountryIso == null) || mDefaultCountryIso.isEmpty()) {
url = url.substring(telPrefix.length());
}
else {
url = PhoneNumberUtils.formatNumber(
url.substring(telPrefix.length()), mDefaultCountryIso);
}
}
tv.setText(url);
} catch (android.content.pm.PackageManager.NameNotFoundException ex) {
// it's ok if we're unable to set the drawable for this view - the user
// can still use it
}
return v;
}
};
AlertDialog.Builder b = new AlertDialog.Builder(mContext);
DialogInterface.OnClickListener click = new DialogInterface.OnClickListener() {
@Override
public final void onClick(DialogInterface dialog, int which) {
if (which >= 0) {
spans[which].onClick(mBodyTextView);
}
dialog.dismiss();
}
};
b.setTitle(R.string.select_link_title);
b.setCancelable(true);
b.setAdapter(adapter, click);
b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public final void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
b.show();
}
}
private void setOnClickListener(final MessageItem msgItem) {
switch(msgItem.mAttachmentType) {
case WorkingMessage.IMAGE:
case WorkingMessage.VIDEO:
mImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
sendMessage(msgItem, MSG_LIST_PLAY);
}
});
mImageView.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return v.showContextMenu();
}
});
break;
default:
mImageView.setOnClickListener(null);
break;
}
}
private void drawRightStatusIndicator(MessageItem msgItem) {
// Locked icon
if (msgItem.mLocked) {
mLockedIndicator.setImageResource(R.drawable.ic_lock_message_sms);
mLockedIndicator.setVisibility(View.VISIBLE);
} else {
mLockedIndicator.setVisibility(View.GONE);
}
// Delivery icon - we can show a failed icon for both sms and mms, but for an actual
// delivery, we only show the icon for sms. We don't have the information here in mms to
// know whether the message has been delivered. For mms, msgItem.mDeliveryStatus set
// to MessageItem.DeliveryStatus.RECEIVED simply means the setting requesting a
// delivery report was turned on when the message was sent. Yes, it's confusing!
if ((msgItem.isOutgoingMessage() && msgItem.isFailedMessage()) ||
msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.FAILED) {
mDeliveredIndicator.setImageResource(R.drawable.ic_list_alert_sms_failed);
mDeliveredIndicator.setVisibility(View.VISIBLE);
} else if (msgItem.isSms() &&
msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.RECEIVED) {
mDeliveredIndicator.setImageResource(R.drawable.ic_sms_mms_delivered);
mDeliveredIndicator.setVisibility(View.VISIBLE);
} else {
mDeliveredIndicator.setVisibility(View.GONE);
}
// Message details icon - this icon is shown both for sms and mms messages. For mms,
// we show the icon if the read report or delivery report setting was set when the
// message was sent. Showing the icon tells the user there's more information
// by selecting the "View report" menu.
if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.INFO || msgItem.mReadReport
|| (msgItem.isMms() &&
msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.RECEIVED)) {
mDetailsIndicator.setImageResource(R.drawable.ic_sms_mms_details);
mDetailsIndicator.setVisibility(View.VISIBLE);
} else {
mDetailsIndicator.setVisibility(View.GONE);
}
}
@Override
public void setImageRegionFit(String fit) {
// TODO Auto-generated method stub
}
@Override
public void setImageVisibility(boolean visible) {
// TODO Auto-generated method stub
}
@Override
public void setText(String name, String text) {
// TODO Auto-generated method stub
}
@Override
public void setTextVisibility(boolean visible) {
// TODO Auto-generated method stub
}
@Override
public void setVideo(String name, Uri uri) {
}
@Override
public void setVideoThumbnail(String name, Bitmap bitmap) {
showMmsView(true);
try {
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(VISIBLE);
} catch (java.lang.OutOfMemoryError e) {
Log.e(TAG, "setVideo: out of memory: ", e);
}
}
@Override
public void setVideoVisibility(boolean visible) {
// TODO Auto-generated method stub
}
@Override
public void stopAudio() {
// TODO Auto-generated method stub
}
@Override
public void stopVideo() {
// TODO Auto-generated method stub
}
@Override
public void reset() {
}
@Override
public void setVisibility(boolean visible) {
// TODO Auto-generated method stub
}
@Override
public void pauseAudio() {
// TODO Auto-generated method stub
}
@Override
public void pauseVideo() {
// TODO Auto-generated method stub
}
@Override
public void seekAudio(int seekTo) {
// TODO Auto-generated method stub
}
@Override
public void seekVideo(int seekTo) {
// TODO Auto-generated method stub
}
}