Stopping a background service from notification

后端 未结 3 1517
南方客
南方客 2021-01-12 18:38

I have a background service in which I want to show a notification which allows the user to stop it.

In the android SDK docs it says an activity is used to normally

相关标签:
3条回答
  • 2021-01-12 18:57

    The question is already old, but since there is still no solution with code, I simply share my code as an example for solving the problem:

    You cannot directly stop the service from a Notification. You can start the service, using an Intent that has an action string or extra or something that the service sees in onStartCommand() and triggers it to call stopSelf().

    That's the right solution so let's jump in code (this code is all in your ExampleService class):

    @RequiresApi(Build.VERSION_CODES.O)
    private void startForegroundService() {
        // create PendingIntend to open MainActivity (this is when the notification gets clicked) //
        Intent tabIntent = new Intent(this, MainActivity.class);
        tabIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent tabPendingIntent = PendingIntent.getActivity(this, 0, tabIntent, 0);
    
        // create PendingIntend to open ExampleService (this is when the notification BUTTON gets clicked) //
        Intent closeIntent = new Intent(this, ExampleService.class);
        closeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        closeIntent.putExtra("destroyCode", 666); // this is the important line //
        PendingIntent closePendingIntent = PendingIntent.getService(this, 0, closeIntent, 0);
    
        createNotificationChannel(); // this is only the default code to create notification channel. I just outsourced? it //
    

    Now the Intent has additional data (the "destroy code" -> 666). Notice that we have created 2 pendingIntents: closePendingIntent (stop Service) and tabPendingIntent (start Activity)

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        // get extras to know if Intent has destroyCode (666)
        Bundle extras = intent.getExtras();
        if (extras == null) {  
             // extras is null which means there is no destroyCode (666)
             exampleMethod();
    
        } else {
            // Intent has destroyCode (666) -> Intent comes from notification -> stop the service and close notification
    
            stopSelf();          
        }
        return START_STICKY;
    }
    

    Now we have the code to check if there is a destroyCode or not. The last step is to create a notification with a button:

    // set attributes for notification //
                final NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "channelID_2");
                Notification notification = builder.setOngoing(true)
                        .setSmallIcon(R.drawable.example)
                        .setContentTitle(getText(R.string.notificationTitle))
                        .setContentText(getText(R.string.notificationText))
                        .setPriority(NotificationCompat.PRIORITY_HIGH)
                        .setCategory(NotificationCompat.CATEGORY_MESSAGE)
                        .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                        .setContentIntent(tabPendingIntent) //this is when notification is clicked which only opens ExampleActivity
                        .addAction(R.drawable.example, getString(R.string.notificationButtonText), closePendingIntent) // here is our closePendingIntent with the destroyCode .addAction is "the onClickListener for the notification button"//
                            .build();
                    startForeground(2, notification);
    

    In onCreate you start your service

        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O)
            startForegroundService();
        else
            startForeground(1, new Notification());
    
        // Toast Message that service has started
        Toast.makeText(this, R.string.serviceStarted, Toast.LENGTH_SHORT).show();
    

    That's it

    0 讨论(0)
  • 2021-01-12 19:08

    You can't start an Acitivty from a Service just like that. What you can do is create a callback to an Activity in the Service and let the callback start new activities. But having a notification means you don't have to go through the Service. When the notification is clicked, you can start an activity that's specified in the Intent you supply to the notification. It's really very simple.

    Do read the reference docs on notifications for examples.

    0 讨论(0)
  • 2021-01-12 19:18

    So I am wondering if I need to create an activity to stop the service or can I directly stop the service when user selects the notification,

    You cannot directly stop the service from a Notification. You can start the service, using an Intent that has an action string or extra or something that the service sees in onStartCommand() and triggers it to call stopSelf().

    0 讨论(0)
提交回复
热议问题