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