Two Toast notifications for same app, at the same time. How is it prioritized and handled by the device? - c#

I have an app which can(possibly) show two toast notifications to the user one after the other. I observed that if such scenario arises then only one of the two notifications is displayed to the user but once the user launches the app and then same notifications are presented to the user in message boxes and if he clicks "cancel" for the first message and then the next notification is presented. So, my doubt now is, If two toast notifications are there then how will the device handle it? and which of the two is displayed to the user? And in case only notification is presented to the user (by default behaviour of the device) then is there a way to display notifications one after the other?
This is similar to this QUESTION but i want to know the behaviour of WP7 phones as the features of WP7 very different other smartphone OSes.
All suggestions, comments and answers are appreciated.
Thank You

Windows Phone 7 has the potential to show both the messages, and which one first depends on which one the phone receives first.
If you look at the diagram on this page http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff402558(v=vs.92).aspx you see that there is a lot of communication in sending a push (toast, tile or raw) notification. And it depends on the Microsoft Push Notification Service which normally sends it first come first serve.
So from the sounds of it, I would look into trying to limit how your application sends the toast notifications. So check if a toast notification has been sent to the phone within a certain amount of time, if so hold of on sending the next one in till that time has past.
Also remember to check if the MPNS actually sent the push notification to the, that will help in determining if the phone might have received the notification
In that link I post it goes into a lot of details about sending and receiving the push notifications.

What I did is this,
public static void ShowToast()
{
try
{
string langKey = CacheManager.getInstance().getDataFromConfigFile(CacheManager.APP_CURRENT_LANGUAGE);
string flag = CacheManager.getInstance().getDataFromConfigFile(CacheManager.APP_UPGRADE_STATUS);
string catalogUpdateFlag = CacheManager.getInstance().getDataFromConfigFile(CacheManager.APP_CATALOG_UPGRADE_STATUS);
CultureInfo ci;
if ((null == langKey) || (langKey.Equals(Utils.LANGUAGE_EN)))
{
ci = new CultureInfo("en-US");
}
else
{
ci = new CultureInfo("fr-FR");
}
AppResources.Culture = ci;
if (!Utils.isNullString(flag))
{
var toast = new ShellToast
{
Title = AppResources.APP_NAME,
Content = getMessageStatus(flag),
NavigationUri = new System.Uri("/MainPage.xaml", System.UriKind.Relative)
};
Logger.log(TAG, ":ShowToast():MessageToUser" + AppResources.APP_NAME + getMessageStatus(flag));
toast.Show();
}
if (!Utils.isNullString(catalogUpdateFlag))
{
var toast = new ShellToast
{
Title = AppResources.APP_NAME,
Content = getMessageStatus(catalogUpdateFlag),
NavigationUri = new System.Uri("/MainPage.xaml", System.UriKind.Relative)
};
Logger.log(TAG, ":ShowToast():MessageToUser" + AppResources.APP_NAME + getMessageStatus(catalogUpdateFlag));
toast.Show();
}
}
catch (Exception ex)
{
Logger.log(TAG, "Exception in ShowToast: " + ex.Message + "\n" + ex.StackTrace);
}
}
private static string getMessageStatus(string flagType)
{
//string flag = CacheManager.getInstance().getApplicationSettings(CacheManager.APP_UPGRADE_STATUS);
string flag = CacheManager.getInstance().getDataFromConfigFile(CacheManager.APP_UPGRADE_STATUS);
string catalogUpdateFlag = CacheManager.getInstance().getDataFromConfigFile(CacheManager.APP_CATALOG_UPGRADE_STATUS);
if (flagType == flag)
{
if (flag.Equals(CacheManager.MAJOR_UPGRADE))
{
return AppResources.APP_UPGRADE_CONFIRM;
}
else if (flag.Equals(CacheManager.MINOR_UPGRADE))
{
return AppResources.APP_UPGRADE_MINOR_CONFIRM;
}
}
else if (flagType == catalogUpdateFlag)
{
return AppResources.APP_CATALOG_CONFIRM;
}
return "";
}
I have taken two different variables to know if its the application upgrade or just the catalogue upgrade(New items will be added to the existing ones). So if there is catalogue upgrade and/or application upgrade user will be notified.

Related

Desktop application in C# shows notifications only a few times in Windows 10

