Move sync module to multiplatform

pull/2064/head
lihenggui 1 year ago
parent 0133dabffa
commit ee92faf87c

@ -30,6 +30,7 @@ import com.google.samples.apps.nowinandroid.feature.interests.di.interestModule
import com.google.samples.apps.nowinandroid.feature.search.di.searchModule
import com.google.samples.apps.nowinandroid.feature.settings.di.settingsModule
import com.google.samples.apps.nowinandroid.feature.topic.di.topicModule
import com.google.samples.apps.nowinandroid.sync.di.syncModule
import com.google.samples.apps.nowinandroid.ui.interests2pane.Interests2PaneViewModel
import org.koin.core.annotation.ComponentScan
import org.koin.core.annotation.Module
@ -68,6 +69,7 @@ internal val appModules = module {
notificationModule,
)
includes(featureModules)
includes(syncModule)
includes(appViewModelModule)
includes(AppModule().module)
}

@ -18,8 +18,9 @@ package com.google.samples.apps.nowinandroid.feature.foryou.di
import com.google.samples.apps.nowinandroid.feature.foryou.ForYouViewModel
import org.koin.core.module.dsl.viewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module
val forYouModule = module {
viewModel { ForYouViewModel(get(), get(), get(), get(), get(), get()) }
viewModelOf(::ForYouViewModel)
}

