Skip to content

Commit 6dee7ff

Browse files
committed
fix the worker not running periodically
1 parent 61ec968 commit 6dee7ff

15 files changed

+155
-42
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ dependencies {
8383

8484
def appCenterSdkVersion = '4.1.0'
8585
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
86+
8687
implementation 'androidx.work:work-runtime-ktx:2.8.1'
8788
implementation "androidx.hilt:hilt-work:1.0.0"
8889
kapt "androidx.hilt:hilt-compiler:1.0.0"

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@
6363
android:name="androidx.work.WorkManagerInitializer"
6464
android:value="androidx.startup"
6565
tools:node="remove" />
66+
<meta-data
67+
android:name="com.lcl.lclmeasurementtool.sync.SyncInitializer"
68+
android:value="androidx.startup"
69+
tools:node="remove" />
6670
</provider>
6771

6872
<activity

app/src/main/java/com/lcl/lclmeasurementtool/LCLApplication.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ import javax.inject.Inject
1212
* [Application] class for LCL Measurement tool
1313
*/
1414
@HiltAndroidApp
15-
class LCLApplication : Application(), Configuration.Provider {
16-
@Inject lateinit var workerFactory: HiltWorkerFactory
17-
18-
override fun getWorkManagerConfiguration() = Configuration.Builder()
19-
.setMinimumLoggingLevel(Log.DEBUG)
20-
.setWorkerFactory(workerFactory)
21-
.build()
15+
//class LCLApplication : Application(), Configuration.Provider {
16+
class LCLApplication : Application() {
17+
// @Inject lateinit var workerFactory: HiltWorkerFactory
18+
//
19+
// override fun getWorkManagerConfiguration() = Configuration.Builder()
20+
// .setMinimumLoggingLevel(Log.DEBUG)
21+
// .setWorkerFactory(workerFactory)
22+
// .build()
2223

2324
override fun onCreate() {
2425
super.onCreate()

app/src/main/java/com/lcl/lclmeasurementtool/MainActivityViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.util.Log
77
import androidx.compose.ui.graphics.Color
88
import androidx.lifecycle.ViewModel
99
import androidx.lifecycle.viewModelScope
10+
import androidx.work.WorkManager
1011
import com.google.protobuf.ByteString
1112
import com.lcl.lclmeasurementtool.Utils.ECDSA
1213
import com.lcl.lclmeasurementtool.Utils.Hex

app/src/main/java/com/lcl/lclmeasurementtool/database/dao/ConnectivityDao.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ interface ConnectivityDao {
1717

1818
@Transaction
1919
@Query("SELECT * FROM connectivity_table where reported = false")
20-
fun getAllNotReported(): Flow<List<ConnectivityReportModel>>
20+
fun getAllNotReported(): List<ConnectivityReportModel>
2121

2222
// WRITE
2323
@Transaction

app/src/main/java/com/lcl/lclmeasurementtool/database/dao/SignalStrengthDao.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ interface SignalStrengthDao {
1818

1919
@Transaction
2020
@Query("SELECT * FROM signal_strength_table where reported = false")
21-
fun getAllNotReported(): Flow<List<SignalStrengthReportModel>>
21+
fun getAllNotReported(): List<SignalStrengthReportModel>
2222

2323
// WRITE
2424
@Transaction
Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.lcl.lclmeasurementtool.model.repository
22

3+
import android.util.Log
34
import com.lcl.lclmeasurementtool.database.dao.ConnectivityDao
45
import com.lcl.lclmeasurementtool.model.datamodel.ConnectivityReportModel
5-
import com.lcl.lclmeasurementtool.sync.Synchronizer
6+
import com.lcl.lclmeasurementtool.util.Synchronizer
67
import com.lcl.lclmeasurementtool.util.prepareReportData
7-
import kotlinx.coroutines.flow.Flow
8-
import kotlinx.coroutines.flow.combine
8+
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.flow.*
910
import javax.inject.Inject
1011

1112
class ConnectivityRepository @Inject constructor(
@@ -19,16 +20,30 @@ class ConnectivityRepository @Inject constructor(
1920
override suspend fun insert(data: ConnectivityReportModel) = connectivityDao.insert(data)
2021

2122
override suspend fun syncWith(synchronizer: Synchronizer) = synchronizer.syncData {
22-
userDataRepository.userData.combine(connectivityDao.getAllNotReported()) { preference, connectivity ->
23-
Pair(preference, connectivity)
24-
}.collect {pair ->
23+
val toReportList = connectivityDao.getAllNotReported()
24+
if (toReportList.isEmpty()) {
25+
Log.d(TAG, "no outstanding connectivity reports")
26+
return@syncData
27+
}
2528

26-
val userPreference = pair.first
27-
val connectivityList = pair.second
28-
connectivityList.forEach {connectivityReportModel ->
29-
val reportString = prepareReportData(connectivityReportModel, userPreference)
29+
toReportList.asFlow()
30+
.flowOn(Dispatchers.IO)
31+
.combine(userDataRepository.userData) { connectivity, preference ->
32+
Log.d(TAG, "upload worker will upload $connectivity")
33+
val reportString = prepareReportData(connectivity, preference)
3034
networkApi.uploadConnectivity(reportString)
3135
}
32-
}
36+
.catch {
37+
Log.d(TAG, "upload worker encounter $it when uploading connectivity")
38+
throw it
39+
}
40+
.onCompletion {
41+
Log.d(TAG, "finish uploading all unreported connectivity data")
42+
}
43+
.collect()
44+
}
45+
46+
companion object {
47+
const val TAG = "ConnectivityRepository"
3348
}
3449
}

app/src/main/java/com/lcl/lclmeasurementtool/model/repository/HistoryDataRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.lcl.lclmeasurementtool.model.repository
22

3-
import com.lcl.lclmeasurementtool.sync.Syncable
3+
import com.lcl.lclmeasurementtool.util.Syncable
44
import kotlinx.coroutines.flow.Flow
55

66
interface HistoryDataRepository<T>: Syncable {
Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.lcl.lclmeasurementtool.model.repository
22

3+
import android.util.Log
34
import com.lcl.lclmeasurementtool.database.dao.SignalStrengthDao
45
import com.lcl.lclmeasurementtool.model.datamodel.SignalStrengthReportModel
5-
import com.lcl.lclmeasurementtool.sync.Synchronizer
6+
import com.lcl.lclmeasurementtool.util.Synchronizer
67
import com.lcl.lclmeasurementtool.util.prepareReportData
7-
import kotlinx.coroutines.flow.Flow
8-
import kotlinx.coroutines.flow.combine
8+
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.flow.*
910
import javax.inject.Inject
1011

1112
class SignalStrengthRepository @Inject constructor(
@@ -18,16 +19,30 @@ class SignalStrengthRepository @Inject constructor(
1819
override suspend fun insert(data: SignalStrengthReportModel) = signalStrengthDao.insert(data)
1920

2021
override suspend fun syncWith(synchronizer: Synchronizer) = synchronizer.syncData {
21-
userDataRepository.userData.combine(signalStrengthDao.getAllNotReported()) { preference, signalStrengths ->
22-
Pair(preference, signalStrengths)
23-
}.collect {pair ->
22+
val toReportList = signalStrengthDao.getAllNotReported()
23+
if (toReportList.isEmpty()) {
24+
Log.d(TAG, "no outstanding signal strength reports")
25+
return@syncData
26+
}
2427

25-
val userPreference = pair.first
26-
val signalStrengthList = pair.second
27-
signalStrengthList.forEach {signalStrengthReportModel ->
28-
val reportString = prepareReportData(signalStrengthReportModel, userPreference)
28+
toReportList.asFlow()
29+
.flowOn(Dispatchers.IO)
30+
.combine(userDataRepository.userData) { signalStrength, preference ->
31+
Log.d(TAG, "upload worker will upload $signalStrength")
32+
val reportString = prepareReportData(signalStrength, preference)
2933
networkApi.uploadSignalStrength(reportString)
3034
}
31-
}
35+
.catch {
36+
Log.d(TAG, "upload worker encounter the following exception when uploading outstanding signal strength report")
37+
throw it
38+
}
39+
.onCompletion {
40+
Log.d(TAG, "finish uploading all unreported signal strength data")
41+
}
42+
.collect()
43+
}
44+
45+
companion object {
46+
const val TAG = "SignalStrengthRepository"
3247
}
3348
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.lcl.lclmeasurementtool.sync
2+
3+
import android.content.Context
4+
import androidx.hilt.work.HiltWorkerFactory
5+
import androidx.work.CoroutineWorker
6+
import androidx.work.Data
7+
import androidx.work.ForegroundInfo
8+
import androidx.work.WorkerParameters
9+
import dagger.hilt.EntryPoint
10+
import dagger.hilt.InstallIn
11+
import dagger.hilt.android.EntryPointAccessors
12+
import dagger.hilt.components.SingletonComponent
13+
import kotlin.reflect.KClass
14+
15+
/**
16+
* An entry point to retrieve the [HiltWorkerFactory] at runtime
17+
*/
18+
@EntryPoint
19+
@InstallIn(SingletonComponent::class)
20+
interface HiltWorkerFactoryEntryPoint {
21+
fun hiltWorkerFactory(): HiltWorkerFactory
22+
}
23+
24+
private const val WORKER_CLASS_NAME = "RouterWorkerDelegateClassName"
25+
26+
/**
27+
* Adds metadata to a WorkRequest to identify what [CoroutineWorker] the [DelegatingWorker] should
28+
* delegate to
29+
*/
30+
internal fun KClass<out CoroutineWorker>.delegatedData() =
31+
Data.Builder()
32+
.putString(WORKER_CLASS_NAME, qualifiedName)
33+
.build()
34+
35+
/**
36+
* A worker that delegates sync to another [CoroutineWorker] constructed with a [HiltWorkerFactory].
37+
*
38+
* This allows for creating and using [CoroutineWorker] instances with extended arguments
39+
* without having to provide a custom WorkManager configuration that the app module needs to utilize.
40+
*
41+
* In other words, it allows for custom workers in a library module without having to own
42+
* configuration of the WorkManager singleton.
43+
*/
44+
class DelegatingWorker(
45+
appContext: Context,
46+
workerParams: WorkerParameters,
47+
) : CoroutineWorker(appContext, workerParams) {
48+
49+
private val workerClassName =
50+
workerParams.inputData.getString(WORKER_CLASS_NAME) ?: ""
51+
52+
private val delegateWorker =
53+
EntryPointAccessors.fromApplication<HiltWorkerFactoryEntryPoint>(appContext)
54+
.hiltWorkerFactory()
55+
.createWorker(appContext, workerClassName, workerParams)
56+
as? CoroutineWorker
57+
?: throw IllegalArgumentException("Unable to find appropriate worker")
58+
59+
override suspend fun getForegroundInfo(): ForegroundInfo =
60+
delegateWorker.getForegroundInfo()
61+
62+
override suspend fun doWork(): Result =
63+
delegateWorker.doWork()
64+
}

0 commit comments

Comments
 (0)