Am trying to create a notification that will notify user when alarm matures, am calling the Notification code in my OnCreate method, so i expect to see it when i launch my Activity but my code here seems to have a problem, any help to get the App to notify will greatly be appreciated...
Here is what i got so far
class SecondActivity : AppCompatActivity
{
static readonly int mid = 1000;
static readonly string CHANNEL_ID = "location_notification";
protected override void OnCreate(Bundle onSavedInstanceState){
//Notification code
NotificationChannel channel = null;
Intent intent=new Intent(this, typeof(SecondActivity));
//Construct TaskStack builder for pending intent
Android.App.TaskStackBuilder taskStackBuilder = Android.App.TaskStackBuilder.Create(this);
//Add intent to backstack
taskStackBuilder.AddNextIntentWithParentStack(intent);
//Construct pending intent to open desired activity
PendingIntent pendingIntent = taskStackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
//Enque notification to inform the user that the alarm has matured
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.SetSmallIcon(Resource.Drawable.abc_tab_indicator_mtrl_alpha)
.SetContentTitle("Alarm")
.SetContentIntent(pendingIntent);
.SetContentText("Alarm Time has matured");
NotificationManager notificationManager =
(NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(mid, mBuilder.Build());
channel = notificationManager.GetNotificationChannel(channelName);
notificationManager.CreateNotificationChannel(channel);
}
}
What Am i doing wrong?, Thanks
am calling the Notification code in my OnCreate method
You could not call notification on OnCreate method directly. Generaly We will use button click event or another separated task event to call Notification.
Second, as SushiHangover's said, you need to CreateNotificationChannel before publish
local notification.
You can refer to Notification channels to add notification channel:
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var channelName = Resources.GetString(Resource.String.channel_name);
var channelDescription = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID, channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager) GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
And pulish notification:
// Instantiate the builder and set notification elements:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetContentTitle ("Sample Notification")
.SetContentText ("Hello World! This is my first notification!")
.SetSmallIcon (Resource.Drawable.ic_notification);
// Build the notification:
Notification notification = builder.Build();
// Get the notification manager:
NotificationManager notificationManager =
GetSystemService (Context.NotificationService) as NotificationManager;
// Publish the notification:
const int notificationId = 0;
notificationManager.Notify (notificationId, notification);
Note: The CHANNEL_ID should be the same both on creating channel and publishing notification. Generally, we will use the package name as the channel id.
The full sample code as follows:
private void Button_Click(object sender, EventArgs e)
{
// create notification channel
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var channelName = "Notify user";
var channelDescription = "first local notification";
var channel = new NotificationChannel("com.companyname.appandroidlistview", channelName, NotificationImportance.Default)
{
Description = channelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "com.companyname.appandroidlistview")
.SetContentTitle("Sample Notification")
.SetContentText("Hello World! This is my first notification!")
.SetSmallIcon(Resource.Drawable.icon);
// Build the notification:
Notification notification = builder.Build();
// Get the notification manager:
NotificationManager notificationManager =
GetSystemService(Context.NotificationService) as NotificationManager;
// Publish the notification:
const int notificationId = 0;
notificationManager.Notify(notificationId, notification);
}
You need to do a lot of things before your notification can work, Microsoft documentation provides a very easy way of doing that...
class SecondActivity : AppCompatActivity
{
//Declare notification ID and Channel ID In your class so you can use them from any method
static readonly int NOTIFICATION_ID = 1000;
static readonly string CHANNEL_ID = "location_notification";
protected override void OnCreate(Bundle savedInstanceState){
}
//Define the method you will use to call notification
}
void createNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var name = Resources.GetString(Resource.String.channel_name);
var description = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID, name, NotificationImportance.Default)
{
Description = description
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
//Use a button to send the notification to the operating system
private void notifier(object sender, EventArgs e){
Intent intent=new Intent(this, typeof(SecondActivity));
//Construct TaskStack builder for pending intent
Android.App.TaskStackBuilder taskStackBuilder = Android.App.TaskStackBuilder.Create(this);
//Add intent to backstack
taskStackBuilder.AddNextIntentWithParentStack(intent);
//Construct pending intent to open desired activity
PendingIntent pendingIntent = taskStackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
//Enque notification to inform the user that the alarm has matured
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.abc_tab_indicator_mtrl_alpha)
.SetContentTitle("Alarm")
.SetContentText("Alarm Time has matured")
.SetShowWhen(false).SetContentIntent(pendingIntent);
NotificationManagerCompat notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(NOTIFICATION_ID, mBuilder.Build());
}
}
}
If you follow the instructions on this page then your notification should show without so much hassle
https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/notifications/local-notifications-walkthrough
Related
I have a problem with notifications where the notification doesn't appear on my xiaomi and samsung devices but works for the other device. I've tried what people recommend like trying auto start, managing battery settings, but it still doesn't appear on both devices. I also tried to use the notify library but the results were the same. Strangely, when I checked the notification setting and then clicked on the application, it appeared as shown below
samsung
This is my notification code :
public void showNotification() {
String appname = "App Name";
String title = "Notification Title";
String text = "This is the notification text";
String iconUrl = "http://url.to.image.com/image.png";
NotificationManager notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
TaskStackBuilder stackBuilder = TaskStackBuilder.from(MainActivity.this);
stackBuilder.addParentStack(NewsActivity.class);
stackBuilder.addNextIntent(new Intent(MainActivity.this, NewsActivity.class));
PendingIntent pendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
builder.setContentTitle(title).setContentInfo(appname).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo_wanda_flp)).setContentText(text).setContentIntent(pendingIntent);
builder.setSmallIcon(R.drawable.logo_wanda_flp);
notifyManager.notify("textid", 123, builder.getNotification());
}
The code won't work on Android 8 (API 26) and above without first registering a notification channel. On Android before that, it will work just fine.
Some of the code snippets below are taken from here.
Creating a notification channel
Register notification channels inside your activity before attempting to show any notification. Alternatively, you can register them inside a custom Application class before any activities or services start (but this won't be shown here for the sake of simplicity).
#Override
public void onCreate(Bundle savedInstanceState) {
createNotificationChannel(); // Registering a notification channel
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
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_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}
Deliver the notification
public void showNotification() {
// ...
// NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
// Replace with line below.
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, CHANNEL_ID);
// ...
}
This question already has answers here:
Notification not showing in Oreo
(24 answers)
Closed 4 years ago.
I try to receive notification in android Oreo. But App does not receive any
notification. I also create notification Chanel but it's not work
If I send a notification from fcm then app received. but using the token app not received any notification. In other lower, version notification work proper. In Oreo it does not work.
Here is my MyFirebaseMessagingService class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static int NOTIFICATION_ID = 1;
public static final String NOTIF_CHANNEL_ID = "my_channel_01";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(remoteMessage.getData());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotifChannel(this);
}
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void createNotifChannel(MyFirebaseMessagingService
myFirebaseMessagingService)
{
NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID,
"MyApp events", NotificationManager.IMPORTANCE_LOW);
// Configure the notification channel
channel.setDescription("MyApp event controls");
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = getApplicationContext().
getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
Log.d(TAG, "createNotifChannel: created=" + NOTIF_CHANNEL_ID);
}
private void sendNotification(Map<String, String> data) {
int num = ++NOTIFICATION_ID;
Bundle msg = new Bundle();
for (String key : data.keySet()) {
Log.e(key, data.get(key));
msg.putString(key, data.get(key));
}
Intent intent = new Intent(this, HomeActivity.class);
if (msg.containsKey("action")) {
intent.putExtra("action", msg.getString("action"));
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, num /*
Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri =
RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new
NotificationCompat.Builder(this)
.setSmallIcon(instauser.application.apps.R.drawable.icon)
.setContentTitle(msg.getString("title"))
.setContentText(msg.getString("msg"))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(num, notificationBuilder.build());
}
}
I also create a notification channel but it's not work
You created notification channel, but didn't set it to notification
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
...
.setChannelId(NOTIF_CHANNEL_ID)
Step1 : Build Notification with Reply intent and heads up notification
private void buildInlineReplyNotification() {
// Create an instance of RemoteInput.Builder that you can add to your notification action.
// This class's constructor accepts a string that the system uses as the key for the text input.
// Later, your handheld app uses that key to retrieve the text of the input.
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY).setLabel(
getResources().getString(R.string.reply_label)).build();
// Attach the RemoteInput object to an action using addRemoteInput().
NotificationCompat.Action compatAction =
new NotificationCompat.Action.Builder(R.mipmap.ic_reply,
getResources().getString(R.string.reply), replyPendingIntent).addRemoteInput(
remoteInput).setAllowGeneratedReplies(true).build();
// Build the notification and add the action.
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this).setSmallIcon(R.mipmap.ic_notification)
.setContentTitle(
getResources().getString(R.string.notification_created) + mNotificationId)
.setContentText(getResources().getString(R.string.type_reply))
.setShowWhen(true)
.addAction(compatAction);
mBuilder.setPriority(Notification.PRIORITY_HIGH).setVibrate(new long[0]);
// Issue the notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(mNotificationId, mBuilder.build());
}
Step2 : cancel after reply from notification
private void updateNotification(Context context, int notifyId) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(context).setSmallIcon(R.mipmap.ic_notification)
.setContentText(context.getString(R.string.message_sent));
notificationManager.cancel(notifyId);
}
Issues is not cancel notification by notificationManager.cancel(notifyId) but if i remove this mBuilder.setPriority(Notification.PRIORITY_HIGH).setVibrate(new long[0]); Than work perfect so, what is issue with priority in notification ?
I want to know that how can I change the notification bar small icon in android Oreo (API 26). It has round white icon showing in the notification bar. How can I change it? Manifest file default notification icon set as below.
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_status" />
See the image below
There is a bug in Firebase SDK 11.8.0 on Android 8.0 (API 26), which causes the display of a white version of the app's launcher icon in the status bar instead of the notification icon.
Some people have fixed it by overriding the Application class's getResources() method.
Another way that worked for me was to use an HTTP POST request to send the notification as a data message:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{
"to": "/topics/test",
"data": {
"title": "Update",
"body": "New feature available"
}
}
And then subclass FirebaseMessagingService to display the notification programmatically:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Intent i = new Intent(context, HomeActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, i,
PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, GENERAL_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_stat_chameleon)
.setContentTitle(remoteMessage.getData().get("title"))
.setContentText(remoteMessage.getData().get("body"))
.setContentIntent(pi);
NotificationManager manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
}
In the end, I got this, even on Android 8.0:
Remove <meta-data> tag from AndroidManifest.xml.
Notification Builder has .setSmallIcon(int icon, int level) which accepts icon as a compulsory argument & level parameter as an optional argument.
NOTE: .setSmallIcon accepts drawables & DOES NOT accept mipmaps.
This is how it should be according to Android 8.0 Oreo Notification Channels & behaviour changes:
public class MainActivity extends AppCompatActivity {
private CharSequence name;
private int notifyId;
private int importance;
private String id;
private String description;
private Notification mNotification;
private NotificationManager mNotificationManager;
private NotificationChannel mChannel;
private PendingIntent mPendingIntent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.btnNotification.setOnClickListener(v -> notification());
}
private void notification() {
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifyId = 1;
description = "Hello World, welcome to Android Oreo!";
Intent intent = new Intent(this, MainActivity.class);
mPendingIntent = PendingIntent.getActivity(this, notifyId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (SDK_INT >= O) {
id = "id";
name = "a";
importance = NotificationManager.IMPORTANCE_HIGH;
mChannel = new NotificationChannel(id, name, importance);
mChannel.setDescription(description);
mChannel.enableLights(true);
mChannel.setLightColor(Color.WHITE);
mChannel.enableVibration(true);
mChannel.setVibrationPattern(new long[] {100, 300, 200, 300});
mNotificationManager.createNotificationChannel(mChannel);
mNotification = new Notification.Builder(MainActivity.this, id)
.setContentTitle(id)
.setContentText(description)
.setContentIntent(mPendingIntent)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.build();
} else {
mNotification = new Notification.Builder(MainActivity.this)
.setContentTitle(id)
.setContentText(description)
.setContentIntent(mPendingIntent)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setLights(Color.WHITE, Color.RED, Color.GREEN)
.setVibrate(new long[] {100, 300, 200, 300})
.build();
}
mNotificationManager.notify(notifyId, mNotification);
}
}
I would like to update notification data, but the only way I found is to launch a new one with the same Id.
The problem is that I don't want to raise a new one if the original has beed canceled.
Is there a way to tell if a notification is visible or canceled? Or a way to update a notification only if it exists?
If you're app has a minimum API >= 23 can use this method to get active notification:
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
StatusBarNotification[] notifications = mNotificationManager.getActiveNotifications();
for (StatusBarNotification notification : notifications) {
if (notification.getId() == 100) {
// Do something.
}
}
This is how I solved it:
private boolean isNotificationVisible() {
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent test = PendingIntent.getActivity(context, MY_ID, notificationIntent, PendingIntent.FLAG_NO_CREATE);
return test != null;
}
This is how I generate the notification:
/**
* Issues a notification to inform the user that server has sent a message.
*/
private void generateNotification(String text) {
int icon = R.drawable.notifiaction_icon;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, text, when);
String title = context.getString(R.string.app_name);
Intent notificationIntent = new Intent(context, MainActivity.class);
// set intent so it does not start a new activity
//notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(context, MY_ID, notificationIntent, 0);
notification.setLatestEventInfo(context, title, text, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL; //PendingIntent.FLAG_ONE_SHOT
notificationManager.notify(MY_ID, notification);
}
I think you can use deleteIntent of Notification class.
I remember in one of my application I use use to fire a Broadcast (custom Broadcast) when a notification is cancelled or the Notification tray was cleared.
You can check as follow in Kotlin:
val mNotificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val notifications: Array<StatusBarNotification> = mNotificationManager.activeNotifications
if(notifications.isNotEmpty())
{
//you don't have notifications
}
else
{
//you have notifications
}
An alternative to the deleteIntent is the following which has proved beneficial in my own app:
Basically, you create an intent with your notification that starts an IntentService (or any other service) and in onHandleIntent you can set a flag indicating whether the notification is active.
You can set this intent to be fired when the user taps the notification (contentIntent) and/or when the user clears it from the list (deleteIntent).
To illustrate it, here is what I do in my own app. When building the notification I set
Intent intent = new Intent(this, CleanupIntentService.class);
Notification n = NotificationCompat.Builder(context).setContentIntent(
PendingIntent.getActivity(this, 0, intent, 0)).build();
When the notification is tapped, my CleanupIntentService is launched, setting a flag (in the service that created the notification):
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onCreate(); // If removed, onHandleIntent is not called
return super.onStartCommand(intent, flags, startId);
}
#Override
protected void onHandleIntent(Intent intent) {
OtherService.setNotificationFlag(false);
}
In my situation, I wanted to check if a Notification was already shown before showing another. And it turns out there's a simple way to do it without listening to when the Notification was deleted or dismissed with .setAutoCancel(true) on NotificationManagerCompat.Builder.
private val NOTIF_ID = 80085
private val CHANNEL_ID = "com.package.name.ClassName.WhatNotifycationDoes"
private lateinit var mNotificationManagerCompat: NotificationManagerCompat
private lateinit var mNotificationManager: NotificationManager // this is for creating Notification Channel in newer APIs
override fun onCreate() {
super.onCreate()
mNotificationManagerCompat = NotificationManagerCompat.from(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
mNotificationManager = getSystemService(NotificationManager::class.java)
showNotification()
startWatching()
}
private fun showNotification() {
val contentIntent = Intent(this, MainActivity::class.java)
.apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK }
val contentPendingIntent = PendingIntent.getActivity(this, 1, contentIntent, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = getString(R.string.app_name)
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(CHANNEL_ID, name, importance)
channel.description = getString(R.string.your_custom_description)
mNotificationManager.createNotificationChannel(channel)
}
val mNewStatusNotificationBuilder = NotificationCompat.from(this)
mNewStatusNotificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle(getString(R.string.app_name))
.setContentText(getString(R.string.simple_text))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(contentPendingIntent)
.setAutoCancel(true) // This dismisses the Notification when it is clicked
.setOnlyAlertOnce(true) //this is very important, it pops up the notification only once. Subsequent notify updates are muted. unless it is loaded again
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP)
mNewStatusNotificationBuilder.setSmallIcon(R.drawable.ic_notification)
notification = mNewStatusNotificationBuilder.build()
mNotificationManagerCompat.notify(NOTIF_ID, notification)
}