private void updateBackground() {
   int backgroundId;
   if (mConversation.isChecked()) {
     backgroundId = R.drawable.list_selected_holo_light;
   } else if (mConversation.hasUnreadMessages()) {
     backgroundId = R.drawable.conversation_item_background_unread;
   } else {
     backgroundId = R.drawable.conversation_item_background_read;
   }
   Drawable background = mContext.getResources().getDrawable(backgroundId);
   setBackground(background);
 }
  private void updateAvatarView() {
    Drawable avatarDrawable;
    if (mConversation.getRecipients().size() == 1) {

      Contact contact = mConversation.getRecipients().get(0);

      // to be continued
      avatarDrawable = contact.getAvatar(mContext, sDefaultContactImage);

      if (contact.existsInDatabase()) { // 010查看联系人是否存在于通讯录
        mAvatarView.assignContactUri(contact.getUri());
      } else {
        mAvatarView.assignContactFromPhone(contact.getNumber(), true);
      }
    } else {
      // TODO get a multiple recipients asset (or do something else)
      avatarDrawable = sDefaultContactImage;
      mAvatarView.assignContactUri(null);
    }
    mAvatarView.setImageDrawable(avatarDrawable);
    mAvatarView.setVisibility(View.VISIBLE);
  }
  public boolean sendMessage(long token) throws MmsException {
    if (LogTag.DEBUG_SEND) {
      Log.v(TAG, "sendMessage token: " + token);
    }
    if (mMessageText == null) {
      // Don't try to send an empty message, and destination should be just
      // one.
      throw new MmsException("Null message body or have multiple destinations.");
    }
    SmsManager smsManager = SmsManager.getDefault();
    ArrayList<String> messages = null;
    if ((MmsConfig.getEmailGateway() != null)
        && (Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))) {
      String msgText;
      msgText = mDest + " " + mMessageText;
      mDest = MmsConfig.getEmailGateway();
      messages = smsManager.divideMessage(msgText);
    } else {
      messages = smsManager.divideMessage(mMessageText);
      // remove spaces and dashes from destination number
      // (e.g. "801 555 1212" -> "8015551212")
      // (e.g. "+8211-123-4567" -> "+82111234567")
      mDest = PhoneNumberUtils.stripSeparators(mDest);
      mDest = Conversation.verifySingleRecipient(mContext, mThreadId, mDest);
    }
    int messageCount = messages.size();

    if (messageCount == 0) {
      // Don't try to send an empty message.
      throw new MmsException(
          "SmsMessageSender.sendMessage: divideMessage returned "
              + "empty messages. Original message is \""
              + mMessageText
              + "\"");
    }

    boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX, 0);
    if (!moved) {
      throw new MmsException(
          "SmsMessageSender.sendMessage: couldn't move message " + "to outbox: " + mUri);
    }
    if (LogTag.DEBUG_SEND) {
      Log.v(
          TAG,
          "sendMessage mDest: " + mDest + " mRequestDeliveryReport: " + mRequestDeliveryReport);
    }

    ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(messageCount);
    ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);
    for (int i = 0; i < messageCount; i++) {
      if (mRequestDeliveryReport && (i == (messageCount - 1))) {
        // TODO: Fix: It should not be necessary to
        // specify the class in this intent.  Doing that
        // unnecessarily limits customizability.
        deliveryIntents.add(
            PendingIntent.getBroadcast(
                mContext,
                0,
                new Intent(
                    MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION,
                    mUri,
                    mContext,
                    MessageStatusReceiver.class),
                0));
      } else {
        deliveryIntents.add(null);
      }
      Intent intent =
          new Intent(SmsReceiverService.MESSAGE_SENT_ACTION, mUri, mContext, SmsReceiver.class);

      int requestCode = 0;
      if (i == messageCount - 1) {
        // Changing the requestCode so that a different pending intent
        // is created for the last fragment with
        // EXTRA_MESSAGE_SENT_SEND_NEXT set to true.
        requestCode = 1;
        intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);
      }
      if (LogTag.DEBUG_SEND) {
        Log.v(TAG, "sendMessage sendIntent: " + intent);
      }
      sentIntents.add(PendingIntent.getBroadcast(mContext, requestCode, intent, 0));
    }
    try {
      if (MultiSimConfig.isMultiSimEnabled()) {
        MSimSmsManager smsManagerMSim = MSimSmsManager.getDefault();
        smsManagerMSim.sendMultipartTextMessage(
            mDest,
            mServiceCenter,
            messages,
            sentIntents,
            deliveryIntents,
            ComposeMessageActivity.subSelected);
        Log.v(TAG, "뇰랙죄崗엥친駕가가가가!mSubscription: " + mSubscription);

      } else {
        smsManager.sendMultipartTextMessage(
            mDest, mServiceCenter, messages, sentIntents, deliveryIntents);
      }
    } catch (Exception ex) {
      Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
      throw new MmsException(
          "SmsMessageSender.sendMessage: caught " + ex + " from MSimSmsManager.sendTextMessage()");
    }
    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
      log(
          "sendMessage: address="
              + mDest
              + ", threadId="
              + mThreadId
              + ", uri="
              + mUri
              + ", msgs.count="
              + messageCount);
    }
    return false;
  }
 public void toggle() {
   mConversation.setIsChecked(!mConversation.isChecked());
 }
 public boolean isChecked() {
   return mConversation.isChecked();
 }
 public void setChecked(boolean checked) {
   mConversation.setIsChecked(checked);
   updateBackground();
 }
  public final void bind(Context context, final Conversation conversation) {
    // if (DEBUG) Log.v(TAG, "bind()");

    mConversation = conversation;

    updateBackground();

    LayoutParams attachmentLayout = (LayoutParams) mAttachmentView.getLayoutParams();
    boolean hasError = conversation.hasError();
    // When there's an error icon, the attachment icon is left of the error
    // icon.
    // When there is not an error icon, the attachment icon is left of the
    // date text.
    // As far as I know, there's no way to specify that relationship in xml.
    if (hasError) {
      attachmentLayout.addRule(RelativeLayout.LEFT_OF, R.id.error);
    } else {
      attachmentLayout.addRule(RelativeLayout.LEFT_OF, R.id.date);
    }

    boolean hasAttachment = conversation.hasAttachment();
    mAttachmentView.setVisibility(hasAttachment ? VISIBLE : GONE);

    // Date
    mDateView.setText(MessageUtils.formatTimeStampString(context, conversation.getDate()));

    // mConversation.ensureThreadId();
    if (mConversation != null) {
      if (conversation.getSimType(mConversation.getThreadId()) == 0)
        mType.setText(context.getString(R.string.card_one));
      else if (conversation.getSimType(mConversation.getThreadId()) == 1)
        mType.setText(context.getString(R.string.card_two));
      else if (conversation.getSimType(mConversation.getThreadId()) == 2) mType.setText("");

    } else {
      mType.setText("");
    }
    // From.
    mFromView.setText(formatMessage());

    // Register for updates in changes of any of the contacts in this
    // conversation.
    ContactList contacts = conversation.getRecipients();

    if (Log.isLoggable(LogTag.CONTACT, Log.DEBUG)) {
      Log.v(TAG, "bind: contacts.addListeners " + this);
    }
    Contact.addListener(this);

    // Subject
    SmileyParser parser = SmileyParser.getInstance();
    mSubjectView.setText(parser.addSmileySpans(conversation.getSnippet()));
    LayoutParams subjectLayout = (LayoutParams) mSubjectView.getLayoutParams();
    // We have to make the subject left of whatever optional items are shown
    // on the right.
    subjectLayout.addRule(
        RelativeLayout.LEFT_OF,
        hasAttachment ? R.id.attachment : (hasError ? R.id.error : R.id.date));

    // Transmission error indicator.
    mErrorIndicator.setVisibility(hasError ? VISIBLE : GONE);

    updateAvatarView();
  }
  private CharSequence formatMessage() {
    final int color = android.R.styleable.Theme_textColorSecondary;
    String from = mConversation.getRecipients().formatNames(", ");

    Log.v("formatMessage", "formatMessage: " + from);

    SpannableStringBuilder buf = new SpannableStringBuilder(from);
    try {
      if (mConversation.hasUnreadMessages()
          && mConversation.getUnReadMessageCount(mConversation.getThreadId()) != 0) {
        if (mConversation.getUnReadMessageCount(mConversation.getThreadId()) != 0) {
          buf.setSpan(STYLE_BOLD, 0, buf.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

          buf.append("  "); // 010 make it on
          buf.append(
              mContext
                  .getResources()
                  .getString(
                      R.string.message_count_format,
                      mConversation.getUnReadMessageCount(mConversation.getThreadId())));

          buf.append(" /"); // 010未读"/"已读之间的分隔
        } else {
          mConversation.setHasUnreadMessages(false);
        }
      }

    } catch (Exception e) {

      e.printStackTrace();
    }

    if (mConversation.getMessageCount() >= 1) {
      int before = buf.length();

      buf.append(
          mContext
              .getResources()
              .getString(R.string.message_count_format, mConversation.getMessageCount()));

      buf.setSpan(
          new ForegroundColorSpan(mContext.getResources().getColor(R.color.message_count_color)),
          before,
          buf.length(),
          Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    }
    if (mConversation.hasDraft()) {
      buf.append(mContext.getResources().getString(R.string.draft_separator));
      int before = buf.length();
      int size;
      buf.append(mContext.getResources().getString(R.string.has_draft));
      size = android.R.style.TextAppearance_Small;
      buf.setSpan(
          new TextAppearanceSpan(mContext, size, color),
          before,
          buf.length(),
          Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
      buf.setSpan(
          new ForegroundColorSpan(mContext.getResources().getColor(R.drawable.text_color_red)),
          before,
          buf.length(),
          Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
    }

    // Unread messages are shown in bold

    return buf;
  }