So, I made an app in C# that sends a custom toast notification made from the arguments provided. And it works fine in windows 11, and in windows 10 only in my system.
For other users, the notification appears only sometimes, and sometimes it does not appear at all or appears after a long time in the action centre.
Here is the repo for the app:
https://github.com/deathcrafter/Raintoaster
I have tried different versions of .NET Frameworks, including 4.6.1(lowest) and 4.8. Everything seems to work fine for my Windows 10 pc, and users who have Windows 11 insider build running on their pc. But not for other Windows 10 devices.
Can anyone point out to what I am doing wrong, or what may be causing this.
P.S.: I have recently downgraded from Windows 11 to Windows 10 with a clean install, which may be the reason it's working for me.
Thanks in advance,
death.crafter
Extract from the code:
public static void Main(string[] args)
{
// Check if app was activated from toast
bool m = ToastNotificationManagerCompat.WasCurrentProcessToastActivated();
if (!m)
{
// Parse arguments and create toast
ParseArguments(args);
}
else
{
bool done = false;
Process rainmeter = new Process();
// Listen to notification activation
ToastNotificationManagerCompat.OnActivated += toastArgs =>
{
// Obtain the arguments from the notification
ToastArguments ar = ToastArguments.Parse(toastArgs.Argument);
// Obtain any user input (text boxes, menu selections) from the notification
ValueSet userInput = toastArgs.UserInput;
string[] programArgs = ar["arguments"].Split(new string[] { "|" }, 2, StringSplitOptions.RemoveEmptyEntries);
rainmeter.StartInfo.FileName = programArgs[0];
foreach (KeyValuePair<string, object> pair in userInput)
{
string arg = pair.Value.ToString();
programArgs[1] = programArgs[1].Replace("$" + pair.Key + "$", arg.Replace("\r", "\n"));
programArgs[1] = programArgs[1].Replace("$" + pair.Key + ":CRLF$", arg.Replace("\r", "#CRLF#"));
}
rainmeter.StartInfo.Arguments = programArgs[1];
try
{
rainmeter.Start();
done = true;
}
catch (SystemException exec)
{
MessageBox.Show("Couldn't start program. Error: " + exec);
done = true;
}
};
// Keep the app running until OnActivated event is raised and is completed
while (!done)
Thread.Sleep(100);
}
}

How to create minimized ongoing notification like USB connection or google weather

I'm developing a Xamarin.Android application that uses a Foreground Service to track user's location after certain time/distance.
To keep the service running I have an ongoing notification with Low priority as well as the notification channel with low priority too. I've tried all kind of combinations (low and min priorities and content texts).
NotificationChannel code:
private NotificationChannel CreateNotificationChannel(string channelId)
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return null;
}
string channelName = Resources.GetString(Resource.String.notification_channel_name);
string channelDesc = Resources.GetString(Resource.String.notification_channel_desc);
NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, NotificationImportance.Default)
{
Description = channelDesc
};
switch(channelId)
{
case UPDATES_NOTIFICATION_CHANNEL_ID:
notificationChannel.Importance = NotificationImportance.High;
break;
case ONGOING_NOTIFICATION_CHANNEL_ID:
notificationChannel.Importance = NotificationImportance.Low;
break;
default:
break;
}
var notifManager = (NotificationManager)GetSystemService(NotificationService);
notifManager.CreateNotificationChannel(notificationChannel);
return notificationChannel;
}
Notification code:
private Notification CreateOngoingNotification()
{
Intent notificationIntent = new Intent(this, typeof(MainActivity));
PendingIntent pendingIntent =
PendingIntent.GetActivity(this, 0, notificationIntent, 0);
string content = "The application is fetching your location every " + MIN_TIME / (60 * 1000) + " minutes if you moved at least " + MIN_DISTANCE + " meters.";
NotificationCompat.Builder builder;
if (Build.VERSION.SdkInt < BuildVersionCodes.O) builder = new NotificationCompat.Builder(this);
else builder = new NotificationCompat.Builder(this, m_ongoingNotificationChannel.Id);
builder
.SetContentTitle("Persistent notification")
.SetStyle(new NotificationCompat.BigTextStyle().BigText(content))
.SetSmallIcon(Resource.Drawable.ic_notification)
.SetContentIntent(pendingIntent)
.SetGroup("persistent")
.SetOngoing(true)
.SetVisibility((int)NotificationVisibility.Private)
.SetPriority((int)NotificationPriority.Low);
Notification notification = builder.Build();
return notification;
}
Having the following image in mind, what I'm trying to acomplish is the style of the notifications from LinkedIn app, the Google Weather one (bottom), and the other one (3rd one starting from the end).
All I can get is the one with "Persistent notification" in the title.
Any kind of help will be welcome!
EDIT: made clear that I'm using Xamarin, not Java
If I am not wrong and you are looking for an expandable notification
A basic notification usually includes a title, a line of text, and one or more actions the user can perform in response. To provide even more information, you can also create large, expandable notifications by applying one of several notification templates.
Now if you read the documents carefully it has all the different types of expandable notifications,
The one you are looking for is either the Add a large block of text or the Create an inbox-style notification
Both codes available on the documentation are easily convertible to C# i.e. Xamarin.Android
In case you face issues or have queries feel free to revert
Goodluck

