Xamarin Forms: Load a contentpage when tap push notification android - xamarin.forms

I completed receiving test notification from FCM console. Now I am trying to open a page when tapping the notification. Any ideas about how to achieve this? I have searched the internet but can't find a working solution. I am also able to send the notification through the postman.

I handle the notification tapping in following way. The page loading is handled in App.xaml.cs.
On OnCreate():
//Background or killed mode
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
if (key == "webContentList")
{
if (value?.Length > 0)
{
isNotification = true;
LoadApplication(new App(domainname, value));
}
}
}
}
//Foreground mode
if (FirebaseNotificationService.webContentList.ToString() != "")
{
isNotification = true;
LoadApplication(new App(domainname, FirebaseNotificationService.webContentList.ToString()));
FirebaseNotificationService.webContentList = "";
}
//Normal loading
if (!isNotification)
{
LoadApplication(new App(domainname, string.Empty));
}
On FirebaseNotificationService:
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FirebaseNotificationService : FirebaseMessagingService
{
public static string webContentList = "";
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
webContentList = message.Data["webContentList"];
try
{
SendNotificatios(message.GetNotification().Body, message.GetNotification().Title);
}
catch (Exception ex)
{
Console.WriteLine("Error:>>" + ex);
}
}
public void SendNotificatios(string body, string Header)
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
.SetContentTitle(Header)
.SetSmallIcon(Resource.Drawable.icon)
.SetContentText(body)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManager.FromContext(this);
notificationManager.Notify(0, notificationBuilder.Build());
}
else
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new Android.App.Notification.Builder(this, Utils.CHANNEL_ID)
.SetContentTitle(Header)
.SetSmallIcon(Resource.Drawable.icon)
.SetContentText(body)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent)
.SetChannelId(Utils.CHANNEL_ID);
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
return;
}
var channel = new NotificationChannel(Utils.CHANNEL_ID, "FCM Notifications", NotificationImportance.High)
{
Description = "Firebase Cloud Messages appear in this channel"
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
notificationManager.Notify(0, notificationBuilder.Build());
}
}

I don't know what's your actual Firebase implementation, but this might help you.
There is a nice package for Firebase in Xamarin Forms that we use in our production App made by CrossGeeks team. Its working great and has all handlers for your needs. This works with iOS and Android and you don't need to write platform specific code, only configuration and some code in AppDelegate.cs and MainActivity.cs
https://github.com/CrossGeeks/FirebasePushNotificationPlugin/blob/master/docs/FirebaseNotifications.md#notification-events
I wrote a simple PushNotificationService that processes automatic refresh and/or pushes new pages considering push notif data.
When app is closed and user clicks on the notification, I store the push notif data using Akavache.
CrossFirebasePushNotification.Current.OnNotificationOpened += async (s, p) =>
{
if (App.AppBeenResumed)
{
await BlobCache.UserAccount.InsertObject("pushNotifData", p.Data);
}
else
{
await ProcessReceivedPushNotification(p.Data);
}
};
And on the landing page of the app, I check if there is an existing push notif data in the OnAppearing method of the page.
protected override void OnAppearing()
{
base.OnAppearing();
App.AppBeenResumed = false;
HandlePushNotificationIfExists();
}
private async void HandlePushNotificationIfExists()
{
IDictionary<string, object> pushNotifData;
try
{
pushNotifData = await BlobCache.UserAccount.GetObject<IDictionary<string, object>>("pushNotifData");
}
catch (KeyNotFoundException)
{
pushNotifData = null;
}
if (pushNotifData == null) return;
await BlobCache.UserAccount.InvalidateAllObjects<IDictionary<string, object>>();
await PushNotificationService.ProcessReceivedPushNotification(pushNotifData);
}
In the ProcessReceivedPushNotification you can do whatever you want ... push directly the page or whatever... call another service that will do the job of pushing a new page and some business process.
Note that App.AppBeenResumed is a static bool to determine if App has been started or resumed to handle correctly the process of treatment of the push notif (process it instant or store it in blobcache to treat it later when landing page is Appearing).
In MainActivity.cs :
protected override void OnCreate(Bundle bundle)
{
...
LoadApplication(new App(true));
}
In the App.cs :
public App(bool beenResumedOrStarted)
{
...
AppBeenResumed = beenResumedOrStarted;
...
}
protected override void OnResume()
{
AppBeenResumed = false;
}
protected override void OnSleep()
{
//iOS states are not the same so always false when device is iOS
AppBeenResumed = Device.RuntimePlatform != Device.iOS;
}

