mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-22 16:38:25 +00:00
Support for dual-sim SMS/MMS functionality
Allow source selection for sending SMS/MMS, and display the SIM that received SMS/MMS. Fixes #555 Closes #5199 // FREEBIE
This commit is contained in:
parent
c1106d98dd
commit
6da86e482d
@ -113,6 +113,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:paddingTop="2dp"
|
android:paddingTop="2dp"
|
||||||
|
android:paddingRight="4dp"
|
||||||
|
android:paddingEnd="4dp"
|
||||||
android:src="?menu_lock_icon_small"
|
android:src="?menu_lock_icon_small"
|
||||||
android:contentDescription="@string/conversation_item__secure_message_description"
|
android:contentDescription="@string/conversation_item__secure_message_description"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
@ -126,6 +128,19 @@
|
|||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<TextView android:id="@+id/conversation_item_date"
|
<TextView android:id="@+id/conversation_item_date"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:paddingTop="1dip"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="?conversation_item_received_text_secondary_color"
|
||||||
|
android:textSize="@dimen/conversation_item_date_text_size"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:autoLink="none"
|
||||||
|
android:linksClickable="false"
|
||||||
|
tools:text="Now"/>
|
||||||
|
|
||||||
|
<TextView android:id="@+id/sim_info"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="left"
|
android:layout_gravity="left"
|
||||||
@ -137,7 +152,10 @@
|
|||||||
android:textSize="@dimen/conversation_item_date_text_size"
|
android:textSize="@dimen/conversation_item_date_text_size"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:autoLink="none"
|
android:autoLink="none"
|
||||||
android:linksClickable="false" />
|
android:linksClickable="false"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:text="from SIM1"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -125,6 +125,25 @@
|
|||||||
android:paddingBottom="2dp"
|
android:paddingBottom="2dp"
|
||||||
tools:text="30 mins" />
|
tools:text="30 mins" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/sim_info"
|
||||||
|
android:autoLink="none"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="15sp"
|
||||||
|
android:linksClickable="false"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:textColor="?conversation_item_sent_text_secondary_color"
|
||||||
|
android:textSize="@dimen/conversation_item_date_text_size"
|
||||||
|
android:paddingTop="1dip"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
|
android:paddingLeft="4dp"
|
||||||
|
android:paddingStart="4dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"
|
||||||
|
tools:text="to SIM1"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.DeliveryStatusView
|
<org.thoughtcrime.securesms.components.DeliveryStatusView
|
||||||
android:id="@+id/delivery_status"
|
android:id="@+id/delivery_status"
|
||||||
android:layout_width="20dp"
|
android:layout_width="20dp"
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingLeft="10dp"
|
android:paddingLeft="10dp"
|
||||||
android:paddingRight="10dp">
|
android:paddingRight="10dp">
|
||||||
|
|
||||||
<ImageView android:id="@+id/icon"
|
<ImageView android:id="@+id/icon"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -16,11 +17,28 @@
|
|||||||
android:contentDescription="@string/transport_selection_list_item__transport_icon"
|
android:contentDescription="@string/transport_selection_list_item__transport_icon"
|
||||||
tools:src="@drawable/ic_send_push_white_24dp"
|
tools:src="@drawable/ic_send_push_white_24dp"
|
||||||
tools:backgroundTint="@color/textsecure_primary" />
|
tools:backgroundTint="@color/textsecure_primary" />
|
||||||
|
|
||||||
|
<LinearLayout android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingLeft="10dp">
|
||||||
|
|
||||||
<TextView android:id="@+id/text"
|
<TextView android:id="@+id/text"
|
||||||
android:paddingLeft="10dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:text="TextSecure" />
|
tools:text="TextSecure" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/subtext"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:textSize="12dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="From Home"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -100,6 +100,8 @@
|
|||||||
<string name="ConversationItem_click_to_approve_unencrypted_mms_dialog_title">Fallback to unencrypted MMS?</string>
|
<string name="ConversationItem_click_to_approve_unencrypted_mms_dialog_title">Fallback to unencrypted MMS?</string>
|
||||||
<string name="ConversationItem_click_to_approve_unencrypted_dialog_message">This message will <b>not</b> be encrypted because the recipient is no longer a Signal user.\n\nSend unsecured message?</string>
|
<string name="ConversationItem_click_to_approve_unencrypted_dialog_message">This message will <b>not</b> be encrypted because the recipient is no longer a Signal user.\n\nSend unsecured message?</string>
|
||||||
<string name="ConversationItem_unable_to_open_media">Can\'t find an app able to open this media.</string>
|
<string name="ConversationItem_unable_to_open_media">Can\'t find an app able to open this media.</string>
|
||||||
|
<string name="ConversationItem_from_s">from %s</string>
|
||||||
|
<string name="ConversationItem_to_s">to %s</string>
|
||||||
|
|
||||||
<!-- ConversationActivity -->
|
<!-- ConversationActivity -->
|
||||||
<string name="ConversationActivity_reset_secure_session_question">Reset secure session?</string>
|
<string name="ConversationActivity_reset_secure_session_question">Reset secure session?</string>
|
||||||
|
@ -535,7 +535,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
|
|
||||||
OutgoingEndSessionMessage endSessionMessage =
|
OutgoingEndSessionMessage endSessionMessage =
|
||||||
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE"));
|
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE", -1));
|
||||||
|
|
||||||
new AsyncTask<OutgoingEndSessionMessage, Void, Long>() {
|
new AsyncTask<OutgoingEndSessionMessage, Void, Long>() {
|
||||||
@Override
|
@Override
|
||||||
@ -823,22 +823,43 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onSecurityUpdated() {
|
private void onSecurityUpdated() {
|
||||||
updateInviteReminder();
|
updateRecipientPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateInviteReminder() {
|
private void updateRecipientPreferences() {
|
||||||
if (TextSecurePreferences.isPushRegistered(this) &&
|
if (recipients.getPrimaryRecipient() != null &&
|
||||||
!isSecureText &&
|
|
||||||
recipients.isSingleRecipient() &&
|
|
||||||
recipients.getPrimaryRecipient() != null &&
|
|
||||||
recipients.getPrimaryRecipient().getContactUri() != null)
|
recipients.getPrimaryRecipient().getContactUri() != null)
|
||||||
{
|
{
|
||||||
new ShowInviteReminderTask().execute(recipients);
|
new RecipientPreferencesTask().execute(recipients);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateInviteReminder(boolean seenInvite) {
|
||||||
|
Log.w(TAG, "updateInviteReminder(" + seenInvite+")");
|
||||||
|
if (TextSecurePreferences.isPushRegistered(this) &&
|
||||||
|
!isSecureText &&
|
||||||
|
!seenInvite &&
|
||||||
|
recipients.isSingleRecipient())
|
||||||
|
{
|
||||||
|
InviteReminder reminder = new InviteReminder(this, recipients);
|
||||||
|
reminder.setOkListener(new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
handleInviteLink();
|
||||||
|
reminderView.requestDismiss();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
reminderView.showReminder(reminder);
|
||||||
} else {
|
} else {
|
||||||
reminderView.hide();
|
reminderView.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateDefaultSubscriptionId(Optional<Integer> defaultSubscriptionId) {
|
||||||
|
Log.w(TAG, "updateDefaultSubscriptionId(" + defaultSubscriptionId.orNull() + ")");
|
||||||
|
sendButton.setDefaultSubscriptionId(defaultSubscriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeMmsEnabledCheck() {
|
private void initializeMmsEnabledCheck() {
|
||||||
new AsyncTask<Void, Void, Boolean>() {
|
new AsyncTask<Void, Void, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
@ -896,11 +917,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
sendButton.setEnabled(true);
|
sendButton.setEnabled(true);
|
||||||
sendButton.addOnTransportChangedListener(new OnTransportChangedListener() {
|
sendButton.addOnTransportChangedListener(new OnTransportChangedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onChange(TransportOption newTransport) {
|
public void onChange(TransportOption newTransport, boolean manuallySelected) {
|
||||||
calculateCharactersRemaining();
|
calculateCharactersRemaining();
|
||||||
composeText.setTransport(newTransport);
|
composeText.setTransport(newTransport);
|
||||||
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), Mode.MULTIPLY);
|
buttonToggle.getBackground().setColorFilter(newTransport.getBackgroundColor(), Mode.MULTIPLY);
|
||||||
buttonToggle.getBackground().invalidateSelf();
|
buttonToggle.getBackground().invalidateSelf();
|
||||||
|
if (manuallySelected) recordSubscriptionIdPreference(newTransport.getSimSubscriptionId());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -968,7 +990,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
titleView.setTitle(recipients);
|
titleView.setTitle(recipients);
|
||||||
setBlockedUserState(recipients);
|
setBlockedUserState(recipients);
|
||||||
setActionBarColor(recipients.getColor());
|
setActionBarColor(recipients.getColor());
|
||||||
updateInviteReminder();
|
updateRecipientPreferences();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1244,6 +1266,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
try {
|
try {
|
||||||
Recipients recipients = getRecipients();
|
Recipients recipients = getRecipients();
|
||||||
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
||||||
|
int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
|
||||||
|
|
||||||
Log.w(TAG, "isManual Selection: " + sendButton.isManualSelection());
|
Log.w(TAG, "isManual Selection: " + sendButton.isManualSelection());
|
||||||
Log.w(TAG, "forceSms: " + forceSms);
|
Log.w(TAG, "forceSms: " + forceSms);
|
||||||
@ -1255,9 +1278,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
|
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
|
||||||
handleManualMmsRequired();
|
handleManualMmsRequired();
|
||||||
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
|
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
|
||||||
sendMediaMessage(forceSms);
|
sendMediaMessage(forceSms, subscriptionId);
|
||||||
} else {
|
} else {
|
||||||
sendTextMessage(forceSms);
|
sendTextMessage(forceSms, subscriptionId);
|
||||||
}
|
}
|
||||||
} catch (RecipientFormattingException ex) {
|
} catch (RecipientFormattingException ex) {
|
||||||
Toast.makeText(ConversationActivity.this,
|
Toast.makeText(ConversationActivity.this,
|
||||||
@ -1271,13 +1294,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMediaMessage(final boolean forceSms)
|
private void sendMediaMessage(final boolean forceSms, final int subscriptionId)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
sendMediaMessage(forceSms, getMessage(), attachmentManager.buildSlideDeck());
|
sendMediaMessage(forceSms, getMessage(), attachmentManager.buildSlideDeck(), subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ListenableFuture<Void> sendMediaMessage(final boolean forceSms, String body, SlideDeck slideDeck)
|
private ListenableFuture<Void> sendMediaMessage(final boolean forceSms, String body, SlideDeck slideDeck, final int subscriptionId)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
final SettableFuture<Void> future = new SettableFuture<>();
|
final SettableFuture<Void> future = new SettableFuture<>();
|
||||||
@ -1286,6 +1309,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
slideDeck,
|
slideDeck,
|
||||||
body,
|
body,
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
|
subscriptionId,
|
||||||
distributionType);
|
distributionType);
|
||||||
|
|
||||||
if (isSecureText && !forceSms) {
|
if (isSecureText && !forceSms) {
|
||||||
@ -1311,7 +1335,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendTextMessage(final boolean forceSms)
|
private void sendTextMessage(final boolean forceSms, final int subscriptionId)
|
||||||
throws InvalidMessageException
|
throws InvalidMessageException
|
||||||
{
|
{
|
||||||
final Context context = getApplicationContext();
|
final Context context = getApplicationContext();
|
||||||
@ -1320,7 +1344,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
if (isSecureText && !forceSms) {
|
if (isSecureText && !forceSms) {
|
||||||
message = new OutgoingEncryptedMessage(recipients, getMessage());
|
message = new OutgoingEncryptedMessage(recipients, getMessage());
|
||||||
} else {
|
} else {
|
||||||
message = new OutgoingTextMessage(recipients, getMessage());
|
message = new OutgoingTextMessage(recipients, getMessage(), subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.composeText.setText("");
|
this.composeText.setText("");
|
||||||
@ -1348,6 +1372,17 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recordSubscriptionIdPreference(final Optional<Integer> subscriptionId) {
|
||||||
|
new AsyncTask<Void, Void, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||||
|
.setDefaultSubscriptionId(recipients, subscriptionId.or(-1));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttachmentDrawerStateChanged(DrawerState drawerState) {
|
public void onAttachmentDrawerStateChanged(DrawerState drawerState) {
|
||||||
if (drawerState == DrawerState.FULL_EXPANDED) {
|
if (drawerState == DrawerState.FULL_EXPANDED) {
|
||||||
@ -1399,11 +1434,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
public void onSuccess(final @NonNull Pair<Uri, Long> result) {
|
public void onSuccess(final @NonNull Pair<Uri, Long> result) {
|
||||||
try {
|
try {
|
||||||
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
||||||
|
int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
|
||||||
AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, ContentType.AUDIO_AAC);
|
AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, ContentType.AUDIO_AAC);
|
||||||
SlideDeck slideDeck = new SlideDeck();
|
SlideDeck slideDeck = new SlideDeck();
|
||||||
slideDeck.addSlide(audioSlide);
|
slideDeck.addSlide(audioSlide);
|
||||||
|
|
||||||
sendMediaMessage(forceSms, "", slideDeck).addListener(new AssertedSuccessListener<Void>() {
|
sendMediaMessage(forceSms, "", slideDeck, subscriptionId).addListener(new AssertedSuccessListener<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Void nothing) {
|
public void onSuccess(Void nothing) {
|
||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@ -1568,30 +1604,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
updateToggleButtonState();
|
updateToggleButtonState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ShowInviteReminderTask extends AsyncTask<Recipients, Void, Pair<Recipients,Boolean>> {
|
private class RecipientPreferencesTask extends AsyncTask<Recipients, Void, Pair<Recipients,RecipientsPreferences>> {
|
||||||
@Override
|
@Override
|
||||||
protected Pair<Recipients, Boolean> doInBackground(Recipients... recipients) {
|
protected Pair<Recipients, RecipientsPreferences> doInBackground(Recipients... recipients) {
|
||||||
if (recipients.length != 1 || recipients[0] == null) throw new AssertionError("task needs exactly one Recipients object");
|
if (recipients.length != 1 || recipients[0] == null) {
|
||||||
|
throw new AssertionError("task needs exactly one Recipients object");
|
||||||
|
}
|
||||||
|
|
||||||
Optional<RecipientsPreferences> prefs = DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
Optional<RecipientsPreferences> prefs = DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||||
.getRecipientsPreferences(recipients[0].getIds());
|
.getRecipientsPreferences(recipients[0].getIds());
|
||||||
return new Pair<>(recipients[0], prefs.isPresent() && prefs.get().hasSeenInviteReminder());
|
return new Pair<>(recipients[0], prefs.orNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Pair<Recipients, Boolean> result) {
|
protected void onPostExecute(@NonNull Pair<Recipients, RecipientsPreferences> result) {
|
||||||
if (!result.second && result.first == recipients) {
|
if (result.first == recipients) {
|
||||||
InviteReminder reminder = new InviteReminder(ConversationActivity.this, result.first);
|
updateInviteReminder(result.second != null && result.second.hasSeenInviteReminder());
|
||||||
reminder.setOkListener(new OnClickListener() {
|
updateDefaultSubscriptionId(result.second != null ? result.second.getDefaultSubscriptionId() : Optional.<Integer>absent());
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
handleInviteLink();
|
|
||||||
reminderView.requestDismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
reminderView.showReminder(reminder);
|
|
||||||
} else {
|
|
||||||
reminderView.hide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,9 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
|||||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
|
||||||
|
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -93,6 +96,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
private View bodyBubble;
|
private View bodyBubble;
|
||||||
private TextView bodyText;
|
private TextView bodyText;
|
||||||
private TextView dateText;
|
private TextView dateText;
|
||||||
|
private TextView simInfoText;
|
||||||
private TextView indicatorText;
|
private TextView indicatorText;
|
||||||
private TextView groupStatusText;
|
private TextView groupStatusText;
|
||||||
private ImageView secureImage;
|
private ImageView secureImage;
|
||||||
@ -135,6 +139,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
|
|
||||||
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
|
this.bodyText = (TextView) findViewById(R.id.conversation_item_body);
|
||||||
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
|
this.dateText = (TextView) findViewById(R.id.conversation_item_date);
|
||||||
|
this.simInfoText = (TextView) findViewById(R.id.sim_info);
|
||||||
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
|
this.indicatorText = (TextView) findViewById(R.id.indicator_text);
|
||||||
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
|
this.groupStatusText = (TextView) findViewById(R.id.group_message_status);
|
||||||
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
|
this.secureImage = (ImageView) findViewById(R.id.secure_indicator);
|
||||||
@ -188,6 +193,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
setGroupMessageStatus(messageRecord, recipient);
|
setGroupMessageStatus(messageRecord, recipient);
|
||||||
setMinimumWidth();
|
setMinimumWidth();
|
||||||
setMediaAttributes(messageRecord);
|
setMediaAttributes(messageRecord);
|
||||||
|
setSimInfo(messageRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeAttributes() {
|
private void initializeAttributes() {
|
||||||
@ -327,6 +333,25 @@ public class ConversationItem extends LinearLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSimInfo(MessageRecord messageRecord) {
|
||||||
|
if (messageRecord.getSubscriptionId() == -1) {
|
||||||
|
simInfoText.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
|
||||||
|
Optional<SubscriptionInfoCompat> subscriptionInfo = subscriptionManager.getActiveSubscriptionInfo(messageRecord.getSubscriptionId());
|
||||||
|
|
||||||
|
if (subscriptionInfo.isPresent() && messageRecord.isOutgoing()) {
|
||||||
|
simInfoText.setText(getContext().getString(R.string.ConversationItem_from_s, subscriptionInfo.get().getDisplayName()));
|
||||||
|
simInfoText.setVisibility(View.VISIBLE);
|
||||||
|
} else if (subscriptionInfo.isPresent()) {
|
||||||
|
simInfoText.setText(getContext().getString(R.string.ConversationItem_to_s, subscriptionInfo.get().getDisplayName()));
|
||||||
|
simInfoText.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
simInfoText.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setFailedStatusIcons() {
|
private void setFailedStatusIcons() {
|
||||||
alertView.setFailed();
|
alertView.setFailed();
|
||||||
deliveryStatusIndicator.setNone();
|
deliveryStatusIndicator.setNone();
|
||||||
|
@ -121,7 +121,7 @@ public class ConversationPopupActivity extends ConversationActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateInviteReminder() {
|
protected void updateInviteReminder(boolean seenInvite) {
|
||||||
reminderView.setVisibility(View.GONE);
|
reminderView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,15 @@ import org.thoughtcrime.securesms.components.ContactFilterToolbar;
|
|||||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
|
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture.Listener;
|
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture.Listener;
|
||||||
|
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
@ -227,9 +229,14 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
|||||||
if (context == null) return null;
|
if (context == null) return null;
|
||||||
|
|
||||||
for (String number : numbers) {
|
for (String number : numbers) {
|
||||||
final Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
|
Recipients recipients = RecipientFactory.getRecipientsFromString(context, number, false);
|
||||||
if (recipients != null && recipients.getPrimaryRecipient() != null) {
|
|
||||||
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message), -1L, true);
|
if (recipients.getPrimaryRecipient() != null) {
|
||||||
|
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipients.getIds());
|
||||||
|
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||||
|
|
||||||
|
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message, subscriptionId), -1L, true);
|
||||||
|
|
||||||
if (recipients.getPrimaryRecipient().getContactUri() != null) {
|
if (recipients.getPrimaryRecipient().getContactUri() != null) {
|
||||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipients, true);
|
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipients, true);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.support.annotation.DrawableRes;
|
import android.support.annotation.DrawableRes;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
||||||
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
public class TransportOption {
|
public class TransportOption {
|
||||||
|
|
||||||
@ -12,19 +14,34 @@ public class TransportOption {
|
|||||||
TEXTSECURE
|
TEXTSECURE
|
||||||
}
|
}
|
||||||
|
|
||||||
private int drawable;
|
private final int drawable;
|
||||||
private int backgroundColor;
|
private final int backgroundColor;
|
||||||
private String text;
|
private final @NonNull String text;
|
||||||
private Type type;
|
private final @NonNull Type type;
|
||||||
private String composeHint;
|
private final @NonNull String composeHint;
|
||||||
private CharacterCalculator characterCalculator;
|
private final @NonNull CharacterCalculator characterCalculator;
|
||||||
|
private final @NonNull Optional<CharSequence> simName;
|
||||||
|
private final @NonNull Optional<Integer> simSubscriptionId;
|
||||||
|
|
||||||
public TransportOption(Type type,
|
public TransportOption(@NonNull Type type,
|
||||||
@DrawableRes int drawable,
|
@DrawableRes int drawable,
|
||||||
int backgroundColor,
|
int backgroundColor,
|
||||||
String text,
|
@NonNull String text,
|
||||||
String composeHint,
|
@NonNull String composeHint,
|
||||||
CharacterCalculator characterCalculator)
|
@NonNull CharacterCalculator characterCalculator)
|
||||||
|
{
|
||||||
|
this(type, drawable, backgroundColor, text, composeHint, characterCalculator,
|
||||||
|
Optional.<CharSequence>absent(), Optional.<Integer>absent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransportOption(@NonNull Type type,
|
||||||
|
@DrawableRes int drawable,
|
||||||
|
int backgroundColor,
|
||||||
|
@NonNull String text,
|
||||||
|
@NonNull String composeHint,
|
||||||
|
@NonNull CharacterCalculator characterCalculator,
|
||||||
|
@NonNull Optional<CharSequence> simName,
|
||||||
|
@NonNull Optional<Integer> simSubscriptionId)
|
||||||
{
|
{
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.drawable = drawable;
|
this.drawable = drawable;
|
||||||
@ -32,9 +49,12 @@ public class TransportOption {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
this.composeHint = composeHint;
|
this.composeHint = composeHint;
|
||||||
this.characterCalculator = characterCalculator;
|
this.characterCalculator = characterCalculator;
|
||||||
|
this.simName = simName;
|
||||||
|
this.simSubscriptionId = simSubscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type getType() {
|
|
||||||
|
public @NonNull Type getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,11 +78,22 @@ public class TransportOption {
|
|||||||
return backgroundColor;
|
return backgroundColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getComposeHint() {
|
public @NonNull String getComposeHint() {
|
||||||
return composeHint;
|
return composeHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public @NonNull String getDescription() {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Optional<CharSequence> getSimName() {
|
||||||
|
return simName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public Optional<Integer> getSimSubscriptionId() {
|
||||||
|
return simSubscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
package org.thoughtcrime.securesms;
|
package org.thoughtcrime.securesms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.util.CharacterCalculator;
|
||||||
import org.thoughtcrime.securesms.util.MmsCharacterCalculator;
|
import org.thoughtcrime.securesms.util.MmsCharacterCalculator;
|
||||||
import org.thoughtcrime.securesms.util.PushCharacterCalculator;
|
import org.thoughtcrime.securesms.util.PushCharacterCalculator;
|
||||||
import org.thoughtcrime.securesms.util.SmsCharacterCalculator;
|
import org.thoughtcrime.securesms.util.SmsCharacterCalculator;
|
||||||
|
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
|
||||||
|
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
|
||||||
import org.whispersystems.libaxolotl.util.guava.Optional;
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -20,49 +25,76 @@ public class TransportOptions {
|
|||||||
private final Context context;
|
private final Context context;
|
||||||
private final List<TransportOption> enabledTransports;
|
private final List<TransportOption> enabledTransports;
|
||||||
|
|
||||||
private Type selectedType;
|
private Type defaultTransportType = Type.SMS;
|
||||||
private boolean manuallySelected;
|
private Optional<Integer> defaultSubscriptionId = Optional.absent();
|
||||||
|
private Optional<TransportOption> selectedOption = Optional.absent();
|
||||||
|
|
||||||
public TransportOptions(Context context, boolean media) {
|
public TransportOptions(Context context, boolean media) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.enabledTransports = initializeAvailableTransports(media);
|
this.enabledTransports = initializeAvailableTransports(media);
|
||||||
|
|
||||||
setDefaultTransport(Type.SMS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset(boolean media) {
|
public void reset(boolean media) {
|
||||||
List<TransportOption> transportOptions = initializeAvailableTransports(media);
|
List<TransportOption> transportOptions = initializeAvailableTransports(media);
|
||||||
|
|
||||||
this.enabledTransports.clear();
|
this.enabledTransports.clear();
|
||||||
this.enabledTransports.addAll(transportOptions);
|
this.enabledTransports.addAll(transportOptions);
|
||||||
|
|
||||||
if (!find(selectedType).isPresent()) {
|
if (selectedOption.isPresent() && !isEnabled(selectedOption.get())) {
|
||||||
this.manuallySelected = false;
|
setSelectedTransport(null);
|
||||||
setTransport(Type.SMS);
|
|
||||||
} else {
|
} else {
|
||||||
|
this.defaultTransportType = Type.SMS;
|
||||||
|
this.defaultSubscriptionId = Optional.absent();
|
||||||
|
|
||||||
notifyTransportChangeListeners();
|
notifyTransportChangeListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultTransport(Type type) {
|
public void setDefaultTransport(Type type) {
|
||||||
if (!this.manuallySelected) {
|
this.defaultTransportType = type;
|
||||||
setTransport(type);
|
|
||||||
|
if (!selectedOption.isPresent()) {
|
||||||
|
notifyTransportChangeListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectedTransport(Type type) {
|
public void setDefaultSubscriptionId(Optional<Integer> subscriptionId) {
|
||||||
this.manuallySelected= true;
|
this.defaultSubscriptionId = subscriptionId;
|
||||||
setTransport(type);
|
|
||||||
|
if (!selectedOption.isPresent()) {
|
||||||
|
notifyTransportChangeListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectedTransport(@Nullable TransportOption transportOption) {
|
||||||
|
this.selectedOption = Optional.fromNullable(transportOption);
|
||||||
|
notifyTransportChangeListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isManualSelection() {
|
public boolean isManualSelection() {
|
||||||
return manuallySelected;
|
return this.selectedOption.isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TransportOption getSelectedTransport() {
|
public @NonNull TransportOption getSelectedTransport() {
|
||||||
Optional<TransportOption> option = find(selectedType);
|
if (selectedOption.isPresent()) return selectedOption.get();
|
||||||
|
|
||||||
if (option.isPresent()) return option.get();
|
if (defaultSubscriptionId.isPresent()) {
|
||||||
else throw new AssertionError("Selected type isn't present!");
|
for (TransportOption transportOption : enabledTransports) {
|
||||||
|
if (transportOption.getType() == defaultTransportType &&
|
||||||
|
(int)defaultSubscriptionId.get() == transportOption.getSimSubscriptionId().or(-1))
|
||||||
|
{
|
||||||
|
return transportOption;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TransportOption transportOption : enabledTransports) {
|
||||||
|
if (transportOption.getType() == defaultTransportType) {
|
||||||
|
return transportOption;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError("No options of default type!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableTransport(Type type) {
|
public void disableTransport(Type type) {
|
||||||
@ -71,8 +103,8 @@ public class TransportOptions {
|
|||||||
if (option.isPresent()) {
|
if (option.isPresent()) {
|
||||||
enabledTransports.remove(option.get());
|
enabledTransports.remove(option.get());
|
||||||
|
|
||||||
if (manuallySelected && type == selectedType) {
|
if (selectedOption.isPresent() && selectedOption.get().getType() == type) {
|
||||||
manuallySelected = false;
|
setSelectedTransport(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,15 +121,11 @@ public class TransportOptions {
|
|||||||
List<TransportOption> results = new LinkedList<>();
|
List<TransportOption> results = new LinkedList<>();
|
||||||
|
|
||||||
if (isMediaMessage) {
|
if (isMediaMessage) {
|
||||||
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
results.addAll(getTransportOptionsForSimCards(context.getString(R.string.ConversationActivity_transport_insecure_mms),
|
||||||
context.getResources().getColor(R.color.grey_600),
|
|
||||||
context.getString(R.string.ConversationActivity_transport_insecure_mms),
|
|
||||||
context.getString(R.string.conversation_activity__type_message_mms_insecure),
|
context.getString(R.string.conversation_activity__type_message_mms_insecure),
|
||||||
new MmsCharacterCalculator()));
|
new MmsCharacterCalculator()));
|
||||||
} else {
|
} else {
|
||||||
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
results.addAll(getTransportOptionsForSimCards(context.getString(R.string.ConversationActivity_transport_insecure_sms),
|
||||||
context.getResources().getColor(R.color.grey_600),
|
|
||||||
context.getString(R.string.ConversationActivity_transport_insecure_sms),
|
|
||||||
context.getString(R.string.conversation_activity__type_message_sms_insecure),
|
context.getString(R.string.conversation_activity__type_message_sms_insecure),
|
||||||
new SmsCharacterCalculator()));
|
new SmsCharacterCalculator()));
|
||||||
}
|
}
|
||||||
@ -111,16 +139,34 @@ public class TransportOptions {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @NonNull List<TransportOption> getTransportOptionsForSimCards(@NonNull String text,
|
||||||
|
@NonNull String composeHint,
|
||||||
|
@NonNull CharacterCalculator characterCalculator)
|
||||||
|
{
|
||||||
|
List<TransportOption> results = new LinkedList<>();
|
||||||
|
SubscriptionManagerCompat subscriptionManager = new SubscriptionManagerCompat(context);
|
||||||
|
List<SubscriptionInfoCompat> subscriptions = subscriptionManager.getActiveSubscriptionInfoList();
|
||||||
|
|
||||||
private void setTransport(Type type) {
|
if (subscriptions.size() < 2) {
|
||||||
this.selectedType = type;
|
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
||||||
|
context.getResources().getColor(R.color.grey_600),
|
||||||
|
text, composeHint, characterCalculator));
|
||||||
|
} else {
|
||||||
|
for (SubscriptionInfoCompat subscriptionInfo : subscriptions) {
|
||||||
|
results.add(new TransportOption(Type.SMS, R.drawable.ic_send_sms_white_24dp,
|
||||||
|
context.getResources().getColor(R.color.grey_600),
|
||||||
|
text, composeHint, characterCalculator,
|
||||||
|
Optional.of(subscriptionInfo.getDisplayName()),
|
||||||
|
Optional.of(subscriptionInfo.getSubscriptionId())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
notifyTransportChangeListeners();
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyTransportChangeListeners() {
|
private void notifyTransportChangeListeners() {
|
||||||
for (OnTransportChangedListener listener : listeners) {
|
for (OnTransportChangedListener listener : listeners) {
|
||||||
listener.onChange(getSelectedTransport());
|
listener.onChange(getSelectedTransport(), selectedOption.isPresent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +180,15 @@ public class TransportOptions {
|
|||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isEnabled(TransportOption transportOption) {
|
||||||
|
for (TransportOption option : enabledTransports) {
|
||||||
|
if (option.equals(transportOption)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnTransportChangedListener {
|
public interface OnTransportChangedListener {
|
||||||
public void onChange(TransportOption newTransport);
|
public void onChange(TransportOption newTransport, boolean manuallySelected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ import android.widget.BaseAdapter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class TransportOptionsAdapter extends BaseAdapter {
|
public class TransportOptionsAdapter extends BaseAdapter {
|
||||||
@ -52,13 +54,21 @@ public class TransportOptionsAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransportOption transport = (TransportOption) getItem(position);
|
TransportOption transport = (TransportOption) getItem(position);
|
||||||
ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
|
ImageView imageView = ViewUtil.findById(convertView, R.id.icon);
|
||||||
TextView textView = (TextView) convertView.findViewById(R.id.text);
|
TextView textView = ViewUtil.findById(convertView, R.id.text);
|
||||||
|
TextView subtextView = ViewUtil.findById(convertView, R.id.subtext);
|
||||||
|
|
||||||
imageView.getBackground().setColorFilter(transport.getBackgroundColor(), Mode.MULTIPLY);
|
imageView.getBackground().setColorFilter(transport.getBackgroundColor(), Mode.MULTIPLY);
|
||||||
imageView.setImageResource(transport.getDrawable());
|
imageView.setImageResource(transport.getDrawable());
|
||||||
textView.setText(transport.getDescription());
|
textView.setText(transport.getDescription());
|
||||||
|
|
||||||
|
if (transport.getSimName().isPresent()) {
|
||||||
|
subtextView.setText(transport.getSimName().get());
|
||||||
|
subtextView.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
subtextView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package org.thoughtcrime.securesms.components;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextUtils.TruncateAt;
|
import android.text.TextUtils.TruncateAt;
|
||||||
import android.text.style.RelativeSizeSpan;
|
import android.text.style.RelativeSizeSpan;
|
||||||
@ -17,7 +19,9 @@ import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
public class ComposeText extends EmojiEditText {
|
public class ComposeText extends EmojiEditText {
|
||||||
|
|
||||||
private SpannableString hint;
|
private SpannableString hint;
|
||||||
|
private SpannableString subHint;
|
||||||
|
|
||||||
public ComposeText(Context context) {
|
public ComposeText(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@ -31,12 +35,20 @@ public class ComposeText extends EmojiEditText {
|
|||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
super.onLayout(changed, left, top, right, bottom);
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(hint)) {
|
if (!TextUtils.isEmpty(hint)) {
|
||||||
|
if (!TextUtils.isEmpty(subHint)) {
|
||||||
|
setHint(new SpannableStringBuilder().append(ellipsizeToWidth(hint))
|
||||||
|
.append("\n")
|
||||||
|
.append(ellipsizeToWidth(subHint)));
|
||||||
|
} else {
|
||||||
setHint(ellipsizeToWidth(hint));
|
setHint(ellipsizeToWidth(hint));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CharSequence ellipsizeToWidth(CharSequence text) {
|
private CharSequence ellipsizeToWidth(CharSequence text) {
|
||||||
return TextUtils.ellipsize(text,
|
return TextUtils.ellipsize(text,
|
||||||
@ -45,11 +57,25 @@ public class ComposeText extends EmojiEditText {
|
|||||||
TruncateAt.END);
|
TruncateAt.END);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHint(@NonNull String hint) {
|
public void setHint(@NonNull String hint, @Nullable CharSequence subHint) {
|
||||||
this.hint = new SpannableString(hint);
|
this.hint = new SpannableString(hint);
|
||||||
this.hint.setSpan(new RelativeSizeSpan(0.8f), 0, hint.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
this.hint.setSpan(new RelativeSizeSpan(0.8f), 0, hint.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
|
|
||||||
|
if (subHint != null) {
|
||||||
|
this.subHint = new SpannableString(subHint);
|
||||||
|
this.subHint.setSpan(new RelativeSizeSpan(0.8f), 0, subHint.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
|
} else {
|
||||||
|
this.subHint = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.subHint != null) {
|
||||||
|
super.setHint(new SpannableStringBuilder().append(ellipsizeToWidth(this.hint))
|
||||||
|
.append("\n")
|
||||||
|
.append(ellipsizeToWidth(this.subHint)));
|
||||||
|
} else {
|
||||||
super.setHint(ellipsizeToWidth(this.hint));
|
super.setHint(ellipsizeToWidth(this.hint));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void appendInvite(String invite) {
|
public void appendInvite(String invite) {
|
||||||
if (!TextUtils.isEmpty(getText()) && !getText().toString().equals(" ")) {
|
if (!TextUtils.isEmpty(getText()) && !getText().toString().equals(" ")) {
|
||||||
@ -88,6 +114,6 @@ public class ComposeText extends EmojiEditText {
|
|||||||
|
|
||||||
setInputType(inputType);
|
setInputType(inputType);
|
||||||
setImeOptions(imeOptions);
|
setImeOptions(imeOptions);
|
||||||
setHint(transport.getComposeHint());
|
setHint(transport.getComposeHint(), transport.getSimName().isPresent() ? "From " + transport.getSimName().get() : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,14 +83,18 @@ public class SendButton extends ImageButton
|
|||||||
transportOptions.setDefaultTransport(type);
|
transportOptions.setDefaultTransport(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDefaultSubscriptionId(Optional<Integer> subscriptionId) {
|
||||||
|
transportOptions.setDefaultSubscriptionId(subscriptionId);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSelected(TransportOption option) {
|
public void onSelected(TransportOption option) {
|
||||||
transportOptions.setSelectedTransport(option.getType());
|
transportOptions.setSelectedTransport(option);
|
||||||
getTransportOptionsPopup().dismiss();
|
getTransportOptionsPopup().dismiss();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(TransportOption newTransport) {
|
public void onChange(TransportOption newTransport, boolean isManualSelection) {
|
||||||
setImageResource(newTransport.getDrawable());
|
setImageResource(newTransport.getDrawable());
|
||||||
setContentDescription(newTransport.getDescription());
|
setContentDescription(newTransport.getDescription());
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,8 @@ public class DatabaseFactory {
|
|||||||
private static final int INTRODUCED_ARCHIVE_VERSION = 24;
|
private static final int INTRODUCED_ARCHIVE_VERSION = 24;
|
||||||
private static final int INTRODUCED_CONVERSATION_LIST_STATUS_VERSION = 25;
|
private static final int INTRODUCED_CONVERSATION_LIST_STATUS_VERSION = 25;
|
||||||
private static final int MIGRATED_CONVERSATION_LIST_STATUS_VERSION = 26;
|
private static final int MIGRATED_CONVERSATION_LIST_STATUS_VERSION = 26;
|
||||||
private static final int DATABASE_VERSION = 26;
|
private static final int INTRODUCED_SUBSCRIPTION_ID_VERSION = 27;
|
||||||
|
private static final int DATABASE_VERSION = 27;
|
||||||
|
|
||||||
private static final String DATABASE_NAME = "messages.db";
|
private static final String DATABASE_NAME = "messages.db";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
@ -813,6 +814,12 @@ public class DatabaseFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldVersion < INTRODUCED_SUBSCRIPTION_ID_VERSION) {
|
||||||
|
db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN default_subscription_id INTEGER DEFAULT -1");
|
||||||
|
db.execSQL("ALTER TABLE sms ADD COLUMN subscription_id INTEGER DEFAULT -1");
|
||||||
|
db.execSQL("ALTER TABLE mms ADD COLUMN subscription_id INTEGER DEFAULT -1");
|
||||||
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
@ -20,27 +20,24 @@ import android.content.Context;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
|
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
|
||||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
|
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||||
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
|
||||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.LRUCache;
|
import org.thoughtcrime.securesms.util.LRUCache;
|
||||||
import org.whispersystems.libaxolotl.InvalidMessageException;
|
import org.whispersystems.libaxolotl.InvalidMessageException;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|
||||||
|
|
||||||
import java.lang.ref.SoftReference;
|
import java.lang.ref.SoftReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class EncryptingSmsDatabase extends SmsDatabase {
|
public class EncryptingSmsDatabase extends SmsDatabase {
|
||||||
|
@ -24,7 +24,6 @@ import android.database.sqlite.SQLiteOpenHelper;
|
|||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@ -110,7 +109,8 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
"retr_txt" + " TEXT, " + "retr_txt_cs" + " INTEGER, " + "read_status" + " INTEGER, " +
|
"retr_txt" + " TEXT, " + "retr_txt_cs" + " INTEGER, " + "read_status" + " INTEGER, " +
|
||||||
"ct_cls" + " INTEGER, " + "resp_txt" + " TEXT, " + "d_tm" + " INTEGER, " +
|
"ct_cls" + " INTEGER, " + "resp_txt" + " TEXT, " + "d_tm" + " INTEGER, " +
|
||||||
RECEIPT_COUNT + " INTEGER DEFAULT 0, " + MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " +
|
RECEIPT_COUNT + " INTEGER DEFAULT 0, " + MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " +
|
||||||
NETWORK_FAILURE + " TEXT DEFAULT NULL," + "d_rpt" + " INTEGER);";
|
NETWORK_FAILURE + " TEXT DEFAULT NULL," + "d_rpt" + " INTEGER, " +
|
||||||
|
SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
|
||||||
|
|
||||||
public static final String[] CREATE_INDEXS = {
|
public static final String[] CREATE_INDEXS = {
|
||||||
"CREATE INDEX IF NOT EXISTS mms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
|
"CREATE INDEX IF NOT EXISTS mms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
|
||||||
@ -129,7 +129,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
|
CONTENT_LOCATION, EXPIRY, MESSAGE_TYPE,
|
||||||
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
|
MESSAGE_SIZE, STATUS, TRANSACTION_ID,
|
||||||
BODY, PART_COUNT, ADDRESS, ADDRESS_DEVICE_ID,
|
BODY, PART_COUNT, ADDRESS, ADDRESS_DEVICE_ID,
|
||||||
RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE,
|
RECEIPT_COUNT, MISMATCHED_IDENTITIES, NETWORK_FAILURE, SUBSCRIPTION_ID,
|
||||||
AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " AS " + AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
||||||
AttachmentDatabase.UNIQUE_ID,
|
AttachmentDatabase.UNIQUE_ID,
|
||||||
AttachmentDatabase.MMS_ID,
|
AttachmentDatabase.MMS_ID,
|
||||||
@ -478,7 +478,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
return new Pair<>(messageId, threadId);
|
return new Pair<>(messageId, threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<NotificationInd> getNotification(long messageId) {
|
public Optional<Pair<NotificationInd, Integer>> getNotification(long messageId) {
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -493,7 +493,8 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
builder.addLong(MESSAGE_SIZE, PduHeaders.MESSAGE_SIZE);
|
builder.addLong(MESSAGE_SIZE, PduHeaders.MESSAGE_SIZE);
|
||||||
builder.addText(TRANSACTION_ID, PduHeaders.TRANSACTION_ID);
|
builder.addText(TRANSACTION_ID, PduHeaders.TRANSACTION_ID);
|
||||||
|
|
||||||
return Optional.of(new NotificationInd(headers));
|
return Optional.of(new Pair<>(new NotificationInd(headers),
|
||||||
|
cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID))));
|
||||||
} else {
|
} else {
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
}
|
}
|
||||||
@ -517,6 +518,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
|
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
|
||||||
String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
|
String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
|
||||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
|
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
|
||||||
|
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
|
||||||
List<Attachment> attachments = new LinkedList<Attachment>(attachmentDatabase.getAttachmentsForMessage(messageId));
|
List<Attachment> attachments = new LinkedList<Attachment>(attachmentDatabase.getAttachmentsForMessage(messageId));
|
||||||
MmsAddresses addresses = addr.getAddressesForId(messageId);
|
MmsAddresses addresses = addr.getAddressesForId(messageId);
|
||||||
List<String> destinations = new LinkedList<>();
|
List<String> destinations = new LinkedList<>();
|
||||||
@ -532,7 +534,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
return new OutgoingGroupMediaMessage(recipients, body, attachments, timestamp);
|
return new OutgoingGroupMediaMessage(recipients, body, attachments, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
OutgoingMediaMessage message = new OutgoingMediaMessage(recipients, body, attachments, timestamp,
|
OutgoingMediaMessage message = new OutgoingMediaMessage(recipients, body, attachments, timestamp, subscriptionId,
|
||||||
!addresses.getBcc().isEmpty() ? ThreadDatabase.DistributionTypes.BROADCAST :
|
!addresses.getBcc().isEmpty() ? ThreadDatabase.DistributionTypes.BROADCAST :
|
||||||
ThreadDatabase.DistributionTypes.DEFAULT);
|
ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
if (Types.isSecureType(outboxType)) {
|
if (Types.isSecureType(outboxType)) {
|
||||||
@ -615,6 +617,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
||||||
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
|
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
|
||||||
contentValues.put(PART_COUNT, retrieved.getAttachments().size());
|
contentValues.put(PART_COUNT, retrieved.getAttachments().size());
|
||||||
|
contentValues.put(SUBSCRIPTION_ID, retrieved.getSubscriptionId());
|
||||||
contentValues.put(READ, 0);
|
contentValues.put(READ, 0);
|
||||||
|
|
||||||
if (!contentValues.containsKey(DATE_SENT)) {
|
if (!contentValues.containsKey(DATE_SENT)) {
|
||||||
@ -673,7 +676,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
return insertMessageInbox(masterSecret, retrieved, "", threadId, type);
|
return insertMessageInbox(masterSecret, retrieved, "", threadId, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<Long, Long> insertMessageInbox(@NonNull NotificationInd notification) {
|
public Pair<Long, Long> insertMessageInbox(@NonNull NotificationInd notification, int subscriptionId) {
|
||||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||||
long threadId = getThreadIdFor(notification);
|
long threadId = getThreadIdFor(notification);
|
||||||
@ -702,6 +705,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
||||||
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
|
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
|
||||||
contentValues.put(READ, Util.isDefaultSmsProvider(context) ? 0 : 1);
|
contentValues.put(READ, Util.isDefaultSmsProvider(context) ? 0 : 1);
|
||||||
|
contentValues.put(SUBSCRIPTION_ID, subscriptionId);
|
||||||
|
|
||||||
if (!contentValues.containsKey(DATE_SENT))
|
if (!contentValues.containsKey(DATE_SENT))
|
||||||
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
|
contentValues.put(DATE_SENT, contentValues.getAsLong(DATE_RECEIVED));
|
||||||
@ -761,6 +765,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
contentValues.put(THREAD_ID, threadId);
|
contentValues.put(THREAD_ID, threadId);
|
||||||
contentValues.put(READ, 1);
|
contentValues.put(READ, 1);
|
||||||
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
|
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||||
|
contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
|
||||||
|
|
||||||
if (message.getRecipients().isSingleRecipient()) {
|
if (message.getRecipients().isSingleRecipient()) {
|
||||||
try {
|
try {
|
||||||
@ -1021,6 +1026,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
long expiry = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRY));
|
long expiry = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRY));
|
||||||
int status = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.STATUS));
|
int status = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.STATUS));
|
||||||
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.RECEIPT_COUNT));
|
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.RECEIPT_COUNT));
|
||||||
|
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
|
||||||
|
|
||||||
byte[]contentLocationBytes = null;
|
byte[]contentLocationBytes = null;
|
||||||
byte[]transactionIdBytes = null;
|
byte[]transactionIdBytes = null;
|
||||||
@ -1035,7 +1041,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
return new NotificationMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
return new NotificationMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
||||||
addressDeviceId, dateSent, dateReceived, receiptCount, threadId,
|
addressDeviceId, dateSent, dateReceived, receiptCount, threadId,
|
||||||
contentLocationBytes, messageSize, expiry, status,
|
contentLocationBytes, messageSize, expiry, status,
|
||||||
transactionIdBytes, mailbox);
|
transactionIdBytes, mailbox, subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
|
private MediaMmsMessageRecord getMediaMmsMessageRecord(Cursor cursor) {
|
||||||
@ -1051,6 +1057,7 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
|
int partCount = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.PART_COUNT));
|
||||||
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
|
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.MISMATCHED_IDENTITIES));
|
||||||
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
|
String networkDocument = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.NETWORK_FAILURE));
|
||||||
|
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.SUBSCRIPTION_ID));
|
||||||
|
|
||||||
Recipients recipients = getRecipientsFor(address);
|
Recipients recipients = getRecipientsFor(address);
|
||||||
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
|
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
|
||||||
@ -1059,7 +1066,8 @@ public class MmsDatabase extends MessagingDatabase {
|
|||||||
|
|
||||||
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
||||||
addressDeviceId, dateSent, dateReceived, receiptCount,
|
addressDeviceId, dateSent, dateReceived, receiptCount,
|
||||||
threadId, body, slideDeck, partCount, box, mismatches, networkFailures);
|
threadId, body, slideDeck, partCount, box, mismatches,
|
||||||
|
networkFailures, subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipients getRecipientsFor(String address) {
|
private Recipients getRecipientsFor(String address) {
|
||||||
|
@ -14,6 +14,7 @@ public interface MmsSmsColumns {
|
|||||||
public static final String RECEIPT_COUNT = "delivery_receipt_count";
|
public static final String RECEIPT_COUNT = "delivery_receipt_count";
|
||||||
public static final String MISMATCHED_IDENTITIES = "mismatched_identities";
|
public static final String MISMATCHED_IDENTITIES = "mismatched_identities";
|
||||||
public static final String UNIQUE_ROW_ID = "unique_row_id";
|
public static final String UNIQUE_ROW_ID = "unique_row_id";
|
||||||
|
public static final String SUBSCRIPTION_ID = "subscription_id";
|
||||||
|
|
||||||
public static class Types {
|
public static class Types {
|
||||||
protected static final long TOTAL_MASK = 0xFFFFFFFF;
|
protected static final long TOTAL_MASK = 0xFFFFFFFF;
|
||||||
|
@ -52,7 +52,8 @@ public class MmsSmsDatabase extends Database {
|
|||||||
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
|
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY,
|
||||||
MmsDatabase.STATUS, MmsSmsColumns.RECEIPT_COUNT,
|
MmsDatabase.STATUS, MmsSmsColumns.RECEIPT_COUNT,
|
||||||
MmsSmsColumns.MISMATCHED_IDENTITIES,
|
MmsSmsColumns.MISMATCHED_IDENTITIES,
|
||||||
MmsDatabase.NETWORK_FAILURE, TRANSPORT,
|
MmsDatabase.NETWORK_FAILURE,
|
||||||
|
MmsSmsColumns.SUBSCRIPTION_ID, TRANSPORT,
|
||||||
AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
AttachmentDatabase.ATTACHMENT_ID_ALIAS,
|
||||||
AttachmentDatabase.UNIQUE_ID,
|
AttachmentDatabase.UNIQUE_ID,
|
||||||
AttachmentDatabase.MMS_ID,
|
AttachmentDatabase.MMS_ID,
|
||||||
@ -132,7 +133,7 @@ public class MmsSmsDatabase extends Database {
|
|||||||
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
|
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
|
||||||
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
|
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
|
||||||
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
|
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
|
||||||
MmsDatabase.NETWORK_FAILURE, TRANSPORT,
|
MmsSmsColumns.SUBSCRIPTION_ID, MmsDatabase.NETWORK_FAILURE, TRANSPORT,
|
||||||
AttachmentDatabase.UNIQUE_ID,
|
AttachmentDatabase.UNIQUE_ID,
|
||||||
AttachmentDatabase.MMS_ID,
|
AttachmentDatabase.MMS_ID,
|
||||||
AttachmentDatabase.SIZE,
|
AttachmentDatabase.SIZE,
|
||||||
@ -156,6 +157,7 @@ public class MmsSmsDatabase extends Database {
|
|||||||
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
|
MmsDatabase.CONTENT_LOCATION, MmsDatabase.TRANSACTION_ID,
|
||||||
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
|
MmsDatabase.MESSAGE_SIZE, MmsDatabase.EXPIRY, MmsDatabase.STATUS,
|
||||||
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
|
MmsSmsColumns.RECEIPT_COUNT, MmsSmsColumns.MISMATCHED_IDENTITIES,
|
||||||
|
MmsSmsColumns.SUBSCRIPTION_ID,
|
||||||
MmsDatabase.NETWORK_FAILURE, TRANSPORT,
|
MmsDatabase.NETWORK_FAILURE, TRANSPORT,
|
||||||
AttachmentDatabase.UNIQUE_ID,
|
AttachmentDatabase.UNIQUE_ID,
|
||||||
AttachmentDatabase.MMS_ID,
|
AttachmentDatabase.MMS_ID,
|
||||||
@ -192,6 +194,7 @@ public class MmsSmsDatabase extends Database {
|
|||||||
mmsColumnsPresent.add(MmsSmsColumns.ADDRESS_DEVICE_ID);
|
mmsColumnsPresent.add(MmsSmsColumns.ADDRESS_DEVICE_ID);
|
||||||
mmsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
|
mmsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
|
||||||
mmsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
|
mmsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
|
||||||
|
mmsColumnsPresent.add(MmsSmsColumns.SUBSCRIPTION_ID);
|
||||||
mmsColumnsPresent.add(MmsDatabase.MESSAGE_TYPE);
|
mmsColumnsPresent.add(MmsDatabase.MESSAGE_TYPE);
|
||||||
mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX);
|
mmsColumnsPresent.add(MmsDatabase.MESSAGE_BOX);
|
||||||
mmsColumnsPresent.add(MmsDatabase.DATE_SENT);
|
mmsColumnsPresent.add(MmsDatabase.DATE_SENT);
|
||||||
@ -222,6 +225,7 @@ public class MmsSmsDatabase extends Database {
|
|||||||
smsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
|
smsColumnsPresent.add(MmsSmsColumns.THREAD_ID);
|
||||||
smsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
|
smsColumnsPresent.add(MmsSmsColumns.RECEIPT_COUNT);
|
||||||
smsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
|
smsColumnsPresent.add(MmsSmsColumns.MISMATCHED_IDENTITIES);
|
||||||
|
smsColumnsPresent.add(MmsSmsColumns.SUBSCRIPTION_ID);
|
||||||
smsColumnsPresent.add(SmsDatabase.TYPE);
|
smsColumnsPresent.add(SmsDatabase.TYPE);
|
||||||
smsColumnsPresent.add(SmsDatabase.SUBJECT);
|
smsColumnsPresent.add(SmsDatabase.SUBJECT);
|
||||||
smsColumnsPresent.add(SmsDatabase.DATE_SENT);
|
smsColumnsPresent.add(SmsDatabase.DATE_SENT);
|
||||||
|
@ -32,6 +32,7 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
private static final String MUTE_UNTIL = "mute_until";
|
private static final String MUTE_UNTIL = "mute_until";
|
||||||
private static final String COLOR = "color";
|
private static final String COLOR = "color";
|
||||||
private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
|
private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder";
|
||||||
|
private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id";
|
||||||
|
|
||||||
public enum VibrateState {
|
public enum VibrateState {
|
||||||
DEFAULT(0), ENABLED(1), DISABLED(2);
|
DEFAULT(0), ENABLED(1), DISABLED(2);
|
||||||
@ -60,7 +61,8 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
VIBRATE + " INTEGER DEFAULT " + VibrateState.DEFAULT.getId() + ", " +
|
VIBRATE + " INTEGER DEFAULT " + VibrateState.DEFAULT.getId() + ", " +
|
||||||
MUTE_UNTIL + " INTEGER DEFAULT 0, " +
|
MUTE_UNTIL + " INTEGER DEFAULT 0, " +
|
||||||
COLOR + " TEXT DEFAULT NULL, " +
|
COLOR + " TEXT DEFAULT NULL, " +
|
||||||
SEEN_INVITE_REMINDER + " INTEGER DEFAULT 0);";
|
SEEN_INVITE_REMINDER + " INTEGER DEFAULT 0, " +
|
||||||
|
DEFAULT_SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
|
||||||
|
|
||||||
public RecipientPreferenceDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
public RecipientPreferenceDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||||
super(context, databaseHelper);
|
super(context, databaseHelper);
|
||||||
@ -95,6 +97,7 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR));
|
String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR));
|
||||||
Uri notificationUri = notification == null ? null : Uri.parse(notification);
|
Uri notificationUri = notification == null ? null : Uri.parse(notification);
|
||||||
boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
|
boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
|
||||||
|
int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID));
|
||||||
|
|
||||||
MaterialColor color;
|
MaterialColor color;
|
||||||
|
|
||||||
@ -109,7 +112,8 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
|
|
||||||
return Optional.of(new RecipientsPreferences(blocked, muteUntil,
|
return Optional.of(new RecipientsPreferences(blocked, muteUntil,
|
||||||
VibrateState.fromId(vibrateState),
|
VibrateState.fromId(vibrateState),
|
||||||
notificationUri, color, seenInviteReminder));
|
notificationUri, color, seenInviteReminder,
|
||||||
|
defaultSubscriptionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Optional.absent();
|
return Optional.absent();
|
||||||
@ -124,6 +128,13 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
updateOrInsert(recipients, values);
|
updateOrInsert(recipients, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDefaultSubscriptionId(@NonNull Recipients recipients, int defaultSubscriptionId) {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put(DEFAULT_SUBSCRIPTION_ID, defaultSubscriptionId);
|
||||||
|
updateOrInsert(recipients, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setBlocked(Recipients recipients, boolean blocked) {
|
public void setBlocked(Recipients recipients, boolean blocked) {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(BLOCK, blocked ? 1 : 0);
|
values.put(BLOCK, blocked ? 1 : 0);
|
||||||
@ -181,12 +192,14 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
private final Uri notification;
|
private final Uri notification;
|
||||||
private final MaterialColor color;
|
private final MaterialColor color;
|
||||||
private final boolean seenInviteReminder;
|
private final boolean seenInviteReminder;
|
||||||
|
private final int defaultSubscriptionId;
|
||||||
|
|
||||||
public RecipientsPreferences(boolean blocked, long muteUntil,
|
public RecipientsPreferences(boolean blocked, long muteUntil,
|
||||||
@NonNull VibrateState vibrateState,
|
@NonNull VibrateState vibrateState,
|
||||||
@Nullable Uri notification,
|
@Nullable Uri notification,
|
||||||
@Nullable MaterialColor color,
|
@Nullable MaterialColor color,
|
||||||
boolean seenInviteReminder)
|
boolean seenInviteReminder,
|
||||||
|
int defaultSubscriptionId)
|
||||||
{
|
{
|
||||||
this.blocked = blocked;
|
this.blocked = blocked;
|
||||||
this.muteUntil = muteUntil;
|
this.muteUntil = muteUntil;
|
||||||
@ -194,6 +207,7 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
this.color = color;
|
this.color = color;
|
||||||
this.seenInviteReminder = seenInviteReminder;
|
this.seenInviteReminder = seenInviteReminder;
|
||||||
|
this.defaultSubscriptionId = defaultSubscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable MaterialColor getColor() {
|
public @Nullable MaterialColor getColor() {
|
||||||
@ -219,5 +233,9 @@ public class RecipientPreferenceDatabase extends Database {
|
|||||||
public boolean hasSeenInviteReminder() {
|
public boolean hasSeenInviteReminder() {
|
||||||
return seenInviteReminder;
|
return seenInviteReminder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<Integer> getDefaultSubscriptionId() {
|
||||||
|
return defaultSubscriptionId != -1 ? Optional.of(defaultSubscriptionId) : Optional.<Integer>absent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
|||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||||
import org.thoughtcrime.securesms.util.LRUCache;
|
|
||||||
import org.whispersystems.jobqueue.JobManager;
|
import org.whispersystems.jobqueue.JobManager;
|
||||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
||||||
|
|
||||||
@ -78,7 +77,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
DATE_RECEIVED + " INTEGER, " + DATE_SENT + " INTEGER, " + PROTOCOL + " INTEGER, " + READ + " INTEGER DEFAULT 0, " +
|
DATE_RECEIVED + " INTEGER, " + DATE_SENT + " INTEGER, " + PROTOCOL + " INTEGER, " + READ + " INTEGER DEFAULT 0, " +
|
||||||
STATUS + " INTEGER DEFAULT -1," + TYPE + " INTEGER, " + REPLY_PATH_PRESENT + " INTEGER, " +
|
STATUS + " INTEGER DEFAULT -1," + TYPE + " INTEGER, " + REPLY_PATH_PRESENT + " INTEGER, " +
|
||||||
RECEIPT_COUNT + " INTEGER DEFAULT 0," + SUBJECT + " TEXT, " + BODY + " TEXT, " +
|
RECEIPT_COUNT + " INTEGER DEFAULT 0," + SUBJECT + " TEXT, " + BODY + " TEXT, " +
|
||||||
MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " + SERVICE_CENTER + " TEXT);";
|
MISMATCHED_IDENTITIES + " TEXT DEFAULT NULL, " + SERVICE_CENTER + " TEXT, " + SUBSCRIPTION_ID + " INTEGER DEFAULT -1);";
|
||||||
|
|
||||||
public static final String[] CREATE_INDEXS = {
|
public static final String[] CREATE_INDEXS = {
|
||||||
"CREATE INDEX IF NOT EXISTS sms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
|
"CREATE INDEX IF NOT EXISTS sms_thread_id_index ON " + TABLE_NAME + " (" + THREAD_ID + ");",
|
||||||
@ -95,7 +94,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
DATE_SENT + " AS " + NORMALIZED_DATE_SENT,
|
DATE_SENT + " AS " + NORMALIZED_DATE_SENT,
|
||||||
PROTOCOL, READ, STATUS, TYPE,
|
PROTOCOL, READ, STATUS, TYPE,
|
||||||
REPLY_PATH_PRESENT, SUBJECT, BODY, SERVICE_CENTER, RECEIPT_COUNT,
|
REPLY_PATH_PRESENT, SUBJECT, BODY, SERVICE_CENTER, RECEIPT_COUNT,
|
||||||
MISMATCHED_IDENTITIES
|
MISMATCHED_IDENTITIES, SUBSCRIPTION_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final EarlyReceiptCache earlyReceiptCache = new EarlyReceiptCache();
|
private static final EarlyReceiptCache earlyReceiptCache = new EarlyReceiptCache();
|
||||||
@ -451,6 +450,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
values.put(DATE_SENT, message.getSentTimestampMillis());
|
values.put(DATE_SENT, message.getSentTimestampMillis());
|
||||||
values.put(PROTOCOL, message.getProtocol());
|
values.put(PROTOCOL, message.getProtocol());
|
||||||
values.put(READ, unread ? 0 : 1);
|
values.put(READ, unread ? 0 : 1);
|
||||||
|
values.put(SUBSCRIPTION_ID, message.getSubscriptionId());
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(message.getPseudoSubject()))
|
if (!TextUtils.isEmpty(message.getPseudoSubject()))
|
||||||
values.put(SUBJECT, message.getPseudoSubject());
|
values.put(SUBJECT, message.getPseudoSubject());
|
||||||
@ -497,6 +497,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
contentValues.put(DATE_SENT, date);
|
contentValues.put(DATE_SENT, date);
|
||||||
contentValues.put(READ, 1);
|
contentValues.put(READ, 1);
|
||||||
contentValues.put(TYPE, type);
|
contentValues.put(TYPE, type);
|
||||||
|
contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(date, canonicalizeNumber(context, address)));
|
contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(date, canonicalizeNumber(context, address)));
|
||||||
@ -663,6 +664,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
|
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
|
||||||
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.RECEIPT_COUNT));
|
int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.RECEIPT_COUNT));
|
||||||
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
|
String mismatchDocument = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.MISMATCHED_IDENTITIES));
|
||||||
|
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.SUBSCRIPTION_ID));
|
||||||
|
|
||||||
List<IdentityKeyMismatch> mismatches = getMismatches(mismatchDocument);
|
List<IdentityKeyMismatch> mismatches = getMismatches(mismatchDocument);
|
||||||
Recipients recipients = getRecipientsFor(address);
|
Recipients recipients = getRecipientsFor(address);
|
||||||
@ -672,7 +674,7 @@ public class SmsDatabase extends MessagingDatabase {
|
|||||||
recipients.getPrimaryRecipient(),
|
recipients.getPrimaryRecipient(),
|
||||||
addressDeviceId,
|
addressDeviceId,
|
||||||
dateSent, dateReceived, receiptCount, type,
|
dateSent, dateReceived, receiptCount, type,
|
||||||
threadId, status, mismatches);
|
threadId, status, mismatches, subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Recipients getRecipientsFor(String address) {
|
private Recipients getRecipientsFor(String address) {
|
||||||
|
@ -21,8 +21,8 @@ import android.support.annotation.NonNull;
|
|||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
@ -53,10 +53,10 @@ public class MediaMmsMessageRecord extends MessageRecord {
|
|||||||
@NonNull SlideDeck slideDeck,
|
@NonNull SlideDeck slideDeck,
|
||||||
int partCount, long mailbox,
|
int partCount, long mailbox,
|
||||||
List<IdentityKeyMismatch> mismatches,
|
List<IdentityKeyMismatch> mismatches,
|
||||||
List<NetworkFailure> failures)
|
List<NetworkFailure> failures, int subscriptionId)
|
||||||
{
|
{
|
||||||
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent,
|
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent,
|
||||||
dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures);
|
dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures, subscriptionId);
|
||||||
|
|
||||||
this.context = context.getApplicationContext();
|
this.context = context.getApplicationContext();
|
||||||
this.partCount = partCount;
|
this.partCount = partCount;
|
||||||
|
@ -50,13 +50,15 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
private final long id;
|
private final long id;
|
||||||
private final List<IdentityKeyMismatch> mismatches;
|
private final List<IdentityKeyMismatch> mismatches;
|
||||||
private final List<NetworkFailure> networkFailures;
|
private final List<NetworkFailure> networkFailures;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
MessageRecord(Context context, long id, Body body, Recipients recipients,
|
MessageRecord(Context context, long id, Body body, Recipients recipients,
|
||||||
Recipient individualRecipient, int recipientDeviceId,
|
Recipient individualRecipient, int recipientDeviceId,
|
||||||
long dateSent, long dateReceived, long threadId,
|
long dateSent, long dateReceived, long threadId,
|
||||||
int deliveryStatus, int receiptCount, long type,
|
int deliveryStatus, int receiptCount, long type,
|
||||||
List<IdentityKeyMismatch> mismatches,
|
List<IdentityKeyMismatch> mismatches,
|
||||||
List<NetworkFailure> networkFailures)
|
List<NetworkFailure> networkFailures,
|
||||||
|
int subscriptionId)
|
||||||
{
|
{
|
||||||
super(context, body, recipients, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
|
super(context, body, recipients, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
|
||||||
type);
|
type);
|
||||||
@ -65,6 +67,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
this.recipientDeviceId = recipientDeviceId;
|
this.recipientDeviceId = recipientDeviceId;
|
||||||
this.mismatches = mismatches;
|
this.mismatches = mismatches;
|
||||||
this.networkFailures = networkFailures;
|
this.networkFailures = networkFailures;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean isMms();
|
public abstract boolean isMms();
|
||||||
@ -195,4 +198,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||||||
return (int)getId();
|
return (int)getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,12 @@ public class NotificationMmsMessageRecord extends MessageRecord {
|
|||||||
Recipient individualRecipient, int recipientDeviceId,
|
Recipient individualRecipient, int recipientDeviceId,
|
||||||
long dateSent, long dateReceived, int receiptCount,
|
long dateSent, long dateReceived, int receiptCount,
|
||||||
long threadId, byte[] contentLocation, long messageSize,
|
long threadId, byte[] contentLocation, long messageSize,
|
||||||
long expiry, int status, byte[] transactionId, long mailbox)
|
long expiry, int status, byte[] transactionId, long mailbox,
|
||||||
|
int subscriptionId)
|
||||||
{
|
{
|
||||||
super(context, id, new Body("", true), recipients, individualRecipient, recipientDeviceId,
|
super(context, id, new Body("", true), recipients, individualRecipient, recipientDeviceId,
|
||||||
dateSent, dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox,
|
dateSent, dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox,
|
||||||
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>());
|
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>(), subscriptionId);
|
||||||
|
|
||||||
this.contentLocation = contentLocation;
|
this.contentLocation = contentLocation;
|
||||||
this.messageSize = messageSize;
|
this.messageSize = messageSize;
|
||||||
|
@ -47,11 +47,12 @@ public class SmsMessageRecord extends MessageRecord {
|
|||||||
long dateSent, long dateReceived,
|
long dateSent, long dateReceived,
|
||||||
int receiptCount,
|
int receiptCount,
|
||||||
long type, long threadId,
|
long type, long threadId,
|
||||||
int status, List<IdentityKeyMismatch> mismatches)
|
int status, List<IdentityKeyMismatch> mismatches,
|
||||||
|
int subscriptionId)
|
||||||
{
|
{
|
||||||
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
|
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
|
||||||
dateSent, dateReceived, threadId, status, receiptCount, type,
|
dateSent, dateReceived, threadId, status, receiptCount, type,
|
||||||
mismatches, new LinkedList<NetworkFailure>());
|
mismatches, new LinkedList<NetworkFailure>(), subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getType() {
|
public long getType() {
|
||||||
|
@ -9,9 +9,9 @@ import org.thoughtcrime.securesms.attachments.Attachment;
|
|||||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||||
|
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|
||||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||||
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
import org.thoughtcrime.securesms.mms.ApnUnavailableException;
|
||||||
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||||
@ -35,7 +35,6 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import ws.com.google.android.mms.ContentType;
|
|
||||||
import ws.com.google.android.mms.MmsException;
|
import ws.com.google.android.mms.MmsException;
|
||||||
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
||||||
import ws.com.google.android.mms.pdu.NotificationInd;
|
import ws.com.google.android.mms.pdu.NotificationInd;
|
||||||
@ -76,7 +75,7 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
@Override
|
@Override
|
||||||
public void onRun(MasterSecret masterSecret) {
|
public void onRun(MasterSecret masterSecret) {
|
||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
Optional<NotificationInd> notification = database.getNotification(messageId);
|
Optional<Pair<NotificationInd, Integer>> notification = database.getNotification(messageId);
|
||||||
|
|
||||||
if (!notification.isPresent()) {
|
if (!notification.isPresent()) {
|
||||||
Log.w(TAG, "No notification for ID: " + messageId);
|
Log.w(TAG, "No notification for ID: " + messageId);
|
||||||
@ -84,22 +83,24 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (notification.get().getContentLocation() == null) {
|
if (notification.get().first.getContentLocation() == null) {
|
||||||
throw new MmsException("Notification content location was null.");
|
throw new MmsException("Notification content location was null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
|
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
|
||||||
|
|
||||||
String contentLocation = new String(notification.get().getContentLocation());
|
String contentLocation = new String(notification.get().first.getContentLocation());
|
||||||
byte[] transactionId = notification.get().getTransactionId();
|
byte[] transactionId = notification.get().first.getTransactionId();
|
||||||
|
|
||||||
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
|
Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost());
|
||||||
|
|
||||||
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId);
|
RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().second);
|
||||||
|
|
||||||
if (retrieveConf == null) {
|
if (retrieveConf == null) {
|
||||||
throw new MmsException("RetrieveConf was null");
|
throw new MmsException("RetrieveConf was null");
|
||||||
}
|
}
|
||||||
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf);
|
|
||||||
|
storeRetrievedMms(masterSecret, contentLocation, messageId, threadId, retrieveConf, notification.get().second);
|
||||||
} catch (ApnUnavailableException e) {
|
} catch (ApnUnavailableException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
|
handleDownloadError(masterSecret, messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE,
|
||||||
@ -146,7 +147,8 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void storeRetrievedMms(MasterSecret masterSecret, String contentLocation,
|
private void storeRetrievedMms(MasterSecret masterSecret, String contentLocation,
|
||||||
long messageId, long threadId, RetrieveConf retrieved)
|
long messageId, long threadId, RetrieveConf retrieved,
|
||||||
|
int subscriptionId)
|
||||||
throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
|
throws MmsException, NoSessionException, DuplicateMessageException, InvalidMessageException,
|
||||||
LegacyMessageException
|
LegacyMessageException
|
||||||
{
|
{
|
||||||
@ -192,7 +194,7 @@ public class MmsDownloadJob extends MasterSecretJob {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments);
|
IncomingMediaMessage message = new IncomingMediaMessage(from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId);
|
||||||
|
|
||||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
|
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
|
||||||
message, contentLocation, threadId);
|
message, contentLocation, threadId);
|
||||||
|
@ -19,16 +19,20 @@ import ws.com.google.android.mms.pdu.PduParser;
|
|||||||
|
|
||||||
public class MmsReceiveJob extends ContextJob {
|
public class MmsReceiveJob extends ContextJob {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final String TAG = MmsReceiveJob.class.getSimpleName();
|
private static final String TAG = MmsReceiveJob.class.getSimpleName();
|
||||||
|
|
||||||
private final byte[] data;
|
private final byte[] data;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
public MmsReceiveJob(Context context, byte[] data) {
|
public MmsReceiveJob(Context context, byte[] data, int subscriptionId) {
|
||||||
super(context, JobParameters.newBuilder()
|
super(context, JobParameters.newBuilder()
|
||||||
.withWakeLock(true)
|
.withWakeLock(true)
|
||||||
.withPersistence().create());
|
.withPersistence().create());
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,7 +58,7 @@ public class MmsReceiveJob extends ContextJob {
|
|||||||
|
|
||||||
if (isNotification(pdu) && !isBlocked(pdu)) {
|
if (isNotification(pdu) && !isBlocked(pdu)) {
|
||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu);
|
Pair<Long, Long> messageAndThreadId = database.insertMessageInbox((NotificationInd)pdu, subscriptionId);
|
||||||
|
|
||||||
Log.w(TAG, "Inserted received MMS notification...");
|
Log.w(TAG, "Inserted received MMS notification...");
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.mms.MmsSendResult;
|
|||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||||
@ -25,12 +24,9 @@ import org.thoughtcrime.securesms.util.Hex;
|
|||||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||||
import org.thoughtcrime.securesms.util.SmilUtil;
|
import org.thoughtcrime.securesms.util.SmilUtil;
|
||||||
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.jobqueue.JobParameters;
|
import org.whispersystems.jobqueue.JobParameters;
|
||||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||||
import org.whispersystems.textsecure.api.util.InvalidNumberException;
|
|
||||||
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -83,7 +79,7 @@ public class MmsSendJob extends SendJob {
|
|||||||
validateDestinations(message, pdu);
|
validateDestinations(message, pdu);
|
||||||
|
|
||||||
final byte[] pduBytes = getPduBytes(pdu);
|
final byte[] pduBytes = getPduBytes(pdu);
|
||||||
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes);
|
final SendConf sendConf = new CompatMmsConnection(context).send(pduBytes, message.getSubscriptionId());
|
||||||
final MmsSendResult result = getSendResult(sendConf, pdu);
|
final MmsSendResult result = getSendResult(sendConf, pdu);
|
||||||
|
|
||||||
database.markAsSent(messageId);
|
database.markAsSent(messageId);
|
||||||
|
@ -261,7 +261,7 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
|
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret, envelope.getSource(),
|
||||||
localNumber, message.getTimestamp(),
|
localNumber, message.getTimestamp(), -1,
|
||||||
Optional.fromNullable(envelope.getRelay()),
|
Optional.fromNullable(envelope.getRelay()),
|
||||||
message.getBody(),
|
message.getBody(),
|
||||||
message.getGroupInfo(),
|
message.getGroupInfo(),
|
||||||
@ -293,7 +293,7 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
Recipients recipients = getSyncMessageDestination(message);
|
Recipients recipients = getSyncMessageDestination(message);
|
||||||
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
|
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
|
||||||
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
|
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
|
||||||
message.getTimestamp(), ThreadDatabase.DistributionTypes.DEFAULT);
|
message.getTimestamp(), -1, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||||
|
|
||||||
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
|
mediaMessage = new OutgoingSecureMediaMessage(mediaMessage);
|
||||||
|
|
||||||
@ -350,7 +350,7 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||||
Recipients recipients = getSyncMessageDestination(message);
|
Recipients recipients = getSyncMessageDestination(message);
|
||||||
String body = message.getMessage().getBody().or("");
|
String body = message.getMessage().getBody().or("");
|
||||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body);
|
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body, -1);
|
||||||
|
|
||||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||||
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp());
|
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp());
|
||||||
|
@ -23,17 +23,21 @@ import java.util.List;
|
|||||||
|
|
||||||
public class SmsReceiveJob extends ContextJob {
|
public class SmsReceiveJob extends ContextJob {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private static final String TAG = SmsReceiveJob.class.getSimpleName();
|
private static final String TAG = SmsReceiveJob.class.getSimpleName();
|
||||||
|
|
||||||
private final Object[] pdus;
|
private final Object[] pdus;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
public SmsReceiveJob(Context context, Object[] pdus) {
|
public SmsReceiveJob(Context context, Object[] pdus, int subscriptionId) {
|
||||||
super(context, JobParameters.newBuilder()
|
super(context, JobParameters.newBuilder()
|
||||||
.withPersistence()
|
.withPersistence()
|
||||||
.withWakeLock(true)
|
.withWakeLock(true)
|
||||||
.create());
|
.create());
|
||||||
|
|
||||||
this.pdus = pdus;
|
this.pdus = pdus;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,7 +45,7 @@ public class SmsReceiveJob extends ContextJob {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRun() {
|
public void onRun() {
|
||||||
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus);
|
Optional<IncomingTextMessage> message = assembleMessageFragments(pdus, subscriptionId);
|
||||||
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
|
MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
|
||||||
|
|
||||||
MasterSecretUnion masterSecretUnion;
|
MasterSecretUnion masterSecretUnion;
|
||||||
@ -95,11 +99,11 @@ public class SmsReceiveJob extends ContextJob {
|
|||||||
return messageAndThreadId;
|
return messageAndThreadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus) {
|
private Optional<IncomingTextMessage> assembleMessageFragments(Object[] pdus, int subscriptionId) {
|
||||||
List<IncomingTextMessage> messages = new LinkedList<>();
|
List<IncomingTextMessage> messages = new LinkedList<>();
|
||||||
|
|
||||||
for (Object pdu : pdus) {
|
for (Object pdu : pdus) {
|
||||||
messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu)));
|
messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdu), subscriptionId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messages.isEmpty()) {
|
if (messages.isEmpty()) {
|
||||||
|
@ -4,6 +4,7 @@ import android.app.PendingIntent;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
import android.telephony.SmsManager;
|
import android.telephony.SmsManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -105,7 +106,7 @@ public class SmsSendJob extends SendJob {
|
|||||||
// catching it and marking the message as a failure. That way at least it doesn't
|
// catching it and marking the message as a failure. That way at least it doesn't
|
||||||
// repeatedly crash every time you start the app.
|
// repeatedly crash every time you start the app.
|
||||||
try {
|
try {
|
||||||
SmsManager.getDefault().sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
|
getSmsManagerFor(message.getSubscriptionId()).sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
Log.w(TAG, npe);
|
Log.w(TAG, npe);
|
||||||
Log.w(TAG, "Recipient: " + recipient);
|
Log.w(TAG, "Recipient: " + recipient);
|
||||||
@ -113,7 +114,7 @@ public class SmsSendJob extends SendJob {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
for (int i=0;i<messages.size();i++) {
|
for (int i=0;i<messages.size();i++) {
|
||||||
SmsManager.getDefault().sendTextMessage(recipient, null, messages.get(i),
|
getSmsManagerFor(message.getSubscriptionId()).sendTextMessage(recipient, null, messages.get(i),
|
||||||
sentIntents.get(i),
|
sentIntents.get(i),
|
||||||
deliveredIntents == null ? null : deliveredIntents.get(i));
|
deliveredIntents == null ? null : deliveredIntents.get(i));
|
||||||
}
|
}
|
||||||
@ -179,6 +180,14 @@ public class SmsSendJob extends SendJob {
|
|||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SmsManager getSmsManagerFor(int subscriptionId) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 22 && subscriptionId != -1) {
|
||||||
|
return SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
|
||||||
|
} else {
|
||||||
|
return SmsManager.getDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static JobParameters constructParameters(Context context, String name) {
|
private static JobParameters constructParameters(Context context, String name) {
|
||||||
JobParameters.Builder builder = JobParameters.newBuilder()
|
JobParameters.Builder builder = JobParameters.newBuilder()
|
||||||
.withPersistence()
|
.withPersistence()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.mms;
|
package org.thoughtcrime.securesms.mms;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Build.VERSION;
|
import android.os.Build.VERSION;
|
||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
@ -26,38 +27,46 @@ public class CompatMmsConnection implements OutgoingMmsConnection, IncomingMmsCo
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public SendConf send(@NonNull byte[] pduBytes)
|
public SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
|
||||||
throws UndeliverableMessageException
|
throws UndeliverableMessageException
|
||||||
{
|
{
|
||||||
try {
|
if (subscriptionId == -1 || VERSION.SDK_INT < 22) {
|
||||||
Log.w(TAG, "Sending via legacy connection");
|
Log.w(TAG, "Sending via legacy connection");
|
||||||
return new OutgoingLegacyMmsConnection(context).send(pduBytes);
|
try {
|
||||||
|
return new OutgoingLegacyMmsConnection(context).send(pduBytes, subscriptionId);
|
||||||
} catch (UndeliverableMessageException | ApnUnavailableException e) {
|
} catch (UndeliverableMessageException | ApnUnavailableException e) {
|
||||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
Log.w(TAG, e);
|
||||||
Log.w(TAG, "Falling back to try sending via Lollipop API");
|
|
||||||
return new OutgoingLollipopMmsConnection(context).send(pduBytes);
|
|
||||||
} else {
|
|
||||||
throw new UndeliverableMessageException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
|
return new OutgoingLollipopMmsConnection(context).send(pduBytes, subscriptionId);
|
||||||
|
} else {
|
||||||
|
throw new UndeliverableMessageException("Lollipop API not available to try...");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public RetrieveConf retrieve(@NonNull String contentLocation,
|
public RetrieveConf retrieve(@NonNull String contentLocation,
|
||||||
byte[] transactionId)
|
byte[] transactionId,
|
||||||
|
int subscriptionId)
|
||||||
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
|
throws MmsException, MmsRadioException, ApnUnavailableException, IOException
|
||||||
{
|
{
|
||||||
try {
|
if (VERSION.SDK_INT < 22 || subscriptionId == -1) {
|
||||||
Log.w(TAG, "Receiving via legacy connection");
|
Log.w(TAG, "Receiving via legacy connection");
|
||||||
return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId);
|
try {
|
||||||
} catch (MmsRadioException | IOException | ApnUnavailableException e) {
|
return new IncomingLegacyMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
|
||||||
|
} catch (MmsRadioException | ApnUnavailableException | IOException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||||
Log.w(TAG, "Falling back to try receiving via Lollipop API");
|
Log.w(TAG, "Falling back to try receiving via Lollipop API");
|
||||||
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId);
|
return new IncomingLollipopMmsConnection(context).retrieve(contentLocation, transactionId, subscriptionId);
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw new IOException("Not able to use Lollipop APIs, giving up...");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class IncomingLegacyMmsConnection extends LegacyMmsConnection implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
|
public @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
|
||||||
byte[] transactionId)
|
byte[] transactionId, int subscriptionId)
|
||||||
throws MmsRadioException, ApnUnavailableException, IOException
|
throws MmsRadioException, ApnUnavailableException, IOException
|
||||||
{
|
{
|
||||||
MmsRadio radio = MmsRadio.getInstance(context);
|
MmsRadio radio = MmsRadio.getInstance(context);
|
||||||
|
@ -39,6 +39,7 @@ import ws.com.google.android.mms.pdu.PduParser;
|
|||||||
import ws.com.google.android.mms.pdu.RetrieveConf;
|
import ws.com.google.android.mms.pdu.RetrieveConf;
|
||||||
|
|
||||||
public class IncomingLollipopMmsConnection extends LollipopMmsConnection implements IncomingMmsConnection {
|
public class IncomingLollipopMmsConnection extends LollipopMmsConnection implements IncomingMmsConnection {
|
||||||
|
|
||||||
public static final String ACTION = IncomingLollipopMmsConnection.class.getCanonicalName() + "MMS_DOWNLOADED_ACTION";
|
public static final String ACTION = IncomingLollipopMmsConnection.class.getCanonicalName() + "MMS_DOWNLOADED_ACTION";
|
||||||
private static final String TAG = IncomingLollipopMmsConnection.class.getSimpleName();
|
private static final String TAG = IncomingLollipopMmsConnection.class.getSimpleName();
|
||||||
|
|
||||||
@ -58,7 +59,8 @@ public class IncomingLollipopMmsConnection extends LollipopMmsConnection impleme
|
|||||||
@Override
|
@Override
|
||||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||||
public synchronized @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
|
public synchronized @Nullable RetrieveConf retrieve(@NonNull String contentLocation,
|
||||||
byte[] transactionId) throws MmsException
|
byte[] transactionId,
|
||||||
|
int subscriptionId) throws MmsException
|
||||||
{
|
{
|
||||||
beginTransaction();
|
beginTransaction();
|
||||||
|
|
||||||
@ -66,7 +68,16 @@ public class IncomingLollipopMmsConnection extends LollipopMmsConnection impleme
|
|||||||
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
|
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
|
||||||
|
|
||||||
Log.w(TAG, "downloading multimedia from " + contentLocation + " to " + pointer.getUri());
|
Log.w(TAG, "downloading multimedia from " + contentLocation + " to " + pointer.getUri());
|
||||||
SmsManager.getDefault().downloadMultimediaMessage(getContext(),
|
|
||||||
|
SmsManager smsManager;
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= 22 && subscriptionId != -1) {
|
||||||
|
smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
|
||||||
|
} else {
|
||||||
|
smsManager = SmsManager.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
smsManager.downloadMultimediaMessage(getContext(),
|
||||||
contentLocation,
|
contentLocation,
|
||||||
pointer.getUri(),
|
pointer.getUri(),
|
||||||
null,
|
null,
|
||||||
|
@ -19,6 +19,7 @@ public class IncomingMediaMessage {
|
|||||||
private final String groupId;
|
private final String groupId;
|
||||||
private final boolean push;
|
private final boolean push;
|
||||||
private final long sentTimeMillis;
|
private final long sentTimeMillis;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
private final List<String> to = new LinkedList<>();
|
private final List<String> to = new LinkedList<>();
|
||||||
private final List<String> cc = new LinkedList<>();
|
private final List<String> cc = new LinkedList<>();
|
||||||
@ -26,13 +27,14 @@ public class IncomingMediaMessage {
|
|||||||
|
|
||||||
public IncomingMediaMessage(String from, List<String> to, List<String> cc,
|
public IncomingMediaMessage(String from, List<String> to, List<String> cc,
|
||||||
String body, long sentTimeMillis,
|
String body, long sentTimeMillis,
|
||||||
List<Attachment> attachments)
|
List<Attachment> attachments, int subscriptionId)
|
||||||
{
|
{
|
||||||
this.from = from;
|
this.from = from;
|
||||||
this.sentTimeMillis = sentTimeMillis;
|
this.sentTimeMillis = sentTimeMillis;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.groupId = null;
|
this.groupId = null;
|
||||||
this.push = false;
|
this.push = false;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
|
|
||||||
this.to.addAll(to);
|
this.to.addAll(to);
|
||||||
this.cc.addAll(cc);
|
this.cc.addAll(cc);
|
||||||
@ -43,6 +45,7 @@ public class IncomingMediaMessage {
|
|||||||
String from,
|
String from,
|
||||||
String to,
|
String to,
|
||||||
long sentTimeMillis,
|
long sentTimeMillis,
|
||||||
|
int subscriptionId,
|
||||||
Optional<String> relay,
|
Optional<String> relay,
|
||||||
Optional<String> body,
|
Optional<String> body,
|
||||||
Optional<TextSecureGroup> group,
|
Optional<TextSecureGroup> group,
|
||||||
@ -52,6 +55,7 @@ public class IncomingMediaMessage {
|
|||||||
this.from = from;
|
this.from = from;
|
||||||
this.sentTimeMillis = sentTimeMillis;
|
this.sentTimeMillis = sentTimeMillis;
|
||||||
this.body = body.orNull();
|
this.body = body.orNull();
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
|
|
||||||
if (group.isPresent()) this.groupId = GroupUtil.getEncodedId(group.get().getGroupId());
|
if (group.isPresent()) this.groupId = GroupUtil.getEncodedId(group.get().getGroupId());
|
||||||
else this.groupId = null;
|
else this.groupId = null;
|
||||||
@ -60,6 +64,10 @@ public class IncomingMediaMessage {
|
|||||||
this.attachments.addAll(PointerAttachment.forPointers(masterSecret, attachments));
|
this.attachments.addAll(PointerAttachment.forPointers(masterSecret, attachments));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getBody() {
|
public String getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
@ -9,5 +9,5 @@ import ws.com.google.android.mms.MmsException;
|
|||||||
import ws.com.google.android.mms.pdu.RetrieveConf;
|
import ws.com.google.android.mms.pdu.RetrieveConf;
|
||||||
|
|
||||||
public interface IncomingMmsConnection {
|
public interface IncomingMmsConnection {
|
||||||
@Nullable RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
|
@Nullable RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public class OutgoingLegacyMmsConnection extends LegacyMmsConnection implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException {
|
public @Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException {
|
||||||
try {
|
try {
|
||||||
MmsRadio radio = MmsRadio.getInstance(context);
|
MmsRadio radio = MmsRadio.getInstance(context);
|
||||||
|
|
||||||
|
@ -59,13 +59,23 @@ public class OutgoingLollipopMmsConnection extends LollipopMmsConnection impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||||
public @Nullable synchronized SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException {
|
public @Nullable synchronized SendConf send(@NonNull byte[] pduBytes, int subscriptionId)
|
||||||
|
throws UndeliverableMessageException
|
||||||
|
{
|
||||||
beginTransaction();
|
beginTransaction();
|
||||||
try {
|
try {
|
||||||
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
|
MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
|
||||||
Util.copy(new ByteArrayInputStream(pduBytes), pointer.getOutputStream());
|
Util.copy(new ByteArrayInputStream(pduBytes), pointer.getOutputStream());
|
||||||
|
|
||||||
SmsManager.getDefault().sendMultimediaMessage(getContext(),
|
SmsManager smsManager;
|
||||||
|
|
||||||
|
if (VERSION.SDK_INT >= 22 && subscriptionId != -1) {
|
||||||
|
smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
|
||||||
|
} else {
|
||||||
|
smsManager = SmsManager.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
smsManager.sendMultimediaMessage(getContext(),
|
||||||
pointer.getUri(),
|
pointer.getUri(),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
@ -14,9 +14,11 @@ public class OutgoingMediaMessage {
|
|||||||
protected final List<Attachment> attachments;
|
protected final List<Attachment> attachments;
|
||||||
private final long sentTimeMillis;
|
private final long sentTimeMillis;
|
||||||
private final int distributionType;
|
private final int distributionType;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
public OutgoingMediaMessage(Recipients recipients, String message,
|
public OutgoingMediaMessage(Recipients recipients, String message,
|
||||||
List<Attachment> attachments, long sentTimeMillis,
|
List<Attachment> attachments, long sentTimeMillis,
|
||||||
|
int subscriptionId,
|
||||||
int distributionType)
|
int distributionType)
|
||||||
{
|
{
|
||||||
this.recipients = recipients;
|
this.recipients = recipients;
|
||||||
@ -24,14 +26,15 @@ public class OutgoingMediaMessage {
|
|||||||
this.sentTimeMillis = sentTimeMillis;
|
this.sentTimeMillis = sentTimeMillis;
|
||||||
this.distributionType = distributionType;
|
this.distributionType = distributionType;
|
||||||
this.attachments = attachments;
|
this.attachments = attachments;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int distributionType)
|
public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int subscriptionId, int distributionType)
|
||||||
{
|
{
|
||||||
this(recipients,
|
this(recipients,
|
||||||
buildMessage(slideDeck, message),
|
buildMessage(slideDeck, message),
|
||||||
slideDeck.asAttachments(),
|
slideDeck.asAttachments(),
|
||||||
sentTimeMillis,
|
sentTimeMillis, subscriptionId,
|
||||||
distributionType);
|
distributionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +44,7 @@ public class OutgoingMediaMessage {
|
|||||||
this.distributionType = that.distributionType;
|
this.distributionType = that.distributionType;
|
||||||
this.attachments = that.attachments;
|
this.attachments = that.attachments;
|
||||||
this.sentTimeMillis = that.sentTimeMillis;
|
this.sentTimeMillis = that.sentTimeMillis;
|
||||||
|
this.subscriptionId = that.subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Recipients getRecipients() {
|
public Recipients getRecipients() {
|
||||||
@ -71,6 +75,10 @@ public class OutgoingMediaMessage {
|
|||||||
return sentTimeMillis;
|
return sentTimeMillis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
private static String buildMessage(SlideDeck slideDeck, String message) {
|
private static String buildMessage(SlideDeck slideDeck, String message) {
|
||||||
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
|
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
|
||||||
return slideDeck.getBody() + "\n\n" + message;
|
return slideDeck.getBody() + "\n\n" + message;
|
||||||
|
@ -8,5 +8,5 @@ import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
|||||||
import ws.com.google.android.mms.pdu.SendConf;
|
import ws.com.google.android.mms.pdu.SendConf;
|
||||||
|
|
||||||
public interface OutgoingMmsConnection {
|
public interface OutgoingMmsConnection {
|
||||||
@Nullable SendConf send(@NonNull byte[] pduBytes) throws UndeliverableMessageException;
|
@Nullable SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public class OutgoingSecureMediaMessage extends OutgoingMediaMessage {
|
|||||||
long sentTimeMillis,
|
long sentTimeMillis,
|
||||||
int distributionType)
|
int distributionType)
|
||||||
{
|
{
|
||||||
super(recipients, body, attachments, sentTimeMillis, distributionType);
|
super(recipients, body, attachments, sentTimeMillis, -1, distributionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingSecureMediaMessage(OutgoingMediaMessage base) {
|
public OutgoingSecureMediaMessage(OutgoingMediaMessage base) {
|
||||||
|
@ -27,16 +27,16 @@ import android.support.v4.app.RemoteInput;
|
|||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import ws.com.google.android.mms.pdu.PduBody;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the response text from the Wearable Device and sends an message as a reply
|
* Get the response text from the Wearable Device and sends an message as a reply
|
||||||
*/
|
*/
|
||||||
@ -66,11 +66,14 @@ public class WearReplyReceiver extends MasterSecretBroadcastReceiver {
|
|||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
long threadId;
|
long threadId;
|
||||||
|
|
||||||
|
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipientIds);
|
||||||
|
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||||
|
|
||||||
if (recipients.isGroupRecipient()) {
|
if (recipients.isGroupRecipient()) {
|
||||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), 0);
|
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, 0);
|
||||||
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
|
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
|
||||||
} else {
|
} else {
|
||||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString());
|
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), subscriptionId);
|
||||||
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
|
threadId = MessageSender.send(context, masterSecret, reply, -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public class RecipientFactory {
|
|||||||
return provider.getRecipients(context, recipientIds, asynchronous);
|
return provider.getRecipients(context, recipientIds, asynchronous);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
|
public static @NonNull Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
|
||||||
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
|
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
|
||||||
List<String> ids = new LinkedList<>();
|
List<String> ids = new LinkedList<>();
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ public class RecipientFactory {
|
|||||||
return getRecipientsForIds(context, ids, asynchronous);
|
return getRecipientsForIds(context, ids, asynchronous);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Recipients getRecipientsFromStrings(@NonNull Context context, @NonNull List<String> numbers, boolean asynchronous) {
|
public static @NonNull Recipients getRecipientsFromStrings(@NonNull Context context, @NonNull List<String> numbers, boolean asynchronous) {
|
||||||
List<String> ids = new LinkedList<>();
|
List<String> ids = new LinkedList<>();
|
||||||
|
|
||||||
for (String number : numbers) {
|
for (String number : numbers) {
|
||||||
@ -95,7 +95,7 @@ public class RecipientFactory {
|
|||||||
return getRecipientsForIds(context, ids, asynchronous);
|
return getRecipientsForIds(context, ids, asynchronous);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Recipients getRecipientsForIds(Context context, List<String> idStrings, boolean asynchronous) {
|
private static @NonNull Recipients getRecipientsForIds(Context context, List<String> idStrings, boolean asynchronous) {
|
||||||
long[] ids = new long[idStrings.size()];
|
long[] ids = new long[idStrings.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
@ -63,9 +63,11 @@ public class MmsListener extends BroadcastReceiver {
|
|||||||
isRelevant(context, intent)))
|
isRelevant(context, intent)))
|
||||||
{
|
{
|
||||||
Log.w(TAG, "Relevant!");
|
Log.w(TAG, "Relevant!");
|
||||||
|
int subscriptionId = intent.getExtras().getInt("subscription", -1);
|
||||||
|
|
||||||
ApplicationContext.getInstance(context)
|
ApplicationContext.getInstance(context)
|
||||||
.getJobManager()
|
.getJobManager()
|
||||||
.add(new MmsReceiveJob(context, intent.getByteArrayExtra("data")));
|
.add(new MmsReceiveJob(context, intent.getByteArrayExtra("data"), subscriptionId));
|
||||||
|
|
||||||
abortBroadcast();
|
abortBroadcast();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
@ -17,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
|||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
@ -49,14 +52,17 @@ public class QuickResponseService extends MasterSecretIntentService {
|
|||||||
if(numbers.contains("%")){
|
if(numbers.contains("%")){
|
||||||
numbers = URLDecoder.decode(numbers);
|
numbers = URLDecoder.decode(numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
Recipients recipients = RecipientFactory.getRecipientsFromString(this, numbers, false);
|
Recipients recipients = RecipientFactory.getRecipientsFromString(this, numbers, false);
|
||||||
|
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(this).getRecipientsPreferences(recipients.getIds());
|
||||||
|
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(content)) {
|
if (!TextUtils.isEmpty(content)) {
|
||||||
if (recipients.isSingleRecipient()) {
|
if (recipients.isSingleRecipient()) {
|
||||||
MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipients, content), -1, false);
|
MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipients, content, subscriptionId), -1, false);
|
||||||
} else {
|
} else {
|
||||||
MessageSender.send(this, masterSecret, new OutgoingMediaMessage(recipients, new SlideDeck(), content, System.currentTimeMillis(),
|
MessageSender.send(this, masterSecret, new OutgoingMediaMessage(recipients, new SlideDeck(), content, System.currentTimeMillis(),
|
||||||
ThreadDatabase.DistributionTypes.DEFAULT), -1, false);
|
subscriptionId, ThreadDatabase.DistributionTypes.DEFAULT), -1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (URISyntaxException e) {
|
} catch (URISyntaxException e) {
|
||||||
|
@ -84,16 +84,6 @@ public class SmsListener extends BroadcastReceiver {
|
|||||||
return bodyBuilder.toString();
|
return bodyBuilder.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// private ArrayList<IncomingTextMessage> getAsTextMessages(Intent intent) {
|
|
||||||
// Object[] pdus = (Object[])intent.getExtras().get("pdus");
|
|
||||||
// ArrayList<IncomingTextMessage> messages = new ArrayList<IncomingTextMessage>(pdus.length);
|
|
||||||
//
|
|
||||||
// for (int i=0;i<pdus.length;i++)
|
|
||||||
// messages.add(new IncomingTextMessage(SmsMessage.createFromPdu((byte[])pdus[i])));
|
|
||||||
//
|
|
||||||
// return messages;
|
|
||||||
// }
|
|
||||||
|
|
||||||
private boolean isRelevant(Context context, Intent intent) {
|
private boolean isRelevant(Context context, Intent intent) {
|
||||||
SmsMessage message = getSmsMessageFromIntent(intent);
|
SmsMessage message = getSmsMessageFromIntent(intent);
|
||||||
String messageBody = getSmsMessageBodyFromIntent(intent);
|
String messageBody = getSmsMessageBodyFromIntent(intent);
|
||||||
@ -165,13 +155,9 @@ public class SmsListener extends BroadcastReceiver {
|
|||||||
(intent.getAction().equals(SMS_RECEIVED_ACTION)) && isRelevant(context, intent))
|
(intent.getAction().equals(SMS_RECEIVED_ACTION)) && isRelevant(context, intent))
|
||||||
{
|
{
|
||||||
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
|
Object[] pdus = (Object[]) intent.getExtras().get("pdus");
|
||||||
ApplicationContext.getInstance(context).getJobManager().add(new SmsReceiveJob(context, pdus));
|
int subscriptionId = intent.getExtras().getInt("subscription", -1);
|
||||||
|
|
||||||
// Intent receivedIntent = new Intent(context, SendReceiveService.class);
|
ApplicationContext.getInstance(context).getJobManager().add(new SmsReceiveJob(context, pdus, subscriptionId));
|
||||||
// receivedIntent.setAction(SendReceiveService.RECEIVE_SMS_ACTION);
|
|
||||||
// receivedIntent.putExtra("ResultCode", this.getResultCode());
|
|
||||||
// receivedIntent.putParcelableArrayListExtra("text_messages",getAsTextMessages(intent));
|
|
||||||
// context.startService(receivedIntent);
|
|
||||||
|
|
||||||
abortBroadcast();
|
abortBroadcast();
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,9 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
private final long sentTimestampMillis;
|
private final long sentTimestampMillis;
|
||||||
private final String groupId;
|
private final String groupId;
|
||||||
private final boolean push;
|
private final boolean push;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
public IncomingTextMessage(SmsMessage message) {
|
public IncomingTextMessage(SmsMessage message, int subscriptionId) {
|
||||||
this.message = message.getDisplayMessageBody();
|
this.message = message.getDisplayMessageBody();
|
||||||
this.sender = message.getDisplayOriginatingAddress();
|
this.sender = message.getDisplayOriginatingAddress();
|
||||||
this.senderDeviceId = TextSecureAddress.DEFAULT_DEVICE_ID;
|
this.senderDeviceId = TextSecureAddress.DEFAULT_DEVICE_ID;
|
||||||
@ -45,6 +46,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.replyPathPresent = message.isReplyPathPresent();
|
this.replyPathPresent = message.isReplyPathPresent();
|
||||||
this.pseudoSubject = message.getPseudoSubject();
|
this.pseudoSubject = message.getPseudoSubject();
|
||||||
this.sentTimestampMillis = message.getTimestampMillis();
|
this.sentTimestampMillis = message.getTimestampMillis();
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
this.groupId = null;
|
this.groupId = null;
|
||||||
this.push = false;
|
this.push = false;
|
||||||
}
|
}
|
||||||
@ -61,6 +63,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.pseudoSubject = "";
|
this.pseudoSubject = "";
|
||||||
this.sentTimestampMillis = sentTimestampMillis;
|
this.sentTimestampMillis = sentTimestampMillis;
|
||||||
this.push = true;
|
this.push = true;
|
||||||
|
this.subscriptionId = -1;
|
||||||
|
|
||||||
if (group.isPresent()) {
|
if (group.isPresent()) {
|
||||||
this.groupId = GroupUtil.getEncodedId(group.get().getGroupId());
|
this.groupId = GroupUtil.getEncodedId(group.get().getGroupId());
|
||||||
@ -80,6 +83,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.sentTimestampMillis = in.readLong();
|
this.sentTimestampMillis = in.readLong();
|
||||||
this.groupId = in.readString();
|
this.groupId = in.readString();
|
||||||
this.push = (in.readInt() == 1);
|
this.push = (in.readInt() == 1);
|
||||||
|
this.subscriptionId = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
||||||
@ -93,6 +97,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.sentTimestampMillis = base.getSentTimestampMillis();
|
this.sentTimestampMillis = base.getSentTimestampMillis();
|
||||||
this.groupId = base.getGroupId();
|
this.groupId = base.getGroupId();
|
||||||
this.push = base.isPush();
|
this.push = base.isPush();
|
||||||
|
this.subscriptionId = base.getSubscriptionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
|
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
|
||||||
@ -112,6 +117,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
||||||
this.groupId = fragments.get(0).getGroupId();
|
this.groupId = fragments.get(0).getGroupId();
|
||||||
this.push = fragments.get(0).isPush();
|
this.push = fragments.get(0).isPush();
|
||||||
|
this.subscriptionId = fragments.get(0).getSubscriptionId();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IncomingTextMessage(String sender, String groupId)
|
protected IncomingTextMessage(String sender, String groupId)
|
||||||
@ -126,6 +132,11 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
this.sentTimestampMillis = System.currentTimeMillis();
|
this.sentTimestampMillis = System.currentTimeMillis();
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
this.push = true;
|
this.push = true;
|
||||||
|
this.subscriptionId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSentTimestampMillis() {
|
public long getSentTimestampMillis() {
|
||||||
@ -209,5 +220,6 @@ public class IncomingTextMessage implements Parcelable {
|
|||||||
out.writeLong(sentTimestampMillis);
|
out.writeLong(sentTimestampMillis);
|
||||||
out.writeString(groupId);
|
out.writeString(groupId);
|
||||||
out.writeInt(push ? 1 : 0);
|
out.writeInt(push ? 1 : 0);
|
||||||
|
out.writeInt(subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,8 @@ public class MessageSender {
|
|||||||
allocatedThreadId = threadId;
|
allocatedThreadId = threadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), allocatedThreadId, message, forceSms, System.currentTimeMillis());
|
long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), allocatedThreadId,
|
||||||
|
message, forceSms, System.currentTimeMillis());
|
||||||
|
|
||||||
sendTextMessage(context, recipients, forceSms, keyExchange, messageId);
|
sendTextMessage(context, recipients, forceSms, keyExchange, messageId);
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
|||||||
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
|
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
|
||||||
|
|
||||||
public OutgoingEncryptedMessage(Recipients recipients, String body) {
|
public OutgoingEncryptedMessage(Recipients recipients, String body) {
|
||||||
super(recipients, body);
|
super(recipients, body, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutgoingEncryptedMessage(OutgoingEncryptedMessage base, String body) {
|
private OutgoingEncryptedMessage(OutgoingEncryptedMessage base, String body) {
|
||||||
|
@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
|||||||
public class OutgoingKeyExchangeMessage extends OutgoingTextMessage {
|
public class OutgoingKeyExchangeMessage extends OutgoingTextMessage {
|
||||||
|
|
||||||
public OutgoingKeyExchangeMessage(Recipients recipients, String message) {
|
public OutgoingKeyExchangeMessage(Recipients recipients, String message) {
|
||||||
super(recipients, message);
|
super(recipients, message, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutgoingKeyExchangeMessage(OutgoingKeyExchangeMessage base, String body) {
|
private OutgoingKeyExchangeMessage(OutgoingKeyExchangeMessage base, String body) {
|
||||||
|
@ -7,17 +7,24 @@ public class OutgoingTextMessage {
|
|||||||
|
|
||||||
private final Recipients recipients;
|
private final Recipients recipients;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
private final int subscriptionId;
|
||||||
|
|
||||||
public OutgoingTextMessage(Recipients recipients, String message) {
|
public OutgoingTextMessage(Recipients recipients, String message, int subscriptionId) {
|
||||||
this.recipients = recipients;
|
this.recipients = recipients;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected OutgoingTextMessage(OutgoingTextMessage base, String body) {
|
protected OutgoingTextMessage(OutgoingTextMessage base, String body) {
|
||||||
this.recipients = base.getRecipients();
|
this.recipients = base.getRecipients();
|
||||||
|
this.subscriptionId = base.getSubscriptionId();
|
||||||
this.message = body;
|
this.message = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMessageBody() {
|
public String getMessageBody() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
@ -48,9 +55,9 @@ public class OutgoingTextMessage {
|
|||||||
} else if (record.isKeyExchange()) {
|
} else if (record.isKeyExchange()) {
|
||||||
return new OutgoingKeyExchangeMessage(record.getRecipients(), record.getBody().getBody());
|
return new OutgoingKeyExchangeMessage(record.getRecipients(), record.getBody().getBody());
|
||||||
} else if (record.isEndSession()) {
|
} else if (record.isEndSession()) {
|
||||||
return new OutgoingEndSessionMessage(new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody()));
|
return new OutgoingEndSessionMessage(new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody(), -1));
|
||||||
} else {
|
} else {
|
||||||
return new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody());
|
return new OutgoingTextMessage(record.getRecipients(), record.getBody().getBody(), record.getSubscriptionId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.thoughtcrime.securesms.util.dualsim;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
|
public class SubscriptionInfoCompat {
|
||||||
|
|
||||||
|
private final int subscriptionId;
|
||||||
|
private final @Nullable CharSequence displayName;
|
||||||
|
|
||||||
|
public SubscriptionInfoCompat(int subscriptionId, @Nullable CharSequence displayName) {
|
||||||
|
this.subscriptionId = subscriptionId;
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NonNull CharSequence getDisplayName() {
|
||||||
|
return displayName != null ? displayName : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSubscriptionId() {
|
||||||
|
return subscriptionId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package org.thoughtcrime.securesms.util.dualsim;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.telephony.SubscriptionInfo;
|
||||||
|
import android.telephony.SubscriptionManager;
|
||||||
|
|
||||||
|
import org.whispersystems.libaxolotl.util.guava.Optional;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SubscriptionManagerCompat {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
public SubscriptionManagerCompat(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<SubscriptionInfoCompat> getActiveSubscriptionInfo(int subscriptionId) {
|
||||||
|
if (Build.VERSION.SDK_INT < 22) {
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
SubscriptionInfo subscriptionInfo = SubscriptionManager.from(context).getActiveSubscriptionInfo(subscriptionId);
|
||||||
|
|
||||||
|
if (subscriptionInfo != null) {
|
||||||
|
return Optional.of(new SubscriptionInfoCompat(subscriptionId, subscriptionInfo.getDisplayName()));
|
||||||
|
} else {
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NonNull List<SubscriptionInfoCompat> getActiveSubscriptionInfoList() {
|
||||||
|
if (Build.VERSION.SDK_INT < 22) {
|
||||||
|
return new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SubscriptionInfo> subscriptionInfos = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
|
||||||
|
|
||||||
|
if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
|
||||||
|
return new LinkedList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<SubscriptionInfoCompat> compatList = new LinkedList<>();
|
||||||
|
|
||||||
|
for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
|
||||||
|
compatList.add(new SubscriptionInfoCompat(subscriptionInfo.getSubscriptionId(),
|
||||||
|
subscriptionInfo.getDisplayName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return compatList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user