mirror of
https://github.com/topjohnwu/Magisk
synced 2025-10-28 05:40:52 +01:00
Compare commits
44 Commits
canary-290
...
v30.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e81de7ec36 | ||
|
|
c78da1ce24 | ||
|
|
7b2d40987c | ||
|
|
3a37e8c9c5 | ||
|
|
58b405bce1 | ||
|
|
810174ef73 | ||
|
|
690a5ac033 | ||
|
|
89aad31f7e | ||
|
|
7124db98e3 | ||
|
|
0860e859f7 | ||
|
|
04008949b8 | ||
|
|
39f2940bd1 | ||
|
|
1460317ebd | ||
|
|
12340c9bd5 | ||
|
|
c4590fe2ba | ||
|
|
b36066bbcd | ||
|
|
65d1c5827c | ||
|
|
1d675c8b2e | ||
|
|
0b494ed7df | ||
|
|
48d9fc24eb | ||
|
|
83426f7f36 | ||
|
|
0e86d4dbcb | ||
|
|
5e050d7456 | ||
|
|
898580bf90 | ||
|
|
86621a4c46 | ||
|
|
a834e72b71 | ||
|
|
d8cf42af16 | ||
|
|
8c79d66b7b | ||
|
|
fada8b148a | ||
|
|
dc0acea47c | ||
|
|
78d1200608 | ||
|
|
527bbc0368 | ||
|
|
4c89c7e2b3 | ||
|
|
adbea7e313 | ||
|
|
76962f965e | ||
|
|
a4b8c5e46b | ||
|
|
83c707439c | ||
|
|
25dd6121f4 | ||
|
|
67f35ad027 | ||
|
|
0c4b8afbc5 | ||
|
|
34b30d7ce1 | ||
|
|
2215088973 | ||
|
|
8b7fb6cdde | ||
|
|
94c7dbedf2 |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@@ -70,7 +70,7 @@ runs:
|
||||
.gradle/caches
|
||||
.gradle/wrapper
|
||||
!.gradle/caches/build-cache-*
|
||||
key: gradle-cache-${{ hashFiles('gradle/**') }}
|
||||
key: gradle-cache-${{ hashFiles('app/gradle/**') }}
|
||||
restore-keys: gradle-cache-
|
||||
|
||||
- name: Restore Gradle dependencies
|
||||
|
||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
env:
|
||||
AVD_TEST_LOG: 1
|
||||
run: scripts/avd_test.sh ${{ matrix.version }} ${{ matrix.type }}
|
||||
run: scripts/avd.sh test ${{ matrix.version }} ${{ matrix.type }}
|
||||
|
||||
- name: Upload logs on error
|
||||
if: ${{ failure() }}
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
env:
|
||||
FORCE_32_BIT: 1
|
||||
AVD_TEST_LOG: 1
|
||||
run: scripts/avd_test.sh ${{ matrix.version }}
|
||||
run: scripts/avd.sh test ${{ matrix.version }}
|
||||
|
||||
- name: Upload logs on error
|
||||
if: ${{ failure() }}
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,9 +10,6 @@
|
||||
[submodule "libcxx"]
|
||||
path = native/src/external/libcxx
|
||||
url = https://github.com/topjohnwu/libcxx.git
|
||||
[submodule "zopfli"]
|
||||
path = native/src/external/zopfli
|
||||
url = https://github.com/google/zopfli.git
|
||||
[submodule "cxx-rs"]
|
||||
path = native/src/external/cxx-rs
|
||||
url = https://github.com/topjohnwu/cxx.git
|
||||
|
||||
@@ -16,13 +16,7 @@ Some highlight features:
|
||||
|
||||
## Downloads
|
||||
|
||||
[Github](https://github.com/topjohnwu/Magisk/) is the only source where you can get official Magisk information and downloads.
|
||||
|
||||
Click the icon below to download Magisk apk.
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v28.1)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v29.0)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/canary-29001)
|
||||
[Github](https://github.com/topjohnwu/Magisk/releases) is the only source where you can get official Magisk information and downloads.
|
||||
|
||||
## Useful Links
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.dialog
|
||||
import com.topjohnwu.magisk.core.AppContext
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.R
|
||||
import com.topjohnwu.magisk.core.di.ServiceLocator
|
||||
import com.topjohnwu.magisk.core.download.DownloadEngine
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
@@ -11,15 +10,10 @@ import java.io.File
|
||||
|
||||
class ManagerInstallDialog : MarkDownDialog() {
|
||||
|
||||
private val svc get() = ServiceLocator.networkService
|
||||
|
||||
override suspend fun getMarkdownText(): String {
|
||||
val text = svc.fetchString(Info.remote.magisk.note)
|
||||
val text = Info.update.note
|
||||
// Cache the changelog
|
||||
AppContext.cacheDir.listFiles { _, name -> name.endsWith(".md") }.orEmpty().forEach {
|
||||
it.delete()
|
||||
}
|
||||
File(AppContext.cacheDir, "${Info.remote.magisk.versionCode}.md").writeText(text)
|
||||
File(AppContext.cacheDir, "${Info.update.versionCode}.md").writeText(text)
|
||||
return text
|
||||
}
|
||||
|
||||
|
||||
@@ -91,16 +91,15 @@ class HomeViewModel(
|
||||
|
||||
override suspend fun doLoadWork() {
|
||||
appState = State.LOADING
|
||||
Info.getRemote(svc)?.apply {
|
||||
Info.fetchUpdate(svc)?.apply {
|
||||
appState = when {
|
||||
BuildConfig.APP_VERSION_CODE < magisk.versionCode -> State.OUTDATED
|
||||
BuildConfig.APP_VERSION_CODE < versionCode -> State.OUTDATED
|
||||
else -> State.UP_TO_DATE
|
||||
}
|
||||
|
||||
val isDebug = Config.updateChannel == Config.Value.DEBUG_CHANNEL
|
||||
managerRemoteVersion =
|
||||
("${magisk.version} (${magisk.versionCode})" +
|
||||
if (isDebug) " (D)" else "").asText()
|
||||
("$version (${versionCode})" + if (isDebug) " (D)" else "").asText()
|
||||
} ?: run {
|
||||
appState = State.INVALID
|
||||
managerRemoteVersion = CoreR.string.not_available.asText()
|
||||
|
||||
@@ -14,9 +14,8 @@ import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||
import com.topjohnwu.magisk.core.AppContext
|
||||
import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.BuildConfig.APP_VERSION_CODE
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.base.ContentResultCallback
|
||||
import com.topjohnwu.magisk.core.ktx.toast
|
||||
@@ -70,17 +69,16 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val file = File(AppContext.cacheDir, "${BuildConfig.APP_VERSION_CODE}.md")
|
||||
val text = when {
|
||||
file.exists() -> file.readText()
|
||||
Const.Url.CHANGELOG_URL.isEmpty() -> ""
|
||||
val noteFile = File(AppContext.cacheDir, "${APP_VERSION_CODE}.md")
|
||||
val noteText = when {
|
||||
noteFile.exists() -> noteFile.readText()
|
||||
else -> {
|
||||
val str = svc.fetchString(Const.Url.CHANGELOG_URL)
|
||||
file.writeText(str)
|
||||
str
|
||||
val note = svc.fetchUpdate(APP_VERSION_CODE).note
|
||||
noteFile.writeText(note)
|
||||
note
|
||||
}
|
||||
}
|
||||
val spanned = markwon.toMarkdown(text)
|
||||
val spanned = markwon.toMarkdown(noteText)
|
||||
withContext(Dispatchers.Main) {
|
||||
notes = spanned
|
||||
}
|
||||
@@ -100,13 +98,15 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
||||
}
|
||||
|
||||
override fun onSaveState(state: Bundle) {
|
||||
state.putParcelable(INSTALL_STATE_KEY, InstallState(
|
||||
methodId,
|
||||
step,
|
||||
Config.keepVerity,
|
||||
Config.keepEnc,
|
||||
Config.recovery
|
||||
))
|
||||
state.putParcelable(
|
||||
INSTALL_STATE_KEY, InstallState(
|
||||
methodId,
|
||||
step,
|
||||
Config.keepVerity,
|
||||
Config.keepEnc,
|
||||
Config.recovery
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun onRestoreState(state: Bundle) {
|
||||
@@ -124,6 +124,7 @@ class InstallViewModel(svc: NetworkService, markwon: Markwon) : BaseViewModel()
|
||||
override fun onActivityLaunch() {
|
||||
AppContext.toast(CoreR.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
}
|
||||
|
||||
override fun onActivityResult(result: Uri) {
|
||||
uri.value = result
|
||||
}
|
||||
|
||||
@@ -147,19 +147,11 @@ object UpdateChannel : BaseSettingsItem.Selector() {
|
||||
get() = Config.updateChannel
|
||||
set(value) {
|
||||
Config.updateChannel = value
|
||||
Info.remote = Info.EMPTY_REMOTE
|
||||
Info.resetUpdate()
|
||||
}
|
||||
|
||||
override val title = CoreR.string.settings_update_channel_title.asText()
|
||||
|
||||
override val entryRes = CoreR.array.update_channel
|
||||
override fun entries(res: Resources): Array<String> {
|
||||
return super.entries(res).let {
|
||||
if (!Const.APP_IS_CANARY && !BuildConfig.DEBUG)
|
||||
it.copyOfRange(0, Config.Value.CANARY_CHANNEL)
|
||||
else it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object UpdateChannelUrl : BaseSettingsItem.Input() {
|
||||
@@ -169,7 +161,7 @@ object UpdateChannelUrl : BaseSettingsItem.Input() {
|
||||
get() = Config.customChannelUrl
|
||||
set(value) {
|
||||
Config.customChannelUrl = value
|
||||
Info.remote = Info.EMPTY_REMOTE
|
||||
Info.resetUpdate()
|
||||
notifyPropertyChanged(BR.description)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,5 +30,6 @@ dependencies {
|
||||
implementation(libs.ksp.plugin)
|
||||
implementation(libs.navigation.safe.args.plugin)
|
||||
implementation(libs.lsparanoid.plugin)
|
||||
implementation(libs.moshi.plugin)
|
||||
implementation(libs.jgit)
|
||||
}
|
||||
|
||||
77
app/buildSrc/src/main/java/AddCommentTask.kt
Normal file
77
app/buildSrc/src/main/java/AddCommentTask.kt
Normal file
@@ -0,0 +1,77 @@
|
||||
import com.android.build.api.artifact.ArtifactTransformationRequest
|
||||
import com.android.build.api.dsl.ApkSigningConfig
|
||||
import com.android.builder.internal.packaging.IncrementalPackager
|
||||
import com.android.tools.build.apkzlib.sign.SigningExtension
|
||||
import com.android.tools.build.apkzlib.sign.SigningOptions
|
||||
import com.android.tools.build.apkzlib.zfile.ZFiles
|
||||
import com.android.tools.build.apkzlib.zip.ZFileOptions
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.io.File
|
||||
import java.security.KeyStore
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.jar.JarFile
|
||||
|
||||
abstract class AddCommentTask: DefaultTask() {
|
||||
@get:Input
|
||||
abstract val comment: Property<String>
|
||||
|
||||
@get:Input
|
||||
abstract val signingConfig: Property<ApkSigningConfig>
|
||||
|
||||
@get:InputFiles
|
||||
abstract val apkFolder: DirectoryProperty
|
||||
|
||||
@get:OutputDirectory
|
||||
abstract val outFolder: DirectoryProperty
|
||||
|
||||
@get:Internal
|
||||
abstract val transformationRequest: Property<ArtifactTransformationRequest<AddCommentTask>>
|
||||
|
||||
@TaskAction
|
||||
fun taskAction() = transformationRequest.get().submit(this) { artifact ->
|
||||
val inFile = File(artifact.outputFile)
|
||||
val outFile = outFolder.file(inFile.name).get().asFile
|
||||
|
||||
val privateKey = signingConfig.get().getPrivateKey()
|
||||
val signingOptions = SigningOptions.builder()
|
||||
.setMinSdkVersion(0)
|
||||
.setV1SigningEnabled(true)
|
||||
.setV2SigningEnabled(true)
|
||||
.setKey(privateKey.privateKey)
|
||||
.setCertificates(privateKey.certificate as X509Certificate)
|
||||
.setValidation(SigningOptions.Validation.ASSUME_INVALID)
|
||||
.build()
|
||||
val options = ZFileOptions().apply {
|
||||
noTimestamps = true
|
||||
autoSortFiles = true
|
||||
}
|
||||
outFile.parentFile?.mkdirs()
|
||||
inFile.copyTo(outFile, overwrite = true)
|
||||
ZFiles.apk(outFile, options).use {
|
||||
SigningExtension(signingOptions).register(it)
|
||||
it.eocdComment = comment.get().toByteArray()
|
||||
it.get(IncrementalPackager.APP_METADATA_ENTRY_PATH)?.delete()
|
||||
it.get(IncrementalPackager.VERSION_CONTROL_INFO_ENTRY_PATH)?.delete()
|
||||
it.get(JarFile.MANIFEST_NAME)?.delete()
|
||||
}
|
||||
|
||||
outFile
|
||||
}
|
||||
|
||||
private fun ApkSigningConfig.getPrivateKey(): KeyStore.PrivateKeyEntry {
|
||||
val keyStore = KeyStore.getInstance(storeType ?: KeyStore.getDefaultType())
|
||||
storeFile!!.inputStream().use {
|
||||
keyStore.load(it, storePassword!!.toCharArray())
|
||||
}
|
||||
val keyPwdArray = keyPassword!!.toCharArray()
|
||||
val entry = keyStore.getEntry(keyAlias!!, KeyStore.PasswordProtection(keyPwdArray))
|
||||
return entry as KeyStore.PrivateKeyEntry
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,12 @@ import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import java.io.File
|
||||
import java.util.Properties
|
||||
import java.util.Random
|
||||
|
||||
// Set non-zero value here to fix the random seed for reproducible builds
|
||||
// CI builds are always reproducible
|
||||
val RAND_SEED = if (System.getenv("CI") != null) 42 else 0
|
||||
lateinit var RANDOM: Random
|
||||
|
||||
private val props = Properties()
|
||||
private var commitHash = ""
|
||||
@@ -28,7 +34,11 @@ object Config {
|
||||
}
|
||||
}
|
||||
|
||||
val Project.baseDir: File get() = rootProject.file("..")
|
||||
fun Project.rootFile(path: String): File {
|
||||
val file = File(path)
|
||||
return if (file.isAbsolute) file
|
||||
else File(rootProject.file(".."), path)
|
||||
}
|
||||
|
||||
class MagiskPlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) = project.applyPlugin()
|
||||
@@ -38,11 +48,11 @@ class MagiskPlugin : Plugin<Project> {
|
||||
props.clear()
|
||||
rootProject.file("gradle.properties").inputStream().use { props.load(it) }
|
||||
val configPath: String? by this
|
||||
val config = configPath?.let { File(it) } ?: File(baseDir, "config.prop")
|
||||
val config = rootFile(configPath ?: "config.prop")
|
||||
if (config.exists())
|
||||
config.inputStream().use { props.load(it) }
|
||||
|
||||
val repo = FileRepository(File(baseDir, ".git"))
|
||||
val repo = FileRepository(rootFile(".git"))
|
||||
val refId = repo.refDatabase.exactRef("HEAD").objectId
|
||||
commitHash = repo.newObjectReader().abbreviate(refId, 8).name()
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,11 @@
|
||||
import com.android.build.api.artifact.SingleArtifact
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.CacheableTask
|
||||
import org.gradle.api.tasks.Delete
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
@@ -10,22 +13,25 @@ import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.PathSensitive
|
||||
import org.gradle.api.tasks.PathSensitivity
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.kotlin.dsl.assign
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.security.SecureRandom
|
||||
import java.util.Random
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.DeflaterOutputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipFile
|
||||
import java.util.zip.ZipOutputStream
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.CipherOutputStream
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
import kotlin.random.asKotlinRandom
|
||||
|
||||
// Set non-zero value here to fix the random seed for reproducible builds
|
||||
// CI builds are always reproducible
|
||||
val RAND_SEED = if (System.getenv("CI") != null) 42 else 0
|
||||
private lateinit var RANDOM: Random
|
||||
private val kRANDOM get() = RANDOM.asKotlinRandom()
|
||||
|
||||
private val c1 = mutableListOf<String>()
|
||||
@@ -72,7 +78,7 @@ private fun PrintStream.byteField(name: String, bytes: ByteArray) {
|
||||
}
|
||||
|
||||
@CacheableTask
|
||||
abstract class ManifestUpdater: DefaultTask() {
|
||||
private abstract class ManifestUpdater: DefaultTask() {
|
||||
@get:Input
|
||||
abstract val applicationId: Property<String>
|
||||
|
||||
@@ -182,9 +188,7 @@ abstract class ManifestUpdater: DefaultTask() {
|
||||
}
|
||||
|
||||
|
||||
fun genStubClasses(factoryOutDir: File, appOutDir: File) {
|
||||
fun String.ind(level: Int) = replaceIndentByMargin(" ".repeat(level))
|
||||
|
||||
private fun genStubClasses(factoryOutDir: File, appOutDir: File) {
|
||||
val classNameGenerator = sequence {
|
||||
fun notJavaKeyword(name: String) = when (name) {
|
||||
"do", "if", "for", "int", "new", "try" -> false
|
||||
@@ -228,7 +232,7 @@ fun genStubClasses(factoryOutDir: File, appOutDir: File) {
|
||||
genClass("StubApplication", appOutDir)
|
||||
}
|
||||
|
||||
fun genEncryptedResources(res: ByteArray, outDir: File) {
|
||||
private fun genEncryptedResources(res: ByteArray, outDir: File) {
|
||||
val mainPkgDir = File(outDir, "com/topjohnwu/magisk")
|
||||
mainPkgDir.mkdirs()
|
||||
|
||||
@@ -259,3 +263,86 @@ fun genEncryptedResources(res: ByteArray, outDir: File) {
|
||||
it.println("}")
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.setupStubApk() {
|
||||
setupAppCommon()
|
||||
|
||||
androidComponents.onVariants { variant ->
|
||||
val variantName = variant.name
|
||||
val variantCapped = variantName.replaceFirstChar { it.uppercase() }
|
||||
val manifestUpdater =
|
||||
project.tasks.register("${variantName}ManifestProducer", ManifestUpdater::class.java) {
|
||||
dependsOn("generate${variantCapped}ObfuscatedClass")
|
||||
applicationId = variant.applicationId
|
||||
appClassDir.set(layout.buildDirectory.dir("generated/source/app/$variantName"))
|
||||
factoryClassDir.set(layout.buildDirectory.dir("generated/source/factory/$variantName"))
|
||||
}
|
||||
variant.artifacts.use(manifestUpdater)
|
||||
.wiredWithFiles(
|
||||
ManifestUpdater::mergedManifest,
|
||||
ManifestUpdater::outputManifest)
|
||||
.toTransform(SingleArtifact.MERGED_MANIFEST)
|
||||
}
|
||||
|
||||
androidApp.applicationVariants.all {
|
||||
val variantCapped = name.replaceFirstChar { it.uppercase() }
|
||||
val variantLowered = name.lowercase()
|
||||
val outFactoryClassDir = layout.buildDirectory.file("generated/source/factory/${variantLowered}").get().asFile
|
||||
val outAppClassDir = layout.buildDirectory.file("generated/source/app/${variantLowered}").get().asFile
|
||||
val outResDir = layout.buildDirectory.dir("generated/source/res/${variantLowered}").get().asFile
|
||||
val aapt = File(androidApp.sdkDirectory, "build-tools/${androidApp.buildToolsVersion}/aapt2")
|
||||
val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
|
||||
"${variantLowered}/process${variantCapped}Resources/linked-resources-binary-format-${variantLowered}.ap_").get().asFile
|
||||
|
||||
val genManifestTask = tasks.register("generate${variantCapped}ObfuscatedClass") {
|
||||
inputs.property("seed", RAND_SEED)
|
||||
outputs.dirs(outFactoryClassDir, outAppClassDir)
|
||||
doLast {
|
||||
outFactoryClassDir.mkdirs()
|
||||
outAppClassDir.mkdirs()
|
||||
genStubClasses(outFactoryClassDir, outAppClassDir)
|
||||
}
|
||||
}
|
||||
registerJavaGeneratingTask(genManifestTask, outFactoryClassDir, outAppClassDir)
|
||||
|
||||
val processResourcesTask = tasks.named("process${variantCapped}Resources") {
|
||||
outputs.dir(outResDir)
|
||||
doLast {
|
||||
val apkTmp = File("${apk}.tmp")
|
||||
exec {
|
||||
commandLine(aapt, "optimize", "-o", apkTmp, "--collapse-resource-names", apk)
|
||||
}
|
||||
|
||||
val bos = ByteArrayOutputStream()
|
||||
ZipFile(apkTmp).use { src ->
|
||||
ZipOutputStream(apk.outputStream()).use {
|
||||
it.setLevel(Deflater.BEST_COMPRESSION)
|
||||
it.putNextEntry(ZipEntry("AndroidManifest.xml"))
|
||||
src.getInputStream(src.getEntry("AndroidManifest.xml")).transferTo(it)
|
||||
it.closeEntry()
|
||||
}
|
||||
DeflaterOutputStream(bos, Deflater(Deflater.BEST_COMPRESSION)).use {
|
||||
src.getInputStream(src.getEntry("resources.arsc")).transferTo(it)
|
||||
}
|
||||
}
|
||||
apkTmp.delete()
|
||||
genEncryptedResources(bos.toByteArray(), outResDir)
|
||||
}
|
||||
}
|
||||
|
||||
registerJavaGeneratingTask(processResourcesTask, outResDir)
|
||||
}
|
||||
// Override optimizeReleaseResources task
|
||||
val apk = layout.buildDirectory.file("intermediates/linked_resources_binary_format/" +
|
||||
"release/processReleaseResources/linked-resources-binary-format-release.ap_").get().asFile
|
||||
val optRes = layout.buildDirectory.file("intermediates/optimized_processed_res/" +
|
||||
"release/optimizeReleaseResources/resources-release-optimize.ap_").get().asFile
|
||||
afterEvaluate {
|
||||
tasks.named("optimizeReleaseResources") {
|
||||
doLast { apk.copyTo(optRes, true) }
|
||||
}
|
||||
}
|
||||
tasks.named<Delete>("clean") {
|
||||
delete.addAll(listOf("src/debug/AndroidManifest.xml", "src/release/AndroidManifest.xml"))
|
||||
}
|
||||
}
|
||||
5
app/core/.gitignore
vendored
5
app/core/.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
/build
|
||||
src/*/assets
|
||||
src/*/jniLibs
|
||||
src/*/resources
|
||||
src/debug
|
||||
src/release
|
||||
|
||||
@@ -2,6 +2,7 @@ plugins {
|
||||
id("com.android.library")
|
||||
kotlin("android")
|
||||
kotlin("plugin.parcelize")
|
||||
id("dev.zacsweers.moshix")
|
||||
id("com.google.devtools.ksp")
|
||||
}
|
||||
|
||||
@@ -48,9 +49,6 @@ dependencies {
|
||||
implementation(libs.okhttp.logging)
|
||||
implementation(libs.okhttp.dnsoverhttps)
|
||||
|
||||
implementation(libs.moshi)
|
||||
ksp(libs.moshi.codegen)
|
||||
|
||||
implementation(libs.room.runtime)
|
||||
implementation(libs.room.ktx)
|
||||
ksp(libs.room.compiler)
|
||||
|
||||
@@ -33,7 +33,7 @@ object Config : PreferenceConfig, DBConfig {
|
||||
const val SU_REAUTH = "su_reauth"
|
||||
const val SU_TAPJACK = "su_tapjack"
|
||||
const val CHECK_UPDATES = "check_update"
|
||||
const val UPDATE_CHANNEL = "update_channel"
|
||||
const val RELEASE_CHANNEL = "release_channel"
|
||||
const val CUSTOM_CHANNEL = "custom_channel"
|
||||
const val LOCALE = "locale"
|
||||
const val DARK_THEME = "dark_theme_extended"
|
||||
@@ -48,7 +48,7 @@ object Config : PreferenceConfig, DBConfig {
|
||||
SU_AUTO_RESPONSE, SU_REAUTH, SU_TAPJACK)
|
||||
}
|
||||
|
||||
object Value {
|
||||
object OldValue {
|
||||
// Update channels
|
||||
const val DEFAULT_CHANNEL = -1
|
||||
const val STABLE_CHANNEL = 0
|
||||
@@ -56,6 +56,15 @@ object Config : PreferenceConfig, DBConfig {
|
||||
const val CUSTOM_CHANNEL = 2
|
||||
const val CANARY_CHANNEL = 3
|
||||
const val DEBUG_CHANNEL = 4
|
||||
}
|
||||
|
||||
object Value {
|
||||
// Update channels
|
||||
const val DEFAULT_CHANNEL = -1
|
||||
const val STABLE_CHANNEL = 0
|
||||
const val BETA_CHANNEL = 1
|
||||
const val DEBUG_CHANNEL = 2
|
||||
const val CUSTOM_CHANNEL = 3
|
||||
|
||||
// root access mode
|
||||
const val ROOT_ACCESS_DISABLED = 0
|
||||
@@ -86,14 +95,6 @@ object Config : PreferenceConfig, DBConfig {
|
||||
val TIMEOUT_LIST = longArrayOf(0, -1, 10, 20, 30, 60)
|
||||
}
|
||||
|
||||
private val defaultChannel =
|
||||
if (BuildConfig.DEBUG)
|
||||
Value.DEBUG_CHANNEL
|
||||
else if (Const.APP_IS_CANARY)
|
||||
Value.CANARY_CHANNEL
|
||||
else
|
||||
Value.DEFAULT_CHANNEL
|
||||
|
||||
@JvmField var keepVerity = false
|
||||
@JvmField var keepEnc = false
|
||||
@JvmField var recovery = false
|
||||
@@ -109,7 +110,7 @@ object Config : PreferenceConfig, DBConfig {
|
||||
private var checkUpdatePrefs by preference(Key.CHECK_UPDATES, true)
|
||||
private var localePrefs by preference(Key.LOCALE, "")
|
||||
var doh by preference(Key.DOH, false)
|
||||
var updateChannel by preferenceStrInt(Key.UPDATE_CHANNEL, defaultChannel)
|
||||
var updateChannel by preference(Key.RELEASE_CHANNEL, Value.DEFAULT_CHANNEL)
|
||||
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
||||
var downloadDir by preference(Key.DOWNLOAD_DIR, "")
|
||||
var randName by preference(Key.RAND_NAME, true)
|
||||
@@ -148,6 +149,7 @@ object Config : PreferenceConfig, DBConfig {
|
||||
var suTapjack by preference(Key.SU_TAPJACK, true)
|
||||
|
||||
private const val SU_FINGERPRINT = "su_fingerprint"
|
||||
private const val UPDATE_CHANNEL = "update_channel"
|
||||
|
||||
fun toBundle(): Bundle {
|
||||
val map = prefs.all - Key.NO_MIGRATION
|
||||
@@ -183,17 +185,23 @@ object Config : PreferenceConfig, DBConfig {
|
||||
}
|
||||
|
||||
prefs.edit {
|
||||
// Settings migration
|
||||
// Migrate su_fingerprint
|
||||
if (prefs.getBoolean(SU_FINGERPRINT, false))
|
||||
suBiometric = true
|
||||
remove(SU_FINGERPRINT)
|
||||
prefs.getString(Key.UPDATE_CHANNEL, null).also {
|
||||
if (it == null ||
|
||||
it.toInt() > Value.DEBUG_CHANNEL ||
|
||||
it.toInt() < Value.DEFAULT_CHANNEL) {
|
||||
putString(Key.UPDATE_CHANNEL, defaultChannel.toString())
|
||||
|
||||
// Migrate update_channel
|
||||
prefs.getString(UPDATE_CHANNEL, null)?.let {
|
||||
val channel = when (it.toInt()) {
|
||||
OldValue.STABLE_CHANNEL -> Value.STABLE_CHANNEL
|
||||
OldValue.CANARY_CHANNEL, OldValue.BETA_CHANNEL -> Value.BETA_CHANNEL
|
||||
OldValue.DEBUG_CHANNEL -> Value.DEBUG_CHANNEL
|
||||
OldValue.CUSTOM_CHANNEL -> Value.CUSTOM_CHANNEL
|
||||
else -> Value.DEFAULT_CHANNEL
|
||||
}
|
||||
putInt(Key.RELEASE_CHANNEL, channel)
|
||||
}
|
||||
remove(UPDATE_CHANNEL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.topjohnwu.magisk.core
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import com.topjohnwu.magisk.core.BuildConfig.APP_VERSION_CODE
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object Const {
|
||||
@@ -20,18 +21,14 @@ object Const {
|
||||
|
||||
// Misc
|
||||
val USER_ID = Process.myUid() / 100000
|
||||
val APP_IS_CANARY get() = Version.isCanary(BuildConfig.APP_VERSION_CODE)
|
||||
|
||||
object Version {
|
||||
const val MIN_VERSION = "v22.0"
|
||||
const val MIN_VERCODE = 22000
|
||||
|
||||
fun atLeast_24_0() = Info.env.versionCode >= 24000 || isCanary()
|
||||
fun atLeast_25_0() = Info.env.versionCode >= 25000 || isCanary()
|
||||
fun atLeast_28_0() = Info.env.versionCode >= 28000 || isCanary()
|
||||
fun isCanary() = isCanary(Info.env.versionCode)
|
||||
|
||||
fun isCanary(ver: Int) = ver > 0 && ver % 100 != 0
|
||||
fun atLeast_24_0() = Info.env.versionCode >= 24000
|
||||
fun atLeast_25_0() = Info.env.versionCode >= 25000
|
||||
fun atLeast_28_0() = Info.env.versionCode >= 28000
|
||||
}
|
||||
|
||||
object ID {
|
||||
@@ -43,13 +40,9 @@ object Const {
|
||||
const val PATREON_URL = "https://www.patreon.com/topjohnwu"
|
||||
const val SOURCE_CODE_URL = "https://github.com/topjohnwu/Magisk"
|
||||
|
||||
val CHANGELOG_URL = if (APP_IS_CANARY) Info.remote.magisk.note
|
||||
else "https://topjohnwu.github.io/Magisk/releases/${BuildConfig.APP_VERSION_CODE}.md"
|
||||
|
||||
const val GITHUB_RAW_URL = "https://raw.githubusercontent.com/"
|
||||
const val GITHUB_API_URL = "https://api.github.com/"
|
||||
const val GITHUB_PAGE_URL = "https://topjohnwu.github.io/magisk-files/"
|
||||
const val JS_DELIVR_URL = "https://cdn.jsdelivr.net/gh/"
|
||||
const val INVALID_URL = "https://example.com/"
|
||||
}
|
||||
|
||||
object Key {
|
||||
|
||||
@@ -19,12 +19,18 @@ object Info {
|
||||
|
||||
var stub: StubApk.Data? = null
|
||||
|
||||
val EMPTY_REMOTE = UpdateInfo()
|
||||
var remote = EMPTY_REMOTE
|
||||
suspend fun getRemote(svc: NetworkService): UpdateInfo? {
|
||||
return if (remote === EMPTY_REMOTE) {
|
||||
svc.fetchUpdate()?.apply { remote = this }
|
||||
} else remote
|
||||
private val EMPTY_UPDATE = UpdateInfo()
|
||||
var update = EMPTY_UPDATE
|
||||
private set
|
||||
|
||||
suspend fun fetchUpdate(svc: NetworkService): UpdateInfo? {
|
||||
return if (update === EMPTY_UPDATE) {
|
||||
svc.fetchUpdate()?.apply { update = this }
|
||||
} else update
|
||||
}
|
||||
|
||||
fun resetUpdate() {
|
||||
update = EMPTY_UPDATE
|
||||
}
|
||||
|
||||
var isRooted = false
|
||||
|
||||
@@ -75,9 +75,8 @@ class JobService : BaseJobService() {
|
||||
|
||||
private fun checkUpdate(params: JobParameters): Boolean {
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
ServiceLocator.networkService.fetchUpdate()?.let {
|
||||
Info.remote = it
|
||||
if (Info.env.isActive && BuildConfig.APP_VERSION_CODE < it.magisk.versionCode)
|
||||
Info.fetchUpdate(ServiceLocator.networkService)?.let {
|
||||
if (Info.env.isActive && BuildConfig.APP_VERSION_CODE < it.versionCode)
|
||||
Notifications.updateAvailable()
|
||||
jobFinished(params, false)
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.data
|
||||
|
||||
import com.topjohnwu.magisk.core.model.BranchInfo
|
||||
import com.topjohnwu.magisk.core.model.ModuleJson
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
|
||||
private const val BRANCH = "branch"
|
||||
private const val REPO = "repo"
|
||||
private const val FILE = "file"
|
||||
|
||||
interface GithubPageServices {
|
||||
|
||||
@GET
|
||||
suspend fun fetchUpdateJSON(@Url file: String): UpdateInfo
|
||||
}
|
||||
|
||||
interface RawServices {
|
||||
|
||||
@GET
|
||||
@Streaming
|
||||
suspend fun fetchFile(@Url url: String): ResponseBody
|
||||
|
||||
@GET
|
||||
suspend fun fetchString(@Url url: String): String
|
||||
|
||||
@GET
|
||||
suspend fun fetchModuleJson(@Url url: String): ModuleJson
|
||||
|
||||
}
|
||||
|
||||
interface GithubApiServices {
|
||||
|
||||
@GET("repos/{$REPO}/branches/{$BRANCH}")
|
||||
@Headers("Accept: application/vnd.github.v3+json")
|
||||
suspend fun fetchBranch(
|
||||
@Path(REPO, encoded = true) repo: String,
|
||||
@Path(BRANCH) branch: String
|
||||
): BranchInfo
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.topjohnwu.magisk.core.data
|
||||
|
||||
import com.topjohnwu.magisk.core.model.ModuleJson
|
||||
import com.topjohnwu.magisk.core.model.Release
|
||||
import com.topjohnwu.magisk.core.model.UpdateJson
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Headers
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
import retrofit2.http.Streaming
|
||||
import retrofit2.http.Url
|
||||
|
||||
interface RawUrl {
|
||||
|
||||
@GET
|
||||
@Streaming
|
||||
suspend fun fetchFile(@Url url: String): ResponseBody
|
||||
|
||||
@GET
|
||||
suspend fun fetchString(@Url url: String): String
|
||||
|
||||
@GET
|
||||
suspend fun fetchModuleJson(@Url url: String): ModuleJson
|
||||
|
||||
@GET
|
||||
suspend fun fetchUpdateJson(@Url url: String): UpdateJson
|
||||
}
|
||||
|
||||
interface GithubApiServices {
|
||||
|
||||
@GET("/repos/{owner}/{repo}/releases")
|
||||
@Headers("Accept: application/vnd.github+json")
|
||||
suspend fun fetchReleases(
|
||||
@Path("owner") owner: String = "topjohnwu",
|
||||
@Path("repo") repo: String = "Magisk",
|
||||
@Query("per_page") per: Int = 10,
|
||||
@Query("page") page: Int = 1,
|
||||
): Response<MutableList<Release>>
|
||||
|
||||
@GET("/repos/{owner}/{repo}/releases/latest")
|
||||
@Headers("Accept: application/vnd.github+json")
|
||||
suspend fun fetchLatestRelease(
|
||||
@Path("owner") owner: String = "topjohnwu",
|
||||
@Path("repo") repo: String = "Magisk",
|
||||
): Release
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.squareup.moshi.Moshi
|
||||
import com.topjohnwu.magisk.ProviderInstaller
|
||||
import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.model.DateTimeAdapter
|
||||
import com.topjohnwu.magisk.core.utils.LocaleSetting
|
||||
import okhttp3.Cache
|
||||
import okhttp3.ConnectionSpec
|
||||
@@ -77,7 +78,7 @@ fun createOkHttpClient(context: Context): OkHttpClient {
|
||||
}
|
||||
|
||||
fun createMoshiConverterFactory(): MoshiConverterFactory {
|
||||
val moshi = Moshi.Builder().build()
|
||||
val moshi = Moshi.Builder().add(DateTimeAdapter()).build()
|
||||
return MoshiConverterFactory.create(moshi)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ object ServiceLocator {
|
||||
val markwon by lazy { createMarkwon(AppContext) }
|
||||
val networkService by lazy {
|
||||
NetworkService(
|
||||
createApiService(retrofit, Const.Url.GITHUB_PAGE_URL),
|
||||
createApiService(retrofit, Const.Url.GITHUB_RAW_URL),
|
||||
createApiService(retrofit, Const.Url.INVALID_URL),
|
||||
createApiService(retrofit, Const.Url.GITHUB_API_URL),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import androidx.core.net.toUri
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
@@ -38,7 +38,7 @@ abstract class Subject : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
class App(
|
||||
private val json: MagiskJson = Info.remote.magisk,
|
||||
private val json: UpdateInfo = Info.update,
|
||||
override val notifyId: Int = Notifications.nextId()
|
||||
) : Subject() {
|
||||
override val title: String get() = "Magisk-${json.version}(${json.versionCode})"
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package com.topjohnwu.magisk.core.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.Json
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.squareup.moshi.JsonQualifier
|
||||
import com.squareup.moshi.ToJson
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class UpdateInfo(
|
||||
val magisk: MagiskJson = MagiskJson(),
|
||||
class UpdateJson(
|
||||
val magisk: UpdateInfo = UpdateInfo(),
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MagiskJson(
|
||||
data class UpdateInfo(
|
||||
val version: String = "",
|
||||
val versionCode: Int = -1,
|
||||
val link: String = "",
|
||||
@@ -27,11 +33,37 @@ data class ModuleJson(
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CommitInfo(
|
||||
val sha: String
|
||||
data class ReleaseAssets(
|
||||
val name: String,
|
||||
@Json(name = "browser_download_url") val url: String,
|
||||
)
|
||||
|
||||
class DateTimeAdapter {
|
||||
@ToJson
|
||||
fun toJson(date: LocalDateTime): String {
|
||||
return date.toString()
|
||||
}
|
||||
|
||||
@FromJson
|
||||
fun fromJson(date: String): LocalDateTime {
|
||||
return LocalDateTime.parse(date, ISO_OFFSET_DATE_TIME)
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class BranchInfo(
|
||||
val commit: CommitInfo
|
||||
)
|
||||
data class Release(
|
||||
@Json(name = "tag_name") val tag: String,
|
||||
val name: String,
|
||||
val prerelease: Boolean,
|
||||
val assets: List<ReleaseAssets>,
|
||||
val body: String,
|
||||
@Json(name = "created_at") val createdTime: LocalDateTime,
|
||||
) {
|
||||
val versionCode: Int get() {
|
||||
return if (tag[0] == 'v') {
|
||||
(tag.drop(1).toFloat() * 1000).toInt()
|
||||
} else {
|
||||
tag.drop(7).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,112 @@
|
||||
package com.topjohnwu.magisk.core.repository
|
||||
|
||||
import com.topjohnwu.magisk.core.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Config.Value.BETA_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.CANARY_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.CUSTOM_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.DEBUG_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.DEFAULT_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.data.GithubPageServices
|
||||
import com.topjohnwu.magisk.core.data.RawServices
|
||||
import com.topjohnwu.magisk.core.data.GithubApiServices
|
||||
import com.topjohnwu.magisk.core.data.RawUrl
|
||||
import com.topjohnwu.magisk.core.model.Release
|
||||
import com.topjohnwu.magisk.core.model.ReleaseAssets
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
class NetworkService(
|
||||
private val pages: GithubPageServices,
|
||||
private val raw: RawServices
|
||||
private val raw: RawUrl,
|
||||
private val api: GithubApiServices,
|
||||
) {
|
||||
suspend fun fetchUpdate() = safe {
|
||||
var info = when (Config.updateChannel) {
|
||||
DEFAULT_CHANNEL, STABLE_CHANNEL -> fetchStableUpdate()
|
||||
DEFAULT_CHANNEL -> if (BuildConfig.DEBUG) fetchDebugUpdate() else fetchStableUpdate()
|
||||
STABLE_CHANNEL -> fetchStableUpdate()
|
||||
BETA_CHANNEL -> fetchBetaUpdate()
|
||||
CANARY_CHANNEL -> fetchCanaryUpdate()
|
||||
DEBUG_CHANNEL -> fetchDebugUpdate()
|
||||
CUSTOM_CHANNEL -> fetchCustomUpdate(Config.customChannelUrl)
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
if (info.magisk.versionCode < Info.env.versionCode &&
|
||||
Config.updateChannel == DEFAULT_CHANNEL) {
|
||||
if (info.versionCode < Info.env.versionCode &&
|
||||
Config.updateChannel == DEFAULT_CHANNEL &&
|
||||
!BuildConfig.DEBUG
|
||||
) {
|
||||
Config.updateChannel = BETA_CHANNEL
|
||||
info = fetchBetaUpdate()
|
||||
}
|
||||
info
|
||||
}
|
||||
|
||||
// UpdateInfo
|
||||
private suspend fun fetchStableUpdate() = pages.fetchUpdateJSON("stable.json")
|
||||
private suspend fun fetchBetaUpdate() = pages.fetchUpdateJSON("beta.json")
|
||||
private suspend fun fetchCanaryUpdate() = pages.fetchUpdateJSON("canary.json")
|
||||
private suspend fun fetchDebugUpdate() = pages.fetchUpdateJSON("debug.json")
|
||||
private suspend fun fetchCustomUpdate(url: String) = pages.fetchUpdateJSON(url)
|
||||
suspend fun fetchUpdate(version: Int) = findRelease { it.versionCode == version }.asInfo()
|
||||
|
||||
// Keep going through all release pages until we find a match
|
||||
private suspend inline fun findRelease(predicate: (Release) -> Boolean): Release? {
|
||||
var page = 1
|
||||
while (true) {
|
||||
val response = api.fetchReleases(page = page)
|
||||
val releases = response.body() ?: throw HttpException(response)
|
||||
// Remove all non Magisk releases
|
||||
releases.removeAll { it.tag[0] != 'v' && !it.tag.startsWith("canary") }
|
||||
// Make sure it's sorted correctly
|
||||
releases.sortByDescending { it.createdTime }
|
||||
releases.find(predicate)?.let { return it }
|
||||
if (response.headers()["link"]?.contains("rel=\"next\"", ignoreCase = true) == true) {
|
||||
page += 1
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun Release?.asInfo(
|
||||
selector: (ReleaseAssets) -> Boolean = {
|
||||
// Default selector picks the non-debug APK
|
||||
it.name.run { endsWith(".apk") && !contains("debug") }
|
||||
}): UpdateInfo {
|
||||
return if (this == null) UpdateInfo()
|
||||
else if (tag[0] == 'v') asPublicInfo(selector)
|
||||
else asCanaryInfo(selector)
|
||||
}
|
||||
|
||||
private inline fun Release.asPublicInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
|
||||
val version = tag.drop(1)
|
||||
val date = createdTime.format(DateTimeFormatter.ofPattern("yyyy.M.d"))
|
||||
return UpdateInfo(
|
||||
version = version,
|
||||
versionCode = versionCode,
|
||||
link = assets.find(selector)!!.url,
|
||||
note = "## $date $name\n\n$body"
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun Release.asCanaryInfo(selector: (ReleaseAssets) -> Boolean): UpdateInfo {
|
||||
return UpdateInfo(
|
||||
version = name.substring(8, 16),
|
||||
versionCode = versionCode,
|
||||
link = assets.find(selector)!!.url,
|
||||
note = "## $name\n\n$body"
|
||||
)
|
||||
}
|
||||
|
||||
// Version number: debug == beta >= stable
|
||||
|
||||
// Find the latest non-prerelease
|
||||
private suspend fun fetchStableUpdate() = api.fetchLatestRelease().asInfo()
|
||||
|
||||
// Find the latest release, regardless whether it's prerelease
|
||||
private suspend fun fetchBetaUpdate() = findRelease { true }.asInfo()
|
||||
|
||||
private suspend fun fetchDebugUpdate() =
|
||||
findRelease { true }.asInfo { it.name == "app-debug.apk" }
|
||||
|
||||
private suspend fun fetchCustomUpdate(url: String): UpdateInfo {
|
||||
val info = raw.fetchUpdateJson(url).magisk
|
||||
return info.let { it.copy(note = raw.fetchString(it.note)) }
|
||||
}
|
||||
|
||||
private inline fun <T> safe(factory: () -> T): T? {
|
||||
return try {
|
||||
|
||||
@@ -62,7 +62,7 @@ class NetworkObserver(context: Context) {
|
||||
}
|
||||
|
||||
private fun postValue(b: Boolean) {
|
||||
Info.remote = Info.EMPTY_REMOTE
|
||||
Info.resetUpdate()
|
||||
Info.isConnected.postValue(b)
|
||||
}
|
||||
|
||||
|
||||
252
app/core/src/main/res/values-b+sr+Latn/strings.xml
Normal file
252
app/core/src/main/res/values-b+sr+Latn/strings.xml
Normal file
@@ -0,0 +1,252 @@
|
||||
<resources>
|
||||
<!--Author: Radoš Milićev (https://github.com/rammba)-->
|
||||
|
||||
<!--Sections-->
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="superuser">Super-korisnik</string>
|
||||
<string name="logs">Logovi</string>
|
||||
<string name="settings">Podešavanja</string>
|
||||
<string name="install">Instalacija</string>
|
||||
<string name="section_home">Početno</string>
|
||||
<string name="section_theme">Teme</string>
|
||||
<string name="denylist">Lista zabrana</string>
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">Nedostupna konekcija</string>
|
||||
<string name="app_changelog">Promene u aplikaciji</string>
|
||||
<string name="loading">Učitavanje…</string>
|
||||
<string name="update">Ažuriranje</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Sakrij</string>
|
||||
<string name="home_package">Paket</string>
|
||||
<string name="home_app_title">Apl.</string>
|
||||
|
||||
<string name="home_notice_content">Preuzmite Magisk SAMO sa zvanične GitHub stranice. Fajlovi iz nepoznatih izvora mogu biti maliciozni!</string>
|
||||
<string name="home_support_title">Podržite nas</string>
|
||||
<string name="home_follow_title">Zapratite nas</string>
|
||||
<string name="home_item_source">Izvor</string>
|
||||
<string name="home_support_content">Magisk jeste i uvek će biti besplatan i open source. Možete pokazati da vam je stalo svojom donacijom.</string>
|
||||
<string name="home_installed_version">Instalirano</string>
|
||||
<string name="home_latest_version">Najnovije</string>
|
||||
<string name="invalid_update_channel">Nevalidan kanal ažuriranja</string>
|
||||
<string name="uninstall_magisk_title">Deinstaliraj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Svi moduli će biti onemogućeni/uklonjeni!\nKoren će biti uklonjen!\nSvako neenkriptovano interno skladište će upotrebom Magisk-a biti ponovo enkriptovano!</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Zadrži forsiranu enkripciju</string>
|
||||
<string name="keep_dm_verity">Zadrži AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Režim oporavka</string>
|
||||
<string name="install_options_title">Opcije</string>
|
||||
<string name="install_method_title">Metod</string>
|
||||
<string name="install_next">Naredno</string>
|
||||
<string name="install_start">Počnimo</string>
|
||||
<string name="manager_download_install">Pritisni da preuzmeš i instaliraš</string>
|
||||
<string name="direct_install">Direktna instalacija (Preporučeno)</string>
|
||||
<string name="install_inactive_slot">Instalacija na neaktivan slot (Nakon OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Vaš uređaj će biti FORSIRAN da se pokrene na trenutno neaktivnom slotu nakon ponovnog pokretanja!\nKoristite opciju samo kad se OTA završi.\nNastavi?</string>
|
||||
<string name="setup_title">Dodatne postavke</string>
|
||||
<string name="select_patch_file">Izaberite fajl</string>
|
||||
<string name="patch_file_msg">Izaberite sliku (*.img) ili ODIN tarfile (*.tar) ili payload.bin (*.bin)</string>
|
||||
<string name="reboot_delay_toast">Ponovo pokretanje za 5 sekundi…</string>
|
||||
<string name="flash_screen_title">Instalacija</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Super-korisnički zahtev</string>
|
||||
<string name="touch_filtered_warning">Magisk ne može da verifikuje vaš odgovor, jer aplikacija prikriva super-korisnički zahtev</string>
|
||||
<string name="deny">Zabrani</string>
|
||||
<string name="prompt">Zahtev</string>
|
||||
<string name="grant">Dozvoli</string>
|
||||
<string name="su_warning">Pruža potpun pristup vašem uređaju.\nZabranite ako niste sigurni!</string>
|
||||
<string name="forever">Zauvek</string>
|
||||
<string name="once">Jednom</string>
|
||||
<string name="tenmin">10 min</string>
|
||||
<string name="twentymin">20 min</string>
|
||||
<string name="thirtymin">30 min</string>
|
||||
<string name="sixtymin">60 min</string>
|
||||
<string name="su_allow_toast">%1$s je dobio prava na super-korisnika</string>
|
||||
<string name="su_deny_toast">%1$s nije dobio prava na super-korisnika</string>
|
||||
<string name="su_snack_grant">Super-korisnička prava od %1$s su pružena</string>
|
||||
<string name="su_snack_deny">Super-korisnička prava od %1$s su odbijena</string>
|
||||
<string name="su_snack_notif_on">Notifikacije od %1$s su omogućene</string>
|
||||
<string name="su_snack_notif_off">Notifikacije od %1$s su onemogućene</string>
|
||||
<string name="su_snack_log_on">Logovanje za %1$s je omogućeno</string>
|
||||
<string name="su_snack_log_off">Logovanje za %1$s je onemogućeno</string>
|
||||
<string name="su_revoke_title">Opozovi?</string>
|
||||
<string name="su_revoke_msg">Potvrdi da opozoveš prava na super-korisnika od %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Ništa</string>
|
||||
|
||||
<string name="superuser_toggle_notification">Notifikacije</string>
|
||||
<string name="superuser_toggle_revoke">Opozovi</string>
|
||||
<string name="superuser_policy_none">Nijedna aplikacija nije tražila permisije za super-korisnika još uvek.</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Nemate logova, pokušajte koristiti korenske aplikacije više</string>
|
||||
<string name="log_data_magisk_none">Magisk logovi su prazni, to je čudno</string>
|
||||
<string name="menuSaveLog">Sačuvaj log</string>
|
||||
<string name="menuClearLog">Ukloni log</string>
|
||||
<string name="logs_cleared">Log uspešno uklonjen</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Ciljani UID: %1$d</string>
|
||||
<string name="target_pid">Mount ns cinjani PID: %s</string>
|
||||
<string name="selinux_context">SELinux kontekst: %s</string>
|
||||
<string name="supp_group">Dopunska grupa: %s</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">Prikaži sistemske apl.</string>
|
||||
<string name="show_os_app">Prikaži apl. OS-a</string>
|
||||
<string name="hide_filter_hint">Filtriraj po imenu</string>
|
||||
<string name="hide_search">Pretraga</string>
|
||||
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(Bez informacija)</string>
|
||||
<string name="reboot_userspace">Lako ponovo pokretanje</string>
|
||||
<string name="reboot_recovery">Ponovo pokreni za oporavak</string>
|
||||
<string name="reboot_bootloader">Ponovo pokreni za bootloader</string>
|
||||
<string name="reboot_download">Ponovo pokreni za preuzimanje</string>
|
||||
<string name="reboot_edl">Ponovo pokreni za EDL</string>
|
||||
<string name="reboot_safe_mode">Siguran mod</string>
|
||||
<string name="module_version_author">%1$s od %2$s</string>
|
||||
<string name="module_state_remove">Ukloni</string>
|
||||
<string name="module_action">Akcija</string>
|
||||
<string name="module_state_restore">Povrati</string>
|
||||
<string name="module_action_install_external">Instaliraj iz skladišta</string>
|
||||
<string name="update_available">Ažuriranje dostupno</string>
|
||||
<string name="suspend_text_riru">Modul je suspendovan jer je %1$s omogućeno</string>
|
||||
<string name="suspend_text_zygisk">Modul je suspendovan jer %1$s nije omogućeno</string>
|
||||
<string name="zygisk_module_unloaded">Zygisk modul nije učitan zbog nekompatibilnosti</string>
|
||||
<string name="module_empty">Nijedan modul nije instaliran</string>
|
||||
<string name="confirm_install">Instaliraj modul %1$s?</string>
|
||||
<string name="confirm_install_title">Potvrda instalacije</string>
|
||||
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">Tema</string>
|
||||
<string name="settings_dark_mode_message">Izaberite temu koja vam najviše odgovara!</string>
|
||||
<string name="settings_dark_mode_light">Uvek svetlo</string>
|
||||
<string name="settings_dark_mode_system">Prati sistem</string>
|
||||
<string name="settings_dark_mode_dark">Uvek tamno</string>
|
||||
<string name="settings_download_path_title">Putanja za preuzimanje</string>
|
||||
<string name="settings_download_path_message">Fajlovi će biti sačuvani na %1$s</string>
|
||||
<string name="settings_hide_app_title">Sakrij Magisk apl.</string>
|
||||
<string name="settings_hide_app_summary">Instaliraj proxy aplikaciju sa nasumičnim ID-jem paketa i prilagođenom labelom</string>
|
||||
<string name="settings_restore_app_title">Povrati Magisk apl.</string>
|
||||
<string name="settings_restore_app_summary">Otkrij apl. i povrati originalni APK</string>
|
||||
<string name="language">Jezik</string>
|
||||
<string name="system_default">(Podrazumevano sistemski)</string>
|
||||
<string name="settings_check_update_title">Proveri ažuriranja</string>
|
||||
<string name="settings_check_update_summary">Periodično proveri ažuriranja u pozadini</string>
|
||||
<string name="settings_update_channel_title">Kanal ažuriranja</string>
|
||||
<string name="settings_update_stable">Stabilno</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Prilagođeno</string>
|
||||
<string name="settings_update_custom_msg">Unesi prilagođeni URL kanala</string>
|
||||
<string name="settings_zygisk_summary">Pokreni delove Magisk-a u zygote daemon-u</string>
|
||||
<string name="settings_denylist_title">Sprovedi listu zabrana</string>
|
||||
<string name="settings_denylist_summary">Procesi na listi zabrana će povratiti sve Magisk izmene</string>
|
||||
<string name="settings_denylist_config_title">Konfiguriši listu zabrana</string>
|
||||
<string name="settings_denylist_config_summary">Izaberi procese koji će biti na listi zabrana</string>
|
||||
<string name="settings_hosts_title">Bezsistemski domaćini (hosts)</string>
|
||||
<string name="settings_hosts_summary">Podrška bezsistemskih domaćina za aplikacije blokiranja reklama</string>
|
||||
<string name="settings_hosts_toast">Modul bezsistemskih domaćina dodat</string>
|
||||
<string name="settings_app_name_hint">Novo ime</string>
|
||||
<string name="settings_app_name_helper">Apl. će biti spakovana pod ovim imenom</string>
|
||||
<string name="settings_app_name_error">Nevalidan format</string>
|
||||
<string name="settings_su_app_adb">Aplikacije i ADB</string>
|
||||
<string name="settings_su_app">Samo aplikacije</string>
|
||||
<string name="settings_su_adb">Samo ADB</string>
|
||||
<string name="settings_su_disable">Onemogućeno</string>
|
||||
<string name="settings_su_request_10">10 sekundi</string>
|
||||
<string name="settings_su_request_15">15 sekundi</string>
|
||||
<string name="settings_su_request_20">20 sekundi</string>
|
||||
<string name="settings_su_request_30">30 sekundi</string>
|
||||
<string name="settings_su_request_45">45 sekundi</string>
|
||||
<string name="settings_su_request_60">60 sekundi</string>
|
||||
<string name="superuser_access">Pristup super-korisnika</string>
|
||||
<string name="auto_response">Automatski odgovor</string>
|
||||
<string name="request_timeout">Istek zahteva</string>
|
||||
<string name="superuser_notification">Notifikacije super-korisnika</string>
|
||||
<string name="settings_su_reauth_title">Ponovo odobri nakon ažuriranja</string>
|
||||
<string name="settings_su_reauth_summary">Ponovo traži permisije super-korisnika nakon ažuriranja aplikacija</string>
|
||||
<string name="settings_su_tapjack_title">Zaštita od tapjacking-a</string>
|
||||
<string name="settings_su_tapjack_summary">Prompt dijalog super-korisnika neće reagovati dok je prikriven drugim prozorom ili overlay-em</string>
|
||||
<string name="settings_su_auth_title">Autentifikacija korisnika</string>
|
||||
<string name="settings_su_auth_summary">Traži autentifikaciju korisnika tokom zahteva super-korisnika</string>
|
||||
<string name="settings_su_auth_insecure">Nijedan metod autentifikacije nije podešen na uređaju</string>
|
||||
<string name="settings_customization">Prilagođavanje</string>
|
||||
<string name="setting_add_shortcut_summary">Dodaj lepu prečicu na početni ekran u slučaju da se ime i ikonica ne prepoznaju lako nakon skrivanja aplikacije</string>
|
||||
<string name="settings_doh_title">DNS preko HTTPS-a</string>
|
||||
<string name="settings_doh_description">Zaobilazno rešenje DNS trovanja u nekim nacijama</string>
|
||||
<string name="settings_random_name_title">Nasumično ime na izlazu</string>
|
||||
<string name="settings_random_name_description">Nasumično ime izlaznog fajla slika i tar fajlova radi sprečavanja detekcije</string>
|
||||
|
||||
<string name="multiuser_mode">Višekorisnički režim</string>
|
||||
<string name="settings_owner_only">Samo vlasnik uređaja</string>
|
||||
<string name="settings_owner_manage">Određeno od strane vlasnika</string>
|
||||
<string name="settings_user_independent">Nezavisno od korisnika</string>
|
||||
<string name="owner_only_summary">Samo vlasnik ima pristup korenu</string>
|
||||
<string name="owner_manage_summary">Samo vlasnik može da pristupa korenu i da prima zahteve za njega</string>
|
||||
<string name="user_independent_summary">Svaki korisnik ima svoja pravila korena</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mount režim namespace-a</string>
|
||||
<string name="settings_ns_global">Globalni namespace</string>
|
||||
<string name="settings_ns_requester">Nasleđeni namespace</string>
|
||||
<string name="settings_ns_isolate">Izolovani namespace</string>
|
||||
<string name="global_summary">Sve korenske sesije koriste globalni mount namespace</string>
|
||||
<string name="requester_summary">Korenske sesije će naslediti namespace od podnosioca zahteva</string>
|
||||
<string name="isolate_summary">Svaka korenska sesija će imati svoj izolovani namespace</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Ažuriranja Magisk-a</string>
|
||||
<string name="progress_channel">Notifikacije o progresu</string>
|
||||
<string name="updated_channel">Ažuriranje završeno</string>
|
||||
<string name="download_complete">Preuzimanje završeno</string>
|
||||
<string name="download_file_error">Greška pri preuzimanju fajla</string>
|
||||
<string name="magisk_update_title">Ažuriranje Magisk-a dostupno!</string>
|
||||
<string name="updated_title">Magisk je ažuriran</string>
|
||||
<string name="updated_text">Klikni da otvoriš aplikaciju</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Da</string>
|
||||
<string name="no">Ne</string>
|
||||
<string name="repo_install_title">Instaliraj %1$s %2$s(%3$d)</string>
|
||||
<string name="download">Preuzmi</string>
|
||||
<string name="reboot">Ponovo pokreni</string>
|
||||
<string name="close">Zatvori</string>
|
||||
<string name="release_notes">Release notes</string>
|
||||
<string name="flashing">Flešovanje…</string>
|
||||
<string name="running">Pokretanje…</string>
|
||||
<string name="done">Završeno!</string>
|
||||
<string name="done_action">Pokretanje akcije %1$s završeno</string>
|
||||
<string name="failure">Neuspešno!</string>
|
||||
<string name="hide_app_title">Skrivanje Magisk aplikacije…</string>
|
||||
<string name="open_link_failed_toast">Nije pronađena aplikacija za otvaranje linka</string>
|
||||
<string name="complete_uninstall">Kompletna deinstalacija</string>
|
||||
<string name="restore_img">Povrati slike</string>
|
||||
<string name="restore_img_msg">Povratak…</string>
|
||||
<string name="restore_done">Povratak uspešan!</string>
|
||||
<string name="restore_fail">Fabrički bekap ne postoji!</string>
|
||||
<string name="setup_fail">Neuspešna postavka</string>
|
||||
<string name="env_fix_title">Potrebno dodatno podešavanje</string>
|
||||
<string name="env_fix_msg">Vaš uređaj zahteva dodatno podešavanje da bi Magisk radio kako treba. Da li želite nastaviti i pokrenuti ponovo?</string>
|
||||
<string name="env_full_fix_msg">Vaš uređaj zahteva ponovno flešovanje da bi Magisk radio kako treba. Reinstalirajte Magisk kroz aplikaciju, režim oporavka ne može dobiti tačne informacije o uređaju.</string>
|
||||
<string name="setup_msg">Pokretanje podešavanja okruženja…</string>
|
||||
<string name="unsupport_magisk_title">Nepodržana verzija Magisk-a</string>
|
||||
<string name="unsupport_magisk_msg">Ova verzija aplikacije ne podržava Magisk verzije manje od %1$s.\n\nAplikacija će se ponašati kao da Magisk nije instaliran, molimo ažurirajte Magisk što pre.</string>
|
||||
<string name="unsupport_general_title">Nenormalno stanje</string>
|
||||
<string name="unsupport_system_app_msg">Pokretanje aplikacije kao sistemske nije podržano. Molimo postavite aplikaciju da bude korisnička.</string>
|
||||
<string name="unsupport_other_su_msg">Detektovan \"su\" binary koji nije Magisk-ov. Molimo uklonite konkurentno korensko rešenje i/ili reinstalirajte Magisk.</string>
|
||||
<string name="unsupport_external_storage_msg">Magisk je instaliran na eksterno skladište. Molimo pomerite apl. u interno skladište.</string>
|
||||
<string name="unsupport_nonroot_stub_msg">Skrivena Magisk aplikacija ne može nastaviti sa radom jer je koren izgubljen. Molimo povratite originalni APK.</string>
|
||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||
<string name="external_rw_permission_denied">Dozvolite permisiju za skladište da biste omogućili ovu funkcionalnost</string>
|
||||
<string name="post_notifications_denied">Dozvolite permisiju za notifikacije da biste omogućili ovu funkcionalnost</string>
|
||||
<string name="install_unknown_denied">Dozvolite "instaliranje nepoznatih aplikacija" da biste omogućili ovu funkcionalnost</string>
|
||||
<string name="add_shortcut_title">Dodaj prečicu na početni ekran</string>
|
||||
<string name="add_shortcut_msg">Nakon skrivanja aplikacije, njeno ime i ikonicu ćete teško prepoznati. Želite li dodati lepu prečicu na početni ekran?</string>
|
||||
<string name="app_not_found">Nije pronađena aplikacija za ovu akciju</string>
|
||||
<string name="reboot_apply_change">Ponovo pokreni da primeniš izmene</string>
|
||||
<string name="restore_app_confirmation">Ovo će vratiti skrivenu aplikaciju na originalnu. Da li stvarno to želite?</string>
|
||||
|
||||
</resources>
|
||||
@@ -3,7 +3,7 @@
|
||||
<!--Sections-->
|
||||
<string name="modules">מודולים</string>
|
||||
<string name="superuser">משתמש על</string>
|
||||
<string name="logs">יומני רישום</string>
|
||||
<string name="logs">Log</string>
|
||||
<string name="settings">הגדרות</string>
|
||||
<string name="install">התקנה</string>
|
||||
<string name="section_home">בית</string>
|
||||
@@ -12,10 +12,10 @@
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">אין חיבור זמין</string>
|
||||
<string name="app_changelog">יומן שינויים</string>
|
||||
<string name="app_changelog">רשימת שינויים</string>
|
||||
<string name="loading">טוען…</string>
|
||||
<string name="update">עדכון</string>
|
||||
<string name="not_available">ל/ז</string>
|
||||
<string name="not_available">לא זמין</string>
|
||||
<string name="hide">הסתרה</string>
|
||||
<string name="home_package">חבילה</string>
|
||||
<string name="home_app_title">יישום</string>
|
||||
@@ -23,28 +23,28 @@
|
||||
<string name="home_support_title">תמיכה בנו</string>
|
||||
<string name="home_follow_title">עקבו אחרינו</string>
|
||||
<string name="home_item_source">מקור</string>
|
||||
<string name="home_support_content">Magisk היה ותמיד יהיה בעל קוד מקור פתוח. עם זאת באפשרותך להראות לנו שאכפת לך על ידי שליחת תרומה קטנה.</string>
|
||||
<string name="home_support_content">Magisk היה ותמיד יהיה בקוד פתוח. עם זאת באפשרותך להראות לנו שאכפת לך על ידי שליחת תרומה קטנה.</string>
|
||||
<string name="home_installed_version">מותקנת</string>
|
||||
<string name="home_latest_version">אחרונה</string>
|
||||
<string name="invalid_update_channel">ערוץ עדכון לא חוקי</string>
|
||||
<string name="uninstall_magisk_title">הסרת Magisk</string>
|
||||
<string name="uninstall_magisk_msg">כל המודולים יושבתו/יוסרו!\nגישת שורש תושבת!\nהנתונים שלך עשויים להיות מוצפנים אם לא הוצפנו כבר!</string>
|
||||
<string name="uninstall_magisk_msg">כל המודולים יושבתו/יוסרו!\nגישת Root תושבת!\nהנתונים שלך עשויים להיות מוצפנים אם לא הוצפנו כבר!</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">שמירה על הצפנה בכח</string>
|
||||
<string name="keep_dm_verity">שמירה על AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">מצב שחזור</string>
|
||||
<string name="recovery_mode">מצב Recovery</string>
|
||||
<string name="install_options_title">אפשרויות</string>
|
||||
<string name="install_method_title">שיטה</string>
|
||||
<string name="install_next">הבא</string>
|
||||
<string name="install_start">צא לדרך</string>
|
||||
<string name="manager_download_install">לחיצה להורדה והתקנה</string>
|
||||
<string name="direct_install">התקנה ישירה (מומלץ)</string>
|
||||
<string name="install_inactive_slot">התקנה לחריץ לא פעיל (לאחר OTA)</string>
|
||||
<string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לחריץ הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string>
|
||||
<string name="install_inactive_slot">התקנה לסלוט לא פעיל (לאחר OTA)</string>
|
||||
<string name="install_inactive_slot_msg">ההתקן שלך ייאלץ אתחול לסלוט הלא פעיל הנוכחי שלך לאחר הפעלה מחדש!\nיש להשתמש באפשרות זו רק לאחר ביצוע OTA בלבד.\nלהמשיך?</string>
|
||||
<string name="setup_title">התקנה נוספת</string>
|
||||
<string name="select_patch_file">בחירה והתקנת קובץ</string>
|
||||
<string name="patch_file_msg">בחירת תמונה גולמית (*.img) או ODIN tarfile (*.tar) או payload.bin (*.bin)</string>
|
||||
<string name="patch_file_msg">בחירת קובץ גולמי (*.img) או ODIN tarfile (*.tar) או payload.bin (*.bin)</string>
|
||||
<string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string>
|
||||
<string name="flash_screen_title">התקנה</string>
|
||||
|
||||
@@ -67,22 +67,22 @@
|
||||
<string name="su_snack_deny">הרשאות משתמש על עבור %1$s נשללו</string>
|
||||
<string name="su_snack_notif_on">התראות של %1$s מופעלות</string>
|
||||
<string name="su_snack_notif_off">התראות של %1$s מושבתות</string>
|
||||
<string name="su_snack_log_on">יומני רישום עבור %1$s פועלות</string>
|
||||
<string name="su_snack_log_off">יומני רישום עבור %1$s מושבתות</string>
|
||||
<string name="su_snack_log_on">Log עבור %1$s מופעל</string>
|
||||
<string name="su_snack_log_off">Log עבור %1$s מושבת</string>
|
||||
<string name="su_revoke_title">להסיר?</string>
|
||||
<string name="su_revoke_msg">נא לאשר שלילת הרשאות עבור %1$s?</string>
|
||||
<string name="toast">הרמת כוסית</string>
|
||||
<string name="toast">התראה</string>
|
||||
<string name="none">ללא</string>
|
||||
<string name="superuser_toggle_notification">התראות</string>
|
||||
<string name="superuser_toggle_revoke">הסרה</string>
|
||||
<string name="superuser_policy_none">טרם נתבקשו הרשאות משתמש על על ידי יישומים</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">הינך ללא יומן, יש לנסות להשתמש יותר ביישומי השורש שלך</string>
|
||||
<string name="log_data_magisk_none">יומני רישום Magisk ריקים, זה מוזר</string>
|
||||
<string name="menuSaveLog">שמירת יומן רישום</string>
|
||||
<string name="menuClearLog">ניקוי יומן רישום כעת</string>
|
||||
<string name="logs_cleared">יומני רישום נוקו בהצלחה</string>
|
||||
<string name="log_data_none">אין Log, יש לנסות להשתמש יותר ביישומי הRoot שלך</string>
|
||||
<string name="log_data_magisk_none">Log Magisk ריק, זה מוזר</string>
|
||||
<string name="menuSaveLog">שמירת Log</string>
|
||||
<string name="menuClearLog">ניקוי Log כעת</string>
|
||||
<string name="logs_cleared">Log נוקה בהצלחה</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">יעד UID: %1$d</string>
|
||||
<string name="target_pid">מציב ns יעד PID: %s</string>
|
||||
@@ -100,15 +100,15 @@
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(לא סופק מידע)</string>
|
||||
<string name="reboot_userspace">אתחול רך</string>
|
||||
<string name="reboot_recovery">אתחול למצב שחזור</string>
|
||||
<string name="reboot_bootloader">אתחול לטוען האתחול</string>
|
||||
<string name="reboot_recovery">אתחול למצב Recovery</string>
|
||||
<string name="reboot_bootloader">אתחול לBootloader</string>
|
||||
<string name="reboot_download">אתחול למצב הורדה</string>
|
||||
<string name="reboot_edl">אתחול למצב EDL</string>
|
||||
<string name="reboot_safe_mode">מצב בטוח</string>
|
||||
<string name="module_version_author">%1$s מאת %2$s</string>
|
||||
<string name="module_state_remove">הסרה</string>
|
||||
<string name="module_action">פעולה</string>
|
||||
<string name="module_state_restore">שחזור</string>
|
||||
<string name="module_state_restore">שיחזור</string>
|
||||
<string name="module_action_install_external">התקנה מהאחסון</string>
|
||||
<string name="update_available">עדכונים זמינים</string>
|
||||
<string name="suspend_text_riru">מודול מושעה כי %1$s מופעל</string>
|
||||
@@ -129,7 +129,7 @@
|
||||
<string name="settings_hide_app_title">הסתרת היישום Magisk</string>
|
||||
<string name="settings_hide_app_summary">התקנת יישום מתווך עם מזהה חבילה אקראי ותווית שם מותאמת אישית</string>
|
||||
<string name="settings_restore_app_title">שיחזור היישום Magisk</string>
|
||||
<string name="settings_restore_app_summary">ביטול הסתרת היישום ושחזור אל ה-APK המקורי</string>
|
||||
<string name="settings_restore_app_summary">ביטול הסתרת היישום ושיחזור אל ה-APK המקורי</string>
|
||||
<string name="language">שפה</string>
|
||||
<string name="system_default">(ברירת מחדל מערכת)</string>
|
||||
<string name="settings_check_update_title">בדיקת עדכונים</string>
|
||||
@@ -144,9 +144,9 @@
|
||||
<string name="settings_denylist_summary">כל השינויים של Magisk יוחזרו לתהליכים ברשימת הדחייה</string>
|
||||
<string name="settings_denylist_config_title">הגדרת רשימת הדחייה</string>
|
||||
<string name="settings_denylist_config_summary">בחירת התהליכים שייכללו ברשימת הדחייה</string>
|
||||
<string name="settings_hosts_title">מארחים חסרי מערכת</string>
|
||||
<string name="settings_hosts_summary">מארחים חסרי מערכת תומכים ביישומים חוסמי פרסומות</string>
|
||||
<string name="settings_hosts_toast">הוספת מודול מארחים חסרי מערכת</string>
|
||||
<string name="settings_hosts_title">hosts חסרי מערכת</string>
|
||||
<string name="settings_hosts_summary">hosts חסרי מערכת תומכים ביישומים חוסמי פרסומות</string>
|
||||
<string name="settings_hosts_toast">הוספת מודול hosts חסרי מערכת</string>
|
||||
<string name="settings_app_name_hint">שם חדש</string>
|
||||
<string name="settings_app_name_helper">היישום יארז מחדש בשם זה</string>
|
||||
<string name="settings_app_name_error">פורמט לא חוקי</string>
|
||||
@@ -181,16 +181,16 @@
|
||||
<string name="settings_owner_only">בעל ההתקן בלבד</string>
|
||||
<string name="settings_owner_manage">אחראי ניהול ההתקן</string>
|
||||
<string name="settings_user_independent">משתמש עצמאי</string>
|
||||
<string name="owner_only_summary">לבעלים בלבד ישנה גישת שורש</string>
|
||||
<string name="owner_manage_summary">הבעלים בלבד יכול לנהל גישת שורש ולקבל הנחיות לבקשה</string>
|
||||
<string name="user_independent_summary">לכל משתמש יש כללי שורש נפרדים משלו</string>
|
||||
<string name="owner_only_summary">לבעלים בלבד ישנה גישת Root</string>
|
||||
<string name="owner_manage_summary">הבעלים בלבד יכול לנהל גישת Root ולקבל הנחיות לבקשה</string>
|
||||
<string name="user_independent_summary">לכל משתמש יש כללי Root נפרדים משלו</string>
|
||||
<string name="mount_namespace_mode">מצב הצבת מרחב שם</string>
|
||||
<string name="settings_ns_global">מרחב שם גלובלי</string>
|
||||
<string name="settings_ns_requester">מרחב שם מורש</string>
|
||||
<string name="settings_ns_isolate">מרחב שם מבודד</string>
|
||||
<string name="global_summary">כלל חיבורי השורש משתמשים במרחב שם הגלובלי</string>
|
||||
<string name="requester_summary">חיבורי השורש יירשו את מרחב השם של המבקש</string>
|
||||
<string name="isolate_summary">לכל חיבור שורש יהיה מרחב שם מבודד</string>
|
||||
<string name="global_summary">כלל חיבורי הRoot משתמשים במרחב שם הגלובלי</string>
|
||||
<string name="requester_summary">חיבורי הRoot יירשו את מרחב השם של המבקש</string>
|
||||
<string name="isolate_summary">לכל חיבור Root יהיה מרחב שם מבודד</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">עדכוני Magisk</string>
|
||||
@@ -225,7 +225,7 @@
|
||||
<string name="setup_fail">ההתקנה כשלה</string>
|
||||
<string name="env_fix_title">דורש התקנה נוספת</string>
|
||||
<string name="env_fix_msg">ההתקן שלך זקוק להתקנה נוספת כדי ש-Magisk יפעל כראוי. האם ברצונך להמשיך ולהפעיל מחדש?</string>
|
||||
<string name="env_full_fix_msg">ההתקן שלך זקוק לצריבה מחדש של Magisk כדי לעבוד כראוי. נא להתקין מחדש את Magisk בתוך היישום, מצב השחזור אינו יכול לקבל מידע נכון על ההתקן.</string>
|
||||
<string name="env_full_fix_msg">ההתקן שלך זקוק לצריבה מחדש של Magisk כדי לעבוד כראוי. נא להתקין מחדש את Magisk בתוך היישום, מצב הRecovery אינו יכול לקבל מידע נכון על ההתקן.</string>
|
||||
<string name="setup_msg">הגדרת סביבת ריצה…</string>
|
||||
<string name="unsupport_magisk_title">גרסת Magisk אינה נתמכת</string>
|
||||
<string name="unsupport_magisk_msg">גרסה זו של היישום אינה תומכת ביישום Magisk הנמוך מ- %1$s.\n\nהיישום יתנהג כאילו Magisk אינו מותקן,יש לשדרג את Magisk במהירות האפשריות.</string>
|
||||
@@ -233,7 +233,7 @@
|
||||
<string name="unsupport_system_app_msg">הפעלת יישום זה כיישום מערכת אינה נתמך. נא להשיב את היישום כיישום משתמש.</string>
|
||||
<string name="unsupport_other_su_msg">התגלתה פקודת \"su\" שאינה שייכת ליישום Magisk נא להסיר את הפקודה שאינה נתמכת.</string>
|
||||
<string name="unsupport_external_storage_msg">Magisk מותקן באחסון החיצוני. נא להעביר את היישום לאחסון הפנימי.</string>
|
||||
<string name="unsupport_nonroot_stub_msg">היישום אינו יכול להמשיך לעבוד במצב הנסתר מכיוון שגישת השורש אבדה. נא לשחזר אותו חזרה ל-APK המקורי.</string>
|
||||
<string name="unsupport_nonroot_stub_msg">היישום אינו יכול להמשיך לעבוד במצב הנסתר מכיוון שגישת הRoot אבדה. נא לשחזר אותו חזרה ל-APK המקורי.</string>
|
||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||
<string name="external_rw_permission_denied">הענת הרשאת אחסון להפעלת פונקציה זו</string>
|
||||
<string name="post_notifications_denied">הענקת הרשאה להתראות כדי להפעיל פונקציה זו</string>
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<string name="deny">Negar</string>
|
||||
<string name="prompt">Perguntar</string>
|
||||
<string name="grant">Permitir</string>
|
||||
<string name="su_warning">Permite acesso total ao seu aparelho.\nNão permita se você não tiver certeza do que está fazendo!</string>
|
||||
<string name="su_warning">Permite acesso total ao seu dispositivo.\nNão permita se você não tiver certeza do que está fazendo!</string>
|
||||
<string name="forever">Sempre</string>
|
||||
<string name="once">Uma vez</string>
|
||||
<string name="tenmin">10 mins</string>
|
||||
@@ -63,19 +63,19 @@
|
||||
<string name="sixtymin">60 mins</string>
|
||||
<string name="su_allow_toast">%1$s foi permitido o acesso de SuperUsuário</string>
|
||||
<string name="su_deny_toast">%1$s foi negado o acesso de SuperUsuário</string>
|
||||
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram concedidos</string>
|
||||
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram permitidos</string>
|
||||
<string name="su_snack_deny">Os acessos de SuperUsuário de %1$s foram negados</string>
|
||||
<string name="su_snack_notif_on">As notificações de %1$s foram ativadas</string>
|
||||
<string name="su_snack_notif_off">As notificações de %1$s foram desativadas</string>
|
||||
<string name="su_snack_log_on">Os registros de %1$s foram ativados</string>
|
||||
<string name="su_snack_log_off">Os registros de %1$s foram desativados</string>
|
||||
<string name="su_revoke_title">Revogar?</string>
|
||||
<string name="su_revoke_msg">Confirmar a remoção do acesso de SuperUsuário de %1$s?</string>
|
||||
<string name="su_revoke_msg">Confirme para revogar os acessos de SuperUsuário de %1$s</string>
|
||||
<string name="toast">Notificação (Pop-up)</string>
|
||||
<string name="none">Nenhum</string>
|
||||
<string name="superuser_toggle_notification">Notificações</string>
|
||||
<string name="superuser_toggle_revoke">Revogar</string>
|
||||
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda</string>
|
||||
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda.</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Não há registros. Tente usar mais seus apps root.</string>
|
||||
@@ -135,6 +135,7 @@
|
||||
<string name="settings_update_channel_title">Canal de atualização</string>
|
||||
<string name="settings_update_stable">Estável</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_debug">Debug</string>
|
||||
<string name="settings_update_custom">Personalizado</string>
|
||||
<string name="settings_update_custom_msg">Insira um URL de canal personalizado</string>
|
||||
<string name="settings_zygisk_summary">Executa partes do Magisk no Zygote</string>
|
||||
@@ -235,7 +236,7 @@
|
||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||
<string name="external_rw_permission_denied">Conceda permissão de armazenamento para ativar esta funcionalidade</string>
|
||||
<string name="post_notifications_denied">Conceda permissão às notificações para ativar esta funcionalidade</string>
|
||||
<string name="install_unknown_denied">Permita a opção "Instalar apps de fontes desconhecidas" para ativar esta funcionalidade</string>
|
||||
<string name="install_unknown_denied">Permita a opção \"Instalar apps de fontes desconhecidas\" para ativar esta funcionalidade</string>
|
||||
<string name="add_shortcut_title">Adicionar atalho à tela inicial</string>
|
||||
<string name="add_shortcut_msg">Após ocultar o app do Magisk, seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
|
||||
<string name="app_not_found">Nenhum app encontrado para realizar esta ação</string>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!--Sections-->
|
||||
<string name="modules">Módulos</string>
|
||||
<string name="superuser">SuperUsuário</string>
|
||||
<string name="logs">Registros</string>
|
||||
<string name="logs">Registos</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="section_home">Início</string>
|
||||
@@ -11,50 +11,50 @@
|
||||
<string name="denylist">Lista de negação</string>
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">Nenhuma conexão disponível</string>
|
||||
<string name="app_changelog">Registro de alterações</string>
|
||||
<string name="loading">Carregando…</string>
|
||||
<string name="no_connection">Nenhuma ligação disponível</string>
|
||||
<string name="app_changelog">Registo de alterações</string>
|
||||
<string name="loading">A carregar…</string>
|
||||
<string name="update">Atualizar</string>
|
||||
<string name="not_available">Não disponível</string>
|
||||
<string name="hide">Ocultar</string>
|
||||
<string name="home_package">Pacote</string>
|
||||
<string name="home_app_title">App</string>
|
||||
<string name="home_notice_content">Baixe o Magisk SOMENTE pela página oficial do GitHub. Arquivos de fontes desconhecidas podem ser maliciosos!</string>
|
||||
<string name="home_notice_content">Descarregue o Magisk APENAS na página oficial do GitHub. Os ficheiros de fontes desconhecidas podem ser maliciosos!</string>
|
||||
<string name="home_support_title">Apoie-nos</string>
|
||||
<string name="home_follow_title">Siga-nos</string>
|
||||
<string name="home_item_source">Fonte</string>
|
||||
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode nos ajudar enviando uma pequena doação.</string>
|
||||
<string name="home_support_content">Magisk sempre foi e sempre será, gratuito e de código aberto. No entanto, você pode ajudar-nos enviando uma pequena doação.</string>
|
||||
<string name="home_installed_version">Instalado</string>
|
||||
<string name="home_latest_version">Recente</string>
|
||||
<string name="invalid_update_channel">Canal de atualização inválido</string>
|
||||
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nO root será removido!\nSeus dados não criptografados devido ao uso do Magisk, serão re-criptografados!</string>
|
||||
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nO root será removido!\nOs seus dados não encriptados devido à utilização do Magisk, serão re-encriptados!</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Manter criptografia forçada</string>
|
||||
<string name="keep_force_encryption">Manter encriptação forçada</string>
|
||||
<string name="keep_dm_verity">Manter AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Modo Recovery</string>
|
||||
<string name="install_options_title">Opções</string>
|
||||
<string name="install_method_title">Método</string>
|
||||
<string name="install_next">Próximo</string>
|
||||
<string name="install_start">Vamos lá</string>
|
||||
<string name="manager_download_install">Toque para baixar e instalar</string>
|
||||
<string name="manager_download_install">Toque para descarregar e instalar</string>
|
||||
<string name="direct_install">Instalação direta (recomendada)</string>
|
||||
<string name="install_inactive_slot">Instalar no slot inativo (após o OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Seu dispositivo será FORÇADO a inicializar no slot inativo atual após uma reinicialização!\nSó use esta opção após a conclusão do OTA.\nDeseja continuar?</string>
|
||||
<string name="install_inactive_slot_msg">O seu dispositivo será FORÇADO a inicializar no slot inativo atual após um reinício!\nSó use esta opção após a conclusão do OTA.\nDeseja continuar?</string>
|
||||
<string name="setup_title">Configuração adicional</string>
|
||||
<string name="select_patch_file">Selecione e corrija um arquivo</string>
|
||||
<string name="patch_file_msg">Selecione um arquivo imagem (*.img) ou um arquivo tar (*.tar) ou um arquivo payload.bin (*.bin)</string>
|
||||
<string name="reboot_delay_toast">Reiniciando em 5 segundos…</string>
|
||||
<string name="select_patch_file">Selecione e corrija um ficheiro</string>
|
||||
<string name="patch_file_msg">Selecione um ficheiro de imagem (*.img) ou um ficheiro tar (*.tar) ou um ficheiro payload.bin (*.bin)</string>
|
||||
<string name="reboot_delay_toast">A reiniciar em 5 segundos…</string>
|
||||
<string name="flash_screen_title">Instalação</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Solicitação de SuperUsuário</string>
|
||||
<string name="touch_filtered_warning">Como um app está ocultando uma solicitação de SuperUsuário, o Magisk não pode verificar sua resposta.</string>
|
||||
<string name="touch_filtered_warning">Como um app está a ocultar um pedido de SuperUsuário, o Magisk não consegue verificar a sua resposta.</string>
|
||||
<string name="deny">Negar</string>
|
||||
<string name="prompt">Perguntar</string>
|
||||
<string name="grant">Permitir</string>
|
||||
<string name="su_warning">Permite acesso total ao seu aparelho.\nNão permita se você não tiver certeza do que está fazendo!</string>
|
||||
<string name="su_warning">Permite o acesso total ao seu dispositivo.\nNão o permita se não tiver a certeza do que está a fazer!</string>
|
||||
<string name="forever">Sempre</string>
|
||||
<string name="once">Uma vez</string>
|
||||
<string name="tenmin">10 mins</string>
|
||||
@@ -63,26 +63,26 @@
|
||||
<string name="sixtymin">60 mins</string>
|
||||
<string name="su_allow_toast">%1$s foi permitido o acesso de SuperUsuário</string>
|
||||
<string name="su_deny_toast">%1$s foi negado o acesso de SuperUsuário</string>
|
||||
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram concedidos</string>
|
||||
<string name="su_snack_grant">Os acessos de SuperUsuário de %1$s foram permitidos</string>
|
||||
<string name="su_snack_deny">Os acessos de SuperUsuário de %1$s foram negados</string>
|
||||
<string name="su_snack_notif_on">As notificações de %1$s foram ativadas</string>
|
||||
<string name="su_snack_notif_off">As notificações de %1$s foram desativadas</string>
|
||||
<string name="su_snack_log_on">Os registros de %1$s foram ativados</string>
|
||||
<string name="su_snack_log_off">Os registros de %1$s foram desativados</string>
|
||||
<string name="su_snack_log_on">Os registos de %1$s foram ativados</string>
|
||||
<string name="su_snack_log_off">Os registos de %1$s foram desativados</string>
|
||||
<string name="su_revoke_title">Revogar?</string>
|
||||
<string name="su_revoke_msg">Confirmar a remoção do acesso de SuperUsuário de %1$s?</string>
|
||||
<string name="su_revoke_msg">Confirme para revogar os acessos de SuperUsuário de %1$s</string>
|
||||
<string name="toast">Notificação (Pop-up)</string>
|
||||
<string name="none">Nenhum</string>
|
||||
<string name="superuser_toggle_notification">Notificações</string>
|
||||
<string name="superuser_toggle_revoke">Revogar</string>
|
||||
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda</string>
|
||||
<string name="superuser_policy_none">Nenhum app solicitou permissão de SuperUsuário ainda.</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Não há registros. Tente usar mais seus apps root.</string>
|
||||
<string name="log_data_magisk_none">Os registros do Magisk estão vazios, isso é estranho.</string>
|
||||
<string name="menuSaveLog">Salvar registros</string>
|
||||
<string name="menuClearLog">Limpar registros agora</string>
|
||||
<string name="logs_cleared">Registros limpo com sucesso</string>
|
||||
<string name="log_data_none">Não há registos. Tente utilizar mais seus apps root.</string>
|
||||
<string name="log_data_magisk_none">Os registos do Magisk estão vazios, isto é estranho.</string>
|
||||
<string name="menuSaveLog">Salvar registos</string>
|
||||
<string name="menuClearLog">Limpar registos agora</string>
|
||||
<string name="logs_cleared">Registos limpo com sucesso</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Alvo UID: %1$d</string>
|
||||
<string name="target_pid">Alvo PID: %s</string>
|
||||
@@ -118,12 +118,12 @@
|
||||
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">Modo do tema</string>
|
||||
<string name="settings_dark_mode_message">Selecione o modo mais adequado para você!</string>
|
||||
<string name="settings_dark_mode_message">Selecione o modo mais adequado para si!</string>
|
||||
<string name="settings_dark_mode_light">Sempre claro</string>
|
||||
<string name="settings_dark_mode_system">Seguir sistema</string>
|
||||
<string name="settings_dark_mode_dark">Sempre escuro</string>
|
||||
<string name="settings_download_path_title">Caminho para baixar</string>
|
||||
<string name="settings_download_path_message">Os arquivos serão salvos em %1$s</string>
|
||||
<string name="settings_download_path_title">Caminho para descarregar</string>
|
||||
<string name="settings_download_path_message">Os ficheiros serão salvos em %1$s</string>
|
||||
<string name="settings_hide_app_title">Ocultar app do Magisk</string>
|
||||
<string name="settings_hide_app_summary">Instala o app oculto com ID aleatório e nome personalizado</string>
|
||||
<string name="settings_restore_app_title">Restaurar app do Magisk</string>
|
||||
@@ -135,8 +135,9 @@
|
||||
<string name="settings_update_channel_title">Canal de atualização</string>
|
||||
<string name="settings_update_stable">Estável</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_debug">Debug</string>
|
||||
<string name="settings_update_custom">Personalizado</string>
|
||||
<string name="settings_update_custom_msg">Insira um URL de canal personalizado</string>
|
||||
<string name="settings_update_custom_msg">Introduza um URL de canal personalizado</string>
|
||||
<string name="settings_zygisk_summary">Executa partes do Magisk no Zygote</string>
|
||||
<string name="settings_denylist_title">Aplicar lista de negação</string>
|
||||
<string name="settings_denylist_summary">Os processos na lista de negação terão todas as modificações do Magisk revertidas</string>
|
||||
@@ -167,35 +168,35 @@
|
||||
<string name="settings_su_tapjack_title">Proteção contra atividades sobrepostas</string>
|
||||
<string name="settings_su_tapjack_summary">A caixa de diálogo do SuperUsuário não responderá à entrada enquanto estiver oculta por qualquer outra janela ou sobreposição</string>
|
||||
<string name="settings_su_auth_title">Autenticação de usuário</string>
|
||||
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante solicitações de SuperUsuário</string>
|
||||
<string name="settings_su_auth_summary">Solicite autenticação de usuário durante pedidos de SuperUsuário</string>
|
||||
<string name="settings_su_auth_insecure">Nenhum método de autenticação está configurado no dispositivo</string>
|
||||
<string name="settings_customization">Personalizações</string>
|
||||
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
||||
<string name="setting_add_shortcut_summary">Adicione um atalho no ecrã inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o app.</string>
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
|
||||
<string name="settings_random_name_title">Randomizar nome de saída</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do arquivo de saída de imagens corrigidas e arquivos tar (*.tar) para evitar a detecção</string>
|
||||
<string name="settings_random_name_description">Randomize o nome do ficheiro de saída de imagens corrigidas e ficheiros tar (*.tar) para evitar a deteção</string>
|
||||
<string name="multiuser_mode">Modo multiusuário</string>
|
||||
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
|
||||
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
|
||||
<string name="settings_owner_manage">Gerido pelo proprietário do dispositivo</string>
|
||||
<string name="settings_user_independent">Independente do usuário</string>
|
||||
<string name="owner_only_summary">Somente o proprietário tem acesso root</string>
|
||||
<string name="owner_manage_summary">Somente o proprietário pode gerenciar o acesso root e receber pedidos de solicitação</string>
|
||||
<string name="owner_manage_summary">Somente o proprietário pode gerir o acesso root e receber pedidos de solicitação</string>
|
||||
<string name="user_independent_summary">Cada usuário tem suas próprias regras de root separadas</string>
|
||||
<string name="mount_namespace_mode">Montar namespace</string>
|
||||
<string name="settings_ns_global">Global</string>
|
||||
<string name="settings_ns_requester">Herdado</string>
|
||||
<string name="settings_ns_isolate">Individual</string>
|
||||
<string name="global_summary">Todas as sessões root usam o namespace de montagem global</string>
|
||||
<string name="requester_summary">As sessões root herdarão o namespace do solicitante</string>
|
||||
<string name="isolate_summary">Cada sessão root terá seu próprio namespace individual</string>
|
||||
<string name="global_summary">Todas as sessões root utilizam o namespace de montagem global</string>
|
||||
<string name="requester_summary">As sessões root herdarão o namespace do requerente</string>
|
||||
<string name="isolate_summary">Cada sessão root terá o seu próprio namespace individual</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Atualizações do Magisk</string>
|
||||
<string name="progress_channel">Notificações de progresso</string>
|
||||
<string name="updated_channel">Atualização concluída</string>
|
||||
<string name="download_complete">Download concluído</string>
|
||||
<string name="download_file_error">Erro ao baixar arquivo</string>
|
||||
<string name="download_file_error">Erro ao descarregar ficheiro</string>
|
||||
<string name="magisk_update_title">Atualização do Magisk disponível!</string>
|
||||
<string name="updated_title">Magisk atualizado</string>
|
||||
<string name="updated_text">Toque para abrir o app</string>
|
||||
@@ -209,37 +210,37 @@
|
||||
<string name="close">Fechar</string>
|
||||
<string name="release_notes">Notas da atualização</string>
|
||||
<string name="flashing">Flashando…</string>
|
||||
<string name="running">Executando…</string>
|
||||
<string name="running">A executar…</string>
|
||||
<string name="done">Concluído!</string>
|
||||
<string name="done_action">Ação de execução de %1$s concluída</string>
|
||||
<string name="failure">Falhou!</string>
|
||||
<string name="hide_app_title">Ocultando o app do Magisk…</string>
|
||||
<string name="hide_app_title">A ocultar o app do Magisk…</string>
|
||||
<string name="open_link_failed_toast">Nenhum app encontrado para abrir o link</string>
|
||||
<string name="complete_uninstall">Desinstalação completa</string>
|
||||
<string name="restore_img">Restaurar imagens</string>
|
||||
<string name="restore_img_msg">Restaurando…</string>
|
||||
<string name="restore_img_msg">A restaurar…</string>
|
||||
<string name="restore_done">Restauração concluída!</string>
|
||||
<string name="restore_fail">O backup original não existe!</string>
|
||||
<string name="setup_fail">Falha na instalação</string>
|
||||
<string name="env_fix_title">Configuração adicional exigida</string>
|
||||
<string name="env_fix_msg">Seu dispositivo exige uma configuração adicional para o Magisk funcionar corretamente. Deseja continuar e reiniciar?</string>
|
||||
<string name="env_full_fix_msg">Seu dispositivo precisa refazer o flash do Magisk para funcionar corretamente. Por favor, reinstale o Magisk no app, o modo Recovery não pode obter as devidas informações do dispositivo.</string>
|
||||
<string name="setup_msg">Executando a configuração do ambiente…</string>
|
||||
<string name="env_full_fix_msg">O seu dispositivo precisa de refazer o flash do Magisk para funcionar corretamente. Por favor, reinstale o Magisk no app, o modo Recovery não consegue obter as devidas informações do dispositivo.</string>
|
||||
<string name="setup_msg">A executar a configuração do ambiente…</string>
|
||||
<string name="unsupport_magisk_title">Versão do Magisk não suportada</string>
|
||||
<string name="unsupport_magisk_msg">Esta versão do app não suporta a versão do Magisk inferior a %1$s.\n\nO app irá se comportar como se nenhum Magisk estivesse sido instalado. Por favor, atualize o Magisk assim que possível.</string>
|
||||
<string name="unsupport_magisk_msg">Esta versão do app não suporta versões do Magisk inferiores a %1$s.\n\nO app irá comportar-se como se nenhum Magisk estivesse instalado. Por favor, atualize o Magisk assim que possível.</string>
|
||||
<string name="unsupport_general_title">Estado anormal</string>
|
||||
<string name="unsupport_system_app_msg">Não há suporte para executar este app como um app do sistema. Por favor, reverta o app para um app de usuário.</string>
|
||||
<string name="unsupport_other_su_msg">Não foi possível detectar o binário \"su\" do Magisk. Por favor, remova qualquer outro root concorrente e/ou reinstale o Magisk.</string>
|
||||
<string name="unsupport_external_storage_msg">O app do Magisk está instalado no armazenamento externo. Por favor, mova o app para o armazenamento interno.</string>
|
||||
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar funcionando porque o root foi perdido. Por favor, restaure o APK original.</string>
|
||||
<string name="unsupport_nonroot_stub_msg">O app oculto do Magisk não pode continuar a funcionar porque o root foi perdido. Por favor, restaure o APK original.</string>
|
||||
<string name="unsupport_nonroot_stub_title">@string/settings_restore_app_title</string>
|
||||
<string name="external_rw_permission_denied">Conceda permissão de armazenamento para ativar esta funcionalidade</string>
|
||||
<string name="post_notifications_denied">Conceda permissão às notificações para ativar esta funcionalidade</string>
|
||||
<string name="install_unknown_denied">Permita a opção "Instalar apps de fontes desconhecidas" para ativar esta funcionalidade</string>
|
||||
<string name="add_shortcut_title">Adicionar atalho à tela inicial</string>
|
||||
<string name="add_shortcut_msg">Após ocultar o app do Magisk, seu nome e ícone ficarão difíceis de reconhecer. Deseja adicionar um atalho na tela inicial?</string>
|
||||
<string name="install_unknown_denied">Permita a opção \"Instalar apps de fontes desconhecidas\" para ativar esta funcionalidade</string>
|
||||
<string name="add_shortcut_title">Adicionar atalho ao ecrã inicial</string>
|
||||
<string name="add_shortcut_msg">Após ocultar o app do Magisk, o seu nome e ícone serão difíceis de reconhecer. Deseja adicionar um atalho no ecrã inicial?</string>
|
||||
<string name="app_not_found">Nenhum app encontrado para realizar esta ação</string>
|
||||
<string name="reboot_apply_change">Reinicie para aplicar as mudanças</string>
|
||||
<string name="reboot_apply_change">Reinicie para aplicar as alterações</string>
|
||||
<string name="restore_app_confirmation">Isso irá restaurar o app oculto do Magisk de volta para o app original. Deseja realmente fazer isso?</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<resources>
|
||||
<!--Author: Radoš Milićev (https://github.com/rammba)-->
|
||||
|
||||
<!--Sections-->
|
||||
<string name="modules">Модули</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user