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.
Related
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)
}
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
I have an calendar app where the info is downloaded online and there is a recyclerView of events and I want to notify the user when there is a calendar event for today, and notify with the event name or names. I have done some googling but haven't been able to figure this out.
In my MainActivity.java this is the method I created as a test from a page online
private void addNotification() {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.drawable.ic_check);
mBuilder.setContentTitle("Notification Alert, Click Me!");
mBuilder.setContentText("Hi, This is Android Notification Detail!");
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(contentIntent);
// Add as notification
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, mBuilder.build());
}
But when I call this method nothing is happening, what am I doing wrong?
I think you are missing the channel of the notification
I have a different solution, try this one (I checked it on my phone)
calling the function:
showSmallNotification(R.drawable.ic_launcher_background, "title","message");
Function code
private void showSmallNotification( int icon, String title, String message){
String CHANNEL_ID = "Channel_01";
String CHANNEL_NAME = "Notification";
// I removed one of the semi-colons in the next line of code
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// I would suggest that you use IMPORTANCE_DEFAULT instead of IMPORTANCE_HIGH
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
channel.enableVibration(true);
channel.setLightColor(Color.BLUE);
channel.enableLights(true);
//channel.canShowBadge();
// Did you mean to set the property to enable Show Badge?
channel.setShowBadge(true);
notificationManager.createNotificationChannel(channel);
}
Intent mainIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, mainIntent, 0);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
.setVibrate(new long[]{0, 100})
.setPriority(Notification.PRIORITY_MAX)
.setLights(Color.BLUE, 3000, 3000)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setStyle(inboxStyle)
.setContentText(message);
// Don't forget to set the ChannelID!!
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
notificationBuilder.setChannelId(CHANNEL_ID);
}
notificationManager.notify(CHANNEL_ID, 1, notificationBuilder.build());
}
Edit
In order to check if there are any events every day you will need to use AlarmManager as from it's name you can schedule an event every day
You can see a solution (or at least it will give a direction) once you did that I think the next step would be to send the intent to a service which will check if there are any events available in current day. If there are any just show the notification/s
alarm manager link
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(context, AlertDialog.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); // added new line
intent.putExtra("STARTED_BY_RECEIVER", true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
String CHANNEL_ID = "channel id";// The id of the channel.
CharSequence name = "Channel";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
Notification notification = new Notification.Builder(context)
.setContentIntent(pendingIntent)
.setContentText("Some Text")
.setContentTitle("Notification")
.setAutoCancel(true)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification_praying)
.setChannelId(CHANNEL_ID)
.build();
notificationManager.createNotificationChannel(mChannel);
notificationManager.notify(100 , notification);
} else {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(context, AlertDialog.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); // added new line
intent.putExtra("STARTED_BY_RECEIVER", true);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = (NotificationCompat.Builder) new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_notification_praying)
.setContentIntent(pendingIntent)
.setContentText("Some Text")
.setContentTitle("Notification")
.setAutoCancel(true)
.setOngoing(true);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(alarmSound);
notificationManager.notify(100, builder.build());
}
}
I've made an application which show notification on time that user chose in main activity and Notification should disappear only when user tap on notification otherwise not..and it was working fine unless I've updated my phone to android Oreo (8.0) now notification show at time but auto disappear after sometime.. How to make notification not auto disappear (in android Oreo) but only when user tap on it?
alright I figure this out.. it was battery optimize option which was killing my application so that's why notification was disappearing.. I removed my application from auto optimize now it's working fine.
I have a FireBase Message. If it comes in, I show a Notification (works). When I click on the Notification it should open my application (works). Now I want to use putExtra(), to hand over some information to my app (that works only sometimes - if the app is in the foreground). That's my problem.
private void sendMyNotification(String message) {
int rndNo4Intent = Math.round((float)(Math.random()*100000000));
int rndNo4Msg = Math.round((float)(Math.random()*100000000));
//On click of notification it redirect to this Activity
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("action","openWiki"+rndNo4Msg); // My Test-Data
PendingIntent pendingIntent = PendingIntent.getActivity(this, rndNo4Intent , intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
String channelId = getString(R.string.default_notification_channel_id);
Uri soundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("CodingSpace")
.setContentText(message)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent);
// Since android Oreo notification channel is needed. Sonst kommt nichts an.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"CodingSpaceChannel",
NotificationManager.IMPORTANCE_HIGH); // in Oreo ist High so, dass es einen Ton gibt
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(rndNo4Msg, notificationBuilder.build());
}
In the .MainActivity-Class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Intent iin= getIntent();
String msg = iin.getStringExtra("action");
Toast.makeText(MainActivity.this,"get: "+ msg,Toast.LENGTH_SHORT).show();