feat: add button for info about obtaining patched APK

This commit is contained in:
rushiiMachine 2025-03-05 16:59:43 -08:00
parent 113e06dcee
commit 9a31d6d624
No known key found for this signature in database
GPG key ID: DCBE5952BB3B6420
11 changed files with 80 additions and 56 deletions

26
INFO.md Normal file
View file

@ -0,0 +1,26 @@
## Obtaining Patched APKs
Unfortunately, starting with Android 10, file managers cannot access external data of other apps without root.
You will have to manually download the patched APK via `adb`.
ADB command (assuming the first user profile):
```shell
$ adb pull /storage/emulated/0/Android/data/com.aliucord.manager/cache/patched/patched.apk
```
This file should only be used after the patching process has successfully completed.
If the process failed at any step before "Installing", then the APK will be unusable.
The patched APK **should not be reused on another device**. Refer to the section [below](#backing-up-aliucord)
for more information.
## Backing up Aliucord
Note: This section is about the app installation itself, not the installed plugins, themes, and settings.
The patched Aliucord APK is tailored to the current device's Android version and CPU architecture.
Reusing a patched Aliucord APK from one device on another will likely break. Backing up and
restoring on another device will likely break.
Install Aliucord **directly via Manager** on the device you wish to use it on.

View file

@ -33,16 +33,6 @@
android:name=".installers.pm.PMIntentReceiver"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
<activity
android:name=".MainActivity"
android:exported="true"

View file

@ -21,9 +21,11 @@ class AliucordGithubService(
suspend fun getManagerReleases() = github.getReleases(ORG, MANAGER_REPO)
suspend fun getContributors() = github.getContributors(ORG, MAIN_REPO)
private companion object {
companion object {
const val ORG = "Aliucord"
const val MAIN_REPO = "Aliucord"
const val MANAGER_REPO = "Manager"
const val PATCHED_APKS_INFO_URL = "https://github.com/$ORG/$MANAGER_REPO/blob/main/INFO.md#obtaining-patched-apks"
}
}

View file

@ -99,7 +99,7 @@ class SmaliPatchStep : Step(), IDexProvider, KoinComponent {
}
val patched = try {
DiffUtils.patch(smaliFile.readText().split('\n'), patch)
DiffUtils.patch(smaliFile.readLines(), patch)
} catch (t: Throwable) {
throw Error("Failed to smali patch $fullClassName", t)
}

View file

@ -1,4 +1,4 @@
package com.aliucord.manager.ui.screens.patching.components
package com.aliucord.manager.ui.components
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*

View file

@ -14,9 +14,10 @@ fun SettingsSwitch(
icon: @Composable () -> Unit = {},
pref: Boolean,
onPrefChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
SettingsItem(
modifier = Modifier.clickable(enabled = !disabled) { onPrefChange(!pref) },
modifier = modifier.clickable(enabled = !disabled) { onPrefChange(!pref) },
text = { Text(text = label, softWrap = true) },
icon = icon,
secondaryText = {

View file

@ -12,11 +12,10 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.*
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@ -36,7 +35,6 @@ import com.aliucord.manager.ui.util.paddings.PaddingValuesSides
import com.aliucord.manager.ui.util.paddings.exclude
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import kotlin.math.*
@Parcelize
class HomeScreen : Screen, Parcelable {

View file

@ -246,24 +246,24 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
icon = painterResource(R.drawable.ic_refresh),
onClick = model::restart,
)
MainActionButton(
text = stringResource(R.string.setting_clear_cache),
icon = painterResource(R.drawable.ic_delete_forever),
enabled = !cacheCleared,
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = MaterialTheme.colorScheme.error,
),
onClick = {
cacheCleared = true
model.clearCache()
},
modifier = Modifier
.padding(top = 14.dp)
.fillMaxWidth()
)
}
}
MainActionButton(
text = stringResource(R.string.setting_clear_cache),
icon = painterResource(R.drawable.ic_delete_forever),
enabled = !cacheCleared,
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = MaterialTheme.colorScheme.error,
),
onClick = {
cacheCleared = true
model.clearCache()
},
modifier = Modifier
.padding(top = 14.dp)
.fillMaxWidth()
)
}
}
}

