package org.xbmc.android.util;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.preference.PreferenceManager;
import android.provider.Contacts;
import android.provider.Contacts.PeopleColumns;
import android.provider.Contacts.PhotosColumns;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.telephony.gsm.SmsMessage;
import android.text.TextUtils;
/**
* TODO Once we move to 1.6+, waste the deprecated code.
*/
@SuppressWarnings("deprecation")
public class SmsPopupUtils {
// Content URIs for SMS app, these may change in future SDK
public static final Uri MMS_SMS_CONTENT_URI = Uri.parse("content://mms-sms/");
public static final Uri THREAD_ID_CONTENT_URI = Uri.withAppendedPath(MMS_SMS_CONTENT_URI, "threadID");
public static final Uri CONVERSATION_CONTENT_URI = Uri.withAppendedPath(MMS_SMS_CONTENT_URI, "conversations");
public static final Uri SMS_CONTENT_URI = Uri.parse("content://sms");
public static final Uri SMS_INBOX_CONTENT_URI = Uri.withAppendedPath(SMS_CONTENT_URI, "inbox");
public static final Uri MMS_CONTENT_URI = Uri.parse("content://mms");
public static final Uri MMS_INBOX_CONTENT_URI = Uri.withAppendedPath(MMS_CONTENT_URI, "inbox");
public static final String SMS_ID = "_id";
public static final String SMS_TO_URI = "smsto:/";
public static final String SMS_MIME_TYPE = "vnd.android-dir/mms-sms";
public static final int READ_THREAD = 1;
public static final int MESSAGE_TYPE_SMS = 1;
public static final int MESSAGE_TYPE_MMS = 2;
private static final String AUTHOR_CONTACT_INFO = "Adam K <adam@everythingandroid.net>";
/**
* Looks up a contacts display name by contact id - if not found, the
* address (phone number) will be formatted and returned instead.
*/
public static String getPersonName(Context context, String id, String address) {
if (id == null) {
if (address != null) {
// Log.v("Contact not found, formatting number");
return PhoneNumberUtils.formatNumber(address);
} else {
return null;
}
}
Cursor cursor = context.getContentResolver().query(Uri.withAppendedPath(Contacts.People.CONTENT_URI, id),
new String[] { PeopleColumns.DISPLAY_NAME }, null, null, null);
if (cursor != null) {
try {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
String name = cursor.getString(0);
// Log.v("Contact Display Name: " + name);
return name;
}
} finally {
cursor.close();
}
}
if (address != null) {
// Log.v("Contact not found, formatting number");
return PhoneNumberUtils.formatNumber(address);
}
return null;
}
/**
* Looks up a contacts id, given their address (phone number in this case).
* Returns null if not found
*/
public static String getPersonIdFromPhoneNumber(Context context, String address) {
if (address == null)
return null;
Cursor cursor = context.getContentResolver().query(
Uri.withAppendedPath(Contacts.Phones.CONTENT_FILTER_URL, address),
new String[] { Contacts.Phones.PERSON_ID }, null, null, null);
if (cursor != null) {
try {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
Long id = Long.valueOf(cursor.getLong(0));
// Log.v("Found person: " + id);
return (String.valueOf(id));
}
} finally {
cursor.close();
}
}
return null;
}
/**
* Looks up a contats photo by their contact id, returns a byte array that
* represents their photo (or null if not found)
*/
public static byte[] getPersonPhoto(Context context, String id) {
if (id == null)
return null;
if ("0".equals(id))
return null;
byte photo[] = null;
// TODO: switch to API method:
// Contacts.People.loadContactPhoto(arg0, arg1, arg2, arg3)
Cursor cursor = context.getContentResolver().query(Uri.withAppendedPath(Contacts.Photos.CONTENT_URI, id),
new String[] { PhotosColumns.DATA }, null, null, null);
if (cursor != null) {
try {
if (cursor.getCount() > 0) {
cursor.moveToFirst();
photo = cursor.getBlob(0);
if (photo != null) {
return photo;
}
}
} finally {
cursor.close();
}
}
return photo;
}
/**
* Tries to locate the message thread id given the address (phone or email)
* of the message sender
*/
public static long getThreadIdFromAddress(Context context, String address) {
if (address == null)
return 0;
String THREAD_RECIPIENT_QUERY = "recipient";
Uri.Builder uriBuilder = THREAD_ID_CONTENT_URI.buildUpon();
uriBuilder.appendQueryParameter(THREAD_RECIPIENT_QUERY, address);
long threadId = 0;
Cursor cursor = context.getContentResolver().query(uriBuilder.build(), new String[] { SMS_ID }, null, null,
null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
threadId = cursor.getLong(0);
}
} finally {
cursor.close();
}
}
return threadId;
}
/**
* Marks a specific message as read
*/
public static void setMessageRead(Context context, long messageId, int messageType) {
// SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(context);
// boolean markRead = myPrefs.getBoolean(
// context.getString(R.string.pref_markread_key),
// Boolean.valueOf(context.getString(R.string.pref_markread_default)));
boolean markRead = false;
if (!markRead)
return;
if (messageId > 0) {
ContentValues values = new ContentValues(1);
values.put("read", READ_THREAD);
Uri messageUri;
if (SmsMmsMessage.MESSAGE_TYPE_MMS == messageType) {
messageUri = Uri.withAppendedPath(MMS_CONTENT_URI, String.valueOf(messageId));
} else if (SmsMmsMessage.MESSAGE_TYPE_SMS == messageType) {
messageUri = Uri.withAppendedPath(SMS_CONTENT_URI, String.valueOf(messageId));
} else {
return;
}
// Log.v("messageUri for marking message read: " +
// messageUri.toString());
ContentResolver cr = context.getContentResolver();
// int result = 0;
try {
// result = cr.update(messageUri, values, null, null);
cr.update(messageUri, values, null, null);
} catch (Exception e) {
// Log.v("error marking message read");
}
// Log.v("message id " + messageId + " marked as read, result = " +
// result);
}
}
/**
* Marks a specific message thread as read - all messages in the thread will
* be marked read
*/
public static void setThreadRead(Context context, long threadId) {
//SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(context);
// boolean markRead = myPrefs.getBoolean(
// context.getString(R.string.pref_markread_key),
// Boolean.valueOf(context.getString(R.string.pref_markread_default)));
boolean markRead = false;
if (!markRead)
return;
if (threadId > 0) {
ContentValues values = new ContentValues(1);
values.put("read", READ_THREAD);
ContentResolver cr = context.getContentResolver();
// int result = 0;
try {
// result = cr.update(ContentUris.withAppendedId(CONVERSATION_CONTENT_URI, threadId), values, null, null);
cr.update(ContentUris.withAppendedId(CONVERSATION_CONTENT_URI, threadId), values, null, null);
} catch (Exception e) {
// Log.v("error marking thread read");
}
// Log.v("thread id " + threadId + " marked as read, result = " +
// result);
}
}
/**
* Tries to locate the message id (from the system database), given the
* message thread id, the timestamp of the message and the type of message
* (sms/mms)
*/
public static long findMessageId(Context context, long threadId, long _timestamp, int messageType) {
long id = 0;
long timestamp = _timestamp;
if (threadId > 0) {
// Log.v("Trying to find message ID");
// It seems MMS timestamps are stored in a seconds, whereas SMS
// timestamps are in millis
if (SmsMmsMessage.MESSAGE_TYPE_MMS == messageType) {
timestamp = _timestamp / 1000;
// //Log.v("adjusted timestmap for MMS (" + _timestamp + " -> "
// + timestamp + ")");
}
Cursor cursor = context.getContentResolver().query(
ContentUris.withAppendedId(CONVERSATION_CONTENT_URI, threadId),
new String[] { "_id", "date", "thread_id" },
// "thread_id=" + threadId + " and " + "date=" + timestamp,
"date=" + timestamp, null, "date desc");
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
id = cursor.getLong(0);
// Log.v("Message id found = " + id);
}
} finally {
cursor.close();
}
}
}
return id;
}
/**
* Tries to delete a message from the system database, given the thread id,
* the timestamp of the message and the message type (sms/mms).
*/
public static void deleteMessage(Context context, long messageId, long threadId, int messageType) {
if (messageId > 0) {
// Log.v("id of message to delete is " + messageId);
Uri deleteUri;
if (SmsMmsMessage.MESSAGE_TYPE_MMS == messageType) {
deleteUri = Uri.withAppendedPath(MMS_CONTENT_URI, String.valueOf(messageId));
} else if (SmsMmsMessage.MESSAGE_TYPE_SMS == messageType) {
deleteUri = Uri.withAppendedPath(SMS_CONTENT_URI, String.valueOf(messageId));
} else {
return;
}
int count = context.getContentResolver().delete(deleteUri, null, null);
// Log.v("Messages deleted: " + count);
if (count == 1) {
// TODO: should only set the thread read if there are no more
// unread
// messages
setThreadRead(context, threadId);
}
}
}
/**
*
*/
public static Intent getSmsIntent() {
Intent conversations = new Intent(Intent.ACTION_MAIN);
// conversations.addCategory(Intent.CATEGORY_DEFAULT);
conversations.setType(SMS_MIME_TYPE);
// should I be using FLAG_ACTIVITY_RESET_TASK_IF_NEEDED??
int flags = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP;
conversations.setFlags(flags);
return conversations;
}
/**
*
*/
public static Intent getSmsToIntentFromThreadId(Context context, long threadId) {
Intent popup = new Intent(Intent.ACTION_VIEW);
// should I be using FLAG_ACTIVITY_RESET_TASK_IF_NEEDED??
int flags = Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP;
popup.setFlags(flags);
if (threadId > 0) {
// //Log.v("^^Found threadId (" + threadId +
// "), sending to Sms intent");
popup.setData(Uri.withAppendedPath(THREAD_ID_CONTENT_URI, String.valueOf(threadId)));
} else {
return getSmsIntent();
}
return popup;
}
/**
*
*/
public static void launchEmailToIntent(Context context, String subject, boolean includeDebug) {
Intent msg = new Intent(Intent.ACTION_SEND);
String[] recipients = { AUTHOR_CONTACT_INFO };
String body = "";
if (includeDebug) {
body = "\n\n----------\nSysinfo - " + Build.FINGERPRINT + "\n" + "Model: " + Build.MODEL + "\n\n";
// Array of preference keys to include in email
String[] pref_keys = {
// context.getString(R.string.pref_enabled_key),
// context.getString(R.string.pref_timeout_key),
// context.getString(R.string.pref_privacy_key),
// context.getString(R.string.pref_dimscreen_key),
// context.getString(R.string.pref_markread_key),
// context.getString(R.string.pref_onlyShowOnKeyguard_key),
// context.getString(R.string.pref_show_delete_button_key),
// context.getString(R.string.pref_blur_key),
// context.getString(R.string.pref_notif_enabled_key),
// context.getString(R.string.pref_notif_sound_key),
// context.getString(R.string.pref_vibrate_key),
// context.getString(R.string.pref_vibrate_pattern_key),
// context.getString(R.string.pref_vibrate_pattern_custom_key),
// context.getString(R.string.pref_flashled_key),
// context.getString(R.string.pref_flashled_color_key),
// context.getString(R.string.pref_notif_repeat_key),
// context.getString(R.string.pref_notif_repeat_times_key),
// context.getString(R.string.pref_notif_repeat_interval_key),
};
SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Map<String, ?> m = myPrefs.getAll();
body += subject + " config -\n";
for (int i = 0; i < pref_keys.length; i++) {
try {
body += pref_keys[i] + ": " + String.valueOf(m.get(pref_keys[i])) + "\n";
} catch (NullPointerException e) {
// Nothing to do here
}
}
// Add locale info
body += "locale: " + context.getResources().getConfiguration().locale.getDisplayName() + "\n";
// Add audio info
AudioManager AM = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
String audioMode = "audio_mode: ";
switch (AM.getMode()) {
case AudioManager.MODE_NORMAL:
audioMode += "MODE_NORMAL";
break;
case AudioManager.MODE_IN_CALL:
audioMode += "MODE_IN_CALL";
break;
case AudioManager.MODE_RINGTONE:
audioMode += "MODE_RINGTONE";
break;
default:
audioMode += "MODE is UNKNOWN";
break;
}
body += audioMode + "\n";
String audioRouting = "audio_routing: ";
switch (AM.getRouting(AudioManager.MODE_NORMAL)) {
case AudioManager.ROUTE_SPEAKER:
audioRouting += "ROUTE_SPEAKER";
break;
case AudioManager.ROUTE_BLUETOOTH:
audioRouting += "ROUTE_BLUETOOTH";
break;
case AudioManager.ROUTE_HEADSET:
audioRouting += "ROUTE_HEADSET";
break;
default:
audioRouting += "ROUTE is UNKNOWN";
break;
}
body += audioRouting + "\n";
TelephonyManager TM = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String callState = "call state: ";
switch (TM.getCallState()) {
case TelephonyManager.CALL_STATE_IDLE:
callState += "CALL_STATE_IDLE";
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
callState += "CALL_STATE_OFFHOOK";
break;
case TelephonyManager.CALL_STATE_RINGING:
callState += "CALL_STATE_RINGING";
break;
default:
callState += "CALL_STATE is UNKNOWN";
break;
}
body += callState + "\n";
}
msg.putExtra(Intent.EXTRA_EMAIL, recipients);
msg.putExtra(Intent.EXTRA_SUBJECT, subject);
msg.putExtra(Intent.EXTRA_TEXT, body);
msg.setType("message/rfc822");
context.startActivity(Intent.createChooser(msg, "Send E-mail"));
}
public static int getUnreadMessagesCount(Context context, long timestamp) {
int unreadSms = getUnreadSmsCount(context, timestamp);
int unreadMms = getUnreadMmsCount(context);
return (unreadSms + unreadMms);
}
public static int getUnreadMessagesCount(Context context) {
return getUnreadMessagesCount(context, 0);
// int unreadSms = getUnreadSmsCount(context);
// int unreadMms = getUnreadMmsCount(context);
// return (unreadSms + unreadMms);
}
public static SmsMmsMessage getSmsDetailsById(Context context, int id) {
// public SmsMmsMessage(Context _context, String _fromAddress, String
// _contactId,
// String _messageBody, long _timestamp, long _threadId,
// int _unreadCount, long _messageId, int _messageType)
SmsMmsMessage msg = null;
String SORT_ORDER = "date DESC";
String WHERE_CONDITION = "_id=" + id;
Cursor cursor = context.getContentResolver().query(
SMS_INBOX_CONTENT_URI,
new String[] { SMSConstants.ID, SMSConstants.THREAD_ID, SMSConstants.ADDRESS, SMSConstants.PERSON,
SMSConstants.DATE, SMSConstants.BODY }, WHERE_CONDITION, null, SORT_ORDER);
if (cursor != null && cursor.moveToFirst()) {
try {
long messageId = cursor.getLong(0);
long threadId = cursor.getLong(1);
String address = cursor.getString(2);
long contactId = cursor.getLong(3);
String contactId_string = String.valueOf(contactId);
long timestamp = cursor.getLong(4);
String body = cursor.getString(5);
msg = new SmsMmsMessage(context, address, contactId_string, body, timestamp, threadId, 0, // TODO
// evaluate
// the
// real
// unread
// count.
// currently
// not
// needed
messageId, SmsMmsMessage.MESSAGE_TYPE_SMS);
} finally {
cursor.close();
}
}
return msg;
}
public static int getSmsInboxCount(Context context) {
int count = 0;
Cursor cursor = context.getContentResolver().query(SMS_INBOX_CONTENT_URI, new String[] { SMS_ID }, null, null,
null);
if (cursor != null) {
try {
count = cursor.getCount();
} finally {
cursor.close();
}
}
return count;
}
public static int[] getSmsIdsFromInbox(Context context) {
int[] ids = null;
Cursor cursor = context.getContentResolver().query(SMS_INBOX_CONTENT_URI, new String[] { SMS_ID }, null, null,
null);
if (cursor != null && cursor.moveToFirst()) {
try {
ids = new int[cursor.getCount()];
int i = 0;
do {
ids[i++] = cursor.getInt(0);
} while (cursor.moveToNext());
} finally {
cursor.close();
}
}
return ids;
}
public static SmsMmsMessage getLastSmsFromInbox(Context context) {
return getSmsDetailsById(context, getSmsIdsFromInbox(context)[0]);
}
public static int getUnreadSmsCount(Context context) {
return getUnreadSmsCount(context, 0);
// String SMS_READ_COLUMN = "read";
// String UNREAD_CONDITION = SMS_READ_COLUMN + "=0";
//
// int count = 0;
//
// Cursor cursor = context.getContentResolver().query(
// SMS_INBOX_CONTENT_URI,
// new String[] { SMS_ID },
// UNREAD_CONDITION, null, null);
//
// if (cursor != null) {
// try {
// count = cursor.getCount();
// } finally {
// cursor.close();
// }
// }
// //Log.v("sms unread count = " + count);
// return count;
}
public static int getUnreadSmsCount(Context context, long timestamp) {
String SMS_READ_COLUMN = "read";
String UNREAD_CONDITION = SMS_READ_COLUMN + "=0";
if (timestamp > 0) {
// Log.v("getUnreadSmsCount(), timestamp = " + timestamp);
UNREAD_CONDITION += " and date<" + String.valueOf(timestamp);
}
int count = 0;
Cursor cursor = context.getContentResolver().query(SMS_INBOX_CONTENT_URI, new String[] { SMS_ID },
UNREAD_CONDITION, null, null);
if (cursor != null) {
try {
count = cursor.getCount();
} finally {
cursor.close();
}
}
// We ignored the latest incoming message so add one to the total count
if (timestamp > 0) {
// Log.v("adding 1 to unread, previous count was " + count);
count += 1;
}
// Log.v("sms unread count = " + count);
return count;
}
public static int getUnreadMmsCount(Context context) {
String MMS_READ_COLUMN = "read";
String UNREAD_CONDITION = MMS_READ_COLUMN + "=0";
int count = 0;
Cursor cursor = context.getContentResolver().query(MMS_INBOX_CONTENT_URI, new String[] { SMS_ID },
UNREAD_CONDITION, null, null);
if (cursor != null) {
try {
count = cursor.getCount();
} finally {
cursor.close();
}
}
// Log.v("mms unread count = " + count);
return count;
}
/*
*
*/
public static SmsMmsMessage getSmsDetails(Context context, long ignoreThreadId, boolean unreadOnly) {
String SMS_READ_COLUMN = "read";
String WHERE_CONDITION = unreadOnly ? SMS_READ_COLUMN + " = 0" : null;
String SORT_ORDER = "date DESC";
int count = 0;
// //Log.v(WHERE_CONDITION);
if (ignoreThreadId > 0) {
// //Log.v("Ignoring sms threadId = " + ignoreThreadId);
WHERE_CONDITION += " AND thread_id != " + ignoreThreadId;
}
Cursor cursor = context.getContentResolver().query(SMS_INBOX_CONTENT_URI,
new String[] { "_id", "thread_id", "address", "person", "date", "body" }, WHERE_CONDITION, null,
SORT_ORDER);
if (cursor != null) {
try {
count = cursor.getCount();
if (count > 0) {
cursor.moveToFirst();
// String[] columns = cursor.getColumnNames();
// for (int i=0; i<columns.length; i++) {
// //Log.v("columns " + i + ": " + columns[i] + ": "
// + cursor.getString(i));
// }
long messageId = cursor.getLong(0);
long threadId = cursor.getLong(1);
String address = cursor.getString(2);
long contactId = cursor.getLong(3);
String contactId_string = String.valueOf(contactId);
long timestamp = cursor.getLong(4);
String body = cursor.getString(5);
if (!unreadOnly) {
count = 0;
}
SmsMmsMessage smsMessage = new SmsMmsMessage(context, address, contactId_string, body, timestamp,
threadId, count, messageId, SmsMmsMessage.MESSAGE_TYPE_SMS);
return smsMessage;
}
} finally {
cursor.close();
}
}
return null;
}
public static SmsMmsMessage getSmsDetails(Context context) {
return getSmsDetails(context, 0);
}
public static SmsMmsMessage getSmsDetails(Context context, boolean unreadOnly) {
return getSmsDetails(context, 0, unreadOnly);
}
public static SmsMmsMessage getSmsDetails(Context context, long ignoreThreadId) {
return getSmsDetails(context, ignoreThreadId, true);
}
/*
*
*/
public static SmsMmsMessage getMmsDetails(Context context, long ignoreThreadId) {
String MMS_READ_COLUMN = "read";
String UNREAD_CONDITION = MMS_READ_COLUMN + " = 0";
String SORT_ORDER = "date DESC";
int count = 0;
if (ignoreThreadId > 0) {
// //Log.v("Ignoring mms threadId = " + ignoreThreadId);
UNREAD_CONDITION += " AND thread_id != " + ignoreThreadId;
}
Cursor cursor = context.getContentResolver().query(MMS_INBOX_CONTENT_URI,
// new String[] { "m_id", "\"from\"", "sub", "d_tm", "thread_id" },
new String[] { "_id", "thread_id", "date", "sub", "sub_cs" }, UNREAD_CONDITION, null, SORT_ORDER);
if (cursor != null) {
try {
count = cursor.getCount();
if (count > 0) {
cursor.moveToFirst();
// String[] columns = cursor.getColumnNames();
// for (int i=0; i<columns.length; i++) {
// //Log.v("columns " + i + ": " + columns[i] + ": "
// + cursor.getString(i));
// }
String address = getMmsFrom(context, cursor.getLong(0));
long threadId = cursor.getLong(1);
long timestamp = cursor.getLong(2) * 1000;
String subject = cursor.getString(3);
SmsMmsMessage mmsMessage = new SmsMmsMessage(context, address, subject, timestamp, threadId, count,
SmsMmsMessage.MESSAGE_TYPE_MMS);
return mmsMessage;
}
} finally {
cursor.close();
}
}
return null;
}
public static SmsMmsMessage getMmsDetails(Context context) {
return getMmsDetails(context, 0);
}
public static String getMmsFrom(Context context, long message_id) {
String message_id_string = String.valueOf(message_id);
Uri.Builder builder = MMS_CONTENT_URI.buildUpon();
builder.appendPath(message_id_string).appendPath("addr");
Cursor cursor = context.getContentResolver().query(builder.build(),
// new String[] { "contact_id", "address", "charset", "type" },
new String[] { "address", "contact_id", "charset", "type" },
// "type="+ PduHeaders.FROM,
"type=137",
// null,
null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
// String[] columns = cursor.getColumnNames();
// for (int i = 0; i < columns.length; i++) {
// //Log.v("columns " + i + ": " + columns[i] + ": "
// + cursor.getString(i));
// }
String address = cursor.getString(0);
return getDisplayName(context, address).trim();
// Needed for i18n strings??
// if (!TextUtils.isEmpty(from)) {
// byte[] bytes = PduPersister.getBytes(from);
// int charset = cursor.getInt(1);
// return new EncodedStringValue(charset,
// bytes).getString();
// }
}
} finally {
cursor.close();
}
}
return context.getString(android.R.string.unknownName);
}
public static final Pattern NAME_ADDR_EMAIL_PATTERN = Pattern
.compile("\\s*(\"[^\"]*\"|[^<>\"]+)\\s*<([^<>]+)>\\s*");
public static final Pattern QUOTED_STRING_PATTERN = Pattern.compile("\\s*\"([^\"]*)\"\\s*");
private static String getEmailDisplayName(String displayString) {
Matcher match = QUOTED_STRING_PATTERN.matcher(displayString);
if (match.matches()) {
return match.group(1);
}
return displayString;
}
private static String getDisplayName(Context context, String email) {
Matcher match = NAME_ADDR_EMAIL_PATTERN.matcher(email);
if (match.matches()) {
// email has display name, return that
return getEmailDisplayName(match.group(1));
}
// otherwise let's check the contacts list for a user with this email
Cursor cursor = context.getContentResolver().query(Contacts.ContactMethods.CONTENT_EMAIL_URI,
new String[] { Contacts.ContactMethods.NAME }, Contacts.ContactMethods.DATA + " = \'" + email + "\'",
null, null);
if (cursor != null) {
try {
int columnIndex = cursor.getColumnIndexOrThrow(Contacts.ContactMethods.NAME);
while (cursor.moveToNext()) {
String name = cursor.getString(columnIndex);
if (!TextUtils.isEmpty(name)) {
return name;
}
}
} finally {
cursor.close();
}
}
return email;
}
/*
* Get the most recent unread message, returning in a SmsMmsMessage which is
* suitable for updating the notification. Optional param is the message
* object: we can pull out the thread id of this message in the case the
* user is "replying" to the message and we should ignore all messages in
* the thread when working out what to display in the notification bar (as
* these messages will soon be marked read but we can't be sure when the
* messaging app will actually start).
*/
public static SmsMmsMessage getRecentMessage(Context context, SmsMmsMessage ignoreMessage) {
long ignoreThreadId = 0;
if (ignoreMessage != null) {
ignoreThreadId = ignoreMessage.getThreadId();
}
SmsMmsMessage smsMessage = getSmsDetails(context, ignoreThreadId);
SmsMmsMessage mmsMessage = getMmsDetails(context, ignoreThreadId);
if (mmsMessage == null && smsMessage != null) {
return smsMessage;
}
if (mmsMessage != null && smsMessage == null) {
return mmsMessage;
}
if (mmsMessage != null && smsMessage != null) {
if (mmsMessage.getTimestamp() < smsMessage.getTimestamp()) {
return mmsMessage;
}
return smsMessage;
}
return null;
}
public static SmsMmsMessage getRecentMessage(Context context) {
return getRecentMessage(context, null);
}
/**
* Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
* {@link #DATA_SMS_RECEIVED_ACTION} intent.
*
* @param intent
* the intent to read from
* @return an array of SmsMessages for the PDUs
*/
public static final SmsMessage[] getMessagesFromIntent(Intent intent) {
Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
if (messages == null) {
return null;
}
if (messages.length == 0) {
return null;
}
byte[][] pduObjs = new byte[messages.length][];
for (int i = 0; i < messages.length; i++) {
pduObjs[i] = (byte[]) messages[i];
}
byte[][] pdus = new byte[pduObjs.length][];
int pduCount = pdus.length;
SmsMessage[] msgs = new SmsMessage[pduCount];
for (int i = 0; i < pduCount; i++) {
pdus[i] = pduObjs[i];
msgs[i] = SmsMessage.createFromPdu(pdus[i]);
}
return msgs;
}
/**
* This function will see if the most recent activity was the system
* messaging app so we can suppress the popup as the user is likely already
* viewing messages or composing a new message
*/
public static final boolean inMessagingApp(Context context) {
// TODO: move these to static strings somewhere
final String PACKAGE_NAME = "com.android.mms";
// final String COMPOSE_CLASS_NAME =
// "com.android.mms.ui.ComposeMessageActivity";
final String CONVO_CLASS_NAME = "com.android.mms.ui.ConversationList";
ActivityManager mAM = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> mRunningTaskList = mAM.getRunningTasks(1);
Iterator<RunningTaskInfo> mIterator = mRunningTaskList.iterator();
if (mIterator.hasNext()) {
RunningTaskInfo mRunningTask = mIterator.next();
if (mRunningTask != null) {
ComponentName runningTaskComponent = mRunningTask.baseActivity;
// //Log.v("baseActivity = " +
// mRunningTask.baseActivity.toString());
// //Log.v("topActivity = " +
// mRunningTask.topActivity.toString());
if (PACKAGE_NAME.equals(runningTaskComponent.getPackageName())
&& CONVO_CLASS_NAME.equals(runningTaskComponent.getClassName())) {
// Log.v("User in messaging app - from running task");
return true;
}
}
}
/*
* List<RecentTaskInfo> mActivityList = mAM.getRecentTasks(1, 0);
* Iterator<RecentTaskInfo> mIterator = mActivityList.iterator();
*
* if (mIterator.hasNext()) { RecentTaskInfo mRecentTask =
* (RecentTaskInfo) mIterator.next(); Intent recentTaskIntent =
* mRecentTask.baseIntent;
*
* if (recentTaskIntent != null) { ComponentName recentTaskComponentName
* = recentTaskIntent.getComponent(); if (recentTaskComponentName !=
* null) { String recentTaskClassName =
* recentTaskComponentName.getClassName(); if
* (PACKAGE_NAME.equals(recentTaskComponentName.getPackageName()) &&
* (COMPOSE_CLASS_NAME.equals(recentTaskClassName) ||
* CONVO_CLASS_NAME.equals(recentTaskClassName))) {
* //Log.v("User in messaging app"); return true; } } } }
*/
/*
* These appear to be the 2 main intents that mean the user is using the
* messaging app
*
* action "android.intent.action.MAIN" data null class
* "com.android.mms.ui.ConversationList" package "com.android.mms"
*
* action "android.intent.action.VIEW" data
* "content://mms-sms/threadID/3" class
* "com.android.mms.ui.ComposeMessageActivity" package "com.android.mms"
*/
return false;
}
/**
* Enables or disables the main SMS receiver
*/
public static void enableSMSPopup(Context context, boolean enable) {
// PackageManager pm = context.getPackageManager();
// ComponentName cn = new ComponentName(context, SmsReceiver.class);
//
// // Update preference so it reflects in the preference activity
// SharedPreferences myPrefs =
// PreferenceManager.getDefaultSharedPreferences(context);
// SharedPreferences.Editor settings = myPrefs.edit();
// settings.putBoolean(context.getString(R.string.pref_enabled_key),
// enable);
// settings.commit();
//
// if (enable) {
// //Log.v("SMSPopup receiver is enabled");
// pm.setComponentEnabledSetting(cn,
// PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
// PackageManager.DONT_KILL_APP);
//
// // Send a broadcast to disable other SMS Popup apps
// disableOtherSMSPopup(context);
//
// } else {
// //Log.v("SMSPopup receiver is disabled");
// pm.setComponentEnabledSetting(cn,
// PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
// PackageManager.DONT_KILL_APP);
// }
}
public static void disableOtherSMSPopup(Context context) {
// Send a broadcast to disable SMS Popup Pro
// Intent i = new Intent(ExternalEventReceiver.ACTION_SMSPOPUP_DISABLE);
// i.setClassName("net.everythingandroid.smspopuppro",
// "net.everythingandroid.smspopuppro.ExternalEventReceiver");
// context.sendBroadcast(i);
}
}