First cut at group messaging refactor.

This commit is contained in:
Moxie Marlinspike
2013-04-25 18:59:49 -07:00
parent 83e260436b
commit dd0aecc811
29 changed files with 365 additions and 262 deletions

View File

@@ -57,6 +57,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.DraftDatabase;
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.AttachmentManager;
import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
import org.thoughtcrime.securesms.mms.MediaTooLargeException;
@@ -93,14 +94,15 @@ import ws.com.google.android.mms.MmsException;
*/
public class ConversationActivity extends PassphraseRequiredSherlockFragmentActivity
implements ConversationFragment.ConversationFragmentListener
{
{
public static final String RECIPIENTS_EXTRA = "recipients";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String MASTER_SECRET_EXTRA = "master_secret";
public static final String DRAFT_TEXT_EXTRA = "draft_text";
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
public static final String RECIPIENTS_EXTRA = "recipients";
public static final String THREAD_ID_EXTRA = "thread_id";
public static final String MASTER_SECRET_EXTRA = "master_secret";
public static final String DRAFT_TEXT_EXTRA = "draft_text";
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
private static final int PICK_CONTACT = 1;
private static final int PICK_IMAGE = 2;
@@ -120,6 +122,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
private Recipients recipients;
private long threadId;
private int distributionType;
private boolean isEncryptedConversation;
private boolean isMmsEnabled = true;
@@ -182,7 +185,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
switch (reqCode) {
case PICK_CONTACT:
Recipients recipients = (Recipients)data.getParcelableExtra("recipients");
Recipients recipients = data.getParcelableExtra("recipients");
if (recipients != null)
recipientsPanel.addRecipients(recipients);
@@ -220,6 +223,13 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
inflater.inflate(R.menu.conversation_callable, menu);
} else if (isGroupConversation()) {
inflater.inflate(R.menu.conversation_group_options, menu);
if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST)
{
menu.findItem(R.id.menu_distribution_broadcast).setChecked(true);
} else {
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
}
}
inflater.inflate(R.menu.conversation, menu);
@@ -231,15 +241,17 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_call: handleDial(getRecipients().getPrimaryRecipient()); return true;
case R.id.menu_delete_thread: handleDeleteThread(); return true;
case R.id.menu_add_attachment: handleAddAttachment(); return true;
case R.id.menu_start_secure_session: handleStartSecureSession(); return true;
case R.id.menu_abort_session: handleAbortSecureSession(); return true;
case R.id.menu_verify_recipient: handleVerifyRecipient(); return true;
case R.id.menu_verify_session: handleVerifySession(); return true;
case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
case android.R.id.home: handleReturnToConversationList(); return true;
case R.id.menu_call: handleDial(getRecipients().getPrimaryRecipient()); return true;
case R.id.menu_delete_thread: handleDeleteThread(); return true;
case R.id.menu_add_attachment: handleAddAttachment(); return true;
case R.id.menu_start_secure_session: handleStartSecureSession(); return true;
case R.id.menu_abort_session: handleAbortSecureSession(); return true;
case R.id.menu_verify_recipient: handleVerifyRecipient(); return true;
case R.id.menu_verify_session: handleVerifySession(); return true;
case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true;
case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true;
case android.R.id.home: handleReturnToConversationList(); return true;
}
return false;
@@ -327,6 +339,38 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
builder.show();
}
private void handleDistributionBroadcastEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.BROADCAST;
item.setChecked(true);
if (threadId != -1) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.BROADCAST);
return null;
}
}.execute();
}
}
private void handleDistributionConversationEnabled(MenuItem item) {
distributionType = ThreadDatabase.DistributionTypes.CONVERSATION;
item.setChecked(true);
if (threadId != -1) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.CONVERSATION);
return null;
}
}.execute();
}
}
private void handleDial(Recipient recipient) {
if (recipient == null) return;
@@ -494,12 +538,14 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
private void initializeResources() {
recipientsPanel = (RecipientsPanel)findViewById(R.id.recipients);
recipients = getIntent().getParcelableExtra("recipients");
threadId = getIntent().getLongExtra("thread_id", -1);
recipients = getIntent().getParcelableExtra(RECIPIENTS_EXTRA);
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA,
ThreadDatabase.DistributionTypes.DEFAULT);
addContactButton = (ImageButton)findViewById(R.id.contacts_button);
sendButton = (ImageButton)findViewById(R.id.send_button);
composeText = (EditText)findViewById(R.id.embedded_text_editor);
masterSecret = (MasterSecret)getIntent().getParcelableExtra("master_secret");
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
charactersLeft = (TextView)findViewById(R.id.space_left);
attachmentAdapter = new AttachmentTypeSelectorAdapter(this);
@@ -749,10 +795,11 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
if (attachmentManager.isAttachmentPresent()) {
allocatedThreadId = MessageSender.sendMms(ConversationActivity.this, masterSecret, recipients,
threadId, attachmentManager.getSlideDeck(), body,
forcePlaintext);
} else if (recipients.isEmailRecipient()) {
distributionType, forcePlaintext);
} else if (recipients.isEmailRecipient() || !recipients.isSingleRecipient()) {
allocatedThreadId = MessageSender.sendMms(ConversationActivity.this, masterSecret, recipients,
threadId, new SlideDeck(), body, forcePlaintext);
threadId, new SlideDeck(), body, distributionType,
forcePlaintext);
} else {
OutgoingTextMessage message;
@@ -790,7 +837,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
Intent intent = new Intent(ConversationActivity.this, ContactSelectionActivity.class);
startActivityForResult(intent, PICK_CONTACT);
}
};
}
private class AttachmentTypeListener implements DialogInterface.OnClickListener {
@Override
@@ -823,7 +870,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
}
return false;
}
};
}
private class OnTextChangedListener implements TextWatcher {
@Override

View File

@@ -123,7 +123,7 @@ public class ConversationFragment extends SherlockListFragment
}
private void handleDisplayDetails(MessageRecord message) {
String sender = message.getRecipients().getPrimaryRecipient().getNumber();
String sender = message.getIndividualRecipient().getNumber();
String transport = message.isMms() ? "mms" : "sms";
long dateReceived = message.getDateReceived();
long dateSent = message.getDateSent();
@@ -175,8 +175,7 @@ public class ConversationFragment extends SherlockListFragment
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new ConversationLoader(getActivity(), threadId,
(recipients != null && !recipients.isSingleRecipient()));
return new ConversationLoader(getActivity(), threadId);
}
@Override

