flutter_background_service icon indicating copy to clipboard operation
flutter_background_service copied to clipboard

stopSelf() on notification action press doesn't work.

Open AbdulSamadgithub opened this issue 2 years ago • 4 comments

I want to stop service on "shutdown" notification action press, everything else works but service don't stop on service.stopSelf().

notification :

simpleNotification(
    {required int minutes,
    required int seconds,
    required FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin}) {
  flutterLocalNotificationsPlugin.show(
    1,
    'App sync running ....',
    'Interval  $minutes:$seconds',
    const NotificationDetails(
      android: AndroidNotificationDetails(
        "1",
        'MY FOREGROUND SERVICE',
        subText: "App Sync is running .....",
        icon: 'ic_bg_service_small',
        ongoing: false,
        playSound: false,
        enableVibration: false,
        tag: 'simple_notification',
        actions: [
          AndroidNotificationAction("pause", "pause"),
          AndroidNotificationAction("shutdown", "shutdown"),
        ],
      ),
    ),
  );
}

I'm initializing service like this

Future<void> initializeService() async {
  final service = FlutterBackgroundService();
  final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  // <---------------------Notification-------------------------->
  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    "1",
    'MY FOREGROUND SERVICE',
    description: 'This channel description',
    importance: Importance.high,
  );

  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
      ?.createNotificationChannel(channel);

  flutterLocalNotificationsPlugin.initialize(
    const InitializationSettings(
      android: AndroidInitializationSettings("@mipmap/ic_launcher"),
    ),
    onDidReceiveBackgroundNotificationResponse: onNotificationResponse,
  );

  // <---------------------Notification-------------------------->

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      onStart: onStart,
      autoStart: true,
      isForegroundMode: true,
      notificationChannelId: "1",
      initialNotificationTitle: 'AWESOME SERVICE',
      initialNotificationContent: 'Initializing',
      foregroundServiceNotificationId: 1,
    ),
    iosConfiguration: IosConfiguration(),
  );
}

In above code onDidReceiveBackgroundNotificationResponse accepts onNotificationResponse top level function. on 'shutdown' press print("shutdown pressed ....") executes but service.invoke doesn't.
similarly on "pause" action press print("pause action pressed..."); executes as expected.

@pragma('vm:entry-point')
void onNotificationResponse(NotificationResponse notificationResponse) {
  if (notificationResponse.actionId == "pause") {
    print("pause action pressed...");
  }
  if (notificationResponse.actionId == "shutdown") {

     //  <---------this doesn't work----------->
    final service = FlutterBackgroundService();
    service.invoke("stopService");
    print("Shutdown pressed...");
  }
}

In one of my widget service.invoke works perfectly, which is similar to the previous conditional statement block in onNotificationResponse function where I'm checking for shutdown action press, which doesn't work.

ElevatedButton(
  style: ButtonStyle(
    backgroundColor: MaterialStateProperty.all<Color>(Colors.pink),
  ),
  onPressed: () async {
    final service = FlutterBackgroundService();
    service.invoke("stopService");
    print("service Stopped...");
  },
  child: const Text("   Stop service   "),
)

onStart()

Future<void> onStart(ServiceInstance service) async {
  final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
  DartPluginRegistrant.ensureInitialized();
  int minutes = 0;
  int seconds = 10;

  service.on("stopService").listen((event) {
    service.stopSelf();
  });

  Timer.periodic(const Duration(seconds: 1), (timer) async {
    // one minute completed
    if (seconds == 60) {
      // reset seconds
      seconds = 0;

      // increment minutes
      minutes++;
    }

    simpleNotification(
      minutes: minutes,
      seconds: seconds,
      flutterLocalNotificationsPlugin: flutterLocalNotificationsPlugin,
    );

    // increment seconds every second
    seconds++;
  });
}

I'll be grateful for your help.

AbdulSamadgithub avatar Feb 15 '23 13:02 AbdulSamadgithub

docs say

Only use FlutterBackgroundService class in UI Isolate and ServiceInstance in background isolate. I can't create an Instance of ServiceInstance in onNotificationResponse.

AbdulSamadgithub avatar Feb 17 '23 06:02 AbdulSamadgithub

Did you find a solution or any workaround ?!

mo15hammed avatar May 30 '23 09:05 mo15hammed

I found this workaround where I use "exit(0)" to terminate the app. This will also force the service to stop.

You still have to call "service.invoke("stopService")" because if you do not, the service will just restart itself.

  if (notificationResponse.actionId == "shutdown") {
    final service = FlutterBackgroundService();
    service.invoke("stopService");
    logger.w("Shutdown pressed...");
    // add this line to kill the app process
    exit(0);
  }

mo15hammed avatar May 30 '23 09:05 mo15hammed

FlutterBackgroundService().invoke("stop_service", null); i use this function and work it

appsorooshan avatar Sep 30 '23 10:09 appsorooshan