feat(installer): Store install metadata in APK
This commit is contained in:
parent
c5eded4f63
commit
e4eddf7c89
25 changed files with 160 additions and 28 deletions
|
|
@ -24,6 +24,7 @@ import com.aliucord.manager.ui.screens.home.HomeScreen
|
|||
import com.aliucord.manager.ui.screens.install.InstallScreen
|
||||
import com.aliucord.manager.ui.screens.installopts.InstallOptionsScreen
|
||||
import com.aliucord.manager.ui.widgets.updater.UpdaterDialog
|
||||
import com.aliucord.manager.util.IS_CUSTOM_BUILD
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
// TODO: move to a path provider in DI
|
||||
|
|
@ -46,12 +47,7 @@ class MainActivity : ComponentActivity() {
|
|||
) {
|
||||
StoragePermissionsDialog()
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
if (
|
||||
BuildConfig.GIT_BRANCH == "release" &&
|
||||
!BuildConfig.GIT_LOCAL_CHANGES &&
|
||||
!BuildConfig.GIT_LOCAL_COMMITS
|
||||
) {
|
||||
if (!IS_CUSTOM_BUILD) {
|
||||
UpdaterDialog()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package com.aliucord.manager.installer
|
||||
|
||||
import com.aliucord.manager.ui.screens.installopts.InstallOptions
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Data stored inside patched APKs as "aliucord.json" in order to preserve install-time information about Aliucord and the Manager.
|
||||
*/
|
||||
@Serializable
|
||||
data class InstallMetadata(
|
||||
/**
|
||||
* The user-selected options for this installation.
|
||||
*/
|
||||
val options: InstallOptions,
|
||||
|
||||
/**
|
||||
* The semver version of this manager that performed the installation.
|
||||
*/
|
||||
val managerVersionName: String,
|
||||
|
||||
/**
|
||||
* Whether the manager is a real release or built from source.
|
||||
*/
|
||||
val customManager: Boolean,
|
||||
|
||||
/**
|
||||
* Aliuhook release version injected into the APK.
|
||||
*/
|
||||
val aliuhookVersion: String,
|
||||
|
||||
/**
|
||||
* Short commit hash of the commit the injector was built from.
|
||||
*/
|
||||
val injectorCommitHash: String,
|
||||
)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.aliucord.manager.installer.steps
|
||||
package com.aliucord.manager.installer
|
||||
|
||||
import com.aliucord.manager.installer.steps.download.*
|
||||
import com.aliucord.manager.installer.steps.install.*
|
||||
|
|
@ -29,6 +29,7 @@ class KotlinInstallRunner(options: InstallOptions) : StepRunner() {
|
|||
PatchManifestStep(options),
|
||||
AddInjectorStep(),
|
||||
AddAliuhookStep(),
|
||||
SaveMetadataStep(options),
|
||||
|
||||
// Install
|
||||
AlignmentStep(),
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package com.aliucord.manager.installer.steps
|
||||
package com.aliucord.manager.installer
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.ProcessLifecycleOwner
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.base.DownloadStep
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.manager.PreferencesManager
|
||||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.manager.DownloadManager
|
||||
import com.aliucord.manager.util.showToast
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.base
|
|||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.*
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.util.toPrecision
|
||||
import kotlinx.coroutines.*
|
||||
import org.koin.core.time.measureTimedValue
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.download
|
|||
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
import org.koin.core.component.KoinComponent
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.download
|
|||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.domain.repository.AliucordMavenRepository
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.DownloadStep
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
import com.aliucord.manager.network.utils.getOrThrow
|
||||
|
|
@ -21,7 +21,8 @@ class DownloadAliuhookStep : DownloadStep(), KoinComponent {
|
|||
/**
|
||||
* This is populated right before the download starts (ref: [execute])
|
||||
*/
|
||||
private lateinit var targetVersion: String
|
||||
lateinit var targetVersion: String
|
||||
private set
|
||||
|
||||
override val localizedName = R.string.install_step_dl_aliuhook
|
||||
override val targetUrl get() = AliucordMavenRepository.getAliuhookUrl(targetVersion)
|
||||
|
|
@ -33,4 +34,3 @@ class DownloadAliuhookStep : DownloadStep(), KoinComponent {
|
|||
super.execute(container)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.download
|
|||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.DownloadStep
|
||||
import com.aliucord.manager.installer.steps.prepare.FetchInfoStep
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
|
|
@ -21,7 +21,8 @@ class DownloadInjectorStep : DownloadStep(), KoinComponent {
|
|||
* Populated from a dependency step ([FetchInfoStep]).
|
||||
* This is used as cache invalidation (ref: [Version.aliucordHash])
|
||||
*/
|
||||
private lateinit var aliucordHash: String
|
||||
lateinit var aliucordHash: String
|
||||
private set
|
||||
|
||||
override val localizedName = R.string.install_step_dl_injector
|
||||
override val targetUrl = URL
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.install
|
|||
import android.os.Build
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
|
|
@ -14,8 +14,6 @@ import org.koin.core.component.KoinComponent
|
|||
* Align certain files in the APK to a 4KiB boundary.
|
||||
*/
|
||||
class AlignmentStep : Step(), KoinComponent {
|
||||
private val currentDeviceArch = Build.SUPPORTED_ABIS.first()
|
||||
|
||||
override val group = StepGroup.Install
|
||||
override val localizedName = R.string.install_step_alignment
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.install
|
|||
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import androidx.lifecycle.*
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.install
|
|||
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
import com.aliucord.manager.installer.util.Signer
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.patch
|
|||
import android.os.Build
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
import com.aliucord.manager.installer.steps.download.DownloadAliuhookStep
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.patch
|
|||
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.download.*
|
||||
import com.github.diamondminer88.zip.ZipReader
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.aliucord.manager.installer.steps.patch
|
|||
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
import com.aliucord.manager.installer.util.ManifestPatcher
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import android.os.Build
|
|||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
import com.aliucord.manager.installer.steps.download.CopyDependenciesStep
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
package com.aliucord.manager.installer.steps.patch
|
||||
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.InstallMetadata
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.download.*
|
||||
import com.aliucord.manager.ui.screens.installopts.InstallOptions
|
||||
import com.aliucord.manager.util.IS_CUSTOM_BUILD
|
||||
import com.github.diamondminer88.zip.ZipWriter
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
/**
|
||||
* Store the install options and additional data inside the APK for future use,
|
||||
* for example checking what library versions were used, or performing "updates" while
|
||||
* maintaining the same install options as what was used upon first install.
|
||||
*/
|
||||
class SaveMetadataStep(private val options: InstallOptions) : Step() {
|
||||
override val group = StepGroup.Patch
|
||||
override val localizedName = R.string.install_step_save_metadata
|
||||
|
||||
private val json = Json {
|
||||
prettyPrint = true
|
||||
}
|
||||
|
||||
override suspend fun execute(container: StepRunner) {
|
||||
val apk = container.getStep<CopyDependenciesStep>().patchedApk
|
||||
val aliuhook = container.getStep<DownloadAliuhookStep>()
|
||||
val injector = container.getStep<DownloadInjectorStep>()
|
||||
|
||||
val metadata = InstallMetadata(
|
||||
options = options,
|
||||
managerVersionName = BuildConfig.VERSION_NAME,
|
||||
customManager = IS_CUSTOM_BUILD,
|
||||
aliuhookVersion = aliuhook.targetVersion,
|
||||
injectorCommitHash = injector.aliucordHash,
|
||||
)
|
||||
|
||||
ZipWriter(apk, /* append = */ true).use {
|
||||
it.writeEntry("aliucord.json", json.encodeToString<InstallMetadata>(metadata))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.prepare
|
|||
import android.content.Context
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
import com.aliucord.manager.installer.util.uninstallApk
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.aliucord.manager.installer.steps.prepare
|
|||
import androidx.compose.runtime.Stable
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.steps.StepGroup
|
||||
import com.aliucord.manager.installer.steps.StepRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.network.dto.Version
|
||||
import com.aliucord.manager.network.service.AliucordGithubService
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import cafe.adriel.voyager.core.model.StateScreenModel
|
|||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.R
|
||||
import com.aliucord.manager.installer.KotlinInstallRunner
|
||||
import com.aliucord.manager.installer.StepRunner
|
||||
import com.aliucord.manager.installer.steps.*
|
||||
import com.aliucord.manager.installer.steps.base.Step
|
||||
import com.aliucord.manager.installer.steps.base.StepState
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ import android.os.Parcelable
|
|||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.aliucord.manager.util.ColorParceler
|
||||
import com.aliucord.manager.util.ColorSerializer
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import kotlinx.parcelize.TypeParceler
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Serializable
|
||||
data class InstallOptions(
|
||||
/**
|
||||
* The app name that's user-facing in launchers.
|
||||
|
|
@ -38,12 +42,15 @@ data class InstallOptions(
|
|||
) : Parcelable {
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Serializable
|
||||
sealed interface IconReplacement : Parcelable {
|
||||
/**
|
||||
* Keeps the original icons that are present in the APK.
|
||||
*/
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Serializable
|
||||
@SerialName("original")
|
||||
data object Original : IconReplacement
|
||||
|
||||
/**
|
||||
|
|
@ -52,8 +59,11 @@ data class InstallOptions(
|
|||
*/
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Serializable
|
||||
@SerialName("color")
|
||||
data class CustomColor(
|
||||
@TypeParceler<Color, ColorParceler>
|
||||
@Serializable(ColorSerializer::class)
|
||||
val color: Color,
|
||||
) : IconReplacement
|
||||
|
||||
|
|
@ -63,6 +73,8 @@ data class InstallOptions(
|
|||
*/
|
||||
@Immutable
|
||||
@Parcelize
|
||||
@Serializable
|
||||
@SerialName("image")
|
||||
data class CustomImage(val imageBytes: ByteArray) : IconReplacement {
|
||||
override fun hashCode() = imageBytes.contentHashCode()
|
||||
override fun equals(other: Any?) = this === other
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package com.aliucord.manager.util
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.descriptors.*
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
|
||||
/**
|
||||
* (De)serialize compose's [Color] into/from an ARGB hex string.
|
||||
*/
|
||||
object ColorSerializer : KSerializer<Color> {
|
||||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Color", PrimitiveKind.STRING)
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Color) {
|
||||
val string = value
|
||||
.toArgb().toUInt()
|
||||
.toString(16)
|
||||
.padStart(8, '0')
|
||||
encoder.encodeString(string)
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): Color {
|
||||
val string = decoder.decodeString()
|
||||
return Color(string.toInt(16))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.aliucord.manager.util
|
||||
|
||||
import androidx.collection.ObjectList
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.truncate
|
||||
|
||||
|
|
@ -20,3 +21,13 @@ inline fun <E> ObjectList<E>.find(block: (E) -> Boolean): E? {
|
|||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this manager build is not an official release.
|
||||
*/
|
||||
@Suppress("KotlinConstantConditions")
|
||||
val IS_CUSTOM_BUILD by lazy {
|
||||
BuildConfig.GIT_BRANCH != "release"
|
||||
|| BuildConfig.GIT_LOCAL_CHANGES
|
||||
|| BuildConfig.GIT_LOCAL_COMMITS
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@
|
|||
<string name="install_step_patch_icon">Patching app icon</string>
|
||||
<string name="install_step_add_injector">Adding Aliucord injector</string>
|
||||
<string name="install_step_add_aliuhook">Adding Aliuhook library</string>
|
||||
<string name="install_step_save_metadata">Store metadata</string>
|
||||
<string name="install_step_alignment">Aligning APKs</string>
|
||||
<string name="install_step_signing">Signing APKs</string>
|
||||
<string name="install_step_installing">Installing APKs</string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue