Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set volume to value between 0 and 1 #98

Merged
merged 7 commits into from
Nov 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Remove [stopOnNotificationOpen] property.
* Make notification mandatory so android foreground services can be used.
* [Android] Refactor alarm to native android services.
* Replace [volumeMax] with [volume] double property.

## 2.2.0
* [Android] Move alarm service to native code.
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ final alarmSettings = AlarmSettings(
assetAudioPath: 'assets/alarm.mp3',
loopAudio: true,
vibrate: true,
volumeMax: true,
volume: 0.8,
fadeDuration: 3.0,
notificationTitle: 'This is the title',
notificationBody: 'This is the body',
Expand All @@ -58,7 +58,8 @@ alarmDateTime | `DateTime` | The date and time you want your alarm to ring
assetAudio | `String` | The path to you audio asset you want to use as ringtone. Can be a path in your assets folder or a downloaded local file path.
loopAudio | `bool` | If true, audio will repeat indefinitely until alarm is stopped.
vibrate | `bool` | If true, device will vibrate indefinitely until alarm is stopped. If [loopAudio] is set to false, vibrations will stop when audio ends.
volumeMax | `bool` | If true, set system volume to maximum when [dateTime] is reached. Set back to previous volume when alarm is stopped.
volume | `double` | Sets system volume level (0 to 1) at [dateTime]; reverts on alarm stop. Defaults to current volume if null.
when alarm is stopped.
fadeDuration | `double` | Duration, in seconds, over which to fade the alarm volume. Set to 0 by default, which means no fade.
notificationTitle | `String` | The title of the notification triggered when alarm rings if app is on background.
notificationBody | `String` | The body of the notification.
Expand Down Expand Up @@ -91,14 +92,14 @@ Don't hesitate to check out the example's code, and take a look at the app:

## ⏰ Alarm behaviour

| | Sound | Vibrate | Volume max | Notification
| ------------------------ | ----- | ------- | ---------- | -------
| Locked screen | ✅ | ✅ | ✅ | ✅
| Silent / Mute | ✅ | ✅ | ✅ | ✅
| Do not disturb | ✅ | ✅ | ✅ | Silenced
| Sleep mode | ✅ | ✅ | ✅ | Silenced
| While playing other media| ✅ | ✅ | ✅ | ✅
| App killed | 🤖 | 🤖 | 🤖 | ✅
| | Sound | Vibrate | Volume | Notification
| ------------------------ | ----- | ------- | -------| -------
| Locked screen | ✅ | ✅ | ✅ | ✅
| Silent / Mute | ✅ | ✅ | ✅ | ✅
| Do not disturb | ✅ | ✅ | ✅ | Silenced
| Sleep mode | ✅ | ✅ | ✅ | Silenced
| While playing other media| ✅ | ✅ | ✅ | ✅
| App killed | 🤖 | 🤖 | 🤖 | ✅

✅ : iOS and Android
🤖 : Android only.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class AlarmService : Service() {
Log.d("AlarmService", "Error while invoking alarmRinging channel: $e")
}

if (volume != -1.0) {
if (volume >= 0.0 && volume <= 1.0) {
volumeService?.setVolume(volume, showSystemUI)
}

Expand Down
7 changes: 6 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,10 @@ Future<void> main() async {

await Alarm.init(showDebugLogs: true);

runApp(const MaterialApp(home: ExampleAlarmHomeScreen()));
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const ExampleAlarmHomeScreen(),
),
);
}
60 changes: 43 additions & 17 deletions example/lib/screens/edit_alarm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {
late DateTime selectedDateTime;
late bool loopAudio;
late bool vibrate;
late bool volumeMax;
late double? volume;
late String assetAudio;

@override
Expand All @@ -31,13 +31,13 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {
selectedDateTime = selectedDateTime.copyWith(second: 0, millisecond: 0);
loopAudio = true;
vibrate = true;
volumeMax = false;
volume = null;
assetAudio = 'assets/marimba.mp3';
} else {
selectedDateTime = widget.alarmSettings!.dateTime;
loopAudio = widget.alarmSettings!.loopAudio;
vibrate = widget.alarmSettings!.vibrate;
volumeMax = widget.alarmSettings!.volumeMax;
volume = widget.alarmSettings!.volume;
assetAudio = widget.alarmSettings!.assetAudioPath;
}
}
Expand Down Expand Up @@ -87,7 +87,7 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {
dateTime: selectedDateTime,
loopAudio: loopAudio,
vibrate: vibrate,
volumeMax: volumeMax,
volume: volume,
assetAudioPath: assetAudio,
notificationTitle: 'Alarm example',
notificationBody: 'Your alarm ($id) is ringing',
Expand Down Expand Up @@ -190,19 +190,6 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'System volume max',
style: Theme.of(context).textTheme.titleMedium,
),
Switch(
value: volumeMax,
onChanged: (value) => setState(() => volumeMax = value),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expand Down Expand Up @@ -238,6 +225,45 @@ class _ExampleAlarmEditScreenState extends State<ExampleAlarmEditScreen> {
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Custom volume',
style: Theme.of(context).textTheme.titleMedium,
),
Switch(
value: volume != null,
onChanged: (value) =>
setState(() => volume = value ? 0.5 : null),
),
],
),
SizedBox(
height: 30,
child: volume != null
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(
volume! > 0.7
? Icons.volume_up_rounded
: volume! > 0.1
? Icons.volume_down_rounded
: Icons.volume_mute_rounded,
),
Expanded(
child: Slider(
value: volume!,
onChanged: (value) {
setState(() => volume = value);
},
),
),
],
)
: const SizedBox(),
),
if (!creating)
TextButton(
onPressed: deleteAlarm,
Expand Down
4 changes: 3 additions & 1 deletion example/lib/screens/shortcut_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ class _ExampleAlarmHomeShortcutButtonState

Future<void> onPressButton(int delayInHours) async {
DateTime dateTime = DateTime.now().add(Duration(hours: delayInHours));
double? volume;

if (delayInHours != 0) {
dateTime = dateTime.copyWith(second: 0, millisecond: 0);
volume = 0.5;
}

setState(() => showMenu = false);
Expand All @@ -29,7 +31,7 @@ class _ExampleAlarmHomeShortcutButtonState
id: DateTime.now().millisecondsSinceEpoch % 10000,
dateTime: dateTime,
assetAudioPath: 'assets/marimba.mp3',
volumeMax: false,
volume: volume,
notificationTitle: 'Alarm example',
notificationBody:
'Shortcut button alarm with delay of $delayInHours hours',
Expand Down
18 changes: 9 additions & 9 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ packages:
path: ".."
relative: true
source: path
version: "2.2.0"
version: "3.0.0-dev.1"
args:
dependency: transitive
description:
Expand Down Expand Up @@ -68,10 +68,10 @@ packages:
dependency: transitive
description:
name: dbus
sha256: "6f07cba3f7b3448d42d015bfd3d53fe12e5b36da2423f23838efc1d5fb31a263"
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.8"
version: "0.7.10"
fake_async:
dependency: transitive
description:
Expand Down Expand Up @@ -235,10 +235,10 @@ packages:
dependency: transitive
description:
name: plugin_platform_interface
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8
url: "https://pub.dev"
source: hosted
version: "2.1.6"
version: "2.1.7"
shared_preferences:
dependency: transitive
description:
Expand Down Expand Up @@ -283,10 +283,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_web
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
version: "2.2.2"
shared_preferences_windows:
dependency: transitive
description:
Expand Down Expand Up @@ -397,5 +397,5 @@ packages:
source: hosted
version: "6.4.2"
sdks:
dart: ">=3.2.0-194.0.dev <4.0.0"
flutter: ">=3.7.0"
dart: ">=3.2.0 <4.0.0"
flutter: ">=3.16.0"
25 changes: 14 additions & 11 deletions ios/Classes/SwiftAlarmPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,13 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin {
let loopAudio = args["loopAudio"] as! Bool
let fadeDuration = args["fadeDuration"] as! Double
let vibrationsEnabled = args["vibrate"] as! Bool
let volumeMax = args["volumeMax"] as! Bool
let volume = args["volume"] as? Double
let assetAudio = args["assetAudio"] as! String

var volumeFloat: Float? = nil
if let volumeValue = volume {
volumeFloat = Float(volumeValue)
}

if assetAudio.hasPrefix("assets/") {
let filename = registrar.lookupKey(forAsset: assetAudio)
Expand Down Expand Up @@ -146,7 +151,7 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin {
fadeDuration: fadeDuration,
vibrationsEnabled: vibrationsEnabled,
audioLoop: loopAudio,
volumeMax: volumeMax
volume: volumeFloat
)
})

Expand Down Expand Up @@ -214,7 +219,7 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin {
}
}

private func handleAlarmAfterDelay(id: Int, triggerTime: Date, fadeDuration: Double, vibrationsEnabled: Bool, audioLoop: Bool, volumeMax: Bool) {
private func handleAlarmAfterDelay(id: Int, triggerTime: Date, fadeDuration: Double, vibrationsEnabled: Bool, audioLoop: Bool, volume: Float?) {
guard let audioPlayer = self.audioPlayers[id], let storedTriggerTime = triggerTimes[id], triggerTime == storedTriggerTime else {
return
}
Expand All @@ -234,14 +239,12 @@ public class SwiftAlarmPlugin: NSObject, FlutterPlugin {
self.vibrate = false
}
}

if fadeDuration > 0.0 {
if volumeMax {
self.setVolume(volume: 1.0, enable: true)
}
audioPlayer.setVolume(1.0, fadeDuration: fadeDuration)
} else if volumeMax {
self.setVolume(volume: 1.0, enable: true)

if let volumeValue = volume {
self.setVolume(volume: volumeValue, enable: true)
}
if fadeDuration > 0.0 {
audioPlayer.setVolume(1.0, fadeDuration: fadeDuration)
}
}

Expand Down
33 changes: 19 additions & 14 deletions lib/model/alarm_settings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ class AlarmSettings {
/// If [loopAudio] is set to false, vibrations will stop when audio ends.
final bool vibrate;

/// If true, set system volume to maximum when [dateTime] is reached
/// and set it back to its previous value when alarm is stopped.
/// Else, use current system volume. Enabled by default.
final bool volumeMax;
/// Specifies the system volume level to be set at the designated [dateTime].
///
/// Accepts a value between 0 (mute) and 1 (maximum volume). When the alarm is triggered at [dateTime],
/// the system volume adjusts to this specified level. Upon stopping the alarm, the system volume reverts
/// to its prior setting.
///
/// If left unspecified or set to `null`, the current system volume at the time of the alarm will be used.
/// Defaults to `null`.
final double? volume;

/// Duration, in seconds, over which to fade the alarm ringtone.
/// Set to 0.0 by default, which means no fade.
Expand Down Expand Up @@ -52,7 +57,7 @@ class AlarmSettings {
hash = hash ^ assetAudioPath.hashCode;
hash = hash ^ loopAudio.hashCode;
hash = hash ^ vibrate.hashCode;
hash = hash ^ volumeMax.hashCode;
hash = hash ^ volume.hashCode;
hash = hash ^ fadeDuration.hashCode;
hash = hash ^ (notificationTitle.hashCode);
hash = hash ^ (notificationBody.hashCode);
Expand All @@ -73,7 +78,7 @@ class AlarmSettings {
required this.assetAudioPath,
this.loopAudio = true,
this.vibrate = true,
this.volumeMax = true,
this.volume,
this.fadeDuration = 0.0,
required this.notificationTitle,
required this.notificationBody,
Expand All @@ -87,11 +92,11 @@ class AlarmSettings {
dateTime: DateTime.fromMicrosecondsSinceEpoch(json['dateTime'] as int),
assetAudioPath: json['assetAudioPath'] as String,
loopAudio: json['loopAudio'] as bool,
vibrate: json['vibrate'] as bool,
volumeMax: json['volumeMax'] as bool,
vibrate: json['vibrate'] as bool? ?? true,
volume: json['volume'] as double?,
fadeDuration: json['fadeDuration'] as double,
notificationTitle: json['notificationTitle'] as String,
notificationBody: json['notificationBody'] as String,
notificationTitle: json['notificationTitle'] as String? ?? '',
notificationBody: json['notificationBody'] as String? ?? '',
enableNotificationOnKill:
json['enableNotificationOnKill'] as bool? ?? true,
androidFullScreenIntent:
Expand All @@ -106,7 +111,7 @@ class AlarmSettings {
String? assetAudioPath,
bool? loopAudio,
bool? vibrate,
bool? volumeMax,
double? volume,
double? fadeDuration,
String? notificationTitle,
String? notificationBody,
Expand All @@ -119,7 +124,7 @@ class AlarmSettings {
assetAudioPath: assetAudioPath ?? this.assetAudioPath,
loopAudio: loopAudio ?? this.loopAudio,
vibrate: vibrate ?? this.vibrate,
volumeMax: volumeMax ?? this.volumeMax,
volume: volume ?? this.volume,
fadeDuration: fadeDuration ?? this.fadeDuration,
notificationTitle: notificationTitle ?? this.notificationTitle,
notificationBody: notificationBody ?? this.notificationBody,
Expand All @@ -137,7 +142,7 @@ class AlarmSettings {
'assetAudioPath': assetAudioPath,
'loopAudio': loopAudio,
'vibrate': vibrate,
'volumeMax': volumeMax,
'volume': volume,
'fadeDuration': fadeDuration,
'notificationTitle': notificationTitle,
'notificationBody': notificationBody,
Expand Down Expand Up @@ -165,7 +170,7 @@ class AlarmSettings {
assetAudioPath == other.assetAudioPath &&
loopAudio == other.loopAudio &&
vibrate == other.vibrate &&
volumeMax == other.volumeMax &&
volume == other.volume &&
fadeDuration == other.fadeDuration &&
notificationTitle == other.notificationTitle &&
notificationBody == other.notificationBody &&
Expand Down
Loading