In mvc application how can I show message one by one like notification?

I have an MVC application and I'm registering a device to IOT using a foreach loop.
I want to show messages one by one when one device is done with registration. How can I show the messages on the view?
Code in the controller method -
foreach (var deviceId in collection)
{
try
{
// save device information into database
Models.Device newDevice = new Models.Device()
{
Id = Guid.NewGuid(),
Device = deviceId
};
_deviceRepository.InsertDevice(newDevice);
_deviceRepository.Save();
}
catch (DeviceAlreadyExistsException)
{
device = await registryManager.GetDeviceAsync(deviceId);
ViewBag.Message = "device already present";
}
}
}
catch (Exception ex)
{
ViewBag.Message = "Error";
throw ex;
}
ViewBag.Message = "device register successfully - " + deviceId;
return View("Index")
How can I show ViewBag.Message one by one on view or partial view ?
If an error occurs it will display an error message.
If success then one by one like notification we have to show messagesuccess message.
For example I have 10 items then the foreach will run 10 times, after every device success we need to show a message on the UI:
device register successfully device1
device register successfully device2 and so on ...
I know ViewBag won't be useful, what approach can I take?
I think you would need to take a different approach for this behaviour.
Look into using signalR so you can communicate with the client side view whilst a server side operation is taking place.
You could use this to show a progression loading bar, or give feedback ever time a device has registered.

Redirect to a different aspx page and run the next code in background (.NET 4.5.2)

I am working on an ASP.NET Webform project (legacy code).On my button_click event i am sending sms message to all the datas populated in this.
var customerSMS = BusinessLayer.SMS.SmsSetup.GetAllCustomerSMS(OfficeId);
This takes around 15seconds to do all the computing and get the data(1000rows)
from the Db.And for each data it runs through the loop and does validation and
sends the sms and it does take time.I want to do this task in background and
redirect the user to the index page and the background process continues till it
gets out of the loop.I am new to this and still learning this beautiful
language C#.I did go through this amazing Asynchronous Programming async/await
and Multithreading approach and got hold of it only in simple WindowsForm
applications.Any reference/code snippet/best approach with a simple explanation for my case would be helpful.
My button click event code :
protected void ReturntoDashboard_Click(object sender, EventArgs e)
{
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
if (sms.EnableSmsData && sms.SmsCount > 0)
{
#region Loan Section
var smsLoan = Everest.Net.BusinessLayer.SMS.SmsSetup.GetLoanId(s.Sms_AccountNumber);
var loanId =
BusinessLayer.SMS.SmsSetup.GetLoanIdValue(s.Sms_AccountNumber);
var dateexceeded =
BusinessLayer.SMS.SmsSetup.IsDateExceeded(loanId);
if (smsLoan != null && dateexceeded == true)
{
foreach (Common.SMS.SMSSetup sm in smsLoan)
{
var smsClosingBalanceLoan = BusinessLayer.SMS.SmsSetup.GetAmountForLoanAlert( sm.LoanId,
BusinessLayer.Core.DateConversion
.GetCurrentServerDate()
.AddDays(sms.DaysbeforeLoanalerts).ToString());
if (smsClosingBalanceLoan != null)
{
if (smsClosingBalanceLoan.LoanAmountToPay > 0)
{
int smsSentAlertCount = sms.LoanAlertCount;
var logCount = BusinessLayer.SMS.SmsSetup.GetLoanSmsAlertSentCount(DateTime.Now.AddDays(-smsSentAlertCount).ToString("yyyy-MM-dd"), DateTime.Now.ToString("yyyy-MM-dd"), sm.LoanAccountNumber);
if (logCount < smsSentAlertCount)
{
smsLog = new Everest.Net.Common.SMS.SMSSetup();
finalMessage = "Dear Member, Your Loan accnt " + sm.LoanAccountNumber + " with Principal"+ "+" + "Int Amnt: Rs." + smsClosingBalanceLoan.LoanAmountToPay + " need to be payed.Thank You," + officeName.OfficeName;
smsLog.LogServiceType = "Loan";
smsLog.LogSmsType = s.Sms_SmsType;
smsLog.LogSmsMessage = finalMessage;
smsLog.LogCustomerId = s.CustomerId.ToString();
smsLog.LogAccountNumber = s.Sms_AccountNumber;
smsLog.LogAccountType = s.Sms_AccountType;
smsLog.LogSmsSentDate = BusinessLayer.Core.DateConversion.GetCurrentServerDate();
smsLog.LogSmsFailedDate = "";
smsLog.LogSentStatus = true;
smsLog.LogUserId = UserId;
smsLog.LogSmsFailedMessage = "";
try
{
var result = Everest.Net.BusinessLayer.SMS.smsParameters.SendSMS(sms.FromNum, sms.Token, sms.Url, cellNum, finalMessage);
}
catch (Exception ex)
{
smsLog.LogSmsFailedDate = System.DateTime.Now.ToString("MM/dd/yyyy HHmmss");
smsLog.LogSentStatus = false;
smsLog.LogSmsFailedMessage = ex.Message;
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
sms.SmsCount = sms.SmsCount - 1;
Everest.Net.BusinessLayer.SMS.SmsSetup.UpdateSmsSetup(sms);
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
}
}
}
}
}
}
}
catch (Exception ex)
The ideal solution would remove the responsibility of sending the SMS from the web application itself. Instead, the web application should create a database record containing the message and recipient addresses, and a separate background job (e.g. a Windows Service) should poll the database and send SMS messages when neeeded. This is the best solution in terms of fault tolerance and auditability, because there is a permanent record of the messaging job which can be resumed if the system fails.
That being said, maybe you don't want to go to all that trouble. If you feel strongly that you wish to send the SMS directly from the ASP.NET application, you will need to create a Task and queue it to run using QueueBackgroundWorkitem. You will need to refactor your code a bit.
Move all the logic for sending the SMS into a separate function that accepts all the information needed as parameters. For example,
static void SendSMS(string[] addresses, string messagetext)
{
//Put your SMS code here
}
When you need to call the function, queue it as a background item
HostingEnvironment.QueueBackgroundWorkItem(a => SendSMS(addresses, messageText));
If your worker task needs to access its own cancellation token (e.g. if it is supposed to loop until cancelled), it is passed as an argument to the lambda expression. So you could modify the prototype
static void SendSMS(string[] addresses, string messagetext, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Put your code here
}
}
and pass it thus:
HostingEnvironment.QueueBackgroundWorkItem(token => SendSMS(addresses, messageText, token));
Placing the task in the background queue ensures that ASP.NET keeps track of the thread, doesn't try to garbage collect it, and shuts it down properly when the application pool needs to shut down.
After queuing the background operation, your page can render is content per usual and conclude the HTTP response while the task continues to execute.

