diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 764058ed68..11bdde1518 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -215,7 +215,6 @@
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index a85647fe89..43de6671fb 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -184,4 +184,22 @@
- @drawable/ic_send_sms_secure
- @drawable/ic_send_push
+
+
+ - Never
+ - One time
+ - Two times
+ - Three times
+ - Five times
+ - Ten times
+
+
+
+ - 0
+ - 1
+ - 2
+ - 3
+ - 5
+ - 10
+
diff --git a/res/xml/preferences_notifications.xml b/res/xml/preferences_notifications.xml
index 842ff72a8e..1aa50ae086 100644
--- a/res/xml/preferences_notifications.xml
+++ b/res/xml/preferences_notifications.xml
@@ -6,6 +6,19 @@
android:summary="@string/preferences__display_message_notifications_in_status_bar"
android:defaultValue="true" />
+
+
+
+
-
-
+
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
index c850f7c7fc..d32aeb914b 100644
--- a/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
+++ b/src/org/thoughtcrime/securesms/notifications/MessageNotifier.java
@@ -16,9 +16,11 @@
*/
package org.thoughtcrime.securesms.notifications;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -40,23 +42,24 @@ import android.util.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.RoutingActivity;
import org.thoughtcrime.securesms.crypto.MasterSecret;
-import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
import org.thoughtcrime.securesms.database.PushDatabase;
+import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
import org.thoughtcrime.securesms.recipients.Recipients;
+import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.textsecure.api.messages.TextSecureEnvelope;
import java.io.IOException;
import java.util.List;
import java.util.ListIterator;
+import java.util.concurrent.TimeUnit;
-import me.leolin.shortcutbadger.ShortcutBadgeException;
import me.leolin.shortcutbadger.ShortcutBadger;
/**
@@ -102,13 +105,12 @@ public class MessageNotifier {
}
}
-
public static void updateNotification(Context context, MasterSecret masterSecret) {
if (!TextSecurePreferences.isNotificationsEnabled(context)) {
return;
}
- updateNotification(context, masterSecret, false);
+ updateNotification(context, masterSecret, false, 0);
}
public static void updateNotification(Context context, MasterSecret masterSecret, long threadId) {
@@ -120,11 +122,11 @@ public class MessageNotifier {
DatabaseFactory.getThreadDatabase(context).setRead(threadId);
sendInThreadNotification(context);
} else {
- updateNotification(context, masterSecret, true);
+ updateNotification(context, masterSecret, true, 0);
}
}
- private static void updateNotification(Context context, MasterSecret masterSecret, boolean signal) {
+ private static void updateNotification(Context context, MasterSecret masterSecret, boolean signal, int reminderCount) {
Cursor telcoCursor = null;
Cursor pushCursor = null;
@@ -138,6 +140,7 @@ public class MessageNotifier {
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
.cancel(NOTIFICATION_ID);
updateBadge(context, 0);
+ clearReminder(context);
return;
}
@@ -152,6 +155,7 @@ public class MessageNotifier {
}
updateBadge(context, notificationState.getMessageCount());
+ scheduleReminder(context, masterSecret, reminderCount);
} finally {
if (telcoCursor != null) telcoCursor.close();
if (pushCursor != null) pushCursor.close();
@@ -180,6 +184,7 @@ public class MessageNotifier {
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
builder.setNumber(notificationState.getMessageCount());
+ builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
if (masterSecret != null) {
builder.addAction(R.drawable.check, context.getString(R.string.MessageNotifier_mark_as_read),
@@ -227,6 +232,8 @@ public class MessageNotifier {
builder.setContentInfo(String.valueOf(notificationState.getMessageCount()));
builder.setNumber(notificationState.getMessageCount());
+ builder.setDeleteIntent(PendingIntent.getBroadcast(context, 0, new Intent(DeleteReceiver.DELETE_REMINDER_ACTION), 0));
+
if (masterSecret != null) {
builder.addAction(R.drawable.check, context.getString(R.string.MessageNotifier_mark_all_as_read),
notificationState.getMarkAsReadIntent(context, masterSecret));
@@ -400,4 +407,48 @@ public class MessageNotifier {
Log.w("MessageNotifier", t);
}
}
+
+ private static void scheduleReminder(Context context, MasterSecret masterSecret, int count) {
+ if (count >= TextSecurePreferences.getRepeatAlertsCount(context)) {
+ return;
+ }
+
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ Intent alarmIntent = new Intent(ReminderReceiver.REMINDER_ACTION);
+ alarmIntent.putExtra("reminder_count", count);
+
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ long timeout = TimeUnit.SECONDS.toMillis(10);
+
+ alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
+ }
+
+ private static void clearReminder(Context context) {
+ Intent alarmIntent = new Intent(ReminderReceiver.REMINDER_ACTION);
+ PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
+ AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ alarmManager.cancel(pendingIntent);
+ }
+
+ public static class ReminderReceiver extends BroadcastReceiver {
+
+ public static final String REMINDER_ACTION = "org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ MasterSecret masterSecret = KeyCachingService.getMasterSecret(context);
+ int reminderCount = intent.getIntExtra("reminder_count", 0);
+ MessageNotifier.updateNotification(context, masterSecret, true, reminderCount + 1);
+ }
+ }
+
+ public static class DeleteReceiver extends BroadcastReceiver {
+
+ public static final String DELETE_REMINDER_ACTION = "org.thoughtcrime.securesms.MessageNotifier.DELETE_REMINDER_ACTION";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ clearReminder(context);
+ }
+ }
}
diff --git a/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java b/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
index dc4b6b67e5..f395a5968e 100644
--- a/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
+++ b/src/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
@@ -28,14 +28,17 @@ public class NotificationsPreferenceFragment extends PreferenceFragment {
addPreferencesFromResource(R.xml.preferences_notifications);
this.findPreference(TextSecurePreferences.LED_COLOR_PREF)
- .setOnPreferenceChangeListener(new ListSummaryListener());
+ .setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(TextSecurePreferences.LED_BLINK_PREF)
- .setOnPreferenceChangeListener(new ListSummaryListener());
+ .setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(TextSecurePreferences.RINGTONE_PREF)
- .setOnPreferenceChangeListener(new RingtoneSummaryListener());
+ .setOnPreferenceChangeListener(new RingtoneSummaryListener());
+ this.findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF)
+ .setOnPreferenceChangeListener(new ListSummaryListener());
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.LED_COLOR_PREF));
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.LED_BLINK_PREF));
+ initializeListSummary((ListPreference) findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF));
initializeRingtoneSummary((RingtonePreference) findPreference(TextSecurePreferences.RINGTONE_PREF));
}
diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
index 8b6d084eb7..63ce32a658 100644
--- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
+++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java
@@ -8,6 +8,8 @@ import java.io.IOException;
public class TextSecurePreferences {
+ private static final String TAG = TextSecurePreferences.class.getSimpleName();
+
public static final String IDENTITY_PREF = "pref_choose_identity";
public static final String CHANGE_PASSPHRASE_PREF = "pref_change_passphrase";
public static final String DISABLE_PASSPHRASE_PREF = "pref_disable_passphrase";
@@ -56,6 +58,25 @@ public class TextSecurePreferences {
private static final String FALLBACK_MMS_ENABLED_PREF = "pref_mms_fallback_enabled";
private static final String SIGNED_PREKEY_REGISTERED_PREF = "pref_signed_prekey_registered";
+ private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
+ private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
+
+ private static final String PUSH_REGISTRATION_REMINDER_PREF = "pref_push_registration_reminder";
+ public static final String REPEAT_ALERTS_PREF = "pref_repeat_alerts";
+
+ public static int getRepeatAlertsCount(Context context) {
+ try {
+ return Integer.parseInt(getStringPreference(context, REPEAT_ALERTS_PREF, "0"));
+ } catch (NumberFormatException e) {
+ Log.w(TAG, e);
+ return 0;
+ }
+ }
+
+ public static void setRepeatAlertsCount(Context context, int count) {
+ setStringPreference(context, REPEAT_ALERTS_PREF, String.valueOf(count));
+ }
+
public static boolean isSignedPreKeyRegistered(Context context) {
return getBooleanPreference(context, SIGNED_PREKEY_REGISTERED_PREF, false);
}
@@ -64,11 +85,6 @@ public class TextSecurePreferences {
setBooleanPreference(context, SIGNED_PREKEY_REGISTERED_PREF, value);
}
- private static final String GCM_REGISTRATION_ID_PREF = "pref_gcm_registration_id";
- private static final String GCM_REGISTRATION_ID_VERSION_PREF = "pref_gcm_registration_id_version";
-
- private static final String PUSH_REGISTRATION_REMINDER_PREF = "pref_push_registration_reminder";
-
public static void setGcmRegistrationId(Context context, String registrationId) {
setStringPreference(context, GCM_REGISTRATION_ID_PREF, registrationId);
setIntegerPrefrence(context, GCM_REGISTRATION_ID_VERSION_PREF, Util.getCurrentApkReleaseVersion(context));