Search Unity

[RELEASED] UTNotifications - Professional Cross Platform Push Notifications and More

Discussion in 'Assets and Asset Store' started by Yuriy-Ivanov, Jun 12, 2015.

  1. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    Hi @anzz,

    Please see my reply in the email.

    Best regards,
    Yuriy, Universal Tools team.
     
  2. amadden1990

    amadden1990

    Joined:
    May 13, 2016
    Posts:
    2
    Okay so I just switched to this plugin to schedule notifications. Whenever I use schedule notification it only works with a short amount of time but I have it scheduled to appear 2-3 hours away and they never show up unless i reopen the app or move my phone around. I am testing on a galaxy note 10+. I also have a debug call showing the scheduled time in the console which is always correct. That datetime is the same one being used to schedule the notifications. Does the scheduled notifications timeout or sleep? Thanks
     
  3. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    Hi @amadden1990 ,

    Scheduled notifications don't timeout, but most likely your issue is caused by one of quite many power saving features in Android, especially I suggest you reading this: https://developer.android.com/about/versions/pie/power.
    UTNotifications registers internal "alarms" in AlarmManager (also, see the note in this article) as it lets apps do something in predefined times in background, even if the app is not running. Alarms are significantly affected by Android's power management, and if Android decides that your app is not important enough to put it to one of the "priority" buckets, then notifications may be delivered with significant delay (it's true for both local and push notifications, but local ones are usually affected stronger). You can also take a look at this article: https://www.samsung.com/us/support/answer/ANS00079037/.

    If I'm right about the reason, you should receive your notifications at some point, but likely significantly later than requested. But if notifications are never shown, I'll need a repro Unity project from you to investigate what's going on.

    Hope it helps.

    Best regards,
    Yuriy, Universal Tools team.
     
    Last edited: Jul 6, 2020
  4. kwej

    kwej

    Joined:
    Aug 12, 2017
    Posts:
    2
    I'm looking to upgrade an app to Unity 2019.4 (we have UTNotifications 1.8.2 loaded), but we're seeing a UTNotif errors at build time for iOS:

    Assets/UTNotifications/Src/iOS/IOSManagerImpl.cs(650,39): error CS0618: 'LocalNotification' is obsolete: 'iOS.Notification Services is deprecated. Consider using the Mobile Notifications package (available in the package manager) which implements the UserNotifications framework.'


    Is this resolved in the latest UTNotif package? Or do we need to integrate that Unity Mobile Notifs package? I didn't see mention of it anywhere, and we'd rather not upgrade packages without knowing the upgrade actually addresses a specific issue... so any insight would be greatly appreciated, thanks!
     
  5. shihab37

    shihab37

    Joined:
    Jul 7, 2015
    Posts:
    28

    Hi @Yuriy-Ivanov,
    First of all, thank you for this great plugin. We have been using it for years.

    In our new game, however, I'm having the exact same issue as @anzz
    Code (CSharp):
    1. CommandInvokationFailure: Gradle build failed.
    2. /Applications/Unity/Hub/Editor/2019.4.4f1/PlaybackEngines/AndroidPlayer/OpenJDK/bin/java -classpath "/Applications/Unity/Hub/Editor/2019.4.4f1/PlaybackEngines/AndroidPlayer/Tools/gradle/lib/gradle-launcher-5.1.1.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    3. stderr[
    4. D8: Type com.google.firebase.iid.zzbb is referenced as an interface from `com.google.firebase.messaging.zzf`.
    5. com.android.builder.dexing.DexArchiveBuilderException: com.android.builder.dexing.DexArchiveBuilderException: Failed to process /Users/shihab/.gradle/caches/transforms-2/files-2.1/a8d5840093588f0ddf1422752232c91b/jars/classes.jar
    Here's the detailed log: https://pastebin.com/XPW9GsLn

    Project Setup:
    Unity 2019.4.4f1
    UTNotification 1.8.4
    Packages:
    External Dependency Manager for Unity 1.2.157
    Firebase App (Core) 6.15.2
    Google Analytics for Firebase 6.15.2
    Firebase Crashlytics 6.15.2​

    If I uncheck the FCM checkbox in UTN settings, the game builds and runs fine without any errors.

    Additional Info:
    I also tried to build after deleting the "PlayServicesResolver" that comes with UTNotifications (because I already have EDM4U package), but the result is the same.

    UTN also replaces "Google.VersionHandler.dll" and "Google.VersionHandler.dll.mdb" files in EDM4U package. This causes the following exceptions

    Code (CSharp):
    1. MissingMethodException: bool Google.VersionHandler.RegisterBeforeAssemblyReloadEvent(System.Action)
    2.  
    3. and
    4.  
    5. MissingMethodException: bool Google.VersionHandler.UnregisterBeforeAssemblyReloadEvent(System.Action)
    Detailed log here: https://pastebin.com/7E8AH5NN

    If I replace these two files with the original ones, these exceptions are gone. I'm guessing these two methods were added recently in EDM4U. Should I keep using the original files that come with EDM or use the ones that come with UTN?
     
    Last edited: Aug 12, 2020
  6. bmorgan-ksg

    bmorgan-ksg

    Joined:
    Dec 13, 2016
    Posts:
    11
    We recently expanded our project to include Firebase v6.15.2 along with External Dependency Manager v1.2.157. While we didn't run into issue when building the project, we did get crashes on first install and when receiving a push notification that looked very similar to those posted above. We were able to resolve this by changing the Firebase version in the Dependencies.xml files:

    UTNotificationsAndroidDependencies.xml
    com.google.firebase:firebase-messaging:20.2.4

    UTNotificationsAndroidMinDependencies.xml
    com.google.firebase:firebase-messaging:20.0.0+

    I'm not certain this will resolve your build issue, but hopefully it helps point you in the right direction.
     
  7. shihab37

    shihab37

    Joined:
    Jul 7, 2015
    Posts:
    28
    Thank you for the hints but sadly it didn't work :(
    UTNotifications already added com.google.firebase:firebase-messaging:20.0.0+ to both files so, as per your suggestion, I tried building by changing version to "20.2.4" and then to "20.2.4+" in UTNotificationsAndroidDependencies.xml but the error remains the same.

    Your setup seems similar to mine [at least Firebase and EDM] I wonder why you are not getting these errors. What version of Unity are you using?
    and I also have FacebookSDK v7.21.1 in my project. are you using Facebook too?
     
  8. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    Hi @kwej,

    We're currently working on update addressing this and other issues, related to new versions of Unity and Firebase. Unfortunately there is no fast fix for it, you'll have to wait until we fix it (hope it will be available in several days, but can't guarantee it). The only solution available right, I'm afraid, is to refrain from updating to Unity 2019.4 or 2020, if you can.

    Best regards,
    Yuriy, Universal Tools team.
     
  9. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    @shihab37 @bmorgan-ksg
    It's not very helpful to modify UTNotificationsAndroidDependencies.xml or UTNotificationsAndroidMinDependencies.xml, these 2 files are generated (and overwritten) by UTNotifications when applying any settings - this configuration should be done in the section "Advanced / Android Libs Versions" in UTNotifications' settings in Unity, though I can't guarantee it will help.

    @shihab37 can you please send us to universal.tools.contact@gmail.com a repro Unity project, so we could test and reproduce the issue and find a fix for it asap?

    Thank you.

    Best regards,
    Yuriy, Universal Tools team.
     
  10. bmorgan-ksg

    bmorgan-ksg

    Joined:
    Dec 13, 2016
    Posts:
    11
    We are on Unity 2017.4 LTS and use the FB Plugin, but rolled back to 7.19.2 due to iOS build failures:
    https://github.com/facebook/facebook-sdk-for-unity/issues/455

    A few other things that might help:
    • We use a custom gradle template so that the android library dependencies are defined/resolved there, rather than being kept in the local file system.
    • We execute a custom build command in batchMode, which invokes GooglePlayServices.PlayServicesResolver.ResolveSync(true); before building the project.
    Generally speaking, I find the custom gradle file very helpful when running into these types of build issues as it clearly lists all of the Android dependencies being pulled into the build and where those dependencies originated from within the Unity project. I suspect you'd find a there is a duplicate or incompatible library listed there.
     
  11. shihab37

    shihab37

    Joined:
    Jul 7, 2015
    Posts:
    28
    you are right about custom Gradle file and we also use it for the same reasons.

    You were also right here in that the trick is to use the correct messaging library version especially when there are other firebase modules in the project. I just needed to figure out the correct version for my project. A colleague suggested me to try 20.2.1 and that seemed to work. then I installed FCM package from UPM and noticed that it put v20.1.7 in my mainTemplate.gradle so maybe this is the version that firebase wants in the project. I uninstalled the FCM package and set 20.1.7+ in UTNotification settings under "Advanced/Android Libs Version/Google Play Services" and finally, the build was successful and we are now getting push notifications on device.

    Thank you so much for your help.

    Thank you so much for the help Yuriy but I don't think we need a repro project now that the problem is solved.
    But this whole process of trying to figure out the correct library version was rather painful. Is this information available somewhere from Firebase? I read somewhere that you have to use the same version for every firebase module you have in your project. This seems simpler for Android Firebase SDK but the Unity SDK in my project is using 17.0.0 for Crashlytics, 17.4.1 for Analytics and now 20.1.7 for Messaging.

    so is there a simpler way to find the compatible version information?
     
  12. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    Hi @shihab37 ,

    Glad you sorted it. This is a huge problem indeed, for us as well, and unfortunately there is no simple solution. EDM4U tries to automate it as much as possible, but is not doing great work I'm afraid. F.e., we're currently working on an update to fix issues with Unity 2020, and faced new problems with it and EDM4U which prevent us from releasing a fix: see https://github.com/googlesamples/unity-jar-resolver/issues/396.

    Best regards,
    Yuriy, Universal Tools team.
     
  13. Kaiymu_

    Kaiymu_

    Joined:
    Jun 1, 2016
    Posts:
    47
    Hello!

    I'm also facing some issues regarding UTNotifications.
    When the app is running, the push notifications is displayed on Android without issues.
    But as soon as I quit the app / go into another app, I don't receive any notifications?

    Is that normal?

    If not, what can I do to fix that? Is there anything I need to do inside the AndroidManifest (I know it get patched, but I just want to be sure everything went well).
    The activity I'm launching in my AndroidManifest is this one "unity3d.player.UnityPlayerActivity".

    I'm using Unity 2019.4.24f1 and UTNotifications 1.8.4

    Thank you for your help!
     
  14. Yuriy-Ivanov

    Yuriy-Ivanov

    Joined:
    Jun 12, 2015
    Posts:
    495
    Hi @Kaiymu_ ,

    May I know what target device(s) you're testing it against? Specifically, there is a number of devices that kill any non-explicitly-whitelisted applications, including their background activities, as soon as their Android Activities (i.e. visible windows) are finished. See also: https://stackoverflow.com/questions...ith-huaweis-and-xiaomis-battery-optimizations. Fortunately most devices display scheduled and push notifications just fine when the app is closed or hidden normally. In the same time, force-killing apps (f.e. by stopping them in system settings) is designed by Google to prevent any their activity, including receiving and showing notifications, so it's expected behavior on any Android device.

    Please let me know if it's not your case, further research will be needed then - we'll need a repro Unity project in this case.

    Best regards,
    Yuriy, Universal Tools team.
     
  15. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,939
    Hi @Yuriy-Ivanov
    I upgraded project to 2020.1 and UT is causing issues
    Assets\UTNotifications\Src\Settings.cs(1286,69): error CS0619: 'AndroidMinification' is obsolete: 'AndroidMinification enum is obsolete.'

    Please advise
     
  16. MuzaibRanjha

    MuzaibRanjha

    Joined:
    Aug 28, 2017
    Posts:
    6
    Firebase Images are not showing in the notifications.

    Local notifications with Images are working.
     
  17. GO4MG

    GO4MG

    Joined:
    Sep 25, 2017
    Posts:
    3
    Hello,

    I've encountered this problem before on android device. I fixed it, source of issue was payload.
    But on iOS device, I think my payload is not wrong, when app is running background it is working properly.

    My apns payload:

    {
    "aps": {
    "alert": {
    "body": "Egemen wants to play with you"
    },
    "type": "gameInvite",
    "roomId": "104",
    "joinToken": "j7dVdbvZ3S",
    "displayName": "Egemen"
    }
    }
     
  18. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,939
    Hi @Yuriy-Ivanov
    There is no support for 2020.1 even though Unity 2020.2 is alaso available on beta.
    I'd really appreciate if you share the status regarding 2020.1? i really dont want to move to other plugin.
    Thanks
     
  19. faveris_dt

    faveris_dt

    Joined:
    Sep 13, 2017
    Posts:
    6
    Hi @Yuriy-Ivanov

    I've tried to reach you via email and github (https://github.com/universal-tools/UTNotificationsFeedback/issues/132) but got no answer.

    We can't release our application on Microsoft Store because Windows App Certification is failed with these errors:

    I've tried to pass certification on empty project and I have no such issues until UTNotification is installed. I've also made some experiments and discovered that these issues are related to UTNotifications.winmd.

    We are using Unity 2018.4.23f1 but I think it doesn't matter.
     
  20. DryHeat

    DryHeat

    Joined:
    Jul 31, 2012
    Posts:
    4
    I have also tried to contact support through email, but no response. Has anyone been able to get Push Notifications to work on iOS with Unity 2020?

    I recently purchased UTNotifications for a project I am working on, but am having some difficulty getting the push notifications to send to the device.
    I have been using Firebase cloud messaging to send push notifications, but I wanted to be able to send them from my application instead of just from the Firebase console.
    (Ideally, it would be great if UTNotifications could just use firebase to send my iOS push notifications)
    The iOS notifications do work properly when I send them from Firebase console, so I know the APNs auth key and xcode project are configured properly.
    The demo server says.
    << /notify title=Hey&text=Hey&id=1&badge=-1&_NO_CACHE=0.6882899
    >> HTTP/1.1 200 OK
    >> Server: UTNotificationsDemoServer
    >> Content-Type: text/html
    >> Content-Length: 18
    >> Connection: close
    >>
    >> Notified 1 clients

    But I do not get the push notification or any indication of any errors sending them push.
    Am I missing something else?
    I am using Unity2020.1.0f1.
     
  21. Andelusiy

    Andelusiy

    Joined:
    Mar 24, 2020
    Posts:
    4
    Good day, Yuriy! Could you help me to get started with UTNotifications please, I tried to use it, but got some problems with Initializing the Manager`s Instance
    upload_2020-10-30_0-15-37.png


    When Im hitting the play Im getting this error in Console

    upload_2020-10-30_0-16-23.png

    Hope you can help me.
     
  22. BBO_Lagoon

    BBO_Lagoon

    Joined:
    Mar 2, 2017
    Posts:
    199
    Hi, I have the following error on the OnPushRegistrationFailed callback on Android :
    Code (CSharp):
    1. java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process com.myorg.mygame. Make sure to call FirebaseApp.initializeApp(Context) first.
    I'm using UTNotification 1.8.4 with Unity 2020.1.11f1

    PS: I had to change some line of code in Settings.cs to get it work with unity 2020.1:
    //line 1297
    Code (CSharp):
    1. //replaced
    2. EditorUserBuildSettings.androidDebugMinification != AndroidMinification.None ||
    3. EditorUserBuildSettings.androidReleaseMinification != AndroidMinification.None
    4.  
    5. //by
    6. PlayerSettings.Android.minifyDebug || PlayerSettings.Android.minifyRelease

    // line 772
    Code (CSharp):
    1. //replaced
    2. PluginImporter pluginImporter = (PluginImporter)AssetImporter.GetAtPath( assetPath );
    3. if (pluginImporter != null && pluginImporter.GetCompatibleWithAnyPlatform())
    4.  
    5. // by
    6. var assetImporter = AssetImporter.GetAtPath( assetPath );
    7. if (assetImporter is PluginImporter pluginImporter && pluginImporter.GetCompatibleWithAnyPlatform())

    --- EDIT ---

    I added the following code in the onCreate Method of my MainActivity and the error is gone.

    Code (CSharp):
    1. FirebaseOptions options = new FirebaseOptions.Builder()
    2.               .setApplicationId("APP_ID")
    3.               .setApiKey("API_KEY")
    4.               .setDatabaseUrl("URL")
    5.               .setStorageBucket("BUCKET")
    6.               .setGcmSenderId("SENDER_ID").build();
    7. FirebaseApp.initializeApp(this, options);
    I receive the device token, but when I send a push notification to this device, no notification appears.

    The result of the sent notification is {"multicast_id":xxxxx,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"xxxxx"}]}.

    Any idea on how I can make it work ?
     
    Last edited: Nov 10, 2020
  23. eugene-l

    eugene-l

    Joined:
    Jan 22, 2020
    Posts:
    1
    Hi @Yuriy-Ivanov, I use OnInitialized event to determine if user Allowed or not Notifications on iOS, like this:

    Code (CSharp):
    1. Manager.Instance.OnInitialized += OnInitialized;
    2.  
    3. _notificationsManager.Initialize(true);
    4.  
    5. private void OnInitialized()
    6.         {
    7.             Log.Warn($"Manager.Instance.Initialized={Manager.Instance.Initialized}");
    8.             Log.Warn($"Manager.Instance.NotificationsEnabled()={Manager.Instance.NotificationsEnabled()}");
    9.             Log.Warn($"Manager.Instance.NotificationsAllowed()={Manager.Instance.NotificationsAllowed()}");
    10.         }
    I need this to have specific logic which depends on the player's input: does he allow or not Push Notifications from the Native iOS PopUp?

    After testing I figured out that OnInitialized event fires before the Native iOS PopUp is shown to the player, so the Manager.Instance.NotificationsAllowed() is always return false at this point.

    My question is: what is the best practice to handle player's decision after Native iOS PopUp is closed and the plugin has correct (updated) state of Manager.Instance.NotificationsAllowed()?

    Thank you.
     
  24. blastproofgames

    blastproofgames

    Joined:
    Apr 3, 2014
    Posts:
    18
    Hello!

    I'm having some issues with the WSA Certification for push notifications.
    More specifically:

    Code (CSharp):
    1.  
    2. Parameter allNotifications of method HandleReceivedNotifications of type UTNotifications.WSA.INotificationToolsStatic in file C:\Program Files\WindowsApps\TiltingPoint.MyWSAApp_1.1.3.0_x64__85kh3h6wfjavg\UTNotifications.winmd references the non-Windows Runtime type UTNotifications.WSA.Notification. Windows Runtime types can reference only Windows Runtime types.
    3. The type UTNotifications.WSA.Notification referenced by type UTNotifications.WSA.INotificationToolsStatic in file C:\Program Files\WindowsApps\TiltingPoint.MyWSAApp_1.1.3.0_x64__85kh3h6wfjavg\UTNotifications.winmd was not found. All types referenced in metadata files must be discoverable.
    4. The type UTNotifications.WSA.Notification referenced by type UTNotifications.WSA.INotificationFactory in file C:\Program Files\WindowsApps\TiltingPoint.MyWSAApp_1.1.3.0_x64__85kh3h6wfjavg\UTNotifications.winmd was not found. All types referenced in metadata files must be discoverable.
    Any ideas?
     
  25. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Hi @Yuriy-Ivanov,

    Is this asset being supported any more? It has doesn't seem to work great with Unity 2020.x. quite a few errors and warnings and doesn't compile on iOS properly any more.
     
    Menion-Leah and jGate99 like this.
  26. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Seems very much like this plugin is dead... I've tried implementing the new mobilenotification package from Unity to make iOS work, as I don't have an issue with Android, but it just crashes when I receive a push for some reason. hard to track down as it just gives me a SIGABRT rather than anything useful
     
  27. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168
    Ok - made a lot of progress on this today - pretty close to having it all working again (at least for the way I'm using it) - I'll share the class when I'm done
     
    nateschmold likes this.
  28. UnityTest12345098

    UnityTest12345098

    Joined:
    Dec 19, 2016
    Posts:
    8
    hi

    OnNotificationClicked doesnt trigger if app was not killed completely and is backgrounded.
    if app was killed and then notif pressed then this gets called ?

    Any work around for iOS
     
    Last edited: Jun 21, 2021
  29. CxydaInno

    CxydaInno

    Joined:
    Sep 5, 2017
    Posts:
    14
    Hey @Yuriy-Ivanov,
    we are using version 1.8.4 and some of our android users get
    Code (CSharp):
    1. UnityLogCrashlyticsException : Exception : Exception: Push notification registration failed. Reason: java.io.IOException: MISSING_INSTANCEID_SERVICE
    besides `MISSING_INSTANCEID_SERVICE` there isn't any hint what's going on. For the vast majority of users it is working so there is no general flaw. Any hints would be appreciated. Thank you

    Best
     
  30. cnfaker

    cnfaker

    Joined:
    Mar 25, 2021
    Posts:
    1
    Hey @Yuriy-Ivanov,
    Calling "PostLocalNotification" is OK, but calling "ScheduleNotificationRepeating" and "ScheduleNotification" have no effect. What is the reason? The "Initialize" function was also called successfully.

    Code (CSharp):
    1.  
    2. Manager.Instance.Initialize(willHandleReceivedNotifications: true);
    3. Manager.Instance.ScheduleNotification(5, 20, title,text, 3, null, "hero");
    4. Manager.Instance.ScheduleNotificationRepeating(10, title,text, 4, null, "hero");
     
    Last edited: Jan 11, 2022
  31. nateschmold

    nateschmold

    Joined:
    May 26, 2015
    Posts:
    14
    Hey man - any chance you'd be willing to share your work on this? Running into some blocks because we need to update unity to 2020 for some things but it breaks UTNotifications. Any help you can give would be massively appreciated!
     
    Menion-Leah likes this.
  32. Kujo87

    Kujo87

    Joined:
    Sep 16, 2013
    Posts:
    168

    Sure - as I say, I'm not sure if the whole thing works as was before, because I mainly use it for remote notifications, but I think it should all be fine. You'll need to install the Mobile Notifications package from Unity.

    Code (csharp):
    1.  
    2. #if !UNITY_EDITOR && UNITY_IOS
    3.  
    4.  
    5. using System.Collections;
    6. using System.Collections.Generic;
    7. using System.Runtime.InteropServices;
    8. using System;
    9. using Newtonsoft.Json;
    10. using Unity.Notifications.iOS;
    11. using UnityEngine;
    12.  
    13. namespace UTNotifications
    14. {
    15.     public class ManagerImpl : Manager
    16.     {
    17.         protected override bool InitializeImpl(bool willHandleReceivedNotifications, int startId = 0, bool incrementalId = false)
    18.         {
    19.             m_enabled = false;
    20.             m_pushEnabled = UnityEngine.PlayerPrefs.GetInt(m_pushEnabledOptionName, 1) != 0;
    21.             SetNotificationsEnabled(UnityEngine.PlayerPrefs.GetInt(m_enabledOptionName, 1) != 0, true);
    22.  
    23.             m_willHandleReceivedNotifications = willHandleReceivedNotifications;
    24.             m_nextPushNotificationId = startId;
    25.             m_incrementalId = incrementalId;
    26.  
    27.             Initialized = true;
    28.  
    29.             // Force an update to get clicked/received notifications as fast as possible.
    30.             LateUpdate();
    31.  
    32.             iOSNotificationCenter.OnNotificationReceived += notification =>
    33.             {
    34.                 List<ReceivedNotification> list;
    35.                 if (m_willHandleReceivedNotifications && OnNotificationsReceivedHasSubscribers())
    36.                 {
    37.                     list = new List<ReceivedNotification>();
    38.                 }
    39.                 else
    40.                 {
    41.                     list = null;
    42.                 }
    43.  
    44.                 if( list == null && !OnNotificationsReceivedHasSubscribers())
    45.                 {
    46.                     return;
    47.  
    48.                 }
    49.  
    50.                 ReceivedNotification receivedNotification = null;
    51.  
    52.                 //Check if the notification was clicked
    53.                 if (OnNotificationClickedHasSubscribers())
    54.                 {
    55.                     int id = ExtractId(notification.Data);
    56.  
    57.                     if (_UT_LocalNotificationWasClicked(id))
    58.                     {
    59.                         receivedNotification = ToReceivedNotification(notification);
    60.                         _OnNotificationClicked(receivedNotification);
    61.  
    62.                         if(list == null)
    63.                         {
    64.                             return;
    65.                         }
    66.                     }
    67.  
    68.                     if(list != null)
    69.                     {
    70.                         if(receivedNotification == null)
    71.                         {
    72.                             receivedNotification = ToReceivedNotification(notification);
    73.                         }
    74.    
    75.                         list.Add(receivedNotification);
    76.                     }
    77.                 }
    78.  
    79.                 if (list != null && list.Count > 0)
    80.                 {
    81.                     HideAllNotifications();
    82.                     _OnNotificationsReceived(list);
    83.                 }
    84.             };
    85.  
    86.             iOSNotificationCenter.OnRemoteNotificationReceived += notification =>
    87.             {
    88.                 List<ReceivedNotification> list;
    89.                 if (m_willHandleReceivedNotifications && OnNotificationsReceivedHasSubscribers())
    90.                 {
    91.                     list = new List<ReceivedNotification>();
    92.                 }
    93.                 else
    94.                 {
    95.                     list = null;
    96.                 }
    97.  
    98.                 if (list == null && !OnNotificationsReceivedHasSubscribers())
    99.                 {
    100.                     return;
    101.                 }
    102.  
    103.                 ReceivedNotification receivedNotification = null;
    104.  
    105.                 //Check if the notification was clicked
    106.                 if (OnNotificationClickedHasSubscribers() && _UT_PushNotificationWasClicked(notification.Body))
    107.                 {
    108.                     receivedNotification = ToReceivedNotification(notification);
    109.                     _OnNotificationClicked(receivedNotification);
    110.  
    111.                     if (list == null)
    112.                     {
    113.                         return;
    114.                     }
    115.                 }
    116.  
    117.                 if (list != null)
    118.                 {
    119.                     if (receivedNotification == null)
    120.                     {
    121.                         receivedNotification = ToReceivedNotification(notification);
    122.                     }
    123.  
    124.                     list.Add(receivedNotification);
    125.                 }
    126.  
    127.                 if (list != null && list.Count > 0)
    128.                 {
    129.                     HideAllNotifications();
    130.                     _OnNotificationsReceived(list);
    131.                 }
    132.             };
    133.  
    134.             return true;
    135.         }
    136.  
    137.         protected override void PostLocalNotificationImpl(LocalNotification notification)
    138.         {
    139.             if (m_enabled)
    140.             {
    141.                 iOSNotificationCenter.ScheduleNotification(ToIOSLocalNotification(notification));
    142.                 //NotificationServices.PresentLocalNotificationNow(ToIOSLocalNotification(notification));
    143.             }
    144.         }
    145.  
    146.         protected override void ScheduleNotificationImpl(ScheduledNotification notification)
    147.         {
    148.             if (m_enabled)
    149.             {
    150.                 iOSNotificationCenter.ScheduleNotification(ToIOSScheduledNotification(notification));
    151.                 // NotificationServices.ScheduleLocalNotification(ToIOSScheduledNotification(notification));
    152.             }
    153.         }
    154.  
    155.         //Please note that the actual interval may be different.
    156.         //On iOS there are only fixed options like every minute, every day, every week and so on. So the provided <c>intervalSeconds</c> value will be approximated by one of the available options.
    157.         protected override void ScheduleNotificationRepeatingImpl(ScheduledRepeatingNotification notification)
    158.         {
    159.             if (m_enabled)
    160.             {
    161.                 iOSNotificationCenter.ScheduleNotification(ToIOSScheduledRepeatingNotification(notification));
    162.                 // NotificationServices.ScheduleLocalNotification(ToIOSScheduledRepeatingNotification(notification));
    163.             }
    164.         }
    165.  
    166.         public override bool NotificationsEnabled()
    167.         {
    168.             if (Initialized)
    169.             {
    170.                 return m_enabled;
    171.             }
    172.             else
    173.             {
    174.                 return UnityEngine.PlayerPrefs.GetInt(m_enabledOptionName, 1) != 0;
    175.             }
    176.         }
    177.  
    178.         public override bool NotificationsAllowed()
    179.         {
    180.             return _UT_NotificationsAllowed();
    181.         }
    182.  
    183.         public override void SetNotificationsEnabled(bool enabled)
    184.         {
    185.             SetNotificationsEnabled(enabled, false);
    186.         }
    187.  
    188.         public override bool PushNotificationsEnabled()
    189.         {
    190.             bool enabled;
    191.             if (Initialized)
    192.             {
    193.                 enabled = m_pushEnabled;
    194.             }
    195.             else
    196.             {
    197.                 enabled = UnityEngine.PlayerPrefs.GetInt(m_pushEnabledOptionName, 1) != 0;
    198.             }
    199.  
    200.             return enabled && Settings.Instance.PushNotificationsEnabledIOS && NotificationsEnabled();
    201.         }
    202.  
    203.         public override bool SetPushNotificationsEnabled(bool enabled)
    204.         {
    205.             // Should be done before (enable == m_pushEnabled) check in order to disable push notifications before Manager initialization
    206.             UnityEngine.PlayerPrefs.SetInt(m_pushEnabledOptionName, enabled ? 1 : 0);
    207.  
    208.             if (enabled && !Settings.Instance.PushNotificationsEnabledIOS)
    209.             {
    210.                 UnityEngine.Debug.LogWarning("Can't enable push notifications: iOS -> Push Notifications are disabled in the UTNotifications Settings");
    211.             }
    212.            
    213.             if (!Initialized || enabled == m_pushEnabled)
    214.             {
    215.                 return PushNotificationsEnabled();
    216.             }
    217.            
    218.             m_pushEnabled = enabled;
    219.  
    220.             if (m_enabled && Settings.Instance.PushNotificationsEnabledIOS)
    221.             {
    222.                 if (m_pushEnabled)
    223.                 {
    224.                     RegisterForNotifications();
    225.                 }
    226.                 else
    227.                 {
    228.                     //UnityEngine.iOS.NotificationServices.UnregisterForRemoteNotifications();
    229.                 }
    230.             }
    231.  
    232.             return PushNotificationsEnabled();
    233.         }
    234.  
    235.         protected override void CancelNotificationImpl(int id)
    236.         {
    237.             string idAsString = id.ToString();
    238.  
    239.             string position = "";
    240.             try
    241.             {
    242.                 if (iOSNotificationCenter.GetScheduledNotifications() != null)
    243.                 {
    244.                     position = "start foreach";
    245.                     foreach (var notification in iOSNotificationCenter.GetScheduledNotifications())
    246.                     {
    247.                         position = $"Get userinfo dictionary - {notification.Data}";
    248.                         var userInfo = UserInfoToDictionaryOfStrings(notification.Data);
    249.                         if (userInfo.ContainsKey(m_idKeyName) && userInfo[m_idKeyName] == idAsString)
    250.                         {
    251.                             position = $"Attempt to remove the notification - {notification.Identifier}";
    252.                             iOSNotificationCenter.RemoveScheduledNotification(notification.Identifier);
    253.                             return;
    254.                         }
    255.                     }
    256.                 }
    257.             }
    258.             catch(Exception e)
    259.             {
    260.                 Debug.LogError($"FAiled to cancel notification: {id} - {e.Message} - {position}");
    261.             }
    262.         }
    263.  
    264.         public override void HideNotification(int id)
    265.         {
    266.             if (!CheckInitialized())
    267.             {
    268.                 return;
    269.             }
    270.            
    271.             if (iOSNotificationCenter.GetScheduledNotifications() == null)
    272.             {
    273.                 return;
    274.             }
    275.  
    276.             foreach (var notification in iOSNotificationCenter.GetScheduledNotifications())
    277.             {
    278.                 if (notification.Identifier == id.ToString())
    279.                 {
    280.                     HideNotification(notification);
    281.                     return;
    282.                 }
    283.             }
    284.         }
    285.  
    286.         public override void HideAllNotifications()
    287.         {
    288.             if (!CheckInitialized())
    289.             {
    290.                 return;
    291.             }
    292.            
    293.             if (iOSNotificationCenter.GetScheduledNotifications() != null)
    294.             {
    295.                 foreach (var notification in iOSNotificationCenter.GetScheduledNotifications())
    296.                 {
    297.                     HideNotification(notification);
    298.                 }
    299.                 iOSNotificationCenter.RemoveAllScheduledNotifications();
    300.                
    301.             }
    302.  
    303.             if(iOSNotificationCenter.GetDeliveredNotifications() != null)
    304.             {
    305.                 foreach(var notification in iOSNotificationCenter.GetDeliveredNotifications())
    306.                 {
    307.                     HideNotification(notification);
    308.                 }
    309.  
    310.                 iOSNotificationCenter.RemoveAllDeliveredNotifications();
    311.             }
    312.  
    313.             _UT_HideAllNotifications();
    314.         }
    315.  
    316.         protected override void CancelAllNotificationsImpl()
    317.         {
    318.             HideAllNotifications();
    319.             iOSNotificationCenter.RemoveAllScheduledNotifications();
    320.             iOSNotificationCenter.RemoveAllDeliveredNotifications();
    321.         }
    322.  
    323.         protected override bool CleanupObsoleteScheduledNotifications(List<ScheduledNotification> scheduledNotifications)
    324.         {
    325.             if (Initialized && m_enabled)
    326.             {
    327.                 var scheduledIds = new HashSet<string>();
    328.                 foreach (var notification in iOSNotificationCenter.GetScheduledNotifications())
    329.                 {
    330.                     scheduledIds.Add(notification.Identifier);
    331.                 }
    332.  
    333.                 return scheduledNotifications.RemoveAll((it) => !scheduledIds.Contains(it.id.ToString())) > 0;
    334.             }
    335.             else
    336.             {
    337.                 DateTime now = DateTime.Now;
    338.                 return scheduledNotifications.RemoveAll((it) => !it.IsRepeating && it.triggerDateTime < now) > 0;
    339.             }
    340.         }
    341.  
    342.         public override int GetBadge()
    343.         {
    344.             if (!CheckInitialized())
    345.             {
    346.                 return 0;
    347.             }
    348.            
    349.             return Math.Max(UnityEngine.PlayerPrefs.GetInt(m_badgeOptionName, 0), _UT_GetIconBadgeNumber());
    350.         }
    351.  
    352.         public override void SetBadge(int bandgeNumber)
    353.         {
    354.             if (!CheckInitialized())
    355.             {
    356.                 return;
    357.             }
    358.            
    359.             if (m_enabled)
    360.             {
    361.                 _UT_SetIconBadgeNumber(bandgeNumber);
    362.             }
    363.  
    364.             UnityEngine.PlayerPrefs.SetInt(m_badgeOptionName, bandgeNumber);
    365.         }
    366.  
    367.         public override void SubscribeToTopic(string topic)
    368.         {
    369.             NotSupported("topics");
    370.         }
    371.  
    372.         public override void UnsubscribeFromTopic(string topic)
    373.         {
    374.             NotSupported("topics");
    375.         }
    376.  
    377.     //protected
    378.         protected void LateUpdate()
    379.         {
    380.             if (!Initialized)
    381.             {
    382.                 return;
    383.             }
    384.            
    385.            
    386.             CleanupDuplications();
    387.  
    388.             ////Handle received/clicked notifications
    389.             //int localCount = iOSNotificationCenter.GetDeliveredNotifications() != null ? iOSNotificationCenter.GetDeliveredNotifications().Length : 0;
    390.            
    391.  
    392.             //List<ReceivedNotification> list;
    393.             //if ((localCount > 0) && m_willHandleReceivedNotifications && OnNotificationsReceivedHasSubscribers())
    394.             //{
    395.             //    list = new List<ReceivedNotification>(localCount);
    396.             //}
    397.             //else
    398.             //{
    399.             //    list = null;
    400.             //}
    401.  
    402.             //if (list == null && !OnNotificationClickedHasSubscribers())
    403.             //{
    404.             //    return;
    405.             //}
    406.  
    407.             //if (localCount > 0)
    408.             //{
    409.             //    foreach (var notification in iOSNotificationCenter.GetDeliveredNotifications())
    410.             //    {
    411.             //        ReceivedNotification receivedNotification = null;
    412.  
    413.             //        //Check if the notification was clicked
    414.             //        if (OnNotificationClickedHasSubscribers())
    415.             //        {
    416.             //            int id = ExtractId(notification.Data);
    417.  
    418.             //            if (_UT_LocalNotificationWasClicked(id))
    419.             //            {
    420.             //                receivedNotification = ToReceivedNotification(notification);
    421.             //                _OnNotificationClicked(receivedNotification);
    422.  
    423.             //                if (list == null)
    424.             //                {
    425.             //                    break;
    426.             //                }
    427.             //            }
    428.             //        }
    429.                    
    430.             //        if (list != null)
    431.             //        {
    432.             //            if (receivedNotification == null)
    433.             //            {
    434.             //                receivedNotification = ToReceivedNotification(notification);
    435.             //            }
    436.  
    437.             //            list.Add(receivedNotification);
    438.             //        }
    439.             //    }
    440.             //}
    441.  
    442.             //if (remoteCount > 0)
    443.             //{
    444.             //    foreach (var notification in iOSNotificationCenter.GetDeliveredNotifications())
    445.             //    {
    446.             //        ReceivedNotification receivedNotification = null;
    447.  
    448.             //        //Check if the notification was clicked
    449.             //        if (OnNotificationClickedHasSubscribers() && _UT_PushNotificationWasClicked(notification.Body))
    450.             //        {
    451.             //            receivedNotification = ToReceivedNotification(notification);
    452.             //            _OnNotificationClicked(receivedNotification);
    453.  
    454.             //            if (list == null)
    455.             //            {
    456.             //                break;
    457.             //            }
    458.             //        }
    459.  
    460.             //        if (list != null)
    461.             //        {
    462.             //            if (receivedNotification == null)
    463.             //            {
    464.             //                receivedNotification = ToReceivedNotification(notification);
    465.             //            }
    466.  
    467.             //            list.Add(receivedNotification);
    468.             //        }
    469.             //    }
    470.             //}
    471.  
    472.             //if (list != null && list.Count > 0)
    473.             //{
    474.             //    HideAllNotifications();
    475.             //    _OnNotificationsReceived(list);
    476.             //}
    477.         }
    478.  
    479.     //private
    480.         private void SetNotificationsEnabled(bool enabled, bool inInitialization)
    481.         {
    482.             UnityEngine.PlayerPrefs.SetInt(m_enabledOptionName, enabled ? 1 : 0);
    483.  
    484.             if (!inInitialization && !Initialized)
    485.             {
    486.                 if (!enabled)
    487.                 {
    488.                     //UnityEngine.iOS.NotificationServices.UnregisterForRemoteNotifications();                    
    489.                 }
    490.  
    491.                 return;
    492.             }
    493.  
    494.             if (m_enabled == enabled)
    495.             {
    496.                 return;
    497.             }
    498.  
    499.             if (enabled)
    500.             {
    501.                 RegisterForNotifications();
    502.  
    503.                 if (!inInitialization)
    504.                 {
    505.                     // Reschedule local notifications, if required
    506.                     var scheduledNotifications = ScheduledNotifications;
    507.  
    508.                     if (scheduledNotifications != null && scheduledNotifications.Count > 0)
    509.                     {
    510.                         DateTime nowPlus2Sec = DateTime.Now.AddSeconds(2);
    511.  
    512.                         foreach (var scheduledNotification in scheduledNotifications)
    513.                         {
    514.                             var notification = scheduledNotification.IsRepeating
    515.                                 ? ToIOSScheduledRepeatingNotification((ScheduledRepeatingNotification)scheduledNotification)
    516.                                 : ToIOSScheduledNotification(scheduledNotification);
    517.  
    518.                             // if (notification.fireDate != DateTime.MinValue && notification.fireDate <= nowPlus2Sec)
    519.                             // {
    520.                             //     if (!scheduledNotification.IsRepeating)
    521.                             //     {
    522.                             //         notification.fireDate = nowPlus2Sec;
    523.                             //     }
    524.                             //     else
    525.                             //     {
    526.                             //         notification.fireDate = NextFutureFireDate(notification.fireDate, notification.repeatInterval, nowPlus2Sec);
    527.                             //     }
    528.                             // }
    529.                             //
    530.                             // NotificationServices.ScheduleLocalNotification(notification);
    531.                         }
    532.                     }
    533.  
    534.                     SetBadge(GetBadge());
    535.                 }
    536.             }
    537.             else
    538.             {
    539.                 CancelAllNotificationsImpl();
    540.                 //UnityEngine.iOS.NotificationServices.UnregisterForRemoteNotifications();
    541.                 _UT_SetIconBadgeNumber(0);
    542.             }
    543.  
    544.             m_enabled = enabled;
    545.         }
    546.  
    547.         private ReceivedNotification ToReceivedNotification(iOSNotification notification)
    548.         {
    549.             string title = notification.Title;
    550.             string text = notification.Body;
    551.  
    552.             int id = ExtractId(notification.Data);
    553.  
    554.             LocalNotification localNotification;
    555.  
    556.             if (notification.Trigger is iOSNotificationTimeIntervalTrigger trigger && trigger.TimeInterval.TotalSeconds > 0)
    557.             {
    558.                 if (trigger.Repeats)
    559.                 {
    560.  
    561.                     localNotification = new ScheduledRepeatingNotification(DateTime.Now, (DateTime.Now + trigger.TimeInterval).Second, title, text, id);
    562.                 }
    563.                 else
    564.                 {
    565.                     localNotification = new ScheduledNotification(DateTime.Now, title, text, id);
    566.                 }
    567.             }
    568.             else
    569.             {
    570.                 localNotification = new LocalNotification(title, text, id);
    571.             }
    572.  
    573.             Dictionary<string, string> userData = UserInfoToDictionaryOfStrings(notification.Data);
    574.             if (userData != null)
    575.             {
    576.                 if (userData.ContainsKey(m_idKeyName))
    577.                 {
    578.                     userData.Remove(m_idKeyName);
    579.                 }
    580.            
    581.                 localNotification.SetUserData(userData);
    582.             }
    583.  
    584.             localNotification.SetBadgeNumber(notification.Badge);
    585.            
    586.             return new ReceivedNotification(localNotification);
    587.         }
    588.  
    589.         private iOSNotification ToIOSLocalNotification(LocalNotification notification)
    590.         {
    591.             CancelNotificationImpl(notification.id);
    592.  
    593.             var iosNotification = new iOSNotification();
    594.             if (notification.badgeNumber >= 0)
    595.             {
    596.                 iosNotification.Badge = notification.badgeNumber;
    597.             }
    598.             iosNotification.Title = notification.title;
    599.             iosNotification.Body = notification.text;
    600.  
    601.             // if (!string.IsNullOrEmpty(notification.notificationProfile))
    602.             // {
    603.             //     iosNotification.soundName = m_soundNamePrefix + notification.notificationProfile;
    604.             // }
    605.             // else
    606.             // {
    607.             //     iosNotification.soundName = UnityEngine.iOS.LocalNotification.defaultSoundName;
    608.             // }
    609.             var userInfo = (notification.userData != null) ? new Dictionary<string, string>(notification.userData) : new Dictionary<string, string>();
    610.             userInfo.Add(m_idKeyName, notification.id.ToString());
    611.             userInfo.Add(m_timestampKey, DateTime.UtcNow.ToFileTimeUtc().ToString());
    612.             iosNotification.Data = JsonConvert.SerializeObject(userInfo);
    613.             return iosNotification;
    614.         }
    615.  
    616.         private iOSNotification ToIOSScheduledNotification(ScheduledNotification notification)
    617.         {
    618.             var iosNotification = ToIOSLocalNotification(notification);
    619.  
    620.             var timeTrigger = new iOSNotificationTimeIntervalTrigger()
    621.             {
    622.                 TimeInterval = new TimeSpan(notification.triggerDateTime.Day, notification.triggerDateTime.Hour, notification.triggerDateTime.Minute, notification.triggerDateTime.Second)
    623.             };
    624.             iosNotification.Trigger = timeTrigger;
    625.  
    626.             return iosNotification;
    627.         }
    628.  
    629.         private iOSNotification ToIOSScheduledRepeatingNotification(ScheduledRepeatingNotification notification)
    630.         {
    631.             var iosNotification = ToIOSScheduledNotification(notification);
    632.  
    633.             var timeTrigger = new iOSNotificationTimeIntervalTrigger();
    634.             timeTrigger.Repeats = true;
    635.  
    636.             if (notification.intervalSeconds <= 0)
    637.             {
    638.                 iosNotification.Trigger = timeTrigger;
    639.                 return iosNotification;
    640.             }
    641.  
    642.             if (notification.intervalSeconds < 3)
    643.             {
    644.                 //Approximate it to every second if the desired intervalSeconds is less then 3 seconds
    645.                 // iosNotification.repeatInterval = CalendarUnit.Second;
    646.                 timeTrigger.TimeInterval = new TimeSpan(0, 0, 1);
    647.             }
    648.             else if (notification.intervalSeconds < TimeUtils.MinutesToSeconds(3))
    649.             {
    650.                 //Approximate it to every minute if the desired intervalSeconds is less then 3 minutes
    651.                 // iosNotification.repeatInterval = CalendarUnit.Minute;
    652.                 timeTrigger.TimeInterval = new TimeSpan(0, 1, 0);
    653.             }
    654.             else if (notification.intervalSeconds < TimeUtils.HoursToSeconds(3))
    655.             {
    656.                 //Approximate it to every hour if the desired intervalSeconds is less then 3 hours
    657.                 // iosNotification.repeatInterval = CalendarUnit.Hour;
    658.                 timeTrigger.TimeInterval = new TimeSpan(1, 0, 0);
    659.             }
    660.             else if (notification.intervalSeconds < TimeUtils.DaysToSeconds(3))
    661.             {
    662.                 //Approximate it to every day if the desired intervalSeconds is less then 3 days
    663.                 // iosNotification.repeatInterval = CalendarUnit.Day;
    664.                 timeTrigger.TimeInterval = new TimeSpan(1, 0, 0, 0);
    665.             }
    666.             else if (notification.intervalSeconds < TimeUtils.WeeksToSeconds(3))
    667.             {
    668.                 //Approximate it to every week if the desired intervalSeconds is less then 3 weeks
    669.                 // iosNotification.repeatInterval = CalendarUnit.Week;
    670.                 timeTrigger.TimeInterval = new TimeSpan(7, 0, 0, 0);
    671.             }
    672.             else if (notification.intervalSeconds < TimeUtils.DaysToSeconds(2 * 30))
    673.             {
    674.                 //Approximate it to every month if the desired intervalSeconds is less then 2 months
    675.                 // iosNotification.repeatInterval = CalendarUnit.Month;
    676.                 timeTrigger.TimeInterval = new TimeSpan(30, 0, 0, 0);
    677.             }
    678.             else if (notification.intervalSeconds < TimeUtils.DaysToSeconds(183))
    679.             {
    680.                 //Approximate it to every quarter if the desired intervalSeconds is less then half a year
    681.                 // iosNotification.repeatInterval = CalendarUnit.Quarter;
    682.                 timeTrigger.TimeInterval = new TimeSpan(183, 0, 0, 0);
    683.             }
    684.             else if (notification.intervalSeconds < TimeUtils.DaysToSeconds(3 * 365))
    685.             {
    686.                 //Approximate it to every year if the desired intervalSeconds is less then 3 years
    687.                 //iosNotification.repeatInterval = CalendarUnit.Year;
    688.                 timeTrigger.TimeInterval = new TimeSpan(365, 0, 0, 0);
    689.             }
    690.             else
    691.             {
    692.                 UnityEngine.Debug.LogWarning("Suspicious intervalSeconds value provided: " + notification.intervalSeconds);
    693.                 //iosNotification.repeatInterval = CalendarUnit.Era;
    694.             }
    695.  
    696.             iosNotification.Trigger = timeTrigger;
    697.             return iosNotification;
    698.         }
    699.  
    700.         private void HideNotification(iOSNotification notification)
    701.         {
    702.             var trigger = (iOSNotificationTimeIntervalTrigger)notification.Trigger;
    703.            
    704.             iOSNotificationCenter.RemoveScheduledNotification(notification.Identifier);
    705.             //NotificationServices.CancelLocalNotification(notification);
    706.         }
    707.  
    708.         private static Dictionary<string, string> UserInfoToDictionaryOfStrings(string data)
    709.         {
    710.             var userInfoNode = JSON.Parse(data);
    711.             var userInfo = JsonUtils.ToUserData(userInfoNode);
    712.  
    713.             if (userInfo == null || userInfo.Count == 0)
    714.             {
    715.                 return null;
    716.             }
    717.  
    718.             Dictionary<string, string> userData = new Dictionary<string, string>();
    719.             foreach (var key in userInfo.Keys)
    720.             {
    721.                 if (key != null)
    722.                 {
    723.                     object value = userInfo[key];
    724.                     if (value != null)
    725.                     {
    726.                         userData.Add(key, (string)value);
    727.                     }
    728.                 }
    729.             }
    730.  
    731.             return userData;
    732.         }
    733.  
    734.         private void RegisterForNotifications()
    735.         {
    736.             m_initRemoteNotifications = Settings.Instance.PushNotificationsEnabledIOS && m_pushEnabled;
    737.             //UnityEngine.iOS.NotificationServices.RegisterForNotifications(NotificationType.Badge | NotificationType.Alert | NotificationType.Sound, m_initRemoteNotifications);
    738.  
    739.             StartCoroutine(Register_Local());
    740.             IEnumerator Register_Local()
    741.             {
    742.                 var authorisationOption = AuthorizationOption.Alert | AuthorizationOption.Badge | AuthorizationOption.Sound;
    743.                 using (var req = new AuthorizationRequest(authorisationOption, m_initRemoteNotifications))
    744.                 {
    745.                     while (!req.IsFinished)
    746.                     {
    747.                         yield return null;
    748.                     }
    749.  
    750.                     if (m_initRemoteNotifications)
    751.                     {
    752.                         if (!string.IsNullOrEmpty(req.Error))
    753.                         {
    754.                             m_initRemoteNotifications = false;
    755.                             _OnPushRegistrationFailed(req.Error);
    756.                         }
    757.                         else if (req.DeviceToken != null && req.DeviceToken.Length > 0 && OnSendRegistrationIdHasSubscribers())
    758.                         {
    759.                             m_initRemoteNotifications = false;
    760.                             _OnSendRegistrationId(m_providerName, req.DeviceToken);
    761.                         }
    762.                     }
    763.                 }
    764.             }
    765.         }
    766.  
    767.         private static int ExtractId(string data)
    768.         {
    769.             Dictionary<string, string> userInfo = UserInfoToDictionaryOfStrings(data);
    770.             return userInfo != null && userInfo.ContainsKey(m_idKeyName) ? int.Parse(userInfo[m_idKeyName]) : -1;
    771.         }
    772.  
    773.         private static long ExtractTimestamp(string data)
    774.         {
    775.             Dictionary<string, string> userInfo = UserInfoToDictionaryOfStrings(data);
    776.             return userInfo != null && userInfo.ContainsKey(m_timestampKey) ? long.Parse(userInfo[m_timestampKey]) : 0;
    777.         }
    778.  
    779.         private void CleanupDuplications()
    780.         {
    781.             const float CHECK_INTERVAL = 1.1f;
    782.            
    783.             float time = UnityEngine.Time.unscaledTime;
    784.             if (time - lastDuplicationCheck < CHECK_INTERVAL)
    785.             {
    786.                 return;
    787.             }
    788.             lastDuplicationCheck = time;
    789.            
    790.             var dictionary = new Dictionary<string, List<iOSNotification>>();
    791.             if (iOSNotificationCenter.GetScheduledNotifications() != null)
    792.             {
    793.                 foreach (var notification in iOSNotificationCenter.GetScheduledNotifications())
    794.                 {
    795.                     string id = notification.Identifier != null ? notification.Identifier : "";
    796.                     if (dictionary.ContainsKey(id))
    797.                     {
    798.                         dictionary[id].Add(notification);
    799.                     }
    800.                     else
    801.                     {
    802.                         dictionary.Add(id, new List<iOSNotification>{notification});
    803.                     }
    804.                 }
    805.             }
    806.  
    807.             foreach (var entry in dictionary)
    808.             {
    809.                 var list = entry.Value;
    810.                 if (list.Count > 1)
    811.                 {
    812.                     UnityEngine.Debug.Log("UTNotifications: local notification duplication with id " + entry.Key + " detected. Cleaning up.");
    813.  
    814.                     // Sort by timestamps (newest first)
    815.                     list.Sort((x, y) => ExtractTimestamp(y.Data).CompareTo(ExtractTimestamp(x.Data)));
    816.                     // Remove outdated duplications
    817.                     for (int i = 1; i < list.Count; ++i)
    818.                     {
    819.                         iOSNotificationCenter.RemoveScheduledNotification(list[i].Identifier);
    820.                     }
    821.                 }
    822.             }
    823.         }
    824.  
    825.         [DllImport("__Internal")]
    826.         private static extern int _UT_GetIconBadgeNumber();
    827.  
    828.         [DllImport("__Internal")]
    829.         private static extern void _UT_SetIconBadgeNumber(int value);
    830.  
    831.         [DllImport("__Internal")]
    832.         private static extern void _UT_HideAllNotifications();
    833.  
    834.         [DllImport("__Internal")]
    835.         private static extern bool _UT_LocalNotificationWasClicked(int id);
    836.  
    837.         [DllImport("__Internal")]
    838.         private static extern bool _UT_PushNotificationWasClicked(string body);
    839.  
    840.         [DllImport("__Internal")]
    841.         private static extern bool _UT_NotificationsAllowed();
    842.  
    843.         private const string m_idKeyName = "id";
    844.         private const string m_timestampKey = "created_timestamp";
    845.         private const string m_enabledOptionName = "_UT_NOTIFICATIONS_ENABLED";
    846.         private const string m_pushEnabledOptionName = "_UT_NOTIFICATIONS_PUSH_ENABLED";
    847.         private const string m_badgeOptionName = "_UT_NOTIFICATIONS_BADGE_VALUE";
    848.         private const string m_soundNamePrefix = "Data/Raw/";
    849.         private static readonly string m_providerName = PushNotificationsProvider.APNS.ToString();
    850.         private bool m_willHandleReceivedNotifications;
    851.         private bool m_initRemoteNotifications;
    852.         private int m_nextPushNotificationId;
    853.         private bool m_incrementalId;
    854.         private bool m_enabled = false;
    855.         private bool m_pushEnabled = false;
    856.         private float lastDuplicationCheck = 0;
    857.     }
    858. }
    859. #endif
    860.  
    I think its just this class, but if there's any issues, let me know.
     
  33. lntoan123

    lntoan123

    Joined:
    Apr 1, 2019
    Posts:
    15
    Hi @Yuriy-Ivanov, I purchased UTNotification on AssetStore unity. Everything work well, but i got issue:
    I customize icon_small and icon_large on setting notification like attached image, but it just show default icon
    (I am using unity 2020.3.25f1 and UTNotification version is 1.7.3).
    I hope you can help me solve this problem.
    Thanks!

    unnamed (1).png unnamed.png
     
  34. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    388
    Hi, what is the state of this plugin? It's still being sold on the Asset Store, but the last update is from back in 2019. We want to update our existing app to Unity 2021.
     
  35. waldgeist

    waldgeist

    Joined:
    May 6, 2017
    Posts:
    388
    Hey, since there seems to be no support for this plugin and Unity has already pulled it from the Asset store: Is there a chance to release the source code to the public? Our app relies on this package, so I'd like to be able to fork it and patch it to newer Unity releases. Thank you.
     
    jeromeWork likes this.