From 3c151c9b1c06b5444b2bfe3778df7b5819e5d693 Mon Sep 17 00:00:00 2001 From: Hasib Prince Date: Fri, 8 Jul 2022 14:29:31 +0600 Subject: [PATCH 1/2] Handled signature mismatch during update process --- .../java/foundation/e/apps/MainActivity.kt | 12 ++++++ .../e/apps/api/database/AppDatabase.kt | 7 +++- .../e/apps/api/faultyApps/FaultyApp.kt | 27 ++++++++++++ .../e/apps/api/faultyApps/FaultyAppDao.kt | 38 +++++++++++++++++ .../api/faultyApps/FaultyAppRepository.kt | 41 +++++++++++++++++++ .../e/apps/api/fused/FusedAPIImpl.kt | 26 +++++++----- .../java/foundation/e/apps/di/DaoModule.kt | 6 +++ .../e/apps/manager/pkg/InstallerService.kt | 20 ++++++++- .../e/apps/manager/pkg/PkgManagerBR.kt | 22 ++++++++-- .../updates/manager/UpdatesManagerImpl.kt | 8 +++- .../e/apps/utils/enums/FilterLevel.kt | 10 ++--- .../e/apps/utils/eventBus/AppEvent.kt | 25 +++++++++++ .../e/apps/utils/eventBus/EventBus.kt | 31 ++++++++++++++ 13 files changed, 249 insertions(+), 24 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/api/faultyApps/FaultyApp.kt create mode 100644 app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppDao.kt create mode 100644 app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppRepository.kt create mode 100644 app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt create mode 100644 app/src/main/java/foundation/e/apps/utils/eventBus/EventBus.kt diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index 37a2823a9..e3a9cf5dd 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -43,8 +43,12 @@ import foundation.e.apps.purchase.AppPurchaseFragmentDirections import foundation.e.apps.setup.signin.SignInViewModel import foundation.e.apps.updates.UpdatesNotifier import foundation.e.apps.utils.enums.Status +import foundation.e.apps.utils.eventBus.AppEvent +import foundation.e.apps.utils.eventBus.EventBus import foundation.e.apps.utils.modules.CommonUtilsModule import foundation.e.apps.utils.parentFragment.TimeoutFragment +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import timber.log.Timber import java.io.File @@ -199,6 +203,14 @@ class MainActivity : AppCompatActivity() { } viewModel.updateAppWarningList() + + lifecycleScope.launchWhenResumed { + EventBus.events.filter { appEvent -> + appEvent == AppEvent.INSTALL_FAILED_UPDATE_INCOMPATIBLE + }.collectLatest { + // TODO show message to Users + } + } } private fun handleFusedDownloadQueued( diff --git a/app/src/main/java/foundation/e/apps/api/database/AppDatabase.kt b/app/src/main/java/foundation/e/apps/api/database/AppDatabase.kt index 174e825e2..d52abde04 100644 --- a/app/src/main/java/foundation/e/apps/api/database/AppDatabase.kt +++ b/app/src/main/java/foundation/e/apps/api/database/AppDatabase.kt @@ -6,17 +6,20 @@ import androidx.room.Room import androidx.room.RoomDatabase import foundation.e.apps.api.exodus.Tracker import foundation.e.apps.api.exodus.TrackerDao +import foundation.e.apps.api.faultyApps.FaultyApp +import foundation.e.apps.api.faultyApps.FaultyAppDao import foundation.e.apps.api.fdroid.FdroidDao import foundation.e.apps.api.fdroid.models.FdroidEntity @Database( - entities = [Tracker::class, FdroidEntity::class], - version = 2, + entities = [Tracker::class, FdroidEntity::class, FaultyApp::class], + version = 3, exportSchema = false ) abstract class AppDatabase : RoomDatabase() { abstract fun trackerDao(): TrackerDao abstract fun fdroidDao(): FdroidDao + abstract fun faultyAppsDao(): FaultyAppDao companion object { private lateinit var INSTANCE: AppDatabase diff --git a/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyApp.kt b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyApp.kt new file mode 100644 index 000000000..36c1af2e0 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyApp.kt @@ -0,0 +1,27 @@ +/* + * + * * Copyright ECORP SAS 2022 + * * Apps Quickly and easily install Android apps onto your device! + * * + * * 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 . + * + */ + +package foundation.e.apps.api.faultyApps + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class FaultyApp(@PrimaryKey val packageName: String, val error: String) diff --git a/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppDao.kt b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppDao.kt new file mode 100644 index 000000000..0218ebf6d --- /dev/null +++ b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppDao.kt @@ -0,0 +1,38 @@ +/* + * + * * Copyright ECORP SAS 2022 + * * Apps Quickly and easily install Android apps onto your device! + * * + * * 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 . + * + */ + +package foundation.e.apps.api.faultyApps + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy.REPLACE +import androidx.room.Query + +@Dao +interface FaultyAppDao { + @Insert(onConflict = REPLACE) + suspend fun addFaultyApp(faultyApp: FaultyApp): Long + + @Query("SELECT * FROM FAULTYAPP") + suspend fun getFaultyApps(): List + + @Query("DELETE FROM FaultyApp WHERE packageName = :packageName") + suspend fun deleteFaultyAppByPackageName(packageName: String): Int +} diff --git a/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppRepository.kt b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppRepository.kt new file mode 100644 index 000000000..aebbb2822 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/api/faultyApps/FaultyAppRepository.kt @@ -0,0 +1,41 @@ +/* + * + * * Copyright ECORP SAS 2022 + * * Apps Quickly and easily install Android apps onto your device! + * * + * * 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 . + * + */ + +package foundation.e.apps.api.faultyApps + +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class FaultyAppRepository @Inject constructor(private val faultyAppDao: FaultyAppDao) { + + suspend fun addFaultyApp(packageName: String, error: String) { + val faultyApp = FaultyApp(packageName, error) + faultyAppDao.addFaultyApp(faultyApp) + } + + suspend fun getAllFaultyApps(): List { + return faultyAppDao.getFaultyApps() + } + + suspend fun deleteFaultyAppByPackageName(packageName: String) { + faultyAppDao.deleteFaultyAppByPackageName(packageName) + } +} diff --git a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt index fc32cadeb..a45d98ba7 100644 --- a/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt +++ b/app/src/main/java/foundation/e/apps/api/fused/FusedAPIImpl.kt @@ -49,11 +49,11 @@ import foundation.e.apps.api.gplay.GPlayAPIRepository import foundation.e.apps.manager.database.fusedDownload.FusedDownload import foundation.e.apps.manager.pkg.PkgManagerModule import foundation.e.apps.utils.enums.AppTag +import foundation.e.apps.utils.enums.FilterLevel import foundation.e.apps.utils.enums.Origin import foundation.e.apps.utils.enums.ResultStatus import foundation.e.apps.utils.enums.Status import foundation.e.apps.utils.enums.Type -import foundation.e.apps.utils.enums.FilterLevel import foundation.e.apps.utils.enums.isUnFiltered import foundation.e.apps.utils.modules.CommonUtilsModule.timeoutDurationInMillis import foundation.e.apps.utils.modules.PWAManagerModule @@ -550,9 +550,11 @@ class FusedAPIImpl @Inject constructor( by = "package_name" ).body()?.run { if (apps.isNotEmpty() && numberOfResults == 1) { - fusedAppList.add(apps[0].apply { - updateFilterLevel(null) - }) + fusedAppList.add( + apps[0].apply { + updateFilterLevel(null) + } + ) } } }) @@ -591,9 +593,11 @@ class FusedAPIImpl @Inject constructor( */ val filter = getAppFilterLevel(app, authData) if (filter.isUnFiltered()) { - fusedAppList.add(app.transformToFusedApp().apply { - filterLevel = filter - }) + fusedAppList.add( + app.transformToFusedApp().apply { + filterLevel = filter + } + ) } } }) @@ -621,9 +625,11 @@ class FusedAPIImpl @Inject constructor( appList.forEach { val filter = getAppFilterLevel(it, authData) if (filter.isUnFiltered()) { - filteredFusedApps.add(it.transformToFusedApp().apply { - this.filterLevel = filter - }) + filteredFusedApps.add( + it.transformToFusedApp().apply { + this.filterLevel = filter + } + ) } } }) diff --git a/app/src/main/java/foundation/e/apps/di/DaoModule.kt b/app/src/main/java/foundation/e/apps/di/DaoModule.kt index 6b2f8692a..4c2a77e6f 100644 --- a/app/src/main/java/foundation/e/apps/di/DaoModule.kt +++ b/app/src/main/java/foundation/e/apps/di/DaoModule.kt @@ -8,6 +8,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import foundation.e.apps.api.database.AppDatabase import foundation.e.apps.api.exodus.TrackerDao +import foundation.e.apps.api.faultyApps.FaultyAppDao import foundation.e.apps.api.fdroid.FdroidDao @InstallIn(SingletonComponent::class) @@ -22,4 +23,9 @@ object DaoModule { fun getFdroidDao(@ApplicationContext context: Context): FdroidDao { return AppDatabase.getInstance(context).fdroidDao() } + + @Provides + fun getFaultyAppsDao(@ApplicationContext context: Context): FaultyAppDao { + return AppDatabase.getInstance(context).faultyAppsDao() + } } diff --git a/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt b/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt index 660e83df1..55ad9e711 100644 --- a/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt +++ b/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt @@ -25,9 +25,13 @@ import android.os.Build import android.os.IBinder import androidx.annotation.RequiresApi import dagger.hilt.android.AndroidEntryPoint +import foundation.e.apps.api.faultyApps.FaultyAppRepository import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.utils.enums.Status +import foundation.e.apps.utils.eventBus.AppEvent +import foundation.e.apps.utils.eventBus.EventBus import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @@ -41,6 +45,9 @@ class InstallerService : Service() { @Inject lateinit var pkgManagerModule: PkgManagerModule + @Inject + lateinit var faultyAppRepository: FaultyAppRepository + companion object { const val TAG = "InstallerService" } @@ -56,9 +63,20 @@ class InstallerService : Service() { } private fun postStatus(status: Int, packageName: String?, extra: String?) { - Timber.d("postStatus: $status $packageName $extra") + Timber.d("### postStatus: $status $packageName $extra") if (status != PackageInstaller.STATUS_SUCCESS) { updateInstallationIssue(packageName ?: "") + if (status == 5 && extra?.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE") == true) { + MainScope().launch { + if (packageName.isNullOrEmpty()) { + Timber.wtf("Installation failure for an app without packagename!") + return@launch + } + EventBus.invokeEvent(AppEvent.INSTALL_FAILED_UPDATE_INCOMPATIBLE) + faultyAppRepository.addFaultyApp(packageName, "INSTALL_FAILED_UPDATE_INCOMPATIBLE") + Timber.d("### INSTALL_FAILED_UPDATE_INCOMPATIBLE for $packageName") + } + } } } diff --git a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerBR.kt b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerBR.kt index 211e3dbca..665150bdd 100644 --- a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerBR.kt +++ b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerBR.kt @@ -23,28 +23,34 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageInstaller import dagger.hilt.android.AndroidEntryPoint +import foundation.e.apps.api.faultyApps.FaultyAppRepository import foundation.e.apps.manager.fused.FusedManagerRepository import foundation.e.apps.utils.enums.Status +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject +import javax.inject.Named @AndroidEntryPoint @DelicateCoroutinesApi open class PkgManagerBR : BroadcastReceiver() { - companion object { - private const val TAG = "PkgManagerBR" - } - @Inject lateinit var fusedManagerRepository: FusedManagerRepository @Inject lateinit var pkgManagerModule: PkgManagerModule + @Inject + lateinit var faultyAppRepository: FaultyAppRepository + + @Inject + @Named("ioCoroutineScope") + lateinit var coroutineScope: CoroutineScope + override fun onReceive(context: Context?, intent: Intent?) { val action = intent?.action if (context != null && action != null) { @@ -61,9 +67,11 @@ open class PkgManagerBR : BroadcastReceiver() { when (action) { Intent.ACTION_PACKAGE_ADDED -> { updateDownloadStatus(pkgName) + removeFaultyAppByPackageName(pkgName) } Intent.ACTION_PACKAGE_REMOVED -> { if (!isUpdating) deleteDownload(pkgName) + removeFaultyAppByPackageName(pkgName) } PkgManagerModule.ERROR_PACKAGE_INSTALL -> { Timber.e("Installation failed due to error: $extra") @@ -75,6 +83,12 @@ open class PkgManagerBR : BroadcastReceiver() { } } + private fun removeFaultyAppByPackageName(pkgName: String) { + coroutineScope.launch { + faultyAppRepository.deleteFaultyAppByPackageName(pkgName) + } + } + private fun deleteDownload(pkgName: String) { GlobalScope.launch { val fusedDownload = fusedManagerRepository.getFusedDownload(packageName = pkgName) diff --git a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt index 8ed984890..2c2ce9d2e 100644 --- a/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/updates/manager/UpdatesManagerImpl.kt @@ -19,6 +19,7 @@ package foundation.e.apps.updates.manager import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.api.faultyApps.FaultyAppRepository import foundation.e.apps.api.fused.FusedAPIRepository import foundation.e.apps.api.fused.data.FusedApp import foundation.e.apps.manager.pkg.PkgManagerModule @@ -30,7 +31,8 @@ import javax.inject.Inject class UpdatesManagerImpl @Inject constructor( private val pkgManagerModule: PkgManagerModule, - private val fusedAPIRepository: FusedAPIRepository + private val fusedAPIRepository: FusedAPIRepository, + private val faultyAppRepository: FaultyAppRepository ) { private val TAG = UpdatesManagerImpl::class.java.simpleName @@ -75,7 +77,9 @@ class UpdatesManagerImpl @Inject constructor( } } } - return Pair(updateList, status) + val faultyAppsPackageNames = faultyAppRepository.getAllFaultyApps().map { it.packageName } + val nonFaultyUpdateList = updateList.filter { !faultyAppsPackageNames.contains(it.package_name) } + return Pair(nonFaultyUpdateList, status) } fun getApplicationCategoryPreference(): String { diff --git a/app/src/main/java/foundation/e/apps/utils/enums/FilterLevel.kt b/app/src/main/java/foundation/e/apps/utils/enums/FilterLevel.kt index 7eec33730..4fd93c524 100644 --- a/app/src/main/java/foundation/e/apps/utils/enums/FilterLevel.kt +++ b/app/src/main/java/foundation/e/apps/utils/enums/FilterLevel.kt @@ -34,11 +34,11 @@ package foundation.e.apps.utils.enums * Issue: https://gitlab.e.foundation/e/backlog/-/issues/5720 */ enum class FilterLevel { - UI, // Show the app in lists, but show "N/A" in the install button. - DATA, // Filter the app out from lists and search results, don't show the app at all. - NONE, // No restrictions - UNKNOWN, // Not initialised yet + UI, // Show the app in lists, but show "N/A" in the install button. + DATA, // Filter the app out from lists and search results, don't show the app at all. + NONE, // No restrictions + UNKNOWN, // Not initialised yet } fun FilterLevel.isUnFiltered(): Boolean = this == FilterLevel.NONE -fun FilterLevel.isInitialized(): Boolean = this != FilterLevel.UNKNOWN \ No newline at end of file +fun FilterLevel.isInitialized(): Boolean = this != FilterLevel.UNKNOWN diff --git a/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt new file mode 100644 index 000000000..e5d2f6bf3 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt @@ -0,0 +1,25 @@ +/* + * + * * Copyright ECORP SAS 2022 + * * Apps Quickly and easily install Android apps onto your device! + * * + * * 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 . + * + */ + +package foundation.e.apps.utils.eventBus + +enum class AppEvent { + INSTALL_FAILED_UPDATE_INCOMPATIBLE +} diff --git a/app/src/main/java/foundation/e/apps/utils/eventBus/EventBus.kt b/app/src/main/java/foundation/e/apps/utils/eventBus/EventBus.kt new file mode 100644 index 000000000..ffb5fac95 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/utils/eventBus/EventBus.kt @@ -0,0 +1,31 @@ +/* + * + * * Copyright ECORP SAS 2022 + * * Apps Quickly and easily install Android apps onto your device! + * * + * * 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 . + * + */ + +package foundation.e.apps.utils.eventBus + +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow + +object EventBus { + private val _events = MutableSharedFlow() + val events = _events.asSharedFlow() + + suspend fun invokeEvent(event: AppEvent) = _events.emit(event) +} -- GitLab From 70208c08ea2a935749e5eff48e0a3838aacf2bd0 Mon Sep 17 00:00:00 2001 From: Hasib Prince Date: Fri, 8 Jul 2022 18:13:25 +0600 Subject: [PATCH 2/2] Signature missmatch message added --- .../java/foundation/e/apps/MainActivity.kt | 11 ++++-- .../e/apps/MainActivityViewModel.kt | 4 +++ .../e/apps/manager/pkg/InstallerService.kt | 36 ++++++++++++------- .../e/apps/manager/pkg/PkgManagerModule.kt | 7 ++++ .../e/apps/utils/eventBus/AppEvent.kt | 4 +-- app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt index e3a9cf5dd..f46bd0852 100644 --- a/app/src/main/java/foundation/e/apps/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/MainActivity.kt @@ -206,9 +206,14 @@ class MainActivity : AppCompatActivity() { lifecycleScope.launchWhenResumed { EventBus.events.filter { appEvent -> - appEvent == AppEvent.INSTALL_FAILED_UPDATE_INCOMPATIBLE + appEvent is AppEvent.SignatureMissMatchError }.collectLatest { - // TODO show message to Users + val appName = viewModel.getAppNameByPackageName(it.data.toString()) + ApplicationDialogFragment( + title = getString(R.string.update_error), + message = getString(R.string.error_signature_mismatch, appName), + positiveButtonText = getString(R.string.ok) + ).show(supportFragmentManager, TAG) } } } @@ -258,7 +263,7 @@ class MainActivity : AppCompatActivity() { } fun showSnackbarMessage(message: String) { - Snackbar.make(binding.root, message, Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, message, Snackbar.LENGTH_LONG).show() } private fun showNoInternet() { diff --git a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt index 0156a2d7a..83834f12a 100644 --- a/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt +++ b/app/src/main/java/foundation/e/apps/MainActivityViewModel.kt @@ -561,4 +561,8 @@ class MainActivityViewModel @Inject constructor( fun updateAppWarningList() { blockedAppRepository.fetchUpdateOfAppWarningList() } + + fun getAppNameByPackageName(packageName: String): String { + return pkgManagerModule.getAppNameFromPackageName(packageName) + } } diff --git a/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt b/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt index 55ad9e711..23a5e2f74 100644 --- a/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt +++ b/app/src/main/java/foundation/e/apps/manager/pkg/InstallerService.kt @@ -50,6 +50,7 @@ class InstallerService : Service() { companion object { const val TAG = "InstallerService" + private const val INSTALL_FAILED_UPDATE_INCOMPATIBLE = "INSTALL_FAILED_UPDATE_INCOMPATIBLE" } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @@ -63,20 +64,29 @@ class InstallerService : Service() { } private fun postStatus(status: Int, packageName: String?, extra: String?) { - Timber.d("### postStatus: $status $packageName $extra") - if (status != PackageInstaller.STATUS_SUCCESS) { - updateInstallationIssue(packageName ?: "") - if (status == 5 && extra?.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE") == true) { - MainScope().launch { - if (packageName.isNullOrEmpty()) { - Timber.wtf("Installation failure for an app without packagename!") - return@launch - } - EventBus.invokeEvent(AppEvent.INSTALL_FAILED_UPDATE_INCOMPATIBLE) - faultyAppRepository.addFaultyApp(packageName, "INSTALL_FAILED_UPDATE_INCOMPATIBLE") - Timber.d("### INSTALL_FAILED_UPDATE_INCOMPATIBLE for $packageName") - } + Timber.d("postStatus: $status $packageName $extra") + if (status == PackageInstaller.STATUS_SUCCESS) { + return + } + + updateInstallationIssue(packageName ?: "") + if (status == PackageInstaller.STATUS_FAILURE_CONFLICT && extra?.contains( + INSTALL_FAILED_UPDATE_INCOMPATIBLE + ) == true + ) { + handleInstallFailureDueToSignatureMismatch(packageName) + } + } + + private fun handleInstallFailureDueToSignatureMismatch(packageName: String?) { + MainScope().launch { + if (packageName.isNullOrEmpty()) { + Timber.wtf("Installation failure for an app without packagename!") + return@launch } + EventBus.invokeEvent(AppEvent.SignatureMissMatchError(packageName)) + faultyAppRepository.addFaultyApp(packageName, INSTALL_FAILED_UPDATE_INCOMPATIBLE) + Timber.e("INSTALL_FAILED_UPDATE_INCOMPATIBLE for $packageName") } } diff --git a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt index e694d89e7..20ca99948 100644 --- a/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt +++ b/app/src/main/java/foundation/e/apps/manager/pkg/PkgManagerModule.kt @@ -229,4 +229,11 @@ class PkgManagerModule @Inject constructor( fun getAllSystemApps(): List { return packageManager.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY) } + + fun getAppNameFromPackageName(packageName: String): String { + val packageManager = context.packageManager + return packageManager.getApplicationLabel( + packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA) + ).toString() + } } diff --git a/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt index e5d2f6bf3..a3a7306ef 100644 --- a/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt +++ b/app/src/main/java/foundation/e/apps/utils/eventBus/AppEvent.kt @@ -20,6 +20,6 @@ package foundation.e.apps.utils.eventBus -enum class AppEvent { - INSTALL_FAILED_UPDATE_INCOMPATIBLE +sealed class AppEvent(val data: Any) { + class SignatureMissMatchError(packageName: String) : AppEvent(packageName) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 38407f25e..b6db8704e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -118,6 +118,8 @@ App updates will be installed automatically App updates will not be installed automatically All apps are up-to-date + The update cannot be applied because there is a signature mismatch between the update of %1$s and the version you\'ve installed on your phone. To remedy this you can uninstall %1$s and then install it again from App Lounge. <br /><br /> Note: This message won\'t appear again. + Update Error! Discover -- GitLab