Skip to content

Commit

Permalink
[flutter_local_notifications] Add audioAttributesUsage to Notificatio…
Browse files Browse the repository at this point in the history
…nDetails (MaikuB#1649)

* Add audioAttributesUsage to NotificationDetails

Allows users to change  AudioAttributes (https://developer.android.com/reference/android/media/AudioAttributes) to the notification sound

Closes: MaikuB#1519

* Adding null check when reading audioAttributesUsage in FlutterLocalNotificationsPlugin

* Adding missing enum 'notificationRingtone' in AudioAttributesUsage's property, 'values'
  • Loading branch information
bornold authored and Kavantix committed Feb 8, 2023
1 parent 57a3bd9 commit 35a97e9
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1060,8 +1060,11 @@ private static void setupNotificationChannel(
notificationChannel.setDescription(notificationChannelDetails.description);
notificationChannel.setGroup(notificationChannelDetails.groupId);
if (notificationChannelDetails.playSound) {
Integer audioAttributesUsage = notificationChannelDetails.audioAttributesUsage != null
? notificationChannelDetails.audioAttributesUsage
: AudioAttributes.USAGE_NOTIFICATION;
AudioAttributes audioAttributes =
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build();
new AudioAttributes.Builder().setUsage(audioAttributesUsage).build();
Uri uri =
retrieveSoundResourceUri(
context, notificationChannelDetails.sound, notificationChannelDetails.soundSource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class NotificationChannelDetails implements Serializable {
private static final String LED_COLOR_RED = "ledColorRed";
private static final String LED_COLOR_GREEN = "ledColorGreen";
private static final String LED_COLOR_BLUE = "ledColorBlue";
private static final String AUDIO_ATTRIBUTES_USAGE = "audioAttributesUsage";

public String id;
public String name;
Expand All @@ -39,6 +40,7 @@ public class NotificationChannelDetails implements Serializable {
public NotificationChannelAction channelAction;
public Boolean enableLights;
public Integer ledColor;
public Integer audioAttributesUsage;

public static NotificationChannelDetails from(Map<String, Object> arguments) {
NotificationChannelDetails notificationChannel = new NotificationChannelDetails();
Expand All @@ -55,6 +57,7 @@ public static NotificationChannelDetails from(Map<String, Object> arguments) {

notificationChannel.playSound = (Boolean) arguments.get(PLAY_SOUND);
notificationChannel.sound = (String) arguments.get(SOUND);
notificationChannel.audioAttributesUsage = (Integer) arguments.get(AUDIO_ATTRIBUTES_USAGE);
Integer soundSourceIndex = (Integer) arguments.get(SOUND_SOURCE);
if (soundSourceIndex != null) {
notificationChannel.soundSource = SoundSource.values()[soundSourceIndex];
Expand Down Expand Up @@ -90,6 +93,7 @@ public static NotificationChannelDetails fromNotificationDetails(
notificationChannel.playSound = notificationDetails.playSound;
notificationChannel.sound = notificationDetails.sound;
notificationChannel.soundSource = notificationDetails.soundSource;
notificationChannel.audioAttributesUsage = notificationDetails.audioAttributesUsage;
notificationChannel.ledColor = notificationDetails.ledColor;
notificationChannel.enableLights = notificationDetails.enableLights;
return notificationChannel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ public class NotificationDetails implements Serializable {
private static final String SUB_TEXT = "subText";
private static final String ACTIONS = "actions";
private static final String COLORIZED = "colorized";
private static final String NUMBER = "number";
private static final String AUDIO_ATTRIBUTES_USAGE = "audioAttributesUsage";

public Integer id;
public String title;
Expand Down Expand Up @@ -180,6 +182,8 @@ public class NotificationDetails implements Serializable {
public @Nullable List<NotificationAction> actions;
public String tag;
public Boolean colorized;
public Integer number;
public Integer audioAttributesUsage;

// Note: this is set on the Android to save details about the icon that should be used when
// re-hydrating scheduled notifications when a device has been restarted.
Expand Down Expand Up @@ -266,7 +270,8 @@ private static void readPlatformSpecifics(
notificationDetails.subText = (String) platformChannelSpecifics.get(SUB_TEXT);
notificationDetails.tag = (String) platformChannelSpecifics.get(TAG);
notificationDetails.colorized = (Boolean) platformChannelSpecifics.get(COLORIZED);

notificationDetails.number = (Integer) platformChannelSpecifics.get(NUMBER);
notificationDetails.audioAttributesUsage = (Integer) platformChannelSpecifics.get(AUDIO_ATTRIBUTES_USAGE);
if (platformChannelSpecifics.containsKey(ACTIONS)) {
List<Map<String, Object>> inputActions =
(List<Map<String, Object>>) platformChannelSpecifics.get(ACTIONS);
Expand Down
49 changes: 49 additions & 0 deletions flutter_local_notifications/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,21 @@ class _HomePageState extends State<HomePage> {
await _showFullScreenNotification();
},
),
PaddedElevatedButton(
buttonText:
'Show notification with number if the launcher supports',
onPressed: () async {
await _showNotificationWithNumber();
},
),
PaddedElevatedButton(
buttonText:
'Show notification with sound controlled by '
'alarm volume',
onPressed: () async {
await _showNotificationWithAudioAttributeAlarm();
},
),
PaddedElevatedButton(
buttonText: 'Create grouped notification channels',
onPressed: () async {
Expand Down Expand Up @@ -2426,6 +2441,40 @@ class _HomePageState extends State<HomePage> {
);
}
}

Future<void> _showNotificationWithNumber() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails('your channel id', 'your channel name',
channelDescription: 'your channel description',
importance: Importance.max,
priority: Priority.high,
number: 1);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0, 'icon badge title', 'icon badge body', platformChannelSpecifics,
payload: 'item x');
}

Future<void> _showNotificationWithAudioAttributeAlarm() async {
const AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails(
'your alarm channel id',
'your alarm channel name',
channelDescription: 'your alarm channel description',
importance: Importance.max,
priority: Priority.high,
audioAttributesUsage: AudioAttributesUsage.alarm,
);
const NotificationDetails platformChannelSpecifics =
NotificationDetails(android: androidPlatformChannelSpecifics);
await flutterLocalNotificationsPlugin.show(
0,
'notification sound controlled by alarm volume',
'alarm notification sound body',
platformChannelSpecifics,
);
}
}

Future<void> _showLinuxNotificationWithBodyMarkup() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,83 @@ enum NotificationVisibility {
/// Do not reveal any part of this notification on a secure lockscreen.
secret,
}

/// The available audio attributes usages for an Android service.
@immutable
class AudioAttributesUsage {
/// Constructs an instance of [AudioAttributesUsage].
const AudioAttributesUsage._(this.value);

/// Corresponds to [`AudioAttributes.USAGE_ALARM`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ALARM).
static const AudioAttributesUsage alarm = AudioAttributesUsage._(4);

/// Corresponds to [`AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ASSISTANCE_ACCESSIBILITY).
static const AudioAttributesUsage assistanceAccessibility =
AudioAttributesUsage._(11);

/// Corresponds to [`AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ASSISTANCE_NAVIGATION_GUIDANCE).
static const AudioAttributesUsage assistanceNavigationGuidance =
AudioAttributesUsage._(12);

/// Corresponds to [`AudioAttributes.USAGE_ASSISTANCE_SONIFICATION`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ASSISTANCE_SONIFICATION).
static const AudioAttributesUsage assistanceSonification =
AudioAttributesUsage._(13);

/// Corresponds to [`AudioAttributes.USAGE_ASSISTANT`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_ASSISTANT).
static const AudioAttributesUsage assistant = AudioAttributesUsage._(16);

/// Corresponds to [`AudioAttributes.USAGE_GAME`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_GAME).
static const AudioAttributesUsage game = AudioAttributesUsage._(14);

/// Corresponds to [`AudioAttributes.USAGE_MEDIA`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_MEDIA).
static const AudioAttributesUsage media = AudioAttributesUsage._(1);

/// Corresponds to [`AudioAttributes.USAGE_NOTIFICATION`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_NOTIFICATION).
static const AudioAttributesUsage notification = AudioAttributesUsage._(5);

/// Corresponds to [`AudioAttributes.USAGE_NOTIFICATION_EVENT`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_NOTIFICATION_EVENT).
static const AudioAttributesUsage notificationEvent =
AudioAttributesUsage._(10);

/// Corresponds to [`AudioAttributes.USAGE_NOTIFICATION_RINGTONE`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_NOTIFICATION_RINGTONE).
static const AudioAttributesUsage notificationRingtone =
AudioAttributesUsage._(6);

/// Corresponds to [`AudioAttributes.USAGE_UNKNOWN`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_UNKNOWN).
static const AudioAttributesUsage unknown = AudioAttributesUsage._(0);

/// Corresponds to [`AudioAttributes.USAGE_VOICE_COMMUNICATION`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_VOICE_COMMUNICATION).
static const AudioAttributesUsage voiceCommunication =
AudioAttributesUsage._(2);

/// Corresponds to [`AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING`](https://developer.android.com/reference/android/media/AudioAttributes#USAGE_VOICE_COMMUNICATION_SIGNALLING).
static const AudioAttributesUsage voiceCommunicationSignalling =
AudioAttributesUsage._(3);

/// All the possible values for the [AudioAttributesUsage] enumeration.
static List<AudioAttributesUsage> get values => <AudioAttributesUsage>[
alarm,
assistanceAccessibility,
assistanceNavigationGuidance,
assistanceSonification,
assistant,
game,
media,
notification,
notificationEvent,
notificationRingtone,
unknown,
voiceCommunication,
voiceCommunicationSignalling,
];

/// The integer representation.
final int value;

@override
int get hashCode => value;

@override
bool operator ==(Object other) =>
other is AudioAttributesUsage && other.value == value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ extension AndroidNotificationDetailsMapper on AndroidNotificationDetails {
'subText': subText,
'tag': tag,
'colorized': colorized,
'number': number,
'audioAttributesUsage': audioAttributesUsage.value,
}
..addAll(_convertActionsToMap(actions))
..addAll(_convertStyleInformationToMap())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ class AndroidNotificationDetails {
this.tag,
this.actions,
this.colorized = false,
this.number,
this.audioAttributesUsage = AudioAttributesUsage.notification,
});

/// The icon that should be used when displaying the notification.
Expand Down Expand Up @@ -382,4 +384,16 @@ class AndroidNotificationDetails {
/// Specify coloring background should be enabled, if false, color will be applied to app icon.
/// For most styles, the coloring will only be applied if the notification is for a foreground service notification.
final bool colorized;

/// Set custom notification count.
///
/// Numbers are only displayed if the launcher application supports the display of badges and numbers.
/// If not supported, this value is ignored.
/// See https://developer.android.com/training/notify-user/badges#set_custom_notification_count
final int? number;

/// The attribute describing what is the intended use of the audio signal,
/// such as alarm or ringtone set in [`AudioAttributes.Builder`](https://developer.android.com/reference/android/media/AudioAttributes.Builder#setUsage(int))
/// https://developer.android.com/reference/android/media/AudioAttributes
final AudioAttributesUsage audioAttributesUsage;
}
Loading

0 comments on commit 35a97e9

Please sign in to comment.