Miscellaneous additions related to notifications.

Add notification permissions for Android 13+

Add error notification.
This commit is contained in:
天クマ 2026-01-22 19:17:38 -03:00
commit 50684b57f5
6 changed files with 59 additions and 4 deletions

View file

@ -2,7 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /> tools:ignore="ScopedStorage" />

View file

@ -7,6 +7,7 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.adrianvictor.geleia.service.notifications.ErrorNotification;
import org.adrianvictor.geleia.util.NavigationUtil; import org.adrianvictor.geleia.util.NavigationUtil;
import org.adrianvictor.geleia.util.PreferenceUtil; import org.adrianvictor.geleia.util.PreferenceUtil;
import org.adrianvictor.geleia.databinding.ActivityAboutBinding; import org.adrianvictor.geleia.databinding.ActivityAboutBinding;
@ -102,7 +103,7 @@ public class AboutActivity extends AbsBaseActivity implements View.OnClickListen
try { try {
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace(); ErrorNotification.show(context, e.getMessage());
} }
return "Unknown"; return "Unknown";

View file

@ -11,6 +11,7 @@ import org.adrianvictor.geleia.BuildConfig;
import org.adrianvictor.geleia.database.Cache; import org.adrianvictor.geleia.database.Cache;
import org.adrianvictor.geleia.model.Song; import org.adrianvictor.geleia.model.Song;
import org.adrianvictor.geleia.service.notifications.DownloadNotification; import org.adrianvictor.geleia.service.notifications.DownloadNotification;
import org.adrianvictor.geleia.service.notifications.ErrorNotification;
import org.adrianvictor.geleia.util.MusicUtil; import org.adrianvictor.geleia.util.MusicUtil;
import org.adrianvictor.geleia.util.PreferenceUtil; import org.adrianvictor.geleia.util.PreferenceUtil;
@ -23,7 +24,6 @@ import java.util.List;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@SuppressWarnings("ResultOfMethodCallIgnored")
public class DownloadService extends Service { public class DownloadService extends Service {
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID; public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
public static final String ACTION_START = PACKAGE_NAME + ".action.start"; public static final String ACTION_START = PACKAGE_NAME + ".action.start";
@ -55,6 +55,7 @@ public class DownloadService extends Service {
break; break;
case DownloadService.ACTION_START: case DownloadService.ACTION_START:
List<Song> songs = intent.getParcelableArrayListExtra(EXTRA_SONGS); List<Song> songs = intent.getParcelableArrayListExtra(EXTRA_SONGS);
assert songs != null;
for (Song song : songs) { for (Song song : songs) {
download(song); download(song);
notification.start(song); notification.start(song);
@ -116,7 +117,7 @@ public class DownloadService extends Service {
App.getDatabase().cacheDao().insertCache(new Cache(song)); App.getDatabase().cacheDao().insertCache(new Cache(song));
notification.stop(song); notification.stop(song);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); ErrorNotification.show(this, e.getMessage());
} }
}); });
} }

View file

@ -0,0 +1,49 @@
package org.adrianvictor.geleia.service.notifications;
import static android.content.Context.NOTIFICATION_SERVICE;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import androidx.core.app.NotificationCompat;
import org.adrianvictor.geleia.R;
public class ErrorNotification {
private static final String CHANNEL_ID = ErrorNotification.class.getSimpleName();
private static final int NOTIFICATION_ID = 3;
private ErrorNotification() {}
public static void show(Context context, String error) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
createNotificationChannel(notificationManager);
NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
style.setBigContentTitle("Error:").bigText(error);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_bug_report_white_24dp)
.setContentTitle(context.getString(R.string.error_notification_title))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setStyle(style)
.setContentText("Expand the notification for details.");
}
public static void createNotificationChannel(NotificationManager notificationManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = notificationManager.getNotificationChannel(CHANNEL_ID);
if (channel == null) {
channel = new NotificationChannel(CHANNEL_ID, "Errors", NotificationManager.IMPORTANCE_LOW);
channel.setDescription("Displays all sorts of errors.");
channel.enableLights(false);
channel.enableVibration(true);
notificationManager.createNotificationChannel(channel);
}
}
}
}

View file

@ -18,6 +18,7 @@ import org.adrianvictor.geleia.model.Codec;
import org.adrianvictor.geleia.model.Genre; import org.adrianvictor.geleia.model.Genre;
import org.adrianvictor.geleia.model.Song; import org.adrianvictor.geleia.model.Song;
import org.adrianvictor.geleia.service.notifications.ErrorNotification;
import org.jellyfin.apiclient.interaction.ApiClient; import org.jellyfin.apiclient.interaction.ApiClient;
import org.jellyfin.apiclient.interaction.Response; import org.jellyfin.apiclient.interaction.Response;
import org.jellyfin.apiclient.model.dto.UserItemDataDto; import org.jellyfin.apiclient.model.dto.UserItemDataDto;
@ -102,7 +103,7 @@ public class MusicUtil {
try { try {
return new Intent(); return new Intent();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace(); ErrorNotification.show(context, e.getMessage());
Toast.makeText(context, R.string.error_share_file, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.error_share_file, Toast.LENGTH_SHORT).show();
return new Intent(); return new Intent();
} }

View file

@ -235,5 +235,6 @@
<string name="error_empty_username">Please fill in your username.</string> <string name="error_empty_username">Please fill in your username.</string>
<string name="dkanada_summary">Forking Phonograph and making Gelli</string> <string name="dkanada_summary">Forking Phonograph and making Gelli</string>
<string name="adrianvictor">Adrian Victor</string> <string name="adrianvictor">Adrian Victor</string>
<string name="error_notification_title">An error occurred in Jamfish.</string>
</resources> </resources>