using System; using UnityEngine; using UnityEngine.TestTools; using NUnit.Framework; using System.Collections; using Unity.Notifications.Android; class AndroidNotificationSendingTests { const string kDefaultTestChannel = "default_test_channel"; class NotificationReceivedHandler { public int receivedNotificationCount = 0; public AndroidNotificationIntentData lastNotification; public void OnReceiveNotification(AndroidNotificationIntentData data) { ++receivedNotificationCount; lastNotification = data; } } NotificationReceivedHandler currentHandler; [OneTimeSetUp] public void BeforeAllTests() { #if !UNITY_EDITOR var c = new AndroidNotificationChannel(); c.Id = kDefaultTestChannel; c.Name = "Default Channel 5"; c.Description = "test_channel 5"; c.Importance = Importance.High; AndroidNotificationCenter.RegisterNotificationChannel(c); #endif } [OneTimeTearDown] public void AfterAllTests() { AndroidNotificationCenter.CancelAllNotifications(); } [SetUp] public void BeforeEachTest() { #if !UNITY_EDITOR AndroidNotificationCenter.CancelAllNotifications(); currentHandler = new NotificationReceivedHandler(); AndroidNotificationCenter.OnNotificationReceived += currentHandler.OnReceiveNotification; #endif } [TearDown] public void AfterEachTest() { #if !UNITY_EDITOR AndroidNotificationCenter.OnNotificationReceived -= currentHandler.OnReceiveNotification; currentHandler = null; #endif } IEnumerator WaitForNotification(float timeout) { float passed = 0.0f; int notificationCount = currentHandler.receivedNotificationCount; while (notificationCount == currentHandler.receivedNotificationCount && passed < timeout) { yield return null; passed += Time.deltaTime; } if (passed > timeout) Debug.LogWarning("Timeout waiting for notification"); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotificationExplicitID_NotificationIsReceived() { int originalId = 456; var n = new AndroidNotification(); n.Title = "SendNotificationExplicitID_NotificationIsReceived : " + originalId.ToString(); n.Text = "SendNotificationExplicitID_NotificationIsReceived Text"; n.FireTime = System.DateTime.Now; n.Group = "test.dummy.group"; Debug.LogWarning("SendNotificationExplicitID_NotificationIsReceived sends notification with ID " + originalId); AndroidNotificationCenter.SendNotificationWithExplicitID(n, kDefaultTestChannel, originalId); yield return WaitForNotification(8.0f); Debug.LogWarning("SendNotificationExplicitID_NotificationIsReceived completed. Received notifications: " + currentHandler.receivedNotificationCount); Assert.AreEqual(1, currentHandler.receivedNotificationCount); Assert.AreEqual(originalId, currentHandler.lastNotification.Id); Assert.AreEqual(n.Group, currentHandler.lastNotification.Notification.Group); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotification_NotificationIsReceived() { var n = new AndroidNotification(); n.Title = "SendNotification_NotificationIsReceived"; n.Text = "SendNotification_NotificationIsReceived Text"; n.FireTime = System.DateTime.Now; Debug.LogWarning("SendNotification_NotificationIsReceived sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return WaitForNotification(8.0f); Debug.LogWarning("SendNotification_NotificationIsReceived completed. Received notifications: " + currentHandler.receivedNotificationCount); Assert.AreEqual(1, currentHandler.receivedNotificationCount); Assert.AreEqual(originalId, currentHandler.lastNotification.Id); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotificationAndCancelNotification_NotificationIsNotReceived() { var n = new AndroidNotification(); n.Title = "SendNotificationAndCancelNotification_NotificationIsNotReceived"; n.Text = "SendNotificationAndCancelNotification_NotificationIsNotReceived Text"; n.FireTime = System.DateTime.Now.AddSeconds(2.0f); Debug.LogWarning("SendNotificationAndCancelNotification_NotificationIsNotReceived sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return null; AndroidNotificationCenter.CancelScheduledNotification(originalId); yield return WaitForNotification(8.0f); Debug.LogWarning("SendNotificationAndCancelNotification_NotificationIsNotReceived completed."); Assert.AreEqual(0, currentHandler.receivedNotificationCount); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator ScheduleRepeatableNotification_NotificationsAreReceived() { var n = new AndroidNotification(); n.Title = "Repeating Notification Title"; n.Text = "Repeating Notification Text"; n.FireTime = System.DateTime.Now.AddSeconds(2); n.RepeatInterval = new System.TimeSpan(0, 0, 5); // interval needs to be quite big for test to be reliable Debug.LogWarning("ScheduleRepeatableNotification_NotificationsAreReceived sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); // we use inexact scheduling, so repeated notification may take a while to appear // inexact also can group, so for test purposes we only check that it repeats at least once yield return WaitForNotification(120.0f); yield return WaitForNotification(120.0f); AndroidNotificationCenter.CancelScheduledNotification(originalId); Debug.LogWarning("ScheduleRepeatableNotification_NotificationsAreReceived completed"); Assert.GreaterOrEqual(currentHandler.receivedNotificationCount, 2); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator NotificationIsScheduled_NotificationStatusIsCorrectlyReported() { var n = new AndroidNotification(); n.Title = "NotificationStatusIsCorrectlyReported"; n.Text = "NotificationStatusIsCorrectlyReported"; n.FireTime = System.DateTime.Now.AddSeconds(2f); Debug.LogWarning("NotificationIsScheduled_NotificationStatusIsCorrectlyReported sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return null; var status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Scheduled, status); yield return WaitForNotification(120.0f); yield return new WaitForSeconds(1.0f); // give some time for Status Bar to update status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Delivered, status); AndroidNotificationCenter.CancelNotification(originalId); yield return new WaitForSeconds(1.5f); status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Unknown, status); Debug.LogWarning("NotificationIsScheduled_NotificationStatusIsCorrectlyReported completed"); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator ArrivedAndUserDismissedNotification_DoesNotReportStatusAsScheduled() { var n = new AndroidNotification("ArrivedNotificationAndDissmissed", "ArrivedNotificationAndDissmissed", System.DateTime.Now); yield return DismissedNotification_DoesNotReportStatusAsScheduled(n); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator ArrivedAndUserDismissedScheduledNotification_DoesNotReportStatusAsScheduled() { var n = new AndroidNotification("ArrivedNotificationAndDissmissedScheduled", "ArrivedNotificationAndDissmissedScheduled", System.DateTime.Now.AddSeconds(2)); yield return DismissedNotification_DoesNotReportStatusAsScheduled(n); } public IEnumerator DismissedNotification_DoesNotReportStatusAsScheduled(AndroidNotification n) { int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return WaitForNotification(8.0f); Assert.AreEqual(1, currentHandler.receivedNotificationCount); AndroidNotificationCenter.CancelDisplayedNotification(originalId); yield return new WaitForSeconds(2.0f); // cancel is async var status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Unknown, status); // now simulate app kill and restart, where notifications are loaded from persistent storage using var managerClass = new AndroidJavaClass("com.unity.androidnotifications.UnityNotificationManager"); using var manager = managerClass.GetStatic("mUnityNotificationManager"); using var backgroundThread = manager.Get("mBackgroundThread"); using var scheduledNotifications = manager.Get("mScheduledNotifications"); scheduledNotifications.Call("clear"); backgroundThread.Call("loadNotifications"); status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Unknown, status); } [Test] [UnityPlatform(RuntimePlatform.Android)] public void CreateNotificationChannelWithInitializedSettings_ChannelSettingsAreSaved() { var chOrig = new AndroidNotificationChannel(); chOrig.Id = "test_channel_settings_are_saved_0"; chOrig.Name = "spam Channel"; chOrig.Description = "Generic spam"; chOrig.Importance = Importance.High; chOrig.CanBypassDnd = true; chOrig.CanShowBadge = true; chOrig.EnableLights = true; chOrig.EnableVibration = false; // this opne should be read-only, it reports the system setting, but can't be set // chOrig.LockScreenVisibility = LockScreenVisibility.Private; AndroidNotificationCenter.RegisterNotificationChannel(chOrig); var ch = AndroidNotificationCenter.GetNotificationChannel(chOrig.Id); Assert.AreEqual(chOrig.Id, ch.Id); Assert.AreEqual(chOrig.Name, ch.Name); Assert.AreEqual(chOrig.Description, ch.Description); Assert.AreEqual(chOrig.Importance, ch.Importance); Assert.AreEqual(chOrig.EnableLights, ch.EnableLights); Assert.AreEqual(chOrig.EnableVibration, ch.EnableVibration); //Assert.AreEqual(chOrig.LockScreenVisibility, ch.LockScreenVisibility); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotification_NotificationIsReceived_CallMainThread() { var gameObjects = new GameObject[1]; AndroidNotificationCenter.NotificationReceivedCallback receivedNotificationHandler = delegate (AndroidNotificationIntentData data) { gameObjects[0] = new GameObject(); gameObjects[0].name = "Hello_World"; Assert.AreEqual("Hello_World", gameObjects[0].name); }; var n = new AndroidNotification(); n.Title = "SendNotification_NotificationIsReceived"; n.Text = "SendNotification_NotificationIsReceived Text"; n.FireTime = System.DateTime.Now; Debug.LogWarning("SendNotification_NotificationIsReceived_CallMainThread sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); AndroidNotificationCenter.OnNotificationReceived += receivedNotificationHandler; yield return WaitForNotification(8.0f); Debug.LogWarning("SendNotification_NotificationIsReceived_CallMainThread completed"); AndroidNotificationCenter.OnNotificationReceived -= receivedNotificationHandler; Assert.AreEqual(1, currentHandler.receivedNotificationCount); Assert.AreEqual(originalId, currentHandler.lastNotification.Id); Assert.IsNotNull(gameObjects[0]); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotification_CanAccessNativeBuilder() { var n = new AndroidNotification(); n.Title = "SendNotification_CanAccessNativeBuilder"; n.Text = "SendNotification_CanAccessNativeBuilder Text"; n.FireTime = System.DateTime.Now; Debug.LogWarning("SendNotification_CanAccessNativeBuilder sends notification"); using (var builder = AndroidNotificationCenter.CreateNotificationBuilder(n, kDefaultTestChannel)) { using (var extras = builder.Call("getExtras")) { extras.Call("putString", "notification.test.string", "TheTest"); } AndroidNotificationCenter.SendNotification(builder); } yield return WaitForNotification(8.0f); Debug.LogWarning("SendNotification_CanAccessNativeBuilder completed"); Assert.AreEqual(1, currentHandler.receivedNotificationCount); using (var extras = currentHandler.lastNotification.NativeNotification.Get("extras")) { Assert.AreEqual("TheTest", extras.Call("getString", "notification.test.string")); } } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotification_CanReschedule() { var managerClass = new AndroidJavaClass("com.unity.androidnotifications.UnityNotificationManager"); var rebootClass = new AndroidJavaClass("com.unity.androidnotifications.UnityNotificationRestartReceiver"); AndroidJavaObject context; using (var unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { using (var activity = unityPlayer.GetStatic("currentActivity")) context = activity.Call("getApplicationContext"); } var n = new AndroidNotification(); n.Title = "SendNotification_CanReschedule"; n.Text = "SendNotification_CanReschedule Text"; n.FireTime = System.DateTime.Now.AddSeconds(5); Debug.LogWarning("SendNotification_CanReschedule sends notification"); int id = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return new WaitForSeconds(0.2f); var manager = managerClass.GetStatic("mUnityNotificationManager"); // clear cached notifications to not mess up future tests manager.Get("mScheduledNotifications").Call("clear"); // simulate reboot by directly cancelling scheduled alarms preserving saves manager.Call("cancelPendingNotificationIntent", id); // temporary null the manager, cause that's what we have in reality managerClass.SetStatic("mUnityNotificationManager", null); yield return new WaitForSeconds(0.2f); // simulate reboot by calling reschedule method, that is called after reboot rebootClass.CallStatic("rescheduleSavedNotifications", context); var newManager = managerClass.GetStatic("mUnityNotificationManager"); // new manager was supposed to be created, assign callback from original one to get notifications newManager.Set("mNotificationCallback", manager.Get("mNotificationCallback")); yield return WaitForNotification(120.0f); Debug.LogWarning("SendNotification_CanReschedule completed"); // restore manager (to not ruin other tests) managerClass.SetStatic("mUnityNotificationManager", manager); Assert.AreEqual(1, currentHandler.receivedNotificationCount); } bool RescheduleNotification(AndroidNotification notification) { AndroidJavaObject manager, currentTime; using (var managerClass = new AndroidJavaClass("com.unity.androidnotifications.UnityNotificationManager")) manager = managerClass.GetStatic("mUnityNotificationManager"); var rebootClass = new AndroidJavaClass("com.unity.androidnotifications.UnityNotificationRestartReceiver"); using (var calendarClass = new AndroidJavaClass("java.util.Calendar")) { using (var calendar = calendarClass.CallStatic("getInstance")) currentTime = calendar.Call("getTime"); } using var builder = AndroidNotificationCenter.CreateNotificationBuilder(789, notification, kDefaultTestChannel); var result = rebootClass.CallStatic("rescheduleNotification", manager, currentTime, builder); manager.Dispose(); currentTime.Dispose(); return result; } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator RescheduleNotification_ExpiredMomentAgo_SendsNotification() { var n = new AndroidNotification(); n.Title = "JustExpired"; n.Text = "Should be sent"; n.FireTime = System.DateTime.Now.AddMinutes(-1); var result = RescheduleNotification(n); Assert.IsTrue(result); yield return WaitForNotification(5.0f); Assert.AreEqual(1, currentHandler.receivedNotificationCount); var received = currentHandler.lastNotification.Notification; Assert.AreEqual("JustExpired", received.Title); } [Test] [UnityPlatform(RuntimePlatform.Android)] public void RescheduleNotification_ExpiredNotification_DoesNotReschedule() { var n = new AndroidNotification(); n.Title = "LongExpired"; n.Text = "Should NOT be sent"; n.FireTime = System.DateTime.Now.AddHours(-1); var result = RescheduleNotification(n); Assert.IsFalse(result); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendNotificationNotShownInForeground_IsDeliveredButNotShown() { var n = new AndroidNotification(); n.Title = "SendNotificationNotShownInForeground_ISDeliveredButNotShown"; n.Text = "SendNotificationNotShownInForeground_ISDeliveredButNotShown Text"; n.FireTime = System.DateTime.Now; n.ShowInForeground = false; Debug.LogWarning("SendNotificationNotShownInForeground_ISDeliveredButNotShown sends notification"); int originalId = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return WaitForNotification(5.0f); Debug.LogWarning("SendNotificationNotShownInForeground_ISDeliveredButNotShown sends completed"); Assert.AreEqual(1, currentHandler.receivedNotificationCount); yield return new WaitForSeconds(2.0f); // give some time, since on some devices we don't immediately get infor on delivered notifications var status = AndroidNotificationCenter.CheckScheduledNotificationStatus(originalId); Assert.AreEqual(NotificationStatus.Unknown, status); // status should be unknown, rather than Delivered } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendBigPictureNotification_Roundtrip() { var n = new AndroidNotification("SendBigPictureNotification_Roundtrip", "SendBigPictureNotification_Roundtrip text", DateTime.Now); n.BigPicture = new BigPictureStyle() { LargeIcon = "icon_1", Picture = "icon_0", ContentTitle = "ContentTitle", ContentDescription = "ContentDescription", SummaryText = "summary", ShowWhenCollapsed = true, }; Debug.LogWarning("SendBigPictureNotification_Roundtrip send"); int id = AndroidNotificationCenter.SendNotification(n, kDefaultTestChannel); yield return WaitForNotification(8.0f); Assert.AreEqual(1, currentHandler.receivedNotificationCount); var received = currentHandler.lastNotification.Notification; Assert.AreEqual("SendBigPictureNotification_Roundtrip", received.Title); Assert.AreEqual("SendBigPictureNotification_Roundtrip text", received.Text); Assert.AreEqual(NotificationStyle.BigPictureStyle, received.Style); var bigPicture = received.BigPicture; Assert.IsTrue(bigPicture.HasValue); var bigPictureData = bigPicture.Value; Assert.AreEqual("icon_1", bigPictureData.LargeIcon); Assert.AreEqual("icon_0", bigPictureData.Picture); Assert.AreEqual("ContentTitle", bigPictureData.ContentTitle); Assert.AreEqual("ContentDescription", bigPictureData.ContentDescription); Assert.AreEqual("summary", bigPictureData.SummaryText); Assert.IsTrue(bigPictureData.ShowWhenCollapsed); } [UnityTest] [UnityPlatform(RuntimePlatform.Android)] public IEnumerator SendAndReplaceNotification() { var original = new AndroidNotification("NotificationToBeReplaced", "This should be replaced", DateTime.Now.AddSeconds(5)); int id = AndroidNotificationCenter.SendNotification(original, kDefaultTestChannel); yield return new WaitForSeconds(1); var replacement = new AndroidNotification("ReplacementNotification", "Replacement text", DateTime.Now.AddSeconds(3)); AndroidNotificationCenter.UpdateScheduledNotification(id, replacement, kDefaultTestChannel); yield return WaitForNotification(8.0f); Assert.AreEqual(1, currentHandler.receivedNotificationCount); var received = currentHandler.lastNotification.Notification; Assert.AreEqual(replacement.Title, received.Title); Assert.AreEqual(replacement.Text, received.Text); } }