Related

MainPage fails to Load properly

I have this code to set the Mainpage of my Application.
public async Task LoadMainPage()
{
try
{
signedin = Auth.IsUserSignedIn();
if (signedin)
registered = await Firestore.IsUserRegistered();
if (!signedin)
{
MainPage = new NavigationPage(new MainPage());
}
else if (signedin && !(registered))
{
MainPage = new NavigationPage(new RegistrationPage());
}
else if (signedin && (registered))
{
MainPage = new NavigationPage(new FlyoutPage1());
}
}
catch (Exception ex) { await App.Current.MainPage.DisplayAlert("Error", ex.Message, "OK"); }
}
I am calling this method from App.Xaml.cs Onstart method
protected override async void OnStart()
{
base.OnStart();
await LoadMainPage();
}
the problem is when the Application is launched the Mainpage fails to Load Properly.
it appears only when i tap the triple line icon on my phone wait for some time and tap the application again to launch it.
the code for Firestore.IsUserRegistered is as below
public async Task<bool> IsUserRegistered()
{
FirebaseFirestore collection = FirebaseFirestore.Instance;
string email = FirebaseAuth.Instance.CurrentUser.Email;
Android.Gms.Tasks.Task task = collection.Collection("User").WhereEqualTo("Email", email)
.Limit(1).Get().AddOnSuccessListener(this);
for (int i = 0; i < 25; i++)
{
await Task.Delay(100);
if (isregistered ) break;
}
return isregistered;
}
public void OnSuccess(Java.Lang.Object result)
{
var documents = (QuerySnapshot)result;
isregistered = !documents.IsEmpty;
}
You can add await LoadMainPage(); to OnResume() just like Splash Screen.
It said:
The startup work is performed asynchronously in OnResume. This is necessary so that the startup work does not slow down or delay the appearance of the launch screen. When the work has completed, SplashActivity will launch MainActivity and the user may begin interacting with the app.

Android notifications in a xamarin forms app

