diff --git a/build.gradle b/build.gradle
index 4e9c4d16ab..73578a76c8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -98,6 +98,8 @@ android {
defaultConfig {
minSdkVersion 9
targetSdkVersion 19
+
+ buildConfigField "long", "BUILD_TIMESTAMP", System.currentTimeMillis() + "L"
}
compileOptions {
@@ -105,44 +107,39 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
- android {
- buildTypes {
- debug {
- minifyEnabled false
- }
- release {
- minifyEnabled false
- }
- }
-
- sourceSets {
- main {
- manifest.srcFile 'AndroidManifest.xml'
- java.srcDirs = ['src']
- resources.srcDirs = ['src']
- aidl.srcDirs = ['src']
- renderscript.srcDirs = ['src']
- res.srcDirs = ['res']
- assets.srcDirs = ['assets']
- }
- androidTest {
- java.srcDirs = ['androidTest/java']
- resources.srcDirs = ['androidTest/java']
- aidl.srcDirs = ['androidTest/java']
- renderscript.srcDirs = ['androidTest/java']
- }
- }
- }
-
signingConfigs {
release
}
+
buildTypes {
+ debug {
+ minifyEnabled false
+ }
release {
+ minifyEnabled false
signingConfig signingConfigs.release
}
}
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['src']
+ resources.srcDirs = ['src']
+ aidl.srcDirs = ['src']
+ renderscript.srcDirs = ['src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ }
+ androidTest {
+ java.srcDirs = ['androidTest/java']
+ resources.srcDirs = ['androidTest/java']
+ aidl.srcDirs = ['androidTest/java']
+ renderscript.srcDirs = ['androidTest/java']
+ }
+ }
+
+
lintOptions {
abortOnError false
}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d4850af9e1..57dab652ed 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -816,6 +816,8 @@
Mark all read
+ Your build of TextSecure has expired!
+ Messages will no longer send successfully, please update to the most recent version.
Use as default SMS app?
TextSecure is not currently your default SMS app.
Import system SMS?
diff --git a/src/org/thoughtcrime/securesms/ConversationListFragment.java b/src/org/thoughtcrime/securesms/ConversationListFragment.java
index b72fc2f48d..1178c9e96d 100644
--- a/src/org/thoughtcrime/securesms/ConversationListFragment.java
+++ b/src/org/thoughtcrime/securesms/ConversationListFragment.java
@@ -43,6 +43,7 @@ import android.widget.AdapterView;
import android.widget.ListView;
import org.thoughtcrime.securesms.components.DefaultSmsReminder;
+import org.thoughtcrime.securesms.components.ExpiredBuildReminder;
import org.thoughtcrime.securesms.components.PushRegistrationReminder;
import org.thoughtcrime.securesms.components.ReminderView;
import org.thoughtcrime.securesms.components.SystemSmsImportReminder;
@@ -163,7 +164,9 @@ public class ConversationListFragment extends ListFragment
}
private void initializeReminders() {
- if (DefaultSmsReminder.isEligible(getActivity())) {
+ if (ExpiredBuildReminder.isEligible(getActivity())) {
+ reminderView.showReminder(new ExpiredBuildReminder());
+ } else if (DefaultSmsReminder.isEligible(getActivity())) {
reminderView.showReminder(new DefaultSmsReminder(getActivity()));
} else if (SystemSmsImportReminder.isEligible(getActivity())) {
reminderView.showReminder(new SystemSmsImportReminder(getActivity(), masterSecret));
diff --git a/src/org/thoughtcrime/securesms/TextSecureExpiredException.java b/src/org/thoughtcrime/securesms/TextSecureExpiredException.java
new file mode 100644
index 0000000000..f207b5d686
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/TextSecureExpiredException.java
@@ -0,0 +1,7 @@
+package org.thoughtcrime.securesms;
+
+public class TextSecureExpiredException extends Exception {
+ public TextSecureExpiredException(String message) {
+ super(message);
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/components/ExpiredBuildReminder.java b/src/org/thoughtcrime/securesms/components/ExpiredBuildReminder.java
new file mode 100644
index 0000000000..d8ee5d49c0
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/components/ExpiredBuildReminder.java
@@ -0,0 +1,35 @@
+package org.thoughtcrime.securesms.components;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.provider.Telephony;
+import android.util.Log;
+import android.view.View;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.TextSecureExpiredException;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
+import org.thoughtcrime.securesms.util.Util;
+
+public class ExpiredBuildReminder extends Reminder {
+
+ private static final String TAG = ExpiredBuildReminder.class.getSimpleName();
+
+ public ExpiredBuildReminder() {
+ super(R.drawable.ic_dialog_alert_holo_dark,
+ R.string.reminder_header_expired_build,
+ R.string.reminder_header_expired_build_details);
+ }
+
+ @Override
+ public boolean isDismissable() {
+ return false;
+ }
+
+ public static boolean isEligible(Context context) {
+ return !Util.isBuildFresh();
+ }
+
+}
diff --git a/src/org/thoughtcrime/securesms/components/Reminder.java b/src/org/thoughtcrime/securesms/components/Reminder.java
index 6334675546..090f35d3eb 100644
--- a/src/org/thoughtcrime/securesms/components/Reminder.java
+++ b/src/org/thoughtcrime/securesms/components/Reminder.java
@@ -46,4 +46,8 @@ public abstract class Reminder {
public void setCancelListener(OnClickListener cancelListener) {
this.cancelListener = cancelListener;
}
+
+ public boolean isDismissable() {
+ return true;
+ }
}
diff --git a/src/org/thoughtcrime/securesms/components/ReminderView.java b/src/org/thoughtcrime/securesms/components/ReminderView.java
index b684814eb4..3a127e2d26 100644
--- a/src/org/thoughtcrime/securesms/components/ReminderView.java
+++ b/src/org/thoughtcrime/securesms/components/ReminderView.java
@@ -56,15 +56,21 @@ public class ReminderView extends LinearLayout {
icon.setImageResource(reminder.getIconResId());
title.setText(reminder.getTitleResId());
text.setText(reminder.getTextResId());
- ok.setOnClickListener(reminder.getOkListener());
- cancel.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- hide();
- if (reminder.getCancelListener() != null) reminder.getCancelListener().onClick(v);
- }
- });
- container.setVisibility(View.VISIBLE);
+
+ if (reminder.isDismissable()) {
+ ok.setOnClickListener(reminder.getOkListener());
+ cancel.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ hide();
+ if (reminder.getCancelListener() != null) reminder.getCancelListener().onClick(v);
+ }
+ });
+ container.setVisibility(View.VISIBLE);
+ } else {
+ ok.setVisibility(View.GONE);
+ cancel.setVisibility(View.GONE);
+ }
}
public void hide() {
diff --git a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
index 41f8942db5..a0d98f3c4b 100644
--- a/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/MmsSendJob.java
@@ -31,7 +31,6 @@ import org.whispersystems.libaxolotl.NoSessionException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.util.Arrays;
import ws.com.google.android.mms.MmsException;
@@ -43,7 +42,7 @@ import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendConf;
import ws.com.google.android.mms.pdu.SendReq;
-public class MmsSendJob extends MasterSecretJob {
+public class MmsSendJob extends SendJob {
private static final String TAG = MmsSendJob.class.getSimpleName();
@@ -66,7 +65,7 @@ public class MmsSendJob extends MasterSecretJob {
}
@Override
- public void onRun(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
+ public void onSend(MasterSecret masterSecret) throws MmsException, NoSuchMessageException, IOException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
SendReq message = database.getOutgoingMessage(masterSecret, messageId);
diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
index 6b33e27223..ae940304c0 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java
@@ -66,7 +66,7 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
}
@Override
- public void onRun(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException {
+ public void onSend(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException {
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
SendReq message = database.getOutgoingMessage(masterSecret, messageId);
diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
index a2e40138c5..4605914f43 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
@@ -57,7 +57,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
}
@Override
- public void onRun(MasterSecret masterSecret)
+ public void onSend(MasterSecret masterSecret)
throws RetryLaterException, MmsException, NoSuchMessageException
{
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
index 95815eaf93..d3d4764244 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
@@ -31,7 +31,7 @@ import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendReq;
-public abstract class PushSendJob extends MasterSecretJob {
+public abstract class PushSendJob extends SendJob {
private static final String TAG = PushSendJob.class.getSimpleName();
diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
index 656d9bdad9..3430168031 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
@@ -51,7 +51,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
}
@Override
- public void onRun(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
+ public void onSend(MasterSecret masterSecret) throws NoSuchMessageException, RetryLaterException {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
String destination = record.getIndividualRecipient().getNumber();
diff --git a/src/org/thoughtcrime/securesms/jobs/SendJob.java b/src/org/thoughtcrime/securesms/jobs/SendJob.java
new file mode 100644
index 0000000000..e75db25ec8
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/jobs/SendJob.java
@@ -0,0 +1,29 @@
+package org.thoughtcrime.securesms.jobs;
+
+import android.content.Context;
+
+import org.thoughtcrime.securesms.BuildConfig;
+import org.thoughtcrime.securesms.TextSecureExpiredException;
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.util.Util;
+import org.whispersystems.jobqueue.JobParameters;
+
+public abstract class SendJob extends MasterSecretJob {
+
+ public SendJob(Context context, JobParameters parameters) {
+ super(context, parameters);
+ }
+
+ @Override
+ public final void onRun(MasterSecret masterSecret) throws Exception {
+ if (!Util.isBuildFresh()) {
+ throw new TextSecureExpiredException(String.format("TextSecure expired (build %d, now %d)",
+ BuildConfig.BUILD_TIMESTAMP,
+ System.currentTimeMillis()));
+ }
+
+ onSend(masterSecret);
+ }
+
+ protected abstract void onSend(MasterSecret masterSecret) throws Exception;
+}
diff --git a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
index c0d6048744..8752f84d23 100644
--- a/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/SmsSendJob.java
@@ -31,7 +31,7 @@ import org.whispersystems.libaxolotl.NoSessionException;
import java.util.ArrayList;
-public class SmsSendJob extends MasterSecretJob {
+public class SmsSendJob extends SendJob {
private static final String TAG = SmsSendJob.class.getSimpleName();
@@ -48,7 +48,7 @@ public class SmsSendJob extends MasterSecretJob {
}
@Override
- public void onRun(MasterSecret masterSecret) throws NoSuchMessageException {
+ public void onSend(MasterSecret masterSecret) throws NoSuchMessageException {
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
SmsMessageRecord record = database.getMessage(masterSecret, messageId);
diff --git a/src/org/thoughtcrime/securesms/util/Util.java b/src/org/thoughtcrime/securesms/util/Util.java
index 8b159eee36..578a35083c 100644
--- a/src/org/thoughtcrime/securesms/util/Util.java
+++ b/src/org/thoughtcrime/securesms/util/Util.java
@@ -32,6 +32,8 @@ import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.widget.EditText;
+import org.thoughtcrime.securesms.BuildConfig;
+import org.thoughtcrime.securesms.TextSecureExpiredException;
import org.whispersystems.textsecure.api.util.InvalidNumberException;
import org.whispersystems.textsecure.api.util.PhoneNumberFormatter;
@@ -288,6 +290,7 @@ public class Util {
}
}
-
-
+ public static boolean isBuildFresh() {
+ return BuildConfig.BUILD_TIMESTAMP + TimeUnit.DAYS.toMillis(180) > System.currentTimeMillis();
+ }
}