mirror of
https://github.com/oxen-io/session-android.git
synced 2025-06-10 08:08:34 +00:00
Extract MessageNotifier interface.
This commit is contained in:
parent
a299bafe89
commit
f392229393
@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.logging.PersistentLogger;
|
|||||||
import org.thoughtcrime.securesms.logging.SignalUncaughtExceptionHandler;
|
import org.thoughtcrime.securesms.logging.SignalUncaughtExceptionHandler;
|
||||||
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
||||||
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
@ -162,7 +161,7 @@ public class ApplicationContext extends MultiDexApplication implements DefaultLi
|
|||||||
isAppVisible = false;
|
isAppVisible = false;
|
||||||
Log.i(TAG, "App is no longer visible.");
|
Log.i(TAG, "App is no longer visible.");
|
||||||
KeyCachingService.onAppBackgrounded(this);
|
KeyCachingService.onAppBackgrounded(this);
|
||||||
MessageNotifier.setVisibleThread(-1);
|
ApplicationDependencies.getMessageNotifier().clearVisibleThread();
|
||||||
ApplicationDependencies.getFrameRateTracker().end();
|
ApplicationDependencies.getFrameRateTracker().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import androidx.loader.content.Loader;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationItem;
|
import org.thoughtcrime.securesms.conversation.ConversationItem;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -52,7 +53,6 @@ import org.thoughtcrime.securesms.database.loaders.MessageDetailsLoader;
|
|||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
@ -133,13 +133,13 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
|||||||
assert getSupportActionBar() != null;
|
assert getSupportActionBar() != null;
|
||||||
getSupportActionBar().setTitle(R.string.AndroidManifest__message_details);
|
getSupportActionBar().setTitle(R.string.AndroidManifest__message_details);
|
||||||
|
|
||||||
MessageNotifier.setVisibleThread(threadId);
|
ApplicationDependencies.getMessageNotifier().setVisibleThread(threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
MessageNotifier.setVisibleThread(-1L);
|
ApplicationDependencies.getMessageNotifier().clearVisibleThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
|||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||||
@ -178,9 +177,9 @@ class DirectoryHelperV1 {
|
|||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
|
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
|
||||||
if (hour >= 9 && hour < 23) {
|
if (hour >= 9 && hour < 23) {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), true);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId(), true);
|
||||||
} else {
|
} else {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId(), false);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,6 @@ import org.thoughtcrime.securesms.mms.SlideDeck;
|
|||||||
import org.thoughtcrime.securesms.mms.StickerSlide;
|
import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
|
import org.thoughtcrime.securesms.profiles.GroupShareProfileView;
|
||||||
@ -498,14 +497,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
ApplicationDependencies.getJobManager().add(new RequestGroupV2InfoJob(recipientSnapshot.getGroupId().get().requireV2()));
|
ApplicationDependencies.getJobManager().add(new RequestGroupV2InfoJob(recipientSnapshot.getGroupId().get().requireV2()));
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageNotifier.setVisibleThread(threadId);
|
ApplicationDependencies.getMessageNotifier().setVisibleThread(threadId);
|
||||||
markThreadAsRead();
|
markThreadAsRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
MessageNotifier.setVisibleThread(-1L);
|
ApplicationDependencies.getMessageNotifier().clearVisibleThread();
|
||||||
if (isFinishing()) overridePendingTransition(R.anim.fade_scale_in, R.anim.slide_to_end);
|
if (isFinishing()) overridePendingTransition(R.anim.fade_scale_in, R.anim.slide_to_end);
|
||||||
inputPanel.onPause();
|
inputPanel.onPause();
|
||||||
|
|
||||||
@ -2229,7 +2228,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
Context context = ConversationActivity.this;
|
Context context = ConversationActivity.this;
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(params[0], false);
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(params[0], false);
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -2259,7 +2258,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
|
|
||||||
if (refreshFragment) {
|
if (refreshFragment) {
|
||||||
fragment.reload(recipient.get(), threadId);
|
fragment.reload(recipient.get(), threadId);
|
||||||
MessageNotifier.setVisibleThread(threadId);
|
ApplicationDependencies.getMessageNotifier().setVisibleThread(threadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment.scrollToBottom();
|
fragment.scrollToBottom();
|
||||||
|
@ -90,7 +90,6 @@ import org.thoughtcrime.securesms.components.reminder.ServiceOutageReminder;
|
|||||||
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
|
import org.thoughtcrime.securesms.components.reminder.ShareReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
|
import org.thoughtcrime.securesms.components.reminder.SystemSmsImportReminder;
|
||||||
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
|
import org.thoughtcrime.securesms.components.reminder.UnauthorizedReminder;
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationFragment;
|
|
||||||
import org.thoughtcrime.securesms.conversationlist.ConversationListAdapter.ItemClickListener;
|
import org.thoughtcrime.securesms.conversationlist.ConversationListAdapter.ItemClickListener;
|
||||||
import org.thoughtcrime.securesms.conversationlist.model.MessageResult;
|
import org.thoughtcrime.securesms.conversationlist.model.MessageResult;
|
||||||
import org.thoughtcrime.securesms.conversationlist.model.SearchResult;
|
import org.thoughtcrime.securesms.conversationlist.model.SearchResult;
|
||||||
@ -113,13 +112,11 @@ import org.thoughtcrime.securesms.megaphone.MegaphoneViewBuilder;
|
|||||||
import org.thoughtcrime.securesms.megaphone.Megaphones;
|
import org.thoughtcrime.securesms.megaphone.Megaphones;
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||||
import org.thoughtcrime.securesms.util.AvatarUtil;
|
import org.thoughtcrime.securesms.util.AvatarUtil;
|
||||||
import org.thoughtcrime.securesms.util.CachedInflater;
|
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
@ -591,7 +588,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
|
|||||||
SignalExecutors.BOUNDED.execute(() -> {
|
SignalExecutors.BOUNDED.execute(() -> {
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setAllThreadsRead();
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setAllThreadsRead();
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -672,7 +669,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
DatabaseFactory.getThreadDatabase(getActivity()).deleteConversations(selectedConversations);
|
DatabaseFactory.getThreadDatabase(getActivity()).deleteConversations(selectedConversations);
|
||||||
MessageNotifier.updateNotification(getActivity());
|
ApplicationDependencies.getMessageNotifier().updateNotification(getActivity());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,7 +870,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
|
|||||||
|
|
||||||
if (unreadCount > 0) {
|
if (unreadCount > 0) {
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(getActivity()).setRead(threadId, false);
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(getActivity()).setRead(threadId, false);
|
||||||
MessageNotifier.updateNotification(getActivity());
|
ApplicationDependencies.getMessageNotifier().updateNotification(getActivity());
|
||||||
MarkReadReceiver.process(getActivity(), messageIds);
|
MarkReadReceiver.process(getActivity(), messageIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -884,7 +881,7 @@ public class ConversationListFragment extends MainFragment implements LoaderMana
|
|||||||
|
|
||||||
if (unreadCount > 0) {
|
if (unreadCount > 0) {
|
||||||
DatabaseFactory.getThreadDatabase(getActivity()).incrementUnread(threadId, unreadCount);
|
DatabaseFactory.getThreadDatabase(getActivity()).incrementUnread(threadId, unreadCount);
|
||||||
MessageNotifier.updateNotification(getActivity());
|
ApplicationDependencies.getMessageNotifier().updateNotification(getActivity());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, threadId);
|
||||||
|
@ -35,10 +35,10 @@ import org.thoughtcrime.securesms.database.PushDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
|
import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||||
import org.thoughtcrime.securesms.phonenumbers.NumberUtil;
|
import org.thoughtcrime.securesms.phonenumbers.NumberUtil;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
@ -434,7 +434,7 @@ public class ClassicOpenHelper extends SQLiteOpenHelper {
|
|||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
|
|
||||||
// DecryptingQueue.schedulePendingDecrypts(context, masterSecret);
|
// DecryptingQueue.schedulePendingDecrypts(context, masterSecret);
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -14,6 +14,8 @@ import org.thoughtcrime.securesms.keyvalue.KeyValueStore;
|
|||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||||
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
||||||
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
||||||
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
||||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
||||||
@ -57,6 +59,7 @@ public class ApplicationDependencies {
|
|||||||
private static GroupsV2Operations groupsV2Operations;
|
private static GroupsV2Operations groupsV2Operations;
|
||||||
private static EarlyMessageCache earlyMessageCache;
|
private static EarlyMessageCache earlyMessageCache;
|
||||||
private static InitialMessageRetriever initialMessageRetriever;
|
private static InitialMessageRetriever initialMessageRetriever;
|
||||||
|
private static MessageNotifier messageNotifier;
|
||||||
|
|
||||||
public static synchronized void init(@NonNull Application application, @NonNull Provider provider) {
|
public static synchronized void init(@NonNull Application application, @NonNull Provider provider) {
|
||||||
if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) {
|
if (ApplicationDependencies.application != null || ApplicationDependencies.provider != null) {
|
||||||
@ -246,6 +249,16 @@ public class ApplicationDependencies {
|
|||||||
return initialMessageRetriever;
|
return initialMessageRetriever;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static synchronized @NonNull MessageNotifier getMessageNotifier() {
|
||||||
|
assertInitialization();
|
||||||
|
|
||||||
|
if (messageNotifier == null) {
|
||||||
|
messageNotifier = provider.provideMessageNotifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageNotifier;
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertInitialization() {
|
private static void assertInitialization() {
|
||||||
if (application == null || provider == null) {
|
if (application == null || provider == null) {
|
||||||
throw new UninitializedException();
|
throw new UninitializedException();
|
||||||
@ -267,6 +280,7 @@ public class ApplicationDependencies {
|
|||||||
@NonNull MegaphoneRepository provideMegaphoneRepository();
|
@NonNull MegaphoneRepository provideMegaphoneRepository();
|
||||||
@NonNull EarlyMessageCache provideEarlyMessageCache();
|
@NonNull EarlyMessageCache provideEarlyMessageCache();
|
||||||
@NonNull InitialMessageRetriever provideInitialMessageRetriever();
|
@NonNull InitialMessageRetriever provideInitialMessageRetriever();
|
||||||
|
@NonNull MessageNotifier provideMessageNotifier();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class UninitializedException extends IllegalStateException {
|
private static class UninitializedException extends IllegalStateException {
|
||||||
|
@ -21,6 +21,8 @@ import org.thoughtcrime.securesms.keyvalue.KeyValueStore;
|
|||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
import org.thoughtcrime.securesms.megaphone.MegaphoneRepository;
|
||||||
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
import org.thoughtcrime.securesms.messages.InitialMessageRetriever;
|
||||||
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.push.SecurityEventListener;
|
import org.thoughtcrime.securesms.push.SecurityEventListener;
|
||||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||||
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
import org.thoughtcrime.securesms.recipients.LiveRecipientCache;
|
||||||
@ -158,6 +160,11 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
|
|||||||
return new InitialMessageRetriever();
|
return new InitialMessageRetriever();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull MessageNotifier provideMessageNotifier() {
|
||||||
|
return new DefaultMessageNotifier();
|
||||||
|
}
|
||||||
|
|
||||||
private static class DynamicCredentialsProvider implements CredentialsProvider {
|
private static class DynamicCredentialsProvider implements CredentialsProvider {
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
|||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||||
@ -252,7 +251,7 @@ public final class GroupV1MessageProcessor {
|
|||||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
return insertResult.get().getThreadId();
|
return insertResult.get().getThreadId();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.jobmanager.JobLogger;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
import org.thoughtcrime.securesms.util.AttachmentUtil;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
import org.thoughtcrime.securesms.util.Hex;
|
import org.thoughtcrime.securesms.util.Hex;
|
||||||
@ -109,7 +108,7 @@ public class AttachmentDownloadJob extends BaseJob {
|
|||||||
@Override
|
@Override
|
||||||
public void onRun() throws IOException {
|
public void onRun() throws IOException {
|
||||||
doWork();
|
doWork();
|
||||||
MessageNotifier.updateNotification(context, 0);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doWork() throws IOException {
|
public void doWork() throws IOException {
|
||||||
|
@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.groups.GroupId;
|
import org.thoughtcrime.securesms.groups.GroupId;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
@ -27,7 +28,6 @@ import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
|||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.MmsRadioException;
|
import org.thoughtcrime.securesms.mms.MmsRadioException;
|
||||||
import org.thoughtcrime.securesms.mms.PartParser;
|
import org.thoughtcrime.securesms.mms.PartParser;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
@ -94,7 +94,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
public void onAdded() {
|
public void onAdded() {
|
||||||
if (automatic && KeyCachingService.isLocked(context)) {
|
if (automatic && KeyCachingService.isLocked(context)) {
|
||||||
DatabaseFactory.getMmsDatabase(context).markIncomingNotificationReceived(threadId);
|
DatabaseFactory.getMmsDatabase(context).markIncomingNotificationReceived(threadId);
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
|
|
||||||
if (automatic) {
|
if (automatic) {
|
||||||
database.markIncomingNotificationReceived(threadId);
|
database.markIncomingNotificationReceived(threadId);
|
||||||
MessageNotifier.updateNotification(context, threadId);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
database.delete(messageId);
|
database.delete(messageId);
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +256,7 @@ public class MmsDownloadJob extends BaseJob {
|
|||||||
|
|
||||||
if (automatic) {
|
if (automatic) {
|
||||||
db.markIncomingNotificationReceived(threadId);
|
db.markIncomingNotificationReceived(threadId);
|
||||||
MessageNotifier.updateNotification(context, threadId);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.database.GroupDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobLogger;
|
import org.thoughtcrime.securesms.jobmanager.JobLogger;
|
||||||
@ -41,7 +42,6 @@ import org.thoughtcrime.securesms.mms.MmsException;
|
|||||||
import org.thoughtcrime.securesms.mms.MmsSendResult;
|
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.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||||
@ -333,7 +333,7 @@ public final class MmsSendJob extends SendJob {
|
|||||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||||
|
|
||||||
if (recipient != null) {
|
if (recipient != null) {
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
|||||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
import org.thoughtcrime.securesms.mms.StickerSlide;
|
import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||||
|
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
@ -623,7 +624,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
sessionStore.deleteAllSessions(content.getSender().getIdentifier());
|
sessionStore.deleteAllSessions(content.getSender().getIdentifier());
|
||||||
|
|
||||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||||
MessageNotifier.updateNotification(context, threadId);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,11 +749,11 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (reaction.isRemove()) {
|
if (reaction.isRemove()) {
|
||||||
db.deleteReaction(targetMessage.getId(), reactionAuthor.getId());
|
db.deleteReaction(targetMessage.getId(), reactionAuthor.getId());
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
} else {
|
} else {
|
||||||
ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), reactionAuthor.getId(), message.getTimestamp(), System.currentTimeMillis());
|
ReactionRecord reactionRecord = new ReactionRecord(reaction.getEmoji(), reactionAuthor.getId(), message.getTimestamp(), System.currentTimeMillis());
|
||||||
db.addReaction(targetMessage.getId(), reactionRecord);
|
db.addReaction(targetMessage.getId(), reactionRecord);
|
||||||
MessageNotifier.updateNotification(context, targetMessage.getThreadId(), false);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
|
||||||
}
|
}
|
||||||
} else if (targetMessage != null) {
|
} else if (targetMessage != null) {
|
||||||
Log.w(TAG, "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
|
Log.w(TAG, "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + reaction.getTargetSentTimestamp() + " author: " + targetAuthor.getId());
|
||||||
@ -771,7 +772,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerTimestamp())) {
|
if (targetMessage != null && RemoteDeleteUtil.isValidReceive(targetMessage, sender, content.getServerTimestamp())) {
|
||||||
MessagingDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
MessagingDatabase db = targetMessage.isMms() ? DatabaseFactory.getMmsDatabase(context) : DatabaseFactory.getSmsDatabase(context);
|
||||||
db.markAsRemoteDelete(targetMessage.getId());
|
db.markAsRemoteDelete(targetMessage.getId());
|
||||||
MessageNotifier.updateNotification(context, targetMessage.getThreadId(), false);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, targetMessage.getThreadId(), false);
|
||||||
} else if (targetMessage == null) {
|
} else if (targetMessage == null) {
|
||||||
Log.w(TAG, "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + sender.getId());
|
Log.w(TAG, "[handleRemoteDelete] Could not find matching message! timestamp: " + delete.getTargetSentTimestamp() + " author: " + sender.getId());
|
||||||
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
|
ApplicationDependencies.getEarlyMessageCache().store(sender.getId(), delete.getTargetSentTimestamp(), content);
|
||||||
@ -930,10 +931,10 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (threadId != null) {
|
if (threadId != null) {
|
||||||
DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
|
DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageNotifier.setLastDesktopActivityTimestamp(message.getTimestamp());
|
ApplicationDependencies.getMessageNotifier().setLastDesktopActivityTimestamp(message.getTimestamp());
|
||||||
} catch (MmsException e) {
|
} catch (MmsException e) {
|
||||||
throw new StorageFailedException(e, content.getSender().getIdentifier(), content.getSenderDevice());
|
throw new StorageFailedException(e, content.getSender().getIdentifier(), content.getSenderDevice());
|
||||||
}
|
}
|
||||||
@ -985,9 +986,10 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier();
|
||||||
MessageNotifier.cancelDelayedNotifications();
|
messageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
||||||
MessageNotifier.updateNotification(context);
|
messageNotifier.cancelDelayedNotifications();
|
||||||
|
messageNotifier.updateNotification(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSynchronizeViewOnceOpenMessage(@NonNull ViewOnceOpenMessage openMessage, long envelopeTimestamp) {
|
private void handleSynchronizeViewOnceOpenMessage(@NonNull ViewOnceOpenMessage openMessage, long envelopeTimestamp) {
|
||||||
@ -999,9 +1001,10 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForViewOnceMessage(record.getId());
|
DatabaseFactory.getAttachmentDatabase(context).deleteAttachmentFilesForViewOnceMessage(record.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
MessageNotifier messageNotifier = ApplicationDependencies.getMessageNotifier();
|
||||||
MessageNotifier.cancelDelayedNotifications();
|
messageNotifier.setLastDesktopActivityTimestamp(envelopeTimestamp);
|
||||||
MessageNotifier.updateNotification(context);
|
messageNotifier.cancelDelayedNotifications();
|
||||||
|
messageNotifier.updateNotification(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleMediaMessage(@NonNull SignalServiceContent content,
|
private void handleMediaMessage(@NonNull SignalServiceContent content,
|
||||||
@ -1063,7 +1066,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
|
|
||||||
if (message.isViewOnce()) {
|
if (message.isViewOnce()) {
|
||||||
ApplicationContext.getInstance(context).getViewOnceMessageManager().scheduleIfNecessary();
|
ApplicationContext.getInstance(context).getViewOnceMessageManager().scheduleIfNecessary();
|
||||||
@ -1258,7 +1261,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (threadId != null) {
|
if (threadId != null) {
|
||||||
MessageNotifier.updateNotification(context, threadId);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1323,7 +1326,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsInvalidVersionKeyExchange(insertResult.get().getMessageId());
|
smsDatabase.markAsInvalidVersionKeyExchange(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
|
smsDatabase.markAsInvalidVersionKeyExchange(smsMessageId.get());
|
||||||
@ -1340,7 +1343,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
|
smsDatabase.markAsDecryptFailed(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
||||||
@ -1357,7 +1360,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
|
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
smsDatabase.markAsNoSession(smsMessageId.get());
|
||||||
@ -1377,7 +1380,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsUnsupportedProtocolVersion(insertResult.get().getMessageId());
|
smsDatabase.markAsUnsupportedProtocolVersion(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
smsDatabase.markAsNoSession(smsMessageId.get());
|
||||||
@ -1397,7 +1400,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsInvalidMessage(insertResult.get().getMessageId());
|
smsDatabase.markAsInvalidMessage(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
smsDatabase.markAsNoSession(smsMessageId.get());
|
||||||
@ -1414,7 +1417,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
|
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
smsDatabase.markAsLegacyVersion(smsMessageId.get());
|
smsDatabase.markAsLegacyVersion(smsMessageId.get());
|
||||||
@ -1431,7 +1434,7 @@ public final class PushProcessMessageJob extends BaseJob {
|
|||||||
// if (smsMessageId <= 0) {
|
// if (smsMessageId <= 0) {
|
||||||
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||||
// smsDatabase.markAsDecryptDuplicate(messageAndThreadId.first);
|
// smsDatabase.markAsDecryptDuplicate(messageAndThreadId.first);
|
||||||
// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
// ApplicationDependencies.getMessageNotifier().updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||||
// } else {
|
// } else {
|
||||||
// smsDatabase.markAsDecryptDuplicate(smsMessageId);
|
// smsDatabase.markAsDecryptDuplicate(smsMessageId);
|
||||||
// }
|
// }
|
||||||
|
@ -30,7 +30,6 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
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.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||||
@ -221,7 +220,7 @@ public abstract class PushSendJob extends SendJob {
|
|||||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||||
|
|
||||||
if (threadId != -1 && recipient != null) {
|
if (threadId != -1 && recipient != null) {
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
|||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||||
@ -26,15 +25,12 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
|||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroup;
|
|
||||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class PushTextSendJob extends PushSendJob {
|
public class PushTextSendJob extends PushSendJob {
|
||||||
|
|
||||||
@ -122,7 +118,7 @@ public class PushTextSendJob extends PushSendJob {
|
|||||||
} catch (InsecureFallbackApprovalException e) {
|
} catch (InsecureFallbackApprovalException e) {
|
||||||
warn(TAG, "Failure", e);
|
warn(TAG, "Failure", e);
|
||||||
database.markAsPendingInsecureSmsFallback(record.getId());
|
database.markAsPendingInsecureSmsFallback(record.getId());
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||||
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(false));
|
ApplicationDependencies.getJobManager().add(new DirectoryRefreshJob(false));
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
warn(TAG, "Failure", e);
|
warn(TAG, "Failure", e);
|
||||||
@ -147,7 +143,7 @@ public class PushTextSendJob extends PushSendJob {
|
|||||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||||
|
|
||||||
if (threadId != -1 && recipient != null) {
|
if (threadId != -1 && recipient != null) {
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import android.telephony.SmsMessage;
|
import android.telephony.SmsMessage;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraint;
|
||||||
@ -12,7 +13,6 @@ import org.thoughtcrime.securesms.logging.Log;
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
@ -81,7 +81,7 @@ public class SmsReceiveJob extends BaseJob {
|
|||||||
Optional<InsertResult> insertResult = storeMessage(message.get());
|
Optional<InsertResult> insertResult = storeMessage(message.get());
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
} else if (message.isPresent()) {
|
} else if (message.isPresent()) {
|
||||||
Log.w(TAG, "*** Received blocked SMS, ignoring...");
|
Log.w(TAG, "*** Received blocked SMS, ignoring...");
|
||||||
|
@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
|
|||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
import android.telephony.SmsManager;
|
import android.telephony.SmsManager;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
|
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
|
||||||
@ -17,7 +18,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
||||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||||
@ -87,7 +87,7 @@ public class SmsSendJob extends SendJob {
|
|||||||
} catch (UndeliverableMessageException ude) {
|
} catch (UndeliverableMessageException ude) {
|
||||||
warn(TAG, ude);
|
warn(TAG, ude);
|
||||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
|
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ public class SmsSendJob extends SendJob {
|
|||||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||||
|
|
||||||
if (threadId != -1 && recipient != null) {
|
if (threadId != -1 && recipient != null) {
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,12 +9,10 @@ import org.thoughtcrime.securesms.jobmanager.Data;
|
|||||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
||||||
|
|
||||||
public class SmsSentJob extends BaseJob {
|
public class SmsSentJob extends BaseJob {
|
||||||
@ -107,7 +105,7 @@ public class SmsSentJob extends BaseJob {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
database.markAsSentFailed(messageId);
|
database.markAsSentFailed(messageId);
|
||||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||||
}
|
}
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
|
@ -22,7 +22,6 @@ import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
|
|||||||
import org.thoughtcrime.securesms.jobs.MultiDeviceMessageRequestResponseJob;
|
import org.thoughtcrime.securesms.jobs.MultiDeviceMessageRequestResponseJob;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
import org.thoughtcrime.securesms.recipients.LiveRecipient;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
@ -119,7 +118,7 @@ final class MessageRequestRepository {
|
|||||||
|
|
||||||
List<MessagingDatabase.MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context)
|
List<MessagingDatabase.MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context)
|
||||||
.setEntireThreadRead(threadId);
|
.setEntireThreadRead(threadId);
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
|
||||||
if (TextSecurePreferences.isMultiDevice(context)) {
|
if (TextSecurePreferences.isMultiDevice(context)) {
|
||||||
@ -189,7 +188,7 @@ final class MessageRequestRepository {
|
|||||||
|
|
||||||
List<MessagingDatabase.MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context)
|
List<MessagingDatabase.MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context)
|
||||||
.setEntireThreadRead(threadId);
|
.setEntireThreadRead(threadId);
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
|
||||||
if (TextSecurePreferences.isMultiDevice(context)) {
|
if (TextSecurePreferences.isMultiDevice(context)) {
|
||||||
|
@ -26,6 +26,7 @@ import androidx.core.app.NotificationManagerCompat;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -66,7 +67,7 @@ public class AndroidAutoHeardReceiver extends BroadcastReceiver {
|
|||||||
messageIdsCollection.addAll(messageIds);
|
messageIdsCollection.addAll(messageIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIdsCollection);
|
MarkReadReceiver.process(context, messageIdsCollection);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -27,6 +27,7 @@ import androidx.core.app.RemoteInput;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
@ -84,7 +85,7 @@ public class AndroidAutoReplyReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(replyThreadId, true);
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -0,0 +1,737 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 Whisper Systems
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.thoughtcrime.securesms.notifications;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
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;
|
||||||
|
import android.media.AudioAttributes;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.Ringtone;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.service.notification.StatusBarNotification;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.contactshare.Contact;
|
||||||
|
import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
||||||
|
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||||
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
|
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||||
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
|
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||||
|
import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.mms.Slide;
|
||||||
|
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
|
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||||
|
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
||||||
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.MessageRecordUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
|
||||||
|
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
||||||
|
import org.whispersystems.signalservice.internal.util.Util;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles posting system notifications for new messages.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @author Moxie Marlinspike
|
||||||
|
*/
|
||||||
|
public class DefaultMessageNotifier implements MessageNotifier {
|
||||||
|
|
||||||
|
private static final String TAG = DefaultMessageNotifier.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String EXTRA_REMOTE_REPLY = "extra_remote_reply";
|
||||||
|
|
||||||
|
private static final String EMOJI_REPLACEMENT_STRING = "__EMOJI__";
|
||||||
|
private static final String NOTIFICATION_GROUP = "messages";
|
||||||
|
private static final long MIN_AUDIBLE_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(2);
|
||||||
|
private static final long DESKTOP_ACTIVITY_PERIOD = TimeUnit.MINUTES.toMillis(1);
|
||||||
|
|
||||||
|
private volatile long visibleThread = -1;
|
||||||
|
private volatile long lastDesktopActivityTimestamp = -1;
|
||||||
|
private volatile long lastAudibleNotification = -1;
|
||||||
|
private final CancelableExecutor executor = new CancelableExecutor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisibleThread(long threadId) {
|
||||||
|
visibleThread = threadId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearVisibleThread() {
|
||||||
|
setVisibleThread(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLastDesktopActivityTimestamp(long timestamp) {
|
||||||
|
lastDesktopActivityTimestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyMessageDeliveryFailed(Context context, Recipient recipient, long threadId) {
|
||||||
|
if (visibleThread == threadId) {
|
||||||
|
sendInThreadNotification(context, recipient);
|
||||||
|
} else {
|
||||||
|
Intent intent = new Intent(context, ConversationActivity.class);
|
||||||
|
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId());
|
||||||
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||||
|
intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
|
||||||
|
|
||||||
|
FailedNotificationBuilder builder = new FailedNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context), intent);
|
||||||
|
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
|
||||||
|
.notify((int)threadId, builder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancelDelayedNotifications() {
|
||||||
|
executor.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void cancelActiveNotifications(@NonNull Context context) {
|
||||||
|
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
||||||
|
notifications.cancel(NotificationIds.MESSAGE_SUMMARY);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
try {
|
||||||
|
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
||||||
|
|
||||||
|
for (StatusBarNotification activeNotification : activeNotifications) {
|
||||||
|
if (!CallNotificationBuilder.isWebRtcNotification(activeNotification.getId())) {
|
||||||
|
notifications.cancel(activeNotification.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// XXX Appears to be a ROM bug, see #6043
|
||||||
|
Log.w(TAG, e);
|
||||||
|
notifications.cancelAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDisplayingSummaryNotification(@NonNull Context context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
try {
|
||||||
|
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||||
|
StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications();
|
||||||
|
|
||||||
|
for (StatusBarNotification activeNotification : activeNotifications) {
|
||||||
|
if (activeNotification.getId() == NotificationIds.MESSAGE_SUMMARY) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// XXX Android ROM Bug, see #6043
|
||||||
|
Log.w(TAG, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void cancelOrphanedNotifications(@NonNull Context context, NotificationState notificationState) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
try {
|
||||||
|
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
||||||
|
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
||||||
|
|
||||||
|
for (StatusBarNotification notification : activeNotifications) {
|
||||||
|
boolean validNotification = false;
|
||||||
|
|
||||||
|
if (notification.getId() != NotificationIds.MESSAGE_SUMMARY &&
|
||||||
|
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
|
||||||
|
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
|
||||||
|
notification.getId() != NotificationIds.PENDING_MESSAGES &&
|
||||||
|
!CallNotificationBuilder.isWebRtcNotification(notification.getId()))
|
||||||
|
{
|
||||||
|
for (NotificationItem item : notificationState.getNotifications()) {
|
||||||
|
if (notification.getId() == NotificationIds.getNotificationIdForThread(item.getThreadId())) {
|
||||||
|
validNotification = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validNotification) {
|
||||||
|
notifications.cancel(notification.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// XXX Android ROM Bug, see #6043
|
||||||
|
Log.w(TAG, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNotification(@NonNull Context context) {
|
||||||
|
if (!TextSecurePreferences.isNotificationsEnabled(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNotification(context, -1, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNotification(@NonNull Context context, long threadId)
|
||||||
|
{
|
||||||
|
if (System.currentTimeMillis() - lastDesktopActivityTimestamp < DESKTOP_ACTIVITY_PERIOD) {
|
||||||
|
Log.i(TAG, "Scheduling delayed notification...");
|
||||||
|
executor.execute(new DelayedNotification(context, threadId));
|
||||||
|
} else {
|
||||||
|
updateNotification(context, threadId, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNotification(@NonNull Context context,
|
||||||
|
long threadId,
|
||||||
|
boolean signal)
|
||||||
|
{
|
||||||
|
boolean isVisible = visibleThread == threadId;
|
||||||
|
|
||||||
|
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
|
||||||
|
Recipient recipients = DatabaseFactory.getThreadDatabase(context)
|
||||||
|
.getRecipientForThreadId(threadId);
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
List<MarkedMessageInfo> messageIds = threads.setRead(threadId, false);
|
||||||
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TextSecurePreferences.isNotificationsEnabled(context) ||
|
||||||
|
(recipients != null && recipients.isMuted()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVisible) {
|
||||||
|
sendInThreadNotification(context, threads.getRecipientForThreadId(threadId));
|
||||||
|
} else {
|
||||||
|
updateNotification(context, threadId, signal, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNotification(@NonNull Context context,
|
||||||
|
long targetThread,
|
||||||
|
boolean signal,
|
||||||
|
int reminderCount)
|
||||||
|
{
|
||||||
|
Cursor telcoCursor = null;
|
||||||
|
Cursor pushCursor = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
telcoCursor = DatabaseFactory.getMmsSmsDatabase(context).getUnread();
|
||||||
|
pushCursor = DatabaseFactory.getPushDatabase(context).getPending();
|
||||||
|
|
||||||
|
if ((telcoCursor == null || telcoCursor.isAfterLast()) &&
|
||||||
|
(pushCursor == null || pushCursor.isAfterLast()))
|
||||||
|
{
|
||||||
|
cancelActiveNotifications(context);
|
||||||
|
updateBadge(context, 0);
|
||||||
|
clearReminder(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationState notificationState = constructNotificationState(context, telcoCursor);
|
||||||
|
|
||||||
|
if (signal && (System.currentTimeMillis() - lastAudibleNotification) < MIN_AUDIBLE_PERIOD_MILLIS) {
|
||||||
|
signal = false;
|
||||||
|
} else if (signal) {
|
||||||
|
lastAudibleNotification = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationState.hasMultipleThreads()) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
for (long threadId : notificationState.getThreads()) {
|
||||||
|
if (targetThread < 1 || targetThread == threadId) {
|
||||||
|
sendSingleThreadNotification(context,
|
||||||
|
new NotificationState(notificationState.getNotificationsForThread(threadId)),
|
||||||
|
signal && (threadId == targetThread),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMultipleThreadNotification(context, notificationState, signal && (Build.VERSION.SDK_INT < 23));
|
||||||
|
} else {
|
||||||
|
sendSingleThreadNotification(context, notificationState, signal, false);
|
||||||
|
|
||||||
|
if (isDisplayingSummaryNotification(context)) {
|
||||||
|
sendMultipleThreadNotification(context, notificationState, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelOrphanedNotifications(context, notificationState);
|
||||||
|
updateBadge(context, notificationState.getMessageCount());
|
||||||
|
|
||||||
|
if (signal) {
|
||||||
|
scheduleReminder(context, reminderCount);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (telcoCursor != null) telcoCursor.close();
|
||||||
|
if (pushCursor != null) pushCursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendSingleThreadNotification(@NonNull Context context,
|
||||||
|
@NonNull NotificationState notificationState,
|
||||||
|
boolean signal,
|
||||||
|
boolean bundled)
|
||||||
|
{
|
||||||
|
Log.i(TAG, "sendSingleThreadNotification() signal: " + signal + " bundled: " + bundled);
|
||||||
|
|
||||||
|
if (notificationState.getNotifications().isEmpty()) {
|
||||||
|
if (!bundled) cancelActiveNotifications(context);
|
||||||
|
Log.i(TAG, "[sendSingleThreadNotification] Empty notification state. Skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
|
||||||
|
List<NotificationItem> notifications = notificationState.getNotifications();
|
||||||
|
Recipient recipient = notifications.get(0).getRecipient();
|
||||||
|
int notificationId;
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
notificationId = NotificationIds.getNotificationIdForThread(notifications.get(0).getThreadId());
|
||||||
|
} else {
|
||||||
|
notificationId = NotificationIds.MESSAGE_SUMMARY;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setThread(notifications.get(0).getRecipient());
|
||||||
|
builder.setMessageCount(notificationState.getMessageCount());
|
||||||
|
builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(),
|
||||||
|
notifications.get(0).getText(), notifications.get(0).getSlideDeck());
|
||||||
|
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
|
||||||
|
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
|
||||||
|
builder.setOnlyAlertOnce(!signal);
|
||||||
|
builder.setSortKey(String.valueOf(Long.MAX_VALUE - notifications.get(0).getTimestamp()));
|
||||||
|
|
||||||
|
long timestamp = notifications.get(0).getTimestamp();
|
||||||
|
if (timestamp != 0) builder.setWhen(timestamp);
|
||||||
|
|
||||||
|
if (!KeyCachingService.isLocked(context) && RecipientUtil.isMessageRequestAccepted(context, recipient.resolve())) {
|
||||||
|
ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient);
|
||||||
|
|
||||||
|
builder.addActions(notificationState.getMarkAsReadIntent(context, notificationId),
|
||||||
|
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()),
|
||||||
|
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient(), replyMethod),
|
||||||
|
replyMethod);
|
||||||
|
|
||||||
|
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()),
|
||||||
|
notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
|
||||||
|
|
||||||
|
while(iterator.hasPrevious()) {
|
||||||
|
NotificationItem item = iterator.previous();
|
||||||
|
builder.addMessageBody(item.getRecipient(), item.getIndividualRecipient(), item.getText(), item.getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal) {
|
||||||
|
builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate());
|
||||||
|
builder.setTicker(notifications.get(0).getIndividualRecipient(),
|
||||||
|
notifications.get(0).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
builder.setGroup(NOTIFICATION_GROUP);
|
||||||
|
builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification notification = builder.build();
|
||||||
|
NotificationManagerCompat.from(context).notify(notificationId, notification);
|
||||||
|
Log.i(TAG, "Posted notification. " + notification.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendMultipleThreadNotification(@NonNull Context context,
|
||||||
|
@NonNull NotificationState notificationState,
|
||||||
|
boolean signal)
|
||||||
|
{
|
||||||
|
Log.i(TAG, "sendMultiThreadNotification() signal: " + signal);
|
||||||
|
|
||||||
|
if (notificationState.getNotifications().isEmpty()) {
|
||||||
|
Log.i(TAG, "[sendMultiThreadNotification] Empty notification state. Skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultipleRecipientNotificationBuilder builder = new MultipleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
|
||||||
|
List<NotificationItem> notifications = notificationState.getNotifications();
|
||||||
|
|
||||||
|
builder.setMessageCount(notificationState.getMessageCount(), notificationState.getThreadCount());
|
||||||
|
builder.setMostRecentSender(notifications.get(0).getIndividualRecipient());
|
||||||
|
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
|
||||||
|
builder.setOnlyAlertOnce(!signal);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||||||
|
builder.setGroup(NOTIFICATION_GROUP);
|
||||||
|
builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
||||||
|
}
|
||||||
|
|
||||||
|
long timestamp = notifications.get(0).getTimestamp();
|
||||||
|
if (timestamp != 0) builder.setWhen(timestamp);
|
||||||
|
|
||||||
|
builder.addActions(notificationState.getMarkAsReadIntent(context, NotificationIds.MESSAGE_SUMMARY));
|
||||||
|
|
||||||
|
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
|
||||||
|
|
||||||
|
while(iterator.hasPrevious()) {
|
||||||
|
NotificationItem item = iterator.previous();
|
||||||
|
builder.addMessageBody(item.getIndividualRecipient(), item.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal) {
|
||||||
|
builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate());
|
||||||
|
builder.setTicker(notifications.get(0).getIndividualRecipient(),
|
||||||
|
notifications.get(0).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
Notification notification = builder.build();
|
||||||
|
NotificationManagerCompat.from(context).notify(NotificationIds.MESSAGE_SUMMARY, builder.build());
|
||||||
|
Log.i(TAG, "Posted notification. " + notification.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sendInThreadNotification(Context context, Recipient recipient) {
|
||||||
|
if (!TextSecurePreferences.isInThreadNotifications(context) ||
|
||||||
|
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri uri = null;
|
||||||
|
if (recipient != null) {
|
||||||
|
uri = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context, recipient) : recipient.getMessageRingtone();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
uri = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : TextSecurePreferences.getNotificationRingtone(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uri.toString().isEmpty()) {
|
||||||
|
Log.d(TAG, "ringtone uri is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ringtone ringtone = RingtoneManager.getRingtone(context, uri);
|
||||||
|
|
||||||
|
if (ringtone == null) {
|
||||||
|
Log.w(TAG, "ringtone is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
ringtone.setAudioAttributes(new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
|
||||||
|
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
|
||||||
|
.build());
|
||||||
|
} else {
|
||||||
|
ringtone.setStreamType(AudioManager.STREAM_NOTIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
ringtone.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NotificationState constructNotificationState(@NonNull Context context,
|
||||||
|
@NonNull Cursor cursor)
|
||||||
|
{
|
||||||
|
NotificationState notificationState = new NotificationState();
|
||||||
|
MmsSmsDatabase.Reader reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor);
|
||||||
|
|
||||||
|
MessageRecord record;
|
||||||
|
|
||||||
|
while ((record = reader.getNext()) != null) {
|
||||||
|
long id = record.getId();
|
||||||
|
boolean mms = record.isMms() || record.isMmsNotification();
|
||||||
|
Recipient recipient = record.getIndividualRecipient().resolve();
|
||||||
|
Recipient conversationRecipient = record.getRecipient().resolve();
|
||||||
|
long threadId = record.getThreadId();
|
||||||
|
CharSequence body = record.getDisplayBody(context);
|
||||||
|
Recipient threadRecipients = null;
|
||||||
|
SlideDeck slideDeck = null;
|
||||||
|
long timestamp = record.getTimestamp();
|
||||||
|
long receivedTimestamp = record.getDateReceived();
|
||||||
|
boolean isUnreadMessage = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.READ)) == 0;
|
||||||
|
boolean hasUnreadReactions = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_UNREAD)) == 1;
|
||||||
|
long lastReactionRead = cursor.getLong(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_LAST_SEEN));
|
||||||
|
|
||||||
|
if (threadId != -1) {
|
||||||
|
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUnreadMessage) {
|
||||||
|
if (KeyCachingService.isLocked(context)) {
|
||||||
|
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_locked_message));
|
||||||
|
} else if (record.isMms() && !((MmsMessageRecord) record).getSharedContacts().isEmpty()) {
|
||||||
|
Contact contact = ((MmsMessageRecord) record).getSharedContacts().get(0);
|
||||||
|
body = ContactUtil.getStringSummary(context, contact);
|
||||||
|
} else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getStickerSlide() != null) {
|
||||||
|
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_sticker));
|
||||||
|
slideDeck = ((MmsMessageRecord) record).getSlideDeck();
|
||||||
|
} else if (record.isMms() && ((MmsMessageRecord) record).isViewOnce()) {
|
||||||
|
body = SpanUtil.italic(context.getString(getViewOnceDescription((MmsMessageRecord) record)));
|
||||||
|
} else if (record.isRemoteDelete()) {
|
||||||
|
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_this_message_was_deleted));;
|
||||||
|
} else if (record.isMms() && TextUtils.isEmpty(body) && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
|
||||||
|
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_media_message));
|
||||||
|
slideDeck = ((MediaMmsMessageRecord) record).getSlideDeck();
|
||||||
|
} else if (record.isMms() && !record.isMmsNotification() && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
|
||||||
|
String message = context.getString(R.string.MessageNotifier_media_message_with_text, body);
|
||||||
|
int italicLength = message.length() - body.length();
|
||||||
|
body = SpanUtil.italic(message, italicLength);
|
||||||
|
slideDeck = ((MediaMmsMessageRecord) record).getSlideDeck();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threadRecipients == null || !threadRecipients.isMuted()) {
|
||||||
|
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, receivedTimestamp, slideDeck, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasUnreadReactions) {
|
||||||
|
for (ReactionRecord reaction : record.getReactions()) {
|
||||||
|
Recipient reactionSender = Recipient.resolved(reaction.getAuthor());
|
||||||
|
if (reactionSender.equals(Recipient.self()) || !record.isOutgoing() || reaction.getDateReceived() <= lastReactionRead) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KeyCachingService.isLocked(context)) {
|
||||||
|
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_locked_message));
|
||||||
|
} else {
|
||||||
|
String text = SpanUtil.italic(getReactionMessageBody(context, record)).toString();
|
||||||
|
String[] parts = text.split(EMOJI_REPLACEMENT_STRING);
|
||||||
|
|
||||||
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||||
|
for (int i = 0; i < parts.length; i++) {
|
||||||
|
builder.append(SpanUtil.italic(parts[i]));
|
||||||
|
|
||||||
|
if (i != parts.length -1) {
|
||||||
|
builder.append(reaction.getEmoji());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (text.endsWith(EMOJI_REPLACEMENT_STRING)) {
|
||||||
|
builder.append(reaction.getEmoji());
|
||||||
|
}
|
||||||
|
|
||||||
|
body = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (threadRecipients == null || !threadRecipients.isMuted()) {
|
||||||
|
notificationState.addNotification(new NotificationItem(id, mms, reactionSender, conversationRecipient, threadRecipients, threadId, body, reaction.getDateReceived(), receivedTimestamp, null, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
return notificationState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CharSequence getReactionMessageBody(@NonNull Context context, @NonNull MessageRecord record) {
|
||||||
|
CharSequence body = record.getDisplayBody(context);
|
||||||
|
boolean bodyIsEmpty = TextUtils.isEmpty(body);
|
||||||
|
|
||||||
|
if (MessageRecordUtil.hasSharedContact(record)) {
|
||||||
|
Contact contact = ((MmsMessageRecord) record).getSharedContacts().get(0);
|
||||||
|
CharSequence summary = ContactUtil.getStringSummary(context, contact);
|
||||||
|
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, summary);
|
||||||
|
} else if (MessageRecordUtil.hasSticker(record)) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_sticker, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (record.isMms() && record.isViewOnce() && MediaUtil.isVideoType(getMessageContentType((MmsMessageRecord) record))) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_view_once_video, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (record.isMms() && record.isViewOnce()){
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_view_once_photo, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (!bodyIsEmpty) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, body);
|
||||||
|
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isVideoType(getMessageContentType((MmsMessageRecord) record))) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_video, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isImageType(getMessageContentType((MmsMessageRecord) record))) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_image, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isAudioType(getMessageContentType((MmsMessageRecord) record))) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_audio, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else if (MessageRecordUtil.isMediaMessage(record)) {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_your_file, EMOJI_REPLACEMENT_STRING);
|
||||||
|
} else {
|
||||||
|
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @StringRes int getViewOnceDescription(@NonNull MmsMessageRecord messageRecord) {
|
||||||
|
final String contentType = getMessageContentType(messageRecord);
|
||||||
|
|
||||||
|
if (MediaUtil.isImageType(contentType)) {
|
||||||
|
return R.string.MessageNotifier_view_once_photo;
|
||||||
|
}
|
||||||
|
return R.string.MessageNotifier_view_once_video;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getMessageContentType(@NonNull MmsMessageRecord messageRecord) {
|
||||||
|
Slide thumbnailSlide = messageRecord.getSlideDeck().getThumbnailSlide();
|
||||||
|
if (thumbnailSlide == null) {
|
||||||
|
Log.w(TAG, "Could not distinguish view-once content type from message record, defaulting to JPEG");
|
||||||
|
return MediaUtil.IMAGE_JPEG;
|
||||||
|
}
|
||||||
|
return thumbnailSlide.getContentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateBadge(Context context, int count) {
|
||||||
|
try {
|
||||||
|
if (count == 0) ShortcutBadger.removeCount(context);
|
||||||
|
else ShortcutBadger.applyCount(context, count);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// NOTE :: I don't totally trust this thing, so I'm catching
|
||||||
|
// everything.
|
||||||
|
Log.w(TAG, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void scheduleReminder(Context context, 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.MINUTES.toMillis(2);
|
||||||
|
|
||||||
|
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearReminder(@NonNull 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DelayedNotification implements Runnable {
|
||||||
|
|
||||||
|
private static final long DELAY = TimeUnit.SECONDS.toMillis(5);
|
||||||
|
|
||||||
|
private final AtomicBoolean canceled = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final long threadId;
|
||||||
|
private final long delayUntil;
|
||||||
|
|
||||||
|
private DelayedNotification(Context context, long threadId) {
|
||||||
|
this.context = context;
|
||||||
|
this.threadId = threadId;
|
||||||
|
this.delayUntil = System.currentTimeMillis() + DELAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long delayMillis = delayUntil - System.currentTimeMillis();
|
||||||
|
Log.i(TAG, "Waiting to notify: " + delayMillis);
|
||||||
|
|
||||||
|
if (delayMillis > 0) {
|
||||||
|
Util.sleep(delayMillis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!canceled.get()) {
|
||||||
|
Log.i(TAG, "Not canceled, notifying...");
|
||||||
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, threadId, true);
|
||||||
|
ApplicationDependencies.getMessageNotifier().cancelDelayedNotifications();
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Canceled, not notifying...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
canceled.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CancelableExecutor {
|
||||||
|
|
||||||
|
private final Executor executor = Executors.newSingleThreadExecutor();
|
||||||
|
private final Set<DelayedNotification> tasks = new HashSet<>();
|
||||||
|
|
||||||
|
public void execute(final DelayedNotification runnable) {
|
||||||
|
synchronized (tasks) {
|
||||||
|
tasks.add(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
Runnable wrapper = () -> {
|
||||||
|
runnable.run();
|
||||||
|
|
||||||
|
synchronized (tasks) {
|
||||||
|
tasks.remove(runnable);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
executor.execute(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancel() {
|
||||||
|
synchronized (tasks) {
|
||||||
|
for (DelayedNotification task : tasks) {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import android.content.Intent;
|
|||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
|
|
||||||
public class DeleteNotificationReceiver extends BroadcastReceiver {
|
public class DeleteNotificationReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ public class DeleteNotificationReceiver extends BroadcastReceiver {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, Intent intent) {
|
public void onReceive(final Context context, Intent intent) {
|
||||||
if (DELETE_NOTIFICATION_ACTION.equals(intent.getAction())) {
|
if (DELETE_NOTIFICATION_ACTION.equals(intent.getAction())) {
|
||||||
MessageNotifier.clearReminder(context);
|
ApplicationDependencies.getMessageNotifier().clearReminder(context);
|
||||||
|
|
||||||
final long[] ids = intent.getLongArrayExtra(EXTRA_IDS);
|
final long[] ids = intent.getLongArrayExtra(EXTRA_IDS);
|
||||||
final boolean[] mms = intent.getBooleanArrayExtra(EXTRA_MMS);
|
final boolean[] mms = intent.getBooleanArrayExtra(EXTRA_MMS);
|
||||||
|
@ -59,7 +59,7 @@ public class MarkReadReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
process(context, messageIdsCollection);
|
process(context, messageIdsCollection);
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,759 +1,40 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2011 Whisper Systems
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package org.thoughtcrime.securesms.notifications;
|
package org.thoughtcrime.securesms.notifications;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.media.AudioAttributes;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.Ringtone;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.service.notification.StatusBarNotification;
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
|
||||||
|
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
|
||||||
import org.thoughtcrime.securesms.R;
|
|
||||||
import org.thoughtcrime.securesms.contactshare.Contact;
|
|
||||||
import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
|
||||||
import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
|
||||||
import org.thoughtcrime.securesms.mms.Slide;
|
|
||||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
|
||||||
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
|
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
public interface MessageNotifier {
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
void setVisibleThread(long threadId);
|
||||||
import org.thoughtcrime.securesms.util.MessageRecordUtil;
|
void clearVisibleThread();
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
void setLastDesktopActivityTimestamp(long timestamp);
|
||||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
void notifyMessageDeliveryFailed(Context context, Recipient recipient, long threadId);
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
void cancelDelayedNotifications();
|
||||||
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
void updateNotification(@NonNull Context context);
|
||||||
import org.whispersystems.signalservice.internal.util.Util;
|
void updateNotification(@NonNull Context context, long threadId);
|
||||||
|
void updateNotification(@NonNull Context context, long threadId, boolean signal);
|
||||||
import java.util.HashSet;
|
void updateNotification(@NonNull Context context, long threadId, boolean signal, int reminderCount);
|
||||||
import java.util.List;
|
void clearReminder(@NonNull Context context);
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Executor;
|
class ReminderReceiver extends BroadcastReceiver {
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles posting system notifications for new messages.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author Moxie Marlinspike
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class MessageNotifier {
|
|
||||||
|
|
||||||
private static final String TAG = MessageNotifier.class.getSimpleName();
|
|
||||||
|
|
||||||
public static final String EXTRA_REMOTE_REPLY = "extra_remote_reply";
|
|
||||||
|
|
||||||
private static final String EMOJI_REPLACEMENT_STRING = "__EMOJI__";
|
|
||||||
private static final String NOTIFICATION_GROUP = "messages";
|
|
||||||
private static final long MIN_AUDIBLE_PERIOD_MILLIS = TimeUnit.SECONDS.toMillis(2);
|
|
||||||
private static final long DESKTOP_ACTIVITY_PERIOD = TimeUnit.MINUTES.toMillis(1);
|
|
||||||
|
|
||||||
private volatile static long visibleThread = -1;
|
|
||||||
private volatile static long lastDesktopActivityTimestamp = -1;
|
|
||||||
private volatile static long lastAudibleNotification = -1;
|
|
||||||
private static final CancelableExecutor executor = new CancelableExecutor();
|
|
||||||
|
|
||||||
public static void setVisibleThread(long threadId) {
|
|
||||||
visibleThread = threadId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setLastDesktopActivityTimestamp(long timestamp) {
|
|
||||||
lastDesktopActivityTimestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void notifyMessageDeliveryFailed(Context context, Recipient recipient, long threadId) {
|
|
||||||
if (visibleThread == threadId) {
|
|
||||||
sendInThreadNotification(context, recipient);
|
|
||||||
} else {
|
|
||||||
Intent intent = new Intent(context, ConversationActivity.class);
|
|
||||||
intent.putExtra(ConversationActivity.RECIPIENT_EXTRA, recipient.getId());
|
|
||||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
|
||||||
intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
|
|
||||||
|
|
||||||
FailedNotificationBuilder builder = new FailedNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context), intent);
|
|
||||||
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE))
|
|
||||||
.notify((int)threadId, builder.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void notifyMessagesPending(Context context) {
|
|
||||||
if (!TextSecurePreferences.isNotificationsEnabled(context) || ApplicationContext.getInstance(context).isAppVisible()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingMessageNotificationBuilder builder = new PendingMessageNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
|
|
||||||
ServiceUtil.getNotificationManager(context).notify(NotificationIds.PENDING_MESSAGES, builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cancelMessagesPending(Context context) {
|
|
||||||
ServiceUtil.getNotificationManager(context).cancel(NotificationIds.PENDING_MESSAGES);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cancelDelayedNotifications() {
|
|
||||||
executor.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void cancelActiveNotifications(@NonNull Context context) {
|
|
||||||
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
|
||||||
notifications.cancel(NotificationIds.MESSAGE_SUMMARY);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
try {
|
|
||||||
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
|
||||||
|
|
||||||
for (StatusBarNotification activeNotification : activeNotifications) {
|
|
||||||
if (!CallNotificationBuilder.isWebRtcNotification(activeNotification.getId())) {
|
|
||||||
notifications.cancel(activeNotification.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// XXX Appears to be a ROM bug, see #6043
|
|
||||||
Log.w(TAG, e);
|
|
||||||
notifications.cancelAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isDisplayingSummaryNotification(@NonNull Context context) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
try {
|
|
||||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
|
||||||
StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications();
|
|
||||||
|
|
||||||
for (StatusBarNotification activeNotification : activeNotifications) {
|
|
||||||
if (activeNotification.getId() == NotificationIds.MESSAGE_SUMMARY) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// XXX Android ROM Bug, see #6043
|
|
||||||
Log.w(TAG, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void cancelOrphanedNotifications(@NonNull Context context, NotificationState notificationState) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
try {
|
|
||||||
NotificationManager notifications = ServiceUtil.getNotificationManager(context);
|
|
||||||
StatusBarNotification[] activeNotifications = notifications.getActiveNotifications();
|
|
||||||
|
|
||||||
for (StatusBarNotification notification : activeNotifications) {
|
|
||||||
boolean validNotification = false;
|
|
||||||
|
|
||||||
if (notification.getId() != NotificationIds.MESSAGE_SUMMARY &&
|
|
||||||
notification.getId() != KeyCachingService.SERVICE_RUNNING_ID &&
|
|
||||||
notification.getId() != IncomingMessageObserver.FOREGROUND_ID &&
|
|
||||||
notification.getId() != NotificationIds.PENDING_MESSAGES &&
|
|
||||||
!CallNotificationBuilder.isWebRtcNotification(notification.getId()))
|
|
||||||
{
|
|
||||||
for (NotificationItem item : notificationState.getNotifications()) {
|
|
||||||
if (notification.getId() == NotificationIds.getNotificationIdForThread(item.getThreadId())) {
|
|
||||||
validNotification = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validNotification) {
|
|
||||||
notifications.cancel(notification.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// XXX Android ROM Bug, see #6043
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateNotification(@NonNull Context context) {
|
|
||||||
if (!TextSecurePreferences.isNotificationsEnabled(context)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateNotification(context, -1, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateNotification(@NonNull Context context, long threadId)
|
|
||||||
{
|
|
||||||
if (System.currentTimeMillis() - lastDesktopActivityTimestamp < DESKTOP_ACTIVITY_PERIOD) {
|
|
||||||
Log.i(TAG, "Scheduling delayed notification...");
|
|
||||||
executor.execute(new DelayedNotification(context, threadId));
|
|
||||||
} else {
|
|
||||||
updateNotification(context, threadId, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void updateNotification(@NonNull Context context,
|
|
||||||
long threadId,
|
|
||||||
boolean signal)
|
|
||||||
{
|
|
||||||
boolean isVisible = visibleThread == threadId;
|
|
||||||
|
|
||||||
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
|
|
||||||
Recipient recipients = DatabaseFactory.getThreadDatabase(context)
|
|
||||||
.getRecipientForThreadId(threadId);
|
|
||||||
|
|
||||||
if (isVisible) {
|
|
||||||
List<MarkedMessageInfo> messageIds = threads.setRead(threadId, false);
|
|
||||||
MarkReadReceiver.process(context, messageIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TextSecurePreferences.isNotificationsEnabled(context) ||
|
|
||||||
(recipients != null && recipients.isMuted()))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVisible) {
|
|
||||||
sendInThreadNotification(context, threads.getRecipientForThreadId(threadId));
|
|
||||||
} else {
|
|
||||||
updateNotification(context, threadId, signal, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void updateNotification(@NonNull Context context,
|
|
||||||
long targetThread,
|
|
||||||
boolean signal,
|
|
||||||
int reminderCount)
|
|
||||||
{
|
|
||||||
Cursor telcoCursor = null;
|
|
||||||
Cursor pushCursor = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
telcoCursor = DatabaseFactory.getMmsSmsDatabase(context).getUnread();
|
|
||||||
pushCursor = DatabaseFactory.getPushDatabase(context).getPending();
|
|
||||||
|
|
||||||
if ((telcoCursor == null || telcoCursor.isAfterLast()) &&
|
|
||||||
(pushCursor == null || pushCursor.isAfterLast()))
|
|
||||||
{
|
|
||||||
cancelActiveNotifications(context);
|
|
||||||
updateBadge(context, 0);
|
|
||||||
clearReminder(context);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationState notificationState = constructNotificationState(context, telcoCursor);
|
|
||||||
|
|
||||||
if (signal && (System.currentTimeMillis() - lastAudibleNotification) < MIN_AUDIBLE_PERIOD_MILLIS) {
|
|
||||||
signal = false;
|
|
||||||
} else if (signal) {
|
|
||||||
lastAudibleNotification = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notificationState.hasMultipleThreads()) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
for (long threadId : notificationState.getThreads()) {
|
|
||||||
if (targetThread < 1 || targetThread == threadId) {
|
|
||||||
sendSingleThreadNotification(context,
|
|
||||||
new NotificationState(notificationState.getNotificationsForThread(threadId)),
|
|
||||||
signal && (threadId == targetThread),
|
|
||||||
true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendMultipleThreadNotification(context, notificationState, signal && (Build.VERSION.SDK_INT < 23));
|
|
||||||
} else {
|
|
||||||
sendSingleThreadNotification(context, notificationState, signal, false);
|
|
||||||
|
|
||||||
if (isDisplayingSummaryNotification(context)) {
|
|
||||||
sendMultipleThreadNotification(context, notificationState, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelOrphanedNotifications(context, notificationState);
|
|
||||||
updateBadge(context, notificationState.getMessageCount());
|
|
||||||
|
|
||||||
if (signal) {
|
|
||||||
scheduleReminder(context, reminderCount);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (telcoCursor != null) telcoCursor.close();
|
|
||||||
if (pushCursor != null) pushCursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sendSingleThreadNotification(@NonNull Context context,
|
|
||||||
@NonNull NotificationState notificationState,
|
|
||||||
boolean signal,
|
|
||||||
boolean bundled)
|
|
||||||
{
|
|
||||||
Log.i(TAG, "sendSingleThreadNotification() signal: " + signal + " bundled: " + bundled);
|
|
||||||
|
|
||||||
if (notificationState.getNotifications().isEmpty()) {
|
|
||||||
if (!bundled) cancelActiveNotifications(context);
|
|
||||||
Log.i(TAG, "[sendSingleThreadNotification] Empty notification state. Skipping.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
|
|
||||||
List<NotificationItem> notifications = notificationState.getNotifications();
|
|
||||||
Recipient recipient = notifications.get(0).getRecipient();
|
|
||||||
int notificationId;
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
notificationId = NotificationIds.getNotificationIdForThread(notifications.get(0).getThreadId());
|
|
||||||
} else {
|
|
||||||
notificationId = NotificationIds.MESSAGE_SUMMARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.setThread(notifications.get(0).getRecipient());
|
|
||||||
builder.setMessageCount(notificationState.getMessageCount());
|
|
||||||
builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(),
|
|
||||||
notifications.get(0).getText(), notifications.get(0).getSlideDeck());
|
|
||||||
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
|
|
||||||
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
|
|
||||||
builder.setOnlyAlertOnce(!signal);
|
|
||||||
builder.setSortKey(String.valueOf(Long.MAX_VALUE - notifications.get(0).getTimestamp()));
|
|
||||||
|
|
||||||
long timestamp = notifications.get(0).getTimestamp();
|
|
||||||
if (timestamp != 0) builder.setWhen(timestamp);
|
|
||||||
|
|
||||||
if (!KeyCachingService.isLocked(context) && RecipientUtil.isMessageRequestAccepted(context, recipient.resolve())) {
|
|
||||||
ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient);
|
|
||||||
|
|
||||||
builder.addActions(notificationState.getMarkAsReadIntent(context, notificationId),
|
|
||||||
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()),
|
|
||||||
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient(), replyMethod),
|
|
||||||
replyMethod);
|
|
||||||
|
|
||||||
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()),
|
|
||||||
notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
|
|
||||||
|
|
||||||
while(iterator.hasPrevious()) {
|
|
||||||
NotificationItem item = iterator.previous();
|
|
||||||
builder.addMessageBody(item.getRecipient(), item.getIndividualRecipient(), item.getText(), item.getTimestamp());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal) {
|
|
||||||
builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate());
|
|
||||||
builder.setTicker(notifications.get(0).getIndividualRecipient(),
|
|
||||||
notifications.get(0).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
builder.setGroup(NOTIFICATION_GROUP);
|
|
||||||
builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification notification = builder.build();
|
|
||||||
NotificationManagerCompat.from(context).notify(notificationId, notification);
|
|
||||||
Log.i(TAG, "Posted notification. " + notification.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sendMultipleThreadNotification(@NonNull Context context,
|
|
||||||
@NonNull NotificationState notificationState,
|
|
||||||
boolean signal)
|
|
||||||
{
|
|
||||||
Log.i(TAG, "sendMultiThreadNotification() signal: " + signal);
|
|
||||||
|
|
||||||
if (notificationState.getNotifications().isEmpty()) {
|
|
||||||
Log.i(TAG, "[sendMultiThreadNotification] Empty notification state. Skipping.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MultipleRecipientNotificationBuilder builder = new MultipleRecipientNotificationBuilder(context, TextSecurePreferences.getNotificationPrivacy(context));
|
|
||||||
List<NotificationItem> notifications = notificationState.getNotifications();
|
|
||||||
|
|
||||||
builder.setMessageCount(notificationState.getMessageCount(), notificationState.getThreadCount());
|
|
||||||
builder.setMostRecentSender(notifications.get(0).getIndividualRecipient());
|
|
||||||
builder.setDeleteIntent(notificationState.getDeleteIntent(context));
|
|
||||||
builder.setOnlyAlertOnce(!signal);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 23) {
|
|
||||||
builder.setGroup(NOTIFICATION_GROUP);
|
|
||||||
builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN);
|
|
||||||
}
|
|
||||||
|
|
||||||
long timestamp = notifications.get(0).getTimestamp();
|
|
||||||
if (timestamp != 0) builder.setWhen(timestamp);
|
|
||||||
|
|
||||||
builder.addActions(notificationState.getMarkAsReadIntent(context, NotificationIds.MESSAGE_SUMMARY));
|
|
||||||
|
|
||||||
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
|
|
||||||
|
|
||||||
while(iterator.hasPrevious()) {
|
|
||||||
NotificationItem item = iterator.previous();
|
|
||||||
builder.addMessageBody(item.getIndividualRecipient(), item.getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal) {
|
|
||||||
builder.setAlarms(notificationState.getRingtone(context), notificationState.getVibrate());
|
|
||||||
builder.setTicker(notifications.get(0).getIndividualRecipient(),
|
|
||||||
notifications.get(0).getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification notification = builder.build();
|
|
||||||
NotificationManagerCompat.from(context).notify(NotificationIds.MESSAGE_SUMMARY, builder.build());
|
|
||||||
Log.i(TAG, "Posted notification. " + notification.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void sendInThreadNotification(Context context, Recipient recipient) {
|
|
||||||
if (!TextSecurePreferences.isInThreadNotifications(context) ||
|
|
||||||
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Uri uri = null;
|
|
||||||
if (recipient != null) {
|
|
||||||
uri = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context, recipient) : recipient.getMessageRingtone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uri == null) {
|
|
||||||
uri = NotificationChannels.supported() ? NotificationChannels.getMessageRingtone(context) : TextSecurePreferences.getNotificationRingtone(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uri.toString().isEmpty()) {
|
|
||||||
Log.d(TAG, "ringtone uri is empty");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ringtone ringtone = RingtoneManager.getRingtone(context, uri);
|
|
||||||
|
|
||||||
if (ringtone == null) {
|
|
||||||
Log.w(TAG, "ringtone is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 21) {
|
|
||||||
ringtone.setAudioAttributes(new AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
|
|
||||||
.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT)
|
|
||||||
.build());
|
|
||||||
} else {
|
|
||||||
ringtone.setStreamType(AudioManager.STREAM_NOTIFICATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
ringtone.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static NotificationState constructNotificationState(@NonNull Context context,
|
|
||||||
@NonNull Cursor cursor)
|
|
||||||
{
|
|
||||||
NotificationState notificationState = new NotificationState();
|
|
||||||
MmsSmsDatabase.Reader reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor);
|
|
||||||
|
|
||||||
MessageRecord record;
|
|
||||||
|
|
||||||
while ((record = reader.getNext()) != null) {
|
|
||||||
long id = record.getId();
|
|
||||||
boolean mms = record.isMms() || record.isMmsNotification();
|
|
||||||
Recipient recipient = record.getIndividualRecipient().resolve();
|
|
||||||
Recipient conversationRecipient = record.getRecipient().resolve();
|
|
||||||
long threadId = record.getThreadId();
|
|
||||||
CharSequence body = record.getDisplayBody(context);
|
|
||||||
Recipient threadRecipients = null;
|
|
||||||
SlideDeck slideDeck = null;
|
|
||||||
long timestamp = record.getTimestamp();
|
|
||||||
long receivedTimestamp = record.getDateReceived();
|
|
||||||
boolean isUnreadMessage = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.READ)) == 0;
|
|
||||||
boolean hasUnreadReactions = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_UNREAD)) == 1;
|
|
||||||
long lastReactionRead = cursor.getLong(cursor.getColumnIndexOrThrow(MmsSmsColumns.REACTIONS_LAST_SEEN));
|
|
||||||
|
|
||||||
if (threadId != -1) {
|
|
||||||
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnreadMessage) {
|
|
||||||
if (KeyCachingService.isLocked(context)) {
|
|
||||||
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_locked_message));
|
|
||||||
} else if (record.isMms() && !((MmsMessageRecord) record).getSharedContacts().isEmpty()) {
|
|
||||||
Contact contact = ((MmsMessageRecord) record).getSharedContacts().get(0);
|
|
||||||
body = ContactUtil.getStringSummary(context, contact);
|
|
||||||
} else if (record.isMms() && ((MmsMessageRecord) record).getSlideDeck().getStickerSlide() != null) {
|
|
||||||
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_sticker));
|
|
||||||
slideDeck = ((MmsMessageRecord) record).getSlideDeck();
|
|
||||||
} else if (record.isMms() && ((MmsMessageRecord) record).isViewOnce()) {
|
|
||||||
body = SpanUtil.italic(context.getString(getViewOnceDescription((MmsMessageRecord) record)));
|
|
||||||
} else if (record.isRemoteDelete()) {
|
|
||||||
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_this_message_was_deleted));;
|
|
||||||
} else if (record.isMms() && TextUtils.isEmpty(body) && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
|
|
||||||
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_media_message));
|
|
||||||
slideDeck = ((MediaMmsMessageRecord) record).getSlideDeck();
|
|
||||||
} else if (record.isMms() && !record.isMmsNotification() && !((MmsMessageRecord) record).getSlideDeck().getSlides().isEmpty()) {
|
|
||||||
String message = context.getString(R.string.MessageNotifier_media_message_with_text, body);
|
|
||||||
int italicLength = message.length() - body.length();
|
|
||||||
body = SpanUtil.italic(message, italicLength);
|
|
||||||
slideDeck = ((MediaMmsMessageRecord) record).getSlideDeck();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (threadRecipients == null || !threadRecipients.isMuted()) {
|
|
||||||
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, receivedTimestamp, slideDeck, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasUnreadReactions) {
|
|
||||||
for (ReactionRecord reaction : record.getReactions()) {
|
|
||||||
Recipient reactionSender = Recipient.resolved(reaction.getAuthor());
|
|
||||||
if (reactionSender.equals(Recipient.self()) || !record.isOutgoing() || reaction.getDateReceived() <= lastReactionRead) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyCachingService.isLocked(context)) {
|
|
||||||
body = SpanUtil.italic(context.getString(R.string.MessageNotifier_locked_message));
|
|
||||||
} else {
|
|
||||||
String text = SpanUtil.italic(getReactionMessageBody(context, record)).toString();
|
|
||||||
String[] parts = text.split(EMOJI_REPLACEMENT_STRING);
|
|
||||||
|
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
|
||||||
for (int i = 0; i < parts.length; i++) {
|
|
||||||
builder.append(SpanUtil.italic(parts[i]));
|
|
||||||
|
|
||||||
if (i != parts.length -1) {
|
|
||||||
builder.append(reaction.getEmoji());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (text.endsWith(EMOJI_REPLACEMENT_STRING)) {
|
|
||||||
builder.append(reaction.getEmoji());
|
|
||||||
}
|
|
||||||
|
|
||||||
body = builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (threadRecipients == null || !threadRecipients.isMuted()) {
|
|
||||||
notificationState.addNotification(new NotificationItem(id, mms, reactionSender, conversationRecipient, threadRecipients, threadId, body, reaction.getDateReceived(), receivedTimestamp, null, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.close();
|
|
||||||
return notificationState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CharSequence getReactionMessageBody(@NonNull Context context, @NonNull MessageRecord record) {
|
|
||||||
CharSequence body = record.getDisplayBody(context);
|
|
||||||
boolean bodyIsEmpty = TextUtils.isEmpty(body);
|
|
||||||
|
|
||||||
if (MessageRecordUtil.hasSharedContact(record)) {
|
|
||||||
Contact contact = ((MmsMessageRecord) record).getSharedContacts().get(0);
|
|
||||||
CharSequence summary = ContactUtil.getStringSummary(context, contact);
|
|
||||||
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, summary);
|
|
||||||
} else if (MessageRecordUtil.hasSticker(record)) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_sticker, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (record.isMms() && record.isViewOnce() && MediaUtil.isVideoType(getMessageContentType((MmsMessageRecord) record))) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_view_once_video, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (record.isMms() && record.isViewOnce()){
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_view_once_photo, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (!bodyIsEmpty) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, body);
|
|
||||||
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isVideoType(getMessageContentType((MmsMessageRecord) record))) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_video, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isImageType(getMessageContentType((MmsMessageRecord) record))) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_image, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (MessageRecordUtil.isMediaMessage(record) && MediaUtil.isAudioType(getMessageContentType((MmsMessageRecord) record))) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_audio, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else if (MessageRecordUtil.isMediaMessage(record)) {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_your_file, EMOJI_REPLACEMENT_STRING);
|
|
||||||
} else {
|
|
||||||
return context.getString(R.string.MessageNotifier_reacted_s_to_s, EMOJI_REPLACEMENT_STRING, body);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @StringRes int getViewOnceDescription(@NonNull MmsMessageRecord messageRecord) {
|
|
||||||
final String contentType = getMessageContentType(messageRecord);
|
|
||||||
|
|
||||||
if (MediaUtil.isImageType(contentType)) {
|
|
||||||
return R.string.MessageNotifier_view_once_photo;
|
|
||||||
}
|
|
||||||
return R.string.MessageNotifier_view_once_video;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getMessageContentType(@NonNull MmsMessageRecord messageRecord) {
|
|
||||||
Slide thumbnailSlide = messageRecord.getSlideDeck().getThumbnailSlide();
|
|
||||||
if (thumbnailSlide == null) {
|
|
||||||
Log.w(TAG, "Could not distinguish view-once content type from message record, defaulting to JPEG");
|
|
||||||
return MediaUtil.IMAGE_JPEG;
|
|
||||||
}
|
|
||||||
return thumbnailSlide.getContentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void updateBadge(Context context, int count) {
|
|
||||||
try {
|
|
||||||
if (count == 0) ShortcutBadger.removeCount(context);
|
|
||||||
else ShortcutBadger.applyCount(context, count);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
// NOTE :: I don't totally trust this thing, so I'm catching
|
|
||||||
// everything.
|
|
||||||
Log.w(TAG, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void scheduleReminder(Context context, 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.MINUTES.toMillis(2);
|
|
||||||
|
|
||||||
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public 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";
|
public static final String REMINDER_ACTION = "org.thoughtcrime.securesms.MessageNotifier.REMINDER_ACTION";
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(final Context context, final Intent intent) {
|
public void onReceive(final Context context, final Intent intent) {
|
||||||
new AsyncTask<Void, Void, Void>() {
|
SignalExecutors.BOUNDED.execute(() -> {
|
||||||
@Override
|
int reminderCount = intent.getIntExtra("reminder_count", 0);
|
||||||
protected Void doInBackground(Void... params) {
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, -1, true, reminderCount + 1);
|
||||||
int reminderCount = intent.getIntExtra("reminder_count", 0);
|
});
|
||||||
MessageNotifier.updateNotification(context, -1, true, reminderCount + 1);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class DelayedNotification implements Runnable {
|
|
||||||
|
|
||||||
private static final long DELAY = TimeUnit.SECONDS.toMillis(5);
|
|
||||||
|
|
||||||
private final AtomicBoolean canceled = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
private final Context context;
|
|
||||||
private final long threadId;
|
|
||||||
private final long delayUntil;
|
|
||||||
|
|
||||||
private DelayedNotification(Context context, long threadId) {
|
|
||||||
this.context = context;
|
|
||||||
this.threadId = threadId;
|
|
||||||
this.delayUntil = System.currentTimeMillis() + DELAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
long delayMillis = delayUntil - System.currentTimeMillis();
|
|
||||||
Log.i(TAG, "Waiting to notify: " + delayMillis);
|
|
||||||
|
|
||||||
if (delayMillis > 0) {
|
|
||||||
Util.sleep(delayMillis);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canceled.get()) {
|
|
||||||
Log.i(TAG, "Not canceled, notifying...");
|
|
||||||
MessageNotifier.updateNotification(context, threadId, true);
|
|
||||||
MessageNotifier.cancelDelayedNotifications();
|
|
||||||
} else {
|
|
||||||
Log.w(TAG, "Canceled, not notifying...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
canceled.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class CancelableExecutor {
|
|
||||||
|
|
||||||
private final Executor executor = Executors.newSingleThreadExecutor();
|
|
||||||
private final Set<DelayedNotification> tasks = new HashSet<>();
|
|
||||||
|
|
||||||
public void execute(final DelayedNotification runnable) {
|
|
||||||
synchronized (tasks) {
|
|
||||||
tasks.add(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
Runnable wrapper = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runnable.run();
|
|
||||||
|
|
||||||
synchronized (tasks) {
|
|
||||||
tasks.remove(runnable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
executor.execute(wrapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
synchronized (tasks) {
|
|
||||||
for (DelayedNotification task : tasks) {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import androidx.core.app.RemoteInput;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
@ -59,7 +60,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
final RecipientId recipientId = intent.getParcelableExtra(RECIPIENT_EXTRA);
|
final RecipientId recipientId = intent.getParcelableExtra(RECIPIENT_EXTRA);
|
||||||
final ReplyMethod replyMethod = (ReplyMethod) intent.getSerializableExtra(REPLY_METHOD);
|
final ReplyMethod replyMethod = (ReplyMethod) intent.getSerializableExtra(REPLY_METHOD);
|
||||||
final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_REMOTE_REPLY);
|
final CharSequence responseText = remoteInput.getCharSequence(DefaultMessageNotifier.EXTRA_REMOTE_REPLY);
|
||||||
|
|
||||||
if (recipientId == null) throw new AssertionError("No recipientId specified");
|
if (recipientId == null) throw new AssertionError("No recipientId specified");
|
||||||
if (replyMethod == null) throw new AssertionError("No reply method specified");
|
if (replyMethod == null) throw new AssertionError("No reply method specified");
|
||||||
@ -96,7 +97,7 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
|
List<MarkedMessageInfo> messageIds = DatabaseFactory.getThreadDatabase(context).setRead(threadId, true);
|
||||||
|
|
||||||
MessageNotifier.updateNotification(context);
|
ApplicationDependencies.getMessageNotifier().updateNotification(context);
|
||||||
MarkReadReceiver.process(context, messageIds);
|
MarkReadReceiver.process(context, messageIds);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -176,7 +176,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp,
|
replyAction = new Action.Builder(R.drawable.ic_reply_white_36dp,
|
||||||
actionName,
|
actionName,
|
||||||
wearableReplyIntent)
|
wearableReplyIntent)
|
||||||
.addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY)
|
.addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY)
|
||||||
.setLabel(label).build())
|
.setLabel(label).build())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
|||||||
Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
|
Action wearableReplyAction = new Action.Builder(R.drawable.ic_reply,
|
||||||
actionName,
|
actionName,
|
||||||
wearableReplyIntent)
|
wearableReplyIntent)
|
||||||
.addRemoteInput(new RemoteInput.Builder(MessageNotifier.EXTRA_REMOTE_REPLY)
|
.addRemoteInput(new RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY)
|
||||||
.setLabel(label).build())
|
.setLabel(label).build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import android.text.TextUtils;
|
|||||||
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
|
||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
|
|||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
MessageNotifier.updateNotification(getActivity());
|
ApplicationDependencies.getMessageNotifier().updateNotification(getActivity());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
@ -33,6 +33,7 @@ import androidx.core.app.NotificationCompat;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.MainActivity;
|
import org.thoughtcrime.securesms.MainActivity;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.DummyActivity;
|
import org.thoughtcrime.securesms.DummyActivity;
|
||||||
@ -41,7 +42,6 @@ import org.thoughtcrime.securesms.crypto.InvalidPassphraseException;
|
|||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||||
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
@ -115,7 +115,7 @@ public class KeyCachingService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
if (!ApplicationMigrations.isUpdate(KeyCachingService.this)) {
|
if (!ApplicationMigrations.isUpdate(KeyCachingService.this)) {
|
||||||
MessageNotifier.updateNotification(KeyCachingService.this);
|
ApplicationDependencies.getMessageNotifier().updateNotification(KeyCachingService.this);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ public class KeyCachingService extends Service {
|
|||||||
new AsyncTask<Void, Void, Void>() {
|
new AsyncTask<Void, Void, Void>() {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... params) {
|
protected Void doInBackground(Void... params) {
|
||||||
MessageNotifier.updateNotification(KeyCachingService.this);
|
ApplicationDependencies.getMessageNotifier().updateNotification(KeyCachingService.this);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
@ -5,7 +5,6 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -34,7 +33,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|||||||
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
import org.thoughtcrime.securesms.events.WebRtcViewModel;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.notifications.DoNotDisturbUtil;
|
import org.thoughtcrime.securesms.notifications.DoNotDisturbUtil;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||||
import org.thoughtcrime.securesms.ringrtc.CallState;
|
import org.thoughtcrime.securesms.ringrtc.CallState;
|
||||||
@ -58,10 +56,8 @@ import org.thoughtcrime.securesms.webrtc.audio.OutgoingRinger;
|
|||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
||||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
||||||
import org.webrtc.EglBase;
|
import org.webrtc.EglBase;
|
||||||
import org.webrtc.EglRenderer;
|
|
||||||
import org.webrtc.IceCandidate;
|
import org.webrtc.IceCandidate;
|
||||||
import org.webrtc.PeerConnection;
|
import org.webrtc.PeerConnection;
|
||||||
import org.webrtc.SurfaceViewRenderer;
|
|
||||||
import org.whispersystems.libsignal.IdentityKey;
|
import org.whispersystems.libsignal.IdentityKey;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||||
@ -455,7 +451,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
|
|||||||
|
|
||||||
private void insertMissedCall(@NonNull RemotePeer remotePeer, boolean signal) {
|
private void insertMissedCall(@NonNull RemotePeer remotePeer, boolean signal) {
|
||||||
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getSmsDatabase(this).insertMissedCall(remotePeer.getId());
|
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getSmsDatabase(this).insertMissedCall(remotePeer.getId());
|
||||||
MessageNotifier.updateNotification(this, messageAndThreadId.second, signal);
|
ApplicationDependencies.getMessageNotifier().updateNotification(this, messageAndThreadId.second, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDenyCall(Intent intent) {
|
private void handleDenyCall(Intent intent) {
|
||||||
|
@ -16,8 +16,8 @@ import org.thoughtcrime.securesms.database.IdentityDatabase;
|
|||||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||||
import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage;
|
import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage;
|
||||||
@ -141,7 +141,7 @@ public class IdentityUtil {
|
|||||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);
|
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);
|
||||||
|
|
||||||
if (insertResult.isPresent()) {
|
if (insertResult.isPresent()) {
|
||||||
MessageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
ApplicationDependencies.getMessageNotifier().updateNotification(context, insertResult.get().getThreadId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user