SmsMmsMessage.java :  » Widget » messages-widget » de » heimlich » gut » Android Open Source

Android Open Source » Widget » messages widget 
messages widget » de » heimlich » gut » SmsMmsMessage.java
package de.heimlich.gut;

import java.io.ByteArrayInputStream;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.telephony.PhoneNumberUtils;
import android.text.format.DateUtils;

public class SmsMmsMessage {
  private static final String PREFIX = "net.everythingandroid.smspopup.";
  private static final String EXTRAS_FROM_ADDRESS = PREFIX + "EXTRAS_FROM_ADDRESS";
  private static final String EXTRAS_MESSAGE_BODY = PREFIX + "EXTRAS_MESSAGE_BODY";
  private static final String EXTRAS_TIMESTAMP = PREFIX + "EXTRAS_TIMESTAMP";
  private static final String EXTRAS_UNREAD_COUNT = PREFIX + "EXTRAS_UNREAD_COUNT";
  private static final String EXTRAS_THREAD_ID = PREFIX + "EXTRAS_THREAD_ID";
  private static final String EXTRAS_CONTACT_ID = PREFIX + "EXTRAS_CONTACT_ID";
  private static final String EXTRAS_CONTACT_NAME = PREFIX + "EXTRAS_CONTACT_NAME";
  private static final String EXTRAS_CONTACT_PHOTO = PREFIX + "EXTRAS_CONTACT_PHOTO";
  private static final String EXTRAS_MESSAGE_TYPE = PREFIX + "EXTRAS_MESSAGE_TYPE";
  private static final String EXTRAS_MESSAGE_ID = PREFIX + "EXTRAS_MESSAGE_ID";
  public static final String EXTRAS_NOTIFY = PREFIX + "EXTRAS_NOTIFY";
  public static final String EXTRAS_REMINDER_COUNT = PREFIX + "EXTRAS_REMINDER_COUNT";
  public static final String EXTRAS_REPLYING = PREFIX + "EXTRAS_REPLYING";
  public static final String EXTRAS_QUICKREPLY = PREFIX + "EXTRAS_QUICKREPLY";

  public static final int MESSAGE_TYPE_SMS = 0;
  public static final int MESSAGE_TYPE_MMS = 1;

  private Context context;

  private String fromAddress = null;
  private String messageBody = null;
  private long timestamp = 0;
  private int unreadCount = 0;
  private long threadId = 0;
  private String contactId = null;
  private String contactName = null;
  private byte[] contactPhoto = null;
  private int messageType = 0;
  private boolean notify = true;
  private int reminderCount = 0;
  private long messageId = 0;

  /**
   * Construct SmsMmsMessage with minimal information - this is useful for when
   * a raw SMS comes in which just contains address, body and timestamp.  We
   * must then look in the database for the rest of the information
   */
  public SmsMmsMessage(Context _context, String _fromAddress, String _messageBody,
      long _timestamp, int _messageType) {
    context = _context;
    fromAddress = _fromAddress;
    messageBody = _messageBody;
    timestamp = _timestamp;
    messageType = _messageType;

    contactId = SmsPopupUtils.getPersonIdFromPhoneNumber(context, fromAddress);
    contactName = SmsPopupUtils.getPersonName(context, contactId, fromAddress);
    contactPhoto = SmsPopupUtils.getPersonPhoto(context, contactId);

    unreadCount = SmsPopupUtils.getUnreadMessagesCount(context, timestamp);
    threadId = SmsPopupUtils.getThreadIdFromAddress(context, fromAddress);

    setMessageId();

    if (contactName == null) {
      contactName = context.getString(android.R.string.unknownName);
    }
  }

  /**
   * Construct SmsMmsMessage for getMmsDetails() - info fetched from the MMS
   * database table
   */
  public SmsMmsMessage(Context _context, String _fromAddress, String _messageBody,
      long _timestamp, long _threadId, int _unreadCount, int _messageType) {
    context = _context;
    fromAddress = _fromAddress;
    messageBody = _messageBody;
    timestamp = _timestamp;
    messageType = _messageType;

    // TODO: I think contactId can come the MMS table, this would save
    // this database lookup
    contactId = SmsPopupUtils.getPersonIdFromPhoneNumber(context, fromAddress);

    contactName = SmsPopupUtils.getPersonName(context, contactId, fromAddress);
    contactPhoto = SmsPopupUtils.getPersonPhoto(context, contactId);

    unreadCount = _unreadCount;
    threadId = _threadId;

    setMessageId();

    if (contactName == null) {
      contactName = context.getString(android.R.string.unknownName);
    }
  }

  /**
   * Construct SmsMmsMessage for getSmsDetails() - info fetched from the SMS
   * database table
   */
  public SmsMmsMessage(Context _context, String _fromAddress, String _contactId,
      String _messageBody, long _timestamp, long _threadId,
      int _unreadCount, long _messageId, int _messageType) {
    context = _context;
    fromAddress = _fromAddress;
    messageBody = _messageBody;
    timestamp = _timestamp;
    messageType = _messageType;
    contactId = _contactId;

    if ("0".equals(contactId))
      contactId = null;

    contactName = SmsPopupUtils.getPersonName(context, contactId, fromAddress);
    contactPhoto = SmsPopupUtils.getPersonPhoto(context, contactId);

    unreadCount = _unreadCount;
    threadId = _threadId;

    messageId = _messageId;

    if (contactName == null) {
      contactName = context.getString(android.R.string.unknownName);
    }
  }

