Skip to content

Commit

Permalink
Fix android notif delay & auto abandon audio focus (dev.8)
Browse files Browse the repository at this point in the history
  • Loading branch information
gdelataillade committed Dec 15, 2023
1 parent 75ad7eb commit b7e7cfc
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.0.0-dev.8
* [Android] Fix notification delay for Android 12 and above.
* [Android] Abandon audio focus + stop vibrating when loopAudio is false and audio is over.

## 3.0.0-dev.7
* [Android] Fix notification delay and sound.

Expand Down
1 change: 1 addition & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ class AlarmPlugin: FlutterPlugin, MethodCallHandler {
fun handleDelayedAlarm(context: Context, intent: Intent, delayInSeconds: Int, id: Int) {
val triggerTime = System.currentTimeMillis() + delayInSeconds * 1000
val pendingIntent = PendingIntent.getBroadcast(
context,
id,
intent,
context,
id,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,6 @@ class AlarmService : Service() {
val fullScreenIntent = intent?.getBooleanExtra("fullScreenIntent", true)
showSystemUI = intent?.getBooleanExtra("showSystemUI", true) ?: true

// Log.d("AlarmService", "id: $id")
// Log.d("AlarmService", "assetAudioPath: $assetAudioPath")
// Log.d("AlarmService", "loopAudio: $loopAudio")
// Log.d("AlarmService", "vibrate: $vibrate")
// Log.d("AlarmService", "volume: $volume")
// Log.d("AlarmService", "fadeDuration: $fadeDuration")
// Log.d("AlarmService", "notificationTitle: $notificationTitle")
// Log.d("AlarmService", "notificationBody: $notificationBody")
// Log.d("AlarmService", "fullScreenIntent: $fullScreenIntent")

val notificationHandler = NotificationHandler(this)

val intent = applicationContext.packageManager.getLaunchIntentForPackage(applicationContext.packageName)
Expand All @@ -95,6 +85,14 @@ class AlarmService : Service() {

volumeService?.requestAudioFocus()

audioService?.setOnAudioCompleteListener {
if (!loopAudio!!) {
vibrationService?.stopVibrating()
volumeService?.restorePreviousVolume(showSystemUI)
volumeService?.abandonAudioFocus()
}
}

audioService?.playAudio(id, assetAudioPath!!, loopAudio!!, fadeDuration!!)

ringingAlarmIds = audioService?.getPlayingMediaPlayersIds()!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ class AudioService(private val context: Context) {
private val mediaPlayers = ConcurrentHashMap<Int, MediaPlayer>()
private val timers = ConcurrentHashMap<Int, Timer>()

private var onAudioComplete: (() -> Unit)? = null

fun setOnAudioCompleteListener(listener: () -> Unit) {
onAudioComplete = listener
}

fun isMediaPlayerEmpty(): Boolean {
return mediaPlayers.isEmpty()
}
Expand All @@ -30,6 +36,12 @@ class AudioService(private val context: Context) {
isLooping = loopAudio
start()

setOnCompletionListener {
if (!loopAudio) {
onAudioComplete?.invoke()
}
}

mediaPlayers[id] = this

if (fadeDuration != null && fadeDuration > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ class NotificationHandler(private val context: Context) {
}
}


fun buildNotification(title: String, body: String, fullScreen: Boolean, pendingIntent: PendingIntent): Notification {
val iconResId = context.resources.getIdentifier("ic_launcher", "mipmap", context.packageName)

val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
val pendingIntent = PendingIntent.getActivity(
context,
Expand All @@ -60,6 +58,10 @@ class NotificationHandler(private val context: Context) {
.setSound(null)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
notificationBuilder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
}

if (fullScreen) {
notificationBuilder.setFullScreenIntent(pendingIntent, true)
}
Expand Down
1 change: 1 addition & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Expand Down
6 changes: 6 additions & 0 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ PODS:
- Flutter (1.0.0)
- flutter_fgbg (0.0.1):
- Flutter
- permission_handler_apple (9.1.1):
- Flutter
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
Expand All @@ -12,6 +14,7 @@ DEPENDENCIES:
- alarm (from `.symlinks/plugins/alarm/ios`)
- Flutter (from `Flutter`)
- flutter_fgbg (from `.symlinks/plugins/flutter_fgbg/ios`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)

EXTERNAL SOURCES:
Expand All @@ -21,13 +24,16 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_fgbg:
:path: ".symlinks/plugins/flutter_fgbg/ios"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"

SPEC CHECKSUMS:
alarm: 6c1f6a9688f94cd6bf8f104c67cc26e78c9d8d13
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
flutter_fgbg: 31c0d1140a131daea2d342121808f6aa0dcd879d
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126

PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3
Expand Down
15 changes: 14 additions & 1 deletion example/lib/screens/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:alarm_example/screens/ring.dart';
import 'package:alarm_example/screens/shortcut_button.dart';
import 'package:alarm_example/widgets/tile.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

class ExampleAlarmHomeScreen extends StatefulWidget {
const ExampleAlarmHomeScreen({Key? key}) : super(key: key);
Expand All @@ -22,6 +23,7 @@ class _ExampleAlarmHomeScreenState extends State<ExampleAlarmHomeScreen> {
@override
void initState() {
super.initState();
if (Alarm.android) checkAndroidNotificationPermission();
loadAlarms();
subscription ??= Alarm.ringStream.stream.listen(
(alarmSettings) => navigateToRingScreen(alarmSettings),
Expand Down Expand Up @@ -62,6 +64,17 @@ class _ExampleAlarmHomeScreenState extends State<ExampleAlarmHomeScreen> {
if (res != null && res == true) loadAlarms();
}

Future<void> checkAndroidNotificationPermission() async {
final status = await Permission.notification.status;
if (status.isDenied) {
alarmPrint('Requesting notification permission...');
final res = await Permission.notification.request();
alarmPrint(
'Notification permission ${res.isGranted ? '' : 'not'} granted.',
);
}
}

@override
void dispose() {
subscription?.cancel();
Expand All @@ -71,7 +84,7 @@ class _ExampleAlarmHomeScreenState extends State<ExampleAlarmHomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('alarm 3.0.0-dev.7')),
appBar: AppBar(title: const Text('alarm 3.0.0-dev.8')),
body: SafeArea(
child: alarms.isNotEmpty
? ListView.separated(
Expand Down
48 changes: 48 additions & 0 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
sha256: "860c6b871c94c78e202dc69546d4d8fd84bd59faeb36f8fb9888668a53ff4f78"
url: "https://pub.dev"
source: hosted
version: "11.1.0"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "2f1bec180ee2f5665c22faada971a8f024761f632e93ddc23310487df52dcfa6"
url: "https://pub.dev"
source: hosted
version: "12.0.1"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: "1a816084338ada8d574b1cb48390e6e8b19305d5120fe3a37c98825bacc78306"
url: "https://pub.dev"
source: hosted
version: "9.2.0"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "11b762a8c123dced6461933a88ea1edbbe036078c3f9f41b08886e678e7864df"
url: "https://pub.dev"
source: hosted
version: "0.1.0+2"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: d87349312f7eaf6ce0adaf668daf700ac5b06af84338bd8b8574dfbd93ffe1a1
url: "https://pub.dev"
source: hosted
version: "4.0.2"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1e8640c1e39121128da6b816d236e714d2cf17fac5a105dd6acdd3403a628004"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
platform:
dependency: transitive
description:
Expand Down
3 changes: 2 additions & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ dependencies:
# The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version.
path: ../


permission_handler: ^11.1.0
cupertino_icons: ^1.0.2

dev_dependencies:
Expand Down
1 change: 1 addition & 0 deletions help/INSTALL-ANDROID.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Then, add the following permissions to your `AndroidManifest.xml` within the `<m
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: alarm
description: A simple Flutter alarm manager plugin for both iOS and Android.
version: 3.0.0-dev.7
version: 3.0.0-dev.8
homepage: https://github.com/gdelataillade/alarm

environment:
Expand Down

0 comments on commit b7e7cfc

Please sign in to comment.