-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package io.customer.messagingpush.activity | ||
|
||
import android.app.Activity | ||
import android.content.Intent | ||
import android.os.Bundle | ||
import androidx.core.app.TaskStackBuilder | ||
import io.customer.messagingpush.MessagingPushModuleConfig | ||
import io.customer.messagingpush.config.NotificationClickBehavior | ||
import io.customer.messagingpush.data.model.CustomerIOParsedPushPayload | ||
import io.customer.messagingpush.di.deepLinkUtil | ||
import io.customer.messagingpush.di.moduleConfig | ||
import io.customer.messagingpush.extensions.parcelable | ||
import io.customer.messagingpush.util.DeepLinkUtil | ||
import io.customer.sdk.CustomerIO | ||
import io.customer.sdk.CustomerIOShared | ||
import io.customer.sdk.data.request.MetricEvent | ||
import io.customer.sdk.extensions.takeIfNotBlank | ||
import io.customer.sdk.tracking.TrackableScreen | ||
import io.customer.sdk.util.Logger | ||
|
||
/** | ||
* Activity to handle notification click events. | ||
* | ||
* This activity is launched when a notification is clicked. It tracks opened | ||
* metrics, handles the deep link and opens the desired activity in the host app. | ||
*/ | ||
class NotificationClickReceiverActivity : Activity(), TrackableScreen { | ||
val logger: Logger by lazy { CustomerIOShared.instance().diStaticGraph.logger } | ||
Check warning on line 28 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L27-L28
|
||
|
||
override fun getScreenName(): String? { | ||
// Return null to prevent this screen from being tracked | ||
return null | ||
Check warning on line 32 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L32
|
||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
handleIntent(data = intent) | ||
} | ||
Check warning on line 38 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L36-L38
|
||
|
||
override fun onNewIntent(intent: Intent?) { | ||
super.onNewIntent(intent) | ||
handleIntent(data = intent) | ||
} | ||
Check warning on line 43 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L41-L43
|
||
|
||
private fun handleIntent(data: Intent?) { | ||
kotlin.runCatching { | ||
val payload: CustomerIOParsedPushPayload? = | ||
Check warning on line 47 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L46-L47
|
||
data?.extras?.parcelable(NOTIFICATION_PAYLOAD_EXTRA) | ||
if (payload == null) { | ||
logger.error("Payload is null, cannot handle notification intent") | ||
Check warning on line 50 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L50
|
||
} else { | ||
processNotificationIntent(payload = payload) | ||
Check warning on line 52 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L52
|
||
} | ||
}.onFailure { ex -> | ||
logger.error("Failed to process notification intent: ${ex.message}") | ||
} | ||
finish() | ||
} | ||
Check warning on line 58 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L55-L58
|
||
|
||
private fun processNotificationIntent(payload: CustomerIOParsedPushPayload) { | ||
val sdkInstance = CustomerIO.instanceOrNull(context = this) | ||
Check warning on line 61 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L61
|
||
if (sdkInstance == null) { | ||
logger.error("SDK is not initialized, cannot handle notification intent") | ||
return | ||
Check warning on line 64 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L63-L64
|
||
} | ||
|
||
val moduleConfig: MessagingPushModuleConfig = sdkInstance.diGraph.moduleConfig | ||
trackMetrics(moduleConfig, payload) | ||
handleDeepLink(moduleConfig, payload) | ||
} | ||
Check warning on line 70 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L67-L70
|
||
|
||
private fun trackMetrics( | ||
moduleConfig: MessagingPushModuleConfig, | ||
payload: CustomerIOParsedPushPayload | ||
) { | ||
if (moduleConfig.autoTrackPushEvents) { | ||
CustomerIO.instance().trackMetric( | ||
payload.cioDeliveryId, | ||
MetricEvent.opened, | ||
payload.cioDeliveryToken | ||
Check warning on line 80 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L77-L80
|
||
) | ||
} | ||
} | ||
Check warning on line 83 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L83
|
||
|
||
private fun handleDeepLink( | ||
moduleConfig: MessagingPushModuleConfig, | ||
payload: CustomerIOParsedPushPayload | ||
) { | ||
val deepLinkUtil: DeepLinkUtil = CustomerIO.instance().diGraph.deepLinkUtil | ||
Check warning on line 89 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L89
|
||
val deepLink = payload.deepLink?.takeIfNotBlank() | ||
|
||
// check if host app overrides the handling of deeplink | ||
val notificationCallback = moduleConfig.notificationCallback | ||
Check warning on line 93 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L93
|
||
val taskStackFromPayload = notificationCallback?.createTaskStackFromPayload(this, payload) | ||
if (taskStackFromPayload != null) { | ||
logger.info("Notification target overridden by createTaskStackFromPayload, starting new stack for link $deepLink") | ||
taskStackFromPayload.startActivities() | ||
return | ||
Check warning on line 98 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L96-L98
|
||
} | ||
|
||
// Get the default intent for the host app | ||
val defaultHostAppIntent = deepLinkUtil.createDefaultHostAppIntent( | ||
context = this, | ||
contentActionLink = null | ||
Check warning on line 104 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L102-L104
|
||
) | ||
// Check if the deep links are handled within the host app | ||
val deepLinkHostAppIntent = deepLink?.let { link -> | ||
deepLinkUtil.createDeepLinkHostAppIntent(context = this, link = link) | ||
Check warning on line 108 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L108
|
||
} | ||
// Check if the deep links can be opened outside the host app | ||
val deepLinkExternalIntent = deepLink?.let { link -> | ||
deepLinkUtil.createDeepLinkExternalIntent( | ||
context = this, | ||
link = link, | ||
startingFromService = true | ||
Check warning on line 115 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L112-L115
|
||
) | ||
} | ||
val deepLinkIntent: Intent = deepLinkHostAppIntent | ||
?: deepLinkExternalIntent | ||
?: defaultHostAppIntent | ||
?: return | ||
deepLinkIntent.putExtra(NOTIFICATION_PAYLOAD_EXTRA, payload) | ||
logger.info("Dispatching notification with link $deepLink to intent: $deepLinkIntent with behavior: ${moduleConfig.notificationOnClickBehavior}") | ||
Check warning on line 123 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L121-L123
|
||
|
||
when (moduleConfig.notificationOnClickBehavior) { | ||
NotificationClickBehavior.RESET_TASK_STACK -> { | ||
val taskStackBuilder = TaskStackBuilder.create(this).apply { | ||
addNextIntentWithParentStack(deepLinkIntent) | ||
} | ||
taskStackBuilder.startActivities() | ||
Check warning on line 130 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L127-L130
|
||
} | ||
|
||
NotificationClickBehavior.ACTIVITY_PREVENT_RESTART -> { | ||
deepLinkIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or | ||
Check warning on line 134 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L134
|
||
Intent.FLAG_ACTIVITY_SINGLE_TOP | ||
startActivity(deepLinkIntent) | ||
Check warning on line 136 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L136
|
||
} | ||
|
||
NotificationClickBehavior.ACTIVITY_NO_FLAGS -> { | ||
startActivity(deepLinkIntent) | ||
Check warning on line 140 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L140
|
||
} | ||
} | ||
} | ||
Check warning on line 143 in messagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt Codecov / codecov/patchmessagingpush/src/main/java/io/customer/messagingpush/activity/NotificationClickReceiverActivity.kt#L143
|
||
|
||
companion object { | ||
const val NOTIFICATION_PAYLOAD_EXTRA = "CIO_NotificationPayloadExtras" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package io.customer.messagingpush.config | ||
|
||
/** | ||
* Defines the behaviors for what happens when a notification is clicked. | ||
*/ | ||
enum class NotificationClickBehavior { | ||
|
||
/** | ||
* Resets the task stack to include the deep-linked activity 'D'. | ||
* - Example 1: Stack (A -> B -> C) becomes (D) if D is the deep-linked activity. | ||
* - Example 2: Stack (A -> B -> C) changes to (A -> D) if D is the deep-linked activity and A is the root of the task stack provided by callback. | ||
* | ||
* This is similar to Android's "Set up a regular activity PendingIntent." | ||
* For more info, see [Android Documentation](https://developer.android.com/develop/ui/views/notifications/navigation#DirectEntry). | ||
*/ | ||
RESET_TASK_STACK, | ||
|
||
/** | ||
* Adds the deep-linked activity 'D' to the existing stack only if it's not already there. | ||
* - Example: Stack (A -> B) becomes (A -> B -> D) if D is the deep-linked activity and not already in the stack. | ||
* - Example: Stack (A -> B -> D) stays as (A -> B -> D) if D is the deep-linked activity and is already in the stack. | ||
* | ||
* The same activity instance will be reused and receive the data in `onNewIntent` if already on top. | ||
* | ||
* This is similar to Android's "Set up a special activity PendingIntent." | ||
* For more info, see [Android Documentation](https://developer.android.com/develop/ui/views/notifications/navigation#ExtendedNotification). | ||
*/ | ||
ACTIVITY_PREVENT_RESTART, | ||
|
||
/** | ||
* Starts the deep-linked activity without adding any intent flags. | ||
* - Example: Stack (A -> B) becomes (A -> B -> D) if D is the deep-linked target activity. | ||
* | ||
* This behavior relies on the launch mode or flags specified for the activity in the Android manifest. | ||
* System default behaviors will take over if no flags are mentioned. | ||
*/ | ||
ACTIVITY_NO_FLAGS | ||
} |