mirror of
https://github.com/IllusionMan1212/lyrics-grabbr.git
synced 2026-10-24 02:12:27 +00:00
feat: finish foreground service work
This commit is contained in:
@@ -45,7 +45,7 @@ android {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.illusionware.lyricsgrabbr.lyricsgrabbr"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 30
|
||||
targetSdkVersion 31
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<application
|
||||
android:label="Lyrics Grabbr"
|
||||
android:name=".App"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
+4
-31
@@ -7,14 +7,12 @@ import android.util.Log
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.EventChannel
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
// private var streamHandler : NotificationStreamHandler? = null
|
||||
private var listenerIntent : Intent? = null
|
||||
private var streamHandler : NotificationStreamHandler? = null
|
||||
|
||||
companion object {
|
||||
private const val ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"
|
||||
@@ -25,8 +23,6 @@ class MainActivity: FlutterActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
listenerIntent = Intent(applicationContext, NotificationListener::class.java)
|
||||
|
||||
val methodChannel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, METHOD_CHANNEL_NAME)
|
||||
methodChannel.setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
@@ -36,19 +32,13 @@ class MainActivity: FlutterActivity() {
|
||||
"plugin.openPermissionSettings" -> {
|
||||
result.success(openPermissionSettings())
|
||||
}
|
||||
"plugin.startService" -> {
|
||||
result.success(startService())
|
||||
}
|
||||
"plugin.stopService" -> {
|
||||
result.success(stopService())
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
|
||||
// val eventChannel = EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, EVENT_CHANNEL_NAME)
|
||||
// streamHandler = NotificationStreamHandler(context)
|
||||
// eventChannel.setStreamHandler(streamHandler)
|
||||
val eventChannel = EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, EVENT_CHANNEL_NAME)
|
||||
streamHandler = NotificationStreamHandler(context)
|
||||
eventChannel.setStreamHandler(streamHandler)
|
||||
}
|
||||
|
||||
private fun isPermissionGranted(): Boolean {
|
||||
@@ -67,21 +57,4 @@ class MainActivity: FlutterActivity() {
|
||||
context.startActivity(Intent(ACTION_NOTIFICATION_LISTENER_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -60,6 +60,11 @@ class NotificationListener : NotificationListenerService() {
|
||||
getCurrentNotifications(applicationContext)
|
||||
}
|
||||
|
||||
override fun onListenerDisconnected() {
|
||||
stopForegroundService()
|
||||
super.onListenerDisconnected()
|
||||
}
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification) {
|
||||
if (sbn.packageName == SPOTIFY_PACKAGE) {
|
||||
sendNotificationBroadcast(sbn, applicationContext)
|
||||
@@ -140,7 +145,7 @@ class NotificationListener : NotificationListenerService() {
|
||||
|
||||
notificationManager?.notify(NOTIFICATION_ID, notification)
|
||||
|
||||
//sendBroadcast(intent)
|
||||
sendBroadcast(intent)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
+12
-11
@@ -9,20 +9,21 @@ import androidx.core.content.ContextCompat
|
||||
class NotificationStreamHandler(private val context: Context) : StreamHandler {
|
||||
private var eventSink: EventSink? = null
|
||||
private var receiver: NotificationReceiver? = null
|
||||
private var listenerIntent : Intent? = null
|
||||
|
||||
// Called whenever the event channel is subscribed to in Flutter
|
||||
override fun onListen(o: Any?, eventSink: EventSink?) {
|
||||
this.eventSink = eventSink
|
||||
|
||||
val listenerIntent = Intent(context, NotificationListener::class.java)
|
||||
listenerIntent.action = NotificationListener.START_FOREGROUND_SERVICE_ACTION
|
||||
listenerIntent = Intent(context, NotificationListener::class.java)
|
||||
listenerIntent?.action = NotificationListener.START_FOREGROUND_SERVICE_ACTION
|
||||
|
||||
//receiver = NotificationReceiver()
|
||||
//val intentFilter = IntentFilter()
|
||||
//intentFilter.addAction(NotificationListener.NOTIFICATION_INTENT)
|
||||
//context.registerReceiver(receiver, intentFilter)
|
||||
receiver = NotificationReceiver()
|
||||
val intentFilter = IntentFilter()
|
||||
intentFilter.addAction(NotificationListener.NOTIFICATION_INTENT)
|
||||
context.registerReceiver(receiver, intentFilter)
|
||||
|
||||
ContextCompat.startForegroundService(context, listenerIntent)
|
||||
ContextCompat.startForegroundService(context, listenerIntent!!)
|
||||
}
|
||||
|
||||
// Called whenever the event channel subscription is cancelled in Flutter
|
||||
@@ -30,11 +31,11 @@ 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
|
||||
// val listenerIntent = Intent(context, NotificationListener::class.java)
|
||||
listenerIntent?.action = NotificationListener.STOP_FOREGROUND_SERVICE_ACTION
|
||||
|
||||
ContextCompat.startForegroundService(context, listenerIntent)
|
||||
//context.unregisterReceiver(receiver)
|
||||
ContextCompat.startForegroundService(context, listenerIntent!!)
|
||||
context.unregisterReceiver(receiver)
|
||||
}
|
||||
|
||||
internal inner class NotificationReceiver : BroadcastReceiver() {
|
||||
|
||||
+48
-20
@@ -35,7 +35,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
late AndroidNotificationListener _notifications;
|
||||
late StreamSubscription<NotificationEvent> _subscription;
|
||||
BuildContext? permissionDialogCtx;
|
||||
final List<NotificationEvent> _notifs = [];
|
||||
NotificationEvent? currentlyPlaying;
|
||||
bool running = false;
|
||||
|
||||
@override
|
||||
@@ -67,7 +67,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
void showNotificationPermDialog() {
|
||||
void _showNotificationPermDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
@@ -107,7 +107,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
if (perm != null && perm) {
|
||||
startListening();
|
||||
} else {
|
||||
showNotificationPermDialog();
|
||||
_showNotificationPermDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
// if the app is in the foreground, update the notif, and
|
||||
// fetch the new lyrics and display them.
|
||||
setState(() {
|
||||
_notifs.add(event);
|
||||
currentlyPlaying = event;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -125,17 +125,15 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
// that keeps track of which song is playing
|
||||
// and if pressed will fetch the lyrics and display them.
|
||||
|
||||
//_notifications = AndroidNotificationListener();
|
||||
_notifications = AndroidNotificationListener();
|
||||
|
||||
//_subscription = _notifications.notificationStream.listen(onData);
|
||||
AndroidNotificationListener.startService();
|
||||
_subscription = _notifications.notificationStream.listen(onData);
|
||||
setState(() => running = true);
|
||||
}
|
||||
|
||||
void stopListening() {
|
||||
setState(() => running = false);
|
||||
AndroidNotificationListener.stopService();
|
||||
//_subscription.cancel();
|
||||
_subscription.cancel();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -144,19 +142,49 @@ class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
|
||||
appBar: AppBar(
|
||||
title: Text(widget.title),
|
||||
),
|
||||
body: ListView.builder(
|
||||
itemCount: _notifs.length,
|
||||
reverse: true,
|
||||
itemBuilder: (BuildContext context, int idx) {
|
||||
final entry = _notifs[idx];
|
||||
return ListTile(
|
||||
leading: Text(entry.songTitle),
|
||||
trailing: Text(entry.artist),
|
||||
);
|
||||
}),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
running ? RichText(
|
||||
text: TextSpan(
|
||||
text: currentlyPlaying?.songTitle,
|
||||
style: const TextStyle(
|
||||
fontSize: 24.0,
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "\n",
|
||||
),
|
||||
TextSpan(
|
||||
text: currentlyPlaying?.artist,
|
||||
style: const TextStyle(
|
||||
fontSize: 20.0,
|
||||
color: Color(0xFF303030),
|
||||
)
|
||||
)
|
||||
]
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
) :
|
||||
const Text("Listener stopped"),
|
||||
running ? Text(
|
||||
currentlyPlaying?.playbackState == PlaybackState.STATE_PLAYING ? "Spotify Playing" : "Spotify Paused",
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
) :
|
||||
const Text("")
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: running ? stopListening : startListening,
|
||||
tooltip: running ? 'Stop service' : "Start service",
|
||||
tooltip: running ? 'Stop listener' : "Start listener",
|
||||
child: running ? const Icon(Icons.stop) : const Icon(Icons.play_arrow),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -85,12 +85,4 @@ class AndroidNotificationListener {
|
||||
static Future<bool?> openPermissionSettings() async {
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user