Foreground service notification takes a few seconds to show up - android

Foreground service notification shows too slowly on Android 12. Used ContextCompat.startForegroundService(...) and mContext.startForegroundService(...). It still shows in 5-10 seconds.
Here is an example of my code:
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Counting steps", NotificationManager.IMPORTANCE_DEFAULT);
channel.enableVibration(false);
channel.setSound(null, null);
channel.setShowBadge(false);
notificationManager.createNotificationChannel(channel);
}
}
The onStartCommand method:
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String input = intent.getStringExtra("numberOfSteps");
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Notification.Builder notificationBuilder = new Notification.Builder(this, CHANNEL_ID)
.setContentTitle("Counting steps")
.setContentText(input)
.setSmallIcon(R.drawable.ic_baseline_directions_walk_24)
.setContentIntent(pendingIntent);
startForeground(FOREGROUND_ID, notificationBuilder.build());
}
return START_STICKY;
}
How can I start or show a foreground service notification quickly?

Services that show a notification immediately
If a foreground service has at least one of the following
characteristics, the system shows the associated notification
immediately after the service starts, even on devices that run Android
12 or higher:
The service is associated with a notification that includes action
buttons. The service has a foregroundServiceType of
mediaPlayback, mediaProjection, or phoneCall. The service
provides a use case related to phone calls, navigation, or media
playback, as defined in the notification's category
attribute. The service has opted out of the behavior
change by passing FOREGROUND_SERVICE_IMMEDIATE into
setForegroundServiceBehavior() when setting up the
notification.
On Android 13 (API level 33) or higher, if the user denies the
notification permission, they still see notices related to foreground
services in the Foreground Services (FGS) Task Manager but don't see
them in the notification drawer.
See: Services that show a notification immediately
Java example code:
Notification.Builder notificationBuilder = new Notification.Builder(this, CHANNEL_ID)
.setContentTitle("Counting steps")
.setContentText(message)
.setSmallIcon(R.drawable.your_cool_icon)
.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
notificationBuilder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
}
Kotlin example:
val notificationBuilder: Notification.Builder =
Notification.Builder(this, CHANNEL_ID)
.setContentTitle("Notification title")
.setContentText("Content title")
.setSmallIcon(R.drawable.your_cool_icon)
.setContentIntent(pendingIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
notificationBuilder.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE)
}

Related

Persistent notification android

I need to create a persistent notification - even on new Android versions.
I use a foreground service with (START_STICKY) to display the notification. The notification is created in the method onCreate() and from time to time I start again the foreground service - just in case it was killed.
This is how I create the notification:
String CHANNEL_ID = MainActivity.packageName+".notification";// The id of the channel.
CharSequence name = getString(R.string.app_name);// The user-visible name of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
mChannel.setSound(null, null);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder nBuilder = new NotificationCompat.Builder(this, MainActivity.packageName+".notification");
Intent main = new Intent(this, MainActivity.class);
main.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, main, PendingIntent.FLAG_UPDATE_CURRENT);
// set intent so it does not start a new activity
Notification notification = nBuilder
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.icon)
.setWhen( System.currentTimeMillis())
.setContentTitle("my app")
.setContentText("my msg")
.setOngoing(true)
.setChannelId(MainActivity.packageName+".notification")
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
//notificationManager.notify(StaticMembers.notifId, notification);
startForeground(StaticMembers.notifId+1, notification);
The notification is shown but on some phone models, after a few days the notification is not shown anymore, even if the service is still running.
What should I do? Is there something wrong with how I create the notification?
Should I check when the service runs if the notification is displayed and if not recreate it?
Thanks

Android notification not showing

This is the weirdest thing I ever met in Android development. I want to show a simple notification from a service, the notification is successfully shown when I run it on a virtual device in android studio, but when I run it on my own phone the notification doesn't show at all.
Notification shows on AVD test
I make sure that the notification is allowed on my phone, I can even see the channel information
on the notification settings page, which means the channel is successfully built, but the notification just does not show.
Channel information
No notification on phone test
The following is my code:
public int onStartCommand(final Intent intent, int flags, int startId) {
createNotificationChannel();
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentTitle("test")
.setContentText("test")
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentIntent(pendingIntent)
.setAutoCancel(false);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(001, builder.build());
return super.onStartCommand(intent, flags, startId);
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
channel.setShowBadge(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
By the way, the AVD I used is in API level 29 and my phone is a Huawei phone on HarmonyOS 2.0 but still API level 29.

Android 11 - Foreground service notification isn't visible

I have an android app that makes use of Foreground Services. My foreground service is supposed to display a notification.
I have updated one of my devices to Android 11 and the foreground service's notification is not being displayed. The foreground notification works as expected and is visible on all previous versions.
My code for starting a foreground service with a notification is as follows:
String channelName = "MyChannel";
NotificationChannel chan = new NotificationChannel("com.my.package", channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.createNotificationChannel(chan);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.my_layout);
remoteViews.setImageViewResource(R.id.my_notification_id, R.drawable.my_icon);
remoteViews.setTextViewText(R.id.my_title, "Title");
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, "com.my.package");
notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_image_icon)
.setContentTitle("My Title")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.setStyle(new android.support.v4.media.app.NotificationCompat.DecoratedMediaCustomViewStyle()
.setMediaSession(new MediaSessionCompat(context, MY_TAG).getSessionToken()))
.setColor(0x169AB9)
.setWhen(System.currentTimeMillis())
.setOnlyAlertOnce(true)
.setColorized(true);
PendingIntent contentIntent = PendingIntent.getActivity(context, MYMConstants.NOTIFICATION_GO_TO_ACTIVITY_REQUEST_CODE,
new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContent(remoteViews);
notificationBuilder.setContentIntent(contentIntent);
Notification notification = notificationBuilder.build();
startForeground(10000, notification);
The foreground service is started as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(serviceIntent);
} else {
context.startService(serviceIntent);
}
I searched for the official documentation on Android 11 and underlying changes to Foreground services, but I couldn't find anything. Could someone help me out with this?
Nothing has changed the way how notifications are added to Foreground Service as part of Android 11.
I did find where the problem lies though. This piece of code above was causing the problem.
.setStyle(new android.support.v4.media.app.NotificationCompat.DecoratedMediaCustomViewStyle()
.setMediaSession(new MediaSessionCompat(context, MY_TAG).getSessionToken()))
Removing this fixed the issue.
To utilize setStyle(), we need to replace android.support.v4.media.app by androidx.media.app.

Detect when app is killed from recent apps list in android O and P

Use case is I have to send logout request to server when app get killed from recent lists. I use onTaskRemoved to handle that however in Android O and P I get notification bar saying "app is running" that I want to avoid. Here is how I run foreground service:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
channelId = "my_service_channel_id";
String channelName = "My Foreground Service";
NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setSound(null, null);
notificationManager.createNotificationChannel(channel);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, channelId)
.setContentTitle("")
.setAutoCancel(true)
.setContentText("");
startForeground(NOTIFY_ID, builder.build());
//notificationManager.cancel(NOTIFY_ID); // It doesn't remove notification
//notificationManager.deleteNotificationChannel(channelId); // it causes crash
}
I already tried JobScheduler but onTaskRemoved doesn't get trigger. Any helps would be appreciated.

Android foreground service notification not showing

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.
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.
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);
}
For me everything was set correctly (also added FOREGROUND_SERVICE permission to manifest),
but I just needed to uninstall the app and reinstall it.
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!!!
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
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"
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.
In my case, it was caused by me using IntentService.
In short, if you want a foreground service then subclass Service.

Categories

Resources