WNS PushNotificationReceived does not intercept toast push notification

I'm writing a windows desktop app that relies on notifications to work. However, the event handler code, PushNotificationReceived on the channel does not seem to actually fire when I receive a notification. The following code is called to get the channel before its uri is sent to my server:
internal async Task<PushNotificationChannel> GetChannel()
{
PushNotificationChannel pnc;
try
{
pnc = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
if (_channel == null || !pnc.Uri.Equals(_channel.Uri))
{
_channel = pnc;
_channel.PushNotificationReceived += OnPushNotificationReceived;
Debug.WriteLine(_channel.Uri);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
_channel = null;
}
dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
return _channel;
}
Such that anytime the channel is created or updated (via a different channel uri), it should assign the new channel's PushNotificationReceived event to the following (which is basically lifted from msdn's example):
void OnPushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs e)
{
string typeString = String.Empty;
string notificationContent = String.Empty;
switch (e.NotificationType)
{
//
//other notification types omitted for brevity
//
case PushNotificationType.Toast:
notificationContent = e.ToastNotification.Content.GetXml();
typeString = "Toast";
// Setting the cancel property prevents the notification from being delivered. It's especially important to do this for toasts:
// if your application is already on the screen, there's no need to display a toast from push notifications.
e.Cancel = true;
break;
}
Debug.WriteLine("Received notification, with payload: {0}", notificationContent);
string text = "Received a " + typeString + " notification, containing: " + notificationContent;
var ignored = dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MainPage.Current.ClearBanner();
});
}
Importantly, "MainPage.Current" is a reference to the app's main page as a static variable. The clear banner line simply removes a pink banner from the main page (just trying to get something simple working to start).
However, the code never seems to fire (no debug statement, pink banner remains). I am successfully getting the toast notification, and clicking on it will set focus to my app, so it's definitely not going to the wrong place.
Is there something I am doing wrong or some way to debug the notifications themselves?

Categories