-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14691 from wordpress-mobile/feature/14639-push-no…
…tification-workmanager Setup for local push notifications
- Loading branch information
Showing
12 changed files
with
323 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
WordPress/src/main/java/org/wordpress/android/workers/CreateSiteNotificationHandler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package org.wordpress.android.workers | ||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import org.wordpress.android.fluxc.store.AccountStore | ||
import org.wordpress.android.fluxc.store.SiteStore | ||
import javax.inject.Inject | ||
|
||
class CreateSiteNotificationHandler @Inject constructor( | ||
private val accountStore: AccountStore, | ||
private val siteStore: SiteStore | ||
) : LocalNotificationHandler { | ||
override fun shouldShowNotification(): Boolean { | ||
return accountStore.hasAccessToken() && !siteStore.hasSite() | ||
} | ||
|
||
override fun buildIntent(context: Context): Intent { | ||
return Intent() // TODO: Replace this with respective intent in ActivityLauncher | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
WordPress/src/main/java/org/wordpress/android/workers/LocalNotification.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package org.wordpress.android.workers | ||
|
||
import androidx.annotation.DrawableRes | ||
import androidx.annotation.StringRes | ||
import org.wordpress.android.push.NotificationPushIds | ||
import java.util.concurrent.TimeUnit | ||
|
||
data class LocalNotification( | ||
val type: Type, | ||
val delay: Long, | ||
val delayUnits: TimeUnit, | ||
@StringRes val title: Int, | ||
@StringRes val text: Int, | ||
@DrawableRes val icon: Int, | ||
@DrawableRes val actionIcon: Int, | ||
@StringRes val actionTitle: Int, | ||
val uniqueId: Int? = null | ||
) { | ||
val id = uniqueId ?: NotificationPushIds.LOCAL_NOTIFICATION_ID + type.ordinal | ||
|
||
enum class Type(val tag: String) { | ||
CREATE_SITE("create_site"); | ||
|
||
companion object { | ||
fun fromTag(tag: String?): Type? { | ||
return when (tag) { | ||
CREATE_SITE.tag -> CREATE_SITE | ||
else -> null | ||
} | ||
} | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
WordPress/src/main/java/org/wordpress/android/workers/LocalNotificationHandlerFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.wordpress.android.workers | ||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import org.wordpress.android.workers.LocalNotification.Type | ||
import org.wordpress.android.workers.LocalNotification.Type.CREATE_SITE | ||
import javax.inject.Inject | ||
|
||
class LocalNotificationHandlerFactory @Inject constructor( | ||
private val createSiteNotificationHandler: CreateSiteNotificationHandler | ||
) { | ||
fun buildLocalNotificationHandler(type: Type): LocalNotificationHandler { | ||
return when (type) { | ||
CREATE_SITE -> createSiteNotificationHandler | ||
} | ||
} | ||
} | ||
|
||
interface LocalNotificationHandler { | ||
fun shouldShowNotification(): Boolean | ||
fun buildIntent(context: Context): Intent | ||
} |
47 changes: 47 additions & 0 deletions
47
WordPress/src/main/java/org/wordpress/android/workers/LocalNotificationScheduler.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.wordpress.android.workers | ||
|
||
import androidx.core.app.NotificationManagerCompat | ||
import androidx.work.OneTimeWorkRequestBuilder | ||
import androidx.work.WorkManager | ||
import org.wordpress.android.viewmodel.ContextProvider | ||
import org.wordpress.android.workers.LocalNotification.Type | ||
import javax.inject.Inject | ||
|
||
class LocalNotificationScheduler @Inject constructor( | ||
private val contextProvider: ContextProvider, | ||
private val localNotificationHandlerFactory: LocalNotificationHandlerFactory | ||
) { | ||
fun scheduleOneTimeNotification(localNotification: LocalNotification): Boolean { | ||
val localPushHandler = localNotificationHandlerFactory.buildLocalNotificationHandler(localNotification.type) | ||
if (localPushHandler.shouldShowNotification()) { | ||
val work = OneTimeWorkRequestBuilder<LocalNotificationWorker>() | ||
.setInitialDelay(localNotification.delay, localNotification.delayUnits) | ||
.addTag(localNotification.type.tag) | ||
.setInputData( | ||
LocalNotificationWorker.buildData( | ||
localNotification | ||
) | ||
) | ||
.build() | ||
|
||
WorkManager.getInstance(contextProvider.getContext()).enqueue( | ||
work | ||
) | ||
return true | ||
} else { | ||
return false | ||
} | ||
} | ||
|
||
fun cancelScheduledNotification(notificationType: Type) { | ||
WorkManager.getInstance(contextProvider.getContext()).cancelAllWorkByTag(notificationType.tag) | ||
} | ||
|
||
fun cancelNotification(pushId: Int) { | ||
if (pushId != -1) { | ||
with(NotificationManagerCompat.from(contextProvider.getContext())) { | ||
cancel(pushId) | ||
} | ||
} | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
WordPress/src/main/java/org/wordpress/android/workers/LocalNotificationWorker.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package org.wordpress.android.workers | ||
|
||
import android.app.PendingIntent | ||
import android.content.Context | ||
import androidx.core.app.NotificationCompat | ||
import androidx.core.app.NotificationManagerCompat | ||
import androidx.core.content.ContextCompat | ||
import androidx.work.CoroutineWorker | ||
import androidx.work.Data | ||
import androidx.work.ListenableWorker | ||
import androidx.work.WorkerFactory | ||
import androidx.work.WorkerParameters | ||
import androidx.work.workDataOf | ||
import org.wordpress.android.R | ||
import org.wordpress.android.workers.LocalNotification.Type | ||
|
||
class LocalNotificationWorker( | ||
val context: Context, | ||
params: WorkerParameters, | ||
private val localNotificationHandlerFactory: LocalNotificationHandlerFactory | ||
) : CoroutineWorker(context, params) { | ||
@Suppress("TooGenericExceptionCaught") | ||
override suspend fun doWork(): Result { | ||
val id = inputData.getInt(ID, -1) | ||
|
||
if (id == -1) return Result.failure() | ||
|
||
with(NotificationManagerCompat.from(context)) { | ||
notify(id, localNotificationBuilder().build()) | ||
} | ||
|
||
return Result.success() | ||
} | ||
|
||
private fun localNotificationBuilder(): NotificationCompat.Builder { | ||
val title = inputData.getInt(TITLE, -1) | ||
val text = inputData.getInt(TEXT, -1) | ||
val icon = inputData.getInt(ICON, -1) | ||
val actionIcon = inputData.getInt(ACTION_ICON, -1) | ||
val actionTitle = inputData.getInt(ACTION_TITLE, -1) | ||
|
||
return NotificationCompat.Builder(context, context.getString(R.string.notification_channel_normal_id)).apply { | ||
val pendingIntent = getPendingIntent() | ||
setContentIntent(pendingIntent) | ||
setSmallIcon(icon) | ||
setContentTitle(context.getString(title)) | ||
setContentText(context.getString(text)) | ||
addAction(actionIcon, context.getString(actionTitle), pendingIntent) | ||
priority = NotificationCompat.PRIORITY_DEFAULT | ||
setCategory(NotificationCompat.CATEGORY_REMINDER) | ||
setAutoCancel(true) | ||
setColorized(true) | ||
color = ContextCompat.getColor(context, R.color.blue_50) | ||
} | ||
} | ||
|
||
private fun getPendingIntent(): PendingIntent { | ||
val type = Type.fromTag(inputData.getString(TYPE)) | ||
val handler = type?.let { localNotificationHandlerFactory.buildLocalNotificationHandler(it) } | ||
return PendingIntent.getActivity( | ||
context, | ||
0, | ||
handler?.buildIntent(context), | ||
PendingIntent.FLAG_CANCEL_CURRENT | ||
) | ||
} | ||
|
||
class Factory( | ||
private val localNotificationHandlerFactory: LocalNotificationHandlerFactory | ||
) : WorkerFactory() { | ||
override fun createWorker( | ||
appContext: Context, | ||
workerClassName: String, | ||
workerParameters: WorkerParameters | ||
): ListenableWorker? { | ||
return if (workerClassName == LocalNotificationWorker::class.java.name) { | ||
LocalNotificationWorker(appContext, workerParameters, localNotificationHandlerFactory) | ||
} else { | ||
null | ||
} | ||
} | ||
} | ||
|
||
companion object { | ||
private const val TYPE = "key_type" | ||
private const val ID = "key_id" | ||
private const val TITLE = "key_title" | ||
private const val TEXT = "key_text" | ||
private const val ICON = "key_icon" | ||
private const val ACTION_ICON = "key_action_icon" | ||
private const val ACTION_TITLE = "key_action_title" | ||
|
||
fun buildData(localNotification: LocalNotification): Data { | ||
return workDataOf( | ||
TYPE to localNotification.type.tag, | ||
ID to localNotification.id, | ||
TITLE to localNotification.title, | ||
TEXT to localNotification.text, | ||
ICON to localNotification.icon, | ||
ACTION_ICON to localNotification.actionIcon, | ||
ACTION_TITLE to localNotification.actionTitle | ||
) | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
WordPress/src/main/java/org/wordpress/android/workers/WordPressWorkersFactory.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package org.wordpress.android.workers | ||
|
||
import androidx.work.DelegatingWorkerFactory | ||
import org.wordpress.android.fluxc.store.SiteStore | ||
import org.wordpress.android.ui.uploads.UploadStarter | ||
import org.wordpress.android.util.UploadWorker | ||
import javax.inject.Inject | ||
|
||
class WordPressWorkersFactory @Inject constructor( | ||
uploadStarter: UploadStarter, | ||
siteStore: SiteStore, | ||
localNotificationHandlerFactory: LocalNotificationHandlerFactory | ||
) : DelegatingWorkerFactory() { | ||
init { | ||
addFactory(UploadWorker.Factory(uploadStarter, siteStore)) | ||
addFactory(LocalNotificationWorker.Factory(localNotificationHandlerFactory)) | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
WordPress/src/test/java/org/wordpress/android/workers/CreateSiteNotificationHandlerTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package org.wordpress.android.workers | ||
|
||
import com.nhaarman.mockitokotlin2.whenever | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.mockito.Mock | ||
import org.mockito.junit.MockitoJUnitRunner | ||
import org.wordpress.android.fluxc.store.AccountStore | ||
import org.wordpress.android.fluxc.store.SiteStore | ||
|
||
@RunWith(MockitoJUnitRunner::class) | ||
class CreateSiteNotificationHandlerTest { | ||
@Mock | ||
lateinit var accountStore: AccountStore | ||
@Mock | ||
lateinit var siteStore: SiteStore | ||
|
||
@Before | ||
fun setUp() { | ||
whenever(accountStore.hasAccessToken()).thenReturn(true) | ||
whenever(siteStore.hasSite()).thenReturn(false) | ||
} | ||
|
||
@Test | ||
fun verifyShouldShowNotification() { | ||
assertThat(accountStore.hasAccessToken() && !siteStore.hasSite()).isTrue | ||
} | ||
|
||
@Test | ||
fun verifyShouldNotShowNotification() { | ||
assertThat(accountStore.hasAccessToken() && siteStore.hasSite()).isFalse | ||
} | ||
|
||
@Test | ||
fun verifyDoesNotShowNotification() { | ||
assertThat(!accountStore.hasAccessToken() && !siteStore.hasSite()).isFalse | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
WordPress/src/test/java/org/wordpress/android/workers/LocalNotificationHandlerFactoryTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package org.wordpress.android.workers | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.Before | ||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
import org.mockito.Mock | ||
import org.mockito.junit.MockitoJUnitRunner | ||
import org.wordpress.android.workers.LocalNotification.Type.CREATE_SITE | ||
|
||
@RunWith(MockitoJUnitRunner::class) | ||
class LocalNotificationHandlerFactoryTest { | ||
@Mock | ||
lateinit var createSiteNotificationHandler: CreateSiteNotificationHandler | ||
|
||
lateinit var localNotificationHandlerFactory: LocalNotificationHandlerFactory | ||
|
||
@Before | ||
fun setUp() { | ||
localNotificationHandlerFactory = LocalNotificationHandlerFactory(createSiteNotificationHandler) | ||
} | ||
|
||
@Test | ||
fun verifyLocalNotificationHandlerBuildsCorrectHandler() { | ||
val handler = localNotificationHandlerFactory.buildLocalNotificationHandler(CREATE_SITE) | ||
assertThat(handler).isInstanceOf(CreateSiteNotificationHandler::class.java) | ||
} | ||
} |