Change song progress in notification

565 Views Asked by At

I am using the flutter_notification_listener library to get info related to the currently playing song (on Spotify). Then, when the user presses a button, the song either pauses/resumes. This works perfectly! More than this I was curious to know if there was any method to change the progress of the song using a progress bar in the app? Like: when the user drags the progress bar the song's progress is also changed? This is the code I'm using now:

late NotificationEvent audioEvent;


  void onData(NotificationEvent event) {
    setState(() {
      audioEvent = event;
    });
  }

  Future<void> initPlatformState() async {
    NotificationsListener.initialize();
    NotificationsListener.receivePort?.listen((evt) => onData(evt));
  }

  void startListening() async {
    var hasPermission = await NotificationsListener.hasPermission;
    if (!hasPermission!) {
      NotificationsListener.openPermissionSettings();
      return;
    }

    var isR = await NotificationsListener.isRunning;

    if (!isR!) {
      await NotificationsListener.startService();
    }
   }

  void playPause() {
    audioEvent.actions?[2].tap();   // It works
  }

  @override
  void initState() {
    initPlatformState();
    Future.delayed(const Duration(seconds: 2), () => startListening());
    super.initState();
  }

Button:

TextButton(onPressed: playPause, child: const Text('Play/Pause'))

Any help is highly appreciated ! Thank you

1

There are 1 best solutions below

0
Ajit Kumar On BEST ANSWER

Finally got the solution. By default there is no library/plugin, that I know of, can achieve this. We have to take advantage of the platform channels in flutter and use native java.
I created a new MethodChannel and invoked a method to communicate with the java code:

static const platform =
      MethodChannel('com.example.foobar/playbackstatus');

  Future<void> _setPlayBackDur() async {
    try {
      final int result = await platform.invokeMethod('setPlayBackDur');
    } on PlatformException catch (e) {
      
    }
  }

Next follow the steps in the platform channels docs.
MainActivity.java :

package com.example.audionotification;

import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.os.BatteryManager;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;

import androidx.annotation.NonNull;
import androidx.core.app.NotificationManagerCompat;

import java.util.List;
import java.util.Set;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodChannel;

public class MainActivity extends FlutterActivity {
    private static final String CHANNEL = "com.example.foobar/playbackstatus";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
                .setMethodCallHandler(
                        (call, result) -> {
                            // This method is invoked on the main thread.
                            if (call.method.equals("setPlayBackDur")) {
                                


                                if (!permissionGrantred()) {
                                    Intent intent = new Intent(
                                            "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
                                    startActivity(intent);
                                    result.error("UNAVAILABLE", "...", null);
                                } else {
                                    MediaSessionManager msm = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
                                    ComponentName cn = new ComponentName(this, MyNotificationService.class);
                                    List<MediaController> list = msm.getActiveSessions(cn);
                                    for (MediaController mc : list) {
                                        if (mc.getPackageName().equals("com.spotify.music")) {
                                            mc.getTransportControls().seekTo(136901);  //ms to seekto
                                            result.success(136901);
                                        }
                                    }
                                }
                            } else {
                                result.notImplemented();
                            }
                        }

                );
    }

    private boolean permissionGrantred() {
        Set<String> sets = NotificationManagerCompat.getEnabledListenerPackages(this);
        if (sets != null && sets.contains(getPackageName())) {
            return true;
        } else {
            return false;
        }
    }

//not included
        private int getBatteryLevel() {
            int batteryLevel = -1;
            if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
                BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
                batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
            } else {
                Intent intent = new ContextWrapper(getApplicationContext()).
                        registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
                batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                        intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
            }
    
            return batteryLevel;
        }
    }

MyNotificationService.java:

package com.example.audionotification;

import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;


public class MyNotificationService extends NotificationListenerService {
    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
        super.onNotificationRemoved(sbn);
    }

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        super.onNotificationPosted(sbn);
    }
}

Hope it helps! (Thx to https://stackoverflow.com/a/66795488/14326852)