Data sync to remote servers with Android's WorkManager.
Implemented background syncing for 15 min interval for testing. Tested and confirmed process.
This commit is contained in:
@@ -131,6 +131,9 @@ dependencies {
|
|||||||
// admob
|
// admob
|
||||||
implementation(libs.play.services.ads)
|
implementation(libs.play.services.ads)
|
||||||
|
|
||||||
|
// work manager
|
||||||
|
implementation libs.androidx.work.runtime.ktx
|
||||||
|
|
||||||
implementation libs.firebase.analytics
|
implementation libs.firebase.analytics
|
||||||
implementation libs.firebase.perf
|
implementation libs.firebase.perf
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,17 @@ package com.woka
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.util.Log
|
import androidx.work.Constraints
|
||||||
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
|
import androidx.work.NetworkType
|
||||||
|
import androidx.work.PeriodicWorkRequestBuilder
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.google.android.gms.ads.MobileAds
|
import com.google.android.gms.ads.MobileAds
|
||||||
import com.google.android.gms.ads.RequestConfiguration
|
|
||||||
import com.jwplayer.pub.api.license.LicenseUtil
|
import com.jwplayer.pub.api.license.LicenseUtil
|
||||||
import com.onesignal.OneSignal
|
import com.onesignal.OneSignal
|
||||||
import com.woka.advertisements.AdsRepository
|
import com.woka.advertisements.AdsRepository
|
||||||
import com.woka.database.AppDatabase
|
import com.woka.database.AppDatabase
|
||||||
|
import com.woka.database.helpers.SyncWorker
|
||||||
import com.woka.streamingurls.StreamingUrlRepository
|
import com.woka.streamingurls.StreamingUrlRepository
|
||||||
import com.woka.userPreference.UserPreference
|
import com.woka.userPreference.UserPreference
|
||||||
import com.woka.utils.JW_PLAYER_LICENSE
|
import com.woka.utils.JW_PLAYER_LICENSE
|
||||||
@@ -16,14 +20,18 @@ import com.woka.utils.ONESIGNAL_APP_ID
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Arrays
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class WokaApp: Application() {
|
class WokaApp : Application() {
|
||||||
|
|
||||||
companion object{
|
companion object {
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
var userPrefs: UserPreference? = null
|
var userPrefs: UserPreference? = null
|
||||||
var appDatabase: AppDatabase? = null
|
var appDatabase: AppDatabase? = null
|
||||||
|
|
||||||
|
private const val LOCAL_DATA_SYNC_WORK = "com.woka.LOCAL_DATA_SYNC"
|
||||||
|
private const val LOCAL_DATA_SYNC_PERIODIC_TIME_INTERVAL = 15L
|
||||||
|
private val LOCAL_DATA_SYNC_PERIODIC_TIME_INTERVAL_UNIT = TimeUnit.MINUTES
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@@ -42,9 +50,11 @@ class WokaApp: Application() {
|
|||||||
initOneSignal()
|
initOneSignal()
|
||||||
|
|
||||||
initAdmob()
|
initAdmob()
|
||||||
|
|
||||||
|
dataSyncWorkRequest()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initOneSignal(){
|
private fun initOneSignal() {
|
||||||
// OneSignal Initialization
|
// OneSignal Initialization
|
||||||
OneSignal.initWithContext(this, ONESIGNAL_APP_ID)
|
OneSignal.initWithContext(this, ONESIGNAL_APP_ID)
|
||||||
|
|
||||||
@@ -55,10 +65,27 @@ class WokaApp: Application() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initAdmob(){
|
private fun initAdmob() {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
MobileAds.initialize(this@WokaApp)
|
MobileAds.initialize(this@WokaApp)
|
||||||
// MobileAds.setRequestConfiguration(RequestConfiguration.Builder().setTestDeviceIds(listOf("F895DC452659EA607EB688E47B041B20")).build())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun dataSyncWorkRequest() {
|
||||||
|
WorkManager.getInstance(this)
|
||||||
|
.enqueueUniquePeriodicWork(
|
||||||
|
LOCAL_DATA_SYNC_WORK,
|
||||||
|
ExistingPeriodicWorkPolicy.KEEP,
|
||||||
|
PeriodicWorkRequestBuilder<SyncWorker>(
|
||||||
|
LOCAL_DATA_SYNC_PERIODIC_TIME_INTERVAL,
|
||||||
|
LOCAL_DATA_SYNC_PERIODIC_TIME_INTERVAL_UNIT, // Every day
|
||||||
|
)
|
||||||
|
.setConstraints(
|
||||||
|
Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(NetworkType.CONNECTED) // only when the internet is available
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
28
app/src/main/java/com/woka/database/helpers/SyncWorker.kt
Normal file
28
app/src/main/java/com/woka/database/helpers/SyncWorker.kt
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package com.woka.database.helpers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
|
||||||
|
class SyncWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||||
|
CoroutineWorker(appContext, workerParams) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "LocalDataSyncWorker"
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun doWork(): Result {
|
||||||
|
return try {
|
||||||
|
Log.d(TAG, "doWork: WORK IN PROGRESS..")
|
||||||
|
RemoteSync.syncClickEvents()
|
||||||
|
RemoteSync.syncAdClickEvents()
|
||||||
|
|
||||||
|
Log.d(TAG, "doWork: WORK WAS SUCCESSFUL")
|
||||||
|
Result.success()
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
Log.e(TAG, "doWork: WORK FAILED", t)
|
||||||
|
Result.retry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -75,6 +75,8 @@ import com.woka.utils.lightStatusBar
|
|||||||
import com.woka.utils.setVisibility
|
import com.woka.utils.setVisibility
|
||||||
import com.woka.utils.show
|
import com.woka.utils.show
|
||||||
import com.woka.utils.toast
|
import com.woka.utils.toast
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -163,12 +165,8 @@ class HomeActivity : WokaBaseActivity(),
|
|||||||
decisionDialog.message = getString(R.string.do_you_want_to_exit_from_the_woka_app)
|
decisionDialog.message = getString(R.string.do_you_want_to_exit_from_the_woka_app)
|
||||||
|
|
||||||
decisionDialog.setPositiveButton(getString(R.string.yes)){
|
decisionDialog.setPositiveButton(getString(R.string.yes)){
|
||||||
lifecycleScope.launch {
|
@Suppress("DEPRECATION")
|
||||||
RemoteSync.syncClickEvents()
|
super.onBackPressed()
|
||||||
RemoteSync.syncAdClickEvents()
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decisionDialog.setNegativeButton(getString(R.string.no))
|
decisionDialog.setNegativeButton(getString(R.string.no))
|
||||||
@@ -188,6 +186,11 @@ class HomeActivity : WokaBaseActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
(getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager).unregisterNetworkCallback(networkCallback)
|
(getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager).unregisterNetworkCallback(networkCallback)
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
RemoteSync.syncClickEvents()
|
||||||
|
RemoteSync.syncAdClickEvents()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setObservers(){
|
private fun setObservers(){
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ perfPlugin = "1.4.2"
|
|||||||
sdpAndroid = "1.1.1"
|
sdpAndroid = "1.1.1"
|
||||||
shimmer = "0.5.0"
|
shimmer = "0.5.0"
|
||||||
sspAndroid = "1.1.1"
|
sspAndroid = "1.1.1"
|
||||||
|
workRuntimeKtx = "2.9.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
android_audio_mixer = { module = "com.github.ZeroOneZeroR:android_audio_mixer", version.ref = "android_audio_mixer" }
|
android_audio_mixer = { module = "com.github.ZeroOneZeroR:android_audio_mixer", version.ref = "android_audio_mixer" }
|
||||||
@@ -58,6 +59,7 @@ androidx-media3-exoplayer-smoothstreaming = { module = "androidx.media3:media3-e
|
|||||||
androidx-media3-extractor = { module = "androidx.media3:media3-extractor", version.ref = "media3Exoplayer" }
|
androidx-media3-extractor = { module = "androidx.media3:media3-extractor", version.ref = "media3Exoplayer" }
|
||||||
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3Exoplayer" }
|
androidx-media3-ui = { module = "androidx.media3:media3-ui", version.ref = "media3Exoplayer" }
|
||||||
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
|
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "roomRuntime" }
|
||||||
|
androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" }
|
||||||
circleimageview = { module = "de.hdodenhof:circleimageview", version.ref = "circleimageview" }
|
circleimageview = { module = "de.hdodenhof:circleimageview", version.ref = "circleimageview" }
|
||||||
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
|
converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" }
|
||||||
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
|
||||||
|
|||||||
Reference in New Issue
Block a user