Android Xamarin Notification builder setWhen not working - xamarin.android

I am trying to implement local push notification in Xamarin Forms. I am using DependencyService to get the Android implementation of notification.
Here is the code I am using to push a notification at a particular time:
public void SetNotification(DateTime notificationDate, TimeSpan notificationTime)
{
long dateInMilli = (long)(notificationDate.Add(notificationTime) - DateTime.MinValue).TotalMilliseconds;
Notification.Builder builder = new Notification.Builder(Xamarin.Forms.Forms.Context)
.SetContentTitle("Test Notification")
.SetContentText("Notification from Xamarin Forms")
.SetSmallIcon(Resource.Drawable.icon)
.SetDefaults(NotificationDefaults.Sound)
.SetWhen(dateInMilli);
Notification notification = builder.Build();
NotificationManager notificationManager =
(NotificationManager)Forms.Context.GetSystemService(Context.NotificationService);
const int notificationId = 0;
notificationManager.Notify(notificationId, notification);
}
The problem is, notification is showing instantaneously not as per date and time set by SetWhen(dateInMilli).

SetWhen is used to display the time you put onto the timestamp of the notification, not to send the notification after X. You'll have to use alarms for that.
Refer to this to learn about that class.

Related

local notification is not displayed

I'm working on a Xamarion iOS app. I want to display a local notification when an event occurs in my app, Like Outlook does when an email is received.
I'm using the following code, after having received the right to send notification from the user, of course:
var content = new UNMutableNotificationContent();
if (!string.IsNullOrWhiteSpace(value: mySoundFile))
{
content.Sound = UNNotificationSound.GetCriticalSound(mySoundFile);
}
if (!string.IsNullOrEmpty(myChannelDescription))
{
content.ThreadIdentifier = myChannelDescription;
}
content.Title = "MyTitle";
content.Body = "MyText";
var trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(0.1, false);
var request = UNNotificationRequest.FromIdentifier(notification.Id.ToString(), content, trigger);
var center = UNUserNotificationCenter.Current;
center.AddNotificationRequest(request, null);
But the notification is not displayed.
Any help appreciated.
The reason for not displaying the notification could be several things. Try the following solutions:
Make sure that the application has the required rights to send notifications and that the user has enabled them.
Check if the sound file is valid and located in the application package. It may also be necessary to add it to the Info.plist file.
Check if the thread identifier is valid and not repeatable.
Check if the trigger time is valid. Setting 0.1 seconds is very short and may not be enough to display the notification.
If the above solutions do not work, it is worth using debugging tools to more closely examine why the notification is not displayed.
On iOS, you must request permission to use notifications before attempting to schedule them. Just like this, you can try to check if the following code is added to your project:
UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert, (approved, err) =>
{
...
});
You can change your AddNotificationRequest as follows to see if there is an error in the notification:
center.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
throw new Exception($"Failed to schedule notification: {err}");
}
});
For more details, you can refer to the following documents to check some permission issues:
Enhanced User Notifications in Xamarin.iOS | Microsoft
Asking permission to use notifications | Apple Developer
UpDate: If your app is in the foreground. You could try implementing the delegate userNotificationCenter(_:willPresent:withCompletionHandler:) which will be called when a notification arrives while the app is in the foreground. Refer to the following code:
UNUserNotificationCenter.Current.Delegate = new TestDelegate();
public class TestDelegate: UNUserNotificationCenterDelegate
{
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
completionHandler(UNNotificationPresentationOptions.Alert);
}
}

Tap apple watch push notification issue