  /**
   * Construct SmsMmsMessage from an extras bundle
   */
  public SmsMmsMessage(Context _context, Bundle b) {
    context = _context;
    fromAddress = b.getString(EXTRAS_FROM_ADDRESS);
    messageBody = b.getString(EXTRAS_MESSAGE_BODY);
    timestamp = b.getLong(EXTRAS_TIMESTAMP);
    contactId = b.getString(EXTRAS_CONTACT_ID);
    contactName = b.getString(EXTRAS_CONTACT_NAME);
    contactPhoto = b.getByteArray(EXTRAS_CONTACT_PHOTO);
    unreadCount = b.getInt(EXTRAS_UNREAD_COUNT, 1);
    threadId = b.getLong(EXTRAS_THREAD_ID, 0);
    messageType = b.getInt(EXTRAS_MESSAGE_TYPE, MESSAGE_TYPE_SMS);
    notify = b.getBoolean(EXTRAS_NOTIFY, false);
    reminderCount = b.getInt(EXTRAS_REMINDER_COUNT, 0);
    messageId = b.getLong(EXTRAS_MESSAGE_ID, 0);
  }

  /**
   * Construct SmsMmsMessage by specifying all data, only used for testing the
   * notification from the preferences screen
   */
  public SmsMmsMessage(Context _context, String _fromAddress, String _messageBody,
      long _timestamp, String _contactId, String _contactName, byte[] _contactPhoto,
      int _unreadCount, long _threadId, int _messageType) {
    context = _context;
    fromAddress = _fromAddress;
    messageBody = _messageBody;
    timestamp = _timestamp;
    contactId = _contactId;
    contactName = _contactName;
    contactPhoto = _contactPhoto;
    unreadCount = _unreadCount;
    threadId = _threadId;
    messageType = _messageType;
  }

  /**
   * Convert all SmsMmsMessage data to an extras bundle to send via an intent
   */
  public Bundle toBundle() {
    Bundle b = new Bundle();
    b.putString(EXTRAS_FROM_ADDRESS, fromAddress);
    b.putString(EXTRAS_MESSAGE_BODY, messageBody);
    b.putLong(EXTRAS_TIMESTAMP, timestamp);
    b.putString(EXTRAS_CONTACT_ID, contactId);
    b.putString(EXTRAS_CONTACT_NAME, contactName);
    b.putByteArray(EXTRAS_CONTACT_PHOTO, contactPhoto);
    b.putInt(EXTRAS_UNREAD_COUNT, unreadCount);
    b.putLong(EXTRAS_THREAD_ID, threadId);
    b.putInt(EXTRAS_MESSAGE_TYPE, messageType);
    b.putBoolean(EXTRAS_NOTIFY, notify);
    b.putInt(EXTRAS_REMINDER_COUNT, reminderCount);
    b.putLong(EXTRAS_MESSAGE_ID, messageId);
    return b;
  }

  public Bitmap getContactPhoto() {
    if (contactPhoto == null)
      return null;
    return BitmapFactory.decodeStream(new ByteArrayInputStream(contactPhoto));
  }

  public Intent getPopupIntent() {
    Intent popup = new Intent(context, SmsPopupActivity.class);
    popup.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    popup.putExtras(toBundle());
    return popup;
  }

  public Intent getReplyIntent() {
    return SmsPopupUtils.getSmsToIntentFromThreadId(context, threadId);
  }

  public void setThreadRead() {
    SmsPopupUtils.setThreadRead(context, threadId);
  }

  public void setMessageRead() {
    setMessageId();
    SmsPopupUtils.setMessageRead(context, messageId, messageType);
  }

  public int getUnreadCount() {
    return unreadCount;
  }

  public long getTimestamp() {
    return timestamp;
  }

  public CharSequence getFormattedTimestamp() {
    /*
     * No need for my own format function now, the 1.5 SDK has this built in
     * (this will detect the system settings and return the correct format)
     */
    // return SMSPopupUtils.formatTimestamp(context, timestamp);
    return DateUtils.formatDateTime(context, timestamp, DateUtils.FORMAT_SHOW_TIME);
  }

  public String getContactName() {
    if (contactName == null) {
      contactName = context.getString(android.R.string.unknownName);
    }
    return contactName;
  }

  public String getMessageBody() {
    if (messageBody == null) {
      messageBody = "";
    }
    return messageBody;
  }

  public long getThreadId() {
    return threadId;
  }

  public int getMessageType() {
    return messageType;
  }

  public boolean getNotify() {
    return notify;
  }

  public int getReminderCount() {
    return reminderCount;
  }

  public void updateReminderCount(int count) {
    reminderCount = count;
  }

