Loading app/build.gradle +1 −1 Original line number Original line Diff line number Diff line Loading @@ -10,7 +10,7 @@ plugins { def versionMajor = 2 def versionMajor = 2 def versionMinor = 3 def versionMinor = 3 def versionPatch = 7 def versionPatch = 8 android { android { compileSdk 31 compileSdk 31 Loading app/src/main/java/foundation/e/apps/manager/workmanager/InstallAppWorker.kt +27 −0 Original line number Original line Diff line number Diff line Loading @@ -36,8 +36,11 @@ import foundation.e.apps.R import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.modules.DataStoreManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.delay Loading @@ -46,6 +49,8 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex import timber.log.Timber import timber.log.Timber import java.text.SimpleDateFormat import java.util.Date import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger import kotlin.time.Duration import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds Loading @@ -58,9 +63,12 @@ class InstallAppWorker @AssistedInject constructor( private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val downloadManager: DownloadManager, private val downloadManager: DownloadManager, private val downloadManagerQuery: DownloadManager.Query, private val downloadManagerQuery: DownloadManager.Query, private val packageManagerModule: PkgManagerModule, private val dataStoreManager: DataStoreManager ) : CoroutineWorker(context, params) { ) : CoroutineWorker(context, params) { private var isDownloading: Boolean = false private var isDownloading: Boolean = false private var isItUpdateWork = false companion object { companion object { private const val TAG = "InstallWorker" private const val TAG = "InstallWorker" Loading Loading @@ -89,6 +97,8 @@ class InstallAppWorker @AssistedInject constructor( fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) fusedDownload?.let { fusedDownload?.let { isItUpdateWork = packageManagerModule.isInstalled(it.packageName) if (fusedDownload.status != Status.AWAITING) { if (fusedDownload.status != Status.AWAITING) { return Result.success() return Result.success() } } Loading @@ -112,11 +122,28 @@ class InstallAppWorker @AssistedInject constructor( fusedManagerRepository.installationIssue(it) fusedManagerRepository.installationIssue(it) } } } finally { } finally { if (isItUpdateWork && databaseRepository.getDownloadList().isEmpty()) { // show notification for ended update showNotificationOnUpdateEnded() } Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") return Result.success() return Result.success() } } } } private fun showNotificationOnUpdateEnded() { val date = Date(System.currentTimeMillis()) val dateFormat = SimpleDateFormat("dd/MM/yyyy-HH:mm", dataStoreManager.getAuthData().locale) UpdatesNotifier.showNotification( context, context.getString(R.string.update), context.getString( R.string.message_last_update_triggered, dateFormat.format(date) ) ) } private suspend fun startAppInstallationProcess( private suspend fun startAppInstallationProcess( fusedDownload: FusedDownload fusedDownload: FusedDownload ) { ) { Loading app/src/main/java/foundation/e/apps/updates/UpdatesNotifier.kt +35 −3 Original line number Original line Diff line number Diff line Loading @@ -43,9 +43,7 @@ object UpdatesNotifier { isConnectedToUnmeteredNetwork: Boolean isConnectedToUnmeteredNetwork: Boolean ): Notification { ): Notification { val notificationBuilder = val notificationBuilder = NotificationCompat.Builder(context, UPDATES_NOTIFICATION_CHANNEL_ID) createNotificationBuilder(context) notificationBuilder.setSmallIcon(R.drawable.ic_app_updated_on) notificationBuilder.priority = NotificationCompat.PRIORITY_DEFAULT when (numberOfApps) { when (numberOfApps) { 0 -> { 0 -> { Loading Loading @@ -88,6 +86,15 @@ object UpdatesNotifier { return notificationBuilder.build() return notificationBuilder.build() } } private fun createNotificationBuilder(context: Context): NotificationCompat.Builder { val notificationBuilder = NotificationCompat.Builder(context, UPDATES_NOTIFICATION_CHANNEL_ID) notificationBuilder.setSmallIcon(R.drawable.ic_app_updated_on) notificationBuilder.priority = NotificationCompat.PRIORITY_DEFAULT return notificationBuilder } private fun getClickIntent(context: Context): PendingIntent { private fun getClickIntent(context: Context): PendingIntent { val intent = Intent(context, MainActivity::class.java).apply { val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TASK flags = Intent.FLAG_ACTIVITY_CLEAR_TASK Loading Loading @@ -132,6 +139,31 @@ object UpdatesNotifier { } } } } fun showNotification( context: Context, title: String, message: String, ) { with(NotificationManagerCompat.from(context)) { createNotificationChannel(context) notify( UPDATES_NOTIFICATION_ID, getNotification( context, title, message ) ) } } fun getNotification(context: Context, title: String, message: String): Notification { val notificationBuilder = createNotificationBuilder(context) notificationBuilder.setContentTitle(title) notificationBuilder.setContentText(message) return notificationBuilder.build() } fun cancelNotification(context: Context) { fun cancelNotification(context: Context) { val notificationManager: NotificationManager = val notificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager Loading app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +3 −10 Original line number Original line Diff line number Diff line Loading @@ -13,7 +13,6 @@ import androidx.preference.PreferenceManager import androidx.work.CoroutineWorker import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import androidx.work.WorkerParameters import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.AuthData import com.google.gson.Gson import dagger.assisted.Assisted import dagger.assisted.Assisted import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject import foundation.e.apps.R import foundation.e.apps.R Loading @@ -30,7 +29,7 @@ import foundation.e.apps.utils.enums.ResultStatus import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.eventBus.AppEvent import foundation.e.apps.utils.eventBus.AppEvent import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.DataStoreManager import kotlinx.coroutines.delay import kotlinx.coroutines.delay import timber.log.Timber import timber.log.Timber import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream Loading @@ -43,8 +42,7 @@ class UpdatesWorker @AssistedInject constructor( private val updatesManagerRepository: UpdatesManagerRepository, private val updatesManagerRepository: UpdatesManagerRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val dataStoreModule: DataStoreModule, private val dataStoreManager: DataStoreManager, private val gson: Gson, ) : CoroutineWorker(context, params) { ) : CoroutineWorker(context, params) { companion object { companion object { const val IS_AUTO_UPDATE = "IS_AUTO_UPDATE" const val IS_AUTO_UPDATE = "IS_AUTO_UPDATE" Loading Loading @@ -76,7 +74,7 @@ class UpdatesWorker @AssistedInject constructor( private suspend fun checkForUpdates() { private suspend fun checkForUpdates() { loadSettings() loadSettings() val isConnectedToUnmeteredNetwork = isConnectedToUnmeteredNetwork(applicationContext) val isConnectedToUnmeteredNetwork = isConnectedToUnmeteredNetwork(applicationContext) val authData = getAuthData() val authData = dataStoreManager.getAuthData() var resultStatus: ResultStatus var resultStatus: ResultStatus val updateData = updatesManagerRepository.getUpdates(authData) val updateData = updatesManagerRepository.getUpdates(authData) Loading Loading @@ -157,11 +155,6 @@ class UpdatesWorker @AssistedInject constructor( } } } } private fun getAuthData(): AuthData { val authDataJson = dataStoreModule.getAuthDataSync() return gson.fromJson(authDataJson, AuthData::class.java) } private suspend fun startUpdateProcess( private suspend fun startUpdateProcess( appsNeededToUpdate: List<FusedApp>, appsNeededToUpdate: List<FusedApp>, authData: AuthData authData: AuthData Loading app/src/main/java/foundation/e/apps/utils/modules/DataStoreManager.kt 0 → 100644 +37 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 Murena SAS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.utils.modules import com.aurora.gplayapi.data.models.AuthData import com.google.gson.Gson import javax.inject.Inject import javax.inject.Singleton @Singleton class DataStoreManager @Inject constructor() { @Inject lateinit var dataStoreModule: DataStoreModule @Inject lateinit var gson: Gson fun getAuthData(): AuthData { val authDataJson = dataStoreModule.getAuthDataSync() return gson.fromJson(authDataJson, AuthData::class.java) } } Loading
app/build.gradle +1 −1 Original line number Original line Diff line number Diff line Loading @@ -10,7 +10,7 @@ plugins { def versionMajor = 2 def versionMajor = 2 def versionMinor = 3 def versionMinor = 3 def versionPatch = 7 def versionPatch = 8 android { android { compileSdk 31 compileSdk 31 Loading
app/src/main/java/foundation/e/apps/manager/workmanager/InstallAppWorker.kt +27 −0 Original line number Original line Diff line number Diff line Loading @@ -36,8 +36,11 @@ import foundation.e.apps.R import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.DatabaseRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.modules.DataStoreManager import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.delay Loading @@ -46,6 +49,8 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex import timber.log.Timber import timber.log.Timber import java.text.SimpleDateFormat import java.util.Date import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger import kotlin.time.Duration import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds Loading @@ -58,9 +63,12 @@ class InstallAppWorker @AssistedInject constructor( private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val downloadManager: DownloadManager, private val downloadManager: DownloadManager, private val downloadManagerQuery: DownloadManager.Query, private val downloadManagerQuery: DownloadManager.Query, private val packageManagerModule: PkgManagerModule, private val dataStoreManager: DataStoreManager ) : CoroutineWorker(context, params) { ) : CoroutineWorker(context, params) { private var isDownloading: Boolean = false private var isDownloading: Boolean = false private var isItUpdateWork = false companion object { companion object { private const val TAG = "InstallWorker" private const val TAG = "InstallWorker" Loading Loading @@ -89,6 +97,8 @@ class InstallAppWorker @AssistedInject constructor( fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) fusedDownload = databaseRepository.getDownloadById(fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) Timber.d(">>> dowork started for Fused download name " + fusedDownload?.name + " " + fusedDownloadString) fusedDownload?.let { fusedDownload?.let { isItUpdateWork = packageManagerModule.isInstalled(it.packageName) if (fusedDownload.status != Status.AWAITING) { if (fusedDownload.status != Status.AWAITING) { return Result.success() return Result.success() } } Loading @@ -112,11 +122,28 @@ class InstallAppWorker @AssistedInject constructor( fusedManagerRepository.installationIssue(it) fusedManagerRepository.installationIssue(it) } } } finally { } finally { if (isItUpdateWork && databaseRepository.getDownloadList().isEmpty()) { // show notification for ended update showNotificationOnUpdateEnded() } Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") Timber.d("doWork: RESULT SUCCESS: ${fusedDownload?.name}") return Result.success() return Result.success() } } } } private fun showNotificationOnUpdateEnded() { val date = Date(System.currentTimeMillis()) val dateFormat = SimpleDateFormat("dd/MM/yyyy-HH:mm", dataStoreManager.getAuthData().locale) UpdatesNotifier.showNotification( context, context.getString(R.string.update), context.getString( R.string.message_last_update_triggered, dateFormat.format(date) ) ) } private suspend fun startAppInstallationProcess( private suspend fun startAppInstallationProcess( fusedDownload: FusedDownload fusedDownload: FusedDownload ) { ) { Loading
app/src/main/java/foundation/e/apps/updates/UpdatesNotifier.kt +35 −3 Original line number Original line Diff line number Diff line Loading @@ -43,9 +43,7 @@ object UpdatesNotifier { isConnectedToUnmeteredNetwork: Boolean isConnectedToUnmeteredNetwork: Boolean ): Notification { ): Notification { val notificationBuilder = val notificationBuilder = NotificationCompat.Builder(context, UPDATES_NOTIFICATION_CHANNEL_ID) createNotificationBuilder(context) notificationBuilder.setSmallIcon(R.drawable.ic_app_updated_on) notificationBuilder.priority = NotificationCompat.PRIORITY_DEFAULT when (numberOfApps) { when (numberOfApps) { 0 -> { 0 -> { Loading Loading @@ -88,6 +86,15 @@ object UpdatesNotifier { return notificationBuilder.build() return notificationBuilder.build() } } private fun createNotificationBuilder(context: Context): NotificationCompat.Builder { val notificationBuilder = NotificationCompat.Builder(context, UPDATES_NOTIFICATION_CHANNEL_ID) notificationBuilder.setSmallIcon(R.drawable.ic_app_updated_on) notificationBuilder.priority = NotificationCompat.PRIORITY_DEFAULT return notificationBuilder } private fun getClickIntent(context: Context): PendingIntent { private fun getClickIntent(context: Context): PendingIntent { val intent = Intent(context, MainActivity::class.java).apply { val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TASK flags = Intent.FLAG_ACTIVITY_CLEAR_TASK Loading Loading @@ -132,6 +139,31 @@ object UpdatesNotifier { } } } } fun showNotification( context: Context, title: String, message: String, ) { with(NotificationManagerCompat.from(context)) { createNotificationChannel(context) notify( UPDATES_NOTIFICATION_ID, getNotification( context, title, message ) ) } } fun getNotification(context: Context, title: String, message: String): Notification { val notificationBuilder = createNotificationBuilder(context) notificationBuilder.setContentTitle(title) notificationBuilder.setContentText(message) return notificationBuilder.build() } fun cancelNotification(context: Context) { fun cancelNotification(context: Context) { val notificationManager: NotificationManager = val notificationManager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager Loading
app/src/main/java/foundation/e/apps/updates/manager/UpdatesWorker.kt +3 −10 Original line number Original line Diff line number Diff line Loading @@ -13,7 +13,6 @@ import androidx.preference.PreferenceManager import androidx.work.CoroutineWorker import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import androidx.work.WorkerParameters import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.AuthData import com.google.gson.Gson import dagger.assisted.Assisted import dagger.assisted.Assisted import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject import foundation.e.apps.R import foundation.e.apps.R Loading @@ -30,7 +29,7 @@ import foundation.e.apps.utils.enums.ResultStatus import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.enums.Type import foundation.e.apps.utils.eventBus.AppEvent import foundation.e.apps.utils.eventBus.AppEvent import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.modules.DataStoreModule import foundation.e.apps.utils.modules.DataStoreManager import kotlinx.coroutines.delay import kotlinx.coroutines.delay import timber.log.Timber import timber.log.Timber import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream Loading @@ -43,8 +42,7 @@ class UpdatesWorker @AssistedInject constructor( private val updatesManagerRepository: UpdatesManagerRepository, private val updatesManagerRepository: UpdatesManagerRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedAPIRepository: FusedAPIRepository, private val fusedManagerRepository: FusedManagerRepository, private val fusedManagerRepository: FusedManagerRepository, private val dataStoreModule: DataStoreModule, private val dataStoreManager: DataStoreManager, private val gson: Gson, ) : CoroutineWorker(context, params) { ) : CoroutineWorker(context, params) { companion object { companion object { const val IS_AUTO_UPDATE = "IS_AUTO_UPDATE" const val IS_AUTO_UPDATE = "IS_AUTO_UPDATE" Loading Loading @@ -76,7 +74,7 @@ class UpdatesWorker @AssistedInject constructor( private suspend fun checkForUpdates() { private suspend fun checkForUpdates() { loadSettings() loadSettings() val isConnectedToUnmeteredNetwork = isConnectedToUnmeteredNetwork(applicationContext) val isConnectedToUnmeteredNetwork = isConnectedToUnmeteredNetwork(applicationContext) val authData = getAuthData() val authData = dataStoreManager.getAuthData() var resultStatus: ResultStatus var resultStatus: ResultStatus val updateData = updatesManagerRepository.getUpdates(authData) val updateData = updatesManagerRepository.getUpdates(authData) Loading Loading @@ -157,11 +155,6 @@ class UpdatesWorker @AssistedInject constructor( } } } } private fun getAuthData(): AuthData { val authDataJson = dataStoreModule.getAuthDataSync() return gson.fromJson(authDataJson, AuthData::class.java) } private suspend fun startUpdateProcess( private suspend fun startUpdateProcess( appsNeededToUpdate: List<FusedApp>, appsNeededToUpdate: List<FusedApp>, authData: AuthData authData: AuthData Loading
app/src/main/java/foundation/e/apps/utils/modules/DataStoreManager.kt 0 → 100644 +37 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2022 Murena SAS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.utils.modules import com.aurora.gplayapi.data.models.AuthData import com.google.gson.Gson import javax.inject.Inject import javax.inject.Singleton @Singleton class DataStoreManager @Inject constructor() { @Inject lateinit var dataStoreModule: DataStoreModule @Inject lateinit var gson: Gson fun getAuthData(): AuthData { val authDataJson = dataStoreModule.getAuthDataSync() return gson.fromJson(authDataJson, AuthData::class.java) } }