Add POST_NOTIFICATIONS permission checks (#6951)

Also update AndroidX Core to 1.9.0 because then `checkSelfPermission()` delegates to `areNotificationsEnabled()` if needed
This commit is contained in:
Taco 2024-03-17 14:58:33 -04:00 committed by GitHub
parent 0cbd97b5cb
commit b84a05bd4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 64 additions and 14 deletions

View File

@ -12,7 +12,7 @@ project.ext {
// AndroidX // AndroidX
annotationVersion = "1.4.0" annotationVersion = "1.4.0"
appcompatVersion = "1.5.1" appcompatVersion = "1.5.1"
coreVersion = "1.8.0" coreVersion = "1.9.0"
fragmentVersion = "1.5.5" fragmentVersion = "1.5.5"
mediaVersion = "1.6.0" mediaVersion = "1.6.0"
media3Version = "1.1.1" media3Version = "1.1.1"

View File

@ -10,7 +10,7 @@ android {
lint { lint {
disable "InvalidPeriodicWorkRequestInterval", "ObsoleteLintCustomCheck", "DefaultLocale", "UnusedAttribute", disable "InvalidPeriodicWorkRequestInterval", "ObsoleteLintCustomCheck", "DefaultLocale", "UnusedAttribute",
"ParcelClassLoader", "CheckResult", "TrustAllX509TrustManager", "ParcelClassLoader", "CheckResult", "TrustAllX509TrustManager",
"StaticFieldLeak", "IconDensities", "IconDuplicates" "StaticFieldLeak", "IconDensities", "IconDuplicates", "UnsafeOptInUsageError"
} }
defaultConfig { defaultConfig {

View File

@ -10,6 +10,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application <application
android:allowBackup="true" android:allowBackup="true"

View File

@ -1,12 +1,15 @@
package de.danoeh.antennapod.core.service; package de.danoeh.antennapod.core.service;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.work.ForegroundInfo; import androidx.work.ForegroundInfo;
import androidx.work.WorkManager; import androidx.work.WorkManager;
import androidx.work.Worker; import androidx.work.Worker;
@ -135,7 +138,10 @@ public class FeedUpdateWorker extends Worker {
if (isStopped()) { if (isStopped()) {
return; return;
} }
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_updating_feeds, createNotification(toUpdate)); notificationManager.notify(R.id.notification_updating_feeds, createNotification(toUpdate));
}
Feed feed = toUpdate.get(0); Feed feed = toUpdate.get(0);
try { try {
if (feed.isLocalFeed()) { if (feed.isLocalFeed()) {

View File

@ -1,14 +1,17 @@
package de.danoeh.antennapod.core.service.download; package de.danoeh.antennapod.core.service.download;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.work.Data; import androidx.work.Data;
import androidx.work.ForegroundInfo; import androidx.work.ForegroundInfo;
import androidx.work.Worker; import androidx.work.Worker;
@ -77,7 +80,10 @@ public class EpisodeDownloadWorker extends Worker {
.get(); .get();
NotificationManager nm = (NotificationManager) getApplicationContext() NotificationManager nm = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE); .getSystemService(Context.NOTIFICATION_SERVICE);
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
nm.notify(R.id.notification_downloading, generateProgressNotification()); nm.notify(R.id.notification_downloading, generateProgressNotification());
}
Thread.sleep(1000); Thread.sleep(1000);
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
return; return;
@ -252,8 +258,11 @@ public class EpisodeDownloadWorker extends Worker {
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC); builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
NotificationManager nm = (NotificationManager) getApplicationContext() NotificationManager nm = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE); .getSystemService(Context.NOTIFICATION_SERVICE);
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
nm.notify(R.id.notification_download_report, builder.build()); nm.notify(R.id.notification_download_report, builder.build());
} }
}
private Notification generateProgressNotification() { private Notification generateProgressNotification() {
StringBuilder bigTextB = new StringBuilder(); StringBuilder bigTextB = new StringBuilder();

View File

@ -1,10 +1,12 @@
package de.danoeh.antennapod.core.service.download; package de.danoeh.antennapod.core.service.download;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -12,6 +14,7 @@ import android.os.Build;
import android.util.Log; import android.util.Log;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions; import com.bumptech.glide.request.RequestOptions;
@ -84,8 +87,11 @@ public class NewEpisodesNotification {
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
.setAutoCancel(true) .setAutoCancel(true)
.build(); .build();
if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS)
notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, feed.hashCode(), notification); == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS,
feed.hashCode(), notification);
}
showGroupSummaryNotification(context, notificationManager); showGroupSummaryNotification(context, notificationManager);
} }
@ -109,7 +115,11 @@ public class NewEpisodesNotification {
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
.setAutoCancel(true) .setAutoCancel(true)
.build(); .build();
notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS, 0, notificationGroupSummary); if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(NotificationUtils.CHANNEL_ID_EPISODE_NOTIFICATIONS,
0, notificationGroupSummary);
}
} }
private static Bitmap loadIcon(Context context, Feed feed) { private static Bitmap loadIcon(Context context, Feed feed) {

View File

@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.playback;
import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL; import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
import android.Manifest;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
@ -14,6 +15,7 @@ import android.content.ContentResolver;
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.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.media.AudioManager; import android.media.AudioManager;
import android.net.Uri; import android.net.Uri;
@ -45,6 +47,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.media.MediaBrowserServiceCompat; import androidx.media.MediaBrowserServiceCompat;
import de.danoeh.antennapod.ui.notifications.NotificationUtils; import de.danoeh.antennapod.ui.notifications.NotificationUtils;
@ -303,8 +306,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (notificationBuilder.getPlayerStatus() == PlayerStatus.PLAYING) { if (notificationBuilder.getPlayerStatus() == PlayerStatus.PLAYING) {
notificationBuilder.setPlayerStatus(PlayerStatus.STOPPED); notificationBuilder.setPlayerStatus(PlayerStatus.STOPPED);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_playing, notificationBuilder.build()); notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
} }
}
stateManager.stopForeground(!UserPreferences.isPersistNotify()); stateManager.stopForeground(!UserPreferences.isPersistNotify());
isRunning = false; isRunning = false;
currentMediaType = MediaType.UNKNOWN; currentMediaType = MediaType.UNKNOWN;
@ -628,8 +634,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
pendingIntentAlwaysAllow) pendingIntentAlwaysAllow)
.setAutoCancel(true); .setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_streaming_confirmation, builder.build()); notificationManager.notify(R.id.notification_streaming_confirmation, builder.build());
} }
}
/** /**
* Handles media button events * Handles media button events
@ -1394,14 +1403,20 @@ public class PlaybackService extends MediaBrowserServiceCompat {
notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed()); notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed());
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_playing, notificationBuilder.build()); notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
if (!notificationBuilder.isIconCached()) { if (!notificationBuilder.isIconCached()) {
playableIconLoaderThread = new Thread(() -> { playableIconLoaderThread = new Thread(() -> {
Log.d(TAG, "Loading notification icon"); Log.d(TAG, "Loading notification icon");
notificationBuilder.loadIcon(); notificationBuilder.loadIcon();
if (!Thread.currentThread().isInterrupted()) { if (!Thread.currentThread().isInterrupted()) {
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_playing, notificationBuilder.build()); notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
}
updateMediaSessionMetadata(playable); updateMediaSessionMetadata(playable);
} }
}); });
@ -1779,8 +1794,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed()); notificationBuilder.updatePosition(getCurrentPosition(), getCurrentPlaybackSpeed());
NotificationManager notificationManager = (NotificationManager) NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE); getSystemService(NOTIFICATION_SERVICE);
if (ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(R.id.notification_playing, notificationBuilder.build()); notificationManager.notify(R.id.notification_playing, notificationBuilder.build());
} }
}
skipEndingIfNecessary(); skipEndingIfNecessary();
}); });
} }

View File

@ -1,15 +1,18 @@
package de.danoeh.antennapod.core.sync; package de.danoeh.antennapod.core.sync;
import android.Manifest;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.content.ContextCompat;
import androidx.core.util.Pair; import androidx.core.util.Pair;
import androidx.work.BackoffPolicy; import androidx.work.BackoffPolicy;
import androidx.work.Constraints; import androidx.work.Constraints;
@ -329,8 +332,11 @@ public class SyncService extends Worker {
.build(); .build();
NotificationManager nm = (NotificationManager) getApplicationContext() NotificationManager nm = (NotificationManager) getApplicationContext()
.getSystemService(Context.NOTIFICATION_SERVICE); .getSystemService(Context.NOTIFICATION_SERVICE);
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
nm.notify(R.id.notification_gpodnet_sync_error, notification); nm.notify(R.id.notification_gpodnet_sync_error, notification);
} }
}
private static OneTimeWorkRequest.Builder getWorkRequest() { private static OneTimeWorkRequest.Builder getWorkRequest() {
Constraints.Builder constraints = new Constraints.Builder(); Constraints.Builder constraints = new Constraints.Builder();