Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APPS-3513: Notification analytics #933

Merged
merged 13 commits into from
Jan 18, 2022
Merged
10 changes: 10 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,16 @@
</intent-filter>
</receiver>

<receiver android:name="org.stepik.android.view.base.receiver.DismissedNotificationReceiver">
<intent-filter>
<action android:name="remind_app_notification_dismissed" />
<action android:name="remind_registration_notification_dismissed" />
<action android:name="retention_notification_dismissed" />
<action android:name="deadlines_notification_dismissed" />
<action android:name="streak_notification_dismissed" />
</intent-filter>
</receiver>

<service
android:name=".persistence.service.DownloadCompleteService"
android:permission="android.permission.BIND_JOB_SERVICE"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/stepic/droid/di/AppCoreComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ import org.stepik.android.view.onboarding.ui.activity.OnboardingGoalActivity
import org.stepik.android.view.personal_deadlines.ui.dialogs.EditDeadlinesDialog
import org.stepik.android.view.personal_deadlines.ui.dialogs.LearningRateDialog
import org.stepik.android.view.purchase_notification.receiver.PurchaseNotificationReceiver
import org.stepik.android.view.base.receiver.DismissedNotificationReceiver
import org.stepik.android.view.streak.ui.dialog.StreakNotificationDialogFragment
import org.stepik.android.view.video_player.ui.service.VideoPlayerForegroundService

