提问人:Kalpesh Doru 提问时间:11/8/2023 最后编辑:Kalpesh Doru 更新时间:11/9/2023 访问量:34
当应用程序不在前台时,无法使用 PeriodicWorkRequest 在会议室数据库中插入数据
Unable to Insert Data in the Room Database Using PeriodicWorkRequest When App is Not in the Foreground
问:
当我的 Android 应用程序不在前台时,我遇到了使用 PeriodicWorkRequest 将数据插入数据库的问题。我设置了一个 Room 数据库、Hilt 和 WorkManager 来执行此任务。下面是相关代码和配置:
依赖:
implementation 'androidx.room:room-runtime:2.4.0'
implementation 'androidx.room:room-ktx:2.4.0'
kapt 'androidx.room:room-compiler:2.4.0'
implementation 'com.google.dagger:hilt-android:2.44'
kapt 'com.google.dagger:hilt-compiler:2.44'
kapt 'androidx.hilt:hilt-compiler:1.0.0'
implementation 'androidx.work:work-runtime-ktx:2.8.1'
implementation 'androidx.hilt:hilt-work:1.1.0'
我还在AndroidManifest.xml中定义了一个提供程序:
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
这是我的 Application 类:
@HiltAndroidApp
class App : Application(), Configuration.Provider {
@Inject
lateinit var workerFactory: HiltWorkerFactory
override fun getWorkManagerConfiguration(): Configuration {
return Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.setWorkerFactory(workerFactory)
.build()
}
}
我设置了一个 Hilt 模块:
@InstallIn(SingletonComponent::class)
@Module
class DeviceModule {
@Provides
@Singleton
fun provideDatabase(@ApplicationContext context: Context): AppDatabase {
return Room.databaseBuilder(
context, AppDatabase::class.java, Constant.DATABASE_NAME
)
.addCallback(object : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
val request = OneTimeWorkRequestBuilder<LocationWorker>().build()
WorkManager.getInstance(context).enqueue(request)
}
})
.build()
}
@Provides
fun provideDeviceDao(appDatabase: AppDatabase): DeviceDao {
return appDatabase.deviceDao()
}
}
我使用抽象类绑定了实现:
@Module
@InstallIn(SingletonComponent::class)
abstract class DeviceBind {
@Binds
@Singleton
abstract fun deviceBind(deviceRepoImpl: DeviceRepoImpl): DeviceRepo
}
我的 AppDatabase 类:
@Database(entities = [DeviceModel::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun deviceDao(): DeviceDao
}
DeviceDao 接口:
@Dao
interface DeviceDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addDevice(deviceModel: DeviceModel)
@Query("SELECT * FROM ${Constant.QUESTION_TABLE}")
fun getDevice(): Flow<MutableList<DeviceModel>>
@Query("DELETE FROM ${Constant.QUESTION_TABLE}")
suspend fun truncate()
}
我的仓库接口及其实现:
interface DeviceRepo {
suspend fun addDevice(deviceModel: DeviceModel)
suspend fun getDevice(): Flow<Resource<MutableList<DeviceModel>>>
suspend fun truncate()
}
class DeviceRepoImpl @Inject constructor(private val deviceDao: DeviceDao) : DeviceRepo {
override suspend fun addDevice(deviceModel: DeviceModel) {
deviceDao.addDevice(deviceModel)
}
override suspend fun getDevice(): Flow<Resource<MutableList<DeviceModel>>> = flow {
emit(Resource.Loading())
deviceDao.getDevice().catch {
emit(Resource.Error("Something went wrong"))
}.collect {
emit(Resource.Success(it))
}
}
override suspend fun truncate() {
deviceDao.truncate()
}
}
我的仓库接口及其对 Location 的实现:
interface LocationClient {
suspend fun getLocation(context: Context, interval: Long): Location
class LocationException(message: String) : Exception()
}
class LocationClientImpl @Inject constructor(
private val client: FusedLocationProviderClient
) : LocationClient {
@SuppressLint("MissingPermission")
override suspend fun getLocation(context: Context, interval: Long): Location {
if (!context.hasLocationPermission()) {
throw LocationClient.LocationException("Missing location permission")
}
val locationManager =
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
val isNetworkEnabled =
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
if (!isGpsEnabled && !isNetworkEnabled) {
throw LocationClient.LocationException(message = "GPS is disabled")
}
val request = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, interval)
.setWaitForAccurateLocation(false)
.build()
return suspendCancellableCoroutine { continuation ->
val locationCallback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
super.onLocationResult(result)
result.locations.lastOrNull()?.let { location ->
client.removeLocationUpdates(this)
continuation.resume(location)
}
}
override fun onLocationAvailability(availability: LocationAvailability) {
super.onLocationAvailability(availability)
if (!availability.isLocationAvailable) {
client.removeLocationUpdates(this)
continuation.resumeWithException(LocationClient.LocationException("Location not available"))
}
}
}
client.requestLocationUpdates(request, locationCallback, Looper.getMainLooper())
}
}
}
我还有一个用于后台工作的 worker 类:
@HiltWorker
class LocationWorker @AssistedInject constructor(
@Assisted var context: Context,
@Assisted parameters: WorkerParameters,
private var locationClient: LocationClient,
private val deviceRepo: DeviceRepo
) :
CoroutineWorker(context, parameters) {
private val TAG = "LocationWorker"
override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
try {
val location = locationClient.getLocation(context, 1000L)
val deviceModel = DeviceModel(
longitude = location.longitude,
latitude = location.latitude,
time = location.time,
accuracy = location.accuracy
)
deviceRepo.addDevice(deviceModel)
createNotification(context, location)
Result.success()
} catch (e: Exception) {
Log.d(TAG, "Exception: ${e.message}")
NotificationHandler.createNotification(context = context, "${e.message}", "${e.stackTrace}")
Result.failure()
}
}
private fun createNotification(context: Context, location: Location? = null) {
NotificationHandler.createNotification(
context = context,
title = "Hi from Location",
"Lat: ${location?.latitude}\n" +
"Long: ${location?.accuracy}\n" +
"Accuracy: ${location?.accuracy}"
)
}
}
工作请求
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val workManager = WorkManager.getInstance(this@MainActivity)
val request: PeriodicWorkRequest =
PeriodicWorkRequestBuilder<LocationWorker>(1, TimeUnit.HOUR).setConstraints(constraints)
.build()
workManager.enqueueUniquePeriodicWork(
"reminder_notification_work",
ExistingPeriodicWorkPolicy.UPDATE,request)
workManager.getWorkInfosForUniqueWorkLiveData("reminder_notification_work")
.observe(lifecycleOwner)
{
workInfo ->
workInfo.forEach {
workManagerState.value = it.state.toString()
}
}
尽管进行了所有这些设置,但当应用不在前台时,数据插入不起作用。任何指导或建议将不胜感激。谢谢!
答: 暂无答案
评论