View File

@@ -193,19 +193,19 @@ public class ConversationItem extends LinearLayout {
}
private void setGroupMessageStatus(MessageRecord messageRecord) {
GroupData groupData = messageRecord.getGroupData();
if (groupData != null) {
String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize);
if (groupData.groupSendFailedCount != 0)
status = status + String.format(", Failed (%d/%d)", groupData.groupSendFailedCount, groupData.groupSize);
this.groupStatusText.setText(status);
this.groupStatusText.setVisibility(View.VISIBLE);
} else {
// GroupData groupData = messageRecord.getGroupData();
//
// if (groupData != null) {
// String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize);
//
// if (groupData.groupSendFailedCount != 0)
// status = status + String.format(", Failed (%d/%d)", groupData.groupSendFailedCount, groupData.groupSize);
//
// this.groupStatusText.setText(status);
// this.groupStatusText.setVisibility(View.VISIBLE);
// } else {
this.groupStatusText.setVisibility(View.GONE);
}
// }
}
private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) {
@@ -298,7 +298,7 @@ public class ConversationItem extends LinearLayout {
private void handleKeyExchangeClicked() {
Intent intent = new Intent(context, ReceiveKeyActivity.class);
intent.putExtra("recipient", messageRecord.getRecipients().getPrimaryRecipient());
intent.putExtra("recipient", messageRecord.getIndividualRecipient());
intent.putExtra("body", messageRecord.getBody());
intent.putExtra("thread_id", messageRecord.getThreadId());
intent.putExtra("master_secret", masterSecret);

View File

@@ -10,6 +10,7 @@ import android.view.WindowManager;
import org.thoughtcrime.securesms.ApplicationExportManager.ApplicationExportListener;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.KeyCachingService;
@@ -67,27 +68,30 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
int defaultType = ThreadDatabase.DistributionTypes.DEFAULT;
switch (item.getItemId()) {
case R.id.menu_new_message: createConversation(-1, null); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_export: handleExportDatabase(); return true;
case R.id.menu_import: handleImportDatabase(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_new_message: createConversation(-1, null, defaultType); return true;
case R.id.menu_settings: handleDisplaySettings(); return true;
case R.id.menu_export: handleExportDatabase(); return true;
case R.id.menu_import: handleImportDatabase(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
}
return false;
}
@Override
public void onCreateConversation(long threadId, Recipients recipients) {
createConversation(threadId, recipients);
public void onCreateConversation(long threadId, Recipients recipients, int distributionType) {
createConversation(threadId, recipients, distributionType);
}
private void createConversation(long threadId, Recipients recipients) {
private void createConversation(long threadId, Recipients recipients, int distributionType) {
Intent intent = new Intent(this, ConversationActivity.class);
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
startActivity(intent);
}

View File

@@ -96,7 +96,8 @@ public class ConversationListFragment extends SherlockListFragment
public void onListItemClick(ListView l, View v, int position, long id) {
if (v instanceof ConversationListItem) {
ConversationListItem headerView = (ConversationListItem) v;
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients());
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients(),
headerView.getDistributionType());
}
}
@@ -197,8 +198,8 @@ public class ConversationListFragment extends SherlockListFragment
((ConversationListAdapter)this.getListAdapter()).selectAllThreads();
}
private void handleCreateConversation(long threadId, Recipients recipients) {
listener.onCreateConversation(threadId, recipients);
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) {
listener.onCreateConversation(threadId, recipients, distributionType);
}
@Override
@@ -217,7 +218,7 @@ public class ConversationListFragment extends SherlockListFragment
}
public interface ConversationSelectedListener {
public void onCreateConversation(long threadId, Recipients recipients);
public void onCreateConversation(long threadId, Recipients recipients, int distributionType);
}
@Override

View File

@@ -71,6 +71,7 @@ public class ConversationListItem extends RelativeLayout
private QuickContactBadge contactPhotoBadge;
private final Handler handler = new Handler();
private int distributionType;
public ConversationListItem(Context context) {
super(context);
@@ -97,11 +98,12 @@ public class ConversationListItem extends RelativeLayout
}
public void set(ThreadRecord thread, Set<Long> selectedThreads, boolean batchMode) {
this.selectedThreads = selectedThreads;
this.recipients = thread.getRecipients();
this.threadId = thread.getThreadId();
this.count = thread.getCount();
this.read = thread.isRead();
this.selectedThreads = selectedThreads;
this.recipients = thread.getRecipients();
this.threadId = thread.getThreadId();
this.count = thread.getCount();
this.read = thread.isRead();
this.distributionType = thread.getDistributionType();
this.recipients.addListener(this);
this.fromView.setText(formatFrom(recipients, count, read));
@@ -201,6 +203,10 @@ public class ConversationListItem extends RelativeLayout
return threadId;
}
public int getDistributionType() {
return distributionType;
}
private class CheckedChangedListener implements CompoundButton.OnCheckedChangeListener {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

View File

@@ -43,6 +43,7 @@ import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.MultimediaMessagePdu;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
/**
* A work queue for processing a number of encryption operations.
@@ -186,7 +187,7 @@ public class DecryptingQueue {
plaintextPduBytes = cipher.decryptMessage(ciphertextPduBytes);
}
MultimediaMessagePdu plaintextPdu = (MultimediaMessagePdu)new PduParser(plaintextPduBytes).parse();
RetrieveConf plaintextPdu = (RetrieveConf)new PduParser(plaintextPduBytes).parse();
Log.w("DecryptingQueue", "Successfully decrypted MMS!");
database.insertSecureDecryptedMessageInbox(masterSecret, plaintextPdu, threadId);
database.delete(messageId);

View File

@@ -158,9 +158,36 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
}
}
private long getThreadIdForHeaders(PduHeaders headers) throws RecipientFormattingException {
private long getThreadIdFor(RetrieveConf retrieved) throws RecipientFormattingException {
try {
EncodedStringValue encodedString = headers.getEncodedStringValue(PduHeaders.FROM);
Set<String> group = new HashSet<String>();
EncodedStringValue encodedFrom = retrieved.getFrom();
group.add(new String(encodedFrom.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
EncodedStringValue[] encodedCcList = retrieved.getCc();
if (encodedCcList != null) {
for (EncodedStringValue encodedCc : encodedCcList) {
group.add(new String(encodedCc.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
}
}
StringBuilder sb = new StringBuilder();
for (String recipient : group) {
sb.append(recipient);
sb.append(",");
}
Recipients recipients = RecipientFactory.getRecipientsFromString(context, sb.toString(), false);
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
} catch (UnsupportedEncodingException e) {
throw new AssertionError(e);
}
}
private long getThreadIdFor(NotificationInd notification) throws RecipientFormattingException {
try {
EncodedStringValue encodedString = notification.getFrom();
String fromString = new String(encodedString.getTextString(), CharacterSets.MIMENAME_ISO_8859_1);
Recipients recipients = RecipientFactory.getRecipientsFromString(context, fromString, false);
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
@@ -313,13 +340,21 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
}
}
private long insertMessageInbox(MasterSecret masterSecret, MultimediaMessagePdu retrieved,
String contentLocation, long threadId, long mailbox)
private long insertMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
String contentLocation, long threadId, long mailbox)
throws MmsException
{
PduHeaders headers = retrieved.getPduHeaders();
ContentValues contentValues = getContentValuesFromHeader(headers);
if (!Util.isEmpty(retrieved.getCc())) {
try {
threadId = getThreadIdFor(retrieved);
} catch (RecipientFormattingException e) {
Log.w("MmsDatabase", e);
}
}
contentValues.put(MESSAGE_BOX, mailbox);
contentValues.put(THREAD_ID, threadId);
contentValues.put(CONTENT_LOCATION, contentLocation);
@@ -348,7 +383,8 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_REMOTE_BIT);
}
public long insertSecureDecryptedMessageInbox(MasterSecret masterSecret, MultimediaMessagePdu retrieved, long threadId)
public long insertSecureDecryptedMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
long threadId)
throws MmsException
{
return insertMessageInbox(masterSecret, retrieved, "", threadId,
@@ -360,7 +396,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
PduHeaders headers = notification.getPduHeaders();
ContentValues contentValues = getContentValuesFromHeader(headers);
long threadId = getThreadIdForHeaders(headers);
long threadId = getThreadIdFor(notification);
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
Log.w("MmsDatabse", "Message received type: " + headers.getOctet(PduHeaders.MESSAGE_TYPE));
@@ -688,29 +724,12 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
Recipient recipient = getMessageRecipient(id);
MessageRecord.GroupData groupData = null;
SlideDeck slideDeck;
try {
MultimediaMessagePdu pdu = getMediaMessage(id);
slideDeck = getSlideDeck(masterSecret, pdu);
if (cursor.getColumnIndex(MmsSmsDatabase.GROUP_SIZE) != -1) {
int groupSize = pdu.getTo().length;
int groupSent = MmsDatabase.Types.isFailedMessageType(box) ? 0 : groupSize;
int groupSendFailed = groupSize - groupSent;
if (groupSize <= 1) {
groupSize = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.GROUP_SIZE));
groupSent = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.MMS_GROUP_SENT_COUNT));
groupSendFailed = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.MMS_GROUP_SEND_FAILED_COUNT));
}
Log.w("ConversationAdapter", "MMS GroupSize: " + groupSize + " , GroupSent: " + groupSent + " , GroupSendFailed: " + groupSendFailed);
groupData = new MessageRecord.GroupData(groupSize, groupSent, groupSendFailed);
}
} catch (MmsException me) {
Log.w("ConversationAdapter", me);
slideDeck = null;
@@ -718,7 +737,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
return new MediaMmsMessageRecord(context, id, new Recipients(recipient), recipient,
dateSent, dateReceived, threadId,
slideDeck, box, groupData);
slideDeck, box);
}
protected SlideDeck getSlideDeck(MasterSecret masterSecret, MultimediaMessagePdu pdu) {

View File

@@ -31,13 +31,7 @@ import java.util.Set;
public class MmsSmsDatabase extends Database {
public static final String TRANSPORT = "transport_type";
public static final String GROUP_SIZE = "group_size";
public static final String SMS_GROUP_SENT_COUNT = "sms_group_sent_count";
public static final String SMS_GROUP_SEND_FAILED_COUNT = "sms_group_sent_failed_count";
public static final String MMS_GROUP_SENT_COUNT = "mms_group_sent_count";
public static final String MMS_GROUP_SEND_FAILED_COUNT = "mms_group_sent_failed_count";
public static final String TRANSPORT = "transport_type";
public static final String MMS_TRANSPORT = "mms";
public static final String SMS_TRANSPORT = "sms";
@@ -45,53 +39,53 @@ public class MmsSmsDatabase extends Database {
super(context, databaseHelper);
}
public Cursor getCollatedGroupConversation(long threadId) {
String smsCaseSecurity = "CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
"WHEN " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 1 " +
"ELSE 0 END";
String mmsCaseSecurity = "CASE " + MmsDatabase.MESSAGE_BOX + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
"WHEN " + MmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 'secure' " +
"ELSE 'insecure' END";
String mmsGroupSentCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
"WHEN " + MmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
"ELSE 0 END)";
String smsGroupSentCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
"WHEN " + SmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
"ELSE 0 END)";
String mmsGroupSentFailedCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
"WHEN " + MmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
"ELSE 0 END)";
String smsGroupSentFailedCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
"WHEN " + SmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
"ELSE 0 END)";
String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
MmsSmsColumns.THREAD_ID,
SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, SmsDatabase.STATUS,
MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, TRANSPORT,
"COUNT(" + MmsSmsColumns.ID + ") AS " + GROUP_SIZE,
mmsGroupSentCount + " AS " + MMS_GROUP_SENT_COUNT,
mmsGroupSentFailedCount + " AS " + MMS_GROUP_SEND_FAILED_COUNT,
smsGroupSentCount + " AS " + SMS_GROUP_SENT_COUNT,
smsGroupSentFailedCount + " AS " + SMS_GROUP_SEND_FAILED_COUNT,
smsCaseSecurity + " AS sms_collate", mmsCaseSecurity + " AS mms_collate"};
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
String groupBy = MmsSmsColumns.NORMALIZED_DATE_SENT + " / 1000, sms_collate, mms_collate";
Cursor cursor = queryTables(projection, selection, order, groupBy, null);
setNotifyConverationListeners(cursor, threadId);
return cursor;
}
// public Cursor getCollatedGroupConversation(long threadId) {
// String smsCaseSecurity = "CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
// "WHEN " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 1 " +
// "ELSE 0 END";
//
// String mmsCaseSecurity = "CASE " + MmsDatabase.MESSAGE_BOX + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
// "WHEN " + MmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 'secure' " +
// "ELSE 'insecure' END";
//
// String mmsGroupSentCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + MmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
//
// String smsGroupSentCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + SmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String mmsGroupSentFailedCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + MmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String smsGroupSentFailedCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
// "WHEN " + SmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
// "ELSE 0 END)";
//
// String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
// MmsSmsColumns.THREAD_ID,
// SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, SmsDatabase.STATUS,
// MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
// MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, TRANSPORT,
// "COUNT(" + MmsSmsColumns.ID + ") AS " + GROUP_SIZE,
// mmsGroupSentCount + " AS " + MMS_GROUP_SENT_COUNT,
// mmsGroupSentFailedCount + " AS " + MMS_GROUP_SEND_FAILED_COUNT,
// smsGroupSentCount + " AS " + SMS_GROUP_SENT_COUNT,
// smsGroupSentFailedCount + " AS " + SMS_GROUP_SEND_FAILED_COUNT,
// smsCaseSecurity + " AS sms_collate", mmsCaseSecurity + " AS mms_collate"};
//
// String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
// String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
// String groupBy = MmsSmsColumns.NORMALIZED_DATE_SENT + " / 1000, sms_collate, mms_collate";
//
// Cursor cursor = queryTables(projection, selection, order, groupBy, null);
// setNotifyConverationListeners(cursor, threadId);
//
// return cursor;
// }
public Cursor getConversation(long threadId) {
String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,

View File

@@ -27,7 +27,6 @@ import android.util.Log;
import android.util.Pair;
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -405,22 +404,11 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
Recipients recipients = getRecipientsFor(address);
String body = getBody(cursor);
MessageRecord.GroupData groupData = null;
if (cursor.getColumnIndex(MmsSmsDatabase.GROUP_SIZE) != -1) {
int groupSize = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.GROUP_SIZE));
int groupSent = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.SMS_GROUP_SENT_COUNT));
int groupSendFailed = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.SMS_GROUP_SEND_FAILED_COUNT));
Log.w("ConversationAdapter", "GroupSize: " + groupSize + " , GroupSent: " + groupSent + " , GroupSendFailed: " + groupSendFailed);
groupData = new MessageRecord.GroupData(groupSize, groupSent, groupSendFailed);
}
return new SmsMessageRecord(context, messageId, body, recipients,
recipients.getPrimaryRecipient(),
dateSent, dateReceived, type,
threadId, status, groupData);
threadId, status);
}
private Recipients getRecipientsFor(String address) {

View File

@@ -38,18 +38,18 @@ import java.util.Set;
public class ThreadDatabase extends Database {
static final String TABLE_NAME = "thread";
public static final String ID = "_id";
public static final String DATE = "date";
public static final String MESSAGE_COUNT = "message_count";
public static final String RECIPIENT_IDS = "recipient_ids";
public static final String SNIPPET = "snippet";
private static final String SNIPPET_CHARSET = "snippet_cs";
public static final String READ = "read";
private static final String TYPE = "type";
private static final String ERROR = "error";
private static final String HAS_ATTACHMENT = "has_attachment";
public static final String SNIPPET_TYPE = "snippet_type";
static final String TABLE_NAME = "thread";
public static final String ID = "_id";
public static final String DATE = "date";
public static final String MESSAGE_COUNT = "message_count";
public static final String RECIPIENT_IDS = "recipient_ids";
public static final String SNIPPET = "snippet";
private static final String SNIPPET_CHARSET = "snippet_cs";
public static final String READ = "read";
private static final String TYPE = "type";
private static final String ERROR = "error";
private static final String HAS_ATTACHMENT = "has_attachment";
public static final String SNIPPET_TYPE = "snippet_type";
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
DATE + " INTEGER DEFAULT 0, " + MESSAGE_COUNT + " INTEGER DEFAULT 0, " +
@@ -98,7 +98,7 @@ public class ThreadDatabase extends Database {
return sb.toString();
}
private long createThreadForRecipients(String recipients, int recipientCount) {
private long createThreadForRecipients(String recipients, int recipientCount, int distributionType) {
ContentValues contentValues = new ContentValues(4);
long date = System.currentTimeMillis();
@@ -106,7 +106,7 @@ public class ThreadDatabase extends Database {
contentValues.put(RECIPIENT_IDS, recipients);
if (recipientCount > 1)
contentValues.put(TYPE, 1);
contentValues.put(TYPE, distributionType);
contentValues.put(MESSAGE_COUNT, 0);
@@ -216,7 +216,16 @@ public class ThreadDatabase extends Database {
public void setUnread(long threadId) {
ContentValues contentValues = new ContentValues(1);
contentValues.put("read", 0);
contentValues.put(READ, 0);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
notifyConversationListListeners();
}
public void setDistributionType(long threadId, int distributionType) {
ContentValues contentValues = new ContentValues(1);
contentValues.put(TYPE, distributionType);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
@@ -301,6 +310,10 @@ public class ThreadDatabase extends Database {
}
public long getThreadIdFor(Recipients recipients) {
return getThreadIdFor(recipients, 0);
}
public long getThreadIdFor(Recipients recipients, int distributionType) {
long[] recipientIds = getRecipientIds(recipients);
String recipientsList = getRecipientsAsString(recipientIds);
SQLiteDatabase db = databaseHelper.getReadableDatabase();
@@ -314,7 +327,7 @@ public class ThreadDatabase extends Database {
if (cursor != null && cursor.moveToFirst())
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
else
return createThreadForRecipients(recipientsList, recipientIds.length);
return createThreadForRecipients(recipientsList, recipientIds.length, distributionType);
} finally {
if (cursor != null)
cursor.close();
@@ -378,6 +391,12 @@ public class ThreadDatabase extends Database {
return new Reader(cursor, masterSecret);
}
public static class DistributionTypes {
public static final int DEFAULT = 2;
public static final int BROADCAST = 1;
public static final int CONVERSATION = 2;
}
public class Reader {
private final Cursor cursor;
@@ -405,8 +424,10 @@ public class ThreadDatabase extends Database {
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ));
long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE));
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
return new ThreadRecord(context, body, recipients, date, count, read == 1, threadId, type);
return new ThreadRecord(context, body, recipients, date, count,
read == 1, threadId, type, distributionType);
}
private String getPlaintextBody(Cursor cursor) {

View File

@@ -10,21 +10,15 @@ public class ConversationLoader extends CursorLoader {
private final Context context;
private final long threadId;
private final boolean isGroupConversation;
public ConversationLoader(Context context, long threadId, boolean isGroupConversation) {
public ConversationLoader(Context context, long threadId) {
super(context);
this.context = context.getApplicationContext();
this.threadId = threadId;
this.isGroupConversation = isGroupConversation;
this.context = context.getApplicationContext();
this.threadId = threadId;
}
@Override
public Cursor loadInBackground() {
if (!isGroupConversation) {
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
} else {
return DatabaseFactory.getMmsSmsDatabase(context).getCollatedGroupConversation(threadId);
}
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
}
}

View File

@@ -41,13 +41,11 @@ public class MediaMmsMessageRecord extends MessageRecord {
public MediaMmsMessageRecord(Context context, long id, Recipients recipients,
Recipient individualRecipient, long dateSent, long dateReceived,
long threadId, SlideDeck slideDeck, long mailbox,
GroupData groupData)
long threadId, SlideDeck slideDeck, long mailbox)
{
super(context, id, getBodyFromSlidesIfAvailable(slideDeck), recipients,
individualRecipient, dateSent, dateReceived,
threadId, DELIVERY_STATUS_NONE, mailbox,
groupData);
threadId, DELIVERY_STATUS_NONE, mailbox);
this.context = context.getApplicationContext();
this.slideDeck = slideDeck;

View File

@@ -45,19 +45,17 @@ public abstract class MessageRecord extends DisplayRecord {
private final Recipient individualRecipient;
private final long id;
private final int deliveryStatus;
private final GroupData groupData;
public MessageRecord(Context context, long id, String body, Recipients recipients,
Recipient individualRecipient,
long dateSent, long dateReceived,
long threadId, int deliveryStatus,
long type, GroupData groupData)
long type)
{
super(context, body, recipients, dateSent, dateReceived, threadId, type);
this.id = id;
this.individualRecipient = individualRecipient;
this.deliveryStatus = deliveryStatus;
this.groupData = groupData;
}
public abstract boolean isMms();
@@ -73,7 +71,7 @@ public abstract class MessageRecord extends DisplayRecord {
}
public boolean isPending() {
return MmsSmsColumns.Types.isPendingMessageType(type) || isGroupDeliveryPending();
return MmsSmsColumns.Types.isPendingMessageType(type);
}
public boolean isSecure() {
@@ -109,18 +107,6 @@ public abstract class MessageRecord extends DisplayRecord {
return individualRecipient;
}
public GroupData getGroupData() {
return this.groupData;
}
protected boolean isGroupDeliveryPending() {
if (this.groupData != null) {
return groupData.groupSentCount + groupData.groupSendFailedCount < groupData.groupSize;
}
return false;
}
protected SpannableString emphasisAdded(String sequence) {
SpannableString spannable = new SpannableString(sequence);
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(android.R.color.darker_gray)), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

View File

@@ -47,7 +47,7 @@ public class NotificationMmsMessageRecord extends MessageRecord {
int status, byte[] transactionId, long mailbox)
{
super(context, id, "", recipients, individualRecipient, dateSent, dateReceived,
threadId, DELIVERY_STATUS_NONE, mailbox, null);
threadId, DELIVERY_STATUS_NONE, mailbox);
this.contentLocation = contentLocation;
this.messageSize = messageSize;

View File

@@ -40,10 +40,10 @@ public class SmsMessageRecord extends MessageRecord {
Recipient individualRecipient,
long dateSent, long dateReceived,
long type, long threadId,
int status, GroupData groupData)
int status)
{
super(context, id, body, recipients, individualRecipient, dateSent, dateReceived,
threadId, getGenericDeliveryStatus(status), type, groupData);
threadId, getGenericDeliveryStatus(status), type);
}
public long getType() {

View File

@@ -37,14 +37,17 @@ public class ThreadRecord extends DisplayRecord {
private final Context context;
private final long count;
private final boolean read;
private final int distributionType;
public ThreadRecord(Context context, String body, Recipients recipients, long date,
long count, boolean read, long threadId, long type)
long count, boolean read, long threadId, long snippetType,
int distributionType)
{
super(context, body, recipients, date, date, threadId, type);
this.context = context.getApplicationContext();
this.count = count;
this.read = read;
super(context, body, recipients, date, date, threadId, snippetType);
this.context = context.getApplicationContext();
this.count = count;
this.read = read;
this.distributionType = distributionType;
}
@Override
@@ -86,4 +89,7 @@ public class ThreadRecord extends DisplayRecord {
return getDateReceived();
}
public int getDistributionType() {
return distributionType;
}
}

View File

@@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import java.io.IOException;
@@ -137,13 +138,13 @@ public class MessageNotifier {
NotificationState notificationState,
boolean signal)
{
List<NotificationItem> notifications = notificationState.getNotifications();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Recipients recipients = notifications.get(0).getRecipients();
List<NotificationItem>notifications = notificationState.getNotifications();
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Recipient recipient = notifications.get(0).getIndividualRecipient();
builder.setSmallIcon(R.drawable.icon_notification);
builder.setLargeIcon(recipients.getPrimaryRecipient().getContactPhoto());
builder.setContentTitle(recipients.getPrimaryRecipient().toShortString());
builder.setLargeIcon(recipient.getContactPhoto());
builder.setContentTitle(recipient.toShortString());
builder.setContentText(notifications.get(0).getText());
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
@@ -179,7 +180,7 @@ public class MessageNotifier {
builder.setContentTitle(String.format(context.getString(R.string.MessageNotifier_d_new_messages),
notificationState.getMessageCount()));
builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s),
notifications.get(0).getRecipientName()));
notifications.get(0).getIndividualRecipientName()));
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, RoutingActivity.class), 0));
InboxStyle style = new InboxStyle();
@@ -246,6 +247,7 @@ public class MessageNotifier {
else reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor, masterSecret);
while ((record = reader.getNext()) != null) {
Recipient recipient = record.getIndividualRecipient();
Recipients recipients = record.getRecipients();
long threadId = record.getThreadId();
SpannableString body = record.getDisplayBody();
@@ -257,7 +259,7 @@ public class MessageNotifier {
body.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
notificationState.addNotification(new NotificationItem(recipients, threadId, body, image));
notificationState.addNotification(new NotificationItem(recipient, recipients, threadId, body, image));
}
return notificationState;

View File

@@ -7,29 +7,34 @@ import android.net.Uri;
import android.text.SpannableStringBuilder;
import org.thoughtcrime.securesms.RoutingActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.Util;
public class NotificationItem {
private final Recipients recipients;
private final Recipient individualRecipient;
private final long threadId;
private final CharSequence text;
private final Uri image;
public NotificationItem(Recipients recipients, long threadId, CharSequence text, Uri image) {
this.recipients = recipients;
this.text = text;
this.image = image;
this.threadId = threadId;
public NotificationItem(Recipient individualRecipient, Recipients recipients, long threadId,
CharSequence text, Uri image)
{
this.individualRecipient = individualRecipient;
this.recipients = recipients;
this.text = text;
this.image = image;
this.threadId = threadId;
}
public Recipients getRecipients() {
return recipients;
public Recipient getIndividualRecipient() {
return individualRecipient;
}
public String getRecipientName() {
return recipients.getPrimaryRecipient().toShortString();
public String getIndividualRecipientName() {
return individualRecipient.toShortString();
}
public CharSequence getText() {
@@ -54,7 +59,7 @@ public class NotificationItem {
public CharSequence getTickerText() {
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(Util.getBoldedString(getRecipientName()));
builder.append(Util.getBoldedString(getIndividualRecipientName()));
builder.append(": ");
builder.append(getText());
@@ -65,7 +70,7 @@ public class NotificationItem {
Intent intent = new Intent(context, RoutingActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (recipients.getPrimaryRecipient() != null) {
if (recipients != null) {
intent.putExtra("recipients", recipients);
intent.putExtra("thread_id", threadId);
}

View File

@@ -33,7 +33,7 @@ public class NotificationState {
}
public Bitmap getContactPhoto() {
return notifications.get(0).getRecipients().getPrimaryRecipient().getContactPhoto();
return notifications.get(0).getIndividualRecipient().getContactPhoto();
}
}

View File

@@ -91,29 +91,29 @@ public class Recipients implements Parcelable {
return false;
}
public Recipients getSecureSessionRecipients(Context context) {
List<Recipient> secureRecipients = new LinkedList<Recipient>();
for (Recipient recipient : recipients) {
if (KeyUtil.isSessionFor(context, recipient)) {
secureRecipients.add(recipient);
}
}
return new Recipients(secureRecipients);
}
public Recipients getInsecureSessionRecipients(Context context) {
List<Recipient> insecureRecipients = new LinkedList<Recipient>();
for (Recipient recipient : recipients) {
if (!KeyUtil.isSessionFor(context, recipient)) {
insecureRecipients.add(recipient);
}
}
return new Recipients(insecureRecipients);
}
// public Recipients getSecureSessionRecipients(Context context) {
// List<Recipient> secureRecipients = new LinkedList<Recipient>();
//
// for (Recipient recipient : recipients) {
// if (KeyUtil.isSessionFor(context, recipient)) {
// secureRecipients.add(recipient);
// }
// }
//
// return new Recipients(secureRecipients);
// }
//
// public Recipients getInsecureSessionRecipients(Context context) {
// List<Recipient> insecureRecipients = new LinkedList<Recipient>();
//
// for (Recipient recipient : recipients) {
// if (!KeyUtil.isSessionFor(context, recipient)) {
// insecureRecipients.add(recipient);
// }
// }
//
// return new Recipients(insecureRecipients);
// }
public boolean isEmpty() {
return this.recipients.isEmpty();

View File

@@ -22,9 +22,9 @@ import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.mms.TextSlide;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.service.SendReceiveService;
@@ -39,11 +39,12 @@ import ws.com.google.android.mms.pdu.SendReq;
public class MessageSender {
public static long sendMms(Context context, MasterSecret masterSecret, Recipients recipients,
long threadId, SlideDeck slideDeck, String message, boolean forcePlaintext)
long threadId, SlideDeck slideDeck, String message, int distributionType,
boolean forcePlaintext)
throws MmsException
{
if (threadId == -1)
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients, distributionType);
if (message.trim().length() > 0)
slideDeck.addSlide(new TextSlide(context, message));
@@ -55,17 +56,19 @@ public class MessageSender {
sendRequest.setBody(body);
sendRequest.setContentType(ContentType.MULTIPART_MIXED.getBytes());
Recipients secureRecipients = recipients.getSecureSessionRecipients(context);
Recipients insecureRecipients = recipients.getInsecureSessionRecipients(context);
// Recipients secureRecipients = recipients.getSecureSessionRecipients(context);
// Recipients insecureRecipients = recipients.getInsecureSessionRecipients(context);
for (Recipient secureRecipient : secureRecipients.getRecipientsList()) {
sendMms(context, new Recipients(secureRecipient), masterSecret,
sendRequest, threadId, !forcePlaintext);
}
// for (Recipient secureRecipient : secureRecipients.getRecipientsList()) {
// sendMms(context, new Recipients(secureRecipient), masterSecret,
// sendRequest, threadId, !forcePlaintext);
// }
//
// if (!insecureRecipients.isEmpty()) {
// sendMms(context, insecureRecipients, masterSecret, sendRequest, threadId, false);
// }
if (!insecureRecipients.isEmpty()) {
sendMms(context, insecureRecipients, masterSecret, sendRequest, threadId, false);
}
sendMms(context, recipients, masterSecret, sendRequest, threadId, distributionType, false);
return threadId;
}
@@ -93,13 +96,19 @@ public class MessageSender {
}
private static void sendMms(Context context, Recipients recipients, MasterSecret masterSecret,
SendReq sendRequest, long threadId, boolean secure)
SendReq sendRequest, long threadId, int distributionType, boolean secure)
throws MmsException
{
String[] recipientsArray = recipients.toNumberStringArray(true);
EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(recipientsArray);
sendRequest.setTo(encodedNumbers);
if (recipients.isSingleRecipient()) {
sendRequest.setTo(encodedNumbers);
} else if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST) {
sendRequest.setBcc(encodedNumbers);
} else if (distributionType == ThreadDatabase.DistributionTypes.CONVERSATION) {
sendRequest.setCc(encodedNumbers);
}
long messageId = DatabaseFactory.getMmsDatabase(context)
.insertMessageOutbox(masterSecret, sendRequest, threadId, secure);

View File

@@ -24,7 +24,7 @@ public class UniversalTransport {
}
public void deliver(SmsMessageRecord message) throws UndeliverableMessageException {
Recipient recipient = message.getRecipients().getPrimaryRecipient();
Recipient recipient = message.getIndividualRecipient();
String number = PhoneNumberFormatter.formatNumber(context, recipient.getNumber());
if (NumberFilter.getInstance(context).containsNumber(number)) {

View File

@@ -33,6 +33,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import ws.com.google.android.mms.pdu.EncodedStringValue;
public class Util {
public static byte[] combine(byte[] one, byte[] two) {
@@ -105,6 +107,10 @@ public class Util {
return value == null || value.length() == 0;
}
public static boolean isEmpty(EncodedStringValue[] value) {
return value == null || value.length == 0;
}
public static CharSequence getBoldedString(String value) {
SpannableString spanned = new SpannableString(value);
spanned.setSpan(new StyleSpan(Typeface.BOLD), 0,
@@ -156,6 +162,7 @@ public class Util {
return new String(bout.toByteArray());
}
// public static Bitmap loadScaledBitmap(InputStream src, int targetWidth, int targetHeight) {
// return BitmapFactory.decodeStream(src);
//// BitmapFactory.Options options = new BitmapFactory.Options();