I'm working in a xamarin forms app, and I'm trying to develop an Android notification with two buttons:
In the first one you can write text, and this text must be retrieve to one of the ViewModels.
The second one should open a view of the app.
I have no experience with intents nor Android, and so far I can show the notification with the two buttons:
notification example
The class in charge of showing the notification is LocalNotifications : ILocalNotifications class in the Android solution:
class LocalNotifications : ILocalNotifications
{
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
...
bool channelInitialized = false;
int messageId = 0;
int replyPendingIntentId = 0;
int photoPendingIntentId = 0;
NotificationManager manager;
public event EventHandler NotificationReceived;
public static LocalNotifications Instance { get; private set; }
public LocalNotifications() => Initialize();
public void Initialize()
{
if (Instance == null)
{
CreateNotificationChannel();
Instance = this;
}
}
public void SendNotification(string title, string message)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
Show(title, message);
}
public void ReceiveNotification(string title, string message)
{
var args = new NotificationEventArgs()
{
Title = title,
Message = message,
};
NotificationReceived?.Invoke(null, args);
}
private static readonly string KEY_TEXT_REPLY = "key_text_reply";
AndroidX.Core.App.RemoteInput remoteEntryInput = new AndroidX.Core.App.RemoteInput.Builder(KEY_TEXT_REPLY)
.SetLabel("Escribir entrada")
.Build();
private Intent replyIntent;
private Intent photoIntent;
public void Show(string title, string message)
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentTitle(title)
.SetContentText(message)
.SetLargeIcon(BitmapFactory.DecodeResource(AndroidApp.Context.Resources, Resource.Drawable.abc_ab_share_pack_mtrl_alpha))
.SetSmallIcon(Resource.Drawable.abc_ab_share_pack_mtrl_alpha)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);
NotificationCompat.Action reply = CreateReplyIntent(title, message);
builder.AddAction(reply);
NotificationCompat.Action image = CreateImageIntent();
builder.AddAction(image);
Notification notification = builder.Build();
manager.Notify(messageId++, notification);
}
NotificationCompat.Action CreateReplyIntent(string title, string message)
{
//replyIntent = new Intent(AndroidApp.Context, typeof(MainActivity));
replyIntent = new Intent();
replyIntent.PutExtra(TitleKey, title);
replyIntent.PutExtra(MessageKey, message);
// Build a PendingIntent for the reply action to trigger.
PendingIntent replyPendingIntent =
PendingIntent.GetBroadcast(AndroidApp.Context, replyPendingIntentId++, replyIntent, PendingIntentFlags.UpdateCurrent);
// Create the reply action and add the remote input.
return new NotificationCompat.Action.Builder(Resource.Drawable.abc_ab_share_pack_mtrl_alpha,
"Escribir entrada", replyPendingIntent)
.AddRemoteInput(remoteEntryInput)
.Build();
}
NotificationCompat.Action CreateImageIntent()
{
//photoIntent = new Intent("android.media.action.IMAGE_CAPTURE");
photoIntent = new Intent(AndroidApp.Context, typeof(MainActivity));
//photoIntent.SetFlags( ActivityFlags.LaunchAdjacent | Intent.FLAG_ACTIVITY_CLEAR_TASK);
// Build a PendingIntent for the reply action to trigger.
PendingIntent phtoPendingIntent = PendingIntent.GetBroadcast(AndroidApp.Context, photoPendingIntentId++, photoIntent, PendingIntentFlags.UpdateCurrent);
return new NotificationCompat.Action.Builder(Resource.Drawable.abc_ab_share_pack_mtrl_alpha,
"Sacar foto", phtoPendingIntent)
.Build();
}
void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelNameJava = new Java.Lang.String(channelName);
var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Default)
{
Description = channelDescription
};
manager.CreateNotificationChannel(channel);
}
channelInitialized = true;
}
}
Which a don't get is how/where the app can react to those PendintIntents and how to pass the information from the android solution to the xamarin forms model.

Fetch Firebase push notification data without clicking notification - Xamarin.forms iOS

