Loading app/src/main/java/foundation/e/apps/api/fused/UpdatesDao.kt +12 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,15 @@ package foundation.e.apps.api.fused import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.database.fusedDownload.FusedDownload object UpdatesDao { private val _appsAwaitingForUpdate: MutableList<FusedApp> = mutableListOf() val appsAwaitingForUpdate: List<FusedApp> = _appsAwaitingForUpdate private val _successfulUpdatedApps = mutableListOf<FusedDownload>() val successfulUpdatedApps: List<FusedDownload> = _successfulUpdatedApps fun addItemsForUpdate(appsNeedUpdate: List<FusedApp>) { _appsAwaitingForUpdate.clear() _appsAwaitingForUpdate.addAll(appsNeedUpdate) Loading @@ -31,4 +35,12 @@ object UpdatesDao { fun hasAnyAppsForUpdate() = _appsAwaitingForUpdate.isNotEmpty() fun removeUpdateIfExists(packageName: String) = _appsAwaitingForUpdate.removeIf { it.package_name == packageName } fun addSuccessfullyUpdatedApp(fusedDownload: FusedDownload) { _successfulUpdatedApps.add(fusedDownload) } fun clearSuccessfullyUpdatedApps() { _successfulUpdatedApps.clear() } } app/src/main/java/foundation/e/apps/manager/workmanager/InstallAppWorker.kt +37 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import androidx.work.WorkerParameters import dagger.assisted.Assisted import dagger.assisted.AssistedInject import foundation.e.apps.R import foundation.e.apps.api.fused.UpdatesDao import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository Loading @@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import timber.log.Timber import java.text.NumberFormat import java.text.SimpleDateFormat import java.util.Date import java.util.concurrent.atomic.AtomicInteger Loading @@ -73,6 +75,7 @@ class InstallAppWorker @AssistedInject constructor( companion object { private const val TAG = "InstallWorker" const val INPUT_DATA_FUSED_DOWNLOAD = "input_data_fused_download" const val IS_UPDATE_WORK = "is_update_work" /* * If this is not "static" then each notification has the same ID. Loading @@ -97,7 +100,8 @@ class InstallAppWorker @AssistedInject constructor( fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) fusedDownload?.let { isItUpdateWork = packageManagerModule.isInstalled(it.packageName) isItUpdateWork = params.inputData.getBoolean(IS_UPDATE_WORK, false) && packageManagerModule.isInstalled(it.packageName) if (fusedDownload.status != Status.AWAITING) { return Result.success() Loading @@ -122,32 +126,50 @@ class InstallAppWorker @AssistedInject constructor( fusedManagerRepository.installationIssue(it) } } finally { if (isItUpdateWork && isUpdateCompleted()) { // show notification for ended update showNotificationOnUpdateEnded() } Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") return Result.success() } } private suspend fun InstallAppWorker.checkUpdateWork( fusedDownload: FusedDownload? ) { if (isItUpdateWork) { fusedDownload?.let { val actualFusedDownload = databaseRepository.getDownloadById(it.id) if (actualFusedDownload?.status == Status.INSTALLED) { UpdatesDao.addSuccessfullyUpdatedApp(it) } if (isUpdateCompleted()) { // show notification for ended update showNotificationOnUpdateEnded() UpdatesDao.clearSuccessfullyUpdatedApps() } } } } private suspend fun isUpdateCompleted(): Boolean { val downloadListWithoutAnyIssue = databaseRepository.getDownloadList() .filter { !listOf(Status.INSTALLATION_ISSUE, Status.PURCHASE_NEEDED).contains(it.status) } return downloadListWithoutAnyIssue.isEmpty() return UpdatesDao.successfulUpdatedApps.isNotEmpty() && downloadListWithoutAnyIssue.isEmpty() } private fun showNotificationOnUpdateEnded() { val date = Date(System.currentTimeMillis()) val locale = dataStoreManager.getAuthData().locale val dateFormat = SimpleDateFormat("dd/MM/yyyy-HH:mm", dataStoreManager.getAuthData().locale) SimpleDateFormat("dd/MM/yyyy-HH:mm", locale) val numberOfUpdatedApps = NumberFormat.getNumberInstance(locale) .format(UpdatesDao.successfulUpdatedApps.size) .toString() UpdatesNotifier.showNotification( context, context.getString(R.string.update), context.getString( R.string.message_last_update_triggered, dateFormat.format(date) R.string.message_last_update_triggered, numberOfUpdatedApps, dateFormat.format(date) ) ) } Loading @@ -161,8 +183,9 @@ class InstallAppWorker @AssistedInject constructor( tickerFlow(3.seconds) .onEach { val download = databaseRepository.getDownloadById(fusedDownload.id) if (download == null) { finishInstallation() finishInstallation(fusedDownload) } else { handleFusedDownloadStatusCheckingException(download) if (isAppDownloading(download)) { Loading @@ -184,7 +207,7 @@ class InstallAppWorker @AssistedInject constructor( handleFusedDownloadStatus(download) } catch (e: Exception) { Log.e(TAG, "observeDownload: ", e) finishInstallation() finishInstallation(download) } } Loading Loading @@ -225,11 +248,11 @@ class InstallAppWorker @AssistedInject constructor( Timber.d("===> doWork: Installing ${fusedDownload.name} ${fusedDownload.status}") } Status.INSTALLED, Status.INSTALLATION_ISSUE -> { finishInstallation() finishInstallation(fusedDownload) Timber.d("===> doWork: Installed/Failed: ${fusedDownload.name} ${fusedDownload.status}") } else -> { finishInstallation() finishInstallation(fusedDownload) Log.wtf( TAG, "===> ${fusedDownload.name} is in wrong state ${fusedDownload.status}" Loading @@ -238,7 +261,8 @@ class InstallAppWorker @AssistedInject constructor( } } private fun finishInstallation() { private suspend fun finishInstallation(fusedDownload: FusedDownload) { checkUpdateWork(fusedDownload) isDownloading = false unlockMutex() } Loading app/src/main/java/foundation/e/apps/manager/workmanager/InstallWorkManager.kt +2 −1 Original line number Diff line number Diff line Loading @@ -12,13 +12,14 @@ object InstallWorkManager { const val INSTALL_WORK_NAME = "APP_LOUNGE_INSTALL_APP" lateinit var context: Application fun enqueueWork(fusedDownload: FusedDownload) { fun enqueueWork(fusedDownload: FusedDownload, isUpdateWork:Boolean = false) { WorkManager.getInstance(context).enqueueUniqueWork( INSTALL_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, OneTimeWorkRequestBuilder<InstallAppWorker>().setInputData( Data.Builder() .putString(InstallAppWorker.INPUT_DATA_FUSED_DOWNLOAD, fusedDownload.id) .putBoolean(InstallAppWorker.IS_UPDATE_WORK, isUpdateWork) .build() ).addTag(fusedDownload.id) .build() Loading app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ class SettingsFragment : PreferenceFragmentCompat() { UpdatesWorkManager.enqueueWork( it, newValue.toString().toLong(), ExistingPeriodicWorkPolicy.REPLACE ExistingPeriodicWorkPolicy.KEEP ) } true Loading app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +1 −1 Original line number Diff line number Diff line Loading @@ -236,7 +236,7 @@ class UpdatesWorker @AssistedInject constructor( fusedManagerRepository.addDownload(fusedDownload) fusedManagerRepository.updateAwaiting(fusedDownload) Timber.d("startUpdateProcess: Enqueued for update: ${fusedDownload.name} ${fusedDownload.id} ${fusedDownload.status}") InstallWorkManager.enqueueWork(fusedDownload) InstallWorkManager.enqueueWork(fusedDownload, true) Timber.d(">>> startUpdateProcess: " + fusedDownload.name) } } Loading Loading
app/src/main/java/foundation/e/apps/api/fused/UpdatesDao.kt +12 −0 Original line number Diff line number Diff line Loading @@ -18,11 +18,15 @@ package foundation.e.apps.api.fused import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.database.fusedDownload.FusedDownload object UpdatesDao { private val _appsAwaitingForUpdate: MutableList<FusedApp> = mutableListOf() val appsAwaitingForUpdate: List<FusedApp> = _appsAwaitingForUpdate private val _successfulUpdatedApps = mutableListOf<FusedDownload>() val successfulUpdatedApps: List<FusedDownload> = _successfulUpdatedApps fun addItemsForUpdate(appsNeedUpdate: List<FusedApp>) { _appsAwaitingForUpdate.clear() _appsAwaitingForUpdate.addAll(appsNeedUpdate) Loading @@ -31,4 +35,12 @@ object UpdatesDao { fun hasAnyAppsForUpdate() = _appsAwaitingForUpdate.isNotEmpty() fun removeUpdateIfExists(packageName: String) = _appsAwaitingForUpdate.removeIf { it.package_name == packageName } fun addSuccessfullyUpdatedApp(fusedDownload: FusedDownload) { _successfulUpdatedApps.add(fusedDownload) } fun clearSuccessfullyUpdatedApps() { _successfulUpdatedApps.clear() } }
app/src/main/java/foundation/e/apps/manager/workmanager/InstallAppWorker.kt +37 −13 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import androidx.work.WorkerParameters import dagger.assisted.Assisted import dagger.assisted.AssistedInject import foundation.e.apps.R import foundation.e.apps.api.fused.UpdatesDao import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository Loading @@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import timber.log.Timber import java.text.NumberFormat import java.text.SimpleDateFormat import java.util.Date import java.util.concurrent.atomic.AtomicInteger Loading @@ -73,6 +75,7 @@ class InstallAppWorker @AssistedInject constructor( companion object { private const val TAG = "InstallWorker" const val INPUT_DATA_FUSED_DOWNLOAD = "input_data_fused_download" const val IS_UPDATE_WORK = "is_update_work" /* * If this is not "static" then each notification has the same ID. Loading @@ -97,7 +100,8 @@ class InstallAppWorker @AssistedInject constructor( fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) fusedDownload?.let { isItUpdateWork = packageManagerModule.isInstalled(it.packageName) isItUpdateWork = params.inputData.getBoolean(IS_UPDATE_WORK, false) && packageManagerModule.isInstalled(it.packageName) if (fusedDownload.status != Status.AWAITING) { return Result.success() Loading @@ -122,32 +126,50 @@ class InstallAppWorker @AssistedInject constructor( fusedManagerRepository.installationIssue(it) } } finally { if (isItUpdateWork && isUpdateCompleted()) { // show notification for ended update showNotificationOnUpdateEnded() } Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") return Result.success() } } private suspend fun InstallAppWorker.checkUpdateWork( fusedDownload: FusedDownload? ) { if (isItUpdateWork) { fusedDownload?.let { val actualFusedDownload = databaseRepository.getDownloadById(it.id) if (actualFusedDownload?.status == Status.INSTALLED) { UpdatesDao.addSuccessfullyUpdatedApp(it) } if (isUpdateCompleted()) { // show notification for ended update showNotificationOnUpdateEnded() UpdatesDao.clearSuccessfullyUpdatedApps() } } } } private suspend fun isUpdateCompleted(): Boolean { val downloadListWithoutAnyIssue = databaseRepository.getDownloadList() .filter { !listOf(Status.INSTALLATION_ISSUE, Status.PURCHASE_NEEDED).contains(it.status) } return downloadListWithoutAnyIssue.isEmpty() return UpdatesDao.successfulUpdatedApps.isNotEmpty() && downloadListWithoutAnyIssue.isEmpty() } private fun showNotificationOnUpdateEnded() { val date = Date(System.currentTimeMillis()) val locale = dataStoreManager.getAuthData().locale val dateFormat = SimpleDateFormat("dd/MM/yyyy-HH:mm", dataStoreManager.getAuthData().locale) SimpleDateFormat("dd/MM/yyyy-HH:mm", locale) val numberOfUpdatedApps = NumberFormat.getNumberInstance(locale) .format(UpdatesDao.successfulUpdatedApps.size) .toString() UpdatesNotifier.showNotification( context, context.getString(R.string.update), context.getString( R.string.message_last_update_triggered, dateFormat.format(date) R.string.message_last_update_triggered, numberOfUpdatedApps, dateFormat.format(date) ) ) } Loading @@ -161,8 +183,9 @@ class InstallAppWorker @AssistedInject constructor( tickerFlow(3.seconds) .onEach { val download = databaseRepository.getDownloadById(fusedDownload.id) if (download == null) { finishInstallation() finishInstallation(fusedDownload) } else { handleFusedDownloadStatusCheckingException(download) if (isAppDownloading(download)) { Loading @@ -184,7 +207,7 @@ class InstallAppWorker @AssistedInject constructor( handleFusedDownloadStatus(download) } catch (e: Exception) { Log.e(TAG, "observeDownload: ", e) finishInstallation() finishInstallation(download) } } Loading Loading @@ -225,11 +248,11 @@ class InstallAppWorker @AssistedInject constructor( Timber.d("===> doWork: Installing ${fusedDownload.name} ${fusedDownload.status}") } Status.INSTALLED, Status.INSTALLATION_ISSUE -> { finishInstallation() finishInstallation(fusedDownload) Timber.d("===> doWork: Installed/Failed: ${fusedDownload.name} ${fusedDownload.status}") } else -> { finishInstallation() finishInstallation(fusedDownload) Log.wtf( TAG, "===> ${fusedDownload.name} is in wrong state ${fusedDownload.status}" Loading @@ -238,7 +261,8 @@ class InstallAppWorker @AssistedInject constructor( } } private fun finishInstallation() { private suspend fun finishInstallation(fusedDownload: FusedDownload) { checkUpdateWork(fusedDownload) isDownloading = false unlockMutex() } Loading
app/src/main/java/foundation/e/apps/manager/workmanager/InstallWorkManager.kt +2 −1 Original line number Diff line number Diff line Loading @@ -12,13 +12,14 @@ object InstallWorkManager { const val INSTALL_WORK_NAME = "APP_LOUNGE_INSTALL_APP" lateinit var context: Application fun enqueueWork(fusedDownload: FusedDownload) { fun enqueueWork(fusedDownload: FusedDownload, isUpdateWork:Boolean = false) { WorkManager.getInstance(context).enqueueUniqueWork( INSTALL_WORK_NAME, ExistingWorkPolicy.APPEND_OR_REPLACE, OneTimeWorkRequestBuilder<InstallAppWorker>().setInputData( Data.Builder() .putString(InstallAppWorker.INPUT_DATA_FUSED_DOWNLOAD, fusedDownload.id) .putBoolean(InstallAppWorker.IS_UPDATE_WORK, isUpdateWork) .build() ).addTag(fusedDownload.id) .build() Loading
app/src/main/java/foundation/e/apps/settings/SettingsFragment.kt +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ class SettingsFragment : PreferenceFragmentCompat() { UpdatesWorkManager.enqueueWork( it, newValue.toString().toLong(), ExistingPeriodicWorkPolicy.REPLACE ExistingPeriodicWorkPolicy.KEEP ) } true Loading
app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +1 −1 Original line number Diff line number Diff line Loading @@ -236,7 +236,7 @@ class UpdatesWorker @AssistedInject constructor( fusedManagerRepository.addDownload(fusedDownload) fusedManagerRepository.updateAwaiting(fusedDownload) Timber.d("startUpdateProcess: Enqueued for update: ${fusedDownload.name} ${fusedDownload.id} ${fusedDownload.status}") InstallWorkManager.enqueueWork(fusedDownload) InstallWorkManager.enqueueWork(fusedDownload, true) Timber.d(">>> startUpdateProcess: " + fusedDownload.name) } } Loading