Android Oreo persistent notification "App is running in the background"

Viewed 9832

I'm an Android app developer, and is developing an instant message app. The app has a notification problem on Android Oreo system, which shows persistent notification "App is running in the background" and cannot be cleared, and it's OK on system before Android Oreo.

Screenshot: The phone shows persistent notification App is running in the background

I find some discussion, such as Nexus Help Forum about this question, but it doesn't work in my phone's settings.

I want to know how to hide this notification programmatically and the app also can receive message instantly because it's an instant message app.

Any help is very appreciated.

4 Answers

The app has a notification problem on Android Oreo system, which shows persistent notification "App is running in the background" and cannot be cleared, and it's OK on system before Android Oreo.

You used startForeground() with a minimum-importance Notification.

I want to know how to hide this notification programmatically

Use startForeground() with a Notification that has higher than minimum importance. Or, do not use startForeground().

I find some install message apps such as WeChat, Facebook doesn't have this problem on Android Oreo

They are not using foreground services, presumably. For example, they might be using Firebase Cloud Messaging (FCM).

Before we talk about how to get rid of it, however, let’s talk about why it’s there in the first place.

Basically, in previous versions of Android, there was no real way of knowing if an app was running in the background doing a bunch of stuff it’s not supposed to be doing. In most scenarios, these misbehaving apps would wreak havoc on the battery by keeping the system awake—these are called “wakelocks.” In laymen’s terms, it was keeping the system from sleeping. That’s bad.

With Oreo, Google is calling out developers that let their apps do this sort of thing with the new notification. Essentially, if an app is running in the background and chewing up battery life, this new notification will tell you.

NOTE: There are a few legitimate scenarios where an app will continuously run in the background, like the VPN service running. Often, however, apps are running in the background unjustifiably.

It’s worth noting, though, removing the notification does not solve the issue. Period. There’s a reason this notification exists, and getting rid of it will do nothing to solve the underlying issue. You’ll either need to change a setting within the app or uninstall it altogether.

As long as you understand that and still want to remove it, let’s do this thing. Because this is a relatively crucial system setting, there’s no way within Oreo itself to remove it. That makes sense.

But like with most things, the developer community has found a way to remove it, and developer iboalali released an app to do just that. It’s actually just called “Hide ‘running in the background’ Notification,” which is about as straightforward as an app name could ever be. Go ahead and give it an install.

Without root, there is no way to actually prevent Android System from displaying the persistent “app is running in the background” notification in Android 8.0 Oreo. Looking at the source code for the ForegroundServiceController, its implementation, and the ForegroundServiceDialog doesn’t really reveal anything we can take advantage of. Programatically nothing have been found so far.

Here's a Blog post that can help you

First, you must have the NotificationListenerService implementation. Second, in this service (after onListenerConnected callback), check the active ongoing notifications with packageName called 'android'. And check this notification's title is your app name or text value is 'App is running in the background' and snooze it.

public class NLService extends NotificationListenerService {

   @Override
   public void onNotificationRemoved(StatusBarNotification sbn) {}

   @Override
   public void onListenerConnected() {
      super.onListenerConnected();

      checkOngoingNotification();
   }

   @Override
   public void onNotificationPosted(StatusBarNotification sbn){

      if(sbn.isOngoing()) { 

         checkOngoingNotification(); 
         return; 
      }
   }

   private void checkOngoingNotification() {

      StatusBarNotification[] activeNotifications = getActiveNotifications();

      Log.i("NLService", "Active notifications size : " + activeNotifications.length);

      for (StatusBarNotification statusBarNotification : activeNotifications) {

         Log.i("NLService", "notification package  : " + statusBarNotification.getPackageName());
         Log.i("NLService", "notification id       : " + statusBarNotification.getId());
         Log.i("NLService", "notification key      : " + statusBarNotification.getKey());
         Log.i("NLService", "isOngoing             : " + statusBarNotification.isOngoing());
         Log.i("NLService", "isClearable           : " + statusBarNotification.isClearable());
         Log.i("NLService", "groupKey              : " + statusBarNotification.getGroupKey());

         Notification notification = statusBarNotification.getNotification();

         CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
         CharSequence text  = notification.extras.getCharSequence(Notification.EXTRA_TEXT);


         if (title != null && text != null) {

            Log.i("NLService", "title                : " + title);
            Log.i("NLService", "text                 : " + text);


            if (statusBarNotification.getPackageName().equals("android") &&
                (title.toString().contains("Your App Name") || text.toString().contains("App is running"))) {

                long snoozLong = 60000L * 60L * 24L * 20L;

                this.snoozeNotification(statusBarNotification.getKey(), snoozLong);

                Log.i("NLService", "Snoozed notification  : " + title);
            }
        }
    }
}

It turns out startForeground() with channel's IMPORTANCE_MIN is not only one source of the notification. If you call startForeground() and give it notification without setSmallIcon() result will be the same. https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/am/ServiceRecord.java#816

Also you could find in logs something like that:

ActivityManager: Attempted to start a foreground service (ComponentInfo{com.example.app/com.example.app.ExampleService}) with a broken notification (no icon: Notification(channel=channel_example pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE))

Related