28

I am trying to start a foreground service. I get notified that the service does start but the notification always gets suppressed. I double checked that the app is allowed to show notifications in the app info on my device. Here is my code:

private void showNotification() {
    Intent notificationIntent = new Intent(this, MainActivity.class);
    notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
            | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);

    Bitmap icon = BitmapFactory.decodeResource(getResources(),
            R.mipmap.ic_launcher);

    Notification notification = new NotificationCompat.Builder(getApplicationContext())
            .setContentTitle("Revel Is Running")
            .setTicker("Revel Is Running")
            .setContentText("Click to stop")
            .setSmallIcon(R.mipmap.ic_launcher)
            //.setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
            .setContentIntent(pendingIntent)
            .setOngoing(true).build();
    startForeground(Constants.FOREGROUND_SERVICE,
            notification);
    Log.e(TAG,"notification shown");

}

Here is the only error I see in relation: 06-20 12:26:43.635 895-930/? E/NotificationService: Suppressing notification from the package by user request.

madhan kumar
  • 1,560
  • 2
  • 26
  • 36
Dreamers Org
  • 1,151
  • 3
  • 12
  • 30

9 Answers9

36

It's because of Android O bg services restrictions.

So now you need to call startForeground() only for services that were started with startForegroundService() and call it in first 5 seconds after service has been started.

Here is the guide - https://developer.android.com/about/versions/oreo/background#services

Like this:

//Start service:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  startForegroundService(new Intent(this, YourService.class));
} else {
  startService(new Intent(this, YourService.class));
}

Then create and show notification (with channel as supposed earlier):

private void createAndShowForegroundNotification(Service yourService, int notificationId) {

    final NotificationCompat.Builder builder = getNotificationBuilder(yourService,
         "com.example.your_app.notification.CHANNEL_ID_FOREGROUND", // Channel id
    NotificationManagerCompat.IMPORTANCE_LOW); //Low importance prevent visual appearance for this notification channel on top 
    builder.setOngoing(true)
    .setSmallIcon(R.drawable.small_icon)
    .setContentTitle(yourService.getString(R.string.title))
    .setContentText(yourService.getString(R.string.content));

    Notification notification = builder.build();

    yourService.startForeground(notificationId, notification);

    if (notificationId != lastShownNotificationId) {
          // Cancel previous notification
          final NotificationManager nm = (NotificationManager) yourService.getSystemService(Activity.NOTIFICATION_SERVICE);
          nm.cancel(lastShownNotificationId);
    }
    lastShownNotificationId = notificationId;
}

public static NotificationCompat.Builder getNotificationBuilder(Context context, String channelId, int importance) {
    NotificationCompat.Builder builder;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        prepareChannel(context, channelId, importance);
        builder = new NotificationCompat.Builder(context, channelId);
    } else {
        builder = new NotificationCompat.Builder(context);
    }
    return builder;
}

@TargetApi(26)
private static void prepareChannel(Context context, String id, int importance) {
    final String appName = context.getString(R.string.app_name);
    String description = context.getString(R.string.notifications_channel_description);
    final NotificationManager nm = (NotificationManager) context.getSystemService(Activity.NOTIFICATION_SERVICE);

    if(nm != null) {
        NotificationChannel nChannel = nm.getNotificationChannel(id);

        if (nChannel == null) {
            nChannel = new NotificationChannel(id, appName, importance);
            nChannel.setDescription(description);
            nm.createNotificationChannel(nChannel);
        }
    }
}

Remember that your foreground notification will have the same state as your other notifications even if you'll use different channel ids, so it might be hidden as a group with others. Use different groups to avoid it.

v1k
  • 1,307
  • 2
  • 15
  • 20
  • How to stop the forground service on Android O and above? – Shajeel Afzal Dec 04 '18 at 18:10
  • Check here https://developer.android.com/reference/android/app/Service, if you started it as foreground - use "stopForeground()" with notification id or boolean arg, otherwise use the regular stopService/unbindService depends from how you started and use it. – v1k Dec 04 '18 at 19:09
  • 3
    You can also use ContextCompat.startForegroundService(context, intentService) – Yeti Jan 11 '19 at 06:08
  • Do I need to run this on activity that starts the foreground service or on the service class? I'm a bit confused, looking for advice. – Bangonkali Feb 22 '19 at 15:02
  • startForegroundService/startService from Activity, or wherever you will start your service. And the notification block from anywhere. Maybe some util class. – v1k Feb 22 '19 at 20:20
  • so we can pass any number to notification id ?other than 0? – Wini Sep 24 '20 at 07:09
  • You can pass any string, keep in mind it should be unique. Details here https://developer.android.com/reference/android/app/NotificationChannel#NotificationChannel(java.lang.String,%20java.lang.CharSequence,%20int) – v1k Sep 26 '20 at 02:35
