WIP: make service foreground

This commit is contained in:
2022-02-28 21:30:40 +02:00
parent 2cc0b4b75d
commit 10b7529f98
9 changed files with 208 additions and 132 deletions
+2 -1
View File
@@ -45,7 +45,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.illusionware.lyricsgrabbr.lyricsgrabbr" applicationId "com.illusionware.lyricsgrabbr.lyricsgrabbr"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 31 targetSdkVersion 30
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
} }
@@ -65,4 +65,5 @@ flutter {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
} }
+4 -1
View File
@@ -1,8 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.illusionware.lyricsgrabbr.lyricsgrabbr"> package="com.illusionware.lyricsgrabbr.lyricsgrabbr">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:label="Lyrics Grabbr" android:label="Lyrics Grabbr"
android:name="${applicationName}" android:name=".App"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
@@ -0,0 +1,23 @@
package com.illusionware.lyricsgrabbr.lyricsgrabbr
import android.app.Application
import android.os.StrictMode
class App : Application() {
override fun onCreate() {
super.onCreate()
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectAll() // or .detectAll() for all detectable problems
.penaltyLog()
.build()
)
StrictMode.setVmPolicy(
StrictMode.VmPolicy.Builder()
.detectAll()
.penaltyLog()
.penaltyDeath()
.build()
)
}
}
@@ -1,15 +1,20 @@
package com.illusionware.lyricsgrabbr.lyricsgrabbr package com.illusionware.lyricsgrabbr.lyricsgrabbr
import android.content.Intent import android.content.Intent
import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.util.Log
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
class MainActivity: FlutterActivity() { class MainActivity: FlutterActivity() {
private var streamHandler : NotificationStreamHandler? = null // private var streamHandler : NotificationStreamHandler? = null
private var listenerIntent : Intent? = null
companion object { companion object {
private const val ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS" private const val ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"
@@ -17,10 +22,12 @@ class MainActivity: FlutterActivity() {
private const val METHOD_CHANNEL_NAME = "notifications/method" private const val METHOD_CHANNEL_NAME = "notifications/method"
} }
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { override fun onCreate(savedInstanceState: Bundle?) {
super.configureFlutterEngine(flutterEngine) super.onCreate(savedInstanceState)
val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, METHOD_CHANNEL_NAME) listenerIntent = Intent(applicationContext, NotificationListener::class.java)
val methodChannel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, METHOD_CHANNEL_NAME)
methodChannel.setMethodCallHandler { call, result -> methodChannel.setMethodCallHandler { call, result ->
when (call.method) { when (call.method) {
"plugin.hasPermission" -> { "plugin.hasPermission" -> {
@@ -29,18 +36,19 @@ class MainActivity: FlutterActivity() {
"plugin.openPermissionSettings" -> { "plugin.openPermissionSettings" -> {
result.success(openPermissionSettings()) result.success(openPermissionSettings())
} }
"plugin.startService" -> {
result.success(startService())
}
"plugin.stopService" -> {
result.success(stopService())
}
else -> result.notImplemented() else -> result.notImplemented()
} }
} }
val eventChannel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL_NAME) // val eventChannel = EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, EVENT_CHANNEL_NAME)
streamHandler = NotificationStreamHandler(context) // streamHandler = NotificationStreamHandler(context)
eventChannel.setStreamHandler(streamHandler) // eventChannel.setStreamHandler(streamHandler)
}
override fun onDestroy() {
super.onDestroy()
streamHandler?.cleanUp()
} }
private fun isPermissionGranted(): Boolean { private fun isPermissionGranted(): Boolean {
@@ -59,4 +67,21 @@ class MainActivity: FlutterActivity() {
context.startActivity(Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) context.startActivity(Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
return true return true
} }
private fun startService(): Boolean {
listenerIntent?.action = NotificationListener.START_FOREGROUND_SERVICE_ACTION
ContextCompat.startForegroundService(applicationContext, listenerIntent!!)
Log.d("startService", "starting")
return true
}
private fun stopService(): Boolean {
listenerIntent?.action = NotificationListener.STOP_FOREGROUND_SERVICE_ACTION
ContextCompat.startForegroundService(applicationContext, listenerIntent!!)
Log.d("stopService", "stopping")
//applicationContext.stopService(listenerIntent!!)
return true
}
} }
@@ -1,26 +1,58 @@
package com.illusionware.lyricsgrabbr.lyricsgrabbr package com.illusionware.lyricsgrabbr.lyricsgrabbr
import android.app.Notification import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap
import android.media.MediaMetadata import android.media.MediaMetadata
import android.media.session.MediaController import android.media.session.MediaController
import android.media.session.MediaSession import android.media.session.MediaSession
import android.os.Build
import android.os.Handler
import android.service.notification.NotificationListenerService import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import org.json.JSONException import android.util.Log
import org.json.JSONObject import androidx.core.app.NotificationCompat
import android.os.Bundle import androidx.core.app.NotificationManagerCompat
import java.io.File
import java.io.FileOutputStream
/** /**
* Notification listening service. Intercepts notifications if permission is given to do so. * Notification listening service. Intercepts notifications if permission is given to do so.
*/ */
class NotificationListener : NotificationListenerService() { class NotificationListener : NotificationListenerService() {
private var notificationManager : NotificationManagerCompat? = null
override fun onCreate() {
super.onCreate()
Log.d("onCreate Service", "creating service")
initNotificationChannels(this)
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 { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent != null) {
when (intent.action) {
START_FOREGROUND_SERVICE_ACTION -> {
Log.d("START", "starting foreground service")
startForegroundService()
getCurrentNotifications(applicationContext) getCurrentNotifications(applicationContext)
}
STOP_FOREGROUND_SERVICE_ACTION -> {
Log.d("STOP", "stopping foreground service")
stopForegroundService()
}
}
}
return super.onStartCommand(intent, flags, startId) return super.onStartCommand(intent, flags, startId)
} }
@@ -29,14 +61,46 @@ class NotificationListener : NotificationListenerService() {
} }
override fun onNotificationPosted(sbn: StatusBarNotification) { override fun onNotificationPosted(sbn: StatusBarNotification) {
if (sbn.packageName == SPOTIFY_PACKAGE) {
sendNotificationBroadcast(sbn, applicationContext) sendNotificationBroadcast(sbn, applicationContext)
} }
}
private fun startForegroundService() {
val notification: Notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
.setContentTitle("TITLE")
.setContentText("TEXT")
.setSmallIcon(R.drawable.ic_notification)
.build()
notification.flags = Notification.FLAG_FOREGROUND_SERVICE
startForeground(NOTIFICATION_ID, notification)
}
private fun stopForegroundService() {
stopForeground(true)
stopSelf()
}
private fun initNotificationChannels(context: Context) {
if (Build.VERSION.SDK_INT < 26) {
return
}
val notificationManager =
context.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
"Lyrics",
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(channel)
}
private fun getCurrentNotifications(context: Context) { private fun getCurrentNotifications(context: Context) {
val sbns = activeNotifications val sbns = activeNotifications
for (sbn in sbns) { for (sbn in sbns) {
// TODO: remove this check and figure out a way to send a fucking list instead if (sbn.packageName == SPOTIFY_PACKAGE) {
if (sbn.packageName == "com.spotify.music") {
sendNotificationBroadcast(sbn, context) sendNotificationBroadcast(sbn, context)
} }
} }
@@ -48,19 +112,7 @@ class NotificationListener : NotificationListenerService() {
val mediaCtrl = mediaSessionToken?.let { MediaController(context, it) } val mediaCtrl = mediaSessionToken?.let { MediaController(context, it) }
val duration = mediaCtrl?.metadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.div(1000) val duration = mediaCtrl?.metadata?.getLong(MediaMetadata.METADATA_KEY_DURATION)?.div(1000)
val playbackState = mediaCtrl?.playbackState?.state val playbackState = mediaCtrl?.playbackState?.state
var albumArtPath = ""
if (sbn.packageName == "com.spotify.music") {
val albumArt = mediaCtrl?.metadata?.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART) val albumArt = mediaCtrl?.metadata?.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART)
val tempArtFile = File(cacheDir, "albumart_temp.png")
tempArtFile.createNewFile()
val fileOutputStream = FileOutputStream(tempArtFile)
albumArt?.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)
fileOutputStream.flush()
fileOutputStream.close()
albumArtPath = tempArtFile.absolutePath
}
// Retrieve package name to set as title. // Retrieve package name to set as title.
val packageName = sbn.packageName val packageName = sbn.packageName
@@ -73,10 +125,22 @@ class NotificationListener : NotificationListenerService() {
intent.putExtra(NOTIFICATION_PACKAGE_NAME, packageName) intent.putExtra(NOTIFICATION_PACKAGE_NAME, packageName)
intent.putExtra(NOTIFICATION_PACKAGE_MESSAGE, packageMessage) intent.putExtra(NOTIFICATION_PACKAGE_MESSAGE, packageMessage)
intent.putExtra(NOTIFICATION_PACKAGE_TEXT, packageText) intent.putExtra(NOTIFICATION_PACKAGE_TEXT, packageText)
intent.putExtra(NOTIFICATION_PACKAGE_ART, albumArtPath)
intent.putExtra(NOTIFICATION_PACKAGE_DURATION, duration) intent.putExtra(NOTIFICATION_PACKAGE_DURATION, duration)
intent.putExtra(NOTIFICATION_PACKAGE_PLAYBACK_STATE, playbackState) intent.putExtra(NOTIFICATION_PACKAGE_PLAYBACK_STATE, playbackState)
sendBroadcast(intent)
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()
notification.flags = Notification.FLAG_FOREGROUND_SERVICE
notificationManager?.notify(NOTIFICATION_ID, notification)
//sendBroadcast(intent)
} }
companion object { companion object {
@@ -84,22 +148,12 @@ class NotificationListener : NotificationListenerService() {
const val NOTIFICATION_PACKAGE_NAME = "package_name" const val NOTIFICATION_PACKAGE_NAME = "package_name"
const val NOTIFICATION_PACKAGE_MESSAGE = "package_message" const val NOTIFICATION_PACKAGE_MESSAGE = "package_message"
const val NOTIFICATION_PACKAGE_TEXT = "package_text" const val NOTIFICATION_PACKAGE_TEXT = "package_text"
const val NOTIFICATION_PACKAGE_EXTRA = "package_extra"
const val NOTIFICATION_PACKAGE_ART = "package_art"
const val NOTIFICATION_PACKAGE_PLAYBACK_STATE = "package_playback_state" const val NOTIFICATION_PACKAGE_PLAYBACK_STATE = "package_playback_state"
const val NOTIFICATION_PACKAGE_DURATION = "package_duration" const val NOTIFICATION_PACKAGE_DURATION = "package_duration"
} const val NOTIFICATION_ID = 12251999
const val NOTIFICATION_CHANNEL_ID = "Lyrics"
private fun convertBundleToJsonString(extra: Bundle): String { const val SPOTIFY_PACKAGE = "com.spotify.music"
val json = JSONObject() const val START_FOREGROUND_SERVICE_ACTION = "START_SERVICE"
val keys = extra.keySet() const val STOP_FOREGROUND_SERVICE_ACTION = "STOP_SERVICE"
for (key in keys) {
try {
json.put(key, JSONObject.wrap(extra.get(key)))
} catch (e: JSONException) {
//Handle exception here
}
}
return json.toString()
} }
} }
@@ -3,34 +3,38 @@ package com.illusionware.lyricsgrabbr.lyricsgrabbr
import io.flutter.plugin.common.EventChannel.StreamHandler import io.flutter.plugin.common.EventChannel.StreamHandler
import io.flutter.plugin.common.EventChannel.EventSink import io.flutter.plugin.common.EventChannel.EventSink
import android.content.* import android.content.*
import android.util.Log
import androidx.core.content.ContextCompat
class NotificationStreamHandler(private val context: Context) : StreamHandler { class NotificationStreamHandler(private val context: Context) : StreamHandler {
private var eventSink: EventSink? = null private var eventSink: EventSink? = null
private var receiver: NotificationReceiver? = null private var receiver: NotificationReceiver? = null
private val listenerIntent = Intent(context, NotificationListener::class.java)
// Called whenever the event channel is subscribed to in Flutter // Called whenever the event channel is subscribed to in Flutter
override fun onListen(o: Any?, eventSink: EventSink?) { override fun onListen(o: Any?, eventSink: EventSink?) {
this.eventSink = eventSink this.eventSink = eventSink
receiver = NotificationReceiver() val listenerIntent = Intent(context, NotificationListener::class.java)
val intentFilter = IntentFilter() listenerIntent.action = NotificationListener.START_FOREGROUND_SERVICE_ACTION
intentFilter.addAction(NotificationListener.NOTIFICATION_INTENT)
context.registerReceiver(receiver, intentFilter)
context.startService(listenerIntent) //receiver = NotificationReceiver()
//val intentFilter = IntentFilter()
//intentFilter.addAction(NotificationListener.NOTIFICATION_INTENT)
//context.registerReceiver(receiver, intentFilter)
ContextCompat.startForegroundService(context, listenerIntent)
} }
// Called whenever the event channel subscription is cancelled in Flutter // Called whenever the event channel subscription is cancelled in Flutter
override fun onCancel(o: Any?) { override fun onCancel(o: Any?) {
eventSink = null eventSink = null
Log.d("onCancel", "subscription cancelled, stopping service")
context.stopService(listenerIntent) val listenerIntent = Intent(context, NotificationListener::class.java)
context.unregisterReceiver(receiver) listenerIntent.action = NotificationListener.STOP_FOREGROUND_SERVICE_ACTION
}
fun cleanUp() { ContextCompat.startForegroundService(context, listenerIntent)
context.unregisterReceiver(receiver) //context.unregisterReceiver(receiver)
} }
internal inner class NotificationReceiver : BroadcastReceiver() { internal inner class NotificationReceiver : BroadcastReceiver() {
@@ -38,14 +42,12 @@ class NotificationStreamHandler(private val context: Context) : StreamHandler {
val packageName = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_NAME) val packageName = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_NAME)
val packageMessage = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_MESSAGE) val packageMessage = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_MESSAGE)
val packageText = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_TEXT) val packageText = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_TEXT)
val packageArt = intent.getStringExtra(NotificationListener.NOTIFICATION_PACKAGE_ART)
val packagePlaybackState = intent.getIntExtra(NotificationListener.NOTIFICATION_PACKAGE_PLAYBACK_STATE, -1) val packagePlaybackState = intent.getIntExtra(NotificationListener.NOTIFICATION_PACKAGE_PLAYBACK_STATE, -1)
val packageDuration = intent.getLongExtra(NotificationListener.NOTIFICATION_PACKAGE_DURATION, -1) val packageDuration = intent.getLongExtra(NotificationListener.NOTIFICATION_PACKAGE_DURATION, -1)
val map = HashMap<String, Any>() val map = HashMap<String, Any>()
map["packageName"] = packageName!! map["packageName"] = packageName!!
map["packageMessage"] = packageMessage!! map["packageMessage"] = packageMessage!!
map["packageText"] = packageText!! map["packageText"] = packageText!!
map["packageArt"] = packageArt!!
map["packagePlaybackState"] = packagePlaybackState map["packagePlaybackState"] = packagePlaybackState
map["packageDuration"] = packageDuration map["packageDuration"] = packageDuration
eventSink?.success(map) eventSink?.success(map)
+14 -1
View File
@@ -1,3 +1,16 @@
org.gradle.jvmargs=-Xmx1536M ## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sun Feb 27 21:16:18 EET 2022
org.gradle.jvmargs=-Xmx1024M -Dkotlin.daemon.jvm.options\="-Xmx1024M"
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
+5 -54
View File
@@ -2,34 +2,11 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'notification_listener.dart'; import 'notification_listener.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
const spotifyPackage = "com.spotify.music";
const notificationId = 0;
Future<void> main() async { Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
const AndroidInitializationSettings initializationSettingsAndroid =
AndroidInitializationSettings('@drawable/ic_notification');
const InitializationSettings initializationSettings =
InitializationSettings(android: initializationSettingsAndroid);
await flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: onNotificationClick);
runApp(const LyricsGrabbr()); runApp(const LyricsGrabbr());
} }
void onNotificationClick(String? payload) async {
if (payload != null) {
print('notification payload: $payload');
}
print('notification pressed');
}
class LyricsGrabbr extends StatelessWidget { class LyricsGrabbr extends StatelessWidget {
const LyricsGrabbr({Key? key}) : super(key: key); const LyricsGrabbr({Key? key}) : super(key: key);
@@ -135,56 +112,30 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
} }
void onData(NotificationEvent event) { void onData(NotificationEvent event) {
if (event.packageName == spotifyPackage) {
// TODO: if the app is in the background, only update our notif // TODO: if the app is in the background, only update our notif
// if the app is in the foreground, update the notif, and // if the app is in the foreground, update the notif, and
// fetch the new lyrics and display them. // fetch the new lyrics and display them.
sendNotification(event);
setState(() { setState(() {
_notifs.add(event); _notifs.add(event);
}); });
} }
}
Future<void> sendNotification(NotificationEvent notification) async {
final AndroidNotificationDetails androidNotification =
AndroidNotificationDetails(
"Lyrics",
"Lyrics",
importance: Importance.low,
priority: Priority.min,
showWhen: false,
ongoing: true,
playSound: false,
largeIcon: FilePathAndroidBitmap(notification.art),
);
final NotificationDetails notificationDetails =
NotificationDetails(android: androidNotification);
await flutterLocalNotificationsPlugin.show(
notificationId,
'Playing [${notification.songTitle}] By [${notification.artist}]',
'Tap to get lyrics',
notificationDetails,
);
}
void startListening() { void startListening() {
// TODO: make the FAB start and stop a local notification service // TODO: make the FAB start and stop a local notification service
// that keeps track of which song is playing // that keeps track of which song is playing
// and if pressed will fetch the lyrics and display them. // and if pressed will fetch the lyrics and display them.
_notifications = AndroidNotificationListener(); //_notifications = AndroidNotificationListener();
_subscription = _notifications.notificationStream.listen(onData); //_subscription = _notifications.notificationStream.listen(onData);
AndroidNotificationListener.startService();
setState(() => running = true); setState(() => running = true);
} }
void stopListening() { void stopListening() {
setState(() => running = false); setState(() => running = false);
_subscription.cancel(); AndroidNotificationListener.stopService();
flutterLocalNotificationsPlugin.cancel(notificationId); //_subscription.cancel();
} }
@override @override
+8 -4
View File
@@ -23,7 +23,6 @@ class NotificationEvent {
final String artist; final String artist;
final String packageName; final String packageName;
final String songTitle; final String songTitle;
final String art;
final int playbackState; final int playbackState;
final int duration; final int duration;
@@ -34,7 +33,6 @@ class NotificationEvent {
required this.artist, required this.artist,
required this.timeStamp, required this.timeStamp,
required this.songTitle, required this.songTitle,
required this.art,
required this.playbackState, required this.playbackState,
required this.duration required this.duration
}); });
@@ -44,7 +42,6 @@ class NotificationEvent {
String name = map['packageName']; String name = map['packageName'];
String message = map['packageMessage']; String message = map['packageMessage'];
String text = map['packageText']; String text = map['packageText'];
String icon = map['packageArt'];
int playbackState = map['packagePlaybackState']; int playbackState = map['packagePlaybackState'];
int duration = map['packageDuration']; int duration = map['packageDuration'];
@@ -53,7 +50,6 @@ class NotificationEvent {
artist: message, artist: message,
timeStamp: time, timeStamp: time,
songTitle: text, songTitle: text,
art: icon,
playbackState: playbackState, playbackState: playbackState,
duration: duration duration: duration
); );
@@ -89,4 +85,12 @@ class AndroidNotificationListener {
static Future<bool?> openPermissionSettings() async { static Future<bool?> openPermissionSettings() async {
return await _methodChannel.invokeMethod('plugin.openPermissionSettings'); return await _methodChannel.invokeMethod('plugin.openPermissionSettings');
} }
static Future<bool?> startService() async {
return await _methodChannel.invokeMethod('plugin.startService');
}
static Future<bool?> stopService() async {
return await _methodChannel.invokeMethod('plugin.stopService');
}
} }