Hi I have a xamarin forms ios application implemented with firebase push notifications. I can receive and mange the click of notifications. Currently I am trying to store the notification data ie; Title,body and two other parameters comes with notification in to sqlite database. I can retrieve and store the data when user clicks. But cant store if user swipe away the notification. How can I get the values as soon as notification appear? Any help is appriciated.
My AppDelegate
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
Firebase.Core.App.Configure();
LoadApplication(new App());
//<-------Firebase Implementation------------->
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// iOS 10 or later
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => {
Console.WriteLine(granted);
});
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
// For iOS 10 data message (sent via FCM)
//Messaging.SharedInstance.RemoteMessageDelegate = this;
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
Messaging.SharedInstance.Delegate = this;
Messaging.SharedInstance.ShouldEstablishDirectChannel = true;
return base.FinishedLaunching(app, options);
}
//<--------Firebase Portion------->
[Export("messaging:didReceiveRegistrationToken:")]
public void DidReceiveRegistrationToken(Messaging messaging, string fcmToken)
{
Settings.FirebaseRegID = fcmToken;
MessagingCenter.Send<object, string>(this, "fcmtoken", fcmToken.ToString());
Console.WriteLine($"fcmtoken received: {fcmToken}");
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
HandleMessage(userInfo);
LogInformation(nameof(DidReceiveRemoteNotification), userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
if (UIApplication.SharedApplication.ApplicationState.Equals(UIApplicationState.Active))
{
//App is in foreground. Act on it.
}
else
{
// MessagingCenter.Send<object, List<key>>(this, "messagedata", myData);
}
}
//User for showing the notification in foreground mode
[Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification,
Action<UNNotificationPresentationOptions> completionHandler)
{
completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);
}
//Foreground mode notification tapping handling here
[Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action
completionHandler)
{
completionHandler();
NSDictionary userInfo = response.Notification.Request.Content.UserInfo;
try
{
var Data = userInfo[new NSString("gcm.notification.data")] as NSString;
if (Data != null && Data != "")
{
string[] tokens = Data.ToString().Split(',');
string Username = tokens[0];
string Password = tokens[1];
var Title = string.IsNullOrEmpty(response.Notification.Request.Content.Title)?"No Notification available": response.Notification.Request.Content.Title;
var Body = string.IsNullOrEmpty(response.Notification.Request.Content.Body)?"No Message available": response.Notification.Request.Content.Body;
MessagingCenter.Send(new NotificationData() { TItle = Title.ToString(), Body = Body.ToString(),username= Username ,Password= Password }, "iosnotificationTapped");
}
}
catch (Exception ex)
{
}
}
[Export("messaging:didReceiveMessage:")]
public void DidReceiveMessage(Messaging messaging, RemoteMessage remoteMessage)
{
// Handle Data messages for iOS 10 and above.
HandleMessage(remoteMessage.AppData);
LogInformation(nameof(DidReceiveMessage), remoteMessage.AppData);
}
void HandleMessage(NSDictionary message)
{
//if (MessageReceived == null)
// return;
//MessageType messageType;
//if (message.ContainsKey(new NSString("aps")))
// messageType = MessageType.Notification;
//else
// messageType = MessageType.Data;
//var e = new UserInfoEventArgs(message, messageType);
//MessageReceived(this, e);
}
public static void ShowMessage(string title, string message, UIViewController fromViewController, Action actionForOk = null)
{
var alert = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);
alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, (obj) => actionForOk?.Invoke()));
fromViewController.PresentViewController(alert, true, null);
}
void LogInformation(string methodName, object information) => Console.WriteLine($"\nMethod name: {methodName}\nInformation: {information}");
}
EDIT I tried to put debugger on
void DidReceiveRemoteNotification,void DidReceiveMessage,void HandleMessage
None of them hit when notification appears. Only DidReceiveNotificationResponse will hit if we tap the notification. In android there is onmessagereceived which will hit when notification arrives. Does iOS have such method?

need to send local notification even after killing my app using xamarin.forms