22

The problem was i am using Android O and it requires more information. Here is the successful code for android O.

    mNotifyManager = (NotificationManager) mActivity.getSystemService(Context.NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createChannel(mNotifyManager);
    mBuilder = new NotificationCompat.Builder(mActivity, "YOUR_TEXT_HERE").setSmallIcon(android.R.drawable.stat_sys_download).setColor
            (ContextCompat.getColor(mActivity, R.color.colorNotification)).setContentTitle(YOUR_TITLE_HERE).setContentText(YOUR_DESCRIPTION_HERE);
    mNotifyManager.notify(mFile.getId().hashCode(), mBuilder.build());

@TargetApi(26)
private void createChannel(NotificationManager notificationManager) {
    String name = "FileDownload";
    String description = "Notifications for download status";
    int importance = NotificationManager.IMPORTANCE_DEFAULT;

    NotificationChannel mChannel = new NotificationChannel(name, name, importance);
    mChannel.setDescription(description);
    mChannel.enableLights(true);
    mChannel.setLightColor(Color.BLUE);
    notificationManager.createNotificationChannel(mChannel);
}
Dreamers Org
  • 1,151
  • 3
  • 12
  • 30
  • Is there a more convenient way to handle this? i.e. support/compat-style? Same code that works on both pre-26 and 26+ platforms, without using "if" and duplicating code. – Hendy Irawan Jan 29 '18 at 16:38
  • if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {createNotificationChannel(context);} //REST OF CODE HERE – Dreamers Org Jan 29 '18 at 19:19
  • 10
    But in this new snippet of code, I notice that you are calling `mNotifyManager.notify()` instead of `startForeground()`. In this case, is it really making the service foreground? – Sira Lam Mar 06 '18 at 09:28
  • 2
    What is `mFile` ? – Petro Nov 14 '18 at 00:47
  • i just miss this sentence.. notificationManager.createNotificationChannel(mChannel); when i wrote it it work like charm. no need to define startForeground() – Vasudev Vyas Aug 01 '19 at 09:48
9

For me everything was set correctly (also added FOREGROUND_SERVICE permission to manifest), but I just needed to uninstall the app and reinstall it.

Hanoch Moreno
  • 593
  • 7
  • 9
8

If none of the above worked you should check if your notification id is 0 ... SURPRISE!! it cannot be 0.

Many thanks to @Luka Kama for this post

startForeground(0, notification); // Doesn't work...

startForeground(1, notification); // Works!!!
DoruChidean
  • 7,941
  • 1
  • 29
  • 33
1

if you are targeting Android 9(Pie) api level 28 and higher than you should give FOREGROUND_SERVICE permission in manifest file.see this link : https://developer.android.com/about/versions/pie/android-9.0-migration#bfa

Sanjay
  • 574
  • 6
  • 16
1

I can not believe it. In my case, after adding 'android:name=".App"' to AndroidManifest.xml, the notification started showing. Example:

    <application
    android:name=".App"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
Huu19
  • 11
  • 2
1

For Android API level 33+ you need to request POST_NOTIFICATIONS runtime permission. Although this doesn't prevent the foreground service from running, it's still mandatory to notify as we did for < API 33:

Note: Apps don't need to request the POST_NOTIFICATIONS permission in order to launch a foreground service. However, apps must include a notification when they start a foreground service, just as they do on previous versions of Android.

See more in Android Documentation.

Andy
  • 186
  • 1
  • 4
  • 23
  • this actualy solved my problem. in detail you need to add POST_NOTIFICATIONS to the uses-permission in the manifest AND checkSelfPermission as you would with any other permission before starting the foreground service. – save_jeff Jul 14 '23 at 12:13
0

don't forget to grant notification permission to your app in system setting, the setting name might be something like "App notification management" as the image bellow shows.

SalutonMondo
  • 629
  • 9
  • 17
-4

In my case, it was caused by me using IntentService.

In short, if you want a foreground service then subclass Service.

Hendy Irawan
  • 20,498
  • 11
  • 103
  • 114