have a app that allow push notification and im using one signal with xamarin sdk.
My app is use prism.forms 7.2 and xamarin.forms 4.3.x
I want to navigate when i open notification and i developed some code but i have issue with navigation. It doesnt work as expected. especially app not working in background.
I can get push notification, but when I open the notification does not navigate I want to go to the main page instead of the product detail page.
does not navigate to the page I want.
Here is my App.cs
` public partial class App
{
public new INavigationService NavigationService => base.NavigationService;
/*
* The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
* This imposes a limitation in which the App class must have a default constructor.
* App(IPlatformInitializer initializer = null) cannot be handled by the Activator.
*/
public App() : this(null) { }
public App(IPlatformInitializer initializer) : base(initializer) {
}
protected override async void OnInitialized()
{
InitializeComponent();
XF.Material.Forms.Material.Init(this);
if (Helpers.AppConstants.DebugMode)
{
// Handle Xamarin Form Logging events such as Binding Errors
Log.Listeners.Add(new Services.TraceLogListener());
}
InitAkavache();
InitGoogleAnalytics();
OneSignal.Current.StartInit(Helpers.AppConstants.OneSignalKey)
.Settings(new Dictionary<string, bool>()
{
{IOSSettings.kOSSettingsKeyAutoPrompt, false },
{IOSSettings.kOSSettingsKeyInAppLaunchURL, true },
})
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.UnsubscribeWhenNotificationsAreDisabled(true)
.EndInit();
await NavigationService.NavigateAsync(Screens.SplashScreenPage);
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
..........
}
protected override void OnStart()
{
// Handle when your app starts
Microsoft.AppCenter.AppCenter.Start($"android={Helpers.AppConstants.AppCenterAndroidSecret}; ios={Helpers.AppConstants.AppCenteriOSSecret}",
typeof(Microsoft.AppCenter.Analytics.Analytics), typeof(Microsoft.AppCenter.Crashes.Crashes));
OneSignal.Current.RegisterForPushNotifications();
OneSignal.Current.IdsAvailable((playerID, pushToken) =>
{
Helpers.Settings.PlayerId = playerID.ToString();
});
}
protected override void OnSleep()
{
var caches = new[]
{
Akavache.BlobCache.LocalMachine,
Akavache.BlobCache.Secure,
Akavache.BlobCache.UserAccount,
Akavache.BlobCache.InMemory
};
caches.Select(x => x.Flush())
.Merge()
.Select(_ => System.Reactive.Unit.Default)
.Wait();
}
#region Private Methods
private void InitAkavache()
{
Akavache.BlobCache.ApplicationName = Helpers.AppConstants.ApplicationName;
Akavache.BlobCache.EnsureInitialized();
}
#endregion
}
`
And my AppDeletage.cs
` public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Rg.Plugins.Popup.Popup.Init();
LabelHtml.Forms.Plugin.iOS.HtmlLabelRenderer.Initialize();
global::Xamarin.Forms.Forms.SetFlags("Visual_Experimental", "CollectionView_Experimental");
global::Xamarin.Forms.Forms.Init();
Xamarin.Forms.FormsMaterial.Init();
Xamarin.Essentials.ExperimentalFeatures.Enable("EmailAttachments_Experimental");
SetupThirdPartyLibraries();
LoadApplication(new App(new iOSInitializer()));
//foreach (var font in UIFont.FamilyNames)
//{
// foreach (var item in UIFont.FontNamesForFamilyName(font))
// {
// Console.WriteLine(item);
// }
// Console.WriteLine("-----------");
//}
return base.FinishedLaunching(app, options);
}
public override void OnActivated(UIApplication uiApplication)
{
base.OnActivated(uiApplication);
Facebook.CoreKit.AppEvents.ActivateApp();
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
//return base.OpenUrl(application, url, sourceApplication, annotation);
return Facebook.CoreKit.ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation);
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
// NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
NSDictionary custom = userInfo.ObjectForKey(new NSString("custom")) as NSDictionary;
NSDictionary a = custom.ObjectForKey(new NSString("a")) as NSDictionary;
//NSError error = null;
//var body = NSJsonSerialization.Serialize(userInfo, NSJsonWritingOptions.PrettyPrinted, out error);
if (application.ApplicationState == UIApplicationState.Active)
{
//app is currently active, you can get your payload (userInfo) data here
if (a.ContainsKey(new NSString("product")))
{
var product = NSObjectConverter.ToString(a[new NSString("product")]);
var id = Convert.ToInt64(product);
Helpers.Settings.ProductId = id;
Helpers.Settings.HasNotification = true;
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.ProductDetailPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("category")))
{
var category = NSObjectConverter.ToString(a[new NSString("category")]);
var id = Convert.ToInt32(category);
Helpers.Settings.CategoryId = id;
Helpers.Settings.HasNotification = true;
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.MainTabbedPage}?{KnownNavigationParameters.SelectedTab}={Screens.MainPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("open")))
{
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.MainTabbedPage}?{KnownNavigationParameters.SelectedTab}={Screens.MainPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("coupon")))
{
var coupon = NSObjectConverter.ToString(a[new NSString("coupon")]);
if (!string.IsNullOrWhiteSpace(coupon))
{
Xamarin.Essentials.Clipboard.SetTextAsync(coupon)
.GetAwaiter()
.GetResult();
}
}
}
else if (application.ApplicationState == UIApplicationState.Background)
{
//app is in background, you can get your payload (userInfo)
SaveNotificationToLocalDb(userInfo);
}
else if (application.ApplicationState == UIApplicationState.Inactive)
{
//app is transitioning from background to foreground (user taps notification), do what you need when user taps here, you can get your payload (userInfo)
if (a.ContainsKey(new NSString("product")))
{
var product = NSObjectConverter.ToString(a[new NSString("product")]);
var id = Convert.ToInt64(product);
Helpers.Settings.ProductId = id;
Helpers.Settings.HasNotification = true;
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.ProductDetailPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("category")))
{
var category = NSObjectConverter.ToString(a[new NSString("category")]);
var id = Convert.ToInt32(category);
Helpers.Settings.CategoryId = id;
Helpers.Settings.HasNotification = true;
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.MainTabbedPage}?{KnownNavigationParameters.SelectedTab}={Screens.MainPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("open")))
{
var navigationService = (Xamarin.Forms.Application.Current as YakalaCo.App).NavigationService;
var res = navigationService.NavigateAsync($"app:///{Screens.NavigationPage}/{Screens.MainTabbedPage}?{KnownNavigationParameters.SelectedTab}={Screens.MainPage}")
.GetAwaiter()
.GetResult();
}
if (a.ContainsKey(new NSString("coupon")))
{
var coupon = NSObjectConverter.ToString(a[new NSString("coupon")]);
if (!string.IsNullOrWhiteSpace(coupon))
{
Xamarin.Essentials.Clipboard.SetTextAsync(coupon)
.GetAwaiter()
.GetResult();
}
}
}
}
public override void WillEnterForeground(UIApplication uiApplication)
{
uiApplication.ApplicationIconBadgeNumber = 0;
base.WillEnterForeground(uiApplication);
}
private void SaveNotificationToLocalDb(NSDictionary userInfo)
{
NSDictionary aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
NSDictionary alert = aps.ObjectForKey(new NSString("alert")) as NSDictionary;
NSDictionary custom = userInfo.ObjectForKey(new NSString("custom")) as NSDictionary;
NSDictionary a = custom.ObjectForKey(new NSString("a")) as NSDictionary;
var item = new Data.Entity.Notification();
if (alert.ContainsKey(new NSString("title")))
{
item.Title = NSObjectConverter.ToString(alert[new NSString("title")]);
}
if (alert.ContainsKey(new NSString("body")))
{
item.Body = NSObjectConverter.ToString(alert[new NSString("body")]);
}
if (alert.ContainsKey(new NSString("subtitle")))
{
item.SubTitle = NSObjectConverter.ToString(alert[new NSString("subtitle")]);
}
if (a.ContainsKey(new NSString("product")))
{
var productId = NSObjectConverter.ToString(a[new NSString("product")]);
item.Type = Enums.NotificationType.Product;
item.AdditionalData = new System.Collections.Generic.List<Data.Entity.AdditionalData>
{
new Data.Entity.AdditionalData{
Type = "type",
Value="product"
},
new Data.Entity.AdditionalData{
Type = "product",
Value=productId
},
};
}
else if (a.ContainsKey(new NSString("category")))
{
var categoryId = NSObjectConverter.ToString(a[new NSString("category")]);
item.Type = Enums.NotificationType.Category;
item.AdditionalData = new System.Collections.Generic.List<Data.Entity.AdditionalData>
{
new Data.Entity.AdditionalData{
Type = "type",
Value="category"
},
new Data.Entity.AdditionalData{
Type = "category",
Value=categoryId
},
};
}
else if (a.ContainsKey(new NSString("open")))
{
item.Type = Enums.NotificationType.Open;
item.AdditionalData = new System.Collections.Generic.List<Data.Entity.AdditionalData>
{
new Data.Entity.AdditionalData{
Type = "type",
Value="open"
},
};
}
else if (a.ContainsKey(new NSString("coupon")))
{
var coupon = NSObjectConverter.ToString(a[new NSString("coupon")]);
item.Type = Enums.NotificationType.Coupon;
item.AdditionalData = new System.Collections.Generic.List<Data.Entity.AdditionalData>
{
new Data.Entity.AdditionalData{
Type = "type",
Value="coupon"
},
new Data.Entity.AdditionalData{
Type = "coupon",
Value=coupon
},
};
}
else
{
item.Type = Enums.NotificationType.Unknown;
}
using (var notificationService = new Data.NotificationLiteDbService())
{
notificationService.CreateItem(item);
}
}
private void SetupThirdPartyLibraries()
{
.....
OneSignal.Current.StartInit(Helpers.AppConstants.OneSignalKey).EndInit();
}
}`
My main problem is that when user touch the notification app navigate the product detail page or other pages but OnInitialized method is still triggered so after navigate product detail page than app navigate to main page after navigate to product detail page.
Any advice?
I've searched a lot on the internet, but I can't find a solution.
Thank.