diff --git a/build.gradle b/build.gradle index 4449cdf3..528146e6 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.1.1' - classpath 'com.google.gms:google-services:3.1.1' + classpath 'com.google.gms:google-services:3.2.1' classpath 'com.google.firebase:firebase-plugins:1.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'io.fabric.tools:gradle:1.24.4' diff --git a/client/build.gradle b/client/build.gradle index d55ea3e5..58f6b018 100644 --- a/client/build.gradle +++ b/client/build.gradle @@ -64,12 +64,12 @@ dependencies { compile 'com.android.support:support-compat:27.1.1' compile 'com.android.support:animated-vector-drawable:27.1.1' - compile 'com.google.firebase:firebase-core:15.0.0' - compile 'com.google.firebase:firebase-config:15.0.0' - compile 'com.google.firebase:firebase-perf:15.0.0' - compile 'com.google.firebase:firebase-messaging:15.0.0' - compile 'com.google.firebase:firebase-database:15.0.0' - compile 'com.crashlytics.sdk.android:crashlytics:2.9.1' + compile 'com.google.firebase:firebase-core:15.0.2' + compile 'com.google.firebase:firebase-config:15.0.2' + compile 'com.google.firebase:firebase-perf:15.1.0' + compile 'com.google.firebase:firebase-messaging:15.0.2' + compile 'com.google.firebase:firebase-database:15.0.1' + compile 'com.crashlytics.sdk.android:crashlytics:2.9.2' compile 'android.arch.lifecycle:runtime:1.1.1' diff --git a/client/src/main/java/com/jraska/github/client/AppComponent.kt b/client/src/main/java/com/jraska/github/client/AppComponent.kt index f48f1de9..6c42308e 100644 --- a/client/src/main/java/com/jraska/github/client/AppComponent.kt +++ b/client/src/main/java/com/jraska/github/client/AppComponent.kt @@ -5,6 +5,7 @@ import com.jraska.github.client.analytics.AnalyticsProperty import com.jraska.github.client.analytics.EventAnalytics import com.jraska.github.client.http.HttpComponent import com.jraska.github.client.logging.CrashReporter +import com.jraska.github.client.push.PushModule import com.jraska.github.client.users.UserViewModelModule import com.jraska.github.client.users.data.UsersDataModule import dagger.Component @@ -14,7 +15,7 @@ import retrofit2.Retrofit @PerApp @Component(modules = arrayOf(UsersDataModule::class, UserViewModelModule::class, - NavigationModule::class, AppModule::class, HttpComponentModule::class, CoreComponentModule::class)) + NavigationModule::class, PushModule::class, AppModule::class, HttpComponentModule::class, CoreComponentModule::class)) interface AppComponent { fun inject(app: GitHubClientApp) } diff --git a/client/src/main/java/com/jraska/github/client/RealDeepLinkLauncher.kt b/client/src/main/java/com/jraska/github/client/RealDeepLinkLauncher.kt index 828e5a29..bc83eca0 100644 --- a/client/src/main/java/com/jraska/github/client/RealDeepLinkLauncher.kt +++ b/client/src/main/java/com/jraska/github/client/RealDeepLinkLauncher.kt @@ -1,6 +1,5 @@ package com.jraska.github.client -import com.jraska.github.client.common.DeveloperError import com.jraska.github.client.ui.BaseActivity import com.jraska.github.client.ui.RepoDetailActivity import com.jraska.github.client.ui.UserDetailActivity diff --git a/client/src/main/java/com/jraska/github/client/push/ConfigAsPropertyCommand.kt b/client/src/main/java/com/jraska/github/client/push/ConfigAsPropertyCommand.kt new file mode 100644 index 00000000..8e90eb96 --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/ConfigAsPropertyCommand.kt @@ -0,0 +1,15 @@ +package com.jraska.github.client.push + +import com.jraska.github.client.Config +import com.jraska.github.client.analytics.AnalyticsProperty + +class ConfigAsPropertyCommand constructor(private val config: Config, + private val analyticsProperty: AnalyticsProperty) : PushActionCommand { + override fun execute(action: PushAction): Boolean { + val key = action.parameters["config_key"] ?: return false + + val value = config.getString(key) + analyticsProperty.setUserProperty(key, value) + return true + } +} diff --git a/client/src/main/java/com/jraska/github/client/push/PushActionCommand.kt b/client/src/main/java/com/jraska/github/client/push/PushActionCommand.kt new file mode 100644 index 00000000..9103429b --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/PushActionCommand.kt @@ -0,0 +1,5 @@ +package com.jraska.github.client.push + +interface PushActionCommand { + fun execute(action: PushAction): Boolean +} diff --git a/client/src/main/java/com/jraska/github/client/push/PushHandler.kt b/client/src/main/java/com/jraska/github/client/push/PushHandler.kt index 4f6ac66b..85f80fd1 100644 --- a/client/src/main/java/com/jraska/github/client/push/PushHandler.kt +++ b/client/src/main/java/com/jraska/github/client/push/PushHandler.kt @@ -1,29 +1,16 @@ package com.jraska.github.client.push -import android.app.NotificationManager -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.support.v4.app.NotificationCompat -import com.jraska.github.client.Config -import com.jraska.github.client.NotificationSetup -import com.jraska.github.client.R import com.jraska.github.client.analytics.AnalyticsEvent -import com.jraska.github.client.analytics.AnalyticsProperty import com.jraska.github.client.analytics.EventAnalytics -import com.jraska.github.client.ui.UriHandlerActivity -import dagger.Lazy import timber.log.Timber import javax.inject.Inject +import javax.inject.Provider class PushHandler @Inject internal constructor( private val eventAnalytics: EventAnalytics, private val tokenSynchronizer: PushTokenSynchronizer, - private val config: Lazy, - private val analyticsProperty: Lazy, - private val context: Context, - private val notificationManager: NotificationManager) { + private val pushCommands: Map>) { + internal fun handlePush(action: PushAction) { Timber.v("Push received action: %s", action.name) @@ -44,58 +31,9 @@ class PushHandler @Inject internal constructor( } private fun handleInternal(action: PushAction): Boolean { - return when (action.name) { - ACTION_REFRESH_CONFIG -> refreshConfig() - ACTION_CONFIG_VALUE_AS_PROPERTY -> configAsProperty(action) - ACTION_SET_ANALYTICS_PROPERTY -> setAnalyticsProperty(action) - ACTION_NOTIFICATION -> showNotification(action) - - else -> false - } - } - - private fun showNotification(action: PushAction): Boolean { - val title = action.parameters["title"] ?: return false - val message = action.parameters["message"] ?: return false - val deepLink = action.parameters["clickDeepLink"] ?: return false - - val intent = Intent(context, UriHandlerActivity::class.java) - intent.data = Uri.parse(deepLink) - - val linkContentIntent = PendingIntent.getActivity(context, 0, intent, 0) - - val notification = NotificationCompat.Builder(context, NotificationSetup.PUSH_CHANNEL_ID) - .setSmallIcon(R.mipmap.ic_launcher) - .setContentTitle(title) - .setContentText(message) - .setContentIntent(linkContentIntent) - .setAutoCancel(true) - .build() - - notificationManager.notify(PUSH_NOTIFICATION_ID, notification) - return true - } + val actionCommand = pushCommands.get(action.name) ?: return false - private fun setAnalyticsProperty(action: PushAction): Boolean { - val key = action.parameters["property_key"] ?: return false - - val value = action.parameters["property_value"] ?: return false - - analyticsProperty.get().setUserProperty(key, value) - return true - } - - private fun configAsProperty(action: PushAction): Boolean { - val key = action.parameters["config_key"] ?: return false - - val value = config.get().getString(key) - analyticsProperty.get().setUserProperty(key, value) - return true - } - - private fun refreshConfig(): Boolean { - config.get().triggerRefresh() - return true + return actionCommand.get().execute(action) } internal fun onTokenRefresh() { @@ -104,13 +42,4 @@ class PushHandler @Inject internal constructor( val tokenEvent = AnalyticsEvent.create("push_token_refresh") eventAnalytics.report(tokenEvent) } - - companion object { - private const val ACTION_REFRESH_CONFIG = "refresh_config" - private const val ACTION_CONFIG_VALUE_AS_PROPERTY = "set_config_as_property" - private const val ACTION_SET_ANALYTICS_PROPERTY = "set_analytics_property" - private const val ACTION_NOTIFICATION = "notification" - - private const val PUSH_NOTIFICATION_ID: Int = 1 - } } diff --git a/client/src/main/java/com/jraska/github/client/push/PushModule.kt b/client/src/main/java/com/jraska/github/client/push/PushModule.kt new file mode 100644 index 00000000..c0b9c4e0 --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/PushModule.kt @@ -0,0 +1,45 @@ +package com.jraska.github.client.push + +import android.app.NotificationManager +import android.content.Context +import com.jraska.github.client.Config +import com.jraska.github.client.analytics.AnalyticsProperty +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoMap +import dagger.multibindings.StringKey + +@Module +object PushModule { + @JvmStatic + @Provides + @IntoMap + @StringKey("refresh_config") + fun refreshConfigCommand(config: Config): PushActionCommand { + return RefreshConfigCommand(config) + } + + @JvmStatic + @Provides + @IntoMap + @StringKey("set_config_as_property") + fun configAsPropertyCommand(config: Config, analyticsProperty: AnalyticsProperty): PushActionCommand { + return ConfigAsPropertyCommand(config, analyticsProperty) + } + + @JvmStatic + @Provides + @IntoMap + @StringKey("set_analytics_property") + fun setAnalyticsProperty(analyticsProperty: AnalyticsProperty): PushActionCommand { + return SetAnalyticsPropertyPushCommand(analyticsProperty) + } + + @JvmStatic + @Provides + @IntoMap + @StringKey("notification") + fun notificationCommand(context: Context, notificationManager: NotificationManager): PushActionCommand { + return ShowNotificationPushCommand(context, notificationManager) + } +} diff --git a/client/src/main/java/com/jraska/github/client/push/RefreshConfigCommand.kt b/client/src/main/java/com/jraska/github/client/push/RefreshConfigCommand.kt new file mode 100644 index 00000000..c96bc723 --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/RefreshConfigCommand.kt @@ -0,0 +1,10 @@ +package com.jraska.github.client.push + +import com.jraska.github.client.Config + +class RefreshConfigCommand constructor(private val config: Config) : PushActionCommand { + override fun execute(action: PushAction): Boolean { + config.triggerRefresh() + return true + } +} diff --git a/client/src/main/java/com/jraska/github/client/push/SetAnalyticsPropertyPushCommand.kt b/client/src/main/java/com/jraska/github/client/push/SetAnalyticsPropertyPushCommand.kt new file mode 100644 index 00000000..09876885 --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/SetAnalyticsPropertyPushCommand.kt @@ -0,0 +1,14 @@ +package com.jraska.github.client.push + +import com.jraska.github.client.analytics.AnalyticsProperty + +class SetAnalyticsPropertyPushCommand constructor(private val analyticsProperty: AnalyticsProperty) : PushActionCommand { + override fun execute(action: PushAction): Boolean { + val key = action.parameters["property_key"] ?: return false + + val value = action.parameters["property_value"] ?: return false + + analyticsProperty.setUserProperty(key, value) + return true + } +} diff --git a/client/src/main/java/com/jraska/github/client/push/ShowNotificationPushCommand.kt b/client/src/main/java/com/jraska/github/client/push/ShowNotificationPushCommand.kt new file mode 100644 index 00000000..05c50da2 --- /dev/null +++ b/client/src/main/java/com/jraska/github/client/push/ShowNotificationPushCommand.kt @@ -0,0 +1,36 @@ +package com.jraska.github.client.push + +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.support.v4.app.NotificationCompat +import com.jraska.github.client.NotificationSetup +import com.jraska.github.client.R +import com.jraska.github.client.ui.UriHandlerActivity + +class ShowNotificationPushCommand constructor(private val context: Context, + private val notificationManager: NotificationManager) : PushActionCommand { + override fun execute(action: PushAction): Boolean { + val title = action.parameters["title"] ?: return false + val message = action.parameters["message"] ?: return false + val deepLink = action.parameters["clickDeepLink"] ?: return false + + val intent = Intent(context, UriHandlerActivity::class.java) + intent.data = Uri.parse(deepLink) + + val linkContentIntent = PendingIntent.getActivity(context, 0, intent, 0) + + val notification = NotificationCompat.Builder(context, NotificationSetup.PUSH_CHANNEL_ID) + .setSmallIcon(R.mipmap.ic_launcher) + .setContentTitle(title) + .setContentText(message) + .setContentIntent(linkContentIntent) + .setAutoCancel(true) + .build() + + notificationManager.notify(1, notification) + return true + } +}