I am using xamarin forms for my app. I need to send local notification based on SQLite table for ios. I am using the following code:
AppDelegate.cs:
using System;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Firebase.Database;
using Firebase.CloudMessaging;
using UserNotifications;
using Microsoft.AppCenter.Crashes;
using Plugin.Permissions;
using Plugin.Permissions.Abstractions;
using CoreTelephony;
using Firebase.Auth;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace MyApp.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate, IUNUserNotificationCenterDelegate, IMessagingDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
Firebase.Core.App.Configure();
Database.DefaultInstance.PersistenceEnabled = true;
LoadApplication(new MyApp.App());
RegisterForRemoteNotifications();
Messaging.SharedInstance.Delegate = this;
if (UNUserNotificationCenter.Current != null)
{
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
}
if (UNUserNotificationCenter.Current != null)
{
UNUserNotificationCenter.Current.Delegate = new UserNotificationCenterDelegate();
}
Xamarin.FormsMaps.Init();
UIApplication.SharedApplication.IdleTimerDisabled = true;
UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum);
return base.FinishedLaunching(app, options);
}
public override bool ShouldRestoreApplicationState(UIApplication application, NSCoder coder)
{
return true;
}
private async System.Threading.Tasks.Task AcessPermissionsAsync()
{
try
{
await CrossPermissions.Current.RequestPermissionsAsync(Permission.Camera);
}
catch(Exception ex)
{
Crashes.TrackError(ex);
}
}
private void RegisterForRemoteNotifications()
{
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
UNUserNotificationCenter.Current.RemoveAllPendingNotificationRequests(); // To remove all pending notifications which are not delivered yet but scheduled.
UNUserNotificationCenter.Current.RemoveAllDeliveredNotifications(); // To remove all delivered notifications
}
else
{
UIApplication.SharedApplication.CancelAllLocalNotifications();
}
// Register your app for remote notifications.
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
{
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.Current.Delegate = this;
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, async (granted, error) =>
{
Console.WriteLine(granted);
await System.Threading.Tasks.Task.Delay(500);
await AcessPermissionsAsync();
});
}
else
{
// iOS 9 or before
var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
}
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
public override void DidEnterBackground(UIApplication uiApplication)
{
Messaging.SharedInstance.ShouldEstablishDirectChannel = false;
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
Messaging.SharedInstance.ApnsToken = deviceToken;
}
[Export("messaging:didReceiveRegistrationToken:")]
public void DidReceiveRegistrationToken(Messaging messaging, string fcmToken)
{
Xamarin.Forms.Application.Current.Properties["Fcmtocken"] = Messaging.SharedInstance.FcmToken ?? "";
Xamarin.Forms.Application.Current.SavePropertiesAsync();
System.Diagnostics.Debug.WriteLine($"######Token###### : {fcmToken}");
DeviceId.FCMTocken = fcmToken;
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
// If you are receiving a notification message while your app is in the background,
// this callback will not be fired till the user taps on the notification launching the application.
// TODO: Handle data of notification
// With swizzling disabled you must let Messaging know about the message, for Analytics
// Print full message.
Console.WriteLine(userInfo);
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
try
{
Console.WriteLine(userInfo);
completionHandler(UIBackgroundFetchResult.NewData);
}
catch(Exception ex)
{
Crashes.TrackError(ex);
}
}
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
switch (Device.Idiom)
{
case TargetIdiom.Phone:
return UIInterfaceOrientationMask.Portrait;
case TargetIdiom.Tablet:
return UIInterfaceOrientationMask.Landscape;
default:
return UIInterfaceOrientationMask.Portrait;
}
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
var newExc = new Exception("CurrentDomainOnUnhandledException", unhandledExceptionEventArgs.ExceptionObject as Exception);
ExceptionFileWriter.ToLogUnhandledException(newExc);
}
public void DidRefreshRegistrationToken(Messaging messaging, string fcmToken)
{
Xamarin.Forms.Application.Current.Properties["Fcmtocken"] = Messaging.SharedInstance.FcmToken ?? "";
Xamarin.Forms.Application.Current.SavePropertiesAsync();
System.Diagnostics.Debug.WriteLine($"######Token###### : {fcmToken}");
DeviceId.FCMTocken = fcmToken;
}
public override void PerformFetch(UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
try
{
var baseService = new DatabaseServices<object, object>();
baseService.NotificationAssetTrip();
}
catch(Exception ex)
{
Logs.LogCreate("PerformFetch:Exception: " + ex.Message.ToString());
}
completionHandler(UIBackgroundFetchResult.NewData);
}
}
}
UserNotificationCenterDelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Foundation;
using iAd;
using ObjCRuntime;
using UIKit;
using UserNotifications;
namespace MyApp.iOS
{
public class UserNotificationCenterDelegate : UNUserNotificationCenterDelegate
{
private DBService dataBase;
#region Constructors
public UserNotificationCenterDelegate()
{
UNUserNotificationCenter.Current.Delegate = this;
}
#endregion
#region Override Methods
public override void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action<UNNotificationPresentationOptions> completionHandler)
{
completionHandler.DynamicInvoke(UNNotificationPresentationOptions.Alert);
}
#endregion
}
}
App.xaml.cs:
private void SendNotificationTripAsset(int tripid)
{
//Forexample i have table with columns like title,subtitle,message means, i give like this
var content = new UserNotifications.UNMutableNotificationContent()
{
Title = title,
Subtitle = subtitle,
Body = message,
Badge = 1
};
var request = UserNotifications.UNNotificationRequest.FromIdentifier(list.TripID.ToString(), content, null);
UserNotifications.UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) =>
{
if (err != null)
{
throw new Exception($"Failed to schedule notification: {err}");
}
});
}
But the notification is not trigged after app is killed(terminated). Can anyone please help me to resolve this issue.
To send a local notification when app is killed, you have to specify the time when should the local notification been sent. In your code, when you create the request, set a proper NNotificationTrigger :
NNotificationTrigger trigger = UNTimeIntervalNotificationTrigger.CreateTrigger(3, false);
var request = UserNotifications.UNNotificationRequest.FromIdentifier(list.TripID.ToString(), content, trigger );
That means this notification will be fired after 3 seconds. You can change the time to whatever you want.
Code will not execute when your app is killed, so if you don't know the specific time to fire the notification or it fires randomly, you should use a remote notification.

