From 348643b7b357c7ff54bb7d29bd4aee68b97aef6e Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Mon, 7 May 2018 23:17:31 -0400 Subject: [PATCH 1/8] Documentation assets. collapsedText -> expandedText. --- docs/assets/types/big-picture.svg | 90 ++++++++++++++ docs/assets/types/big-text.svg | 93 +++++++++++++++ docs/assets/types/default.svg | 37 ++++++ docs/assets/types/list-text.svg | 85 ++++++++++++++ docs/assets/types/messages.svg | 110 ++++++++++++++++++ .../io/karn/notify/NotificationInterop.kt | 4 +- .../java/io/karn/notify/entities/Payload.kt | 8 +- .../java/io/karn/notify/NotifyContentTest.kt | 4 +- .../main/java/presentation/MainActivity.kt | 4 +- 9 files changed, 425 insertions(+), 10 deletions(-) create mode 100644 docs/assets/types/big-picture.svg create mode 100644 docs/assets/types/big-text.svg create mode 100644 docs/assets/types/default.svg create mode 100644 docs/assets/types/list-text.svg create mode 100644 docs/assets/types/messages.svg diff --git a/docs/assets/types/big-picture.svg b/docs/assets/types/big-picture.svg new file mode 100644 index 0000000..953757b --- /dev/null +++ b/docs/assets/types/big-picture.svg @@ -0,0 +1,90 @@ + + + + type/big-picture + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + Chocolate brownie sundae + + + Get a look at this amazing dessert! + + + + + + now + + + + + + + Notify + + + + + + + + + + + + + + + + Chocolate brownie sundae + + + Try our newest dessert option! + + + + + now + + + + + + + Notify + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/types/big-text.svg b/docs/assets/types/big-text.svg new file mode 100644 index 0000000..79ecf5c --- /dev/null +++ b/docs/assets/types/big-text.svg @@ -0,0 +1,93 @@ + + + + type/big-text + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + Chocolate brownie sundae + + + Try our newest dessert option! + + + Our own Fabulous Godiva Chocolate Brownie, Vanilla Ice + Cream, Hot Fudge, Whipped Cream and Toasted Almonds. + + Come try this delicious new dessert and get two for the price + of one! + + + + + now + + + + + + + Notify + + + + + + + + + + + + + Chocolate brownie sundae + + + Try our newest dessert option! + + + + + now + + + + + + + Notify + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/types/default.svg b/docs/assets/types/default.svg new file mode 100644 index 0000000..c266bd9 --- /dev/null +++ b/docs/assets/types/default.svg @@ -0,0 +1,37 @@ + + + + type/default + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/assets/types/list-text.svg b/docs/assets/types/list-text.svg new file mode 100644 index 0000000..b7a2bec --- /dev/null +++ b/docs/assets/types/list-text.svg @@ -0,0 +1,85 @@ + + + + type/list-text + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + now + + + + + + + Notify + + + + + + + + + + New menu items! + + + 3 new dessert menu items found. + + + + + + + + now + + + + + + + Notify + + + + + + + + + + New! Fresh Strawberry Cheesecake. + New! Salted Caramel Cheesecake. + New! OREO Dream Dessert. + + + + + + \ No newline at end of file diff --git a/docs/assets/types/messages.svg b/docs/assets/types/messages.svg new file mode 100644 index 0000000..dbbfc9e --- /dev/null +++ b/docs/assets/types/messages.svg @@ -0,0 +1,110 @@ + + + + type/messages + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + now + + + + + + + Notify + + + + + + + + + + Sundae chat + + + Karn + + + Are you guys ready to try the Strawberry sundae? + + + Nitish + + + Yeah! I’ve heard great things about this place. + + + Moez + + + What time are you getting there Karn? + + + + + + + + now + + + + + + + Notify + + + + + + + + + + Sundae chat + + + Nitish + + + Yeah! I’ve heard great things about this place. + + + Moez + + + What time are you getting there Karn? + + + + + + \ No newline at end of file diff --git a/library/src/main/java/io/karn/notify/NotificationInterop.kt b/library/src/main/java/io/karn/notify/NotificationInterop.kt index ff1b5fc..a96e060 100644 --- a/library/src/main/java/io/karn/notify/NotificationInterop.kt +++ b/library/src/main/java/io/karn/notify/NotificationInterop.kt @@ -178,7 +178,7 @@ internal object NotificationInterop { builder.setContentText(Utils.getAsSecondaryFormattedText((content.text ?: "").toString())) - val bigText: CharSequence = Html.fromHtml("" + (content.collapsedText + val bigText: CharSequence = Html.fromHtml("" + (content.expandedText ?: content.title) + "
" + content.bigText?.replace("\n".toRegex(), "
")) NotificationCompat.BigTextStyle() @@ -192,7 +192,7 @@ internal object NotificationInterop { NotificationCompat.BigPictureStyle() // This is the second line in the 'expanded' notification. - .setSummaryText(content.collapsedText ?: content.text) + .setSummaryText(content.expandedText ?: content.text) // This is the picture below. .bigPicture(content.image) diff --git a/library/src/main/java/io/karn/notify/entities/Payload.kt b/library/src/main/java/io/karn/notify/entities/Payload.kt index 39bad2b..fe2115e 100644 --- a/library/src/main/java/io/karn/notify/entities/Payload.kt +++ b/library/src/main/java/io/karn/notify/entities/Payload.kt @@ -124,9 +124,9 @@ sealed class Payload { */ interface Expandable { /** - * The content that is displayed when the notification is not expanded. + * The content that is displayed when the notification is expanded expanded. */ - var collapsedText: CharSequence? + var expandedText: CharSequence? } /** @@ -155,7 +155,7 @@ sealed class Payload { data class BigText( override var title: CharSequence? = null, override var text: CharSequence? = null, - override var collapsedText: CharSequence? = null, + override var expandedText: CharSequence? = null, /** * The large text associated with the notification. */ @@ -168,7 +168,7 @@ sealed class Payload { data class BigPicture( override var title: CharSequence? = null, override var text: CharSequence? = null, - override var collapsedText: CharSequence? = null, + override var expandedText: CharSequence? = null, /** * The large image that appears when the notification is expanded.s */ diff --git a/library/src/test/java/io/karn/notify/NotifyContentTest.kt b/library/src/test/java/io/karn/notify/NotifyContentTest.kt index 6e60c5c..8f65d8a 100644 --- a/library/src/test/java/io/karn/notify/NotifyContentTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyContentTest.kt @@ -118,7 +118,7 @@ class NotifyContentTest { .asBigText { title = testTitle text = testText - collapsedText = testExpandedText + expandedText = testExpandedText bigText = testBigText } .asBuilder() @@ -143,7 +143,7 @@ class NotifyContentTest { title = testTitle text = testText image = testImage - collapsedText = testCollapsedText + expandedText = testCollapsedText } .asBuilder() .build() diff --git a/sample/src/main/java/presentation/MainActivity.kt b/sample/src/main/java/presentation/MainActivity.kt index c39bfcd..ce73f1c 100644 --- a/sample/src/main/java/presentation/MainActivity.kt +++ b/sample/src/main/java/presentation/MainActivity.kt @@ -56,7 +56,7 @@ class MainActivity : AppCompatActivity() { .asBigText { title = "Chocolate brownie sundae" text = "Try our newest dessert option!" - collapsedText = "Try our newest dessert option!" + expandedText = "Mouthwatering deliciousness." bigText = "Our own Fabulous Godiva Chocolate Brownie, Vanilla Ice Cream, Hot Fudge, Whipped Cream and Toasted Almonds.\n" + "\n" + "Come try this delicious new dessert and get two for the price of one!" @@ -70,7 +70,7 @@ class MainActivity : AppCompatActivity() { .asBigPicture { title = "Chocolate brownie sundae" text = "Get a look at this amazing dessert!" - collapsedText = "The delicious brownie sundae now available." + expandedText = "The delicious brownie sundae now available." image = BitmapFactory.decodeResource(this@MainActivity.resources, R.drawable.chocolate_brownie_sundae) } .show() From 6c966497875753e6c6786ded0e9b82a1613b157b Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Mon, 7 May 2018 23:26:56 -0400 Subject: [PATCH 2/8] Updated README to link to Notification Types wiki. --- README.md | 2 ++ docs/assets/types/big-picture.svg | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf8b2c9..b4bc6f6 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ Notify If you run into a case in which the library does not provide the requisite builder functions you can get the `NotificationCompat.Builder` object and continue to use it as you would normally by calling `Creator#asBuilder()`. +> **Tip:** You can view other notification styles on the [Notification Types](https://github.com/Karn/notify/wiki/Notification-types) wiki page. + #### NOTIFICATION ANATOMY ![Anatory](./docs/assets/anatomy.svg) diff --git a/docs/assets/types/big-picture.svg b/docs/assets/types/big-picture.svg index 953757b..0f7b5a4 100644 --- a/docs/assets/types/big-picture.svg +++ b/docs/assets/types/big-picture.svg @@ -41,8 +41,8 @@ now - - + + Notify From 60527a149bdb91633a4bb9a948709bec4a1d9ce0 Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Tue, 8 May 2018 19:00:53 -0400 Subject: [PATCH 3/8] Move types to readme. --- README.md | 2 +- docs/types.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 docs/types.md diff --git a/README.md b/README.md index b4bc6f6..3ce9a53 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Notify If you run into a case in which the library does not provide the requisite builder functions you can get the `NotificationCompat.Builder` object and continue to use it as you would normally by calling `Creator#asBuilder()`. -> **Tip:** You can view other notification styles on the [Notification Types](https://github.com/Karn/notify/wiki/Notification-types) wiki page. +> **Tip:** You can view other notification styles on the [Notification Types](./docs/types.md) docs page. #### NOTIFICATION ANATOMY diff --git a/docs/types.md b/docs/types.md new file mode 100644 index 0000000..7482dce --- /dev/null +++ b/docs/types.md @@ -0,0 +1,120 @@ +## Notification Types + +#### STANDARD NOTIFICATION + +![Standard Notification](./assets/types/default.svg) + +Simple notifications are very easy! + +```Kotlin +Notify + .with(context) + .content { // this: Payload.Content.Default + // The title of the notification (first line). + title = "New dessert menu" + // The second line of the notification. + text = "The Cheesecake Factory has a new dessert for you to try!" + } + .show() +``` + +#### LIST NOTIFICATION + +![List Notification](./assets/types/list-text.svg) + +Notifications with multiple lines are very common. Notify provides a simple DSL to build these notfications. + +```Kotlin +Notify + .with(context) + .asTextList { // this: Payload.Content.TextList + // The lines that are shown when the notification is expanded. + lines = Arrays.asList("New! Fresh Strawberry Cheesecake.", + "New! Salted Caramel Cheesecake.", + "New! OREO Dream Dessert.") + // The title of the collapsed notification. + title = "New menu items!" + // The second line of the collapsed notification. + text = lines.size.toString() + " new dessert menu items found." + } + .show() +``` + +#### BIG TEXT + +[[https://github.com/karn/notify/blob/develop/docs/assets/types/big-text.svg|alt=Big Text Notification]] + +For instances where you'd like to show a longer message you can use the `BigText` notification type. These kinds of messages are ideal for things such as email content, and news previews. + +```Kotlin +Notify + .with(context) + .asBigText { // this: Payload.Content.TextList + // The title of the notification. + title = "Chocolate brownie sundae" + // The second line of the (collapsed) notification. + text = "Try our newest dessert option!" + // The second line of the expanded notification. + expandedText = "Try our newest dessert option!" + // Large string that is displayed under the line above. + bigText = "Our own Fabulous Godiva Chocolate Brownie, Vanilla " + + "Ice Cream, Hot Fudge, Whipped Cream and Toasted " + + "Almonds.\n\n" + + "Come try this delicious new dessert and get two for " + + "the price of one!" + } + .show() +``` + +#### BIG PICTURE + +![Big Picture Notification](./assets/types/big-picture.svg) + +The big picture allows an application to notify the user in a manner similar to the [screenshot saved](https://www.androidexplained.com/wp-content/uploads/2017/10/Pixel-2-Screenshot-Notification.png) notification which shows a preview of the screenshot within the main content of the notification. + +```Kotlin +Notify + .with(context) + .asBigPicture { + // The title of the notification. + title = "Chocolate brownie sundae" + // The second line of the (collapsed) notification. + text = "Get a look at this amazing dessert!" + // The second line of the expanded notification. + expandedText = "The delicious brownie sundae now available." + // A bitmap that is to be shown. The system will automatically resize + // the image. + image = BitmapFactory.decodeResource(context.resources, + R.drawable.chocolate_brownie_sundae) + } + .show() +``` + +#### MESSAGE NOTIFICATION + +![Messages notification](./assets/types/messages.svg) + +The message notification is useful when displaying conversations within an application. It can also be useful to set the `headerText` field of the `Header` block with the number of messages outside the scope (list.size - 6). + +```Kotlin +Notify + .with(context) + .asMessage { + userDisplayName = "Karn" + conversationTitle = "Sundae chat" + messages = Arrays.asList( + NotificationCompat.MessagingStyle.Message( + "Are you guys ready to try the Strawberry sundae?", + System.currentTimeMillis() - (6 * 60 * 1000), // 6 Mins ago + "Karn"), + NotificationCompat.MessagingStyle.Message( + "Yeah! I've heard great things about this place.", + System.currentTimeMillis() - (5 * 60 * 1000), // 5 Mins ago + "Nitish"), + NotificationCompat.MessagingStyle.Message("What time are you getting there Karn?", + System.currentTimeMillis() - (1 * 60 * 1000), // 1 Mins ago + "Moez") + ) + } + .show() +``` \ No newline at end of file From b02c1dece544b847695a14cd7ac24f74d2f62680 Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Tue, 8 May 2018 19:02:40 -0400 Subject: [PATCH 4/8] Fixed image for Big text sample notification. --- docs/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types.md b/docs/types.md index 7482dce..14fcb3a 100644 --- a/docs/types.md +++ b/docs/types.md @@ -42,7 +42,7 @@ Notify #### BIG TEXT -[[https://github.com/karn/notify/blob/develop/docs/assets/types/big-text.svg|alt=Big Text Notification]] +![Big Text Notification](./assets/types/big-text.svg) For instances where you'd like to show a longer message you can use the `BigText` notification type. These kinds of messages are ideal for things such as email content, and news previews. From cac7f7fe3ad7175e1adb23d7bcc6cff5fb930bb6 Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Tue, 8 May 2018 19:14:28 -0400 Subject: [PATCH 5/8] Convert svgs -> outlines. --- docs/assets/types/big-picture.svg | 46 ++++++------------ docs/assets/types/big-text.svg | 56 +++++++--------------- docs/assets/types/list-text.svg | 46 ++++++------------ docs/assets/types/messages.svg | 80 ++++++++++--------------------- 4 files changed, 71 insertions(+), 157 deletions(-) diff --git a/docs/assets/types/big-picture.svg b/docs/assets/types/big-picture.svg index 0f7b5a4..d63f369 100644 --- a/docs/assets/types/big-picture.svg +++ b/docs/assets/types/big-picture.svg @@ -28,26 +28,18 @@ - - Chocolate brownie sundae - - - Get a look at this amazing dessert! - + + - - now - - - + + + - - Notify - - + + @@ -59,26 +51,18 @@ - - - Chocolate brownie sundae - - - Try our newest dessert option! - + + + - - now - - - + + + - - Notify - - + + diff --git a/docs/assets/types/big-text.svg b/docs/assets/types/big-text.svg index 79ecf5c..47a44a2 100644 --- a/docs/assets/types/big-text.svg +++ b/docs/assets/types/big-text.svg @@ -27,33 +27,19 @@ - - - Chocolate brownie sundae - - - Try our newest dessert option! - - - Our own Fabulous Godiva Chocolate Brownie, Vanilla Ice - Cream, Hot Fudge, Whipped Cream and Toasted Almonds. - - Come try this delicious new dessert and get two for the price - of one! - + + + + - - now - - - + + + - - Notify - - + + @@ -62,26 +48,18 @@ - - - Chocolate brownie sundae - - - Try our newest dessert option! - + + + - - now - - - + + + - - Notify - - + + diff --git a/docs/assets/types/list-text.svg b/docs/assets/types/list-text.svg index b7a2bec..4ba366b 100644 --- a/docs/assets/types/list-text.svg +++ b/docs/assets/types/list-text.svg @@ -28,56 +28,40 @@ - - now - - - + + + - - Notify - - + + - - - New menu items! - - - 3 new dessert menu items found. - + + + - - now - - - + + + - - Notify - - + + - - - New! Fresh Strawberry Cheesecake. - New! Salted Caramel Cheesecake. - New! OREO Dream Dessert. - + + diff --git a/docs/assets/types/messages.svg b/docs/assets/types/messages.svg index dbbfc9e..b2e91b3 100644 --- a/docs/assets/types/messages.svg +++ b/docs/assets/types/messages.svg @@ -28,81 +28,49 @@ - - now - - - + + + - - Notify - - + + - - - Sundae chat - - - Karn - - - Are you guys ready to try the Strawberry sundae? - - - Nitish - - - Yeah! I’ve heard great things about this place. - - - Moez - - - What time are you getting there Karn? - + + + + + + + + - - now - - - + + + - - Notify - - + + - - - Sundae chat - - - Nitish - - - Yeah! I’ve heard great things about this place. - - - Moez - - - What time are you getting there Karn? - + + + + + + From 449bf0dd969baad678ea9d00098133d7e7762ade Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Sun, 13 May 2018 00:28:24 -0400 Subject: [PATCH 6/8] Notification Alerting -- LEDs, vibrations, sounds and lockscreen visibility. (#11) - The alerting object is now closely related to the `NotificationChannels`. For newer versions of Android, the alerting object is used to construct the NotificationChannel, while on older versions it is used in the Notification builder to assign to the appropriate values. It defines a coupling with channels that will provide the best means of building notification alerts. - The notification importance levels have been explicitly defined to prevent confusion on which values to use. This change will automatically be mapped to the various API levels that require a transformation. --- build.gradle | 4 +- gradle/wrapper/gradle-wrapper.properties | 3 +- .../src/main/java/io/karn/notify/Creator.kt | 14 ++- .../karn/notify/NotificationChannelInterop.kt | 57 +++++++++ .../io/karn/notify/NotificationInterop.kt | 35 +++++- .../src/main/java/io/karn/notify/Notify.kt | 66 +++++++--- .../main/java/io/karn/notify/NotifyChannel.kt | 27 ---- .../io/karn/notify/entities/NotifyConfig.kt | 37 +++--- .../java/io/karn/notify/entities/Payload.kt | 50 +++++--- .../java/io/karn/notify/utils/Annotations.kt | 11 ++ .../notify/NotificationChannelInteropTest.kt | 40 ++++++ .../karn/notify/NotificationInterlopTest.kt | 58 +++++++++ .../java/io/karn/notify/NotifyAlertingTest.kt | 117 ++++++++++++++++-- .../java/io/karn/notify/NotifyChannelTest.kt | 55 -------- .../java/io/karn/notify/NotifyHeaderTest.kt | 5 - .../java/io/karn/notify/NotifyMetaTest.kt | 9 +- .../test/java/io/karn/notify/NotifyTest.kt | 77 ++++++++---- .../java/io/karn/notify/NotifyTestBase.kt | 21 +++- .../main/java/presentation/MainActivity.kt | 12 +- 19 files changed, 502 insertions(+), 196 deletions(-) create mode 100644 library/src/main/java/io/karn/notify/NotificationChannelInterop.kt delete mode 100644 library/src/main/java/io/karn/notify/NotifyChannel.kt create mode 100644 library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt create mode 100644 library/src/test/java/io/karn/notify/NotificationInterlopTest.kt delete mode 100644 library/src/test/java/io/karn/notify/NotifyChannelTest.kt diff --git a/build.gradle b/build.gradle index 270f66a..90a6dce 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.2.0-alpha07' + classpath 'com.android.tools.build:gradle:3.2.0-alpha14' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -39,5 +39,5 @@ allprojects { } task wrapper(type: Wrapper) { - gradleVersion = '4.5' + gradleVersion = '4.6' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 02be7ad..bf3de21 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Apr 25 23:19:53 EDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip diff --git a/library/src/main/java/io/karn/notify/Creator.kt b/library/src/main/java/io/karn/notify/Creator.kt index f9cf326..8068f36 100644 --- a/library/src/main/java/io/karn/notify/Creator.kt +++ b/library/src/main/java/io/karn/notify/Creator.kt @@ -15,8 +15,8 @@ import io.karn.notify.utils.NotifyScopeMarker class Creator internal constructor(private val notify: Notify, config: NotifyConfig = NotifyConfig()) { private var meta = Payload.Meta() - private var alerts = Payload.Alerts() - private var header = config.header.copy() + private var alerts = config.defaultAlerting + private var header = config.defaultHeader.copy() private var content: Payload.Content = Payload.Content.Default() private var actions: ArrayList? = null private var stackable: Payload.Stackable? = null @@ -34,8 +34,14 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the Alerting of a notification. This includes visibility, * sounds, lights, etc. + * + * If an existing key is provided the existing channel is retrieved (API >= AndroidO) and set as the alerting + * configuration. If the key is new, the channel is created and set as the alerting configuration. */ - fun alerting(init: Payload.Alerts.() -> Unit): Creator { + fun alerting(key: String, init: Payload.Alerts.() -> Unit = {}): Creator { + // Clone object and assign the key. + this.alerts = this.alerts.copy(channelKey = key) + this.alerts.init() return this @@ -44,7 +50,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the Header of a notification. Specifically, it allows the * modification of the notificationIcon, color, the headerText (optional text next to the - * appName), and finally the channel of the notification if targeting Android O. + * appName), and finally the notifyChannel of the notification if targeting Android O. */ fun header(init: Payload.Header.() -> Unit): Creator { this.header.init() diff --git a/library/src/main/java/io/karn/notify/NotificationChannelInterop.kt b/library/src/main/java/io/karn/notify/NotificationChannelInterop.kt new file mode 100644 index 0000000..e3919e5 --- /dev/null +++ b/library/src/main/java/io/karn/notify/NotificationChannelInterop.kt @@ -0,0 +1,57 @@ +package io.karn.notify + +import android.annotation.SuppressLint +import android.app.NotificationChannel +import android.os.Build +import io.karn.notify.entities.Payload + +/** + * Provides compatibility functionality for the Notification channels introduced in Android O. + */ +internal object NotificationChannelInterop { + @SuppressLint("WrongConstant") + fun with(alerting: Payload.Alerts): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + return false + } + + val notificationManager = Notify.defaultConfig.notificationManager!! + + // Ensure that the alerting is not already registered -- return true if it exists. + notificationManager.getNotificationChannel(alerting.channelKey)?.run { + return true + } + + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + val channel = NotificationChannel(alerting.channelKey, alerting.channelName, alerting.channelImportance + 2).apply { + description = alerting.channelDescription + + // Set the lockscreen visibility. + lockscreenVisibility = alerting.lockScreenVisibility + + alerting.lightColor + .takeIf { it != Notify.NO_LIGHTS } + ?.let { + enableLights(true) + lightColor = alerting.lightColor + } + + alerting.vibrationPattern.takeIf { it.isNotEmpty() }?.also { + enableVibration(true) + vibrationPattern = it.toLongArray() + } + + alerting.sound.also { + setSound(it, android.media.AudioAttributes.Builder().build()) + } + + Unit + } + + // Register the alerting with the system + notificationManager.createNotificationChannel(channel) + + return true + } +} diff --git a/library/src/main/java/io/karn/notify/NotificationInterop.kt b/library/src/main/java/io/karn/notify/NotificationInterop.kt index a96e060..fb51e2f 100644 --- a/library/src/main/java/io/karn/notify/NotificationInterop.kt +++ b/library/src/main/java/io/karn/notify/NotificationInterop.kt @@ -95,7 +95,7 @@ internal object NotificationInterop { } fun buildNotification(notify: Notify, payload: RawNotification): NotificationCompat.Builder { - val builder = NotificationCompat.Builder(notify.context, payload.header.channel) + val builder = NotificationCompat.Builder(notify.context, payload.alerting.channelKey) // Ensures that this notification is marked as a Notify notification. .extend(NotifyExtender()) // The color of the RawNotification Icon, App_Name and the expanded chevron. @@ -115,16 +115,12 @@ internal object NotificationInterop { // The category of the notification which allows android to prioritize the // notification as required. .setCategory(payload.meta.category) - // Manual specification of the priority. - .setPriority(payload.meta.priority) // Set whether or not this notification is only relevant to the current device. .setLocalOnly(payload.meta.localOnly) // Set whether this notification is sticky. .setOngoing(payload.meta.sticky) - // The visibility of the notification on the lockscreen. - .setVisibility(payload.alerting.lockScreenVisibility) // The duration of time after which the notification is automatically dismissed. - .setTimeoutAfter(payload.alerting.timeout) + .setTimeoutAfter(payload.meta.timeout) // Standard notifications have the collapsed title and text. if (payload.content is Payload.Content.Standard) { @@ -139,6 +135,33 @@ internal object NotificationInterop { builder.addAction(it) } + // Attach alerting options. + payload.alerting.apply { + // Register the default alerting. + NotificationChannelInterop.with(this) + + // The visibility of the notification on the lockscreen. + builder.setVisibility(lockScreenVisibility) + + // The lights of the notification. + if (lightColor != Notify.NO_LIGHTS) { + builder.setLights(lightColor, 500, 2000) + } + + // The vibration pattern. + vibrationPattern + .takeIf { it.isNotEmpty() } + ?.also { + builder.setVibrate(it.toLongArray()) + } + + // A custom alerting sound. + builder.setSound(sound) + + // Manual specification of the priority. + builder.priority = channelImportance + } + var style: NotificationCompat.Style? = null payload.stackable?.let { diff --git a/library/src/main/java/io/karn/notify/Notify.kt b/library/src/main/java/io/karn/notify/Notify.kt index 7a4c0d6..bf4cc8f 100644 --- a/library/src/main/java/io/karn/notify/Notify.kt +++ b/library/src/main/java/io/karn/notify/Notify.kt @@ -15,15 +15,45 @@ class Notify internal constructor(internal var context: Context) { /** * The default CHANNEL_ID for a notification on Android O. */ - const val DEFAULT_CHANNEL_KEY = "application_notification" + const val CHANNEL_DEFAULT_KEY = "application_notification" /** * The default CHANNEL_NAME for a notification on Android O. */ - const val DEFAULT_CHANNEL_NAME = "Application notifications." + const val CHANNEL_DEFAULT_NAME = "Application notifications." /** * The default CHANNEL_DESCRIPTION for a notification on Android O. */ - const val DEFAULT_CHANNEL_DESCRIPTION = "General application notifications." + const val CHANNEL_DEFAULT_DESCRIPTION = "General application notifications." + /** + * Lowest priority for a notification. These notifications might not be shown to the user except under special + * circumstances, such as detailed notification logs. + */ + const val IMPORTANCE_MIN = NotificationCompat.PRIORITY_MIN + /** + * Lower priority for notifications that are deemed less important. The UI may choose to show these items + * smaller, or at a different position in the list, compared to notifications with normal importance. + */ + const val IMPORTANCE_LOW = NotificationCompat.PRIORITY_LOW + /** + * Default priority for notifications. If your application does not prioritize its own notifications, use this + * value for all notifications. + */ + const val IMPORTANCE_NORMAL = NotificationCompat.PRIORITY_DEFAULT + /** + * Higher priority for notifications, for more important notifications or alerts. The UI may choose to show + * these items larger, or at a different position in notification lists, compared with your app's notifications + * of normal importance. + */ + const val IMPORTANCE_HIGH = NotificationCompat.PRIORITY_HIGH + /** + * Highest priority for notifications, use for notifications that require the user's prompt attention or input. + */ + const val IMPORTANCE_MAX = NotificationCompat.PRIORITY_MAX + + /** + * The flag to disable notification lights. + */ + const val NO_LIGHTS = 0 // This is the initial configuration of the Notify Creator. internal var defaultConfig = NotifyConfig() @@ -33,15 +63,15 @@ class Notify internal constructor(internal var context: Context) { * * Takes a receiver with the NotifyConfig immutable object which has mutable fields. */ - fun defaultConfig(block: (NotifyConfig) -> Unit) { - block(defaultConfig) + fun defaultConfig(init: NotifyConfig.() -> Unit) { + defaultConfig.init() } /** * A new {@see Notify} and {@see Creator} instance. * - * This object is automatically initialized with the singleton default configuration which - * can be modified using {@see Notify#defaultConfig((NotifyConfig) -> Unit)}. + * This object is automatically initialized with the singleton default configuration which can be modified using + * {@see Notify#defaultConfig((NotifyConfig) -> Unit)}. */ fun with(context: Context): Creator { return Creator(Notify(context), defaultConfig) @@ -52,33 +82,29 @@ class Notify internal constructor(internal var context: Context) { this.context = context.applicationContext // Initialize notification manager instance. - if (Companion.defaultConfig.notificationManager == null) { - Companion.defaultConfig.notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + if (defaultConfig.notificationManager == null) { + defaultConfig.notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } - NotifyChannel.registerChannel( - Companion.defaultConfig.notificationManager!!, - defaultConfig.defaultChannelKey, - defaultConfig.defaultChannelName, - defaultConfig.defaultChannelDescription) + NotificationChannelInterop.with(defaultConfig.defaultAlerting) } /** - * Return the standard {@see NotificationCompat.Builder} after applying fluent API - * transformations (if any) from the {@see Creator} builder object. + * Return the standard {@see NotificationCompat.Builder} after applying fluent API transformations (if any) from the + * {@see Creator} builder object. */ internal fun asBuilder(payload: RawNotification): NotificationCompat.Builder { return NotificationInterop.buildNotification(this, payload) } /** - * Delegate a {@see Notification.Builder} object to the Notify NotificationInterop class which - * builds and displays the notification. + * Delegate a {@see Notification.Builder} object to the Notify NotificationInterop class which builds and displays + * the notification. * * This is a terminal operation. * - * @return An integer corresponding to the ID of the system notification. Any updates should use - * this returned integer to make updates or to cancel the notification. + * @return An integer corresponding to the ID of the system notification. Any updates should use this returned + * integer to make updates or to cancel the notification. */ internal fun show(builder: NotificationCompat.Builder): Int { return NotificationInterop.showNotification(Notify.defaultConfig.notificationManager!!, builder) diff --git a/library/src/main/java/io/karn/notify/NotifyChannel.kt b/library/src/main/java/io/karn/notify/NotifyChannel.kt deleted file mode 100644 index 7e019f1..0000000 --- a/library/src/main/java/io/karn/notify/NotifyChannel.kt +++ /dev/null @@ -1,27 +0,0 @@ -package io.karn.notify - -import android.app.NotificationChannel -import android.app.NotificationManager -import android.os.Build - -/** - * Provides compatibility functionality for the Notification channels introduced in Android O. - */ -internal object NotifyChannel { - - fun registerChannel(notificationManager: NotificationManager, channelKey: String, channelName: String, channelDescription: String, importance: Int = NotificationManager.IMPORTANCE_DEFAULT): Boolean { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - return false - } - - // Create the NotificationChannel, but only on API 26+ because - // the NotificationChannel class is new and not in the support library - val channel = NotificationChannel(channelKey, channelName, importance) - - channel.description = channelDescription - // Register the channel with the system - notificationManager.createNotificationChannel(channel) - - return true - } -} diff --git a/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt b/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt index 6709b62..108bde4 100644 --- a/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt +++ b/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt @@ -1,34 +1,35 @@ package io.karn.notify.entities -import android.annotation.TargetApi import android.app.NotificationManager -import android.os.Build -import android.support.v4.app.NotificationManagerCompat -import io.karn.notify.Notify +import io.karn.notify.NotificationChannelInterop /** * Provider of the initial configuration of the Notify > Creator Fluent API. */ data class NotifyConfig( /** - * The default CHANNEL_ID for a notification on Android O. - */ - @TargetApi(Build.VERSION_CODES.O) val defaultChannelKey: String = Notify.DEFAULT_CHANNEL_KEY, - /** - * The default CHANNEL_NAME for a notification on Android O. - */ - @TargetApi(Build.VERSION_CODES.O) val defaultChannelName: String = Notify.DEFAULT_CHANNEL_NAME, - /** - * The default CHANNEL_DESCRIPTION for a notification on Android O. + * A reference to the notification manager. */ - @TargetApi(Build.VERSION_CODES.O) val defaultChannelDescription: String = Notify.DEFAULT_CHANNEL_DESCRIPTION, + internal var notificationManager: NotificationManager? = null, /** * Specifies the default configuration of a notification (e.g the default notificationIcon, * and notification color.) */ - @TargetApi(Build.VERSION_CODES.O) val header: Payload.Header = Payload.Header(channel = defaultChannelKey), + internal var defaultHeader: Payload.Header = Payload.Header(), /** - * A reference to the notification manager. + * Specifies the default alerting configuration for notifications. */ - internal var notificationManager: NotificationManager? = null -) + internal var defaultAlerting: Payload.Alerts = Payload.Alerts() +) { + fun header(init: Payload.Header.() -> Unit): NotifyConfig { + defaultHeader.init() + return this + } + + fun alerting(key: String, init: Payload.Alerts.() -> Unit): NotifyConfig { + // Clone object and assign the key. + defaultAlerting = defaultAlerting.copy(channelKey = key) + defaultAlerting.init() + return this + } +} diff --git a/library/src/main/java/io/karn/notify/entities/Payload.kt b/library/src/main/java/io/karn/notify/entities/Payload.kt index fe2115e..11b89ae 100644 --- a/library/src/main/java/io/karn/notify/entities/Payload.kt +++ b/library/src/main/java/io/karn/notify/entities/Payload.kt @@ -1,15 +1,17 @@ package io.karn.notify.entities -import android.annotation.TargetApi import android.app.PendingIntent import android.graphics.Bitmap -import android.os.Build +import android.media.RingtoneManager +import android.net.Uri +import android.support.annotation.ColorInt import android.support.annotation.ColorRes import android.support.annotation.DrawableRes import android.support.v4.app.NotificationCompat +import io.karn.notify.Notify import io.karn.notify.R import io.karn.notify.utils.Action -import java.util.* +import io.karn.notify.utils.NotifyImportance /** * Wrapper class to provide configurable options for a NotifcationCompact object. @@ -39,10 +41,6 @@ sealed class Payload { * notification as required. */ var category: String? = null, - /** - * Manual specification of the priority of the notification. - */ - var priority: Int = NotificationCompat.PRIORITY_DEFAULT, /** * Set whether or not this notification is only relevant to the current device. */ @@ -51,7 +49,11 @@ sealed class Payload { * Indicates whether the notification is sticky. If enabled, the notification is not * affected by the clear all and is not dismissible. */ - var sticky: Boolean = false + var sticky: Boolean = false, + /** + * The duration of time in milliseconds after which the notification is automatically dismissed. + */ + var timeout: Long = 0L ) /** @@ -68,9 +70,33 @@ sealed class Payload { */ @NotificationCompat.NotificationVisibility var lockScreenVisibility: Int = NotificationCompat.VISIBILITY_PRIVATE, /** - * The duration of time in milliseconds after which the notification is automatically dismissed. + * The default CHANNEL_ID for a notification on versions >= Android O. */ - var timeout: Long = 0L + val channelKey: String = Notify.CHANNEL_DEFAULT_KEY, + /** + * The default CHANNEL_NAME for a notification on versions >= Android O. + */ + var channelName: String = Notify.CHANNEL_DEFAULT_NAME, + /** + * The default CHANNEL_DESCRIPTION for a notification on versions >= Android O. + */ + var channelDescription: String = Notify.CHANNEL_DEFAULT_DESCRIPTION, + /** + * The default IMPORTANCE for a notification. + */ + @NotifyImportance var channelImportance: Int = Notify.IMPORTANCE_NORMAL, + /** + * The LED colors of the notification notifyChannel. + */ + @ColorInt var lightColor: Int = Notify.NO_LIGHTS, + /** + * Vibration pattern for notification on this notifyChannel. + */ + var vibrationPattern: List = ArrayList(), + /** + * A custom notification sound if any. + */ + var sound: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) ) /** @@ -89,10 +115,6 @@ sealed class Payload { * The optional text that appears next to the appName of a notification. */ var headerText: CharSequence? = null, - /** - * Manual override of channel on which this notification is broadcasted. - */ - @TargetApi(Build.VERSION_CODES.O) var channel: String = "", /** * Setting this field to false results in the timestamp (now, 5m, ...) next to the * application name to be hidden. diff --git a/library/src/main/java/io/karn/notify/utils/Annotations.kt b/library/src/main/java/io/karn/notify/utils/Annotations.kt index 7d1f6f3..1d1b29c 100644 --- a/library/src/main/java/io/karn/notify/utils/Annotations.kt +++ b/library/src/main/java/io/karn/notify/utils/Annotations.kt @@ -1,4 +1,15 @@ package io.karn.notify.utils +import android.support.annotation.IntDef +import io.karn.notify.Notify + @DslMarker annotation class NotifyScopeMarker + +@Retention(AnnotationRetention.SOURCE) +@IntDef(Notify.IMPORTANCE_MIN, + Notify.IMPORTANCE_LOW, + Notify.IMPORTANCE_NORMAL, + Notify.IMPORTANCE_HIGH, + Notify.IMPORTANCE_MAX) +annotation class NotifyImportance diff --git a/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt b/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt new file mode 100644 index 0000000..8d6df75 --- /dev/null +++ b/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt @@ -0,0 +1,40 @@ +package io.karn.notify + +import android.os.Build +import io.karn.notify.entities.Payload +import org.junit.After +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.util.ReflectionHelpers + + +@RunWith(RobolectricTestRunner::class) +class NotificationChannelInteropTest : NotifyTestBase() { + + @After + fun runAfter() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, currentSdkVersion) + } + + @Test + fun registerChannelTest_onAndroidN() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.N_MR1) + + val registeredChannel = NotificationChannelInterop.with(Payload.Alerts()) + + Assert.assertFalse(registeredChannel) + } + + @Test + fun registerChannelTest_onAndroidO() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.O) + + val testAlerting = Payload.Alerts() + val registeredChannel = NotificationChannelInterop.with(testAlerting) + + Assert.assertTrue(registeredChannel) + Assert.assertNotNull(shadowNotificationManager.getNotificationChannel(testAlerting.channelKey)) + } +} diff --git a/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt b/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt new file mode 100644 index 0000000..8f5ee75 --- /dev/null +++ b/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt @@ -0,0 +1,58 @@ +package io.karn.notify + +import android.os.Build +import android.support.v4.app.NotificationCompat +import junit.framework.Assert +import org.junit.After +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.util.ReflectionHelpers + +@RunWith(RobolectricTestRunner::class) +class NotificationInterlopTest : NotifyTestBase() { + + @After + fun runAfter() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, currentSdkVersion) + } + + @Test + fun getActiveNotifications_onAndroidLollipop() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.LOLLIPOP_MR1) + + Notify.with(this.context) + .content { + title = "New dessert menu" + text = "The Cheesecake Factory has a new dessert for you to try!" + } + .show() + + val notifications = NotificationInterop.getActiveNotifications(shadowNotificationManager) + Assert.assertEquals(0, notifications.size) + } + + @Test + fun getActiveNotifications_onAndroidM() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.M) + + Notify.with(this.context) + .content { + title = "New dessert menu" + text = "The Cheesecake Factory has a new dessert for you to try!" + } + .show() + + val ogNotification = NotificationCompat.Builder(this.context, Notify.defaultConfig.defaultAlerting.channelKey) + .setContentTitle("Title") + .setContentText("Text") + .build() + + shadowNotificationManager.notify(123, ogNotification) + + val allNotfications = shadowNotificationManager.activeNotifications + Assert.assertEquals(2, allNotfications.size) + val notifyNotifications = NotificationInterop.getActiveNotifications(shadowNotificationManager) + Assert.assertEquals(1, notifyNotifications.size) + } +} diff --git a/library/src/test/java/io/karn/notify/NotifyAlertingTest.kt b/library/src/test/java/io/karn/notify/NotifyAlertingTest.kt index 6b07ea2..1303dee 100644 --- a/library/src/test/java/io/karn/notify/NotifyAlertingTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyAlertingTest.kt @@ -1,16 +1,30 @@ package io.karn.notify +import android.graphics.Color +import android.media.RingtoneManager +import android.os.Build import android.support.v4.app.NotificationCompat +import org.junit.After import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import org.robolectric.util.ReflectionHelpers @RunWith(RobolectricTestRunner::class) class NotifyAlertingTest : NotifyTestBase() { + @After + fun runAfter() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, currentSdkVersion) + } + @Test - fun defaultAlertingTest() { + fun defaultAlertingTest_onAndroidN() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.N_MR1) + + val testAlerting = Notify.defaultConfig.defaultAlerting + val notification = Notify.with(this.context) .content { title = "New dessert menu" @@ -19,19 +33,61 @@ class NotifyAlertingTest : NotifyTestBase() { .asBuilder() .build() - Assert.assertEquals(0, notification.visibility) - Assert.assertEquals(0, notification.timeoutAfter) + Assert.assertNull(notification.channelId) + Assert.assertEquals(testAlerting.lockScreenVisibility, notification.visibility) + Assert.assertEquals(testAlerting.channelImportance, notification.priority) + // Color comparison nonsense again. + // Assert.assertEquals(testLightColor, notification.color) + Assert.assertNull(notification.vibrate) + Assert.assertEquals(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), notification.sound) + } + + @Test + fun defaultAlertingTest_onAndroidO() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.O) + + val testAlerting = Notify.defaultConfig.defaultAlerting + + Notify.with(this.context) + .content { + title = "New dessert menu" + text = "The Cheesecake Factory has a new dessert for you to try!" + } + .show() + + val shadowChannel = shadowNotificationManager.getNotificationChannel(testAlerting.channelKey) + Assert.assertNotNull(shadowChannel) + Assert.assertEquals(testAlerting.lockScreenVisibility, shadowChannel.lockscreenVisibility) + Assert.assertEquals(testAlerting.channelName, shadowChannel.name) + Assert.assertEquals(testAlerting.channelDescription, shadowChannel.description) + Assert.assertEquals(testAlerting.channelImportance + 2, shadowChannel.importance) + // Assert.assertEquals(testLightColor, shadowChannel.lightColor) + Assert.assertNull(shadowChannel.vibrationPattern) + Assert.assertEquals(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION), shadowChannel.sound) } @Test - fun modifiedAlertingTest() { + fun modifiedAlertingTest_onAndroidN() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.N_MR1) + val testVisibility = NotificationCompat.VISIBILITY_PUBLIC - val testTimeout = 5000L + val testChannelKey = "test_key" + val testChannelName = "Test Channel" + val testChannelDescription = "Test Channel Description" + val testChannelImportance = Notify.IMPORTANCE_HIGH + val testLightColor = Color.CYAN + val testVibrationPattern = listOf(0, 200, 0, 200) + val testSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) val notification = Notify.with(this.context) - .alerting { + .alerting(testChannelKey) { lockScreenVisibility = testVisibility - timeout = testTimeout + channelName = testChannelName + channelDescription = testChannelDescription + channelImportance = testChannelImportance + lightColor = testLightColor + vibrationPattern = testVibrationPattern + sound = testSound } .content { title = "New dessert menu" @@ -40,7 +96,52 @@ class NotifyAlertingTest : NotifyTestBase() { .asBuilder() .build() + Assert.assertNull(notification.channelId) Assert.assertEquals(testVisibility, notification.visibility) - Assert.assertEquals(testTimeout, notification.timeoutAfter) + Assert.assertEquals(testChannelImportance, notification.priority) + // Color comparison nonsense again. + // Assert.assertEquals(testLightColor, notification.color) + Assert.assertEquals(testVibrationPattern, notification.vibrate.asList()) + Assert.assertEquals(testSound, notification.sound) + } + + @Test + fun modifiedAlertingTest_onAndroidO() { + ReflectionHelpers.setStaticField(Build.VERSION::class.java, SDK_INT, Build.VERSION_CODES.O) + + val testVisibility = NotificationCompat.VISIBILITY_PUBLIC + val testChannelKey = "test_key" + val testChannelName = "Test Channel" + val testChannelDescription = "Test Channel Description" + val testChannelImportance = Notify.IMPORTANCE_HIGH + val testLightColor = Color.CYAN + val testVibrationPattern = listOf(0, 200, 0, 200) + val testSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + + Notify.with(this.context) + .alerting(testChannelKey) { + lockScreenVisibility = testVisibility + channelName = testChannelName + channelDescription = testChannelDescription + channelImportance = testChannelImportance + lightColor = testLightColor + vibrationPattern = testVibrationPattern + sound = testSound + } + .content { + title = "New dessert menu" + text = "The Cheesecake Factory has a new dessert for you to try!" + } + .show() + + val shadowChannel = shadowNotificationManager.getNotificationChannel(testChannelKey) + Assert.assertNotNull(shadowChannel) + Assert.assertEquals(testVisibility, shadowChannel.lockscreenVisibility) + Assert.assertEquals(testChannelName, shadowChannel.name) + Assert.assertEquals(testChannelDescription, shadowChannel.description) + Assert.assertEquals(testChannelImportance + 2, shadowChannel.importance) + // Assert.assertEquals(testLightColor, shadowChannel.lightColor) + Assert.assertEquals(testVibrationPattern, shadowChannel.vibrationPattern.toList()) + Assert.assertEquals(testSound, shadowChannel.sound) } } diff --git a/library/src/test/java/io/karn/notify/NotifyChannelTest.kt b/library/src/test/java/io/karn/notify/NotifyChannelTest.kt deleted file mode 100644 index fd67bc6..0000000 --- a/library/src/test/java/io/karn/notify/NotifyChannelTest.kt +++ /dev/null @@ -1,55 +0,0 @@ -package io.karn.notify - -import android.app.NotificationManager -import android.os.Build -import android.support.v4.app.NotificationCompat -import org.junit.After -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.shadow.api.Shadow -import org.robolectric.util.ReflectionHelpers - - -@RunWith(RobolectricTestRunner::class) -class NotifyChannelTest : NotifyTestBase() { - - private var currentSdkVersion = Build.VERSION.SDK_INT - - @After - fun runAfter() { - ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", currentSdkVersion) - } - - @Test - fun registerChannelTest_onAndroidO() { - ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", Build.VERSION_CODES.O) - - val notificationManager = Shadow.newInstanceOf(NotificationManager::class.java) - - val registeredChannel = NotifyChannel.registerChannel(notificationManager, - Notify.DEFAULT_CHANNEL_KEY, - Notify.DEFAULT_CHANNEL_NAME, - Notify.DEFAULT_CHANNEL_DESCRIPTION, - NotificationCompat.PRIORITY_DEFAULT) - - Assert.assertTrue(registeredChannel) - Assert.assertNotNull(notificationManager.getNotificationChannel(Notify.DEFAULT_CHANNEL_KEY)) - } - - @Test - fun registerChannelTest_onAndroidN() { - ReflectionHelpers.setStaticField(Build.VERSION::class.java, "SDK_INT", Build.VERSION_CODES.N_MR1) - - val notificationManager = Shadow.newInstanceOf(NotificationManager::class.java) - - val registeredChannel = NotifyChannel.registerChannel(notificationManager, - Notify.DEFAULT_CHANNEL_KEY, - Notify.DEFAULT_CHANNEL_NAME, - Notify.DEFAULT_CHANNEL_DESCRIPTION, - NotificationCompat.PRIORITY_DEFAULT) - - Assert.assertFalse(registeredChannel) - } -} diff --git a/library/src/test/java/io/karn/notify/NotifyHeaderTest.kt b/library/src/test/java/io/karn/notify/NotifyHeaderTest.kt index 99f43fc..6e551a2 100644 --- a/library/src/test/java/io/karn/notify/NotifyHeaderTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyHeaderTest.kt @@ -13,7 +13,6 @@ class NotifyHeaderTest : NotifyTestBase() { @Test @Ignore fun defaultHeaderTest() { - val notification = Notify.with(this.context) .content { title = "New dessert menu" @@ -28,7 +27,6 @@ class NotifyHeaderTest : NotifyTestBase() { String.format("#%06X", context.resources.getColor(R.color.notification_header_color, context.theme)), String.format("#%06X", 0xFFFFFFFF and notification.color.toLong())) Assert.assertEquals(null, notification.extras.getCharSequence(NotificationCompat.EXTRA_SUB_TEXT)) - Assert.assertEquals(Notify.DEFAULT_CHANNEL_KEY, notification.channelId) Assert.assertTrue(notification.extras.getBoolean(NotificationCompat.EXTRA_SHOW_WHEN)) } @@ -37,7 +35,6 @@ class NotifyHeaderTest : NotifyTestBase() { val testIcon = R.drawable.ic_android_black val testColor = android.R.color.holo_purple val testHeaderText = "New Menu!" - val testChannel = "test_channel" val testShowTimestamp = false val notification = Notify.with(this.context) @@ -45,7 +42,6 @@ class NotifyHeaderTest : NotifyTestBase() { icon = testIcon color = testColor headerText = testHeaderText - channel = testChannel showTimestamp = testShowTimestamp } .content { @@ -60,7 +56,6 @@ class NotifyHeaderTest : NotifyTestBase() { String.format("#%06X", context.resources.getColor(testColor, context.theme)), String.format("#%06X", 0xFFFFFFFF and notification.color.toLong())) Assert.assertEquals(testHeaderText, notification.extras.getCharSequence(NotificationCompat.EXTRA_SUB_TEXT)) - Assert.assertEquals(testChannel, notification.channelId) Assert.assertEquals(testShowTimestamp, notification.extras.getBoolean(NotificationCompat.EXTRA_SHOW_WHEN)) } } diff --git a/library/src/test/java/io/karn/notify/NotifyMetaTest.kt b/library/src/test/java/io/karn/notify/NotifyMetaTest.kt index 66046d2..866e3a6 100644 --- a/library/src/test/java/io/karn/notify/NotifyMetaTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyMetaTest.kt @@ -1,6 +1,5 @@ package io.karn.notify -import android.app.Application import android.app.PendingIntent import android.content.Intent import android.provider.Settings @@ -9,7 +8,6 @@ import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment @RunWith(RobolectricTestRunner::class) class NotifyMetaTest : NotifyTestBase() { @@ -28,7 +26,6 @@ class NotifyMetaTest : NotifyTestBase() { Assert.assertNull(notification.deleteIntent) Assert.assertTrue((notification.flags and NotificationCompat.FLAG_AUTO_CANCEL) != 0) Assert.assertNull(notification.category) - Assert.assertEquals(NotificationCompat.PRIORITY_DEFAULT, notification.priority) } @Test @@ -38,7 +35,7 @@ class NotifyMetaTest : NotifyTestBase() { val testCancelOnClick = false val testCategory = NotificationCompat.CATEGORY_STATUS - val testPriority = NotificationCompat.PRIORITY_MAX + val testTimeout = 5000L val notification = Notify.with(this.context) .meta { @@ -46,7 +43,7 @@ class NotifyMetaTest : NotifyTestBase() { clearIntent = testClearIntent cancelOnClick = testCancelOnClick category = testCategory - priority = testPriority + timeout = testTimeout } .content { title = "New dessert menu" @@ -59,6 +56,6 @@ class NotifyMetaTest : NotifyTestBase() { Assert.assertEquals(testClearIntent, notification.deleteIntent) Assert.assertEquals(testCancelOnClick, (notification.flags and NotificationCompat.FLAG_AUTO_CANCEL) != 0) Assert.assertEquals(testCategory, notification.category) - Assert.assertEquals(testPriority, notification.priority) + Assert.assertEquals(testTimeout, notification.timeoutAfter) } } diff --git a/library/src/test/java/io/karn/notify/NotifyTest.kt b/library/src/test/java/io/karn/notify/NotifyTest.kt index aa27a43..5226cd6 100644 --- a/library/src/test/java/io/karn/notify/NotifyTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyTest.kt @@ -1,34 +1,70 @@ package io.karn.notify -import android.app.NotificationManager +import android.graphics.Color +import android.media.RingtoneManager +import android.support.v4.app.NotificationCompat import junit.framework.Assert import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import org.robolectric.shadow.api.Shadow @RunWith(RobolectricTestRunner::class) -class NotifyTest { - - private val context = RuntimeEnvironment.application +class NotifyTest : NotifyTestBase() { @Test fun initializationTest() { + val testIcon = R.drawable.ic_android_black + val testColor = android.R.color.darker_gray + + val testVisibility = NotificationCompat.VISIBILITY_PUBLIC + val testChannelKey = "test_key_alt" + val testChannelName = "Test Channel" + val testChannelDescription = "Test Channel Description" + val testChannelImportance = Notify.IMPORTANCE_HIGH + val testLightColor = Color.CYAN + val testVibrationPattern = listOf(0, 200, 0, 200) + val testSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + Notify.defaultConfig { - it.header.icon = R.drawable.ic_android_black - it.header.color = android.R.color.darker_gray + header { + icon = testIcon + color = testColor + } + + alerting(testChannelKey) { + lockScreenVisibility = testVisibility + channelName = testChannelName + channelDescription = testChannelDescription + channelImportance = testChannelImportance + lightColor = testLightColor + vibrationPattern = testVibrationPattern + sound = testSound + } } + + val rawNotification = Notify.with(this.context) + .content { + title = "New dessert menu" + text = "The Cheesecake Factory has a new dessert for you to try!" + } + + Assert.assertEquals(context.resources.getDrawable(testIcon, context.theme), rawNotification.asBuilder().build().smallIcon.loadDrawable(context)) + + rawNotification.show() + + val shadowChannel = shadowNotificationManager.getNotificationChannel(testChannelKey) + org.junit.Assert.assertNotNull(shadowChannel) + org.junit.Assert.assertEquals(testVisibility, shadowChannel.lockscreenVisibility) + org.junit.Assert.assertEquals(testChannelName, shadowChannel.name) + org.junit.Assert.assertEquals(testChannelDescription, shadowChannel.description) + org.junit.Assert.assertEquals(testChannelImportance + 2, shadowChannel.importance) + // Assert.assertEquals(testLightColor, shadowChannel.lightColor) + org.junit.Assert.assertEquals(testVibrationPattern, shadowChannel.vibrationPattern.toList()) + org.junit.Assert.assertEquals(testSound, shadowChannel.sound) } @Test fun showNotification() { - val notificationManager = Shadow.newInstanceOf(NotificationManager::class.java) - - Notify.defaultConfig { - it.notificationManager = notificationManager - } - Notify.with(this.context) .content { title = "New dessert menu" @@ -36,18 +72,11 @@ class NotifyTest { } .show() - Assert.assertEquals(1, NotificationInterop.getActiveNotifications(notificationManager).size) + Assert.assertEquals(1, NotificationInterop.getActiveNotifications(shadowNotificationManager).size) } @Test fun cancelNotification() { - // TODO: Inject existing notifications so there is no code duplication. - val notificationManager = Shadow.newInstanceOf(NotificationManager::class.java) - - Notify.defaultConfig { - it.notificationManager = notificationManager - } - val notificationId = Notify.with(this.context) .content { title = "New dessert menu" @@ -55,11 +84,11 @@ class NotifyTest { } .show() - Assert.assertEquals(1, NotificationInterop.getActiveNotifications(notificationManager).size) + Assert.assertEquals(1, NotificationInterop.getActiveNotifications(shadowNotificationManager).size) Notify.with(this.context) .cancel(notificationId) - Assert.assertEquals(0, NotificationInterop.getActiveNotifications(notificationManager).size) + Assert.assertEquals(0, NotificationInterop.getActiveNotifications(shadowNotificationManager).size) } } diff --git a/library/src/test/java/io/karn/notify/NotifyTestBase.kt b/library/src/test/java/io/karn/notify/NotifyTestBase.kt index 58a63d7..a391924 100644 --- a/library/src/test/java/io/karn/notify/NotifyTestBase.kt +++ b/library/src/test/java/io/karn/notify/NotifyTestBase.kt @@ -2,19 +2,32 @@ package io.karn.notify import android.app.Application import android.app.NotificationManager +import android.os.Build +import io.karn.notify.entities.Payload import org.junit.Before import org.robolectric.RuntimeEnvironment import org.robolectric.shadow.api.Shadow open class NotifyTestBase { + + companion object { + @JvmStatic + protected val SDK_INT = "SDK_INT" + @JvmStatic + protected var currentSdkVersion = Build.VERSION.SDK_INT + } + protected val context: Application = RuntimeEnvironment.application + protected var shadowNotificationManager: NotificationManager = Shadow.newInstanceOf(NotificationManager::class.java) @Before - fun resetNotificationManager() { - val notificationManager = Shadow.newInstanceOf(NotificationManager::class.java) - + fun setNotificationManager() { + shadowNotificationManager = Shadow.newInstanceOf(NotificationManager::class.java) Notify.defaultConfig { - it.notificationManager = notificationManager + defaultHeader = Payload.Header() + defaultAlerting = Payload.Alerts() + notificationManager = shadowNotificationManager } + NotificationChannelInterop.with(Notify.defaultConfig.defaultAlerting) } } diff --git a/sample/src/main/java/presentation/MainActivity.kt b/sample/src/main/java/presentation/MainActivity.kt index ce73f1c..cd3be8d 100644 --- a/sample/src/main/java/presentation/MainActivity.kt +++ b/sample/src/main/java/presentation/MainActivity.kt @@ -1,6 +1,8 @@ package presentation import android.graphics.BitmapFactory +import android.graphics.Color +import android.media.RingtoneManager import android.os.Bundle import android.support.v4.app.NotificationCompat import android.support.v7.app.AppCompatActivity @@ -16,7 +18,15 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) Notify.defaultConfig { - it.header.color = R.color.colorPrimaryDark + header { + color = R.color.colorPrimaryDark + } + alerting(Notify.CHANNEL_DEFAULT_KEY) { + lightColor = Color.RED + channelImportance = Notify.IMPORTANCE_HIGH + vibrationPattern = listOf(0, 200, 0, 200) + sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM) + } } } From c637f32e02c2bb864bfc041a29d5f696ccda4ace Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Sun, 13 May 2018 03:35:05 -0400 Subject: [PATCH 7/8] Added people and largeIcon members. (#12) --- .../src/main/java/io/karn/notify/Creator.kt | 3 -- .../io/karn/notify/NotificationInterop.kt | 16 +++++-- .../java/io/karn/notify/entities/Payload.kt | 47 +++++++++++++++---- .../main/java/io/karn/notify/utils/Errors.kt | 1 - .../java/io/karn/notify/NotifyContentTest.kt | 12 ++++- .../java/io/karn/notify/NotifyMetaTest.kt | 4 ++ .../main/java/presentation/MainActivity.kt | 4 -- 7 files changed, 65 insertions(+), 22 deletions(-) diff --git a/library/src/main/java/io/karn/notify/Creator.kt b/library/src/main/java/io/karn/notify/Creator.kt index 8068f36..9dd6626 100644 --- a/library/src/main/java/io/karn/notify/Creator.kt +++ b/library/src/main/java/io/karn/notify/Creator.kt @@ -41,9 +41,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon fun alerting(key: String, init: Payload.Alerts.() -> Unit = {}): Creator { // Clone object and assign the key. this.alerts = this.alerts.copy(channelKey = key) - this.alerts.init() - return this } @@ -54,7 +52,6 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon */ fun header(init: Payload.Header.() -> Unit): Creator { this.header.init() - return this } diff --git a/library/src/main/java/io/karn/notify/NotificationInterop.kt b/library/src/main/java/io/karn/notify/NotificationInterop.kt index fb51e2f..4123580 100644 --- a/library/src/main/java/io/karn/notify/NotificationInterop.kt +++ b/library/src/main/java/io/karn/notify/NotificationInterop.kt @@ -122,6 +122,11 @@ internal object NotificationInterop { // The duration of time after which the notification is automatically dismissed. .setTimeoutAfter(payload.meta.timeout) + // Add contacts if any -- will help display prominently if possible. + payload.meta.contacts.takeIf { it.isNotEmpty() }?.forEach { + builder.addPerson(it) + } + // Standard notifications have the collapsed title and text. if (payload.content is Payload.Content.Standard) { // This is the title of the RawNotification. @@ -130,6 +135,11 @@ internal object NotificationInterop { .setContentText(payload.content.text) } + if (payload.content is Payload.Content.SupportsLargeIcon) { + // Sets the large icon of the notification. + builder.setLargeIcon(payload.content.largeIcon) + } + // Attach all the actions. payload.actions?.forEach { builder.addAction(it) @@ -208,16 +218,12 @@ internal object NotificationInterop { .bigText(bigText) } is Payload.Content.BigPicture -> { - // Document these by linking to resource with labels. (1), (2), etc. - - // This large icon is show in both expanded and collapsed views. Might consider creating a custom view for this. - // builder.setLargeIcon(content.image) - NotificationCompat.BigPictureStyle() // This is the second line in the 'expanded' notification. .setSummaryText(content.expandedText ?: content.text) // This is the picture below. .bigPicture(content.image) + .bigLargeIcon(null) } is Payload.Content.Message -> { diff --git a/library/src/main/java/io/karn/notify/entities/Payload.kt b/library/src/main/java/io/karn/notify/entities/Payload.kt index 11b89ae..e1512a5 100644 --- a/library/src/main/java/io/karn/notify/entities/Payload.kt +++ b/library/src/main/java/io/karn/notify/entities/Payload.kt @@ -53,8 +53,27 @@ sealed class Payload { /** * The duration of time in milliseconds after which the notification is automatically dismissed. */ - var timeout: Long = 0L - ) + var timeout: Long = 0L, + /** + * Add a person that is relevant to this notification. + * + * Depending on user preferences, this may allow the notification to pass through interruption filters, and + * to appear more prominently in the user interface. + * + * The person should be specified by the {@code String} representation of a + * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. + * + * The system will also attempt to resolve {@code mailto:} and {@code tel:} schema + * URIs. The path part of these URIs must exist in the contacts database, in the + * appropriate column, or the reference will be discarded as invalid. Telephone schema + * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}. + */ + internal val contacts: ArrayList = ArrayList() + ) { + fun people(init: ArrayList.() -> Unit) { + contacts.init() + } + } /** * Defines the alerting configuration for a particular notification. This includes notification @@ -141,6 +160,13 @@ sealed class Payload { var text: CharSequence? } + interface SupportsLargeIcon { + /** + * The large icon of the notification. + */ + var largeIcon: Bitmap? + } + /** * Indicates whether a notification is expandable. */ @@ -156,8 +182,9 @@ sealed class Payload { */ data class Default( override var title: CharSequence? = null, - override var text: CharSequence? = null - ) : Content(), Standard + override var text: CharSequence? = null, + override var largeIcon: Bitmap? = null + ) : Content(), Standard, SupportsLargeIcon /** * The object representation of a 'TextList' notification. @@ -165,11 +192,12 @@ sealed class Payload { data class TextList( override var title: CharSequence? = null, override var text: CharSequence? = null, + override var largeIcon: Bitmap? = null, /** * The lines of the notification. */ var lines: List = ArrayList() - ) : Content(), Standard + ) : Content(), Standard, SupportsLargeIcon /** * The object representation of a 'BigText' notification. @@ -177,12 +205,13 @@ sealed class Payload { data class BigText( override var title: CharSequence? = null, override var text: CharSequence? = null, + override var largeIcon: Bitmap? = null, override var expandedText: CharSequence? = null, /** * The large text associated with the notification. */ var bigText: CharSequence? = null - ) : Content(), Standard, Expandable + ) : Content(), Standard, SupportsLargeIcon, Expandable /** * The object representation of a 'BigPicture' notification. @@ -190,17 +219,19 @@ sealed class Payload { data class BigPicture( override var title: CharSequence? = null, override var text: CharSequence? = null, + override var largeIcon: Bitmap? = null, override var expandedText: CharSequence? = null, /** * The large image that appears when the notification is expanded.s */ var image: Bitmap? = null - ) : Content(), Standard, Expandable + ) : Content(), Standard, SupportsLargeIcon, Expandable /** * The object representaiton of a 'Message' notification. */ data class Message( + override var largeIcon: Bitmap? = null, /** * The title of the conversation. */ @@ -213,7 +244,7 @@ sealed class Payload { * A collection of messages associated with a particualar conversation. */ var messages: List = ArrayList() - ) : Content() + ) : Content(), SupportsLargeIcon } /** diff --git a/library/src/main/java/io/karn/notify/utils/Errors.kt b/library/src/main/java/io/karn/notify/utils/Errors.kt index 61f92dc..b9a9a77 100644 --- a/library/src/main/java/io/karn/notify/utils/Errors.kt +++ b/library/src/main/java/io/karn/notify/utils/Errors.kt @@ -1,6 +1,5 @@ package io.karn.notify.utils internal object Errors { - const val INVALID_STACK_KEY_ERROR = "Invalid stack key provided." } diff --git a/library/src/test/java/io/karn/notify/NotifyContentTest.kt b/library/src/test/java/io/karn/notify/NotifyContentTest.kt index 8f65d8a..b519b63 100644 --- a/library/src/test/java/io/karn/notify/NotifyContentTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyContentTest.kt @@ -3,6 +3,7 @@ package io.karn.notify import android.app.Application import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.graphics.drawable.Icon import android.net.Uri import android.os.Bundle import android.os.Parcelable @@ -12,7 +13,6 @@ import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment -import java.util.* @RunWith(RobolectricTestRunner::class) class NotifyContentTest { @@ -63,11 +63,13 @@ class NotifyContentTest { fun defaultNotification() { val testTitle = "New dessert menu" val testText = "The Cheesecake Factory has a new dessert for you to try!" + val testLargeIconResID = R.drawable.notification_tile_bg val notification = Notify.with(this.context) .content { title = testTitle text = testText + largeIcon = BitmapFactory.decodeResource(context.resources, testLargeIconResID) } .asBuilder() .build() @@ -75,6 +77,7 @@ class NotifyContentTest { Assert.assertNull(notification.extras.getCharSequence(NotificationCompat.EXTRA_TEMPLATE)) Assert.assertEquals(testTitle, notification.extras.getCharSequence(NotificationCompat.EXTRA_TITLE).toString()) Assert.assertEquals(testText, notification.extras.getCharSequence(NotificationCompat.EXTRA_TEXT).toString()) + Assert.assertEquals(context.resources.getDrawable(testLargeIconResID, context.theme), notification.getLargeIcon().loadDrawable(this.context)) } @Test @@ -135,6 +138,7 @@ class NotifyContentTest { val testTitle = "Chocolate brownie sundae" val testText = "Get a look at this amazing dessert!" val testCollapsedText = "The delicious brownie sundae now available." + val testLargeIconResID = R.drawable.notification_tile_bg val testImage = BitmapFactory.decodeResource(context.resources, R.drawable.notification_tile_bg) Assert.assertNotNull(testImage) @@ -144,6 +148,7 @@ class NotifyContentTest { text = testText image = testImage expandedText = testCollapsedText + largeIcon = BitmapFactory.decodeResource(context.resources, testLargeIconResID) } .asBuilder() .build() @@ -154,6 +159,11 @@ class NotifyContentTest { // This is an example of Notifications vague methods. The Builder#setSummaryText is // different from the Style#setSummaryText. Assert.assertEquals(testCollapsedText, notification.extras.getCharSequence(NotificationCompat.EXTRA_SUMMARY_TEXT)) + Assert.assertEquals(context.resources.getDrawable(testLargeIconResID, context.theme), notification.getLargeIcon().loadDrawable(this.context)) + + val actualIcon: Icon = notification.extras.getParcelable(NotificationCompat.EXTRA_LARGE_ICON) + Assert.assertNotNull(actualIcon) + val actualImage: Bitmap = notification.extras.getParcelable(NotificationCompat.EXTRA_PICTURE) Assert.assertNotNull(actualImage) diff --git a/library/src/test/java/io/karn/notify/NotifyMetaTest.kt b/library/src/test/java/io/karn/notify/NotifyMetaTest.kt index 866e3a6..b398e16 100644 --- a/library/src/test/java/io/karn/notify/NotifyMetaTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyMetaTest.kt @@ -44,6 +44,9 @@ class NotifyMetaTest : NotifyTestBase() { cancelOnClick = testCancelOnClick category = testCategory timeout = testTimeout + people { + add("mailto:hello@test.com") + } } .content { title = "New dessert menu" @@ -57,5 +60,6 @@ class NotifyMetaTest : NotifyTestBase() { Assert.assertEquals(testCancelOnClick, (notification.flags and NotificationCompat.FLAG_AUTO_CANCEL) != 0) Assert.assertEquals(testCategory, notification.category) Assert.assertEquals(testTimeout, notification.timeoutAfter) + Assert.assertEquals(1, notification.extras.getStringArray(NotificationCompat.EXTRA_PEOPLE)?.size ?: 0) } } diff --git a/sample/src/main/java/presentation/MainActivity.kt b/sample/src/main/java/presentation/MainActivity.kt index cd3be8d..5299772 100644 --- a/sample/src/main/java/presentation/MainActivity.kt +++ b/sample/src/main/java/presentation/MainActivity.kt @@ -2,7 +2,6 @@ package presentation import android.graphics.BitmapFactory import android.graphics.Color -import android.media.RingtoneManager import android.os.Bundle import android.support.v4.app.NotificationCompat import android.support.v7.app.AppCompatActivity @@ -23,9 +22,6 @@ class MainActivity : AppCompatActivity() { } alerting(Notify.CHANNEL_DEFAULT_KEY) { lightColor = Color.RED - channelImportance = Notify.IMPORTANCE_HIGH - vibrationPattern = listOf(0, 200, 0, 200) - sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM) } } } From 2d76e2da36f4f890749f1845c22791a09b73fd54 Mon Sep 17 00:00:00 2001 From: Karn Saheb Date: Sun, 13 May 2018 16:41:45 -0400 Subject: [PATCH 8/8] Package reorg. + Clean up. --- README.md | 16 ++++++---- docs/advanced.md | 10 ++++++ .../src/main/java/io/karn/notify/Notify.kt | 14 ++++---- .../notify/{Creator.kt => NotifyCreator.kt} | 32 +++++++++---------- .../io/karn/notify/entities/NotifyConfig.kt | 3 +- .../java/io/karn/notify/entities/Payload.kt | 4 +-- .../NotificationChannelInterop.kt | 3 +- .../{ => internal}/NotificationInterop.kt | 6 ++-- .../notify/{ => internal}/NotifyExtender.kt | 2 +- .../{entities => internal}/RawNotification.kt | 5 +-- .../notify/{ => internal}/utils/Aliases.kt | 2 +- .../{ => internal}/utils/Annotations.kt | 2 +- .../notify/{ => internal}/utils/Errors.kt | 2 +- .../karn/notify/{ => internal}/utils/Utils.kt | 2 +- .../notify/NotificationChannelInteropTest.kt | 1 + .../karn/notify/NotificationInterlopTest.kt | 1 + .../java/io/karn/notify/NotifyActionsTest.kt | 2 +- .../io/karn/notify/NotifyStackableTest.kt | 6 ++-- .../test/java/io/karn/notify/NotifyTest.kt | 1 + .../java/io/karn/notify/NotifyTestBase.kt | 1 + 20 files changed, 68 insertions(+), 47 deletions(-) create mode 100644 docs/advanced.md rename library/src/main/java/io/karn/notify/{Creator.kt => NotifyCreator.kt} (81%) rename library/src/main/java/io/karn/notify/{ => internal}/NotificationChannelInterop.kt (96%) rename library/src/main/java/io/karn/notify/{ => internal}/NotificationInterop.kt (98%) rename library/src/main/java/io/karn/notify/{ => internal}/NotifyExtender.kt (99%) rename library/src/main/java/io/karn/notify/{entities => internal}/RawNotification.kt (73%) rename library/src/main/java/io/karn/notify/{ => internal}/utils/Aliases.kt (71%) rename library/src/main/java/io/karn/notify/{ => internal}/utils/Annotations.kt (90%) rename library/src/main/java/io/karn/notify/{ => internal}/utils/Errors.kt (72%) rename library/src/main/java/io/karn/notify/{ => internal}/utils/Utils.kt (89%) diff --git a/README.md b/README.md index 3ce9a53..b2419f4 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ Simplified notification delivery for Android. #### GETTING STARTED -You can install Notify using Jitpack while it is still in development. +Notify (pre-)releases are available via JitPack. It is recommended that a specific release version is selected when using the library in production as there may be breaking changes at anytime. -As such there currently are pre-releases available until test coverage is improved. +> **Tip:** Test out the canary channel to try out features by using the latest develop snapshot; `develop-SNAPSHOT`. ``` Groovy // Project level build.gradle @@ -27,8 +27,8 @@ repositories { // Module level build.gradle dependencies { - // -SNAPSHOT (latest release) - implementation "io.karn:notify:-SNAPSHOT" + // Replace version with release version, e.g. 1.0.0-alpha, -SNAPSHOT + implementation "io.karn:notify:[VERSION]" } ``` @@ -48,10 +48,12 @@ Notify ![Basic usecase](./docs/assets/default.svg) -If you run into a case in which the library does not provide the requisite builder functions you can get the `NotificationCompat.Builder` object and continue to use it as you would normally by calling `Creator#asBuilder()`. +If you run into a case in which the library does not provide the requisite builder functions you can get the `NotificationCompat.Builder` object and continue to use it as you would normally by calling `NotifyCreator#asBuilder()`. > **Tip:** You can view other notification styles on the [Notification Types](./docs/types.md) docs page. +> **Tip:** Advanced usage topics are documented [here](./docs/advanced.md). + #### NOTIFICATION ANATOMY ![Anatory](./docs/assets/anatomy.svg) @@ -63,8 +65,8 @@ If you run into a case in which the library does not provide the requisite build | 3 | Header Text | Optional description text. Set using the `Header#headerText` field. | | 4 | Timestamp | Timestamp of the notification. | | 5 | Expand Icon | Indicates that the notification is expandable. | -| 6 | Content | The "meat" of the notification set using of of the `Creator#as[Type]((Type) -> Unit)` scoped functions. | -| 7 | Actions | Set using the `Creator#actions((ArrayList) -> Unit)` scoped function. | +| 6 | Content | The "meat" of the notification set using of of the `NotifyCreator#as[Type]((Type) -> Unit)` scoped functions. | +| 7 | Actions | Set using the `NotifyCreator#actions((ArrayList) -> Unit)` scoped function. | #### CONTRIBUTING There are many ways to [contribute](./.github/CONTRIBUTING.md), you can diff --git a/docs/advanced.md b/docs/advanced.md new file mode 100644 index 0000000..4909f60 --- /dev/null +++ b/docs/advanced.md @@ -0,0 +1,10 @@ +## Advanced Usage +> **Note:** This page is still a work-in-progress. You can help complete the documentation by contributing to the project. + + +#### RESPONDING TO CLICKS +The `Payload.Meta` object provides `clickIntent` and `clearIntent` members which when not `null` will be fired when clicked or dismissed. + +#### STACKABLE NOTIFICATIONS + +#### ACTIONS \ No newline at end of file diff --git a/library/src/main/java/io/karn/notify/Notify.kt b/library/src/main/java/io/karn/notify/Notify.kt index bf4cc8f..f3efcdf 100644 --- a/library/src/main/java/io/karn/notify/Notify.kt +++ b/library/src/main/java/io/karn/notify/Notify.kt @@ -4,7 +4,9 @@ import android.app.NotificationManager import android.content.Context import android.support.v4.app.NotificationCompat import io.karn.notify.entities.NotifyConfig -import io.karn.notify.entities.RawNotification +import io.karn.notify.internal.RawNotification +import io.karn.notify.internal.NotificationChannelInterop +import io.karn.notify.internal.NotificationInterop /** * Simplified Notification delivery for Android. @@ -55,7 +57,7 @@ class Notify internal constructor(internal var context: Context) { */ const val NO_LIGHTS = 0 - // This is the initial configuration of the Notify Creator. + // This is the initial configuration of the Notify NotifyCreator. internal var defaultConfig = NotifyConfig() /** @@ -68,13 +70,13 @@ class Notify internal constructor(internal var context: Context) { } /** - * A new {@see Notify} and {@see Creator} instance. + * A new {@see Notify} and {@see NotifyCreator} instance. * * This object is automatically initialized with the singleton default configuration which can be modified using * {@see Notify#defaultConfig((NotifyConfig) -> Unit)}. */ - fun with(context: Context): Creator { - return Creator(Notify(context), defaultConfig) + fun with(context: Context): NotifyCreator { + return NotifyCreator(Notify(context), defaultConfig) } } @@ -91,7 +93,7 @@ class Notify internal constructor(internal var context: Context) { /** * Return the standard {@see NotificationCompat.Builder} after applying fluent API transformations (if any) from the - * {@see Creator} builder object. + * {@see NotifyCreator} builder object. */ internal fun asBuilder(payload: RawNotification): NotificationCompat.Builder { return NotificationInterop.buildNotification(this, payload) diff --git a/library/src/main/java/io/karn/notify/Creator.kt b/library/src/main/java/io/karn/notify/NotifyCreator.kt similarity index 81% rename from library/src/main/java/io/karn/notify/Creator.kt rename to library/src/main/java/io/karn/notify/NotifyCreator.kt index 9dd6626..7757bab 100644 --- a/library/src/main/java/io/karn/notify/Creator.kt +++ b/library/src/main/java/io/karn/notify/NotifyCreator.kt @@ -3,16 +3,16 @@ package io.karn.notify import android.support.v4.app.NotificationCompat import io.karn.notify.entities.NotifyConfig import io.karn.notify.entities.Payload -import io.karn.notify.entities.RawNotification -import io.karn.notify.utils.Action -import io.karn.notify.utils.Errors -import io.karn.notify.utils.NotifyScopeMarker +import io.karn.notify.internal.RawNotification +import io.karn.notify.internal.utils.Action +import io.karn.notify.internal.utils.Errors +import io.karn.notify.internal.utils.NotifyScopeMarker /** * Fluent API for creating a Notification object. */ @NotifyScopeMarker -class Creator internal constructor(private val notify: Notify, config: NotifyConfig = NotifyConfig()) { +class NotifyCreator internal constructor(private val notify: Notify, config: NotifyConfig = NotifyConfig()) { private var meta = Payload.Meta() private var alerts = config.defaultAlerting @@ -25,7 +25,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon * Scoped function for modifying the Metadata of a notification, such as click intents, * notification category, and priority among other options. */ - fun meta(init: Payload.Meta.() -> Unit): Creator { + fun meta(init: Payload.Meta.() -> Unit): NotifyCreator { this.meta.init() return this @@ -38,7 +38,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon * If an existing key is provided the existing channel is retrieved (API >= AndroidO) and set as the alerting * configuration. If the key is new, the channel is created and set as the alerting configuration. */ - fun alerting(key: String, init: Payload.Alerts.() -> Unit = {}): Creator { + fun alerting(key: String, init: Payload.Alerts.() -> Unit): NotifyCreator { // Clone object and assign the key. this.alerts = this.alerts.copy(channelKey = key) this.alerts.init() @@ -50,7 +50,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon * modification of the notificationIcon, color, the headerText (optional text next to the * appName), and finally the notifyChannel of the notification if targeting Android O. */ - fun header(init: Payload.Header.() -> Unit): Creator { + fun header(init: Payload.Header.() -> Unit): NotifyCreator { this.header.init() return this } @@ -58,7 +58,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the content of a 'Default' notification. */ - fun content(init: Payload.Content.Default.() -> Unit): Creator { + fun content(init: Payload.Content.Default.() -> Unit): NotifyCreator { this.content = Payload.Content.Default() (this.content as Payload.Content.Default).init() return this @@ -67,7 +67,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the content of a 'TextList' notification. */ - fun asTextList(init: Payload.Content.TextList.() -> Unit): Creator { + fun asTextList(init: Payload.Content.TextList.() -> Unit): NotifyCreator { this.content = Payload.Content.TextList() (this.content as Payload.Content.TextList).init() return this @@ -76,7 +76,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the content of a 'BigText' notification. */ - fun asBigText(init: Payload.Content.BigText.() -> Unit): Creator { + fun asBigText(init: Payload.Content.BigText.() -> Unit): NotifyCreator { this.content = Payload.Content.BigText() (this.content as Payload.Content.BigText).init() return this @@ -85,7 +85,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the content of a 'BigPicture' notification. */ - fun asBigPicture(init: Payload.Content.BigPicture.() -> Unit): Creator { + fun asBigPicture(init: Payload.Content.BigPicture.() -> Unit): NotifyCreator { this.content = Payload.Content.BigPicture() (this.content as Payload.Content.BigPicture).init() return this @@ -94,7 +94,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Scoped function for modifying the content of a 'Message' notification. */ - fun asMessage(init: Payload.Content.Message.() -> Unit): Creator { + fun asMessage(init: Payload.Content.Message.() -> Unit): NotifyCreator { this.content = Payload.Content.Message() (this.content as Payload.Content.Message).init() return this @@ -104,7 +104,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon * Scoped function for modifying the 'Actions' of a notification. The transformation * relies on adding standard notification Action objects. */ - fun actions(init: ArrayList.() -> Unit): Creator { + fun actions(init: ArrayList.() -> Unit): NotifyCreator { this.actions = ArrayList() (this.actions as ArrayList).init() return this @@ -114,7 +114,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon * Scoped function for modifying the behaviour of 'Stacked' notifications. The transformation * relies on the 'summaryText' of a stackable notification. */ - fun stackable(init: Payload.Stackable.() -> Unit): Creator { + fun stackable(init: Payload.Stackable.() -> Unit): NotifyCreator { this.stackable = Payload.Stackable() (this.stackable as Payload.Stackable).init() @@ -129,7 +129,7 @@ class Creator internal constructor(private val notify: Notify, config: NotifyCon /** * Return the standard {@see NotificationCompat.Builder} after applying fluent API - * transformations (if any) from the {@see Creator} builder object. + * transformations (if any) from the {@see NotifyCreator} builder object. */ fun asBuilder(): NotificationCompat.Builder { return notify.asBuilder(RawNotification(meta, alerts, header, content, stackable, actions)) diff --git a/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt b/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt index 108bde4..e062737 100644 --- a/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt +++ b/library/src/main/java/io/karn/notify/entities/NotifyConfig.kt @@ -1,10 +1,9 @@ package io.karn.notify.entities import android.app.NotificationManager -import io.karn.notify.NotificationChannelInterop /** - * Provider of the initial configuration of the Notify > Creator Fluent API. + * Provider of the initial configuration of the Notify > NotifyCreator Fluent API. */ data class NotifyConfig( /** diff --git a/library/src/main/java/io/karn/notify/entities/Payload.kt b/library/src/main/java/io/karn/notify/entities/Payload.kt index e1512a5..e51bb9a 100644 --- a/library/src/main/java/io/karn/notify/entities/Payload.kt +++ b/library/src/main/java/io/karn/notify/entities/Payload.kt @@ -10,8 +10,8 @@ import android.support.annotation.DrawableRes import android.support.v4.app.NotificationCompat import io.karn.notify.Notify import io.karn.notify.R -import io.karn.notify.utils.Action -import io.karn.notify.utils.NotifyImportance +import io.karn.notify.internal.utils.Action +import io.karn.notify.internal.utils.NotifyImportance /** * Wrapper class to provide configurable options for a NotifcationCompact object. diff --git a/library/src/main/java/io/karn/notify/NotificationChannelInterop.kt b/library/src/main/java/io/karn/notify/internal/NotificationChannelInterop.kt similarity index 96% rename from library/src/main/java/io/karn/notify/NotificationChannelInterop.kt rename to library/src/main/java/io/karn/notify/internal/NotificationChannelInterop.kt index e3919e5..0c2eee2 100644 --- a/library/src/main/java/io/karn/notify/NotificationChannelInterop.kt +++ b/library/src/main/java/io/karn/notify/internal/NotificationChannelInterop.kt @@ -1,8 +1,9 @@ -package io.karn.notify +package io.karn.notify.internal import android.annotation.SuppressLint import android.app.NotificationChannel import android.os.Build +import io.karn.notify.Notify import io.karn.notify.entities.Payload /** diff --git a/library/src/main/java/io/karn/notify/NotificationInterop.kt b/library/src/main/java/io/karn/notify/internal/NotificationInterop.kt similarity index 98% rename from library/src/main/java/io/karn/notify/NotificationInterop.kt rename to library/src/main/java/io/karn/notify/internal/NotificationInterop.kt index 4123580..fd234b1 100644 --- a/library/src/main/java/io/karn/notify/NotificationInterop.kt +++ b/library/src/main/java/io/karn/notify/internal/NotificationInterop.kt @@ -1,13 +1,13 @@ -package io.karn.notify +package io.karn.notify.internal import android.app.NotificationManager import android.os.Build import android.support.annotation.VisibleForTesting import android.support.v4.app.NotificationCompat import android.text.Html +import io.karn.notify.Notify import io.karn.notify.entities.Payload -import io.karn.notify.entities.RawNotification -import io.karn.notify.utils.Utils +import io.karn.notify.internal.utils.Utils internal object NotificationInterop { diff --git a/library/src/main/java/io/karn/notify/NotifyExtender.kt b/library/src/main/java/io/karn/notify/internal/NotifyExtender.kt similarity index 99% rename from library/src/main/java/io/karn/notify/NotifyExtender.kt rename to library/src/main/java/io/karn/notify/internal/NotifyExtender.kt index 8598f36..7b98744 100644 --- a/library/src/main/java/io/karn/notify/NotifyExtender.kt +++ b/library/src/main/java/io/karn/notify/internal/NotifyExtender.kt @@ -1,4 +1,4 @@ -package io.karn.notify +package io.karn.notify.internal import android.os.Bundle import android.service.notification.StatusBarNotification diff --git a/library/src/main/java/io/karn/notify/entities/RawNotification.kt b/library/src/main/java/io/karn/notify/internal/RawNotification.kt similarity index 73% rename from library/src/main/java/io/karn/notify/entities/RawNotification.kt rename to library/src/main/java/io/karn/notify/internal/RawNotification.kt index c11426c..574acb6 100644 --- a/library/src/main/java/io/karn/notify/entities/RawNotification.kt +++ b/library/src/main/java/io/karn/notify/internal/RawNotification.kt @@ -1,6 +1,7 @@ -package io.karn.notify.entities +package io.karn.notify.internal -import io.karn.notify.utils.Action +import io.karn.notify.entities.Payload +import io.karn.notify.internal.utils.Action internal data class RawNotification( internal val meta: Payload.Meta, diff --git a/library/src/main/java/io/karn/notify/utils/Aliases.kt b/library/src/main/java/io/karn/notify/internal/utils/Aliases.kt similarity index 71% rename from library/src/main/java/io/karn/notify/utils/Aliases.kt rename to library/src/main/java/io/karn/notify/internal/utils/Aliases.kt index 7b77073..1f6704f 100644 --- a/library/src/main/java/io/karn/notify/utils/Aliases.kt +++ b/library/src/main/java/io/karn/notify/internal/utils/Aliases.kt @@ -1,4 +1,4 @@ -package io.karn.notify.utils +package io.karn.notify.internal.utils import android.support.v4.app.NotificationCompat diff --git a/library/src/main/java/io/karn/notify/utils/Annotations.kt b/library/src/main/java/io/karn/notify/internal/utils/Annotations.kt similarity index 90% rename from library/src/main/java/io/karn/notify/utils/Annotations.kt rename to library/src/main/java/io/karn/notify/internal/utils/Annotations.kt index 1d1b29c..83df29f 100644 --- a/library/src/main/java/io/karn/notify/utils/Annotations.kt +++ b/library/src/main/java/io/karn/notify/internal/utils/Annotations.kt @@ -1,4 +1,4 @@ -package io.karn.notify.utils +package io.karn.notify.internal.utils import android.support.annotation.IntDef import io.karn.notify.Notify diff --git a/library/src/main/java/io/karn/notify/utils/Errors.kt b/library/src/main/java/io/karn/notify/internal/utils/Errors.kt similarity index 72% rename from library/src/main/java/io/karn/notify/utils/Errors.kt rename to library/src/main/java/io/karn/notify/internal/utils/Errors.kt index b9a9a77..ae3f47b 100644 --- a/library/src/main/java/io/karn/notify/utils/Errors.kt +++ b/library/src/main/java/io/karn/notify/internal/utils/Errors.kt @@ -1,4 +1,4 @@ -package io.karn.notify.utils +package io.karn.notify.internal.utils internal object Errors { const val INVALID_STACK_KEY_ERROR = "Invalid stack key provided." diff --git a/library/src/main/java/io/karn/notify/utils/Utils.kt b/library/src/main/java/io/karn/notify/internal/utils/Utils.kt similarity index 89% rename from library/src/main/java/io/karn/notify/utils/Utils.kt rename to library/src/main/java/io/karn/notify/internal/utils/Utils.kt index 722ec48..2e26d38 100644 --- a/library/src/main/java/io/karn/notify/utils/Utils.kt +++ b/library/src/main/java/io/karn/notify/internal/utils/Utils.kt @@ -1,4 +1,4 @@ -package io.karn.notify.utils +package io.karn.notify.internal.utils import android.text.Html import java.util.* diff --git a/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt b/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt index 8d6df75..db02ad3 100644 --- a/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt +++ b/library/src/test/java/io/karn/notify/NotificationChannelInteropTest.kt @@ -2,6 +2,7 @@ package io.karn.notify import android.os.Build import io.karn.notify.entities.Payload +import io.karn.notify.internal.NotificationChannelInterop import org.junit.After import org.junit.Assert import org.junit.Test diff --git a/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt b/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt index 8f5ee75..8b50b6a 100644 --- a/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt +++ b/library/src/test/java/io/karn/notify/NotificationInterlopTest.kt @@ -2,6 +2,7 @@ package io.karn.notify import android.os.Build import android.support.v4.app.NotificationCompat +import io.karn.notify.internal.NotificationInterop import junit.framework.Assert import org.junit.After import org.junit.Test diff --git a/library/src/test/java/io/karn/notify/NotifyActionsTest.kt b/library/src/test/java/io/karn/notify/NotifyActionsTest.kt index cfc7aeb..ca08405 100644 --- a/library/src/test/java/io/karn/notify/NotifyActionsTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyActionsTest.kt @@ -1,6 +1,6 @@ package io.karn.notify -import io.karn.notify.utils.Action +import io.karn.notify.internal.utils.Action import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith diff --git a/library/src/test/java/io/karn/notify/NotifyStackableTest.kt b/library/src/test/java/io/karn/notify/NotifyStackableTest.kt index 6747c48..3533901 100644 --- a/library/src/test/java/io/karn/notify/NotifyStackableTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyStackableTest.kt @@ -4,8 +4,10 @@ import android.app.PendingIntent import android.content.Intent import android.provider.Settings import android.support.v4.app.NotificationCompat -import io.karn.notify.utils.Action -import io.karn.notify.utils.Errors +import io.karn.notify.internal.NotificationInterop +import io.karn.notify.internal.NotifyExtender +import io.karn.notify.internal.utils.Action +import io.karn.notify.internal.utils.Errors import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith diff --git a/library/src/test/java/io/karn/notify/NotifyTest.kt b/library/src/test/java/io/karn/notify/NotifyTest.kt index 5226cd6..e0d39ec 100644 --- a/library/src/test/java/io/karn/notify/NotifyTest.kt +++ b/library/src/test/java/io/karn/notify/NotifyTest.kt @@ -3,6 +3,7 @@ package io.karn.notify import android.graphics.Color import android.media.RingtoneManager import android.support.v4.app.NotificationCompat +import io.karn.notify.internal.NotificationInterop import junit.framework.Assert import org.junit.Test import org.junit.runner.RunWith diff --git a/library/src/test/java/io/karn/notify/NotifyTestBase.kt b/library/src/test/java/io/karn/notify/NotifyTestBase.kt index a391924..0b5effa 100644 --- a/library/src/test/java/io/karn/notify/NotifyTestBase.kt +++ b/library/src/test/java/io/karn/notify/NotifyTestBase.kt @@ -4,6 +4,7 @@ import android.app.Application import android.app.NotificationManager import android.os.Build import io.karn.notify.entities.Payload +import io.karn.notify.internal.NotificationChannelInterop import org.junit.Before import org.robolectric.RuntimeEnvironment import org.robolectric.shadow.api.Shadow