View file

@ -13,14 +13,16 @@ import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel
import com.aliucord.manager.R
import com.aliucord.manager.network.service.AliucordGithubService
import com.aliucord.manager.ui.components.BackButton
import com.aliucord.manager.ui.components.MainActionButton
import com.aliucord.manager.ui.components.settings.*
import com.aliucord.manager.ui.screens.settings.components.ThemeDialog
import kotlinx.parcelize.IgnoredOnParcel
@ -34,6 +36,7 @@ class SettingsScreen : Screen, Parcelable {
@Composable
override fun Content() {
val model = getScreenModel<SettingsModel>()
var clearedCache by rememberSaveable { mutableStateOf(false) }
Scaffold(
topBar = {
@ -76,10 +79,9 @@ class SettingsScreen : Screen, Parcelable {
label = stringResource(R.string.setting_dynamic_color),
secondaryLabel = stringResource(R.string.setting_dynamic_color_desc),
pref = preferences.dynamicColor,
icon = { Icon(painterResource(R.drawable.ic_palette), null) }
) {
preferences.dynamicColor = it
}
icon = { Icon(painterResource(R.drawable.ic_palette), null) },
onPrefChange = { preferences.dynamicColor = it },
)
}
SettingsHeader(stringResource(R.string.settings_advanced))
@ -88,10 +90,9 @@ class SettingsScreen : Screen, Parcelable {
label = stringResource(R.string.settings_developer_options),
secondaryLabel = stringResource(R.string.settings_developer_options_desc),
pref = preferences.devMode,
icon = { Icon(painterResource(R.drawable.ic_code), null) }
) {
preferences.devMode = it
}
icon = { Icon(painterResource(R.drawable.ic_code), null) },
onPrefChange = { preferences.devMode = it },
)
SettingsSwitch(
label = stringResource(R.string.setting_keep_patched_apks),
@ -99,23 +100,34 @@ class SettingsScreen : Screen, Parcelable {
icon = { Icon(painterResource(R.drawable.ic_delete_forever), null) },
pref = preferences.keepPatchedApks,
onPrefChange = model::setKeepPatchedApks,
modifier = Modifier.padding(bottom = 18.dp),
)
var clearedCache by rememberSaveable { mutableStateOf(false) }
Button(
shape = ShapeDefaults.Large,
MainActionButton(
text = stringResource(R.string.setting_clear_cache),
icon = painterResource(R.drawable.ic_delete_forever),
enabled = !clearedCache,
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = MaterialTheme.colorScheme.error,
),
onClick = {
clearedCache = true
model.clearCacheDir()
},
modifier = Modifier
.padding(horizontal = 18.dp, vertical = 10.dp)
.fillMaxWidth()
.padding(18.dp),
) {
Text(
text = stringResource(R.string.setting_clear_cache),
textAlign = TextAlign.Center
)
if (preferences.keepPatchedApks) {
val handler = LocalUriHandler.current
MainActionButton(
text = stringResource(R.string.setting_see_patched_apks),
icon = painterResource(R.drawable.ic_launch),
onClick = { handler.openUri(AliucordGithubService.PATCHED_APKS_INFO_URL) },
modifier = Modifier
.padding(horizontal = 18.dp, vertical = 9.dp)
.fillMaxWidth()
)
}
}

View file

@ -50,6 +50,7 @@
<string name="setting_keep_patched_apks">Keep patched APKs</string>
<string name="setting_keep_patched_apks_desc">Keep all patched files and APKs after installing for debugging.</string>
<string name="setting_keep_patched_apks_error">This device does not support external cache directories!</string>
<string name="setting_see_patched_apks">See patched APKs</string>
<string name="theme_system">System</string>
<string name="theme_dark">Dark</string>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>