diff --git a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/MainActivity.kt b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/MainActivity.kt index bce4914..bee87aa 100644 --- a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/MainActivity.kt +++ b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/MainActivity.kt @@ -15,7 +15,7 @@ class MainActivity: FlutterActivity() { private var streamHandler : NotificationStreamHandler? = null companion object { - private const val ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS" + const val ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS" private const val EVENT_CHANNEL_NAME = "notifications.eventChannel" private const val METHOD_CHANNEL_NAME = "notifications/method" } @@ -41,6 +41,13 @@ class MainActivity: FlutterActivity() { eventChannel.setStreamHandler(streamHandler) } + override fun onDestroy() { + if (streamHandler?.receiver != null) { + context.unregisterReceiver(streamHandler?.receiver) + } + super.onDestroy() + } + private fun isPermissionGranted(): Boolean { val packageName = packageName val pkgs = NotificationManagerCompat.getEnabledListenerPackages(context) diff --git a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationListener.kt b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationListener.kt index e818f02..cc4a181 100644 --- a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationListener.kt +++ b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationListener.kt @@ -3,11 +3,13 @@ package com.illusionware.lyricsgrabbr.lyricsgrabbr import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager +import android.app.PendingIntent import android.content.Context import android.content.Intent import android.media.MediaMetadata import android.media.session.MediaController import android.media.session.MediaSession +import android.media.session.PlaybackState import android.os.Build import android.os.Handler import android.service.notification.NotificationListenerService @@ -31,13 +33,6 @@ class NotificationListener : NotificationListenerService() { notificationManager = NotificationManagerCompat.from(applicationContext) } - override fun onDestroy() { - Log.d("onDestroy Service", "destroying service") - stopForeground(true) - stopSelf() - super.onDestroy() - } - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { if (intent != null) { when (intent.action) { @@ -46,10 +41,6 @@ class NotificationListener : NotificationListenerService() { startForegroundService() getCurrentNotifications(applicationContext) } - STOP_FOREGROUND_SERVICE_ACTION -> { - Log.d("STOP", "stopping foreground service") - stopForegroundService() - } } } @@ -62,7 +53,6 @@ class NotificationListener : NotificationListenerService() { override fun onListenerDisconnected() { stopForegroundService() - super.onListenerDisconnected() } override fun onNotificationPosted(sbn: StatusBarNotification) { @@ -71,11 +61,19 @@ class NotificationListener : NotificationListenerService() { } } + private fun getStopServiceNotificationAction(): PendingIntent { + val intent = Intent(MainActivity.ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0) + return pendingIntent + } + private fun startForegroundService() { val notification: Notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) - .setContentTitle("TITLE") - .setContentText("TEXT") + .setContentTitle("Service Running") + .setContentText("Play some songs on spotify to get lyrics") .setSmallIcon(R.drawable.ic_notification) + .setShowWhen(false) + .addAction(R.drawable.ic_notification, "Stop Service", getStopServiceNotificationAction()) .build() notification.flags = Notification.FLAG_FOREGROUND_SERVICE @@ -133,17 +131,35 @@ class NotificationListener : NotificationListenerService() { intent.putExtra(NOTIFICATION_PACKAGE_DURATION, duration) intent.putExtra(NOTIFICATION_PACKAGE_PLAYBACK_STATE, playbackState) - val notification: Notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) - .setContentTitle("Playing [${packageText}] By [${packageMessage}]") - .setContentText("Tap to get lyrics") - .setSmallIcon(R.drawable.ic_notification) - .setLargeIcon(albumArt) -// .setContentIntent(pendingIntent) // launch intent when clicking on notification - .build() + if (playbackState == PlaybackState.STATE_PAUSED) { + val notification: Notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) + .setContentTitle("Service Running") + .setContentText("Play some songs on spotify to get lyrics") + .setSmallIcon(R.drawable.ic_notification) + .setShowWhen(false) + .addAction(R.drawable.ic_notification, "Stop Service", getStopServiceNotificationAction()) + .build() - notification.flags = Notification.FLAG_FOREGROUND_SERVICE + notification.flags = Notification.FLAG_FOREGROUND_SERVICE + notificationManager?.notify(NOTIFICATION_ID, notification) + } else { + val notificationIntent = Intent(this, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE) + val notification: Notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) + .setContentTitle("Playing [${packageText}] By [${packageMessage}]") + .setContentText("Tap to get lyrics") + .setSmallIcon(R.drawable.ic_notification) + .setLargeIcon(albumArt) + .setShowWhen(false) + .setContentIntent(pendingIntent) + .addAction(R.drawable.ic_notification, "Stop Service", getStopServiceNotificationAction()) + .build() - notificationManager?.notify(NOTIFICATION_ID, notification) + notification.flags = Notification.FLAG_FOREGROUND_SERVICE + notificationManager?.notify(NOTIFICATION_ID, notification) + } sendBroadcast(intent) } @@ -159,6 +175,5 @@ class NotificationListener : NotificationListenerService() { const val NOTIFICATION_CHANNEL_ID = "Lyrics" const val SPOTIFY_PACKAGE = "com.spotify.music" const val START_FOREGROUND_SERVICE_ACTION = "START_SERVICE" - const val STOP_FOREGROUND_SERVICE_ACTION = "STOP_SERVICE" } } diff --git a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationStreamHandler.kt b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationStreamHandler.kt index 3314675..0d2d95d 100644 --- a/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationStreamHandler.kt +++ b/android/app/src/main/kotlin/com/illusionware/lyricsgrabbr/lyricsgrabbr/NotificationStreamHandler.kt @@ -8,7 +8,7 @@ import androidx.core.content.ContextCompat class NotificationStreamHandler(private val context: Context) : StreamHandler { private var eventSink: EventSink? = null - private var receiver: NotificationReceiver? = null + var receiver: NotificationReceiver? = null private var listenerIntent : Intent? = null // Called whenever the event channel is subscribed to in Flutter @@ -31,14 +31,10 @@ class NotificationStreamHandler(private val context: Context) : StreamHandler { eventSink = null Log.d("onCancel", "subscription cancelled, stopping service") -// val listenerIntent = Intent(context, NotificationListener::class.java) - listenerIntent?.action = NotificationListener.STOP_FOREGROUND_SERVICE_ACTION - - ContextCompat.startForegroundService(context, listenerIntent!!) context.unregisterReceiver(receiver) } - internal inner class NotificationReceiver : BroadcastReceiver() { + inner class NotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val packageName = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_NAME) val packageMessage = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_MESSAGE) diff --git a/lib/main.dart b/lib/main.dart index 7fc01ce..26f4241 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -112,19 +112,12 @@ class _HomePageState extends State with WidgetsBindingObserver { } void onData(NotificationEvent event) { - // TODO: if the app is in the background, only update our notif - // if the app is in the foreground, update the notif, and - // fetch the new lyrics and display them. setState(() { currentlyPlaying = event; }); } void startListening() { - // TODO: make the FAB start and stop a local notification service - // that keeps track of which song is playing - // and if pressed will fetch the lyrics and display them. - _notifications = AndroidNotificationListener(); _subscription = _notifications.notificationStream.listen(onData);