diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index becd880924067d3ad4b2c7e23a94bdeb239ad083..66b2941e78e6d5876ba4909e9fad196ea9800818 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,16 +2,27 @@ image: registry.gitlab.e.foundation/e/os/docker-android-apps-cicd:master variables: SENTRY_DSN: $SENTRY_DSN + PROJECT_ID: "355" # under Settings -> General + APK_PATH: "apks" + UNSIGNED_APK: "AppLounge-release.apk" + DEV_APK: "AppLounge-release-dev.apk" + STABLE_APK: "AppLounge-release-stable.apk" stages: - debug - release - publish + - gitlab_release before_script: - export GRADLE_USER_HOME=$(pwd)/.gradle - chmod +x ./gradlew +cache: + key: ${CI_PROJECT_ID} + paths: + - .gradle/ + # Debug build related jobs buildDebug: stage: debug @@ -173,6 +184,7 @@ pushToPrebuilt: - git push # Sometimes a single push doesn't do all the job, so we have to push twice - git push + allow_failure: true publish-contracts: stage: publish @@ -186,3 +198,86 @@ publish-contracts: - ./gradlew :parental-control-data:build - ./gradlew :parental-control-data:publish allow_failure: true + +init-submodules: + stage: gitlab_release + needs: [] + rules: + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + when: on_success + script: + - | + git submodule add --force \ + https://gitlab.e.foundation/e/os/system-apps-update-info.git systemAppsUpdateInfo + artifacts: + paths: + - systemAppsUpdateInfo/ + +generate-apks: + stage: gitlab_release + rules: + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + when: on_success + needs: + - init-submodules + - buildRelease + - buildReleaseDev + - buildReleaseStable + dependencies: + - init-submodules + - buildRelease + - buildReleaseDev + - buildReleaseStable + script: + - mkdir -p $APK_PATH + - unsignedApk=$(ls app/build/outputs/apk/release/*.apk | grep "release") + - devApk=$(ls app/build/outputs/apk/releaseDev/*.apk | grep "releaseDev") + - stableApk=$(ls app/build/outputs/apk/releaseStable/*.apk | grep "releaseStable") + - cp "$unsignedApk" "$APK_PATH/$UNSIGNED_APK" + - cp "$devApk" "$APK_PATH/$DEV_APK" + - cp "$stableApk" "$APK_PATH/$STABLE_APK" + artifacts: + paths: + - $APK_PATH/$UNSIGNED_APK + - $APK_PATH/$DEV_APK + - $APK_PATH/$STABLE_APK + +create-json-files: + stage: gitlab_release + dependencies: + - init-submodules + - generate-apks + needs: + - init-submodules + - generate-apks + rules: + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + when: manual + before_script: + - apt update && apt install jq aapt -y + script: + - | + ./systemAppsUpdateInfo/scripts/create-json-files.sh \ + "$APK_PATH" "$UNSIGNED_APK" "$DEV_APK" "$STABLE_APK" + artifacts: + paths: + - dev.json + - stable.json + +create-release: + stage: gitlab_release + dependencies: + - init-submodules + needs: + - init-submodules + - create-json-files + - generate-apks + rules: + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + when: on_success + before_script: + - apt update && apt install jq -y + script: + - | + ./systemAppsUpdateInfo/scripts/create-release.sh \ + "$APK_PATH" "$UNSIGNED_APK" "$DEV_APK" "$STABLE_APK" \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5f2f500d7d1ac06bcb490d5c6a8eebe4f0eb9511..b0b6212189461e3bdd062594d3462a5dbd2e4dae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -101,6 +101,7 @@ android:exported="false"> + diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt index e634645d2bf1c4d59dd9926cb22390f2fbed3897..7fb6ee71f9df68da50a4b4b1fedbbe5e0237e7b5 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt @@ -52,7 +52,20 @@ class SystemAppsUpdatesRepository @Inject constructor( if (getUpdatableSystemApps().isNotEmpty() && !forceRefresh) { return@handleNetworkResult } - val response = updatableSystemAppsApi.getUpdatableSystemApps() + + val systemName = getFullSystemName() + val endPoint = if ( + systemName.isBlank() || + systemName.contains("beta") || + systemName.contains("rc") + ) { + UpdatableSystemAppsApi.EndPoint.ENDPOINT_TEST + } else { + UpdatableSystemAppsApi.EndPoint.ENDPOINT_RELEASE + } + + val response = updatableSystemAppsApi.getUpdatableSystemApps(endPoint) + if (response.isSuccessful && !response.body().isNullOrEmpty()) { systemAppProjectList.clear() response.body()?.let { systemAppProjectList.addAll(it) } @@ -103,6 +116,10 @@ class SystemAppsUpdatesRepository @Inject constructor( } } + private fun getFullSystemName(): String { + return SystemInfoProvider.getSystemProperty(SystemInfoProvider.KEY_LINEAGE_VERSION) ?: "" + } + private fun getSdkLevel(): Int { return Build.VERSION.SDK_INT } diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/UpdatableSystemAppsApi.kt b/app/src/main/java/foundation/e/apps/data/gitlab/UpdatableSystemAppsApi.kt index 2ea9774faaa5c3cbee98a089fec57a5fe56af16b..7053450f2a129f9611babfe33ed3fc058b1e0e28 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/UpdatableSystemAppsApi.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/UpdatableSystemAppsApi.kt @@ -20,6 +20,7 @@ package foundation.e.apps.data.gitlab import foundation.e.apps.data.gitlab.models.SystemAppProject import retrofit2.Response import retrofit2.http.GET +import retrofit2.http.Path interface UpdatableSystemAppsApi { @@ -28,7 +29,18 @@ interface UpdatableSystemAppsApi { "https://gitlab.e.foundation/e/os/system-apps-update-info/-/raw/main/" } - @GET("updatable_system_apps.json?inline=false") - suspend fun getUpdatableSystemApps(): Response> + enum class EndPoint(private val value: String) { + ENDPOINT_RELEASE("updatable_system_apps.json"), + ENDPOINT_TEST("updatable_system_apps_test.json"), + ; + override fun toString(): String { + return value + } + } + + @GET("{endPoint}?inline=false") + suspend fun getUpdatableSystemApps( + @Path("endPoint") endPoint: EndPoint = EndPoint.ENDPOINT_RELEASE + ): Response> } diff --git a/app/src/main/java/foundation/e/apps/data/install/AppManagerImpl.kt b/app/src/main/java/foundation/e/apps/data/install/AppManagerImpl.kt index 1757e7d2f62504a80900211bc3d29febc6b56d42..27670c9be4774728eab4e0f43340ab3f47e0f229 100644 --- a/app/src/main/java/foundation/e/apps/data/install/AppManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/install/AppManagerImpl.kt @@ -100,7 +100,13 @@ class AppManagerImpl @Inject constructor( } else if (status == Status.INSTALLING) { appInstall.downloadIdMap.all { true } appInstall.status = status - appInstallRepository.updateDownload(appInstall) + val isSelfUpdate = appInstall.packageName == context.packageName + if (isSelfUpdate) { + appInstallRepository.deleteDownload(appInstall) + } else { + appInstall.status = status + appInstallRepository.updateDownload(appInstall) + } installApp(appInstall) } } diff --git a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt index ddaacfbadf28ba822c928cd5c34090b6e87fe5d8..4cf3cd31a098106fdce6cdc2c220b644c96e0f47 100644 --- a/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt +++ b/app/src/main/java/foundation/e/apps/data/updates/UpdatesManagerImpl.kt @@ -128,7 +128,7 @@ class UpdatesManagerImpl @Inject constructor( val systemApps = getSystemAppUpdates() val nonFaultyUpdateList = faultyAppRepository.removeFaultyApps(updateList) - addSystemAppsAtFirst(updateList, nonFaultyUpdateList, systemApps) + addSystemApps(updateList, nonFaultyUpdateList, systemApps) return Pair(updateList, status) } @@ -166,7 +166,7 @@ class UpdatesManagerImpl @Inject constructor( val systemApps = getSystemAppUpdates() val nonFaultyUpdateList = faultyAppRepository.removeFaultyApps(updateList) - addSystemAppsAtFirst(updateList, nonFaultyUpdateList, systemApps) + addSystemApps(updateList, nonFaultyUpdateList, systemApps) return Pair(updateList, status) } @@ -183,8 +183,11 @@ class UpdatesManagerImpl @Inject constructor( * This method adds the system app updates at the beginning of the update list. * It will ensure our system apps are updated first, followed by other apps, * avoiding potential conflicts. + * + * Since installing an App Lounge update will cause App Lounge to be closed by the system, + * it is added at the end of the list. */ - private fun addSystemAppsAtFirst( + private fun addSystemApps( updateList: MutableList, nonFaultyApps: List, systemApps: List, @@ -192,6 +195,13 @@ class UpdatesManagerImpl @Inject constructor( updateList.clear() updateList.addAll(systemApps) updateList.addAll(nonFaultyApps) + + // Move App Lounge to the end of the list + val appLoungeItem = updateList.find { + it.isSystemApp && it.package_name == context.packageName + } ?: return + updateList.remove(appLoungeItem) + updateList.add(appLoungeItem) } /** diff --git a/app/src/main/java/foundation/e/apps/install/updates/UpdatesBroadcastReceiver.kt b/app/src/main/java/foundation/e/apps/install/updates/UpdatesBroadcastReceiver.kt index 8598a2543b41c1e4423b38dd059e2612bdd0a992..36e89a2470e0a022e1e25620028d31cdcaf156aa 100644 --- a/app/src/main/java/foundation/e/apps/install/updates/UpdatesBroadcastReceiver.kt +++ b/app/src/main/java/foundation/e/apps/install/updates/UpdatesBroadcastReceiver.kt @@ -28,7 +28,7 @@ class UpdatesBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { Timber.d("onReceive: ${intent.action}") - if (intent.action == Intent.ACTION_BOOT_COMPLETED) { + if (intent.action in listOf(Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED)) { val appLoungePreference = AppLoungePreference(context) val interval = appLoungePreference.getUpdateInterval() UpdatesWorkManager.enqueueWork(context, interval, ExistingPeriodicWorkPolicy.REPLACE) diff --git a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt index c88ae84aac86a4732678079d9f6b36788b797b30..db6b9e8aaad3922348e28a3d414d2736a8edfc92 100644 --- a/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt +++ b/app/src/main/java/foundation/e/apps/ui/applicationlist/ApplicationListRVAdapter.kt @@ -17,10 +17,12 @@ package foundation.e.apps.ui.applicationlist +import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageView +import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.core.view.children import androidx.core.view.isVisible @@ -532,7 +534,11 @@ class ApplicationListRVAdapter( if (mainActivityViewModel.checkUnsupportedApplication(searchApp, context)) { return@setOnClickListener } - installApplication(searchApp) + if (searchApp.package_name == context.packageName) { + showUpdateConfirmationDialog(context, searchApp) + } else { + installApplication(searchApp) + } } } progressBarInstall.visibility = View.GONE @@ -557,6 +563,17 @@ class ApplicationListRVAdapter( progressBarInstall.visibility = View.GONE } + private fun showUpdateConfirmationDialog(context: Context, searchApp: Application) { + AlertDialog.Builder(context).apply { + setTitle(R.string.own_update_warning_title) + setMessage(R.string.own_update_warning_description) + setPositiveButton(android.R.string.ok) {_, _ -> + installApplication(searchApp) + } + setNegativeButton(android.R.string.cancel, null) + }.show() + } + fun setData(newList: List, optionalCategory: String? = null) { optionalCategory?.let { this.optionalCategory = it diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 993dcea40961870a935c2ddf8d6a04b3c05ea0bf..fa41bcdf6112f70981e43b1cec523b8900253c62 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -143,6 +143,8 @@ Update all has failed. Automatic retries are in progress. Due to temporary failure, your apps cannot be all updated. Please try again later. %1$s\'s update has failed due to a support rule (location, OS version…). + Update warning! + App Lounge will be closed by the system while installing its own update. Kindly refrain from doing any other task till App Lounge is updated and closed. Discover Discover PWA