@ -38,6 +38,7 @@ kotlin {
api(projects.core.model)
api(projects.core.analytics)
api(projects.core.notifications)
api(projects.sync.work)
api(compose.components.resources)
}
commonTest.dependencies {

@ -14,9 +14,9 @@
* limitations under the License.
*/
plugins {
alias(libs.plugins.nowinandroid.android.library)
alias(libs.plugins.nowinandroid.kmp.library)
alias(libs.plugins.nowinandroid.android.library.jacoco)
alias(libs.plugins.nowinandroid.hilt)
alias(libs.plugins.nowinandroid.di.koin)
}
android {
@ -26,21 +26,28 @@ android {
namespace = "com.google.samples.apps.nowinandroid.sync"
}
dependencies {
ksp(libs.hilt.ext.compiler)
implementation(libs.androidx.tracing.ktx)
implementation(libs.androidx.work.ktx)
implementation(libs.hilt.ext.work)
implementation(projects.core.analytics)
implementation(projects.core.data)
implementation(projects.core.notifications)
prodImplementation(libs.firebase.cloud.messaging)
prodImplementation(platform(libs.firebase.bom))
androidTestImplementation(libs.androidx.work.testing)
androidTestImplementation(libs.hilt.android.testing)
androidTestImplementation(libs.kotlinx.coroutines.guava)
androidTestImplementation(projects.core.testing)
kotlin {
sourceSets{
commonMain.dependencies {
implementation(projects.core.analytics)
implementation(projects.core.data)
implementation(projects.core.notifications)
}
commonTest.dependencies {
implementation(projects.core.testing)
}
androidMain.dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.tracing.ktx)
implementation(libs.androidx.work.ktx)
}
androidInstrumentedTest.dependencies {
implementation(projects.core.testing)
implementation(libs.androidx.work.testing)
implementation(libs.kotlinx.coroutines.guava)
}
}
}
// prodImplementation(libs.firebase.cloud.messaging)
// prodImplementation(platform(libs.firebase.bom))

@ -23,14 +23,12 @@ import androidx.work.WorkInfo
import androidx.work.WorkManager
import androidx.work.testing.SynchronousExecutor
import androidx.work.testing.WorkManagerTestInitHelper
import dagger.hilt.android.testing.HiltAndroidRule
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import kotlin.test.assertEquals
@HiltAndroidTest
//@HiltAndroidTest
class SyncWorkerTest {
@get:Rule(order = 0)

@ -1,5 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -71,7 +71,8 @@ private fun Context.syncWorkNotification(): Notification {
SYNC_NOTIFICATION_CHANNEL_ID,
)
.setSmallIcon(
com.google.samples.apps.nowinandroid.core.notifications.R.drawable.core_notifications_ic_nia_notification,
android.R.drawable.stat_notify_sync,
// com.google.samples.apps.nowinandroid.core.notifications.R.drawable.core_notifications_ic_nia_notification,
)
.setContentTitle(getString(R.string.sync_work_notification_title))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)

@ -1,5 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,17 +24,14 @@ import androidx.work.WorkManager
import com.google.samples.apps.nowinandroid.core.data.util.SyncManager
import com.google.samples.apps.nowinandroid.sync.initializers.SYNC_WORK_NAME
import com.google.samples.apps.nowinandroid.sync.workers.SyncWorker
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.map
import javax.inject.Inject
/**
* [SyncManager] backed by [WorkInfo] from [WorkManager]
*/
internal class WorkManagerSyncManager @Inject constructor(
@ApplicationContext private val context: Context,
internal class WorkManagerSyncManager(
private val context: Context,
) : SyncManager {
override val isSyncing: Flow<Boolean> =
WorkManager.getInstance(context).getWorkInfosForUniqueWorkFlow(SYNC_WORK_NAME)

@ -17,25 +17,20 @@
package com.google.samples.apps.nowinandroid.sync.workers
import android.content.Context
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.components.SingletonComponent
import kotlin.reflect.KClass
/**
* An entry point to retrieve the [HiltWorkerFactory] at runtime
*/
@EntryPoint
@InstallIn(SingletonComponent::class)
interface HiltWorkerFactoryEntryPoint {
fun hiltWorkerFactory(): HiltWorkerFactory
}
///**
// * An entry point to retrieve the [HiltWorkerFactory] at runtime
// */
//@EntryPoint
//@InstallIn(SingletonComponent::class)
//interface HiltWorkerFactoryEntryPoint {
// fun hiltWorkerFactory(): HiltWorkerFactory
//}
private const val WORKER_CLASS_NAME = "RouterWorkerDelegateClassName"
@ -65,12 +60,14 @@ class DelegatingWorker(
private val workerClassName =
workerParams.inputData.getString(WORKER_CLASS_NAME) ?: ""
private val delegateWorker =
EntryPointAccessors.fromApplication<HiltWorkerFactoryEntryPoint>(appContext)
.hiltWorkerFactory()
.createWorker(appContext, workerClassName, workerParams)
as? CoroutineWorker
?: throw IllegalArgumentException("Unable to find appropriate worker")
// private val delegateWorker =
// EntryPointAccessors.fromApplication<HiltWorkerFactoryEntryPoint>(appContext)
// .hiltWorkerFactory()
// .createWorker(appContext, workerClassName, workerParams)
// as? CoroutineWorker
// ?: throw IllegalArgumentException("Unable to find appropriate worker")
private val delegateWorker: DelegatingWorker = TODO()
override suspend fun getForegroundInfo(): ForegroundInfo =
delegateWorker.getForegroundInfo()

@ -1,5 +1,5 @@
/*
* Copyright 2022 The Android Open Source Project
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,7 +17,6 @@
package com.google.samples.apps.nowinandroid.sync.workers
import android.content.Context
import androidx.hilt.work.HiltWorker
import androidx.tracing.traceAsync
import androidx.work.CoroutineWorker
import androidx.work.ForegroundInfo
@ -31,13 +30,9 @@ import com.google.samples.apps.nowinandroid.core.data.repository.SearchContentsR
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
import com.google.samples.apps.nowinandroid.sync.initializers.SyncConstraints
import com.google.samples.apps.nowinandroid.sync.initializers.syncForegroundInfo
import com.google.samples.apps.nowinandroid.sync.status.SyncSubscriber
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@ -47,15 +42,14 @@ import kotlinx.coroutines.withContext
* Syncs the data layer by delegating to the appropriate repository instances with
* sync functionality.
*/
@HiltWorker
internal class SyncWorker @AssistedInject constructor(
@Assisted private val appContext: Context,
@Assisted workerParams: WorkerParameters,
internal class SyncWorker(
private val appContext: Context,
workerParams: WorkerParameters,
private val niaPreferences: NiaPreferencesDataSource,
private val topicRepository: TopicsRepository,
private val newsRepository: NewsRepository,
private val searchContentsRepository: SearchContentsRepository,
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
private val ioDispatcher: CoroutineDispatcher,
private val analyticsHelper: AnalyticsHelper,
private val syncSubscriber: SyncSubscriber,
) : CoroutineWorker(appContext, workerParams), Synchronizer {

@ -18,5 +18,4 @@
<string name="sync_work_notification_title">Now in Android</string>
<string name="sync_work_notification_channel_name">Sync</string>
<string name="sync_work_notification_channel_description">Background tasks for Now in Android</string>
</resources>

@ -0,0 +1,39 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.samples.apps.nowinandroid.sync.di
import com.google.samples.apps.nowinandroid.core.data.util.SyncManager
import com.google.samples.apps.nowinandroid.sync.status.StubSyncSubscriber
import com.google.samples.apps.nowinandroid.sync.status.SyncSubscriber
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import org.koin.dsl.module
val syncModule = module {
// TODO use the actual implementation for syncing data
single<SyncSubscriber> { StubSyncSubscriber() }
single<SyncManager> {
object : SyncManager {
override val isSyncing: Flow<Boolean>
get() = flowOf(false)
override fun requestSync() {
// no-op
}
}
}
}

@ -16,16 +16,13 @@
package com.google.samples.apps.nowinandroid.sync.status
import android.util.Log
import javax.inject.Inject
private const val TAG = "StubSyncSubscriber"
import co.touchlab.kermit.Logger
/**
* Stub implementation of [SyncSubscriber]
*/
class StubSyncSubscriber @Inject constructor() : SyncSubscriber {
class StubSyncSubscriber : SyncSubscriber {
override suspend fun subscribe() {
Log.d(TAG, "Subscribing to sync")
Logger.d { "Subscribing to sync" }
}
}
Loading…
Cancel
Save