I have an apple watch app that is not independent from the iPhone and I receive push notifications successfully on my watch.
However, tapping the push notification always opens the watch app. I do not want to handle this in the watch app. Is there a way to do this? Is there a way to not open the watch app on tap?
I've tried using the handleAction() functions in the WKExtensionDelegate but these are apparently now deprecated, and they never get fired.
This might not be possible. It relies on the OS.
Possible reasons for this is notifications are for the user to click and open the app usually. And this might go against apple app guidelines too to prevent the app from opening.
However, you can try these:
This is an example of a foreground service with the notification.
public class UploadService extends IntentService{
private NotificationCompat.Builder mBuilder;
public UploadService() {
super("UploadService");
}
#Override
protected void onHandleIntent(Intent intent) {
Intent deleteIntent = new Intent(this, CancelUploadReceiver.class);
PendingIntent pendingIntentCancel = PendingIntent.getBroadcast(this, 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//building the notification
mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(android.R.drawable.ic_menu_upload)
.setContentTitle("Uploading Media...")
.setTicker("Starting uploads")
.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Cancel Upload", pendingIntentCancel);
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
mBuilder.setProgress(100, 0, true);
startForeground(12345, mBuilder.build());
for(int i=0;i<10;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
You need to register the CancelUploadReceiver in the manifest file.
<receiver android:name=".CancelUploadReceiver"/>
And when the “Cancel Upload” is tapped it will receive the broadcast. Then we can simply stop the service.
public class CancelUploadReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent();
service.setComponent(new ComponentName(context,UploadService.class));
context.stopService(service);
}
}
Another option might be to create a Custom Interface that implements the UINotificationContentExtension protocol.
Related:
Can you disable App-opening mechanism when the user presses the Notification Banner?
How to disable opening app when user tap push notification
iOS notifications actions without opening the app
Is it possible to avoid showing app to user when tapping on a push notification in iOS?
Android notifications actions without opening the app
Andriod notifications with actions

IOS 13 doesn't play a notification sound using FirebasePushNotificationPlugin

I use Firebase to push notifications to the users at a certain time. They receive the notification but no alert sound is played. In the settings, the allow sound/notifications are turned on and other IOS13 and other apps play sound.
Version Number of FirebasePushNotificationPlugin Plugin: 3.3.10
Device Tested On: iphone X, OS: 13.4.1
Simulator Tested On: N/A (simulators don't receive notifications)
Version of VS: VS for Mac Community, 8.6.6 (build 11)
Version of Xamarin: Xamarin.IOS 13.18.2.1, Xamarin.Forms v4.6.0.847
AppDelegate.cs:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
bool fbaseStarted = false;
try
{
// This method does all the UNUserNotificationCenter.Current.RequestAuthorization() code so we don't have to.
FirebasePushNotificationManager.Initialize(options, true);
fbaseStarted = true;
}
catch
{ }
LoadApplication(new App());
if (!fbaseStarted)
{
try
{
FirebasePushNotificationManager.Initialize(options, true);
}
catch { }
}
FirebasePushNotificationManager.CurrentNotificationPresentationOption = UNNotificationPresentationOptions.Badge | UNNotificationPresentationOptions.Alert | UNNotificationPresentationOptions.Sound;
}
Within one of the pages of my code, I subscribe a list of tags (please note that I unsubscribe because the first time the code runs it fails silently if the notifications aren't approved - resulting in the model thinking the notifications was subscribed when it wasn't):
CrossFirebasePushNotification.Current.UnsubscribeAll();
CrossFirebasePushNotification.Current.Subscribe(Constants.NotificationTagsArray);
I keep coming across payload json solutions but unless I am wrong, I don't think that applies to me as I am using Xamarin and the FirebasePushNotificationPlugin. Is there any additional permissions that were added in ios 13 for playing notifications with sound that I have missed?
I have also posted here: https://github.com/CrossGeeks/FirebasePushNotificationPlugin/issues/348 but nobody has been able to assist me yet.
Thanks
The issue actually lies with the sending of the notifications nothing to do with the Xamarin App. The issue resided in the services that sends the notifications to firebase (to then be sent out to the phones).
In the service we were sending a FirebaseNet.Messaging.Message() to the phones:
Message FireBasemessage = new Message()
{
To = "/topics/" + PushNote.Tag,
TimeToLive = 86400,
Priority = MessagePriority.high,
ContentAvailable = true,
Notification = new AndroidNotification()
{
Tag = "/topics/" + PushNote.Tag,
Body = enhancedMessage,
Title = xtitle,
}
,
Data = new Dictionary<string, string>
{
{ "param", PushNote.Tag },
{ "text", enhancedMessage}
}
};
In the AndroidNotification() object required Sound = "default" to be added for it to work. Please note that this works for both Android and IOS notifications despite the fact it is an AndroidNotification object.

Xamarin IOS Push Killed app

Push =>
{{
aps = {
alert = {
"loc-args" = (
);
"loc-key" = "new_chat";
};
"content-available" = 1;
id = 3;
message = Aaa;
sound = default;
subject = "new_chat";
type = chat;
};
}}
When the application is killed and I receive a push notification it is shown with the text "new_chat". How can I change it to another text?
Assuming you are targeting iOS 10+, you can add a Notification Services extension app (UNNotificationServiceExtension) to your app bundle.
modifies the content of a remote notification before it is delivered to the user.
In the DidReceiveNotificationRequest override, extract your content from the UNNotificationRequest and modify it and return it via the contentHandler provided.
Required reading to understand how/when the extension is used:
Modifying Content in Newly Delivered Notifications
Also:
Xamarin Docs: iOS Extensions in Xamarin.iOS
Apple docs: UNNotificationServiceExtension

iOS RemoveDeliveredNotifications(string[] identifier) will not delete the notification(s) when app in background

maybe someone can help me.
In my app I'm using push notifications to inform the users that a new message is written to the database. One user can accept the notification and work with the content or dismiss it. If the user accepts it, a silent push is sent to all other devices which received the notification earlier. Here is my code handling this silent notification:
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary remoteNotification)
{
try
{
if (remoteNotification != null)
{
var alert = remoteNotification[FromObject("aps")];
if (alert != null)
{
string id = ((NSDictionary)alert)[FromObject("deleteId")].Description;
if (!String.IsNullOrEmpty(id))
{
List<string> idents = new List<string>();
UNUserNotificationCenter.Current.GetDeliveredNotifications(completionHandler: (UNNotification[] t) =>
{
foreach (UNNotification item in t)
{
UNNotificationRequest curRequest = item.Request;
var notificationId = ((NSDictionary)curRequest.Content.UserInfo[FromObject("aps")])[FromObject("notificationId")].Description;
if (id == notificationId)
{
idents.Add(curRequest.Identifier);
}
}
UNUserNotificationCenter.Current.RemoveDeliveredNotifications(idents.ToArray());
});
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
The problem is that the notification is still visible in the notification center until the app is brought to foreground. But then it gets deleted.
Is there a way to force the method to delete the notification instantly and not only when the app is (re)opened?
When you want to clear the Notifications send from this app. Set its application's badge to 0 to achieve this.
As you said you send a silent notifications to other users, Then DidReceiveRemoteNotification() will fire. In this event we can clear all notifications:
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
var aps = userInfo["aps"] as NSDictionary;
if (aps["content-available"].ToString() == "1")
{
//check if this is a silent notification.
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
}
completionHandler(UIBackgroundFetchResult.NewData);
}
Please notice that starting with iOS 8.0, your application needs to register for user notifications to be able to set the application icon badge number. So please add the code below in FinishedLaunching():
UIUserNotificationSettings settings = UIUserNotificationSettings.GetSettingsForTypes(UIUserNotificationType.Badge, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
Moreover silent notifications can only be received when your app is on background or foreground. If it's terminated, this will fail.
To remove a notification, you send a silent push notification to all devices with the notification ID as payload that should be removed.
On the clients you implement a UNNotificationServiceExtension which allows you to remove currently displayed notifications by their IDs: UNUserNotificationCenter.current().removeDeliveredNotifications.
This gives you the advantage that you have full control over this logic on the server side.

Resources