replacing non foss dependencies with noop replaceable modules when the project is build with the -Pfoss flag

This commit is contained in:
Adam Brown 2022-08-31 17:44:17 +01:00
parent 346bf026d4
commit d01451e3e9
31 changed files with 311 additions and 87 deletions

View File

@ -85,6 +85,8 @@ dependencies {
implementation project(":domains:android:imageloader")
implementation project(":domains:olm")
firebase(it, "messaging")
implementation project(":matrix:matrix")
implementation project(":matrix:matrix-http-ktor")
implementation project(":matrix:services:auth")

View File

@ -1,7 +1,6 @@
package app.dapk.st
import android.app.Application
import android.content.Intent
import android.util.Log
import app.dapk.st.core.CoreAndroidModule
import app.dapk.st.core.ModuleProvider
@ -11,13 +10,13 @@ import app.dapk.st.core.extensions.ResettableUnsafeLazy
import app.dapk.st.core.extensions.Scope
import app.dapk.st.directory.DirectoryModule
import app.dapk.st.domain.StoreModule
import app.dapk.st.firebase.messaging.MessagingModule
import app.dapk.st.graph.AppModule
import app.dapk.st.home.HomeModule
import app.dapk.st.login.LoginModule
import app.dapk.st.messenger.MessengerModule
import app.dapk.st.notifications.NotificationsModule
import app.dapk.st.profile.ProfileModule
import app.dapk.st.push.firebase.FirebasePushService
import app.dapk.st.push.PushModule
import app.dapk.st.settings.SettingsModule
import app.dapk.st.share.ShareEntryModule
@ -75,6 +74,7 @@ class SmallTalkApplication : Application(), ModuleProvider {
ProfileModule::class -> featureModules.profileModule
NotificationsModule::class -> featureModules.notificationsModule
PushModule::class -> featureModules.pushModule
MessagingModule::class -> featureModules.messagingModule
MessengerModule::class -> featureModules.messengerModule
TaskRunnerModule::class -> appModule.domainModules.taskRunnerModule
CoreAndroidModule::class -> appModule.coreAndroidModule

View File

@ -16,6 +16,7 @@ import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.directory.DirectoryModule
import app.dapk.st.domain.StoreModule
import app.dapk.st.firebase.messaging.MessagingModule
import app.dapk.st.home.HomeModule
import app.dapk.st.home.MainActivity
import app.dapk.st.imageloader.ImageLoaderModule
@ -55,6 +56,7 @@ import app.dapk.st.olm.OlmPersistenceWrapper
import app.dapk.st.olm.OlmWrapper
import app.dapk.st.profile.ProfileModule
import app.dapk.st.push.PushModule
import app.dapk.st.push.firebase.MessagingServiceAdapter
import app.dapk.st.settings.SettingsModule
import app.dapk.st.share.ShareEntryModule
import app.dapk.st.tracking.TrackingModule
@ -208,6 +210,10 @@ internal class FeatureModules internal constructor(
domainModules.pushModule
}
val messagingModule by unsafeLazy {
domainModules.messaging
}
}
internal class MatrixModules(
@ -428,23 +434,30 @@ internal class DomainModules(
private val dispatchers: CoroutineDispatchers,
) {
val pushModule by unsafeLazy {
val pushHandler by unsafeLazy {
val store = storeModule.value
val pushHandler = MatrixPushHandler(
MatrixPushHandler(
workScheduler = workModule.workScheduler(),
credentialsStore = store.credentialsStore(),
matrixModules.sync,
store.roomStore(),
)
}
val messaging by unsafeLazy { MessagingModule(MessagingServiceAdapter(pushHandler), context) }
val pushModule by unsafeLazy {
PushModule(
errorTracker,
pushHandler,
context,
dispatchers,
SharedPreferencesDelegate(context.applicationContext, fileName = "dapk-user-preferences", dispatchers)
SharedPreferencesDelegate(context.applicationContext, fileName = "dapk-user-preferences", dispatchers),
messaging.messaging,
)
}
val taskRunnerModule by unsafeLazy { TaskRunnerModule(TaskRunnerAdapter(matrixModules.matrix::run, AppTaskRunner(matrixModules.push))) }
}
internal class AndroidImageContentReader(private val contentResolver: ContentResolver) : ImageContentReader {

View File

@ -118,7 +118,7 @@ ext.applyAndroidLibraryModule = { project ->
}
ext.applyCrashlyticsIfRelease = { project ->
if (isReleaseBuild) {
if (isReleaseBuild && !isFoss()) {
project.apply plugin: 'com.google.firebase.crashlytics'
project.afterEvaluate {
project.tasks.withType(com.google.firebase.crashlytics.buildtools.gradle.tasks.UploadMappingFileTask).configureEach {
@ -151,6 +151,19 @@ ext.androidImportFixturesWorkaround = { project, fixtures ->
project.dependencies.testImplementation fixtures.files("build/libs/${fixtures.name}.jar")
}
ext.isFoss = {
return rootProject.hasProperty("foss")
}
ext.firebase = { dependencies, name ->
if (isFoss()) {
dependencies.implementation(project(":domains:firebase:$name-noop"))
} else {
dependencies.implementation(project(":domains:firebase:$name"))
}
}
if (launchTask.contains("codeCoverageReport".toLowerCase())) {
apply from: 'tools/coverage.gradle'
}

View File

@ -6,8 +6,9 @@ dependencies {
implementation project(':domains:android:core')
implementation project(':domains:store')
implementation project(':matrix:services:push')
implementation platform('com.google.firebase:firebase-bom:29.0.3')
implementation 'com.google.firebase:firebase-messaging'
firebase(it, "messaging")
implementation Dependencies.mavenCentral.kotlinSerializationJson
implementation Dependencies.jitPack.unifiedPush
}

View File

@ -2,15 +2,6 @@
<manifest package="app.dapk.st.push" xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<service
android:name=".firebase.FirebasePushService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<receiver android:exported="true" android:enabled="true" android:name=".unifiedpush.UnifiedPushMessageReceiver">
<intent-filter>
<action android:name="org.unifiedpush.android.connector.MESSAGE"/>

View File

@ -7,6 +7,8 @@ import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.domain.Preferences
import app.dapk.st.domain.push.PushTokenRegistrarPreferences
import app.dapk.st.firebase.messaging.Messaging
import app.dapk.st.firebase.messaging.MessagingModule
import app.dapk.st.push.firebase.FirebasePushTokenRegistrar
import app.dapk.st.push.unifiedpush.UnifiedPushRegistrar
@ -16,6 +18,7 @@ class PushModule(
private val context: Context,
private val dispatchers: CoroutineDispatchers,
private val preferences: Preferences,
private val messaging: Messaging,
) : ProvidableModule {
private val registrars by unsafeLazy {
@ -23,8 +26,8 @@ class PushModule(
context,
FirebasePushTokenRegistrar(
errorTracker,
context,
pushHandler,
messaging,
),
UnifiedPushRegistrar(context),
PushTokenRegistrarPreferences(preferences)

View File

@ -1,18 +0,0 @@
package app.dapk.st.push.firebase
import com.google.firebase.messaging.FirebaseMessaging
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
suspend fun FirebaseMessaging.token() = suspendCoroutine<String> { continuation ->
this.token.addOnCompleteListener { task ->
when {
task.isSuccessful -> continuation.resume(task.result!!)
task.isCanceled -> continuation.resumeWith(Result.failure(CancelledTokenFetchingException()))
else -> continuation.resumeWith(Result.failure(task.exception ?: UnknownTokenFetchingFailedException()))
}
}
}
private class CancelledTokenFetchingException : Throwable()
private class UnknownTokenFetchingFailedException : Throwable()

View File

@ -1,37 +1,28 @@
package app.dapk.st.push.firebase
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import app.dapk.st.core.AppLogTag
import app.dapk.st.core.extensions.CrashScope
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.log
import app.dapk.st.firebase.messaging.Messaging
import app.dapk.st.push.PushHandler
import app.dapk.st.push.PushTokenPayload
import app.dapk.st.push.PushTokenRegistrar
import app.dapk.st.push.unifiedpush.UnifiedPushMessageReceiver
import com.google.firebase.messaging.FirebaseMessaging
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
class FirebasePushTokenRegistrar(
override val errorTracker: ErrorTracker,
private val context: Context,
private val pushHandler: PushHandler,
private val messaging: Messaging,
) : PushTokenRegistrar, CrashScope {
override suspend fun registerCurrentToken() {
log(AppLogTag.PUSH, "FCM - register current token")
context.packageManager.setComponentEnabledSetting(
ComponentName(context, FirebasePushService::class.java),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP,
)
messaging.enable()
kotlin.runCatching {
FirebaseMessaging.getInstance().token().also {
messaging.token().also {
pushHandler.onNewToken(
PushTokenPayload(
token = it,
@ -48,14 +39,8 @@ class FirebasePushTokenRegistrar(
override fun unregister() {
log(AppLogTag.PUSH, "FCM - unregister")
FirebaseMessaging.getInstance().deleteToken()
context.stopService(Intent(context, FirebasePushService::class.java))
context.packageManager.setComponentEnabledSetting(
ComponentName(context, FirebasePushService::class.java),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP,
)
messaging.deleteToken()
messaging.disable()
}
}

View File

@ -1,21 +1,18 @@
package app.dapk.st.push.firebase
import app.dapk.st.core.AppLogTag
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.core.log
import app.dapk.st.core.module
import app.dapk.st.firebase.messaging.ServiceDelegate
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.push.PushModule
import app.dapk.st.push.PushHandler
import app.dapk.st.push.PushTokenPayload
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
private const val SYGNAL_GATEWAY = "https://sygnal.dapk.app/_matrix/push/v1/notify"
class FirebasePushService : FirebaseMessagingService() {
private val handler by unsafeLazy { module<PushModule>().pushHandler() }
class MessagingServiceAdapter(
private val handler: PushHandler,
) : ServiceDelegate {
override fun onNewToken(token: String) {
log(AppLogTag.PUSH, "FCM onNewToken")
@ -27,10 +24,8 @@ class FirebasePushService : FirebaseMessagingService() {
)
}
override fun onMessageReceived(message: RemoteMessage) {
override fun onMessageReceived(eventId: EventId?, roomId: RoomId?) {
log(AppLogTag.PUSH, "FCM onMessage")
val eventId = message.data["event_id"]?.let { EventId(it) }
val roomId = message.data["room_id"]?.let { RoomId(it) }
handler.onMessageReceived(eventId, roomId)
}
}

View File

@ -2,9 +2,5 @@ applyAndroidLibraryModule(project)
dependencies {
implementation project(':core')
implementation platform('com.google.firebase:firebase-bom:29.0.3')
implementation 'com.google.firebase:firebase-crashlytics'
// is it worth the 400kb size increase?
// implementation 'com.google.firebase:firebase-analytics'
firebase(it, "crashlytics")
}

View File

@ -4,16 +4,12 @@ import android.util.Log
import app.dapk.st.core.AppLogTag
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.log
import com.google.firebase.crashlytics.FirebaseCrashlytics
class CrashlyticsCrashTracker(
private val firebaseCrashlytics: FirebaseCrashlytics,
) : ErrorTracker {
class CrashTrackerLogger : ErrorTracker {
override fun track(throwable: Throwable, extra: String) {
Log.e("ST", throwable.message, throwable)
log(AppLogTag.ERROR_NON_FATAL, "${throwable.message ?: "N/A"} extra=$extra")
firebaseCrashlytics.recordException(throwable)
}
}

View File

@ -1,9 +1,8 @@
package app.dapk.st.tracking
import android.util.Log
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.extensions.unsafeLazy
import com.google.firebase.crashlytics.FirebaseCrashlytics
import app.dapk.st.firebase.crashlytics.CrashlyticsModule
class TrackingModule(
private val isCrashTrackingEnabled: Boolean,
@ -11,13 +10,18 @@ class TrackingModule(
val errorTracker: ErrorTracker by unsafeLazy {
when (isCrashTrackingEnabled) {
true -> CrashlyticsCrashTracker(FirebaseCrashlytics.getInstance())
false -> object : ErrorTracker {
override fun track(throwable: Throwable, extra: String) {
Log.e("error", throwable.message, throwable)
}
}
true -> compositeTracker(
CrashTrackerLogger(),
CrashlyticsModule().errorTracker,
)
false -> CrashTrackerLogger()
}
}
}
private fun compositeTracker(vararg loggers: ErrorTracker) = object : ErrorTracker {
override fun track(throwable: Throwable, extra: String) {
loggers.forEach { it.track(throwable, extra) }
}
}

View File

@ -0,0 +1,5 @@
plugins { id 'kotlin' }
dependencies {
implementation project(':core')
}

View File

@ -0,0 +1,16 @@
package app.dapk.st.firebase.crashlytics
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.extensions.unsafeLazy
class CrashlyticsModule {
val errorTracker: ErrorTracker by unsafeLazy {
object : ErrorTracker {
override fun track(throwable: Throwable, extra: String) {
// no op
}
}
}
}

View File

@ -0,0 +1,7 @@
applyAndroidLibraryModule(project)
dependencies {
implementation project(':core')
implementation platform('com.google.firebase:firebase-bom:29.0.3')
implementation 'com.google.firebase:firebase-crashlytics'
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="app.dapk.st.firebase.crashlytics"/>

View File

@ -0,0 +1,14 @@
package app.dapk.st.firebase.crashlytics
import app.dapk.st.core.extensions.ErrorTracker
import com.google.firebase.crashlytics.FirebaseCrashlytics
class CrashlyticsCrashTracker(
private val firebaseCrashlytics: FirebaseCrashlytics,
) : ErrorTracker {
override fun track(throwable: Throwable, extra: String) {
firebaseCrashlytics.recordException(throwable)
}
}

View File

@ -0,0 +1,13 @@
package app.dapk.st.firebase.crashlytics
import app.dapk.st.core.extensions.ErrorTracker
import app.dapk.st.core.extensions.unsafeLazy
import com.google.firebase.crashlytics.FirebaseCrashlytics
class CrashlyticsModule {
val errorTracker: ErrorTracker by unsafeLazy {
CrashlyticsCrashTracker(FirebaseCrashlytics.getInstance())
}
}

View File

@ -0,0 +1,6 @@
applyAndroidLibraryModule(project)
dependencies {
implementation project(':core')
implementation project(':matrix:common')
}

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="app.dapk.st.firebase.messaging"/>

View File

@ -0,0 +1,21 @@
package app.dapk.st.firebase.messaging
class Messaging {
fun enable() {
// do nothing
}
fun disable() {
// do nothing
}
fun deleteToken() {
// do nothing
}
suspend fun token(): String {
return ""
}
}

View File

@ -0,0 +1,17 @@
package app.dapk.st.firebase.messaging
import android.content.Context
import app.dapk.st.core.ProvidableModule
import app.dapk.st.core.extensions.unsafeLazy
@Suppress("UNUSED")
class MessagingModule(
val serviceDelegate: ServiceDelegate,
val context: Context,
) : ProvidableModule {
val messaging by unsafeLazy {
Messaging()
}
}

View File

@ -0,0 +1,9 @@
package app.dapk.st.firebase.messaging
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
interface ServiceDelegate {
fun onNewToken(token: String)
fun onMessageReceived(eventId: EventId?, roomId: RoomId?)
}

View File

@ -0,0 +1,9 @@
applyAndroidLibraryModule(project)
dependencies {
implementation project(':core')
implementation project(':domains:android:core')
implementation project(':matrix:common')
implementation platform('com.google.firebase:firebase-bom:29.0.3')
implementation 'com.google.firebase:firebase-messaging'
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="app.dapk.st.firebase.messaging" xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<service
android:name=".FirebasePushServiceDelegate"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>

View File

@ -0,0 +1,26 @@
package app.dapk.st.firebase.messaging
import app.dapk.st.core.AppLogTag
import app.dapk.st.core.extensions.unsafeLazy
import app.dapk.st.core.log
import app.dapk.st.core.module
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
class FirebasePushServiceDelegate : FirebaseMessagingService() {
private val delegate by unsafeLazy { module<MessagingModule>().serviceDelegate }
override fun onNewToken(token: String) {
delegate.onNewToken(token)
}
override fun onMessageReceived(message: RemoteMessage) {
log(AppLogTag.PUSH, "FCM onMessage")
val eventId = message.data["event_id"]?.let { EventId(it) }
val roomId = message.data["room_id"]?.let { RoomId(it) }
delegate.onMessageReceived(eventId, roomId)
}
}

View File

@ -0,0 +1,50 @@
package app.dapk.st.firebase.messaging
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import com.google.firebase.messaging.FirebaseMessaging
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class Messaging(
private val instance: FirebaseMessaging,
private val context: Context,
) {
fun enable() {
context.packageManager.setComponentEnabledSetting(
ComponentName(context, FirebasePushServiceDelegate::class.java),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP,
)
}
fun disable() {
context.stopService(Intent(context, FirebasePushServiceDelegate::class.java))
context.packageManager.setComponentEnabledSetting(
ComponentName(context, FirebasePushServiceDelegate::class.java),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP,
)
}
fun deleteToken() {
instance.deleteToken()
}
suspend fun token() = suspendCoroutine { continuation ->
instance.token.addOnCompleteListener { task ->
when {
task.isSuccessful -> continuation.resume(task.result!!)
task.isCanceled -> continuation.resumeWith(Result.failure(CancelledTokenFetchingException()))
else -> continuation.resumeWith(Result.failure(task.exception ?: UnknownTokenFetchingFailedException()))
}
}
}
private class CancelledTokenFetchingException : Throwable()
private class UnknownTokenFetchingFailedException : Throwable()
}

View File

@ -0,0 +1,17 @@
package app.dapk.st.firebase.messaging
import android.content.Context
import app.dapk.st.core.ProvidableModule
import app.dapk.st.core.extensions.unsafeLazy
import com.google.firebase.messaging.FirebaseMessaging
class MessagingModule(
val serviceDelegate: ServiceDelegate,
val context: Context,
) : ProvidableModule {
val messaging by unsafeLazy {
Messaging(FirebaseMessaging.getInstance(), context)
}
}

View File

@ -0,0 +1,9 @@
package app.dapk.st.firebase.messaging
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
interface ServiceDelegate {
fun onNewToken(token: String)
fun onMessageReceived(eventId: EventId?, roomId: RoomId?)
}

View File

@ -34,6 +34,11 @@ include ':domains:store'
include ':domains:olm-stub'
include ':domains:olm'
include ':domains:firebase:crashlytics'
include ':domains:firebase:crashlytics-noop'
include ':domains:firebase:messaging'
include ':domains:firebase:messaging-noop'
include ':matrix:matrix'
include ':matrix:common'
include ':matrix:matrix-http'