Skip to content

Commit

Permalink
Merge pull request #25 from Karn/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Karn authored Jan 2, 2019
2 parents 7b519da + ae79787 commit 861cb36
Show file tree
Hide file tree
Showing 24 changed files with 170 additions and 80 deletions.
22 changes: 5 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@


## Notify
Simplified notification delivery for Android.
Simplified notification construction for Android.

[![Kotlin](https://img.shields.io/badge/Kotlin-1.2.41-blue.svg?style=flat-square)](http://kotlinlang.org)
[![RxJava](https://img.shields.io/badge/Support-27.1.1-6ab344.svg?style=flat-square)](https://github.com/ReactiveX/RxJava/releases/tag/v2.1.10)
[![Kotlin](https://img.shields.io/badge/Kotlin-1.3.11-blue.svg?style=flat-square)](http://kotlinlang.org)
[![AndroidX](https://img.shields.io/badge/AndroidX-1.0-6ab344.svg?style=flat-square)](https://developer.android.com/jetpack/androidx/)
[![Build Status](https://img.shields.io/travis/Karn/notify.svg?style=flat-square)](https://travis-ci.org/Karn/notify)
[![Codecov](https://img.shields.io/codecov/c/github/karn/notify.svg?style=flat-square)](https://codecov.io/gh/Karn/notify)
[![GitHub (pre-)release](https://img.shields.io/github/release/karn/notify/all.svg?style=flat-square)
](./../../releases)

Notify is a Fluent API for Android notifications which lets you build notifications without worrying how they'll look across devices or API versions. You can bring deterministic notifications to your Android projects with clarity & ease so you can finally stop fighting Developer documentation and get back to dev work that really matters.

#### GETTING STARTED
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.

> **Tip:** Test out the canary channel to try out features by using the latest develop snapshot; `develop-SNAPSHOT`.
``` Groovy
```Groovy
// Project level build.gradle
// ...
repositories {
Expand Down Expand Up @@ -54,19 +55,6 @@ If you run into a case in which the library does not provide the requisite build
> **Tip:** Advanced usage topics are documented [here](./docs/advanced.md).
#### NOTIFICATION ANATOMY

![Anatory](./docs/assets/anatomy.svg)

| ID | Name | Description |
| ---- | ------------ | ------------------------------------------------------------------------------------------------------- |
| 1 | Icon | Set using the `Header#icon` field. |
| 2 | App Name | Application name, immutable. |
| 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 `NotifyCreator#as[Type]((Type) -> Unit)` scoped functions. |
| 7 | Actions | Set using the `NotifyCreator#actions((ArrayList<Action>) -> Unit)` scoped function. |

#### CONTRIBUTING
There are many ways to [contribute](./.github/CONTRIBUTING.md), you can
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
group = 'io.karn'
version = '0.0.1'
version = '1.2.0'

subprojects {
apply from: rootProject.file('gradle/configuration.gradle')
Expand Down Expand Up @@ -35,6 +35,6 @@ subprojects {
}

task wrapper(type: Wrapper) {
gradleVersion = '4.7'
gradleVersion = '4.10.2'
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}
98 changes: 96 additions & 2 deletions docs/advanced.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,104 @@
## Advanced Usage
> **Note:** This page is still a work-in-progress. You can help complete the documentation by contributing to the project.
#### NOTIFICATION ANATOMY

![Anatomy](./assets/anatomy.svg)

| ID | Name | Description |
| --- | --- | --- |
| 1 | Icon | Set using the `Header#icon` field. |
| 2 | App Name | Application name, immutable. |
| 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 `NotifyCreator#as[Type]((Type) -> Unit)` scoped functions. |
| 7 | Actions | Set using the `NotifyCreator#actions((ArrayList<Action>) -> Unit)` scoped function. |

#### RESPONDING TO CLICKS
The `Payload.Meta` object provides `clickIntent` and `clearIntent` members which when not `null` will be fired when clicked or dismissed.

The `Payload.Meta` object provides `clickIntent` and `clearIntent` members which when not `null`, will be fired when clicked or dismissed.

```Kotlin
Notify
.with(context)
.meta { // this: Payload.Meta
// Launch the MainActivity once the notification is clicked.
clickIntent = PendingIntent.getActivity(this@MainActivity,
0,
Intent(this@MainActivity, MainActivity::class.java),
0)
// Start a service which clears the badge count once the notification is dismissed.
clearIntent = PendingIntent.getService(this@MainActivity,
0,
Intent(this@MainActivity, MyNotificationService::class.java)
.putExtra("action", "clear_badges"),
0)
}
.content { // this: Payload.Content.Default
title = "New dessert menu"
text = "The Cheesecake Factory has a new dessert for you to try!"
}
.show()
```


#### ACTIONS

Similarly, we can construct actions which can be used to quickly perform tasks without opening your app. The actions are the collection of buttons that are shown below the notification to quickly perform tasks.

```Kotlin
Notify
.with(context)
.content { // this: Payload.Content.Default
title = "New dessert menu"
text = "The Cheesecake Factory has a new dessert for you to try!"
}
.actions { // this: ArrayList<Action>
add(Action(
// The icon corresponding to the action.
R.drawable.ic_app_icon,
// The text corresponding to the action -- this is what shows .
"Clear",
// Swap this PendingIntent for whatever Intent is to be processed when the action is clicked.
PendingIntent.getService(this@MainActivity,
0,
Intent(this@MainActivity, MyNotificationService::class.java)
.putExtra("action", "clear_badges"),
0)
))
}
.show()
```


#### STACKABLE NOTIFICATIONS

#### ACTIONS
Notify provides a solution to the idea of grouping notifications into a "stack". I.e the notifications are grouped into a single notification when there is more than one of the same type as defined by `stackable.key`.
This is a particularly effective method of reducing the clutter of the notification tray while also providing the relevant information.

```Kotlin
Notify
.with(this)
.content { // this: Payload.Content.Default
title = "New dessert menu"
text = "The Cheesecake Factory has a new dessert for you to try!"
}
// Define the notification as being stackable. This block should be the same for all notifications which
// are to be grouped together.
.stackable { // this: Payload.Stackable
// In particular, this key should be the same. The properties of this stackable notification as
// taken from the latest stackable notification's stackable block.
key = "test_key"
// This is the summary of this notification as it appears when it is as part of a stacked notification. This
// String value is what is shown as a single line in the stacked notification.
summaryContent = "test summary content"
// The number of notifications with the same key is passed as the 'count' argument. We happen not to
// use it, but it is there if needed.
summaryTitle = { count -> "Summary title" }
// ... here as well, but we instead choose to use to to update the summary for when the notification
// is collapsed.
summaryDescription = { count -> count.toString() + " new notifications." }
}
.show()
```
Binary file added docs/assets/notify.sketch
Binary file not shown.
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ org.gradle.jvmargs=-Xmx1536m
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.enableUnitTestBinaryResources=true
21 changes: 11 additions & 10 deletions gradle/configuration.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,23 @@


def versions = [
kotlin: '1.2.41',
support: '27.1.1',
kotlin: '1.3.11',
core: '1.0.1',
appcompat: '1.0.2',

jacoco: '0.8.2',
dokka: '0.9.17'
]

def build = [
compileSdk: 27,
targetSdk: 27,
compileSdk: 28,
targetSdk: 28,
minSdk: 19,

jacocoAgentVersion: versions.jacoco,

gradle: [
androidPlugin: 'com.android.tools.build:gradle:3.2.0-alpha18',
androidPlugin: 'com.android.tools.build:gradle:3.2.1',
androidMaven: 'com.github.dcendents:android-maven-gradle-plugin:2.0',
kotlin: "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}",
jacoco: "org.jacoco:org.jacoco.core:${versions.jacoco}",
Expand All @@ -35,16 +36,16 @@ def dependencies = [
stdlib : "org.jetbrains.kotlin:kotlin-stdlib:${versions.kotlin}",
reflect: "org.jetbrains.kotlin:kotlin-reflect:${versions.kotlin}"
],
support: [
compat: "com.android.support:support-compat:${versions.support}",
appcompat: "com.android.support:appcompat-v7:${versions.support}"
androidx: [
core: "androidx.core:core:${versions.core}",
appcompat: "androidx.appcompat:appcompat:${versions.appcompat}"
]
]

def testDependencies = [
instrumentationRunner: 'android.support.test.runner.AndroidJUnitRunner',
instrumentationRunner: 'androidx.test.runner.AndroidJUnitRunner',
junit: 'junit:junit:4.12',
robolectric: 'org.robolectric:robolectric:3.8'
robolectric: 'org.robolectric:robolectric:4.0'
]

ext.config = [
Expand Down
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Sun Dec 30 15:40:11 BRST 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.10.2-all.zip
9 changes: 3 additions & 6 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
targetSdkVersion config.build.targetSdk
minSdkVersion config.build.minSdk

versionCode 1
versionName "1.0"
versionCode 10
versionName "1.2.0"

testInstrumentationRunner config.testDeps.instrumentationRunner
}
Expand Down Expand Up @@ -55,10 +55,7 @@ allprojects {
dependencies {
implementation config.deps.kotlin.stdlib

implementation config.deps.support.compat

// android.support.v4.media.app.NotificationCompat.MediaStyle()
// implementation "com.android.support:support-media-compat:$support_version"
implementation config.deps.androidx.core

testImplementation config.testDeps.junit
testImplementation config.testDeps.robolectric
Expand Down
18 changes: 9 additions & 9 deletions library/src/main/java/io/karn/notify/Notify.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package io.karn.notify

import android.app.NotificationManager
import android.content.Context
import android.support.v4.app.NotificationCompat
import androidx.core.app.NotificationCompat
import io.karn.notify.entities.NotifyConfig
import io.karn.notify.internal.RawNotification
import io.karn.notify.internal.NotificationChannelInterop
import io.karn.notify.internal.NotificationInterop
import io.karn.notify.internal.RawNotification

/**
* Simplified Notification delivery for Android.
Expand Down Expand Up @@ -78,6 +78,13 @@ class Notify internal constructor(internal var context: Context) {
fun with(context: Context): NotifyCreator {
return NotifyCreator(Notify(context), defaultConfig)
}

/**
* Cancel an existing notification with a particular id.
*/
fun cancelNotification(id: Int) {
return NotificationInterop.cancelNotification(Notify.defaultConfig.notificationManager!!, id)
}
}

init {
Expand Down Expand Up @@ -111,11 +118,4 @@ class Notify internal constructor(internal var context: Context) {
internal fun show(builder: NotificationCompat.Builder): Int {
return NotificationInterop.showNotification(Notify.defaultConfig.notificationManager!!, builder)
}

/**
* Cancel an existing notification with a particular id.
*/
internal fun cancel(id: Int) {
return NotificationInterop.cancelNotification(Notify.defaultConfig.notificationManager!!, id)
}
}
12 changes: 10 additions & 2 deletions library/src/main/java/io/karn/notify/NotifyCreator.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.karn.notify

import android.support.v4.app.NotificationCompat
import androidx.core.app.NotificationCompat
import io.karn.notify.entities.NotifyConfig
import io.karn.notify.entities.Payload
import io.karn.notify.internal.RawNotification
Expand Down Expand Up @@ -148,7 +148,15 @@ class NotifyCreator internal constructor(private val notify: Notify, config: Not
return notify.show(asBuilder())
}

/**
* Cancel an existing notification given an ID.
*
* @deprecated Choose to instead use the static function {@see Notify#cancelNotification()} which provides the correct
* encapsulation of the this `cancel` function.
*/
@Deprecated(message = "Exposes function under the incorrect API -- NotifyCreator is reserved strictly for notification construction.",
replaceWith = ReplaceWith("Notify.cancelNotification(id)", "io.karn.notify.Notify"))
fun cancel(id: Int) {
return notify.cancel(id)
return Notify.cancelNotification(id)
}
}
6 changes: 3 additions & 3 deletions library/src/main/java/io/karn/notify/entities/Payload.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import android.app.PendingIntent
import android.graphics.Bitmap
import android.media.RingtoneManager
import android.net.Uri
import android.support.annotation.ColorInt
import android.support.annotation.DrawableRes
import android.support.v4.app.NotificationCompat
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.core.app.NotificationCompat
import io.karn.notify.Notify
import io.karn.notify.R
import io.karn.notify.internal.utils.Action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ 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 androidx.annotation.VisibleForTesting
import androidx.core.app.NotificationCompat
import io.karn.notify.Notify
import io.karn.notify.entities.Payload
import io.karn.notify.internal.utils.Utils
Expand Down
10 changes: 5 additions & 5 deletions library/src/main/java/io/karn/notify/internal/NotifyExtender.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package io.karn.notify.internal

import android.os.Bundle
import android.service.notification.StatusBarNotification
import android.support.annotation.VisibleForTesting
import android.support.v4.app.NotificationCompat
import androidx.annotation.VisibleForTesting
import androidx.core.app.NotificationCompat

/**
* Helper class to add Notify Extensions to a notification. The extensions contain data specific to
Expand Down Expand Up @@ -81,11 +81,11 @@ internal class NotifyExtender : NotificationCompat.Extender {
*/
constructor(notification: StatusBarNotification) {
// Fetch the extensions if any, from a given notification.
NotificationCompat.getExtras(notification.notification).let {
it.getBundle(EXTRA_NOTIFY_EXTENSIONS)?.let {
NotificationCompat.getExtras(notification.notification)?.let { bundle ->
bundle.getBundle(EXTRA_NOTIFY_EXTENSIONS)?.let {
loadConfigurationFromBundle(it)
}
it.getCharSequenceArray(NotificationCompat.EXTRA_TEXT_LINES)?.let {
bundle.getCharSequenceArray(NotificationCompat.EXTRA_TEXT_LINES)?.let {
stackItems = ArrayList(it.toList())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package io.karn.notify.internal.utils

import android.support.v4.app.NotificationCompat
import androidx.core.app.NotificationCompat

typealias Action = NotificationCompat.Action
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.karn.notify.internal.utils

import android.support.annotation.IntDef
import androidx.annotation.IntDef
import io.karn.notify.Notify

@DslMarker
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.karn.notify

import android.os.Build
import android.support.v4.app.NotificationCompat
import androidx.core.app.NotificationCompat
import io.karn.notify.internal.NotificationInterop
import org.junit.After
import org.junit.Assert
Expand Down
Loading

0 comments on commit 861cb36

Please sign in to comment.