From 9dbb5d70e9368cbfd247b4a8d02a5a350dd74140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 17 Sep 2022 17:21:13 +0200 Subject: [PATCH] [App] Fix PendingIntent crashing on API 31+. --- .../edziennik/data/api/EdziennikNotification.kt | 5 +++-- .../edziennik/data/api/task/PostNotifications.kt | 3 ++- .../edziennik/data/db/entity/Notification.kt | 3 ++- .../pl/szczodrzynski/edziennik/ext/MiscExtensions.kt | 8 ++++++++ .../pl/szczodrzynski/edziennik/sync/UpdateWorker.kt | 3 ++- .../widgets/luckynumber/WidgetLuckyNumberProvider.kt | 3 ++- .../notifications/WidgetNotificationsProvider.kt | 7 ++++--- .../ui/widgets/timetable/WidgetTimetableProvider.kt | 11 ++++++----- .../edziennik/utils/managers/UserActionManager.kt | 3 ++- .../edziennik/sync/UpdateDownloaderService.kt | 1 + 10 files changed, 32 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt index 0b413356..6b2b7533 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EdziennikNotification.kt @@ -13,6 +13,7 @@ import androidx.core.app.NotificationCompat.PRIORITY_MIN import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.ext.Bundle +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.receivers.SzkolnyReceiver import kotlin.math.roundToInt @@ -40,14 +41,14 @@ class EdziennikNotification(val app: App) { "task" to "TaskCancelRequest", "taskId" to taskId )) - return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) as PendingIntent + return PendingIntent.getBroadcast(app, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or pendingIntentFlag()) as PendingIntent } private val closePendingIntent: PendingIntent get() { val intent = SzkolnyReceiver.getIntent(app, Bundle( "task" to "ServiceCloseRequest" )) - return PendingIntent.getBroadcast(app, 0, intent, 0) as PendingIntent + return PendingIntent.getBroadcast(app, 0, intent, pendingIntentFlag()) as PendingIntent } private fun errorCountText(): String? { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/PostNotifications.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/PostNotifications.kt index 8b4682d6..41614394 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/PostNotifications.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/PostNotifications.kt @@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Notification.Companion.TYPE_SER import pl.szczodrzynski.edziennik.ext.Intent import pl.szczodrzynski.edziennik.ext.asBoldSpannable import pl.szczodrzynski.edziennik.ext.concat +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.utils.models.Time import pl.szczodrzynski.edziennik.data.db.entity.Notification as AppNotification @@ -92,7 +93,7 @@ class PostNotifications(val app: App, nList: List) { MainActivity::class.java, "fragmentId" to MainActivity.DRAWER_ITEM_NOTIFICATIONS ) - val summaryIntent = PendingIntent.getActivity(app, app.notificationChannelsManager.data.id, intent, PendingIntent.FLAG_ONE_SHOT) + val summaryIntent = PendingIntent.getActivity(app, app.notificationChannelsManager.data.id, intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag()) // On Nougat or newer - show maximum 8 notifications // On Marshmallow or older - show maximum 4 notifications diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Notification.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Notification.kt index e57e8efa..35208927 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Notification.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Notification.kt @@ -13,6 +13,7 @@ import com.google.gson.JsonObject import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag @Entity(tableName = "notifications") data class Notification( @@ -98,7 +99,7 @@ data class Notification( fun getPendingIntent(context: Context): PendingIntent { val intent = Intent(context, MainActivity::class.java) fillIntent(intent) - return PendingIntent.getActivity(context, id.toInt(), intent, PendingIntent.FLAG_ONE_SHOT) + return PendingIntent.getActivity(context, id.toInt(), intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag()) } fun getLargeIcon(): IIcon = when (type) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ext/MiscExtensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ext/MiscExtensions.kt index 22ed9e43..df931fbd 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ext/MiscExtensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ext/MiscExtensions.kt @@ -4,7 +4,9 @@ package pl.szczodrzynski.edziennik.ext +import android.app.PendingIntent import android.database.Cursor +import android.os.Build import androidx.core.database.getIntOrNull import androidx.core.database.getLongOrNull import androidx.core.database.getStringOrNull @@ -64,3 +66,9 @@ inline fun ifNotNull(a: A?, b: B?, code: (A, B) -> R): R? { } infix fun Int.hasSet(what: Int) = this and what == what + +fun pendingIntentFlag(): Int { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) + return PendingIntent.FLAG_IMMUTABLE + return 0 +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/sync/UpdateWorker.kt b/app/src/main/java/pl/szczodrzynski/edziennik/sync/UpdateWorker.kt index 5325d533..0df0bc83 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/sync/UpdateWorker.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/sync/UpdateWorker.kt @@ -21,6 +21,7 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update import pl.szczodrzynski.edziennik.ext.DAY import pl.szczodrzynski.edziennik.ext.concat import pl.szczodrzynski.edziennik.ext.formatDate +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.html.BetterHtml import java.util.concurrent.TimeUnit @@ -109,7 +110,7 @@ class UpdateWorker(val context: Context, val params: WorkerParameters) : Worker( } val notificationIntent = Intent(app, UpdateDownloaderService::class.java) - val pendingIntent = PendingIntent.getService(app, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT) + val pendingIntent = PendingIntent.getService(app, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT or pendingIntentFlag()) val notification = NotificationCompat.Builder(app, app.notificationChannelsManager.updates.key) .setContentTitle(app.getString(R.string.notification_updates_title)) .setContentText(app.getString(R.string.notification_updates_text, update.versionName)) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/luckynumber/WidgetLuckyNumberProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/luckynumber/WidgetLuckyNumberProvider.kt index e6332115..40b40d5c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/luckynumber/WidgetLuckyNumberProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/luckynumber/WidgetLuckyNumberProvider.kt @@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.ext.getJsonObject +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.models.Date @@ -81,7 +82,7 @@ class WidgetLuckyNumberProvider : AppWidgetProvider() { val openIntent = Intent(context, MainActivity::class.java) openIntent.action = Intent.ACTION_MAIN openIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_HOME) - val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0) + val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, pendingIntentFlag()) views.setOnClickPendingIntent(R.id.widgetLuckyNumberRoot, openPendingIntent) appWidgetManager.updateAppWidget(appWidgetId, views) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt index b2ac08d7..dc4eb02e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/notifications/WidgetNotificationsProvider.kt @@ -22,6 +22,7 @@ import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.ext.Bundle import pl.szczodrzynski.edziennik.ext.getJsonObject +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.receivers.SzkolnyReceiver import pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig @@ -47,7 +48,7 @@ class WidgetNotificationsProvider : AppWidgetProvider() { val syncIntent = SzkolnyReceiver.getIntent(context, Bundle( "task" to "SyncRequest" )) - val syncPendingIntent = PendingIntent.getBroadcast(context, 0, syncIntent, 0) + val syncPendingIntent = PendingIntent.getBroadcast(context, 0, syncIntent, pendingIntentFlag()) views.setOnClickPendingIntent(R.id.widgetNotificationsSync, syncPendingIntent) views.setImageViewBitmap( @@ -68,13 +69,13 @@ class WidgetNotificationsProvider : AppWidgetProvider() { val itemIntent = Intent(context, MainActivity::class.java) itemIntent.action = Intent.ACTION_MAIN - val itemPendingIntent = PendingIntent.getActivity(context, 0, itemIntent, 0) + val itemPendingIntent = PendingIntent.getActivity(context, 0, itemIntent, pendingIntentFlag()) views.setPendingIntentTemplate(R.id.widgetNotificationsListView, itemPendingIntent) val headerIntent = Intent(context, MainActivity::class.java) headerIntent.action = Intent.ACTION_MAIN headerIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_NOTIFICATIONS) - val headerPendingIntent = PendingIntent.getActivity(context, 0, headerIntent, 0) + val headerPendingIntent = PendingIntent.getActivity(context, 0, headerIntent, pendingIntentFlag()) views.setOnClickPendingIntent(R.id.widgetNotificationsHeader, headerPendingIntent) appWidgetManager.updateAppWidget(appWidgetId, views) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt index 8c87ad30..87da09a8 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/widgets/timetable/WidgetTimetableProvider.kt @@ -31,6 +31,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Lesson import pl.szczodrzynski.edziennik.data.db.entity.Lesson.Companion.TYPE_NO_LESSONS import pl.szczodrzynski.edziennik.ext.filterOutArchived import pl.szczodrzynski.edziennik.ext.getJsonObject +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.ui.widgets.LessonDialogActivity import pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig import pl.szczodrzynski.edziennik.utils.models.Date @@ -53,8 +54,8 @@ class WidgetTimetableProvider : AppWidgetProvider() { return getPendingSelfIntent(context, intent) } - fun getPendingSelfIntent(context: Context, intent: Intent): PendingIntent { - return PendingIntent.getBroadcast(context, 0, intent, 0) + private fun getPendingSelfIntent(context: Context, intent: Intent): PendingIntent { + return PendingIntent.getBroadcast(context, 0, intent, pendingIntentFlag()) } fun drawableToBitmap(drawable: Drawable): Bitmap { @@ -111,7 +112,7 @@ class WidgetTimetableProvider : AppWidgetProvider() { refreshIntent.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE refreshIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds) val refreshPendingIntent = PendingIntent.getBroadcast(context, - 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT) + 0, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT or pendingIntentFlag()) views.setOnClickPendingIntent(R.id.widgetTimetableRefresh, refreshPendingIntent) views.setOnClickPendingIntent(R.id.widgetTimetableSync, getPendingSelfIntent(context, ACTION_SYNC_DATA)) @@ -394,7 +395,7 @@ class WidgetTimetableProvider : AppWidgetProvider() { } } headerIntent.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE) - val headerPendingIntent = PendingIntent.getActivity(app, appWidgetId, headerIntent, 0) + val headerPendingIntent = PendingIntent.getActivity(app, appWidgetId, headerIntent, pendingIntentFlag()) views.setOnClickPendingIntent(R.id.widgetTimetableHeader, headerPendingIntent) timetables!!.put(appWidgetId, models) @@ -408,7 +409,7 @@ class WidgetTimetableProvider : AppWidgetProvider() { // create an intent used to display the lesson details dialog val itemIntent = Intent(app, LessonDialogActivity::class.java) itemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK/* or Intent.FLAG_ACTIVITY_CLEAR_TASK*/) - val itemPendingIntent = PendingIntent.getActivity(app, appWidgetId, itemIntent, 0) + val itemPendingIntent = PendingIntent.getActivity(app, appWidgetId, itemIntent, pendingIntentFlag()) views.setPendingIntentTemplate(R.id.widgetTimetableListView, itemPendingIntent) if (!unified) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/UserActionManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/UserActionManager.kt index 7bd69545..dbe05325 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/UserActionManager.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/UserActionManager.kt @@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.ext.Intent import pl.szczodrzynski.edziennik.ext.JsonObject +import pl.szczodrzynski.edziennik.ext.pendingIntentFlag import pl.szczodrzynski.edziennik.ui.captcha.LibrusCaptchaDialog class UserActionManager(val app: App) { @@ -55,7 +56,7 @@ class UserActionManager(val app: App) { "profileId" to (apiError.profileId ?: -1), "type" to type ) - val pendingIntent = PendingIntent.getActivity(app, System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_ONE_SHOT) + val pendingIntent = PendingIntent.getActivity(app, System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag()) val notification = NotificationCompat.Builder(app, app.notificationChannelsManager.userAttention.key) .setContentTitle(app.getString(R.string.notification_user_action_required_title)) diff --git a/app/src/play-not/java/pl/szczodrzynski/edziennik/sync/UpdateDownloaderService.kt b/app/src/play-not/java/pl/szczodrzynski/edziennik/sync/UpdateDownloaderService.kt index 31c24d2f..93881939 100644 --- a/app/src/play-not/java/pl/szczodrzynski/edziennik/sync/UpdateDownloaderService.kt +++ b/app/src/play-not/java/pl/szczodrzynski/edziennik/sync/UpdateDownloaderService.kt @@ -115,6 +115,7 @@ class UpdateDownloaderService : IntentService(UpdateDownloaderService::class.jav Toast.makeText(app, "Nie można znaleźć katalogu docelowego. Pobierz aktualizację ręcznie z Google Play.", Toast.LENGTH_LONG).show() return } + Toast.makeText(app, "Pobieranie aktualizacji Szkolny.eu ${update.versionName}", Toast.LENGTH_LONG).show() downloadId = downloadManager.enqueue(request) } }