  public void incrementReminderCount() {
    reminderCount++;
  }

  public void delete() {
    SmsPopupUtils.deleteMessage(context, getMessageId(), threadId, messageType);
  }

  public void setMessageId() {
    messageId = SmsPopupUtils.findMessageId(context, threadId, timestamp, messageType);
  }

  public long getMessageId() {
    if (messageId == 0) {
      setMessageId();
    }
    return messageId;
  }

  public String getContactId() {
    return contactId;
  }

  //  public boolean equals(SmsMmsMessage compareMessage) {
  //    boolean equals = false;
  //    if (PhoneNumberUtils.compare(this.fromAddress, compareMessage.fromAddress) &&
  //        this.compareTimeStamp(compareMessage.timestamp) &&
  //        this.messageType == compareMessage.messageType) {
  //      equals = true;
  //    }
  //    return equals;
  //  }

  /**
   * Check if this message is sufficiently the same as the provided parameters
   */
  public boolean equals(String fromAddress, long timestamp, long timestamp_provider, String body) {
    boolean equals = false;

    if (PhoneNumberUtils.compare(this.fromAddress, fromAddress) &&
        this.compareTimeStamp(timestamp, timestamp_provider) &&
        this.compareBody(body)) {
      equals = true;
    }
    return equals;
  }

  //  private boolean compareTimeStamp(long compareTimestamp) {
  //    return compareTimeStamp(compareTimestamp, 0);
  //  }

  /*
   * Compares the timestamps of a message, this is super hacky because the way
   * which builds of Android store SMS timestamps changed in the cupcake branch -
   * pre-cupcake it stored the timestamp provided by the telecom provider;
   * post-cupcake it stored the system timestamp.
   * Unfortunately this means we need to use 2 different ways to determine if
   * the received message timestamp is sufficiently equal to the database timestamp :(
   */
  private boolean compareTimeStamp(long compareTimestamp, long providerTimestamp) {
    final int MESSAGE_COMPARE_TIME_BUFFER = 2000;
    //    final int buildVersion = Integer.valueOf(Build.VERSION.INCREMENTAL);

    /*
     * On March 28th, 2009 - these are the latest builds that I could find:
     * 128600 TMI-RC9 (Tmobile EU)
     * 126986 PLAT-RC33 (Tmobile US)
     * 129975 Emulator (from Android 1.1 SDK r1)
     * Hopefully anything later will have the updated SMS code that uses the system
     * timestamp rather than the SMS timestamp
     */
    //    final int LATEST_BUILD = 129975;
    //    boolean PRE_CUPCAKE = false;
    //    if (buildVersion <= LATEST_BUILD) {
    //      PRE_CUPCAKE = true;
    //    }

    Log.v("DB timestamp = " + timestamp);
    Log.v("Provider timestamp = " + providerTimestamp);
    Log.v("System timestamp = " + compareTimestamp);

    /*
     * If pre-cupcake we can just do a direct comparison as the Mms app stores the
     * timestamp from the telecom provider (in the sms pdu)
     */
    //    if (PRE_CUPCAKE) {
    //      Log.v("Build is pre-cupcake ("+buildVersion+"), doing direct SMS timestamp comparison");
    //      Log.v("DB timestamp = " + timestamp);
    //      Log.v("Intent timestamp = " + providerTimestamp);
    if (timestamp == providerTimestamp) {
      Log.v("SMS Compare: compareTimestamp() - intent timestamp = provider timestamp");
      return true;
    } //else {
    //        return false;
    //      }
    //    }

    /*
     * If post-cupcake, the system app stores a system timestamp - the only problem is
     * we have no way of knowing the exact time the system app used.  So what
     * we'll do is compare against our own system timestamp and add a buffer in.
     * This is an awful way of doing this, but I don't see any other way around it :(
     */
    //    Log.v("Build is post-cupcake ("+buildVersion+"), doing approx. SMS timestamp comparison");
    //    Log.v("DB timestamp = " + timestamp);
    //    Log.v("Intent timestamp = " + compareTimestamp);

    if (timestamp < (compareTimestamp + MESSAGE_COMPARE_TIME_BUFFER)
        && timestamp > (compareTimestamp - MESSAGE_COMPARE_TIME_BUFFER)) {
      Log.v("SMS Compare: compareTimestamp() - timestamp is approx. the same");
      return true;
    }
    Log.v("SMS Compare: compareTimestamp() - return false");
    return false;
  }

  /*
   * Compare message body
   */
  private boolean compareBody(String compareBody) {
    if (compareBody != null) {
      if (messageBody.length() != compareBody.length()) {
        Log.v("SMS Compare: compareBody() - length is different");
        return false;
      }

      if (messageBody.equals(compareBody)) {
        Log.v("SMS Compare: compareBody() - messageBody is the same");
        return true;
      }
    }
    Log.v("SMS Compare: compareBody() - return false");
    return false;
  }

  public boolean replyToMessage(String quickreply) {
//    SmsMessageSender sender =
//      new SmsMessageSender(context, new String[] {fromAddress}, quickreply, threadId);
//    return sender.sendMessage();
    return false;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.