mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-27 14:40:22 +00:00
Fix too many pending intents crashes.
This commit is contained in:
@@ -285,16 +285,18 @@ class DefaultMessageNotifier(context: Application) : MessageNotifier {
|
||||
}
|
||||
|
||||
val alarmManager: AlarmManager? = ContextCompat.getSystemService(context, AlarmManager::class.java)
|
||||
val pendingIntent: PendingIntent = PendingIntent.getBroadcast(context, 0, Intent(context, ReminderReceiver::class.java), PendingIntentFlags.updateCurrent())
|
||||
alarmManager?.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent)
|
||||
lastScheduledReminder = System.currentTimeMillis()
|
||||
val pendingIntent: PendingIntent? = NotificationPendingIntentHelper.getBroadcast(context, 0, Intent(context, ReminderReceiver::class.java), PendingIntentFlags.updateCurrent())
|
||||
if (pendingIntent != null) {
|
||||
alarmManager?.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent)
|
||||
lastScheduledReminder = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearReminderInternal(context: Context) {
|
||||
lastScheduledReminder = 0
|
||||
threadReminders.clear()
|
||||
|
||||
val pendingIntent: PendingIntent? = PendingIntent.getBroadcast(context, 0, Intent(context, ReminderReceiver::class.java), PendingIntentFlags.cancelCurrent())
|
||||
val pendingIntent: PendingIntent? = NotificationPendingIntentHelper.getBroadcast(context, 0, Intent(context, ReminderReceiver::class.java), PendingIntentFlags.cancelCurrent())
|
||||
if (pendingIntent != null) {
|
||||
val alarmManager: AlarmManager? = ContextCompat.getSystemService(context, AlarmManager::class.java)
|
||||
alarmManager?.cancel(pendingIntent)
|
||||
|
||||
@@ -70,7 +70,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
||||
abstract fun setPriority(priority: Int)
|
||||
abstract fun setAlarms(recipient: Recipient?)
|
||||
abstract fun setTicker(ticker: CharSequence?)
|
||||
abstract fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent)
|
||||
abstract fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent?)
|
||||
abstract fun setAutoCancel(autoCancel: Boolean)
|
||||
abstract fun setLocusIdActual(locusId: String)
|
||||
abstract fun build(): Notification
|
||||
@@ -189,58 +189,72 @@ sealed class NotificationBuilder(protected val context: Context) {
|
||||
val builder: NotificationCompat.Builder = NotificationCompat.Builder(context, NotificationChannels.getMessagesChannel(context))
|
||||
|
||||
override fun addActions(replyMethod: ReplyMethod, conversation: NotificationConversation) {
|
||||
val markAsRead: PendingIntent = conversation.getMarkAsReadIntent(context)
|
||||
val markAsReadAction: NotificationCompat.Action = NotificationCompat.Action.Builder(R.drawable.check, context.getString(R.string.MessageNotifier_mark_read), markAsRead)
|
||||
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ)
|
||||
.setShowsUserInterface(false)
|
||||
.build()
|
||||
|
||||
val extender: NotificationCompat.WearableExtender = NotificationCompat.WearableExtender()
|
||||
|
||||
builder.addAction(markAsReadAction)
|
||||
extender.addAction(markAsReadAction)
|
||||
val markAsRead: PendingIntent? = conversation.getMarkAsReadIntent(context)
|
||||
if (markAsRead != null) {
|
||||
val markAsReadAction: NotificationCompat.Action =
|
||||
NotificationCompat.Action.Builder(R.drawable.check, context.getString(R.string.MessageNotifier_mark_read), markAsRead)
|
||||
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ)
|
||||
.setShowsUserInterface(false)
|
||||
.build()
|
||||
|
||||
builder.addAction(markAsReadAction)
|
||||
extender.addAction(markAsReadAction)
|
||||
}
|
||||
|
||||
if (conversation.mostRecentNotification.canReply(context)) {
|
||||
val quickReply: PendingIntent = conversation.getQuickReplyIntent(context)
|
||||
val remoteReply: PendingIntent = conversation.getRemoteReplyIntent(context, replyMethod)
|
||||
val quickReply: PendingIntent? = conversation.getQuickReplyIntent(context)
|
||||
val remoteReply: PendingIntent? = conversation.getRemoteReplyIntent(context, replyMethod)
|
||||
|
||||
val actionName: String = context.getString(R.string.MessageNotifier_reply)
|
||||
val label: String = context.getString(replyMethod.toLongDescription())
|
||||
val replyAction: NotificationCompat.Action = if (Build.VERSION.SDK_INT >= 24) {
|
||||
val replyAction: NotificationCompat.Action? = if (Build.VERSION.SDK_INT >= 24 && remoteReply != null) {
|
||||
NotificationCompat.Action.Builder(R.drawable.ic_reply_white_36dp, actionName, remoteReply)
|
||||
.addRemoteInput(RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build())
|
||||
.setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY)
|
||||
.setShowsUserInterface(false)
|
||||
.build()
|
||||
} else {
|
||||
} else if (quickReply != null) {
|
||||
NotificationCompat.Action(R.drawable.ic_reply_white_36dp, actionName, quickReply)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val wearableReplyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, actionName, remoteReply)
|
||||
.addRemoteInput(RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build())
|
||||
.build()
|
||||
|
||||
builder.addAction(replyAction)
|
||||
extender.addAction(wearableReplyAction)
|
||||
|
||||
if (remoteReply != null) {
|
||||
val wearableReplyAction = NotificationCompat.Action.Builder(R.drawable.ic_reply, actionName, remoteReply)
|
||||
.addRemoteInput(RemoteInput.Builder(DefaultMessageNotifier.EXTRA_REMOTE_REPLY).setLabel(label).build())
|
||||
.build()
|
||||
|
||||
extender.addAction(wearableReplyAction)
|
||||
}
|
||||
}
|
||||
|
||||
builder.extend(extender)
|
||||
}
|
||||
|
||||
override fun addMarkAsReadActionActual(state: NotificationState) {
|
||||
val markAllAsReadAction = NotificationCompat.Action(R.drawable.check, context.getString(R.string.MessageNotifier_mark_all_as_read), state.getMarkAsReadIntent(context))
|
||||
builder.addAction(markAllAsReadAction)
|
||||
builder.extend(NotificationCompat.WearableExtender().addAction(markAllAsReadAction))
|
||||
val markAsRead: PendingIntent? = state.getMarkAsReadIntent(context)
|
||||
|
||||
if (markAsRead != null) {
|
||||
val markAllAsReadAction = NotificationCompat.Action(R.drawable.check, context.getString(R.string.MessageNotifier_mark_all_as_read), markAsRead)
|
||||
builder.addAction(markAllAsReadAction)
|
||||
builder.extend(NotificationCompat.WearableExtender().addAction(markAllAsReadAction))
|
||||
}
|
||||
}
|
||||
|
||||
override fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent) {
|
||||
val turnOffTheseNotifications = NotificationCompat.Action(
|
||||
R.drawable.check,
|
||||
context.getString(R.string.MessageNotifier_turn_off_these_notifications),
|
||||
pendingIntent
|
||||
)
|
||||
override fun addTurnOffJoinedNotificationsAction(pendingIntent: PendingIntent?) {
|
||||
if (pendingIntent != null) {
|
||||
val turnOffTheseNotifications = NotificationCompat.Action(
|
||||
R.drawable.check,
|
||||
context.getString(R.string.MessageNotifier_turn_off_these_notifications),
|
||||
pendingIntent
|
||||
)
|
||||
|
||||
builder.addAction(turnOffTheseNotifications)
|
||||
builder.addAction(turnOffTheseNotifications)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addMessagesActual(conversation: NotificationConversation, includeShortcut: Boolean) {
|
||||
@@ -338,20 +352,22 @@ sealed class NotificationBuilder(protected val context: Context) {
|
||||
return
|
||||
}
|
||||
|
||||
val intent = PendingIntent.getActivity(
|
||||
val intent: PendingIntent? = NotificationPendingIntentHelper.getActivity(
|
||||
context,
|
||||
0,
|
||||
ConversationIntents.createBubbleIntent(context, conversation.recipient.id, conversation.thread.threadId),
|
||||
mutable()
|
||||
)
|
||||
|
||||
val bubbleMetadata = NotificationCompat.BubbleMetadata.Builder(intent, AvatarUtil.getIconCompatForShortcut(context, conversation.recipient))
|
||||
.setAutoExpandBubble(bubbleState === BubbleUtil.BubbleState.SHOWN)
|
||||
.setDesiredHeight(600)
|
||||
.setSuppressNotification(bubbleState === BubbleUtil.BubbleState.SHOWN)
|
||||
.build()
|
||||
if (intent != null) {
|
||||
val bubbleMetadata = NotificationCompat.BubbleMetadata.Builder(intent, AvatarUtil.getIconCompatForShortcut(context, conversation.recipient))
|
||||
.setAutoExpandBubble(bubbleState === BubbleUtil.BubbleState.SHOWN)
|
||||
.setDesiredHeight(600)
|
||||
.setSuppressNotification(bubbleState === BubbleUtil.BubbleState.SHOWN)
|
||||
.build()
|
||||
|
||||
builder.bubbleMetadata = bubbleMetadata
|
||||
builder.bubbleMetadata = bubbleMetadata
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLights(@ColorInt color: Int, onTime: Int, offTime: Int) {
|
||||
|
||||
@@ -140,7 +140,10 @@ data class NotificationConversation(
|
||||
} catch (e: NullPointerException) {
|
||||
Log.w(NotificationFactory.TAG, "Vivo device quirk sometimes throws NPE", e)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
PendingIntent.getActivity(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
NotificationPendingIntentHelper.getActivity(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(NotificationFactory.TAG, "TaskStackBuilder too many pending intents device quirk: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,28 +162,28 @@ data class NotificationConversation(
|
||||
.putParcelableArrayListExtra(DeleteNotificationReceiver.EXTRA_THREADS, arrayListOf(thread))
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getMarkAsReadIntent(context: Context): PendingIntent {
|
||||
fun getMarkAsReadIntent(context: Context): PendingIntent? {
|
||||
val intent = Intent(context, MarkReadReceiver::class.java)
|
||||
.setAction(MarkReadReceiver.CLEAR_ACTION)
|
||||
.putParcelableArrayListExtra(MarkReadReceiver.THREADS_EXTRA, arrayListOf(mostRecentNotification.thread))
|
||||
.putExtra(MarkReadReceiver.NOTIFICATION_ID_EXTRA, notificationId)
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getBroadcast(context, (thread.threadId * 2).toInt(), intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getBroadcast(context, (thread.threadId * 2).toInt(), intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getQuickReplyIntent(context: Context): PendingIntent {
|
||||
fun getQuickReplyIntent(context: Context): PendingIntent? {
|
||||
val intent: Intent = ConversationIntents.createPopUpBuilder(context, recipient.id, mostRecentNotification.thread.threadId)
|
||||
.build()
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getActivity(context, (thread.threadId * 2).toInt() + 1, intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getActivity(context, (thread.threadId * 2).toInt() + 1, intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getRemoteReplyIntent(context: Context, replyMethod: ReplyMethod): PendingIntent {
|
||||
fun getRemoteReplyIntent(context: Context, replyMethod: ReplyMethod): PendingIntent? {
|
||||
val intent = Intent(context, RemoteReplyReceiver::class.java)
|
||||
.setAction(RemoteReplyReceiver.REPLY_ACTION)
|
||||
.putExtra(RemoteReplyReceiver.RECIPIENT_EXTRA, recipient.id)
|
||||
@@ -189,11 +192,11 @@ data class NotificationConversation(
|
||||
.putExtra(RemoteReplyReceiver.GROUP_STORY_ID_EXTRA, notificationItems.first().thread.groupStoryId ?: Long.MIN_VALUE)
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getBroadcast(context, (thread.threadId * 2).toInt() + 1, intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getBroadcast(context, (thread.threadId * 2).toInt() + 1, intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getTurnOffJoinedNotificationsIntent(context: Context): PendingIntent {
|
||||
return PendingIntent.getActivity(
|
||||
fun getTurnOffJoinedNotificationsIntent(context: Context): PendingIntent? {
|
||||
return NotificationPendingIntentHelper.getActivity(
|
||||
context,
|
||||
0,
|
||||
TurnOffContactJoinedNotificationsActivity.newIntent(context, thread.threadId),
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.notifications.v2
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
@@ -240,7 +239,7 @@ object NotificationFactory {
|
||||
setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_CHILDREN)
|
||||
setChannelId(NotificationChannels.getMessagesChannel(context))
|
||||
setContentTitle(context.getString(R.string.app_name))
|
||||
setContentIntent(PendingIntent.getActivity(context, 0, MainActivity.clearTop(context), PendingIntentFlags.mutable()))
|
||||
setContentIntent(NotificationPendingIntentHelper.getActivity(context, 0, MainActivity.clearTop(context), PendingIntentFlags.mutable()))
|
||||
setGroupSummary(true)
|
||||
setSubText(context.getString(R.string.MessageNotifier_d_new_messages_in_d_conversations, state.messageCount, state.threadCount))
|
||||
setContentInfo(state.messageCount.toString())
|
||||
@@ -321,7 +320,7 @@ object NotificationFactory {
|
||||
setContentTitle(context.getString(R.string.MessageNotifier_message_delivery_failed))
|
||||
setContentText(context.getString(R.string.MessageNotifier_failed_to_deliver_message))
|
||||
setTicker(context.getString(R.string.MessageNotifier_error_delivering_message))
|
||||
setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntentFlags.mutable()))
|
||||
setContentIntent(NotificationPendingIntentHelper.getActivity(context, 0, intent, PendingIntentFlags.mutable()))
|
||||
setAutoCancel(true)
|
||||
setAlarms(recipient)
|
||||
setChannelId(NotificationChannels.FAILURES)
|
||||
@@ -350,7 +349,7 @@ object NotificationFactory {
|
||||
setLargeIcon(BitmapFactory.decodeResource(context.resources, R.drawable.ic_info_outline))
|
||||
setContentTitle(context.getString(R.string.MessageNotifier_message_delivery_paused))
|
||||
setContentText(context.getString(R.string.MessageNotifier_verify_to_continue_messaging_on_signal))
|
||||
setContentIntent(PendingIntent.getActivity(context, 0, intent, PendingIntentFlags.mutable()))
|
||||
setContentIntent(NotificationPendingIntentHelper.getActivity(context, 0, intent, PendingIntentFlags.mutable()))
|
||||
setOnlyAlertOnce(true)
|
||||
setAutoCancel(true)
|
||||
setAlarms(recipient)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.thoughtcrime.securesms.notifications.v2
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import org.signal.core.util.logging.Log
|
||||
|
||||
/**
|
||||
* Wrapper for creating pending intents that catches security exceptions thrown by Xiaomi devices randomly.
|
||||
*/
|
||||
object NotificationPendingIntentHelper {
|
||||
private val TAG = Log.tag(NotificationPendingIntentHelper::class.java)
|
||||
|
||||
fun getBroadcast(context: Context, requestCode: Int, intent: Intent, flags: Int): PendingIntent? {
|
||||
return try {
|
||||
PendingIntent.getBroadcast(context, requestCode, intent, flags)
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Too many pending intents device quirk: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getActivity(context: Context, requestCode: Int, intent: Intent, flags: Int): PendingIntent? {
|
||||
return try {
|
||||
PendingIntent.getActivity(context, requestCode, intent, flags)
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Too many pending intents device quirk: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ data class NotificationState(val conversations: List<NotificationConversation>,
|
||||
.putParcelableArrayListExtra(DeleteNotificationReceiver.EXTRA_THREADS, ArrayList(threads))
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getMarkAsReadIntent(context: Context): PendingIntent? {
|
||||
@@ -77,7 +77,7 @@ data class NotificationState(val conversations: List<NotificationConversation>,
|
||||
.putExtra(MarkReadReceiver.NOTIFICATION_ID_EXTRA, NotificationIds.MESSAGE_SUMMARY)
|
||||
.makeUniqueToPreventMerging()
|
||||
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
return NotificationPendingIntentHelper.getBroadcast(context, 0, intent, PendingIntentFlags.updateCurrent())
|
||||
}
|
||||
|
||||
fun getThreadsWithMostRecentNotificationFromSelf(): Set<ConversationId> {
|
||||
|
||||
Reference in New Issue
Block a user