How to initialize bar code scanner on App startup

I have a requirement for my xamarin cross platform application that as soon as app start up .QR Scanner set in to read the code. on completing scanning a beep will be ring up.and app again ready for next scanning how can i get this done. what i have done is on button click scanner start, its read code, then i have to press button again to start it again.
public HomePage()
{
Button scanBtn = new Button
{
Text = "Scan Barcode",
HorizontalOptions = LayoutOptions.FillAndExpand,
};
scanBtn.Clicked += async (sender, args) =>
{
var scanResult = await Acr.BarCodes.BarCodes.Instance.Read();
if (!scanResult.Success)
{
await this.DisplayAlert("Alert ! ", "Sorry ! \n Failed to read the Barcode !", "OK");
}
else
{
var endpoint = new EndpointAddress("http://192.168.15.33/SMS/WebServices/SMSService.svc");
var binding = new BasicHttpBinding
{
Name = "basicHttpBinding",
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647
};
TimeSpan timeout = new TimeSpan(0, 0, 30);
binding.SendTimeout = timeout;
binding.OpenTimeout = timeout;
binding.ReceiveTimeout = timeout;
_client = new SMSServiceClient(binding, endpoint);
_client.ValidateStudentAsync("123-admin");
_client.ValidateStudentCompleted += _client_ValidateStudentCompleted; ;
// await this.DisplayAlert("Scan Successful !", String.Format("Barcode Format : {0} \n Barcode Value : {1}", scanResult.Format, scanResult.Code), "OK");
}
};
Content = new StackLayout
{
Children = {
scanBtn
}
};
}
and in app.cs
public class App : Application
{
public App()
{
// The root page of your application
MainPage = new HomePage();
}
protected override void OnStart()
{
MainPage = new HomePage();
}
protected override void OnSleep()
{
MainPage = new HomePage();
}
protected override void OnResume()
{
MainPage = new HomePage();
}
}
You can use ZXing.Net.Mobile for Forms to read QR codes. To initialize this plugin you should call method to init into each project (Android, iOS, UWP) like this:
For Android in MainActivity.cs class call:
ZXing.Net.Mobile.Forms.Droid.Platform.Init();
For iOS in AppDeletage.cs class call
ZXing.Net.Mobile.Forms.iOS.Platform.Init();
And finally to read QR Codes:
private async void Scan() {
var scanPage = new ZXingScannerPage();
scanPage.OnScanResult += (result) => {
// Stop scanning
scanPage.IsScanning = false;
// Pop the page and show the result
Device.BeginInvokeOnMainThread( async () => {
await Navigation.PopAsync();
await DisplayAlert("Scanned Barcode", result.Text, "OK");
});
};
// Navigate to our scanner page
await Navigation.PushAsync(scanPage);
}

Resources