feat: silent updating (#51)
Co-authored-by: Diamond <33725716+DiamondMiner88@users.noreply.github.com>
This commit is contained in:
parent
f44cae2311
commit
c18ffbabea
5 changed files with 68 additions and 26 deletions
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
|
||||
|
|
@ -25,8 +26,8 @@
|
|||
android:name=".ManagerApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
tools:ignore="AllowBackup">
|
||||
<service android:name=".installer.service.InstallService" />
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
package com.aliucord.manager.installer.util
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
import pxb.android.axml.*
|
||||
|
||||
object ManifestPatcher {
|
||||
|
|
@ -67,10 +68,12 @@ object ManifestPatcher {
|
|||
|
||||
"uses-sdk" -> object : NodeVisitor(nv) {
|
||||
override fun attr(ns: String?, name: String?, resourceId: Int, type: Int, value: Any?) {
|
||||
if (name != "targetSdkVersion")
|
||||
if (name == "targetSdkVersion") {
|
||||
val version = if (Build.VERSION.SDK_INT >= 31) 30 else 28
|
||||
super.attr(ns, name, resourceId, type, version)
|
||||
} else {
|
||||
super.attr(ns, name, resourceId, type, value)
|
||||
|
||||
super.attr(ns, name, resourceId, type, 28)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,18 +6,28 @@ import android.app.PendingIntent
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageInstaller.SessionParams
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import com.aliucord.manager.installer.service.InstallService
|
||||
import kotlinx.coroutines.delay
|
||||
import java.io.File
|
||||
|
||||
fun Application.installApks(vararg apks: File) =
|
||||
packageManager.packageInstaller.installApks(this, *apks)
|
||||
fun Application.installApks(silent: Boolean = false, vararg apks: File) {
|
||||
val packageInstaller = packageManager.packageInstaller
|
||||
val params = SessionParams(SessionParams.MODE_FULL_INSTALL).apply {
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
setInstallScenario(PackageManager.INSTALL_SCENARIO_FAST)
|
||||
|
||||
fun PackageInstaller.installApks(application: Application, vararg apks: File) {
|
||||
val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
|
||||
val sessionId = createSession(params)
|
||||
val session = openSession(sessionId)
|
||||
if (silent) {
|
||||
setRequireUserAction(SessionParams.USER_ACTION_NOT_REQUIRED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sessionId = packageInstaller.createSession(params)
|
||||
val session = packageInstaller.openSession(sessionId)
|
||||
|
||||
apks.forEach { apk ->
|
||||
session.openWrite(apk.name, 0, apk.length()).use {
|
||||
|
|
@ -26,13 +36,13 @@ fun PackageInstaller.installApks(application: Application, vararg apks: File) {
|
|||
}
|
||||
}
|
||||
|
||||
val callbackIntent = Intent(application, InstallService::class.java)
|
||||
val callbackIntent = Intent(this, InstallService::class.java)
|
||||
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
val contentIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
PendingIntent.getService(application, 0, callbackIntent, PendingIntent.FLAG_MUTABLE)
|
||||
PendingIntent.getService(this, 0, callbackIntent, PendingIntent.FLAG_MUTABLE)
|
||||
} else {
|
||||
PendingIntent.getService(application, 0, callbackIntent, 0)
|
||||
PendingIntent.getService(this, 0, callbackIntent, 0)
|
||||
}
|
||||
|
||||
session.commit(contentIntent.intentSender)
|
||||
|
|
|
|||
|
|
@ -409,12 +409,29 @@ class InstallViewModel(
|
|||
}
|
||||
|
||||
step(InstallStep.SIGN_APK) {
|
||||
// Align resources.arsc due to targeting api 30 for silent install
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
for (file in apks) {
|
||||
val bytes = ZipReader(file).use {
|
||||
if (it.entryNames.contains("resources.arsc")) {
|
||||
it.openEntry("resources.arsc")?.read()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} ?: continue
|
||||
|
||||
ZipWriter(file, true).use {
|
||||
it.deleteEntry("resources.arsc", true)
|
||||
it.writeEntry("resources.arsc", bytes, ZipCompression.NONE, 4096)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apks.forEach(Signer::signApk)
|
||||
}
|
||||
|
||||
step(InstallStep.INSTALL_APK) {
|
||||
application.packageManager.packageInstaller
|
||||
.installApks(application, *apks)
|
||||
application.installApks(silent = !preferences.devMode, *apks)
|
||||
}
|
||||
|
||||
patchedDir.deleteRecursively()
|
||||
|
|
@ -595,12 +612,27 @@ class InstallViewModel(
|
|||
}
|
||||
|
||||
step(InstallStep.SIGN_APK) {
|
||||
// Align resources.arsc due to targeting api 30 for silent install
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
val bytes = ZipReader(baseApkFile).use {
|
||||
if (it.entryNames.contains("resources.arsc")) {
|
||||
it.openEntry("resources.arsc")?.read()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
ZipWriter(baseApkFile, true).use {
|
||||
it.deleteEntry("resources.arsc", true)
|
||||
it.writeEntry("resources.arsc", bytes, ZipCompression.NONE, 4096)
|
||||
}
|
||||
}
|
||||
|
||||
Signer.signApk(baseApkFile)
|
||||
}
|
||||
|
||||
step(InstallStep.INSTALL_APK) {
|
||||
application.packageManager.packageInstaller
|
||||
.installApks(application, baseApkFile)
|
||||
application.installApks(silent = !preferences.devMode, baseApkFile)
|
||||
}
|
||||
|
||||
patchedDir.deleteRecursively()
|
||||
|
|
|
|||
|
|
@ -41,18 +41,14 @@ class UpdaterViewModel(
|
|||
viewModelScope.launch {
|
||||
isWorking = true
|
||||
|
||||
application.externalCacheDir!!.resolve("manager.apk").apply {
|
||||
delete()
|
||||
application.externalCacheDir!!.resolve("manager.apk").also {
|
||||
it.delete()
|
||||
|
||||
downloadManager.download(url, this)
|
||||
application.installApks(this)
|
||||
delay(10000)
|
||||
downloadManager.download(url, it)
|
||||
application.installApks(silent = true, it)
|
||||
|
||||
showDialog = false
|
||||
delete()
|
||||
it.delete()
|
||||
}
|
||||
|
||||
isWorking = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue