| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package androidx.core.app; |
| |
| import static androidx.core.app.NotificationCompat.DEFAULT_ALL; |
| import static androidx.core.app.NotificationCompat.DEFAULT_LIGHTS; |
| import static androidx.core.app.NotificationCompat.DEFAULT_SOUND; |
| import static androidx.core.app.NotificationCompat.DEFAULT_VIBRATE; |
| import static androidx.core.app.NotificationCompat.GROUP_ALERT_ALL; |
| import static androidx.core.app.NotificationCompat.GROUP_ALERT_CHILDREN; |
| import static androidx.core.app.NotificationCompat.GROUP_ALERT_SUMMARY; |
| import static androidx.core.app.NotificationCompat.GROUP_KEY_SILENT; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import android.app.Notification; |
| import android.app.NotificationChannel; |
| import android.app.NotificationManager; |
| import android.app.PendingIntent; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.graphics.BitmapFactory; |
| import android.graphics.Color; |
| import android.media.AudioAttributes; |
| import android.media.AudioManager; |
| import android.net.Uri; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.support.v4.BaseInstrumentationTestCase; |
| |
| import androidx.core.R; |
| import androidx.core.app.NotificationCompat.MessagingStyle.Message; |
| import androidx.core.content.LocusIdCompat; |
| import androidx.core.graphics.drawable.IconCompat; |
| import androidx.test.ext.junit.runners.AndroidJUnit4; |
| import androidx.test.filters.SdkSuppress; |
| import androidx.test.filters.SmallTest; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| |
| @RunWith(AndroidJUnit4.class) |
| @SmallTest |
| public class NotificationCompatTest extends BaseInstrumentationTestCase<TestActivity> { |
| private static final String TEXT_RESULT_KEY = "text"; |
| private static final String DATA_RESULT_KEY = "data"; |
| private static final String EXTRA_COLORIZED = "android.colorized"; |
| |
| Context mContext; |
| |
| public NotificationCompatTest() { |
| super(TestActivity.class); |
| } |
| |
| @Before |
| public void setup() { |
| mContext = mActivityTestRule.getActivity(); |
| } |
| |
| @Test |
| public void testBadgeIcon() throws Throwable { |
| int badgeIcon = NotificationCompat.BADGE_ICON_SMALL; |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setBadgeIconType(badgeIcon) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(badgeIcon, NotificationCompat.getBadgeIconType(n)); |
| } else { |
| assertEquals(NotificationCompat.BADGE_ICON_NONE, |
| NotificationCompat.getBadgeIconType(n)); |
| } |
| } |
| |
| @Test |
| public void testTimeout() throws Throwable { |
| long timeout = 23552; |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setTimeoutAfter(timeout) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(timeout, NotificationCompat.getTimeoutAfter(n)); |
| } else { |
| assertEquals(0, NotificationCompat.getTimeoutAfter(n)); |
| } |
| } |
| |
| @Test |
| public void testShortcutId() throws Throwable { |
| String shortcutId = "fgdfg"; |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setShortcutId(shortcutId) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(shortcutId, NotificationCompat.getShortcutId(n)); |
| } else { |
| assertEquals(null, NotificationCompat.getShortcutId(n)); |
| } |
| } |
| |
| @Test |
| public void testLocusId() throws Throwable { |
| final LocusIdCompat locusId = new LocusIdCompat("Chat_A_B"); |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setLocusId(locusId) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 29) { |
| assertEquals(locusId, NotificationCompat.getLocusId(n)); |
| } else { |
| assertEquals(null, NotificationCompat.getLocusId(n)); |
| } |
| } |
| |
| @Test |
| public void testNotificationChannel() throws Throwable { |
| String channelId = "new ID"; |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setChannelId(channelId) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(channelId, NotificationCompat.getChannelId(n)); |
| } else { |
| assertNull(NotificationCompat.getChannelId(n)); |
| } |
| } |
| |
| @Test |
| public void testNotificationChannel_assignedFromBuilder() throws Throwable { |
| String channelId = "new ID"; |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity(), channelId) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(channelId, NotificationCompat.getChannelId(n)); |
| } else { |
| assertNull(NotificationCompat.getChannelId(n)); |
| } |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_assignsColorized() throws Throwable { |
| Notification n = newNotificationBuilder().setColorized(true).build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| Bundle extras = NotificationCompat.getExtras(n); |
| assertTrue(Boolean.TRUE.equals(extras.get(EXTRA_COLORIZED))); |
| } |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_unassignesColorized() throws Throwable { |
| Notification n = newNotificationBuilder().setColorized(false).build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| Bundle extras = NotificationCompat.getExtras(n); |
| assertTrue(Boolean.FALSE.equals(extras.get(EXTRA_COLORIZED))); |
| } |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_doesntAssignColorized() throws Throwable { |
| Notification n = newNotificationBuilder().build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| Bundle extras = NotificationCompat.getExtras(n); |
| assertFalse(extras.containsKey(EXTRA_COLORIZED)); |
| } |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_copiesIcon() { |
| NotificationCompat.Action a = new NotificationCompat.Action.Builder( |
| R.drawable.notification_action_background, "title", null).build(); |
| assertEquals(R.drawable.notification_action_background, a.getIconCompat().getResId()); |
| |
| NotificationCompat.Action aCopy = new NotificationCompat.Action.Builder(a).build(); |
| |
| assertEquals(R.drawable.notification_action_background, aCopy.getIconCompat().getResId()); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_copiesRemoteInputs() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .addRemoteInput(new RemoteInput("a", "b", null, false, |
| RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, null, null)).build(); |
| |
| NotificationCompat.Action aCopy = new NotificationCompat.Action.Builder(a).build(); |
| |
| assertSame(a.getRemoteInputs()[0], aCopy.getRemoteInputs()[0]); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_copiesAllowGeneratedReplies() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .setAllowGeneratedReplies(true).build(); |
| |
| NotificationCompat.Action aCopy = new NotificationCompat.Action.Builder(a).build(); |
| |
| assertEquals(a.getAllowGeneratedReplies(), aCopy.getAllowGeneratedReplies()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 24) |
| @Test |
| public void testFrameworkNotificationActionBuilder_setAllowGeneratedRepliesTrue() |
| throws Throwable { |
| Notification notif = new Notification.Builder(mContext) |
| .addAction(new Notification.Action.Builder(0, "title", null) |
| .setAllowGeneratedReplies(true).build()).build(); |
| NotificationCompat.Action action = NotificationCompat.getAction(notif, 0); |
| assertTrue(action.getAllowGeneratedReplies()); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_defaultAllowGeneratedRepliesTrue() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder().build(); |
| |
| assertTrue(a.getAllowGeneratedReplies()); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_defaultShowsUserInterfaceTrue() { |
| NotificationCompat.Action action = newActionBuilder().build(); |
| |
| assertTrue(action.getShowsUserInterface()); |
| } |
| |
| @Test |
| public void testNotificationAction_defaultAllowGeneratedRepliesTrue() throws Throwable { |
| NotificationCompat.Action a = new NotificationCompat.Action(0, null, null); |
| |
| assertTrue(a.getAllowGeneratedReplies()); |
| } |
| |
| @Test |
| public void testNotificationAction_defaultShowsUserInterfaceTrue() { |
| NotificationCompat.Action action = new NotificationCompat.Action(0, null, null); |
| |
| assertTrue(action.getShowsUserInterface()); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_setAllowGeneratedRepliesFalse() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .setAllowGeneratedReplies(false).build(); |
| |
| assertFalse(a.getAllowGeneratedReplies()); |
| } |
| |
| @Test |
| public void testNotificationAction_setShowsUserInterfaceFalse() { |
| NotificationCompat.Action action = newActionBuilder() |
| .setShowsUserInterface(false).build(); |
| |
| assertFalse(action.getShowsUserInterface()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 20) |
| @Test |
| public void testGetActionCompatFromAction_sameIconResourceId() { |
| NotificationCompat.Action action = new NotificationCompat.Action.Builder( |
| R.drawable.notification_bg, "title", null).build(); |
| assertEquals(R.drawable.notification_bg, action.getIconCompat().getResId()); |
| Notification notification = newNotificationBuilder().addAction(action).build(); |
| |
| NotificationCompat.Action result = |
| NotificationCompat.getActionCompatFromAction(notification.actions[0]); |
| |
| assertEquals(R.drawable.notification_bg, result.getIconCompat().getResId()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 20) |
| @Test |
| public void testGetActionCompatFromAction_showsUserInterface() { |
| NotificationCompat.Action action = newActionBuilder() |
| .setShowsUserInterface(false).build(); |
| Notification notification = newNotificationBuilder().addAction(action).build(); |
| NotificationCompat.Action result = |
| NotificationCompat.getActionCompatFromAction(notification.actions[0]); |
| |
| assertFalse(result.getExtras().getBoolean( |
| NotificationCompat.Action.EXTRA_SHOWS_USER_INTERFACE, true)); |
| assertFalse(result.getShowsUserInterface()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 20) |
| @Test |
| public void testGetActionCompatFromAction_withRemoteInputs_doesntCrash() { |
| NotificationCompat.Action action = newActionBuilder() |
| .addRemoteInput(new RemoteInput( |
| "a", |
| "b", |
| null /* choices */, |
| false /* allowFreeFormTextInput */, |
| RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, |
| null /* extras */, |
| null /* allowedDataTypes */)).build(); |
| Notification notification = newNotificationBuilder().addAction(action).build(); |
| |
| NotificationCompat.Action result = |
| NotificationCompat.getActionCompatFromAction(notification.actions[0]); |
| |
| assertEquals(1, result.getRemoteInputs().length); |
| } |
| |
| @SdkSuppress(minSdkVersion = 17) |
| @Test |
| public void testNotificationWearableExtenderAction_noIcon() throws Throwable { |
| NotificationCompat.Action a = new NotificationCompat.Action.Builder(0, "title", null) |
| .build(); |
| NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() |
| .addAction(a); |
| Notification notification = newNotificationBuilder().extend(extender).build(); |
| NotificationCompat.Action actualAction = |
| new NotificationCompat.WearableExtender(notification).getActions().get(0); |
| assertNull(actualAction.getIconCompat()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 17) |
| @Test |
| public void testNotificationWearableExtenderAction_drawableIcon() throws Throwable { |
| NotificationCompat.Action a = |
| new NotificationCompat.Action.Builder(android.R.drawable.ic_delete, "title", null) |
| .build(); |
| NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() |
| .addAction(a); |
| Notification notification = newNotificationBuilder().extend(extender).build(); |
| NotificationCompat.Action actualAction = |
| new NotificationCompat.WearableExtender(notification).getActions().get(0); |
| assertEquals(android.R.drawable.ic_delete, actualAction.getIconCompat().getResId()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 17) |
| @Test |
| public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesTrue() |
| throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .setAllowGeneratedReplies(true).build(); |
| NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() |
| .addAction(a); |
| Notification notification = newNotificationBuilder().extend(extender).build(); |
| assertTrue(new NotificationCompat.WearableExtender(notification).getActions().get(0) |
| .getAllowGeneratedReplies()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 17) |
| @Test |
| public void testNotificationWearableExtenderAction_setAllowGeneratedRepliesFalse() |
| throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .setAllowGeneratedReplies(false).build(); |
| NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() |
| .addAction(a); |
| Notification notification = newNotificationBuilder().extend(extender).build(); |
| assertFalse(new NotificationCompat.WearableExtender(notification).getActions().get(0) |
| .getAllowGeneratedReplies()); |
| } |
| |
| |
| @SdkSuppress(maxSdkVersion = 16) |
| @SmallTest |
| @Test |
| public void testNotificationWearableExtenderAction_noActions() |
| throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .setAllowGeneratedReplies(true).build(); |
| NotificationCompat.WearableExtender extender = new NotificationCompat.WearableExtender() |
| .addAction(a); |
| Notification notification = newNotificationBuilder().extend(extender).build(); |
| assertTrue(new NotificationCompat.WearableExtender(notification).getActions().size() == 0); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_setDataOnlyRemoteInput() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .addRemoteInput(newDataOnlyRemoteInput()).build(); |
| RemoteInput[] textInputs = a.getRemoteInputs(); |
| assertTrue(textInputs == null || textInputs.length == 0); |
| verifyRemoteInputArrayHasSingleResult(a.getDataOnlyRemoteInputs(), DATA_RESULT_KEY); |
| } |
| |
| @Test |
| public void testNotificationActionBuilder_setTextAndDataOnlyRemoteInput() throws Throwable { |
| NotificationCompat.Action a = newActionBuilder() |
| .addRemoteInput(newDataOnlyRemoteInput()) |
| .addRemoteInput(newTextRemoteInput()) |
| .build(); |
| |
| verifyRemoteInputArrayHasSingleResult(a.getRemoteInputs(), TEXT_RESULT_KEY); |
| verifyRemoteInputArrayHasSingleResult(a.getDataOnlyRemoteInputs(), DATA_RESULT_KEY); |
| } |
| |
| @Test |
| public void testMessage_setAndGetExtras() throws Throwable { |
| String extraKey = "extra_key"; |
| CharSequence extraValue = "extra_value"; |
| Message m = |
| new Message("text", 0 /*timestamp */, "sender"); |
| m.getExtras().putCharSequence(extraKey, extraValue); |
| assertEquals(extraValue, m.getExtras().getCharSequence(extraKey)); |
| |
| ArrayList<Message> messages = new ArrayList<>(1); |
| messages.add(m); |
| Bundle[] bundleArray = |
| Message.getBundleArrayForMessages(messages); |
| assertEquals(1, bundleArray.length); |
| Message fromBundle = |
| Message.getMessageFromBundle(bundleArray[0]); |
| assertEquals(extraValue, fromBundle.getExtras().getCharSequence(extraKey)); |
| } |
| |
| @Test |
| public void testGetGroupAlertBehavior() throws Throwable { |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_CHILDREN) |
| .build(); |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(GROUP_ALERT_CHILDREN, NotificationCompat.getGroupAlertBehavior(n)); |
| } else { |
| assertEquals(GROUP_ALERT_ALL, NotificationCompat.getGroupAlertBehavior(n)); |
| } |
| } |
| |
| @Test |
| public void testGroupAlertBehavior_mutesGroupNotifications() throws Throwable { |
| // valid between api 20, when groups were added, and api 25, the last to use sound |
| // and vibration from the notification itself |
| |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_CHILDREN) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(true) |
| .build(); |
| |
| Notification n2 = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_SUMMARY) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(false) |
| .build(); |
| |
| if (Build.VERSION.SDK_INT >= 20 && !(Build.VERSION.SDK_INT >= 26)) { |
| assertNull(n.sound); |
| assertNull(n.vibrate); |
| assertTrue((n.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n.defaults & DEFAULT_SOUND) == 0); |
| assertTrue((n.defaults & DEFAULT_VIBRATE) == 0); |
| |
| assertNull(n2.sound); |
| assertNull(n2.vibrate); |
| assertTrue((n2.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n2.defaults & DEFAULT_SOUND) == 0); |
| assertTrue((n2.defaults & DEFAULT_VIBRATE) == 0); |
| } else if (Build.VERSION.SDK_INT < 20) { |
| assertNotNull(n.sound); |
| assertNotNull(n.vibrate); |
| assertTrue((n.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n.defaults & DEFAULT_VIBRATE) != 0); |
| |
| assertNotNull(n2.sound); |
| assertNotNull(n2.vibrate); |
| assertTrue((n2.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n2.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n2.defaults & DEFAULT_VIBRATE) != 0); |
| } |
| } |
| |
| @Test |
| public void testSetNotificationSilent() throws Throwable { |
| |
| Notification nSummary = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroupSummary(true) |
| .setTicker("summary") |
| .setNotificationSilent() |
| .build(); |
| |
| Notification nChild = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroupSummary(false) |
| .setTicker("child") |
| .setNotificationSilent() |
| .build(); |
| |
| if (Build.VERSION.SDK_INT >= 20 && !(Build.VERSION.SDK_INT >= 26)) { |
| assertNull(nSummary.sound); |
| assertNull(nSummary.vibrate); |
| assertTrue((nSummary.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((nSummary.defaults & DEFAULT_SOUND) == 0); |
| assertTrue((nSummary.defaults & DEFAULT_VIBRATE) == 0); |
| |
| assertNull(nChild.sound); |
| assertNull(nChild.vibrate); |
| assertTrue((nChild.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((nChild.defaults & DEFAULT_SOUND) == 0); |
| assertTrue((nChild.defaults & DEFAULT_VIBRATE) == 0); |
| } |
| |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(GROUP_ALERT_SUMMARY, nChild.getGroupAlertBehavior()); |
| assertEquals(GROUP_ALERT_CHILDREN, nSummary.getGroupAlertBehavior()); |
| assertEquals(GROUP_KEY_SILENT, nChild.getGroup()); |
| assertEquals(GROUP_KEY_SILENT, nSummary.getGroup()); |
| } else if (Build.VERSION.SDK_INT >= 20) { |
| assertNull(nChild.getGroup()); |
| assertNull(nSummary.getGroup()); |
| } |
| } |
| |
| @Test |
| public void testSetNotificationSilent_doesNotOverrideGroup() throws Throwable { |
| final String groupKey = "grouped"; |
| |
| Notification nSummary = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroupSummary(true) |
| .setGroup(groupKey) |
| .setTicker("summary") |
| .setNotificationSilent() |
| .build(); |
| |
| Notification nChild = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroupSummary(false) |
| .setGroup(groupKey) |
| .setTicker("child") |
| .setNotificationSilent() |
| .build(); |
| |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(GROUP_ALERT_SUMMARY, nChild.getGroupAlertBehavior()); |
| assertEquals(GROUP_ALERT_CHILDREN, nSummary.getGroupAlertBehavior()); |
| } |
| if (Build.VERSION.SDK_INT >= 20) { |
| assertEquals(groupKey, nChild.getGroup()); |
| assertEquals(groupKey, nSummary.getGroup()); |
| } |
| } |
| |
| @Test |
| public void testSetNotificationSilent_notSilenced() throws Throwable { |
| |
| Notification nSummary = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(true) |
| .build(); |
| |
| Notification nChild = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(false) |
| .build(); |
| |
| assertNotNull(nSummary.sound); |
| assertNotNull(nSummary.vibrate); |
| assertTrue((nSummary.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((nSummary.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((nSummary.defaults & DEFAULT_VIBRATE) != 0); |
| |
| assertNotNull(nChild.sound); |
| assertNotNull(nChild.vibrate); |
| assertTrue((nChild.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((nChild.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((nChild.defaults & DEFAULT_VIBRATE) != 0); |
| |
| if (Build.VERSION.SDK_INT >= 26) { |
| assertEquals(GROUP_ALERT_ALL, nChild.getGroupAlertBehavior()); |
| assertEquals(GROUP_ALERT_ALL, nSummary.getGroupAlertBehavior()); |
| } |
| } |
| |
| @Test |
| public void testGroupAlertBehavior_doesNotMuteIncorrectGroupNotifications() throws Throwable { |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_SUMMARY) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(true) |
| .build(); |
| |
| Notification n2 = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_CHILDREN) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(false) |
| .build(); |
| |
| Notification n3 = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup("grouped") |
| .setGroupSummary(false) |
| .build(); |
| |
| if (Build.VERSION.SDK_INT >= 20 && !(Build.VERSION.SDK_INT >= 26)) { |
| assertNotNull(n.sound); |
| assertNotNull(n.vibrate); |
| assertTrue((n.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n.defaults & DEFAULT_VIBRATE) != 0); |
| |
| assertNotNull(n2.sound); |
| assertNotNull(n2.vibrate); |
| assertTrue((n2.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n2.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n2.defaults & DEFAULT_VIBRATE) != 0); |
| |
| assertNotNull(n3.sound); |
| assertNotNull(n3.vibrate); |
| assertTrue((n3.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n3.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n3.defaults & DEFAULT_VIBRATE) != 0); |
| } |
| } |
| |
| @Test |
| public void testGroupAlertBehavior_doesNotMuteNonGroupNotifications() throws Throwable { |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setGroupAlertBehavior(GROUP_ALERT_CHILDREN) |
| .setVibrate(new long[] {235}) |
| .setSound(Uri.EMPTY) |
| .setDefaults(DEFAULT_ALL) |
| .setGroup(null) |
| .setGroupSummary(false) |
| .build(); |
| if (!(Build.VERSION.SDK_INT >= 26)) { |
| assertNotNull(n.sound); |
| assertNotNull(n.vibrate); |
| assertTrue((n.defaults & DEFAULT_LIGHTS) != 0); |
| assertTrue((n.defaults & DEFAULT_SOUND) != 0); |
| assertTrue((n.defaults & DEFAULT_VIBRATE) != 0); |
| } |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 21) |
| public void testHasAudioAttributesFrom21() throws Throwable { |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setSound(Uri.EMPTY) |
| .build(); |
| assertNotNull(n.audioAttributes); |
| assertEquals(-1, n.audioStreamType); |
| assertEquals(Uri.EMPTY, n.sound); |
| |
| n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setSound(Uri.EMPTY, AudioManager.STREAM_RING) |
| .build(); |
| assertNotNull(n.audioAttributes); |
| assertEquals(AudioAttributes.USAGE_NOTIFICATION_RINGTONE, n.audioAttributes.getUsage()); |
| assertEquals(-1, n.audioStreamType); |
| assertEquals(Uri.EMPTY, n.sound); |
| } |
| |
| @Test |
| @SdkSuppress(maxSdkVersion = 20) |
| public void testHasStreamTypePre21() throws Throwable { |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setSound(Uri.EMPTY, 34) |
| .build(); |
| assertEquals(34, n.audioStreamType); |
| assertEquals(Uri.EMPTY, n.sound); |
| } |
| |
| @SdkSuppress(minSdkVersion = 26) |
| @Test |
| public void testClearAlertingFieldsIfUsingChannels() throws Throwable { |
| long[] vibration = new long[]{100}; |
| |
| // stripped if using channels |
| Notification n = new NotificationCompat.Builder(mActivityTestRule.getActivity(), "test") |
| .setSound(Uri.EMPTY) |
| .setDefaults(Notification.DEFAULT_ALL) |
| .setVibrate(vibration) |
| .setChronometerCountDown(true) |
| .setLights(Color.BLUE, 100, 100) |
| .build(); |
| assertNull(n.sound); |
| assertEquals(0, n.defaults); |
| assertNull(n.vibrate); |
| assertEquals(0, n.ledARGB); |
| assertEquals(0, n.ledOnMS); |
| assertEquals(0, n.ledOffMS); |
| |
| // left intact if not using channels |
| n = new NotificationCompat.Builder(mActivityTestRule.getActivity()) |
| .setSound(Uri.EMPTY) |
| .setDefaults(Notification.DEFAULT_ALL) |
| .setVibrate(vibration) |
| .setLights(Color.BLUE, 100, 100) |
| .build(); |
| assertEquals(Uri.EMPTY, n.sound); |
| assertNotNull(n.audioAttributes); |
| assertEquals(Notification.DEFAULT_ALL, n.defaults); |
| assertEquals(vibration, n.vibrate); |
| assertEquals(Color.BLUE, n.ledARGB); |
| assertEquals(100, n.ledOnMS); |
| assertEquals(100, n.ledOffMS); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_nullPerson() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle("self name"); |
| messagingStyle.addMessage("text", 200, (Person) null); |
| |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| List<Message> result = NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification) |
| .getMessages(); |
| |
| assertEquals(1, result.size()); |
| assertEquals("text", result.get(0).getText()); |
| assertEquals(200, result.get(0).getTimestamp()); |
| assertNull(result.get(0).getPerson()); |
| assertNull(result.get(0).getSender()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_message() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle("self name"); |
| Person person = new Person.Builder().setName("test name").setKey("key").build(); |
| Person person2 = new Person.Builder() |
| .setName("test name 2").setKey("key 2").setImportant(true).build(); |
| messagingStyle.addMessage("text", 200, person); |
| messagingStyle.addMessage("text2", 300, person2); |
| |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| List<Message> result = NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification) |
| .getMessages(); |
| |
| assertEquals(2, result.size()); |
| assertEquals("text", result.get(0).getText()); |
| assertEquals(200, result.get(0).getTimestamp()); |
| assertEquals("test name", result.get(0).getPerson().getName()); |
| assertEquals("key", result.get(0).getPerson().getKey()); |
| assertEquals("text2", result.get(1).getText()); |
| assertEquals(300, result.get(1).getTimestamp()); |
| assertEquals("test name 2", result.get(1).getPerson().getName()); |
| assertEquals("key 2", result.get(1).getPerson().getKey()); |
| assertTrue(result.get(1).getPerson().isImportant()); |
| } |
| |
| @Test |
| public void testMessagingStyle_requiresNonEmptyUserName() { |
| try { |
| new NotificationCompat.MessagingStyle(new Person.Builder().build()); |
| fail("Expected IllegalArgumentException about a non-empty user name."); |
| } catch (IllegalArgumentException e) { |
| // Expected |
| } |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation() { |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(true) |
| .setConversationTitle("test conversation title"); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertTrue(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation_noConversationTitle() { |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(true) |
| .setConversationTitle(null); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertTrue(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation_withConversationTitle_legacy() { |
| // In legacy (version < P), isGroupConversation is controlled by conversationTitle. |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setConversationTitle("test conversation title"); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertTrue(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation_withoutConversationTitle_legacy() { |
| // In legacy (version < P), isGroupConversation is controlled by conversationTitle. |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setConversationTitle(null); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertFalse(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation_withConversationTitle_legacyWithOverride() { |
| // #setGroupConversation should always take precedence over legacy behavior, so a non-null |
| // title shouldn't affect #isGroupConversation. |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(false) |
| .setConversationTitle("test conversation title"); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertFalse(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 16) |
| @Test |
| public void testMessagingStyle_isGroupConversation_withoutTitle_legacyWithOverride() { |
| // #setGroupConversation should always take precedence over legacy behavior, so a null |
| // title shouldn't affect #isGroupConversation. |
| mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O; |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(true) |
| .setConversationTitle(null); |
| Notification notification = new NotificationCompat.Builder(mContext, "test id") |
| .setSmallIcon(1) |
| .setContentTitle("test title") |
| .setStyle(messagingStyle) |
| .build(); |
| |
| NotificationCompat.MessagingStyle result = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(notification); |
| |
| assertTrue(result.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 28) |
| @Test |
| public void testMessagingStyle_applyNoTitleAndNotGroup() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(false) |
| .addMessage( |
| new Message( |
| "body", |
| 1, |
| new Person.Builder().setName("example name").build())) |
| .addMessage(new Message("body 2", 2, (Person) null)); |
| |
| Notification resultNotification = new NotificationCompat.Builder(mContext, "test id") |
| .setStyle(messagingStyle) |
| .build(); |
| NotificationCompat.MessagingStyle resultCompatMessagingStyle = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(resultNotification); |
| |
| // SDK >= 28 applies no title when none is provided to MessagingStyle. |
| assertNull(resultCompatMessagingStyle.getConversationTitle()); |
| assertFalse(resultCompatMessagingStyle.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 24, maxSdkVersion = 27) |
| @Test |
| public void testMessagingStyle_applyNoTitleAndNotGroup_legacy() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(false) |
| .addMessage( |
| new Message( |
| "body", |
| 1, |
| new Person.Builder().setName("example name").build())) |
| .addMessage(new Message("body 2", 2, (Person) null)); |
| |
| Notification resultNotification = new NotificationCompat.Builder(mContext, "test id") |
| .setStyle(messagingStyle) |
| .build(); |
| NotificationCompat.MessagingStyle resultCompatMessagingStyle = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(resultNotification); |
| |
| // SDK [24, 27] applies first incoming message sender name as Notification content title. |
| assertEquals("example name", NotificationCompat.getContentTitle(resultNotification)); |
| assertNull(resultCompatMessagingStyle.getConversationTitle()); |
| assertFalse(resultCompatMessagingStyle.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 28) |
| @Test |
| public void testMessagingStyle_applyConversationTitleAndNotGroup() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(false) |
| .setConversationTitle("test title"); |
| |
| Notification resultNotification = new NotificationCompat.Builder(mContext, "test id") |
| .setStyle(messagingStyle) |
| .build(); |
| NotificationCompat.MessagingStyle resultMessagingStyle = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(resultNotification); |
| |
| // SDK >= 28 applies provided title to MessagingStyle. |
| assertEquals("test title", resultMessagingStyle.getConversationTitle()); |
| assertFalse(resultMessagingStyle.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 19, maxSdkVersion = 27) |
| @Test |
| public void testMessagingStyle_applyConversationTitleAndNotGroup_legacy() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("self name").build()) |
| .setGroupConversation(false) |
| .setConversationTitle("test title"); |
| |
| Notification resultNotification = new NotificationCompat.Builder(mContext, "test id") |
| .setStyle(messagingStyle) |
| .build(); |
| NotificationCompat.MessagingStyle resultMessagingStyle = |
| NotificationCompat.MessagingStyle |
| .extractMessagingStyleFromNotification(resultNotification); |
| |
| // SDK <= 27 applies MessagingStyle title as Notification content title. |
| assertEquals("test title", resultMessagingStyle.getConversationTitle()); |
| assertFalse(resultMessagingStyle.isGroupConversation()); |
| } |
| |
| @SdkSuppress(minSdkVersion = 28) |
| @Test |
| public void testMessagingStyle_apply_writesMessagePerson() { |
| Notification msNotification = newMsNotification(true, true); |
| |
| Bundle[] messagesBundle = |
| (Bundle[]) msNotification.extras.getParcelableArray(Notification.EXTRA_MESSAGES); |
| assertEquals(2, messagesBundle.length); |
| assertTrue(messagesBundle[0].containsKey(Message.KEY_NOTIFICATION_PERSON)); |
| } |
| |
| @SdkSuppress(minSdkVersion = 24, maxSdkVersion = 27) |
| @Test |
| public void testMessagingStyle_apply_writesMessagePerson_legacy() { |
| Notification msNotification = newMsNotification(true, true); |
| |
| Bundle[] messagesBundle = |
| (Bundle[]) msNotification.extras.getParcelableArray(Notification.EXTRA_MESSAGES); |
| assertEquals(2, messagesBundle.length); |
| assertTrue(messagesBundle[0].containsKey(Message.KEY_PERSON)); |
| } |
| |
| @Test |
| public void testMessagingStyle_restoreFromCompatExtras() { |
| NotificationCompat.MessagingStyle messagingStyle = |
| new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("test name").build()) |
| .setGroupConversation(true); |
| Bundle bundle = new Bundle(); |
| messagingStyle.addCompatExtras(bundle); |
| |
| NotificationCompat.MessagingStyle resultMessagingStyle = |
| new NotificationCompat.MessagingStyle(new Person.Builder().setName("temp").build()); |
| resultMessagingStyle.restoreFromCompatExtras(bundle); |
| |
| assertTrue(resultMessagingStyle.isGroupConversation()); |
| assertEquals("test name", resultMessagingStyle.getUser().getName()); |
| } |
| |
| @Test |
| public void testMessagingStyleMessage_bundle_legacySender() { |
| Bundle legacyBundle = new Bundle(); |
| legacyBundle.putCharSequence(Message.KEY_TEXT, "message"); |
| legacyBundle.putLong(Message.KEY_TIMESTAMP, 100); |
| legacyBundle.putCharSequence(Message.KEY_SENDER, "sender"); |
| |
| Message result = Message.getMessageFromBundle(legacyBundle); |
| assertEquals("sender", result.getPerson().getName()); |
| } |
| |
| @Test |
| public void action_builder_hasDefault() { |
| NotificationCompat.Action action = |
| newActionBuilder().build(); |
| assertEquals(NotificationCompat.Action.SEMANTIC_ACTION_NONE, action.getSemanticAction()); |
| } |
| |
| @Test |
| public void action_builder_setSemanticAction() { |
| NotificationCompat.Action action = |
| newActionBuilder() |
| .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) |
| .build(); |
| assertEquals(NotificationCompat.Action.SEMANTIC_ACTION_REPLY, action.getSemanticAction()); |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 20) |
| public void action_semanticAction_toAndFromNotification() { |
| NotificationCompat.Action action = |
| newActionBuilder() |
| .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) |
| .build(); |
| Notification notification = newNotificationBuilder().addAction(action).build(); |
| NotificationCompat.Action result = NotificationCompat.getAction(notification, 0); |
| |
| assertEquals(NotificationCompat.Action.SEMANTIC_ACTION_REPLY, result.getSemanticAction()); |
| } |
| |
| private static final NotificationCompat.Action TEST_INVISIBLE_ACTION = |
| newActionBuilder() |
| .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MUTE) |
| .setShowsUserInterface(false) |
| .build(); |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 21) |
| public void getInvisibleActions() { |
| Notification notification = |
| newNotificationBuilder().addInvisibleAction(TEST_INVISIBLE_ACTION).build(); |
| verifyInvisibleActionExists(notification); |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 21) |
| public void getInvisibleActions_withCarExtender() { |
| NotificationCompat.CarExtender carExtender = new NotificationCompat.CarExtender(); |
| Notification notification = newNotificationBuilder() |
| .addInvisibleAction(TEST_INVISIBLE_ACTION) |
| .extend(carExtender) |
| .build(); |
| verifyInvisibleActionExists(notification); |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 19) |
| public void getContentTitle() { |
| Notification notification = new NotificationCompat.Builder(mContext, "test channel") |
| .setContentTitle("example title") |
| .build(); |
| |
| assertEquals("example title", NotificationCompat.getContentTitle(notification)); |
| } |
| |
| @Test |
| public void action_builder_defaultNotContextual() { |
| NotificationCompat.Action action = newActionBuilder().build(); |
| assertFalse(action.isContextual()); |
| } |
| |
| @Test |
| public void action_builder_setContextual() { |
| // Without a PendingIntent the Action.Builder class throws an NPE when building a contextual |
| // action. |
| PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
| NotificationCompat.Action action = |
| new NotificationCompat.Action.Builder(0, "Test Title", pendingIntent) |
| .setContextual(true) |
| .build(); |
| assertTrue(action.isContextual()); |
| } |
| |
| @Test |
| public void action_builder_contextual_invalidIntentCausesNpe() { |
| NotificationCompat.Action.Builder builder = newActionBuilder().setContextual(true); |
| try { |
| builder.build(); |
| fail("Creating a contextual Action with a null PendingIntent should cause a " |
| + " NullPointerException"); |
| } catch (NullPointerException e) { |
| // Expected |
| } |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = 28) // TODO(gsennton): this test only applies to Q+ devices. |
| public void action_contextual_toAndFromNotification() { |
| if (Build.VERSION.SDK_INT < 29) return; |
| // Without a PendingIntent the Action.Builder class throws an NPE when building a contextual |
| // action. |
| PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
| NotificationCompat.Action action = new NotificationCompat.Action.Builder( |
| R.drawable.notification_bg, "Test Title", pendingIntent) |
| .setContextual(true) |
| .build(); |
| Notification notification = newNotificationBuilder().addAction(action).build(); |
| NotificationCompat.Action result = NotificationCompat.getAction(notification, 0); |
| |
| assertTrue(result.isContextual()); |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P) // TODO(gsennton): This only works on Q+ |
| public void getAllowSystemGeneratedContextualActions_trueByDefault() { |
| if (Build.VERSION.SDK_INT < 29) return; |
| Notification notification = |
| new NotificationCompat.Builder(mContext, "test channel").build(); |
| assertTrue(NotificationCompat.getAllowSystemGeneratedContextualActions(notification)); |
| } |
| |
| @Test |
| @SdkSuppress(minSdkVersion = Build.VERSION_CODES.P) // TODO(gsennton): This only works on Q+ |
| public void getAllowSystemGeneratedContextualActions() { |
| if (Build.VERSION.SDK_INT < 29) return; |
| Notification notification = new NotificationCompat.Builder(mContext, "test channel") |
| .setAllowSystemGeneratedContextualActions(false) |
| .build(); |
| assertFalse(NotificationCompat.getAllowSystemGeneratedContextualActions(notification)); |
| } |
| |
| @Test |
| public void setBubbleMetadata() { |
| IconCompat icon = IconCompat.createWithAdaptiveBitmap(BitmapFactory.decodeResource( |
| mContext.getResources(), |
| R.drawable.notification_bg_normal)); |
| |
| PendingIntent intent = |
| PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
| |
| PendingIntent deleteIntent = |
| PendingIntent.getActivity(mContext, 1, new Intent(), 0); |
| |
| NotificationCompat.BubbleMetadata originalBubble = |
| new NotificationCompat.BubbleMetadata.Builder() |
| .setAutoExpandBubble(true) |
| .setDeleteIntent(deleteIntent) |
| .setDesiredHeight(600) |
| .setIcon(icon) |
| .setIntent(intent) |
| .setSuppressNotification(true) |
| .build(); |
| |
| Notification notification = new NotificationCompat.Builder(mContext, "test channel") |
| .setBubbleMetadata(originalBubble) |
| .build(); |
| |
| NotificationCompat.BubbleMetadata roundtripBubble = |
| NotificationCompat.getBubbleMetadata(notification); |
| |
| // Bubbles are only supported on Q and above; on P and earlier, simply verify that the above |
| // code does not crash. |
| if (Build.VERSION.SDK_INT < 29) { |
| return; |
| } |
| |
| // TODO: Check notification itself. |
| |
| assertNotNull(roundtripBubble); |
| |
| assertEquals(originalBubble.getAutoExpandBubble(), roundtripBubble.getAutoExpandBubble()); |
| assertEquals(originalBubble.getDeleteIntent(), roundtripBubble.getDeleteIntent()); |
| assertEquals(originalBubble.getDesiredHeight(), roundtripBubble.getDesiredHeight()); |
| // TODO: Check getIcon(). |
| /* assertEquals(originalBubble.getIcon().toIcon(), roundtripBubble.getIcon().toIcon()); */ |
| assertEquals(originalBubble.getIntent(), roundtripBubble.getIntent()); |
| assertEquals( |
| originalBubble.isNotificationSuppressed(), |
| roundtripBubble.isNotificationSuppressed()); |
| } |
| |
| @Test |
| public void setBubbleMetadataDesiredHeightResId() { |
| IconCompat icon = IconCompat.createWithAdaptiveBitmap(BitmapFactory.decodeResource( |
| mContext.getResources(), |
| R.drawable.notification_bg_normal)); |
| |
| PendingIntent intent = |
| PendingIntent.getActivity(mContext, 0, new Intent(), 0); |
| |
| NotificationCompat.BubbleMetadata originalBubble = |
| new NotificationCompat.BubbleMetadata.Builder() |
| .setDesiredHeightResId(R.dimen.compat_notification_large_icon_max_height) |
| .setIcon(icon) |
| .setIntent(intent) |
| .build(); |
| |
| Notification notification = new NotificationCompat.Builder(mContext, "test channel") |
| .setBubbleMetadata(originalBubble) |
| .build(); |
| |
| NotificationCompat.BubbleMetadata roundtripBubble = |
| NotificationCompat.getBubbleMetadata(notification); |
| |
| // Bubbles are only supported on Q and above; on P and earlier, simply verify that the above |
| // code does not crash. |
| if (Build.VERSION.SDK_INT < 29) { |
| return; |
| } |
| |
| // TODO: Check notification itself. |
| |
| assertNotNull(roundtripBubble); |
| |
| assertEquals( |
| originalBubble.getDesiredHeightResId(), |
| roundtripBubble.getDesiredHeightResId()); |
| } |
| |
| @Test |
| public void setBubbleMetadataToNull() { |
| Notification notification = new NotificationCompat.Builder(mContext, "test channel") |
| .setBubbleMetadata(null) |
| .build(); |
| |
| assertNull(NotificationCompat.getBubbleMetadata(notification)); |
| } |
| |
| // Add the @Test annotation to enable this test. This test is disabled by default as it's not a |
| // unit test. This will simply create 4 MessagingStyle notifications so a developer may see what |
| // the end result will look like on a physical device (or emulator). |
| public void makeMessagingStyleNotifications() { |
| NotificationManager notificationManager = |
| (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); |
| |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
| NotificationChannel channel = |
| new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); |
| channel.setDescription("Lol a description"); |
| channel.enableLights(true); |
| notificationManager.createNotificationChannel(channel); |
| } |
| |
| notificationManager.notify(2, newMsNotification(false, false)); |
| notificationManager.notify(3, newMsNotification(false, true)); |
| notificationManager.notify(4, newMsNotification(true, false)); |
| notificationManager.notify(5, newMsNotification(true, true)); |
| } |
| |
| private Notification newMsNotification(boolean isGroup, boolean hasTitle) { |
| IconCompat testIcon = |
| IconCompat.createWithBitmap( |
| BitmapFactory.decodeResource( |
| mContext.getResources(), |
| R.drawable.notification_bg_normal)); |
| NotificationCompat.MessagingStyle ms = new NotificationCompat.MessagingStyle( |
| new Person.Builder().setName("Me").setIcon(testIcon).build()); |
| String message = "compat. isGroup? " + Boolean.toString(isGroup) |
| + "; hasTitle? " + Boolean.toString(hasTitle); |
| ms.addMessage(new Message( |
| message, 40, new Person.Builder().setName("John").setIcon(testIcon).build())); |
| ms.addMessage(new Message("Heyo", 41, (Person) null)); |
| ms.setGroupConversation(isGroup); |
| ms.setConversationTitle(hasTitle ? "My Conversation Title" : null); |
| |
| NotificationCompat.Builder builder; |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
| builder = new NotificationCompat.Builder(mContext, "id"); |
| } else { |
| builder = new NotificationCompat.Builder(mContext); |
| } |
| builder.setSmallIcon(R.drawable.notification_bg_normal); |
| builder.setStyle(ms); |
| return builder.build(); |
| } |
| |
| private static void verifyInvisibleActionExists(Notification notification) { |
| List<NotificationCompat.Action> result = |
| NotificationCompat.getInvisibleActions(notification); |
| assertTrue("Expecting 1 result, got " + result.size(), result.size() == 1); |
| NotificationCompat.Action resultAction = result.get(0); |
| assertEquals(resultAction.getIcon(), TEST_INVISIBLE_ACTION.getIcon()); |
| assertEquals(resultAction.getTitle(), TEST_INVISIBLE_ACTION.getTitle()); |
| assertEquals( |
| resultAction.getShowsUserInterface(), |
| TEST_INVISIBLE_ACTION.getShowsUserInterface()); |
| assertEquals(resultAction.getSemanticAction(), TEST_INVISIBLE_ACTION.getSemanticAction()); |
| } |
| |
| private static RemoteInput newDataOnlyRemoteInput() { |
| return new RemoteInput.Builder(DATA_RESULT_KEY) |
| .setAllowFreeFormInput(false) |
| .setAllowDataType("mimeType", true) |
| .build(); |
| } |
| |
| private static RemoteInput newTextRemoteInput() { |
| return new RemoteInput.Builder(TEXT_RESULT_KEY).build(); // allowFreeForm defaults to true |
| } |
| |
| private static void verifyRemoteInputArrayHasSingleResult( |
| RemoteInput[] remoteInputs, String expectedResultKey) { |
| assertTrue(remoteInputs != null && remoteInputs.length == 1); |
| assertEquals(expectedResultKey, remoteInputs[0].getResultKey()); |
| } |
| |
| private static NotificationCompat.Action.Builder newActionBuilder() { |
| return new NotificationCompat.Action.Builder(0, "title", null); |
| } |
| |
| private NotificationCompat.Builder newNotificationBuilder() { |
| return new NotificationCompat.Builder(mContext) |
| .setSmallIcon(0) |
| .setContentTitle("title") |
| .setContentText("text"); |
| } |
| } |