Expand Down Expand Up @@ -386,4 +387,5 @@ interface AppCoreComponent {

fun inject(transactionBottomSheetDialogFragmentFragment: TransactionBottomSheetDialogFragment)
fun inject(videoPlayerForegroundService: VideoPlayerForegroundService)
fun inject(dismissedNotificationReceiver: DismissedNotificationReceiver)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import android.content.Context
import android.content.Intent
import org.stepic.droid.analytic.Analytic
import org.stepic.droid.base.App
import org.stepic.droid.preferences.SharedPreferenceHelper
import org.stepic.droid.storage.operations.DatabaseFacade
import org.stepic.droid.util.AppConstants
import timber.log.Timber
import java.util.concurrent.ThreadPoolExecutor
import javax.inject.Inject

Expand All @@ -22,9 +20,6 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
@Inject
lateinit var analytic: Analytic

@Inject
lateinit var sharedPreferences: SharedPreferenceHelper

init {
App.component().inject(this)
}
Expand All @@ -39,15 +34,6 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
databaseFacade.removeAllNotificationsWithCourseId(courseId)
}
}
} else if (action == AppConstants.NOTIFICATION_CANCELED_REMINDER) {
Timber.d(Analytic.Notification.REMINDER_SWIPE_TO_CANCEL)
analytic.reportEvent(Analytic.Notification.REMINDER_SWIPE_TO_CANCEL)
} else if (action == AppConstants.NOTIFICATION_CANCELED_STREAK) {
analytic.reportEvent(Analytic.Notification.STREAK_SWIPE_TO_CANCEL)
//continue send notification about streaks
threadPool.execute {
sharedPreferences.resetNumberOfStreakNotifications()
rostikjoystick marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,15 @@ enum class RetentionNotificationType(
val messageRes: Int
) {
DAY1(R.string.retention_notification_day1_title, R.string.retention_notification_day1_message),
DAY3(R.string.retention_notification_day3_title, R.string.retention_notification_day3_message)
DAY3(R.string.retention_notification_day3_title, R.string.retention_notification_day3_message);

fun getDayInt(): Int =
rostikjoystick marked this conversation as resolved.
Show resolved Hide resolved
when (this.name) {
DAY1.name ->
1
DAY3.name ->
3
else ->
throw IllegalStateException("Invalid enum state")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,20 @@ import org.stepic.droid.util.AppConstants
import org.stepic.droid.util.DateTimeHelper
import org.stepic.droid.util.commit
import org.stepik.android.domain.course.analytic.CourseViewSource
import org.stepik.android.domain.remind.analytic.RemindAppNotificationClicked
import org.stepik.android.domain.streak.analytic.StreakNotificationClicked
import org.stepik.android.domain.streak.interactor.StreakInteractor
import org.stepik.android.model.Course
import org.stepik.android.view.catalog.ui.fragment.CatalogFragment
import org.stepik.android.view.course_list.notification.RemindAppNotificationDelegate
import org.stepik.android.view.course_list.routing.getCourseListCollectionId
import org.stepik.android.view.debug.ui.fragment.DebugMenu
import org.stepik.android.view.profile.ui.fragment.ProfileFragment
import org.stepik.android.view.story_deeplink.routing.getStoryId
import org.stepik.android.view.story_deeplink.ui.dialog.StoryDeepLinkDialogFragment
import org.stepik.android.view.streak.notification.StreakNotificationDelegate
import org.stepik.android.view.streak.ui.dialog.StreakNotificationDialogFragment
import ru.nobird.android.view.base.ui.extension.showIfNotExists
import timber.log.Timber
import java.util.concurrent.ThreadPoolExecutor
import javax.inject.Inject

Expand All @@ -58,7 +61,6 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
companion object {
const val CURRENT_INDEX_KEY = "currentIndexKey"

const val reminderKey = "reminderKey"
const val defaultIndex: Int = 0
private const val LOGGED_ACTION = "LOGGED_ACTION"

Expand All @@ -75,6 +77,8 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
const val NOTIFICATIONS_INDEX: Int = 4
const val DEBUG_INDEX: Int = 5

const val EXTRA_STREAK_TYPE = "streak_type"

fun launchAfterLogin(sourceActivity: Activity, course: Course?) {
val intent = Intent(sourceActivity, MainFeedActivity::class.java)
if (course != null) {
Expand Down Expand Up @@ -118,41 +122,48 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
notificationClickedCheck(intent)
checkShortcutAction(intent)

openFragment(intent)
}

private fun notificationClickedCheck(intent: Intent) {
/**
* We call this only from onCreate, because all the notifications launch MainFeedActivity through FLAG_ACTIVITY_NEW_TASK
*/
private fun checkNotificationClick(intent: Intent) {
val action = intent.action
if (action != null) {
if (action == AppConstants.OPEN_NOTIFICATION) {
analytic.reportEvent(AppConstants.OPEN_NOTIFICATION)
} else if (action == AppConstants.OPEN_NOTIFICATION_FOR_ENROLL_REMINDER) {
var dayTypeString: String? = intent.getStringExtra(reminderKey)
if (dayTypeString == null) {
dayTypeString = ""
when (action) {
RemindAppNotificationDelegate.REMIND_APP_NOTIFICATION_CLICKED -> {
sharedPreferenceHelper.clickEnrollNotification(DateTimeHelper.nowUtc())
analytic.report(RemindAppNotificationClicked)
}
analytic.reportEvent(Analytic.Notification.REMIND_OPEN, dayTypeString)
Timber.d(Analytic.Notification.REMIND_OPEN)
sharedPreferenceHelper.clickEnrollNotification(DateTimeHelper.nowUtc())
} else if (action == AppConstants.OPEN_NOTIFICATION_FROM_STREAK) {
sharedPreferenceHelper.resetNumberOfStreakNotifications()
if (intent.hasExtra(Analytic.Streak.NOTIFICATION_TYPE_PARAM)) {
val notificationType = intent.getSerializableExtra(Analytic.Streak.NOTIFICATION_TYPE_PARAM) as Analytic.Streak.NotificationType
val bundle = Bundle()
bundle.putString(Analytic.Streak.NOTIFICATION_TYPE_PARAM, notificationType.name)
analytic.reportEvent(Analytic.Streak.STREAK_NOTIFICATION_OPENED, bundle)
} else {
analytic.reportEvent(Analytic.Streak.STREAK_NOTIFICATION_OPENED)

StreakNotificationDelegate.STREAK_NOTIFICATION_CLICKED -> {
sharedPreferenceHelper.resetNumberOfStreakNotifications()
val streakType = intent.getStringExtra(EXTRA_STREAK_TYPE)
if (streakType != null) {
analytic.report(StreakNotificationClicked(streakType))
}
}
} else if (action == AppConstants.OPEN_SHORTCUT_CATALOG) {
}

//after tracking check on null user
if (sharedPreferenceHelper.authResponseFromStore == null) {
screenManager.openSplash(this)
}
}
}

private fun checkShortcutAction(intent: Intent) {
val action = intent.action
if (action != null) {
if (action == AppConstants.OPEN_SHORTCUT_CATALOG) {
analytic.reportEvent(Analytic.Shortcut.OPEN_CATALOG)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
getSystemService(ShortcutManager::class.java)
?.reportShortcutUsed(AppConstants.CATALOG_SHORTCUT_ID)
}

}

//after tracking check on null user
Expand All @@ -170,7 +181,8 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),

setContentView(R.layout.activity_main_feed)

notificationClickedCheck(intent)
checkShortcutAction(intent)
checkNotificationClick(intent)

initGoogleApiClient(true)

Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,20 @@ import org.stepic.droid.core.presenters.SplashPresenter
import org.stepic.droid.core.presenters.contracts.SplashView
import org.stepic.droid.util.AppConstants
import org.stepic.droid.util.defaultLocale
import org.stepik.android.domain.remind.analytic.RemindRegistrationNotificationClicked
import org.stepik.android.domain.retention.analytic.RetentionNotificationClicked
import org.stepik.android.view.retention.model.RetentionNotificationData
import org.stepik.android.view.routing.deeplink.BranchRoute
import org.stepik.android.view.splash.notification.RemindRegistrationNotificationDelegate
import org.stepik.android.view.splash.notification.RetentionNotificationDelegate
import java.util.Arrays
import javax.inject.Inject

class SplashActivity : BackToExitActivityBase(), SplashView {

companion object {
const val EXTRA_RETENTION_NOTIFICATION_DATA = "retention_notification_data"

private const val RUSSIAN_LANGUAGE_CODE = "ru"
}

Expand All @@ -55,7 +62,19 @@ class SplashActivity : BackToExitActivityBase(), SplashView {
// finish()
// return
// }
when (intent.action) {
rostikjoystick marked this conversation as resolved.
Show resolved Hide resolved
RemindRegistrationNotificationDelegate.REMIND_REGISTRATION_NOTIFICATION_CLICKED ->
analytics.report(RemindRegistrationNotificationClicked)

RetentionNotificationDelegate.RETENTION_NOTIFICATION_CLICKED -> {
val retentionNotificationData = intent
.getParcelableExtra<RetentionNotificationData>(EXTRA_RETENTION_NOTIFICATION_DATA)

if (retentionNotificationData != null) {
analytics.report(RetentionNotificationClicked(retentionNotificationData.retentionDay))
}
}
}
defineShortcuts()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ constructor(
}

fun hasUserInteractedWithApp(): Boolean =
sharedPreferenceHelper.authResponseFromStore == null ||
sharedPreferenceHelper.isStreakNotificationEnabled ||
rostikjoystick marked this conversation as resolved.
Show resolved Hide resolved
hasEnrolledCourses() ||
sharedPreferenceHelper.anyStepIsSolved()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.stepik.android.domain.personal_deadlines.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

class DeadlinesNotificationClicked(
course: Long,
hours: Long
) : AnalyticEvent {
companion object {
private const val PARAM_COURSE = "course"
private const val PARAM_HOURS = "hours"
}

override val name: String =
"Personal deadlines app notification clicked"

override val params: Map<String, Any> =
mapOf(
PARAM_COURSE to course,
PARAM_HOURS to hours
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.stepik.android.domain.personal_deadlines.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

class DeadlinesNotificationDismissed(
course: Long,
hours: Long
) : AnalyticEvent {
companion object {
private const val PARAM_COURSE = "course"
private const val PARAM_HOURS = "hours"
}

override val name: String =
"Personal deadlines app notification dismissed"

override val params: Map<String, Any> =
mapOf(
PARAM_COURSE to course,
PARAM_HOURS to hours
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.stepik.android.domain.personal_deadlines.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

class DeadlinesNotificationShown(
course: Long,
hours: Long
) : AnalyticEvent {
companion object {
private const val PARAM_COURSE = "course"
private const val PARAM_HOURS = "hours"
}

override val name: String =
"Personal deadlines app notification shown"

override val params: Map<String, Any> =
mapOf(
PARAM_COURSE to course,
PARAM_HOURS to hours
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindAppNotificationClicked : AnalyticEvent {
override val name: String =
"Remind app notification clicked"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindAppNotificationDismissed : AnalyticEvent {
override val name: String =
"Remind app notification dismissed"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindAppNotificationShown : AnalyticEvent {
override val name: String =
"Remind app notification shown"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindRegistrationNotificationClicked : AnalyticEvent {
override val name: String =
"Remind registration notification clicked"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindRegistrationNotificationDismissed : AnalyticEvent {
override val name: String =
"Remind registration notification dismissed"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.domain.remind.analytic

import org.stepik.android.domain.base.analytic.AnalyticEvent

object RemindRegistrationNotificationShown : AnalyticEvent {
override val name: String =
"Remind registration notification shown"
}
Loading