mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 12:17:26 +00:00
Compare commits
128 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
483dbcdc40 | ||
![]() |
a1096b5bf0 | ||
![]() |
5ac0e64edb | ||
![]() |
60b2624607 | ||
![]() |
d2e2847b03 | ||
![]() |
b9669f54f7 | ||
![]() |
8c7bd77d33 | ||
![]() |
ba1ce16b8b | ||
![]() |
68090943f4 | ||
![]() |
a4fb1297b0 | ||
![]() |
860a05abf2 | ||
![]() |
8bb2f356c0 | ||
![]() |
4950020635 | ||
![]() |
0a6140c6eb | ||
![]() |
bba2ac8817 | ||
![]() |
331b1f542f | ||
![]() |
ccb55205e6 | ||
![]() |
9cc91b30b3 | ||
![]() |
e836caf31e | ||
![]() |
beaa1e5be2 | ||
![]() |
ea545bae26 | ||
![]() |
1c9ec2df45 | ||
![]() |
b76c80e2ce | ||
![]() |
236990f4a3 | ||
![]() |
1ed32df20d | ||
![]() |
8476eb9f4b | ||
![]() |
735af7843b | ||
![]() |
ded73e958b | ||
![]() |
6dcb84d4f4 | ||
![]() |
501bc9f438 | ||
![]() |
f88e812b63 | ||
![]() |
be6386c410 | ||
![]() |
2af4fd17c4 | ||
![]() |
f870418bd0 | ||
![]() |
00659e4795 | ||
![]() |
cdda10207e | ||
![]() |
701700279f | ||
![]() |
a9d804724a | ||
![]() |
e033a9ab47 | ||
![]() |
059e5fb8aa | ||
![]() |
a78f255928 | ||
![]() |
1d10e69288 | ||
![]() |
63590d379c | ||
![]() |
5f63e88984 | ||
![]() |
75584e2b19 | ||
![]() |
1426ee2ebd | ||
![]() |
b6643b7bfc | ||
![]() |
721dfdf553 | ||
![]() |
2963747d14 | ||
![]() |
e7350d5041 | ||
![]() |
f37e8f4ca8 | ||
![]() |
594c2accc0 | ||
![]() |
7acfac6a91 | ||
![]() |
0646f48e14 | ||
![]() |
37565fd067 | ||
![]() |
26b2e7dc5d | ||
![]() |
c3313623e4 | ||
![]() |
2089223690 | ||
![]() |
52e1b84d41 | ||
![]() |
8794141b7f | ||
![]() |
f6126dd20e | ||
![]() |
18acfda99b | ||
![]() |
bec5edca84 | ||
![]() |
6fb20b3ee5 | ||
![]() |
eaf4d8064b | ||
![]() |
2a5f5b1bba | ||
![]() |
c538a77937 | ||
![]() |
aa9e7b1ed1 | ||
![]() |
a3066eddab | ||
![]() |
d1729fa787 | ||
![]() |
93961dde2c | ||
![]() |
1024e68eb6 | ||
![]() |
6ae2c9387d | ||
![]() |
fba83e2330 | ||
![]() |
f1295cb7d6 | ||
![]() |
dc61dfbde6 | ||
![]() |
21466426da | ||
![]() |
3f0136362b | ||
![]() |
e92d77bbec | ||
![]() |
07bd36c94b | ||
![]() |
b1dbbdef12 | ||
![]() |
3e479726ec | ||
![]() |
4cc41eccb3 | ||
![]() |
8f08ae59ac | ||
![]() |
e8d4e492d6 | ||
![]() |
b8090a8e18 | ||
![]() |
c609a01e55 | ||
![]() |
c97fb385cd | ||
![]() |
da6c57750e | ||
![]() |
6951d926f7 | ||
![]() |
6623195bd5 | ||
![]() |
ec31bb9a82 | ||
![]() |
8618cc383a | ||
![]() |
4b01e3a3c7 | ||
![]() |
7f748c23c1 | ||
![]() |
963d248cc7 | ||
![]() |
657056e636 | ||
![]() |
9d5efea66e | ||
![]() |
658d74e026 | ||
![]() |
5113f6d375 | ||
![]() |
96405c26d0 | ||
![]() |
4ea5f34bf3 | ||
![]() |
dbd13a2019 | ||
![]() |
06773235da | ||
![]() |
e57556a8af | ||
![]() |
b54b78c29d | ||
![]() |
317336f771 | ||
![]() |
b4e52f6135 | ||
![]() |
f2ca042915 | ||
![]() |
1060dd2906 | ||
![]() |
2e0f7a82fa | ||
![]() |
5798536559 | ||
![]() |
ab9a83c82f | ||
![]() |
c87fdbea0f | ||
![]() |
ec8fffe61c | ||
![]() |
61d52991f1 | ||
![]() |
9100186dce | ||
![]() |
d2bc2cfcf8 | ||
![]() |
5a71998b4e | ||
![]() |
42278f12ff | ||
![]() |
f5593e051c | ||
![]() |
a27e30cf54 | ||
![]() |
79140c7636 | ||
![]() |
1f4c595cd3 | ||
![]() |
b5b62e03af | ||
![]() |
67e2a4720e | ||
![]() |
f5c2d72429 | ||
![]() |
2f5331ab48 |
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@@ -43,12 +43,8 @@ jobs:
|
||||
- name: Set up GitHub env (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
$oldAndroidPath = $env:ANDROID_SDK_ROOT
|
||||
$sdk_root = "C:\Android"
|
||||
New-Item -Path $sdk_root -ItemType SymbolicLink -Value $oldAndroidPath
|
||||
$ndk_ver = Select-String -Path "gradle.properties" -Pattern "^magisk.fullNdkVersion=" | % { $_ -replace ".*=" }
|
||||
echo "ANDROID_SDK_ROOT=$sdk_root" >> $env:GITHUB_ENV
|
||||
echo "ANDROID_HOME=$sdk_root" >> $env:GITHUB_ENV
|
||||
echo "ANDROID_SDK_ROOT=$env:ANDROID_SDK_ROOT" >> $env:GITHUB_ENV
|
||||
echo "MAGISK_NDK_VERSION=$ndk_ver" >> $env:GITHUB_ENV
|
||||
echo "GRADLE_OPTS=-Dorg.gradle.daemon=false" >> $env:GITHUB_ENV
|
||||
|
||||
|
10
README.MD
10
README.MD
@@ -15,11 +15,13 @@ Here are some feature highlights:
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.5/MagiskManager-v8.0.5.apk)
|
||||
Please note that the only source of official Magisk information and downloads is [Github](https://github.com/topjohnwu/Magisk/). Beware of any other websites.
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.7/MagiskManager-v8.0.7.apk)
|
||||
[](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-debug.apk)
|
||||
<br>
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.2)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.2)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.4)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.4)
|
||||
|
||||
## Useful Links
|
||||
|
||||
@@ -60,7 +62,7 @@ For Magisk Manager crashes, record and upload the logcat when the crash occurs.
|
||||
- Run `./build.py ndk` to let the script download and install NDK for you
|
||||
- To start building, run `build.py` to see your options. \
|
||||
For each action, use `-h` to access help (e.g. `./build.py all -h`)
|
||||
- To start development, open the project in Android Studio. Both app (Kotlin/Java) and native (C++/C) source code can be properly developed using the IDE, but *always* use `build.py` for building.
|
||||
- To start development, open the project with Android Studio. The IDE can be used for both app (Kotlin/Java) and native (C++/C) sources.
|
||||
- Optionally, set custom configs with `config.prop`. A sample `config.prop.sample` is provided.
|
||||
- To sign APKs and zips with your own private keys, set signing configs in `config.prop`. For more info, check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key).
|
||||
|
||||
|
5
app/.gitignore
vendored
5
app/.gitignore
vendored
@@ -6,6 +6,7 @@
|
||||
app/release
|
||||
*.hprof
|
||||
.externalNativeBuild/
|
||||
public.certificate.x509.pem
|
||||
private.key.pk8
|
||||
*.apk
|
||||
src/main/assets
|
||||
src/main/jniLibs
|
||||
src/main/resources
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import org.apache.tools.ant.filters.FixCrLfFilter
|
||||
import java.io.PrintStream
|
||||
|
||||
plugins {
|
||||
@@ -22,8 +23,9 @@ android {
|
||||
applicationId = "com.topjohnwu.magisk"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled = true
|
||||
versionName = Config.appVersion
|
||||
versionCode = Config.appVersionCode
|
||||
versionName = Config.version
|
||||
versionCode = Config.versionCode
|
||||
ndk.abiFilters("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
|
||||
javaCompileOptions.annotationProcessorOptions.arguments(
|
||||
mapOf("room.incremental" to "true")
|
||||
@@ -51,13 +53,14 @@ android {
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude("/META-INF/**")
|
||||
exclude("/META-INF/*")
|
||||
exclude("/org/bouncycastle/**")
|
||||
exclude("/kotlin/**")
|
||||
exclude("/kotlinx/**")
|
||||
exclude("/okhttp3/**")
|
||||
exclude("/*.txt")
|
||||
exclude("/*.bin")
|
||||
doNotStrip("**/*.so")
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
@@ -65,10 +68,83 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
tasks["preBuild"]?.dependsOn(tasks.register("copyUtils", Copy::class) {
|
||||
from(rootProject.file("scripts/util_functions.sh"))
|
||||
into("src/main/res/raw")
|
||||
})
|
||||
val syncLibs by tasks.registering(Sync::class) {
|
||||
into("src/main/jniLibs")
|
||||
into("armeabi-v7a") {
|
||||
from(rootProject.file("native/out/armeabi-v7a")) {
|
||||
include("busybox", "magiskboot", "magiskinit", "magisk")
|
||||
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
|
||||
}
|
||||
from(rootProject.file("native/out/arm64-v8a")) {
|
||||
include("magisk")
|
||||
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
|
||||
}
|
||||
}
|
||||
into("x86") {
|
||||
from(rootProject.file("native/out/x86")) {
|
||||
include("busybox", "magiskboot", "magiskinit", "magisk")
|
||||
rename { if (it == "magisk") "libmagisk32.so" else "lib$it.so" }
|
||||
}
|
||||
from(rootProject.file("native/out/x86_64")) {
|
||||
include("magisk")
|
||||
rename { if (it == "magisk") "libmagisk64.so" else "lib$it.so" }
|
||||
}
|
||||
}
|
||||
onlyIf {
|
||||
if (inputs.sourceFiles.files.size != 10)
|
||||
throw StopExecutionException("Please build binaries first! (./build.py binary)")
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
val createStubLibs by tasks.registering {
|
||||
dependsOn(syncLibs)
|
||||
doLast {
|
||||
val arm64 = project.file("src/main/jniLibs/arm64-v8a/libstub.so")
|
||||
arm64.parentFile.mkdirs()
|
||||
arm64.createNewFile()
|
||||
val x64 = project.file("src/main/jniLibs/x86_64/libstub.so")
|
||||
x64.parentFile.mkdirs()
|
||||
x64.createNewFile()
|
||||
}
|
||||
}
|
||||
|
||||
val syncAssets by tasks.registering(Sync::class) {
|
||||
dependsOn(createStubLibs)
|
||||
inputs.property("version", Config.version)
|
||||
inputs.property("versionCode", Config.versionCode)
|
||||
into("src/main/assets")
|
||||
from(rootProject.file("scripts")) {
|
||||
include("util_functions.sh", "boot_patch.sh", "uninstaller.sh", "addon.d.sh")
|
||||
}
|
||||
into("chromeos") {
|
||||
from(rootProject.file("tools/futility"))
|
||||
from(rootProject.file("tools/keys")) {
|
||||
include("kernel_data_key.vbprivk", "kernel.keyblock")
|
||||
}
|
||||
}
|
||||
filesMatching("**/util_functions.sh") {
|
||||
filter {
|
||||
it.replace("#MAGISK_VERSION_STUB",
|
||||
"MAGISK_VER='${Config.version}'\n" +
|
||||
"MAGISK_VER_CODE=${Config.versionCode}")
|
||||
}
|
||||
filter<FixCrLfFilter>("eol" to FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
}
|
||||
}
|
||||
|
||||
val syncResources by tasks.registering(Sync::class) {
|
||||
dependsOn(syncAssets)
|
||||
into("src/main/resources/META-INF/com/google/android")
|
||||
from(rootProject.file("scripts/update_binary.sh")) {
|
||||
rename { "update-binary" }
|
||||
}
|
||||
from(rootProject.file("scripts/flash_script.sh")) {
|
||||
rename { "updater-script" }
|
||||
}
|
||||
}
|
||||
|
||||
tasks["preBuild"]?.dependsOn(syncResources)
|
||||
|
||||
android.applicationVariants.all {
|
||||
val keysDir = rootProject.file("tools/keys")
|
||||
@@ -125,13 +201,13 @@ dependencies {
|
||||
implementation("${bindingAdapter}:${vBAdapt}")
|
||||
implementation("${bindingAdapter}-recyclerview:${vBAdapt}")
|
||||
|
||||
val vMarkwon = "4.6.0"
|
||||
val vMarkwon = "4.6.1"
|
||||
implementation("io.noties.markwon:core:${vMarkwon}")
|
||||
implementation("io.noties.markwon:html:${vMarkwon}")
|
||||
implementation("io.noties.markwon:image:${vMarkwon}")
|
||||
implementation("com.caverock:androidsvg:1.4")
|
||||
|
||||
val vLibsu = "3.0.2"
|
||||
val vLibsu = "3.1.1"
|
||||
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
|
||||
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
||||
|
||||
@@ -158,7 +234,7 @@ dependencies {
|
||||
implementation("com.squareup.moshi:moshi:${vMoshi}")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
|
||||
|
||||
val vRoom = "2.3.0-alpha04"
|
||||
val vRoom = "2.3.0-beta01"
|
||||
implementation("androidx.room:room-runtime:${vRoom}")
|
||||
implementation("androidx.room:room-ktx:${vRoom}")
|
||||
kapt("androidx.room:room-compiler:${vRoom}")
|
||||
@@ -167,17 +243,16 @@ dependencies {
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
|
||||
|
||||
implementation("androidx.biometric:biometric:1.0.1")
|
||||
implementation("androidx.biometric:biometric:1.1.0")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.browser:browser:1.3.0")
|
||||
implementation("androidx.preference:preference:1.1.1")
|
||||
implementation("androidx.recyclerview:recyclerview:1.1.0")
|
||||
implementation("androidx.fragment:fragment-ktx:1.2.5")
|
||||
implementation("androidx.work:work-runtime-ktx:2.4.0")
|
||||
implementation("androidx.transition:transition:1.3.1")
|
||||
implementation("androidx.work:work-runtime-ktx:2.5.0")
|
||||
implementation("androidx.transition:transition:1.4.0")
|
||||
implementation("androidx.multidex:multidex:2.0.1")
|
||||
implementation("androidx.core:core-ktx:1.3.2")
|
||||
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.0.0")
|
||||
implementation("com.google.android.material:material:1.2.1")
|
||||
implementation("com.google.android.material:material:1.3.0")
|
||||
}
|
||||
|
17
app/proguard-rules.pro
vendored
17
app/proguard-rules.pro
vendored
@@ -18,16 +18,10 @@
|
||||
|
||||
# Kotlin
|
||||
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
||||
public static void checkExpressionValueIsNotNull(...);
|
||||
public static void checkNotNullExpressionValue(...);
|
||||
public static void checkReturnedValueIsNotNull(...);
|
||||
public static void checkFieldIsNotNull(...);
|
||||
public static void checkParameterIsNotNull(...);
|
||||
public static void check*(...);
|
||||
public static void throw*(...);
|
||||
}
|
||||
|
||||
# Stubs
|
||||
-keep class a.* { *; }
|
||||
|
||||
# Snet
|
||||
-keepclassmembers class com.topjohnwu.magisk.ui.safetynet.SafetyNetHelper { *; }
|
||||
-keep,allowobfuscation interface com.topjohnwu.magisk.ui.safetynet.SafetyNetHelper$Callback
|
||||
@@ -35,14 +29,17 @@
|
||||
void onResponse(org.json.JSONObject);
|
||||
}
|
||||
|
||||
# Stub
|
||||
-keep class com.topjohnwu.magisk.core.App { <init>(java.lang.Object); }
|
||||
|
||||
# Strip Timber verbose and debug logging
|
||||
-assumenosideeffects class timber.log.Timber.Tree {
|
||||
-assumenosideeffects class timber.log.Timber$Tree {
|
||||
public void v(**);
|
||||
public void d(**);
|
||||
}
|
||||
|
||||
# Excessive obfuscation
|
||||
-repackageclasses
|
||||
-repackageclasses 'a'
|
||||
-allowaccessmodification
|
||||
|
||||
# QOL
|
||||
|
@@ -1,17 +1,27 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.topjohnwu.shared">
|
||||
package="com.topjohnwu.shared"
|
||||
android:installLocation="internalOnly">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission
|
||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
|
||||
<application
|
||||
android:label="Magisk Manager"
|
||||
android:installLocation="internalOnly"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:allowBackup="false"
|
||||
android:label="Magisk"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
tools:ignore="UnusedAttribute">
|
||||
</application>
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
</manifest>
|
||||
|
@@ -1,7 +1,10 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
@@ -10,20 +13,36 @@ import com.topjohnwu.magisk.FileProvider;
|
||||
import java.io.File;
|
||||
|
||||
public class APKInstall {
|
||||
|
||||
public static Intent installIntent(Context c, File apk) {
|
||||
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
intent.setData(FileProvider.getUriForFile(c, c.getPackageName() + ".provider", apk));
|
||||
} else {
|
||||
//noinspection ResultOfMethodCallIgnored SetWorldReadable
|
||||
apk.setReadable(true, false);
|
||||
intent.setData(Uri.fromFile(apk));
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static void install(Context c, File apk) {
|
||||
c.startActivity(installIntent(c, apk));
|
||||
}
|
||||
|
||||
public static Intent installIntent(Context c, File apk) {
|
||||
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
||||
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
install.setData(FileProvider.getUriForFile(c, c.getPackageName() + ".provider", apk));
|
||||
} else {
|
||||
apk.setReadable(true, false);
|
||||
install.setData(Uri.fromFile(apk));
|
||||
}
|
||||
return install;
|
||||
public static void registerInstallReceiver(Context c, BroadcastReceiver r) {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addDataScheme("package");
|
||||
c.getApplicationContext().registerReceiver(r, filter);
|
||||
}
|
||||
|
||||
public static void installHideResult(Activity c, File apk) {
|
||||
Intent intent = installIntent(c, apk);
|
||||
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
|
||||
c.startActivityForResult(intent, 0); // Ignore result, use install receiver
|
||||
}
|
||||
}
|
||||
|
@@ -3,21 +3,18 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.topjohnwu.magisk">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
|
||||
|
||||
<application
|
||||
android:name=".core.App"
|
||||
android:extractNativeLibs="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:name="a.e"
|
||||
android:allowBackup="false"
|
||||
android:multiArch="true"
|
||||
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
|
||||
|
||||
<!-- Splash -->
|
||||
<activity
|
||||
android:name="a.c"
|
||||
android:name=".core.SplashActivity"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@@ -30,27 +27,27 @@
|
||||
</activity>
|
||||
|
||||
<!-- Main -->
|
||||
<activity android:name="a.b" />
|
||||
<activity android:name=".ui.MainActivity" />
|
||||
|
||||
<!-- Superuser -->
|
||||
<activity
|
||||
android:name="a.m"
|
||||
android:name=".ui.surequest.SuRequestActivity"
|
||||
android:directBootAware="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="false"
|
||||
tools:ignore="AppLinkUrlError">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Receiver -->
|
||||
<receiver
|
||||
android:name="a.h"
|
||||
android:directBootAware="true">
|
||||
android:name=".core.Receiver"
|
||||
android:directBootAware="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.REBOOT" />
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
@@ -62,16 +59,15 @@
|
||||
</receiver>
|
||||
|
||||
<!-- DownloadService -->
|
||||
<service android:name="a.j" />
|
||||
<service android:name=".core.download.DownloadService" />
|
||||
|
||||
<!-- FileProvider -->
|
||||
<provider
|
||||
android:name="a.p"
|
||||
android:name=".core.Provider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:directBootAware="true"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
</provider>
|
||||
android:grantUriPermissions="true" />
|
||||
|
||||
<!-- Hardcode GMS version -->
|
||||
<meta-data
|
||||
@@ -82,16 +78,12 @@
|
||||
<provider
|
||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||
android:authorities="${applicationId}.workmanager-init"
|
||||
tools:node="remove" />
|
||||
tools:node="remove"
|
||||
tools:ignore="ExportedContentProvider" />
|
||||
|
||||
<!-- We don't invalidate Room -->
|
||||
<service
|
||||
android:name="androidx.room.MultiInstanceInvalidationService"
|
||||
tools:node="remove"/>
|
||||
|
||||
<!-- We don't use Device Credentials -->
|
||||
<activity
|
||||
android:name="androidx.biometric.DeviceCredentialHandlerActivity"
|
||||
tools:node="remove" />
|
||||
|
||||
</application>
|
||||
|
@@ -1,32 +0,0 @@
|
||||
@file:JvmName("a")
|
||||
package a
|
||||
|
||||
import com.topjohnwu.magisk.core.App
|
||||
import com.topjohnwu.magisk.core.Provider
|
||||
import com.topjohnwu.magisk.core.Receiver
|
||||
import com.topjohnwu.magisk.core.SplashActivity
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||
import com.topjohnwu.signing.SignBoot
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
SignBoot.main(args)
|
||||
}
|
||||
|
||||
class b : MainActivity()
|
||||
|
||||
class c : SplashActivity()
|
||||
|
||||
class e : App {
|
||||
constructor() : super()
|
||||
constructor(o: Any) : super(o)
|
||||
}
|
||||
|
||||
class h : Receiver()
|
||||
|
||||
class j : DownloadService()
|
||||
|
||||
class m : SuRequestActivity()
|
||||
|
||||
class p : Provider()
|
@@ -10,8 +10,9 @@ import androidx.multidex.MultiDex
|
||||
import androidx.work.WorkManager
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.core.utils.AppShellInit
|
||||
import com.topjohnwu.magisk.core.utils.BusyBoxInit
|
||||
import com.topjohnwu.magisk.core.utils.IODispatcherExecutor
|
||||
import com.topjohnwu.magisk.core.utils.RootInit
|
||||
import com.topjohnwu.magisk.core.utils.updateConfig
|
||||
import com.topjohnwu.magisk.di.koinModules
|
||||
import com.topjohnwu.magisk.ktx.unwrap
|
||||
@@ -19,6 +20,7 @@ import com.topjohnwu.superuser.Shell
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.context.startKoin
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
open class App() : Application() {
|
||||
@@ -31,7 +33,7 @@ open class App() : Application() {
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
Shell.setDefaultBuilder(Shell.Builder.create()
|
||||
.setFlags(Shell.FLAG_MOUNT_MASTER)
|
||||
.setInitializers(RootInit::class.java)
|
||||
.setInitializers(BusyBoxInit::class.java, AppShellInit::class.java)
|
||||
.setTimeout(2))
|
||||
Shell.EXECUTOR = IODispatcherExecutor()
|
||||
|
||||
@@ -61,12 +63,18 @@ open class App() : Application() {
|
||||
val wrapped = impl.wrap()
|
||||
super.attachBaseContext(wrapped)
|
||||
|
||||
val info = base.applicationInfo
|
||||
val libDir = runCatching {
|
||||
info.javaClass.getDeclaredField("secondaryNativeLibraryDir").get(info) as String?
|
||||
}.getOrNull() ?: info.nativeLibraryDir
|
||||
Const.NATIVE_LIB_DIR = File(libDir)
|
||||
|
||||
// Normal startup
|
||||
startKoin {
|
||||
androidContext(wrapped)
|
||||
modules(koinModules)
|
||||
}
|
||||
ResMgr.init(impl)
|
||||
AssetHack.init(impl)
|
||||
app.registerActivityLifecycleCallbacks(ForegroundTracker)
|
||||
WorkManager.initialize(impl.wrapJob(), androidx.work.Configuration.Builder().build())
|
||||
}
|
||||
|
@@ -1,13 +1,31 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Process
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import java.io.File
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object Const {
|
||||
|
||||
val CPU_ABI: String
|
||||
val CPU_ABI_32: String
|
||||
|
||||
init {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
CPU_ABI = Build.SUPPORTED_ABIS[0]
|
||||
CPU_ABI_32 = Build.SUPPORTED_32_BIT_ABIS.firstOrNull() ?: CPU_ABI
|
||||
} else {
|
||||
CPU_ABI = Build.CPU_ABI
|
||||
CPU_ABI_32 = CPU_ABI
|
||||
}
|
||||
}
|
||||
|
||||
// Paths
|
||||
lateinit var MAGISKTMP: String
|
||||
lateinit var NATIVE_LIB_DIR: File
|
||||
val MAGISK_PATH get() = "$MAGISKTMP/modules"
|
||||
const val TMP_FOLDER_PATH = "/dev/tmp"
|
||||
const val TMPDIR = "/dev/tmp"
|
||||
const val MAGISK_LOG = "/cache/magisk.log"
|
||||
|
||||
// Versions
|
||||
@@ -19,23 +37,16 @@ object Const {
|
||||
val USER_ID = Process.myUid() / 100000
|
||||
|
||||
object Version {
|
||||
const val MIN_VERSION = "v19.0"
|
||||
const val MIN_VERCODE = 19000
|
||||
const val MIN_VERSION = "v20.4"
|
||||
const val MIN_VERCODE = 20400
|
||||
|
||||
fun atLeast_20_2() = Info.env.magiskVersionCode >= 20200 || isCanary()
|
||||
fun atLeast_20_4() = Info.env.magiskVersionCode >= 20400 || isCanary()
|
||||
fun atLeast_21_0() = Info.env.magiskVersionCode >= 21000 || isCanary()
|
||||
fun atLeast_21_2() = Info.env.magiskVersionCode >= 21200 || isCanary()
|
||||
fun isCanary() = Info.env.magiskVersionCode % 100 != 0
|
||||
}
|
||||
|
||||
object ID {
|
||||
const val FETCH_ZIP = 2
|
||||
const val SELECT_FILE = 3
|
||||
const val MAX_ACTIVITY_RESULT = 10
|
||||
|
||||
// notifications
|
||||
const val MAGISK_UPDATE_NOTIFICATION_ID = 4
|
||||
const val APK_UPDATE_NOTIFICATION_ID = 5
|
||||
const val UPDATE_NOTIFICATION_CHANNEL = "update"
|
||||
const val PROGRESS_NOTIFICATION_CHANNEL = "progress"
|
||||
@@ -46,6 +57,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 (BuildConfig.VERSION_CODE % 100 != 0) Info.remote.magisk.note
|
||||
else "https://topjohnwu.github.io/Magisk/releases/${BuildConfig.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/"
|
||||
|
@@ -14,44 +14,38 @@ import android.content.Intent
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.util.DisplayMetrics
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.utils.refreshLocale
|
||||
import com.topjohnwu.magisk.core.utils.updateConfig
|
||||
import com.topjohnwu.magisk.ktx.forceGetDeclaredField
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||
|
||||
fun AssetManager.addAssetPath(path: String) {
|
||||
DynAPK.addAssetPath(this, path)
|
||||
}
|
||||
|
||||
fun Context.wrap(global: Boolean = true): Context =
|
||||
if (global) GlobalResContext(this) else ResContext(this)
|
||||
fun Context.wrap(inject: Boolean = false): Context =
|
||||
if (inject) ReInjectedContext(this) else InjectedContext(this)
|
||||
|
||||
fun Context.wrapJob(): Context = object : GlobalResContext(this) {
|
||||
fun Context.wrapJob(): Context = object : InjectedContext(this) {
|
||||
|
||||
override fun getApplicationContext(): Context {
|
||||
return this
|
||||
}
|
||||
override fun getApplicationContext() = this
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
override fun getSystemService(name: String): Any? {
|
||||
return if (!isRunningAsStub) super.getSystemService(name) else
|
||||
when (name) {
|
||||
Context.JOB_SCHEDULER_SERVICE ->
|
||||
JobSchedulerWrapper(super.getSystemService(name) as JobScheduler)
|
||||
else -> super.getSystemService(name)
|
||||
return super.getSystemService(name).let {
|
||||
when {
|
||||
!isRunningAsStub -> it
|
||||
name == JOB_SCHEDULER_SERVICE -> JobSchedulerWrapper(it as JobScheduler)
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Class<*>.cmp(pkg: String): ComponentName {
|
||||
val name = ClassMap[this].name
|
||||
return ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
|
||||
}
|
||||
fun Class<*>.cmp(pkg: String) =
|
||||
ComponentName(pkg, Info.stub?.classToComponent?.get(name) ?: name)
|
||||
|
||||
inline fun <reified T> Activity.redirect() = Intent(intent)
|
||||
.setComponent(T::class.java.cmp(packageName))
|
||||
@@ -59,34 +53,27 @@ inline fun <reified T> Activity.redirect() = Intent(intent)
|
||||
|
||||
inline fun <reified T> Context.intent() = Intent().setComponent(T::class.java.cmp(packageName))
|
||||
|
||||
private open class GlobalResContext(base: Context) : ContextWrapper(base) {
|
||||
open val mRes: Resources get() = ResMgr.resource
|
||||
|
||||
override fun getResources(): Resources {
|
||||
return mRes
|
||||
}
|
||||
|
||||
override fun getClassLoader(): ClassLoader {
|
||||
return javaClass.classLoader!!
|
||||
}
|
||||
|
||||
private open class InjectedContext(base: Context) : ContextWrapper(base) {
|
||||
open val res: Resources get() = AssetHack.resource
|
||||
override fun getAssets(): AssetManager = res.assets
|
||||
override fun getResources() = res
|
||||
override fun getClassLoader() = javaClass.classLoader!!
|
||||
override fun createConfigurationContext(config: Configuration): Context {
|
||||
return ResContext(super.createConfigurationContext(config))
|
||||
return super.createConfigurationContext(config).wrap(true)
|
||||
}
|
||||
}
|
||||
|
||||
private class ResContext(base: Context) : GlobalResContext(base) {
|
||||
override val mRes by lazy { base.resources.patch() }
|
||||
|
||||
private class ReInjectedContext(base: Context) : InjectedContext(base) {
|
||||
override val res by lazy { base.resources.patch() }
|
||||
private fun Resources.patch(): Resources {
|
||||
updateConfig()
|
||||
if (isRunningAsStub)
|
||||
assets.addAssetPath(ResMgr.apk)
|
||||
assets.addAssetPath(AssetHack.apk)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
object ResMgr {
|
||||
object AssetHack {
|
||||
|
||||
lateinit var resource: Resources
|
||||
lateinit var apk: String
|
||||
@@ -101,62 +88,39 @@ object ResMgr {
|
||||
apk = context.packageResourcePath
|
||||
}
|
||||
}
|
||||
|
||||
fun newResource(): Resources {
|
||||
val asset = AssetManager::class.java.newInstance()
|
||||
asset.addAssetPath(apk)
|
||||
val config = Configuration(resource.configuration)
|
||||
val metrics = DisplayMetrics()
|
||||
metrics.setTo(resource.displayMetrics)
|
||||
return Resources(asset, metrics, config)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(28)
|
||||
private class JobSchedulerWrapper(private val base: JobScheduler) : JobScheduler() {
|
||||
|
||||
override fun schedule(job: JobInfo): Int {
|
||||
return base.schedule(job.patch())
|
||||
}
|
||||
|
||||
override fun enqueue(job: JobInfo, work: JobWorkItem): Int {
|
||||
return base.enqueue(job.patch(), work)
|
||||
}
|
||||
|
||||
override fun cancel(jobId: Int) {
|
||||
base.cancel(jobId)
|
||||
}
|
||||
|
||||
override fun cancelAll() {
|
||||
base.cancelAll()
|
||||
}
|
||||
|
||||
override fun getAllPendingJobs(): List<JobInfo> {
|
||||
return base.allPendingJobs
|
||||
}
|
||||
|
||||
override fun getPendingJob(jobId: Int): JobInfo? {
|
||||
return base.getPendingJob(jobId)
|
||||
}
|
||||
|
||||
override fun schedule(job: JobInfo) = base.schedule(job.patch())
|
||||
override fun enqueue(job: JobInfo, work: JobWorkItem) = base.enqueue(job.patch(), work)
|
||||
override fun cancel(jobId: Int) = base.cancel(jobId)
|
||||
override fun cancelAll() = base.cancelAll()
|
||||
override fun getAllPendingJobs(): List<JobInfo> = base.allPendingJobs
|
||||
override fun getPendingJob(jobId: Int) = base.getPendingJob(jobId)
|
||||
private fun JobInfo.patch(): JobInfo {
|
||||
// We need to swap out the service of JobInfo
|
||||
val name = service.className
|
||||
val component = ComponentName(
|
||||
service.packageName,
|
||||
Info.stubChk.classToComponent[name] ?: name
|
||||
)
|
||||
// Swap out the service of JobInfo
|
||||
val component = service.run {
|
||||
ComponentName(packageName,
|
||||
Info.stub?.classToComponent?.get(className) ?: className)
|
||||
}
|
||||
javaClass.getDeclaredField("service").apply {
|
||||
isAccessible = true
|
||||
}.set(this, component)
|
||||
|
||||
javaClass.forceGetDeclaredField("service")?.set(this, component)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
private object ClassMap {
|
||||
|
||||
private val map = mapOf(
|
||||
App::class.java to a.e::class.java,
|
||||
MainActivity::class.java to a.b::class.java,
|
||||
SplashActivity::class.java to a.c::class.java,
|
||||
Receiver::class.java to a.h::class.java,
|
||||
DownloadService::class.java to a.j::class.java,
|
||||
SuRequestActivity::class.java to a.m::class.java
|
||||
)
|
||||
|
||||
operator fun get(c: Class<*>) = map.getOrElse(c) { c }
|
||||
}
|
||||
|
||||
// Keep a reference to these resources to prevent it from
|
||||
// being removed when running "remove unused resources"
|
||||
val shouldKeepResources = listOf(
|
||||
|
@@ -1,41 +1,45 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.os.Build
|
||||
import androidx.databinding.ObservableBoolean
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import com.topjohnwu.magisk.core.utils.net.NetworkObserver
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.utils.CachedValue
|
||||
import com.topjohnwu.magisk.ktx.getProperty
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils.fastCmd
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||
import java.io.FileInputStream
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
val isRunningAsStub get() = Info.stub != null
|
||||
|
||||
object Info {
|
||||
|
||||
val envRef = CachedValue { loadState() }
|
||||
|
||||
@JvmStatic val env by envRef
|
||||
|
||||
var stub: DynAPK.Data? = null
|
||||
val stubChk: DynAPK.Data
|
||||
get() = stub as DynAPK.Data
|
||||
|
||||
var remote = UpdateInfo()
|
||||
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
|
||||
}
|
||||
|
||||
// Device state
|
||||
var crypto = ""
|
||||
@JvmStatic var isSAR = false
|
||||
@JvmStatic var isAB = false
|
||||
@JvmStatic val env by lazy { loadState() }
|
||||
@JvmField var isSAR = false
|
||||
@JvmField var isAB = false
|
||||
@JvmField val isVirtualAB = getProperty("ro.virtual_ab.enabled", "false") == "true"
|
||||
@JvmStatic val isFDE get() = crypto == "block"
|
||||
@JvmStatic var ramdisk = false
|
||||
@JvmStatic var hasGMS = true
|
||||
@JvmStatic var isPixel = false
|
||||
@JvmStatic val cryptoText get() = crypto.capitalize(Locale.US)
|
||||
@JvmField var ramdisk = false
|
||||
@JvmField var hasGMS = true
|
||||
@JvmField val isPixel = Build.BRAND == "google"
|
||||
@JvmField val isEmulator = getProperty("ro.kernel.qemu", "0") == "1"
|
||||
var crypto = ""
|
||||
var noDataExec = false
|
||||
|
||||
val isConnected by lazy {
|
||||
ObservableBoolean(false).also { field ->
|
||||
@@ -47,14 +51,12 @@ object Info {
|
||||
|
||||
val isNewReboot by lazy {
|
||||
try {
|
||||
FileInputStream("/proc/sys/kernel/random/boot_id").bufferedReader().use {
|
||||
val id = it.readLine()
|
||||
if (id != Config.bootId) {
|
||||
Config.bootId = id
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
val id = File("/proc/sys/kernel/random/boot_id").readText()
|
||||
if (id != Config.bootId) {
|
||||
Config.bootId = id
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
false
|
||||
@@ -73,8 +75,8 @@ object Info {
|
||||
hide: Boolean = false
|
||||
) {
|
||||
val magiskHide get() = Config.magiskHide
|
||||
val magiskVersionCode = when (code) {
|
||||
in Int.MIN_VALUE..Const.Version.MIN_VERCODE -> -1
|
||||
val magiskVersionCode = when {
|
||||
code < Const.Version.MIN_VERCODE -> -1
|
||||
else -> if (Shell.rootAccess()) code else -1
|
||||
}
|
||||
val isUnsupported = code > 0 && code < Const.Version.MIN_VERCODE
|
||||
|
@@ -1,32 +1,30 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
open class SplashActivity : Activity() {
|
||||
open class SplashActivity : BaseActivity() {
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base.wrap())
|
||||
}
|
||||
private val latch = CountDownLatch(1)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(R.style.SplashTheme)
|
||||
super.onCreate(savedInstanceState)
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
initAndStart()
|
||||
}
|
||||
// Pre-initialize root shell
|
||||
Shell.getShell(null) { initAndStart() }
|
||||
}
|
||||
|
||||
private fun handleRepackage(pkg: String?) {
|
||||
@@ -40,13 +38,26 @@ open class SplashActivity : Activity() {
|
||||
if (Config.suManager.isNotEmpty())
|
||||
Config.suManager = ""
|
||||
pkg ?: return
|
||||
Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec()
|
||||
if (!Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec().isSuccess)
|
||||
uninstallApp(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAndStart() {
|
||||
// Pre-initialize root shell
|
||||
Shell.getShell()
|
||||
if (isRunningAsStub && !Shell.rootAccess()) {
|
||||
runOnUiThread {
|
||||
MagiskDialog(this)
|
||||
.applyTitle(R.string.unsupport_nonroot_stub_title)
|
||||
.applyMessage(R.string.unsupport_nonroot_stub_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
titleRes = R.string.install
|
||||
onClick { HideAPK.restore(this@SplashActivity) }
|
||||
}
|
||||
.cancellable(false)
|
||||
.reveal()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)
|
||||
|
||||
@@ -60,11 +71,21 @@ open class SplashActivity : Activity() {
|
||||
get<NetworkService>()
|
||||
|
||||
DONE = true
|
||||
|
||||
redirect<MainActivity>().also { startActivity(it) }
|
||||
startActivity(redirect<MainActivity>())
|
||||
finish()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun uninstallApp(pkg: String) {
|
||||
val uri = Uri.Builder().scheme("package").opaquePart(pkg).build()
|
||||
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, uri)
|
||||
intent.putExtra(Intent.EXTRA_RETURN_RESULT, true)
|
||||
startActivityForResult(intent) { _, _ ->
|
||||
latch.countDown()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
companion object {
|
||||
var DONE = false
|
||||
}
|
||||
|
@@ -1,13 +1,11 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import androidx.work.*
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.inject
|
||||
import java.util.concurrent.TimeUnit
|
||||
@@ -18,20 +16,15 @@ class UpdateCheckService(context: Context, workerParams: WorkerParameters)
|
||||
private val svc: NetworkService by inject()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
// Make sure shell initializer was ran
|
||||
withContext(Dispatchers.IO) {
|
||||
Shell.getShell()
|
||||
}
|
||||
return svc.fetchUpdate()?.let {
|
||||
if (BuildConfig.VERSION_CODE < it.app.versionCode)
|
||||
return svc.fetchUpdate()?.run {
|
||||
if (Info.env.isActive && BuildConfig.VERSION_CODE < magisk.versionCode)
|
||||
Notifications.managerUpdate(applicationContext)
|
||||
else if (Info.env.isActive && Info.env.magiskVersionCode < it.magisk.versionCode)
|
||||
Notifications.magiskUpdate(applicationContext)
|
||||
Result.success()
|
||||
} ?: Result.failure()
|
||||
}
|
||||
|
||||
companion object {
|
||||
@SuppressLint("NewApi")
|
||||
fun schedule(context: Context) {
|
||||
if (Config.checkUpdate) {
|
||||
val constraints = Constraints.Builder()
|
||||
|
@@ -14,7 +14,6 @@ import androidx.collection.SparseArrayCompat
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||
import com.topjohnwu.magisk.core.wrap
|
||||
import com.topjohnwu.magisk.ktx.set
|
||||
@@ -26,6 +25,13 @@ typealias ActivityResultCallback = BaseActivity.(Int, Intent?) -> Unit
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
|
||||
private val resultCallbacks by lazy { SparseArrayCompat<ActivityResultCallback>() }
|
||||
private val newRequestCode: Int get() {
|
||||
var requestCode: Int
|
||||
do {
|
||||
requestCode = Random.nextInt(0, 1 shl 15)
|
||||
} while (resultCallbacks.containsKey(requestCode))
|
||||
return requestCode
|
||||
}
|
||||
|
||||
override fun applyOverrideConfiguration(config: Configuration?) {
|
||||
// Force applying our preferred local
|
||||
@@ -34,7 +40,7 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base.wrap(false))
|
||||
super.attachBaseContext(base.wrap(true))
|
||||
}
|
||||
|
||||
fun withPermission(permission: String, builder: PermissionRequestBuilder.() -> Unit) {
|
||||
@@ -49,10 +55,7 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
|
||||
request.onSuccess()
|
||||
} else {
|
||||
var requestCode: Int
|
||||
do {
|
||||
requestCode = Random.nextInt(Const.ID.MAX_ACTIVITY_RESULT + 1, 1 shl 15)
|
||||
} while (resultCallbacks.containsKey(requestCode))
|
||||
val requestCode = newRequestCode
|
||||
resultCallbacks[requestCode] = { result, _ ->
|
||||
if (result > 0)
|
||||
request.onSuccess()
|
||||
@@ -92,7 +95,8 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
fun startActivityForResult(intent: Intent, requestCode: Int, callback: ActivityResultCallback) {
|
||||
fun startActivityForResult(intent: Intent, callback: ActivityResultCallback) {
|
||||
val requestCode = newRequestCode
|
||||
resultCallbacks[requestCode] = callback
|
||||
try {
|
||||
startActivityForResult(intent, requestCode)
|
||||
|
@@ -1,31 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.download
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
sealed class Action : Parcelable {
|
||||
|
||||
sealed class Flash : Action() {
|
||||
|
||||
@Parcelize
|
||||
object Primary : Flash()
|
||||
|
||||
@Parcelize
|
||||
object Secondary : Flash()
|
||||
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
object Download : Action()
|
||||
|
||||
@Parcelize
|
||||
object Uninstall : Action()
|
||||
|
||||
@Parcelize
|
||||
object EnvFix : Action()
|
||||
|
||||
@Parcelize
|
||||
data class Patch(val fileUri: Uri) : Action()
|
||||
|
||||
}
|
@@ -8,11 +8,8 @@ import androidx.lifecycle.MutableLiveData
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.ForegroundTracker
|
||||
import com.topjohnwu.magisk.core.base.BaseService
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.checkSum
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.core.utils.ProgressInputStream
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -69,18 +66,11 @@ abstract class BaseDownloader : BaseService(), KoinComponent {
|
||||
// -- Download logic
|
||||
|
||||
private suspend fun Subject.startDownload() {
|
||||
val skip = this is Subject.Magisk && file.checkSum("MD5", magisk.md5)
|
||||
if (!skip) {
|
||||
val stream = service.fetchFile(url).toProgressStream(this)
|
||||
when (this) {
|
||||
is Subject.Module -> // Download and process on-the-fly
|
||||
stream.toModule(file, service.fetchInstaller().byteStream())
|
||||
else -> {
|
||||
withStreams(stream, file.outputStream()) { it, out -> it.copyTo(out) }
|
||||
if (this is Subject.Manager)
|
||||
handleAPK(this)
|
||||
}
|
||||
}
|
||||
val stream = service.fetchFile(url).toProgressStream(this)
|
||||
when (this) {
|
||||
is Subject.Module -> // Download and process on-the-fly
|
||||
stream.toModule(file, service.fetchInstaller().byteStream())
|
||||
is Subject.Manager -> handleAPK(this, stream)
|
||||
}
|
||||
val newId = notifyFinish(this)
|
||||
if (ForegroundTracker.hasForeground)
|
||||
|
@@ -7,11 +7,10 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.core.download.Action.*
|
||||
import com.topjohnwu.magisk.core.download.Action.Flash.Secondary
|
||||
import com.topjohnwu.magisk.core.download.Subject.*
|
||||
import com.topjohnwu.magisk.core.download.Action.Flash
|
||||
import com.topjohnwu.magisk.core.download.Subject.Manager
|
||||
import com.topjohnwu.magisk.core.download.Subject.Module
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
import com.topjohnwu.magisk.core.tasks.EnvFixTask
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||
import com.topjohnwu.magisk.utils.APKInstall
|
||||
import kotlin.random.Random.Default.nextInt
|
||||
@@ -22,25 +21,12 @@ open class DownloadService : BaseDownloader() {
|
||||
private val context get() = this
|
||||
|
||||
override suspend fun onFinish(subject: Subject, id: Int) = when (subject) {
|
||||
is Magisk -> subject.onFinish(id)
|
||||
is Module -> subject.onFinish(id)
|
||||
is Manager -> subject.onFinish(id)
|
||||
}
|
||||
|
||||
private suspend fun Magisk.onFinish(id: Int) = when (val action = action) {
|
||||
Uninstall -> FlashFragment.uninstall(file, id)
|
||||
EnvFix -> {
|
||||
remove(id)
|
||||
EnvFixTask(file).exec()
|
||||
Unit
|
||||
}
|
||||
is Patch -> FlashFragment.patch(file, action.fileUri, id)
|
||||
is Flash -> FlashFragment.flash(file, action is Secondary, id)
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
private fun Module.onFinish(id: Int) = when (action) {
|
||||
is Flash -> FlashFragment.install(file, id)
|
||||
Flash -> FlashFragment.install(file, id)
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
@@ -53,22 +39,13 @@ open class DownloadService : BaseDownloader() {
|
||||
|
||||
override fun Notification.Builder.setIntent(subject: Subject)
|
||||
= when (subject) {
|
||||
is Magisk -> setIntent(subject)
|
||||
is Module -> setIntent(subject)
|
||||
is Manager -> setIntent(subject)
|
||||
}
|
||||
|
||||
private fun Notification.Builder.setIntent(subject: Magisk)
|
||||
= when (val action = subject.action) {
|
||||
Uninstall -> setContentIntent(FlashFragment.uninstallIntent(context, subject.file))
|
||||
is Flash -> setContentIntent(FlashFragment.flashIntent(context, subject.file, action is Secondary))
|
||||
is Patch -> setContentIntent(FlashFragment.patchIntent(context, subject.file, action.fileUri))
|
||||
else -> setContentIntent(Intent())
|
||||
}
|
||||
|
||||
private fun Notification.Builder.setIntent(subject: Module)
|
||||
= when (subject.action) {
|
||||
is Flash -> setContentIntent(FlashFragment.installIntent(context, subject.file))
|
||||
Flash -> setContentIntent(FlashFragment.installIntent(context, subject.file))
|
||||
else -> setContentIntent(Intent())
|
||||
}
|
||||
|
||||
|
@@ -2,19 +2,22 @@ package com.topjohnwu.magisk.core.download
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.ktx.relaunchApp
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
private fun Context.patch(apk: File) {
|
||||
val patched = File(apk.parent, "patched.apk")
|
||||
HideAPK.patch(this, apk.path, patched.path, packageName, applicationInfo.nonLocalizedLabel)
|
||||
HideAPK.patch(this, apk, patched, packageName, applicationInfo.nonLocalizedLabel)
|
||||
apk.delete()
|
||||
patched.renameTo(apk)
|
||||
}
|
||||
@@ -22,30 +25,51 @@ private fun Context.patch(apk: File) {
|
||||
private fun BaseDownloader.notifyHide(id: Int) {
|
||||
update(id) {
|
||||
it.setProgress(0, 0, true)
|
||||
.setContentTitle(getString(R.string.hide_manager_title))
|
||||
.setContentTitle(getString(R.string.hide_app_title))
|
||||
.setContentText("")
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun BaseDownloader.handleAPK(subject: Subject.Manager) {
|
||||
val apk = subject.file.toFile()
|
||||
val id = subject.notifyID()
|
||||
private class DupOutputStream(
|
||||
private val o1: OutputStream,
|
||||
private val o2: OutputStream
|
||||
) : OutputStream() {
|
||||
override fun write(b: Int) {
|
||||
o1.write(b)
|
||||
o2.write(b)
|
||||
}
|
||||
override fun write(b: ByteArray?, off: Int, len: Int) {
|
||||
o1.write(b, off, len)
|
||||
o2.write(b, off, len)
|
||||
}
|
||||
override fun close() {
|
||||
o1.close()
|
||||
o2.close()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun BaseDownloader.handleAPK(subject: Subject.Manager, stream: InputStream) {
|
||||
fun write(output: OutputStream) {
|
||||
val ext = subject.externalFile.outputStream()
|
||||
val o = DupOutputStream(ext, output)
|
||||
withStreams(stream, o) { src, out -> src.copyTo(out) }
|
||||
}
|
||||
|
||||
if (isRunningAsStub) {
|
||||
// Move to upgrade location
|
||||
apk.copyTo(DynAPK.update(this), overwrite = true)
|
||||
apk.delete()
|
||||
if (Info.stubChk.version < subject.stub.versionCode) {
|
||||
notifyHide(id)
|
||||
val apk = subject.file.toFile()
|
||||
val id = subject.notifyID()
|
||||
write(DynAPK.update(this).outputStream())
|
||||
if (Info.stub!!.version < subject.stub.versionCode) {
|
||||
// Also upgrade stub
|
||||
service.fetchFile(subject.stub.link).byteStream().use { it.writeTo(apk) }
|
||||
notifyHide(id)
|
||||
service.fetchFile(subject.stub.link).byteStream().writeTo(apk)
|
||||
patch(apk)
|
||||
} else {
|
||||
// Simply relaunch the app
|
||||
stopSelf()
|
||||
relaunchApp(this)
|
||||
}
|
||||
} else if (packageName != BuildConfig.APPLICATION_ID) {
|
||||
notifyHide(id)
|
||||
patch(apk)
|
||||
} else {
|
||||
write(subject.file.outputStream())
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,9 @@
|
||||
package com.topjohnwu.magisk.core.download
|
||||
|
||||
import android.net.Uri
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.ktx.forEach
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import java.io.InputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
@@ -25,8 +26,7 @@ fun InputStream.toModule(file: Uri, installer: InputStream) {
|
||||
zout.write("#MAGISK\n".toByteArray(charset("UTF-8")))
|
||||
|
||||
var off = -1
|
||||
var entry: ZipEntry? = zin.nextEntry
|
||||
while (entry != null) {
|
||||
zin.forEach { entry ->
|
||||
if (off < 0) {
|
||||
off = entry.name.indexOf('/') + 1
|
||||
}
|
||||
@@ -38,8 +38,6 @@ fun InputStream.toModule(file: Uri, installer: InputStream) {
|
||||
zin.copyTo(zout)
|
||||
}
|
||||
}
|
||||
|
||||
entry = zin.nextEntry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ 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.ManagerJson
|
||||
import com.topjohnwu.magisk.core.model.StubJson
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
@@ -40,70 +39,26 @@ sealed class Subject : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
class Manager(
|
||||
private val app: ManagerJson = Info.remote.app,
|
||||
private val json: MagiskJson = Info.remote.magisk,
|
||||
val stub: StubJson = Info.remote.stub
|
||||
) : Subject() {
|
||||
override val action get() = Action.Download
|
||||
override val title: String get() = "MagiskManager-${app.version}(${app.versionCode})"
|
||||
override val url: String get() = app.link
|
||||
override val title: String get() = "Magisk-${json.version}(${json.versionCode})"
|
||||
override val url: String get() = json.link
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
cachedFile("manager.apk")
|
||||
}
|
||||
|
||||
val externalFile get() = MediaStoreUtils.getFile("$title.apk").uri
|
||||
}
|
||||
|
||||
abstract class Magisk : Subject() {
|
||||
|
||||
val magisk: MagiskJson = Info.remote.magisk
|
||||
|
||||
@Parcelize
|
||||
private class Internal(
|
||||
override val action: Action
|
||||
) : Magisk() {
|
||||
override val url: String get() = magisk.link
|
||||
override val title: String get() = "Magisk-${magisk.version}(${magisk.versionCode})"
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
cachedFile("magisk.zip")
|
||||
}
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
private class Uninstall : Magisk() {
|
||||
override val action get() = Action.Uninstall
|
||||
override val url: String get() = Info.remote.uninstaller.link
|
||||
override val title: String get() = "uninstall.zip"
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
cachedFile(title)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
private class Download : Magisk() {
|
||||
override val action get() = Action.Download
|
||||
override val url: String get() = magisk.link
|
||||
override val title: String get() = "Magisk-${magisk.version}(${magisk.versionCode}).zip"
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
MediaStoreUtils.getFile(title).uri
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
operator fun invoke(config: Action) = when (config) {
|
||||
Action.Download -> Download()
|
||||
Action.Uninstall -> Uninstall()
|
||||
Action.EnvFix, is Action.Flash, is Action.Patch -> Internal(config)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sealed class Action : Parcelable {
|
||||
@Parcelize
|
||||
object Flash : Action()
|
||||
|
||||
@Parcelize
|
||||
object Download : Action()
|
||||
}
|
||||
|
@@ -6,17 +6,11 @@ import kotlinx.parcelize.Parcelize
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class UpdateInfo(
|
||||
val app: ManagerJson = ManagerJson(),
|
||||
val uninstaller: UninstallerJson = UninstallerJson(),
|
||||
val magisk: MagiskJson = MagiskJson(),
|
||||
val stub: StubJson = StubJson()
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class UninstallerJson(
|
||||
val link: String = ""
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MagiskJson(
|
||||
val version: String = "",
|
||||
@@ -24,15 +18,6 @@ data class MagiskJson(
|
||||
val link: String = "",
|
||||
val note: String = "",
|
||||
val md5: String = ""
|
||||
)
|
||||
|
||||
@Parcelize
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ManagerJson(
|
||||
val version: String = "",
|
||||
val versionCode: Int = -1,
|
||||
val link: String = "",
|
||||
val note: String = ""
|
||||
) : Parcelable
|
||||
|
||||
@Parcelize
|
||||
|
@@ -1,11 +1,13 @@
|
||||
@file:SuppressLint("InlinedApi")
|
||||
|
||||
package com.topjohnwu.magisk.core.model.su
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.drawable.Drawable
|
||||
import com.topjohnwu.magisk.core.model.su.SuPolicy.Companion.INTERACTIVE
|
||||
import com.topjohnwu.magisk.ktx.getLabel
|
||||
|
||||
|
||||
data class SuPolicy(
|
||||
var uid: Int,
|
||||
val packageName: String,
|
||||
@@ -38,7 +40,7 @@ fun SuPolicy.toMap() = mapOf(
|
||||
fun Map<String, String>.toPolicy(pm: PackageManager): SuPolicy {
|
||||
val uid = get("uid")?.toIntOrNull() ?: -1
|
||||
val packageName = get("package_name").orEmpty()
|
||||
val info = pm.getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES)
|
||||
val info = pm.getApplicationInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES)
|
||||
|
||||
if (info.uid != uid)
|
||||
throw PackageManager.NameNotFoundException()
|
||||
@@ -59,7 +61,7 @@ fun Map<String, String>.toPolicy(pm: PackageManager): SuPolicy {
|
||||
fun Int.toPolicy(pm: PackageManager, policy: Int = INTERACTIVE): SuPolicy {
|
||||
val pkg = pm.getPackagesForUid(this)?.firstOrNull()
|
||||
?: throw PackageManager.NameNotFoundException()
|
||||
val info = pm.getApplicationInfo(pkg, PackageManager.GET_UNINSTALLED_PACKAGES)
|
||||
val info = pm.getApplicationInfo(pkg, PackageManager.MATCH_UNINSTALLED_PACKAGES)
|
||||
return SuPolicy(
|
||||
uid = info.uid,
|
||||
packageName = pkg,
|
||||
|
@@ -2,14 +2,13 @@ package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.displayName
|
||||
import com.topjohnwu.magisk.core.utils.unzip
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
|
||||
import com.topjohnwu.magisk.core.utils.unzip
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.KoinComponent
|
||||
@@ -25,61 +24,50 @@ open class FlashZip(
|
||||
private val logs: MutableList<String>
|
||||
): KoinComponent {
|
||||
|
||||
val context: Context by inject()
|
||||
private val installFolder = File(context.cacheDir, "flash").apply {
|
||||
if (!exists()) mkdirs()
|
||||
}
|
||||
private val tmpFile: File = File(installFolder, "install.zip")
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun unzipAndCheck(): Boolean {
|
||||
val parentFile = tmpFile.parentFile ?: return false
|
||||
tmpFile.unzip(parentFile, "META-INF/com/google/android", true)
|
||||
|
||||
val updaterScript = File(parentFile, "updater-script")
|
||||
return Shell
|
||||
.su("grep -q '#MAGISK' $updaterScript")
|
||||
.exec()
|
||||
.isSuccess
|
||||
}
|
||||
private val context: Context by inject()
|
||||
private val installDir = File(context.cacheDir, "flash")
|
||||
private lateinit var zipFile: File
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun flash(): Boolean {
|
||||
console.add("- Copying zip to temp directory")
|
||||
installDir.deleteRecursively()
|
||||
installDir.mkdirs()
|
||||
|
||||
runCatching {
|
||||
mUri.inputStream().writeTo(tmpFile)
|
||||
}.getOrElse {
|
||||
when (it) {
|
||||
is FileNotFoundException -> console.add("! Invalid Uri")
|
||||
is IOException -> console.add("! Cannot copy to cache")
|
||||
zipFile = if (mUri.scheme == "file") {
|
||||
mUri.toFile()
|
||||
} else {
|
||||
File(installDir, "install.zip").also {
|
||||
console.add("- Copying zip to temp directory")
|
||||
try {
|
||||
mUri.inputStream().writeTo(it)
|
||||
} catch (e: IOException) {
|
||||
when (e) {
|
||||
is FileNotFoundException -> console.add("! Invalid Uri")
|
||||
else -> console.add("! Cannot copy to cache")
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
throw it
|
||||
}
|
||||
|
||||
val isMagiskModule = runCatching {
|
||||
unzipAndCheck()
|
||||
val isValid = runCatching {
|
||||
zipFile.unzip(installDir, "META-INF/com/google/android", true)
|
||||
val script = File(installDir, "updater-script")
|
||||
script.readText().contains("#MAGISK")
|
||||
}.getOrElse {
|
||||
console.add("! Unzip error")
|
||||
throw it
|
||||
}
|
||||
|
||||
if (!isMagiskModule) {
|
||||
console.add("! This zip is not a Magisk Module!")
|
||||
if (!isValid) {
|
||||
console.add("! This zip is not a Magisk module!")
|
||||
return false
|
||||
}
|
||||
|
||||
console.add("- Installing ${mUri.displayName}")
|
||||
|
||||
val parentFile = tmpFile.parent ?: return false
|
||||
|
||||
return Shell
|
||||
.su(
|
||||
"cd $parentFile",
|
||||
"BOOTMODE=true sh update-binary dummy 1 $tmpFile"
|
||||
)
|
||||
.to(console, logs)
|
||||
.exec().isSuccess
|
||||
return Shell.su("sh $installDir/update-binary dummy 1 \"$zipFile\"")
|
||||
.to(console, logs).exec().isSuccess
|
||||
}
|
||||
|
||||
open suspend fun exec() = withContext(Dispatchers.IO) {
|
||||
@@ -94,25 +82,7 @@ open class FlashZip(
|
||||
Timber.e(e)
|
||||
false
|
||||
} finally {
|
||||
Shell.su("cd /", "rm -rf ${tmpFile.parent} ${Const.TMP_FOLDER_PATH}").submit()
|
||||
Shell.su("cd /", "rm -rf $installDir ${Const.TMPDIR}").submit()
|
||||
}
|
||||
}
|
||||
|
||||
class Uninstall(
|
||||
uri: Uri,
|
||||
console: MutableList<String>,
|
||||
log: MutableList<String>
|
||||
) : FlashZip(uri, console, log) {
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
if (success) {
|
||||
UiThreadHandler.handler.postDelayed(3000) {
|
||||
Shell.su("pm uninstall " + context.packageName).exec()
|
||||
}
|
||||
}
|
||||
return success
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,38 +1,41 @@
|
||||
package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.app.Activity
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.*
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.Provider
|
||||
import com.topjohnwu.magisk.core.utils.AXML
|
||||
import com.topjohnwu.magisk.core.utils.Keygen
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.inject
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.magisk.utils.APKInstall
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.signing.JarMap
|
||||
import com.topjohnwu.signing.SignApk
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.lang.ref.WeakReference
|
||||
import java.security.SecureRandom
|
||||
|
||||
object HideAPK {
|
||||
|
||||
private const val ALPHA = "abcdefghijklmnopqrstuvwxyz"
|
||||
private const val ALPHADOTS = "$ALPHA....."
|
||||
private const val APP_NAME = "Magisk Manager"
|
||||
private const val APP_NAME = "Magisk"
|
||||
private const val ANDROID_MANIFEST = "AndroidManifest.xml"
|
||||
|
||||
// Some arbitrary limit
|
||||
@@ -49,7 +52,7 @@ object HideAPK {
|
||||
var next: Char
|
||||
var prev = 0.toChar()
|
||||
for (i in 0 until len) {
|
||||
next = if (prev == '.' || prev == 0.toChar() || i == len - 1) {
|
||||
next = if (prev == '.' || i == 0 || i == len - 1) {
|
||||
ALPHA[random.nextInt(ALPHA.length)]
|
||||
} else {
|
||||
ALPHADOTS[random.nextInt(ALPHADOTS.length)]
|
||||
@@ -59,19 +62,19 @@ object HideAPK {
|
||||
}
|
||||
if (!builder.contains('.')) {
|
||||
// Pick a random index and set it as dot
|
||||
val idx = random.nextInt(len - 1)
|
||||
builder[idx] = '.'
|
||||
val idx = random.nextInt(len - 2)
|
||||
builder[idx + 1] = '.'
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun patch(
|
||||
context: Context,
|
||||
apk: String, out: String,
|
||||
apk: File, out: File,
|
||||
pkg: String, label: CharSequence
|
||||
): Boolean {
|
||||
try {
|
||||
val jar = JarMap.open(apk)
|
||||
val jar = JarMap.open(apk, true)
|
||||
val je = jar.getJarEntry(ANDROID_MANIFEST)
|
||||
val xml = AXML(jar.getRawData(je))
|
||||
|
||||
@@ -90,103 +93,76 @@ object HideAPK {
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun patchAndHide(context: Context, label: String): Boolean {
|
||||
val dlStub = !isRunningAsStub && SDK_INT >= 28 && Const.Version.atLeast_20_2()
|
||||
val src = if (dlStub) {
|
||||
val stub = File(context.cacheDir, "stub.apk")
|
||||
try {
|
||||
svc.fetchFile(Info.remote.stub.link).byteStream().use {
|
||||
it.writeTo(stub)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
stub.path
|
||||
} else {
|
||||
context.packageCodePath
|
||||
}
|
||||
private class WaitPackageReceiver(
|
||||
private val pkg: String,
|
||||
activity: Activity
|
||||
) : BroadcastReceiver() {
|
||||
|
||||
// Generate a new random package name and signature
|
||||
val repack = File(context.cacheDir, "patched.apk")
|
||||
val pkg = genPackageName()
|
||||
Config.keyStoreRaw = ""
|
||||
private val activity = WeakReference(activity)
|
||||
|
||||
if (!patch(context, src, repack.path, pkg, label))
|
||||
return false
|
||||
|
||||
// Install the application
|
||||
if (!Shell.su("adb_pm_install $repack").exec().isSuccess)
|
||||
return false
|
||||
|
||||
context.apply {
|
||||
val intent = packageManager.getLaunchIntentForPackage(pkg) ?: return false
|
||||
Config.suManager = pkg
|
||||
private fun launchApp(): Unit = activity.get()?.run {
|
||||
val intent = packageManager.getLaunchIntentForPackage(pkg) ?: return
|
||||
Config.suManager = if (pkg == APPLICATION_ID) "" else pkg
|
||||
grantUriPermission(pkg, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
grantUriPermission(pkg, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
intent.putExtra(Const.Key.PREV_PKG, packageName)
|
||||
startActivity(intent)
|
||||
}
|
||||
finish()
|
||||
} ?: Unit
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun hide(context: Context, label: String) {
|
||||
val dialog = ProgressDialog.show(context, context.getString(R.string.hide_manager_title), "", true)
|
||||
GlobalScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
patchAndHide(context, label)
|
||||
}
|
||||
if (!result) {
|
||||
Utils.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadAndRestore(context: Context): Boolean {
|
||||
val apk = if (isRunningAsStub) {
|
||||
DynAPK.current(context)
|
||||
} else {
|
||||
File(context.cacheDir, "manager.apk").also { apk ->
|
||||
try {
|
||||
svc.fetchFile(Info.remote.app.link).byteStream().use {
|
||||
it.writeTo(apk)
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when (intent.action ?: return) {
|
||||
Intent.ACTION_PACKAGE_REPLACED, Intent.ACTION_PACKAGE_ADDED -> {
|
||||
val newPkg = intent.data?.encodedSchemeSpecificPart.orEmpty()
|
||||
if (newPkg == pkg) {
|
||||
context.unregisterReceiver(this)
|
||||
launchApp()
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Shell.su("adb_pm_install $apk").exec().isSuccess)
|
||||
return false
|
||||
}
|
||||
|
||||
context.apply {
|
||||
val intent = packageManager.getLaunchIntentForPackage(APPLICATION_ID) ?: return false
|
||||
Config.suManager = ""
|
||||
grantUriPermission(APPLICATION_ID, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
grantUriPermission(APPLICATION_ID, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
intent.putExtra(Const.Key.PREV_PKG, packageName)
|
||||
startActivity(intent)
|
||||
private suspend fun patchAndHide(activity: Activity, label: String): Boolean {
|
||||
val stub = File(activity.cacheDir, "stub.apk")
|
||||
try {
|
||||
svc.fetchFile(Info.remote.stub.link).byteStream().writeTo(stub)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
|
||||
// Generate a new random package name and signature
|
||||
val repack = File(activity.cacheDir, "patched.apk")
|
||||
val pkg = genPackageName()
|
||||
Config.keyStoreRaw = ""
|
||||
|
||||
if (!patch(activity, stub, repack, pkg, label))
|
||||
return false
|
||||
|
||||
// Install and auto launch app
|
||||
APKInstall.registerInstallReceiver(activity, WaitPackageReceiver(pkg, activity))
|
||||
if (!Shell.su("adb_pm_install $repack").exec().isSuccess)
|
||||
APKInstall.installHideResult(activity, repack)
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun restore(context: Context) {
|
||||
val dialog = ProgressDialog.show(context, context.getString(R.string.restore_img_msg), "", true)
|
||||
GlobalScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
downloadAndRestore(context)
|
||||
}
|
||||
if (!result) {
|
||||
Utils.toast(R.string.restore_manager_fail_toast, Toast.LENGTH_LONG)
|
||||
dialog.dismiss()
|
||||
}
|
||||
suspend fun hide(activity: Activity, label: String) {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
patchAndHide(activity, label)
|
||||
}
|
||||
if (!result) {
|
||||
Utils.toast(R.string.failure, Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
|
||||
fun restore(activity: Activity) {
|
||||
val apk = DynAPK.current(activity)
|
||||
APKInstall.registerInstallReceiver(activity, WaitPackageReceiver(APPLICATION_ID, activity))
|
||||
Shell.su("adb_pm_install $apk").submit {
|
||||
if (!it.isSuccess)
|
||||
APKInstall.installHideResult(activity, apk)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,23 @@
|
||||
package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.os.postDelayed
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.*
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.di.Protected
|
||||
import com.topjohnwu.magisk.events.dialog.EnvFixDialog
|
||||
import com.topjohnwu.magisk.ktx.reboot
|
||||
import com.topjohnwu.magisk.ktx.symlink
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.signing.SignBoot
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -37,156 +35,162 @@ import org.kamranzafar.jtar.TarHeader
|
||||
import org.kamranzafar.jtar.TarInputStream
|
||||
import org.kamranzafar.jtar.TarOutputStream
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.get
|
||||
import org.koin.core.inject
|
||||
import timber.log.Timber
|
||||
import java.io.*
|
||||
import java.nio.ByteBuffer
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
abstract class MagiskInstallImpl : KoinComponent {
|
||||
abstract class MagiskInstallImpl protected constructor(
|
||||
protected val console: MutableList<String> = NOPList.getInstance(),
|
||||
private val logs: MutableList<String> = NOPList.getInstance()
|
||||
) : KoinComponent {
|
||||
|
||||
protected lateinit var installDir: File
|
||||
private lateinit var srcBoot: String
|
||||
private lateinit var zipUri: Uri
|
||||
|
||||
protected val console: MutableList<String>
|
||||
private val logs: MutableList<String>
|
||||
private var tarOut: TarOutputStream? = null
|
||||
protected var installDir = File("xxx")
|
||||
private lateinit var srcBoot: File
|
||||
|
||||
private val shell = Shell.getShell()
|
||||
private val service: NetworkService by inject()
|
||||
protected val context: Context by inject()
|
||||
|
||||
protected constructor() {
|
||||
console = NOPList.getInstance()
|
||||
logs = NOPList.getInstance()
|
||||
}
|
||||
|
||||
protected constructor(zip: Uri, out: MutableList<String>, err: MutableList<String>) {
|
||||
console = out
|
||||
logs = err
|
||||
zipUri = zip
|
||||
installDir = File(get<Context>(Protected).filesDir.parent, "install")
|
||||
"rm -rf $installDir".sh()
|
||||
installDir.mkdirs()
|
||||
}
|
||||
protected val context: Context by inject(Protected)
|
||||
private val useRootDir = shell.isRoot && Info.noDataExec
|
||||
|
||||
private fun findImage(): Boolean {
|
||||
srcBoot = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
||||
if (srcBoot.isEmpty()) {
|
||||
val bootPath = "find_boot_image; echo \"\$BOOTIMAGE\"".fsh()
|
||||
if (bootPath.isEmpty()) {
|
||||
console.add("! Unable to detect target image")
|
||||
return false
|
||||
}
|
||||
console.add("- Target image: $srcBoot")
|
||||
srcBoot = SuFile(bootPath)
|
||||
console.add("- Target image: $bootPath")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun findSecondaryImage(): Boolean {
|
||||
private fun findSecondary(): Boolean {
|
||||
val slot = "echo \$SLOT".fsh()
|
||||
val target = if (slot == "_a") "_b" else "_a"
|
||||
console.add("- Target slot: $target")
|
||||
srcBoot = arrayOf(
|
||||
val bootPath = arrayOf(
|
||||
"SLOT=$target",
|
||||
"find_boot_image",
|
||||
"SLOT=$slot",
|
||||
"echo \"\$BOOTIMAGE\"").fsh()
|
||||
if (srcBoot.isEmpty()) {
|
||||
if (bootPath.isEmpty()) {
|
||||
console.add("! Unable to detect target image")
|
||||
return false
|
||||
}
|
||||
console.add("- Target image: $srcBoot")
|
||||
srcBoot = SuFile(bootPath)
|
||||
console.add("- Target image: $bootPath")
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun extractZip(): Boolean {
|
||||
val arch = if (Build.VERSION.SDK_INT >= 21) {
|
||||
val abis = listOf(*Build.SUPPORTED_ABIS)
|
||||
if (abis.contains("x86")) "x86" else "arm"
|
||||
} else {
|
||||
if (Build.CPU_ABI == "x86") "x86" else "arm"
|
||||
}
|
||||
private fun extractFiles(): Boolean {
|
||||
console.add("- Device platform: ${Const.CPU_ABI}")
|
||||
console.add("- Installing: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
|
||||
|
||||
console.add("- Device platform: " + Build.CPU_ABI)
|
||||
console.add("- Magisk Manager: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
|
||||
console.add("- Install target: ${Info.remote.magisk.version} (${Info.remote.magisk.versionCode})")
|
||||
installDir = File(context.filesDir.parent, "install")
|
||||
installDir.deleteRecursively()
|
||||
installDir.mkdirs()
|
||||
|
||||
try {
|
||||
ZipInputStream(zipUri.inputStream().buffered()).use { zi ->
|
||||
lateinit var ze: ZipEntry
|
||||
while (zi.nextEntry?.let { ze = it } != null) {
|
||||
if (ze.isDirectory)
|
||||
continue
|
||||
var name: String? = null
|
||||
val names = arrayOf("$arch/", "common/", "META-INF/com/google/android/update-binary")
|
||||
for (n in names) {
|
||||
ze.name.run {
|
||||
if (startsWith(n)) {
|
||||
name = substring(lastIndexOf('/') + 1)
|
||||
}
|
||||
}
|
||||
name ?: continue
|
||||
break
|
||||
}
|
||||
if (name == null && ze.name.startsWith("chromeos/"))
|
||||
name = ze.name
|
||||
name?.also {
|
||||
val dest = if (installDir is SuFile)
|
||||
SuFile(installDir, it)
|
||||
else
|
||||
File(installDir, it)
|
||||
dest.parentFile!!.mkdirs()
|
||||
SuFileOutputStream(dest).use { s -> zi.copyTo(s) }
|
||||
} ?: continue
|
||||
// Extract binaries
|
||||
if (isRunningAsStub) {
|
||||
val zf = ZipFile(DynAPK.current(context))
|
||||
zf.entries().asSequence().filter {
|
||||
!it.isDirectory && it.name.startsWith("lib/${Const.CPU_ABI_32}/")
|
||||
}.forEach {
|
||||
val n = it.name.substring(it.name.lastIndexOf('/') + 1)
|
||||
val name = n.substring(3, n.length - 3)
|
||||
val dest = File(installDir, name)
|
||||
zf.getInputStream(it).writeTo(dest)
|
||||
}
|
||||
} else {
|
||||
val libs = Const.NATIVE_LIB_DIR.listFiles { _, name ->
|
||||
name.startsWith("lib") && name.endsWith(".so")
|
||||
} ?: emptyArray()
|
||||
for (lib in libs) {
|
||||
val name = lib.name.substring(3, lib.name.length - 3)
|
||||
symlink(lib.path, "$installDir/$name")
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
console.add("! Cannot unzip zip")
|
||||
|
||||
// Extract scripts
|
||||
for (script in listOf("util_functions.sh", "boot_patch.sh", "addon.d.sh")) {
|
||||
val dest = File(installDir, script)
|
||||
context.assets.open(script).writeTo(dest)
|
||||
}
|
||||
// Extract chromeos tools
|
||||
File(installDir, "chromeos").mkdir()
|
||||
for (file in listOf("futility", "kernel_data_key.vbprivk", "kernel.keyblock")) {
|
||||
val name = "chromeos/$file"
|
||||
val dest = File(installDir, name)
|
||||
context.assets.open(name).writeTo(dest)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
console.add("! Unable to extract files")
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
|
||||
val init64 = SuFile.open(installDir, "magiskinit64")
|
||||
if (Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_64_BIT_ABIS.isNotEmpty()) {
|
||||
init64.renameTo(SuFile.open(installDir, "magiskinit"))
|
||||
} else {
|
||||
init64.delete()
|
||||
if (useRootDir) {
|
||||
// Move everything to tmpfs to workaround Samsung bullshit
|
||||
SuFile(Const.TMPDIR).also {
|
||||
arrayOf(
|
||||
"rm -rf $it",
|
||||
"mkdir -p $it",
|
||||
"cp_readlink $installDir $it",
|
||||
"rm -rf $installDir"
|
||||
).sh()
|
||||
installDir = it
|
||||
}
|
||||
}
|
||||
"cd $installDir; chmod 755 *".sh()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun newEntry(name: String, size: Long): TarEntry {
|
||||
// Optimization for SuFile I/O streams to skip an internal trial and error
|
||||
private fun installDirFile(name: String): File {
|
||||
return if (useRootDir)
|
||||
SuFile(installDir, name)
|
||||
else
|
||||
File(installDir, name)
|
||||
}
|
||||
|
||||
private fun InputStream.cleanPump(out: OutputStream) = withStreams(this, out) { src, _ ->
|
||||
src.copyTo(out)
|
||||
}
|
||||
|
||||
private fun newTarEntry(name: String, size: Long): TarEntry {
|
||||
console.add("-- Writing: $name")
|
||||
return TarEntry(TarHeader.createHeader(name, size, 0, false, 420 /* 0644 */))
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun handleTar(input: InputStream, output: OutputStream): OutputStream {
|
||||
private fun processTar(input: InputStream, output: OutputStream): OutputStream {
|
||||
console.add("- Processing tar file")
|
||||
val tarOut = TarOutputStream(output)
|
||||
TarInputStream(input).use { tarIn ->
|
||||
lateinit var entry: TarEntry
|
||||
|
||||
fun decompressedStream() =
|
||||
if (entry.name.contains(".lz4")) LZ4FrameInputStream(tarIn) else tarIn
|
||||
fun decompressedStream(): InputStream {
|
||||
val src = if (entry.name.endsWith(".lz4")) LZ4FrameInputStream(tarIn) else tarIn
|
||||
return object : FilterInputStream(src) {
|
||||
override fun available() = 0 /* Workaround bug in LZ4FrameInputStream */
|
||||
override fun close() { /* Never close src stream */ }
|
||||
}
|
||||
}
|
||||
|
||||
while (tarIn.nextEntry?.let { entry = it } != null) {
|
||||
if (entry.name.contains("boot.img") ||
|
||||
if (entry.name.startsWith("boot.img") ||
|
||||
(Config.recovery && entry.name.contains("recovery.img"))) {
|
||||
val name = entry.name.replace(".lz4", "")
|
||||
console.add("-- Extracting: $name")
|
||||
|
||||
val extract = File(installDir, name)
|
||||
FileOutputStream(extract).use { decompressedStream().copyTo(it) }
|
||||
val extract = installDirFile(name)
|
||||
decompressedStream().cleanPump(SuFileOutputStream.open(extract))
|
||||
} else if (entry.name.contains("vbmeta.img")) {
|
||||
val rawData = ByteArrayOutputStream().let {
|
||||
decompressedStream().copyTo(it)
|
||||
it.toByteArray()
|
||||
}
|
||||
val rawData = decompressedStream().readBytes()
|
||||
// Valid vbmeta.img should be at least 256 bytes
|
||||
if (rawData.size < 256)
|
||||
continue
|
||||
@@ -195,7 +199,7 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
// AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
|
||||
console.add("-- Patching: vbmeta.img")
|
||||
ByteBuffer.wrap(rawData).putInt(120, 3)
|
||||
tarOut.putNextEntry(newEntry("vbmeta.img", rawData.size.toLong()))
|
||||
tarOut.putNextEntry(newTarEntry("vbmeta.img", rawData.size.toLong()))
|
||||
tarOut.write(rawData)
|
||||
} else {
|
||||
console.add("-- Copying: ${entry.name}")
|
||||
@@ -203,29 +207,32 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
tarIn.copyTo(tarOut, bufferSize = 1024 * 1024)
|
||||
}
|
||||
}
|
||||
val boot = SuFile.open(installDir, "boot.img")
|
||||
val recovery = SuFile.open(installDir, "recovery.img")
|
||||
if (Config.recovery && recovery.exists() && boot.exists()) {
|
||||
// Install Magisk to recovery
|
||||
srcBoot = recovery.path
|
||||
// Repack boot image to prevent restore
|
||||
arrayOf(
|
||||
"./magiskboot unpack boot.img",
|
||||
"./magiskboot repack boot.img",
|
||||
"./magiskboot cleanup",
|
||||
"mv new-boot.img boot.img").sh()
|
||||
SuFileInputStream(boot).use {
|
||||
tarOut.putNextEntry(newEntry("boot.img", boot.length()))
|
||||
it.copyTo(tarOut)
|
||||
}
|
||||
boot.delete()
|
||||
} else {
|
||||
if (!boot.exists()) {
|
||||
console.add("! No boot image found")
|
||||
throw IOException()
|
||||
}
|
||||
srcBoot = boot.path
|
||||
}
|
||||
val boot = installDirFile("boot.img")
|
||||
val recovery = installDirFile("recovery.img")
|
||||
if (Config.recovery && recovery.exists() && boot.exists()) {
|
||||
// Install to recovery
|
||||
srcBoot = recovery
|
||||
// Repack boot image to prevent auto restore
|
||||
arrayOf(
|
||||
"cd $installDir",
|
||||
"./magiskboot unpack boot.img",
|
||||
"./magiskboot repack boot.img",
|
||||
"cat new-boot.img > boot.img",
|
||||
"./magiskboot cleanup",
|
||||
"rm -f new-boot.img",
|
||||
"cd /").sh()
|
||||
SuFileInputStream.open(boot).use {
|
||||
tarOut.putNextEntry(newTarEntry("boot.img", boot.length()))
|
||||
it.copyTo(tarOut)
|
||||
}
|
||||
boot.delete()
|
||||
} else {
|
||||
if (!boot.exists()) {
|
||||
console.add("! No boot image found")
|
||||
throw IOException()
|
||||
}
|
||||
srcBoot = boot
|
||||
}
|
||||
return tarOut
|
||||
}
|
||||
@@ -248,20 +255,22 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
val alpha = "abcdefghijklmnopqrstuvwxyz"
|
||||
val alphaNum = "$alpha${alpha.toUpperCase(Locale.ROOT)}0123456789"
|
||||
val random = SecureRandom()
|
||||
val suffix = StringBuilder()
|
||||
for (i in 1..5) {
|
||||
suffix.append(alphaNum[random.nextInt(alphaNum.length)])
|
||||
val filename = StringBuilder("magisk_patched_").run {
|
||||
for (i in 1..5) {
|
||||
append(alphaNum[random.nextInt(alphaNum.length)])
|
||||
}
|
||||
toString()
|
||||
}
|
||||
|
||||
val filename = "magisk_patched_$suffix"
|
||||
outStream = if (magic.contentEquals("ustar".toByteArray())) {
|
||||
// tar file
|
||||
outFile = MediaStoreUtils.getFile("$filename.tar", true)
|
||||
handleTar(src, outFile!!.uri.outputStream())
|
||||
processTar(src, outFile!!.uri.outputStream())
|
||||
} else {
|
||||
// Raw image
|
||||
srcBoot = File(installDir, "boot.img").path
|
||||
// raw image
|
||||
srcBoot = installDirFile("boot.img")
|
||||
console.add("- Copying image to cache")
|
||||
FileOutputStream(srcBoot).use { src.copyTo(it) }
|
||||
src.cleanPump(SuFileOutputStream.open(srcBoot))
|
||||
outFile = MediaStoreUtils.getFile("$filename.img", true)
|
||||
outFile!!.uri.outputStream()
|
||||
}
|
||||
@@ -281,13 +290,13 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
|
||||
// Output file
|
||||
try {
|
||||
val patched = SuFile.open(installDir, "new-boot.img")
|
||||
val newBoot = installDirFile("new-boot.img")
|
||||
if (outStream is TarOutputStream) {
|
||||
val name = if (srcBoot.contains("recovery")) "recovery.img" else "boot.img"
|
||||
outStream.putNextEntry(newEntry(name, patched.length()))
|
||||
val name = if (srcBoot.path.contains("recovery")) "recovery.img" else "boot.img"
|
||||
outStream.putNextEntry(newTarEntry(name, newBoot.length()))
|
||||
}
|
||||
withStreams(SuFileInputStream(patched), outStream) { src, out -> src.copyTo(out) }
|
||||
patched.delete()
|
||||
SuFileInputStream.open(newBoot).cleanPump(outStream)
|
||||
newBoot.delete()
|
||||
|
||||
console.add("")
|
||||
console.add("****************************")
|
||||
@@ -301,118 +310,107 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
return false
|
||||
}
|
||||
|
||||
// Fix up binaries
|
||||
srcBoot.delete()
|
||||
if (shell.isRoot) {
|
||||
"fix_env $installDir".sh()
|
||||
} else {
|
||||
"cp_readlink $installDir".sh()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun patchBoot(): Boolean {
|
||||
var srcNand = ""
|
||||
if ("[ -c $srcBoot ] && nanddump -f boot.img $srcBoot".sh().isSuccess) {
|
||||
srcNand = srcBoot
|
||||
srcBoot = File(installDir, "boot.img").path
|
||||
}
|
||||
|
||||
var isSigned: Boolean
|
||||
try {
|
||||
SuFileInputStream(srcBoot).use {
|
||||
isSigned = SignBoot.verifySignature(it, null)
|
||||
if (isSigned) {
|
||||
console.add("- Boot image is signed with AVB 1.0")
|
||||
var isSigned = false
|
||||
if (srcBoot.let { it !is SuFile || !it.isCharacter }) {
|
||||
try {
|
||||
SuFileInputStream.open(srcBoot).use {
|
||||
if (SignBoot.verifySignature(it, null)) {
|
||||
isSigned = true
|
||||
console.add("- Boot image is signed with AVB 1.0")
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
console.add("! Unable to check signature")
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
console.add("! Unable to check signature")
|
||||
}
|
||||
|
||||
val newBoot = installDirFile("new-boot.img")
|
||||
if (!useRootDir) {
|
||||
// Create output files before hand
|
||||
newBoot.createNewFile()
|
||||
File(installDir, "stock_boot.img").createNewFile()
|
||||
}
|
||||
|
||||
val cmds = arrayOf(
|
||||
"cd $installDir",
|
||||
"KEEPFORCEENCRYPT=${Config.keepEnc} " +
|
||||
"KEEPVERITY=${Config.keepVerity} " +
|
||||
"RECOVERYMODE=${Config.recovery} " +
|
||||
"sh boot_patch.sh $srcBoot")
|
||||
|
||||
if (!cmds.sh().isSuccess)
|
||||
return false
|
||||
}
|
||||
|
||||
if (!("KEEPFORCEENCRYPT=${Config.keepEnc} KEEPVERITY=${Config.keepVerity} " +
|
||||
"RECOVERYMODE=${Config.recovery} sh update-binary " +
|
||||
"sh boot_patch.sh $srcBoot").sh().isSuccess) {
|
||||
return false
|
||||
}
|
||||
val job = shell.newJob().add("./magiskboot cleanup", "cd /")
|
||||
|
||||
if (srcNand.isNotEmpty()) {
|
||||
srcBoot = srcNand
|
||||
}
|
||||
|
||||
val job = Shell.sh(
|
||||
"./magiskboot cleanup",
|
||||
"mv bin/busybox busybox",
|
||||
"rm -rf magisk.apk bin boot.img update-binary",
|
||||
"cd /")
|
||||
|
||||
val patched = File(installDir, "new-boot.img")
|
||||
if (isSigned) {
|
||||
console.add("- Signing boot image with verity keys")
|
||||
val signed = File(installDir, "signed.img")
|
||||
val signed = File.createTempFile("signed", ".img", context.cacheDir)
|
||||
try {
|
||||
withStreams(SuFileInputStream(patched), signed.outputStream().buffered()) {
|
||||
input, out -> SignBoot.doSignature(null, null, input, out, "/boot")
|
||||
val src = SuFileInputStream.open(newBoot).buffered()
|
||||
val out = signed.outputStream().buffered()
|
||||
withStreams(src, out) { _, _ ->
|
||||
SignBoot.doSignature(null, null, src, out, "/boot")
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
console.add("! Unable to sign image")
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
|
||||
job.add("mv -f $signed $patched")
|
||||
job.add("cat $signed > $newBoot", "rm -f $signed")
|
||||
}
|
||||
job.exec()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun copySepolicyRules(): Boolean {
|
||||
if (Info.remote.magisk.versionCode >= 21100) return true
|
||||
// Copy existing rules for migration
|
||||
"copy_sepolicy_rules".sh()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun flashBoot(): Boolean {
|
||||
if (!"direct_install $installDir $srcBoot".sh().isSuccess)
|
||||
return false
|
||||
"run_migrations".sh()
|
||||
return true
|
||||
}
|
||||
private fun flashBoot() = "direct_install $installDir $srcBoot".sh().isSuccess
|
||||
|
||||
private suspend fun postOTA(): Boolean {
|
||||
val bootctl = SuFile("/data/adb/bootctl")
|
||||
try {
|
||||
withStreams(service.fetchBootctl().byteStream(), SuFileOutputStream(bootctl)) {
|
||||
it, out -> it.copyTo(out)
|
||||
}
|
||||
val bootctl = File.createTempFile("bootctl", null, context.cacheDir)
|
||||
service.fetchBootctl().byteStream().writeTo(bootctl)
|
||||
"post_ota $bootctl".sh()
|
||||
} catch (e: IOException) {
|
||||
console.add("! Unable to download bootctl")
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
|
||||
"post_ota ${bootctl.parent}".sh()
|
||||
|
||||
console.add("***************************************")
|
||||
console.add(" Next reboot will boot to second slot!")
|
||||
console.add("***************************************")
|
||||
return true
|
||||
}
|
||||
|
||||
private fun String.sh() = Shell.sh(this).to(console, logs).exec()
|
||||
private fun Array<String>.sh() = Shell.sh(*this).to(console, logs).exec()
|
||||
private fun String.fsh() = ShellUtils.fastCmd(this)
|
||||
private fun Array<String>.fsh() = ShellUtils.fastCmd(*this)
|
||||
private fun String.sh() = shell.newJob().add(this).to(console, logs).exec()
|
||||
private fun Array<String>.sh() = shell.newJob().add(*this).to(console, logs).exec()
|
||||
private fun String.fsh() = ShellUtils.fastCmd(shell, this)
|
||||
private fun Array<String>.fsh() = ShellUtils.fastCmd(shell, *this)
|
||||
|
||||
protected fun doPatchFile(patchFile: Uri) = extractZip() && handleFile(patchFile)
|
||||
protected fun doPatchFile(patchFile: Uri) = extractFiles() && handleFile(patchFile)
|
||||
|
||||
protected fun direct() = findImage() && extractZip() && patchBoot() &&
|
||||
copySepolicyRules() && flashBoot()
|
||||
protected fun direct() = findImage() && extractFiles() && patchBoot() && flashBoot()
|
||||
|
||||
protected suspend fun secondSlot() = findSecondaryImage() && extractZip() &&
|
||||
patchBoot() && copySepolicyRules() && flashBoot() && postOTA()
|
||||
protected suspend fun secondSlot() =
|
||||
findSecondary() && extractFiles() && patchBoot() && flashBoot() && postOTA()
|
||||
|
||||
protected fun fixEnv(zip: Uri): Boolean {
|
||||
installDir = SuFile("/data/adb/magisk")
|
||||
Shell.su("rm -rf /data/adb/magisk/*").exec()
|
||||
zipUri = zip
|
||||
return extractZip() && Shell.su("fix_env").exec().isSuccess
|
||||
}
|
||||
protected fun fixEnv() = extractFiles() && "fix_env $installDir".sh().isSuccess
|
||||
|
||||
protected fun uninstall() = "run_uninstaller ${AssetHack.apk}".sh().isSuccess
|
||||
|
||||
@WorkerThread
|
||||
protected abstract suspend fun operations(): Boolean
|
||||
@@ -420,11 +418,10 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
open suspend fun exec() = withContext(Dispatchers.IO) { operations() }
|
||||
}
|
||||
|
||||
sealed class MagiskInstaller(
|
||||
file: Uri,
|
||||
abstract class MagiskInstaller(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstallImpl(file, console, logs) {
|
||||
) : MagiskInstallImpl(console, logs) {
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
@@ -438,46 +435,64 @@ sealed class MagiskInstaller(
|
||||
}
|
||||
|
||||
class Patch(
|
||||
file: Uri,
|
||||
private val uri: Uri,
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(file, console, logs) {
|
||||
) : MagiskInstaller(console, logs) {
|
||||
override suspend fun operations() = doPatchFile(uri)
|
||||
}
|
||||
|
||||
class SecondSlot(
|
||||
file: Uri,
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(file, console, logs) {
|
||||
) : MagiskInstaller(console, logs) {
|
||||
override suspend fun operations() = secondSlot()
|
||||
}
|
||||
|
||||
class Direct(
|
||||
file: Uri,
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(file, console, logs) {
|
||||
) : MagiskInstaller(console, logs) {
|
||||
override suspend fun operations() = direct()
|
||||
}
|
||||
|
||||
}
|
||||
class Emulator(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstaller(console, logs) {
|
||||
override suspend fun operations() = fixEnv()
|
||||
}
|
||||
|
||||
class EnvFixTask(
|
||||
private val zip: Uri
|
||||
) : MagiskInstallImpl() {
|
||||
override suspend fun operations() = fixEnv(zip)
|
||||
class Uninstall(
|
||||
console: MutableList<String>,
|
||||
logs: MutableList<String>
|
||||
) : MagiskInstallImpl(console, logs) {
|
||||
override suspend fun operations() = uninstall()
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(EnvFixDialog.DISMISS))
|
||||
Utils.toast(
|
||||
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
if (success)
|
||||
UiThreadHandler.handler.postDelayed(5000) { reboot() }
|
||||
return success
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
if (success) {
|
||||
UiThreadHandler.handler.postDelayed(3000) {
|
||||
Shell.su("pm uninstall ${context.packageName}").exec()
|
||||
}
|
||||
}
|
||||
return success
|
||||
}
|
||||
}
|
||||
|
||||
class FixEnv(private val callback: () -> Unit) : MagiskInstallImpl() {
|
||||
override suspend fun operations() = fixEnv()
|
||||
|
||||
override suspend fun exec(): Boolean {
|
||||
val success = super.exec()
|
||||
callback()
|
||||
Utils.toast(
|
||||
if (success) R.string.reboot_delay_toast else R.string.setup_fail,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
if (success)
|
||||
UiThreadHandler.handler.postDelayed(5000) { reboot() }
|
||||
return success
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,20 +3,16 @@
|
||||
package com.topjohnwu.magisk.core.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.util.DisplayMetrics
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.AssetHack
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.ResMgr
|
||||
import com.topjohnwu.magisk.core.addAssetPath
|
||||
import com.topjohnwu.magisk.ktx.langTagToLocale
|
||||
import com.topjohnwu.magisk.ktx.toLangTag
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
var currentLocale: Locale = Locale.getDefault()
|
||||
@@ -30,11 +26,8 @@ suspend fun availableLocales() = cachedLocales ?:
|
||||
withContext(Dispatchers.Default) {
|
||||
val compareId = R.string.app_changelog
|
||||
|
||||
// Create a completely new resource to prevent cross talk over app's configs
|
||||
val asset = AssetManager::class.java.newInstance().apply { addAssetPath(ResMgr.apk) }
|
||||
val config = Configuration(ResMgr.resource.configuration)
|
||||
val metrics = DisplayMetrics().apply { setTo(ResMgr.resource.displayMetrics) }
|
||||
val res = Resources(asset, metrics, config)
|
||||
// Create a completely new resource to prevent cross talk over active configs
|
||||
val res = AssetHack.newResource()
|
||||
|
||||
val locales = ArrayList<String>().apply {
|
||||
// Add default locale
|
||||
@@ -45,19 +38,17 @@ withContext(Dispatchers.Default) {
|
||||
add("pt-BR")
|
||||
|
||||
// Then add all supported locales
|
||||
addAll(res.assets.locales)
|
||||
addAll(Resources.getSystem().assets.locales)
|
||||
}.map {
|
||||
it.langTagToLocale()
|
||||
}.distinctBy {
|
||||
config.setLocale(it)
|
||||
res.updateConfiguration(config, metrics)
|
||||
res.updateLocale(it)
|
||||
res.getString(compareId)
|
||||
}.sortedWith(Comparator { a, b ->
|
||||
}.sortedWith { a, b ->
|
||||
a.getDisplayName(a).compareTo(b.getDisplayName(b), true)
|
||||
})
|
||||
}
|
||||
|
||||
config.setLocale(defaultLocale)
|
||||
res.updateConfiguration(config, metrics)
|
||||
res.updateLocale(defaultLocale)
|
||||
val defName = res.getString(R.string.system_default)
|
||||
|
||||
val names = ArrayList<String>(locales.size + 1)
|
||||
@@ -79,6 +70,11 @@ fun Resources.updateConfig(config: Configuration = configuration) {
|
||||
updateConfiguration(config, displayMetrics)
|
||||
}
|
||||
|
||||
fun Resources.updateLocale(locale: Locale) {
|
||||
configuration.setLocale(locale)
|
||||
updateConfiguration(configuration, displayMetrics)
|
||||
}
|
||||
|
||||
fun refreshLocale() {
|
||||
val localeConfig = Config.locale
|
||||
currentLocale = when {
|
||||
@@ -86,5 +82,5 @@ fun refreshLocale() {
|
||||
else -> localeConfig.langTagToLocale()
|
||||
}
|
||||
Locale.setDefault(currentLocale)
|
||||
ResMgr.resource.updateConfig()
|
||||
AssetHack.resource.updateConfig()
|
||||
}
|
||||
|
@@ -1,59 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.wrap
|
||||
import com.topjohnwu.magisk.ktx.rawResource
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
|
||||
class RootInit : Shell.Initializer() {
|
||||
|
||||
override fun onInit(context: Context, shell: Shell): Boolean {
|
||||
return init(context.wrap(), shell)
|
||||
}
|
||||
|
||||
fun init(context: Context, shell: Shell): Boolean {
|
||||
shell.newJob().apply {
|
||||
add("export SDK_INT=${Build.VERSION.SDK_INT}")
|
||||
if (Const.Version.atLeast_20_4()) {
|
||||
add("export MAGISKTMP=\$(magisk --path)/.magisk")
|
||||
} else {
|
||||
add("export MAGISKTMP=/sbin/.magisk")
|
||||
}
|
||||
if (Const.Version.atLeast_21_0()) {
|
||||
add("export ASH_STANDALONE=1")
|
||||
add("[ -x /data/adb/magisk/busybox ] && exec /data/adb/magisk/busybox sh")
|
||||
} else {
|
||||
add("export PATH=\"\$MAGISKTMP/busybox:\$PATH\"")
|
||||
}
|
||||
add(context.rawResource(R.raw.manager))
|
||||
if (shell.isRoot) {
|
||||
add(context.rawResource(R.raw.util_functions))
|
||||
}
|
||||
add("mm_init")
|
||||
}.exec()
|
||||
|
||||
fun fastCmd(cmd: String) = ShellUtils.fastCmd(shell, cmd)
|
||||
fun getVar(name: String) = fastCmd("echo \$$name")
|
||||
fun getBool(name: String) = getVar(name).toBoolean()
|
||||
|
||||
Const.MAGISKTMP = getVar("MAGISKTMP")
|
||||
Info.isSAR = getBool("SYSTEM_ROOT")
|
||||
Info.ramdisk = getBool("RAMDISKEXIST")
|
||||
Info.isAB = getBool("ISAB")
|
||||
Info.crypto = getVar("CRYPTOTYPE")
|
||||
Info.isPixel = fastCmd("getprop ro.product.brand") == "google"
|
||||
|
||||
// Default presets
|
||||
Config.recovery = getBool("RECOVERYMODE")
|
||||
Config.keepVerity = getBool("KEEPVERITY")
|
||||
Config.keepEnc = getBool("KEEPFORCEENCRYPT")
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
102
app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt
Normal file
102
app/src/main/java/com/topjohnwu/magisk/core/utils/ShellInit.kt
Normal file
@@ -0,0 +1,102 @@
|
||||
package com.topjohnwu.magisk.core.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.*
|
||||
import com.topjohnwu.magisk.ktx.cachedFile
|
||||
import com.topjohnwu.magisk.ktx.deviceProtectedContext
|
||||
import com.topjohnwu.magisk.ktx.rawResource
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import java.io.File
|
||||
import java.util.jar.JarFile
|
||||
|
||||
abstract class BaseShellInit : Shell.Initializer() {
|
||||
final override fun onInit(context: Context, shell: Shell): Boolean {
|
||||
return init(context.wrap(), shell)
|
||||
}
|
||||
|
||||
abstract fun init(context: Context, shell: Shell): Boolean
|
||||
}
|
||||
|
||||
|
||||
class BusyBoxInit : BaseShellInit() {
|
||||
|
||||
override fun init(context: Context, shell: Shell): Boolean {
|
||||
shell.newJob().apply {
|
||||
add("export ASH_STANDALONE=1")
|
||||
|
||||
val localBB: File
|
||||
if (isRunningAsStub) {
|
||||
if (!shell.isRoot)
|
||||
return true
|
||||
val jar = JarFile(DynAPK.current(context))
|
||||
val bb = jar.getJarEntry("lib/${Const.CPU_ABI_32}/libbusybox.so")
|
||||
localBB = context.deviceProtectedContext.cachedFile("busybox")
|
||||
localBB.delete()
|
||||
jar.getInputStream(bb).writeTo(localBB)
|
||||
localBB.setExecutable(true)
|
||||
} else {
|
||||
localBB = File(Const.NATIVE_LIB_DIR, "libbusybox.so")
|
||||
}
|
||||
|
||||
if (shell.isRoot) {
|
||||
add("export MAGISKTMP=\$(magisk --path)/.magisk")
|
||||
// Test if we can properly execute stuff in /data
|
||||
Info.noDataExec = !shell.newJob().add("$localBB true").exec().isSuccess
|
||||
}
|
||||
|
||||
if (Info.noDataExec) {
|
||||
// Copy it out of /data to workaround Samsung bullshit
|
||||
add(
|
||||
"if [ -x \$MAGISKTMP/busybox/busybox ]; then",
|
||||
" cp -af $localBB \$MAGISKTMP/busybox/busybox",
|
||||
" exec \$MAGISKTMP/busybox/busybox sh",
|
||||
"else",
|
||||
" cp -af $localBB /dev/.busybox",
|
||||
" exec /dev/.busybox sh",
|
||||
"fi"
|
||||
)
|
||||
} else {
|
||||
// Directly execute the file
|
||||
add("exec $localBB sh")
|
||||
}
|
||||
}.exec()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class AppShellInit : BaseShellInit() {
|
||||
|
||||
override fun init(context: Context, shell: Shell): Boolean {
|
||||
|
||||
fun fastCmd(cmd: String) = ShellUtils.fastCmd(shell, cmd)
|
||||
fun getVar(name: String) = fastCmd("echo \$$name")
|
||||
fun getBool(name: String) = getVar(name).toBoolean()
|
||||
|
||||
shell.newJob().apply {
|
||||
add("export API=${Build.VERSION.SDK_INT}")
|
||||
add(context.rawResource(R.raw.manager))
|
||||
if (shell.isRoot) {
|
||||
add(context.assets.open("util_functions.sh"))
|
||||
}
|
||||
add("app_init")
|
||||
}.exec()
|
||||
|
||||
Const.MAGISKTMP = getVar("MAGISKTMP")
|
||||
Info.isSAR = getBool("SYSTEM_ROOT")
|
||||
Info.ramdisk = getBool("RAMDISKEXIST")
|
||||
Info.isAB = getBool("ISAB")
|
||||
Info.crypto = getVar("CRYPTOTYPE")
|
||||
|
||||
// Default presets
|
||||
Config.recovery = getBool("RECOVERYMODE")
|
||||
Config.keepVerity = getBool("KEEPVERITY")
|
||||
Config.keepEnc = getBool("KEEPFORCEENCRYPT")
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ fun InputStream.unzip(folder: File, path: String, junkPath: Boolean) {
|
||||
dest = SuFile(folder, name)
|
||||
dest.parentFile!!.mkdirs()
|
||||
}
|
||||
SuFileOutputStream(dest).use { out -> zin.copyTo(out) }
|
||||
SuFileOutputStream.open(dest).use { out -> zin.copyTo(out) }
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
|
@@ -8,7 +8,9 @@ import com.topjohnwu.magisk.core.Config.Value.DEFAULT_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.model.*
|
||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||
import com.topjohnwu.magisk.core.model.StubJson
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import com.topjohnwu.magisk.data.network.*
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
@@ -34,7 +36,6 @@ class NetworkService(
|
||||
Config.updateChannel = BETA_CHANNEL
|
||||
info = fetchBetaUpdate()
|
||||
}
|
||||
Info.remote = info
|
||||
info
|
||||
}
|
||||
|
||||
@@ -47,16 +48,12 @@ class NetworkService(
|
||||
val info = jsd.fetchCanaryUpdate(sha)
|
||||
|
||||
fun genCDNUrl(name: String) = "${Const.Url.JS_DELIVR_URL}${MAGISK_FILES}@${sha}/${name}"
|
||||
fun ManagerJson.updateCopy() = copy(link = genCDNUrl(link), note = genCDNUrl(note))
|
||||
fun MagiskJson.updateCopy() = copy(link = genCDNUrl(link), note = genCDNUrl(note))
|
||||
fun StubJson.updateCopy() = copy(link = genCDNUrl(link))
|
||||
fun UninstallerJson.updateCopy() = copy(link = genCDNUrl(link))
|
||||
|
||||
return info.copy(
|
||||
app = info.app.updateCopy(),
|
||||
magisk = info.magisk.updateCopy(),
|
||||
stub = info.stub.updateCopy(),
|
||||
uninstaller = info.uninstaller.updateCopy()
|
||||
stub = info.stub.updateCopy()
|
||||
)
|
||||
}
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package com.topjohnwu.magisk.di
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.topjohnwu.magisk.core.ResMgr
|
||||
import com.topjohnwu.magisk.core.AssetHack
|
||||
import com.topjohnwu.magisk.ktx.deviceProtectedContext
|
||||
import org.koin.core.qualifier.named
|
||||
import org.koin.dsl.module
|
||||
|
||||
@@ -11,15 +11,9 @@ val SUTimeout = named("su_timeout")
|
||||
val Protected = named("protected")
|
||||
|
||||
val applicationModule = module {
|
||||
factory { ResMgr.resource }
|
||||
factory { AssetHack.resource }
|
||||
factory { get<Context>().packageManager }
|
||||
factory(Protected) { createDEContext(get()) }
|
||||
factory(Protected) { get<Context>().deviceProtectedContext }
|
||||
single(SUTimeout) { get<Context>(Protected).getSharedPreferences("su_timeout", 0) }
|
||||
single { PreferenceManager.getDefaultSharedPreferences(get<Context>(Protected)) }
|
||||
}
|
||||
|
||||
private fun createDEContext(context: Context): Context {
|
||||
return if (Build.VERSION.SDK_INT >= 24)
|
||||
context.createDeviceProtectedStorageContext()
|
||||
else context
|
||||
single { PreferenceManager.getDefaultSharedPreferences(get(Protected)) }
|
||||
}
|
||||
|
@@ -14,20 +14,22 @@ import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.base.ActivityResultCallback
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.events.dialog.MarkDownDialog
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), ActivityExecutor {
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) = action(activity)
|
||||
}
|
||||
|
||||
class OpenReadmeEvent(val item: OnlineModule) : ViewEventWithScope(), ContextExecutor {
|
||||
override fun invoke(context: Context) {
|
||||
scope.launch {
|
||||
MarkDownWindow.show(context, null, item::notes)
|
||||
}
|
||||
class OpenReadmeEvent(private val item: OnlineModule) : MarkDownDialog() {
|
||||
override suspend fun getMarkdownText() = item.notes()
|
||||
override fun build(dialog: MagiskDialog) {
|
||||
super.build(dialog)
|
||||
dialog.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
titleRes = android.R.string.cancel
|
||||
}.cancellable(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +80,7 @@ class MagiskInstallFileEvent(private val callback: ActivityResultCallback)
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT).setType("*/*")
|
||||
try {
|
||||
activity.startActivityForResult(intent, Const.ID.SELECT_FILE, callback)
|
||||
activity.startActivityForResult(intent, callback)
|
||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||
@@ -107,10 +109,10 @@ class SelectModuleEvent : ViewEvent(), FragmentExecutor {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT).setType("application/zip")
|
||||
try {
|
||||
fragment.apply {
|
||||
activity.startActivityForResult(intent, Const.ID.FETCH_ZIP) { code, intent ->
|
||||
activity.startActivityForResult(intent) { code, intent ->
|
||||
if (code == Activity.RESULT_OK && intent != null) {
|
||||
intent.data?.also {
|
||||
MainDirections.actionFlashFragment(it, Const.Value.FLASH_ZIP).navigate()
|
||||
MainDirections.actionFlashFragment(Const.Value.FLASH_ZIP, it).navigate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,9 @@ abstract class DialogEvent : ViewEvent(), ActivityExecutor {
|
||||
protected lateinit var dialog: MagiskDialog
|
||||
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
dialog = MagiskDialog(activity).apply(this::build).reveal()
|
||||
dialog = MagiskDialog(activity)
|
||||
.apply { setOwnerActivity(activity) }
|
||||
.apply(this::build).reveal()
|
||||
}
|
||||
|
||||
abstract fun build(dialog: MagiskDialog)
|
||||
|
@@ -1,15 +1,11 @@
|
||||
package com.topjohnwu.magisk.events.dialog
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.download.Action.EnvFix
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject.Magisk
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class EnvFixDialog : DialogEvent() {
|
||||
|
||||
@@ -24,20 +20,17 @@ class EnvFixDialog : DialogEvent() {
|
||||
.applyMessage(R.string.setup_msg)
|
||||
.resetButtons()
|
||||
.cancellable(false)
|
||||
val lbm = LocalBroadcastManager.getInstance(dialog.context)
|
||||
lbm.registerReceiver(object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
(dialog.ownerActivity as BaseActivity).lifecycleScope.launch {
|
||||
MagiskInstaller.FixEnv {
|
||||
dialog.dismiss()
|
||||
lbm.unregisterReceiver(this)
|
||||
}
|
||||
}, IntentFilter(DISMISS))
|
||||
DownloadService.start(dialog.context, Magisk(EnvFix))
|
||||
}.exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
titleRes = android.R.string.cancel
|
||||
}
|
||||
.let { Unit }
|
||||
.let { }
|
||||
|
||||
companion object {
|
||||
const val DISMISS = "com.topjohnwu.magisk.ENV_DONE"
|
||||
|
@@ -1,40 +1,41 @@
|
||||
package com.topjohnwu.magisk.events.dialog
|
||||
|
||||
import android.content.Context
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.ktx.res
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.get
|
||||
import org.koin.core.inject
|
||||
import java.io.File
|
||||
|
||||
class ManagerInstallDialog : DialogEvent() {
|
||||
class ManagerInstallDialog : MarkDownDialog() {
|
||||
|
||||
private val svc: NetworkService by inject()
|
||||
|
||||
override suspend fun getMarkdownText(): String {
|
||||
val text = svc.fetchString(Info.remote.magisk.note)
|
||||
// Cache the changelog
|
||||
val context = get<Context>()
|
||||
context.cacheDir.listFiles { _, name -> name.endsWith(".md") }.orEmpty().forEach {
|
||||
it.delete()
|
||||
}
|
||||
File(context.cacheDir, "${Info.remote.magisk.versionCode}.md").writeText(text)
|
||||
return text
|
||||
}
|
||||
|
||||
override fun build(dialog: MagiskDialog) {
|
||||
super.build(dialog)
|
||||
with(dialog) {
|
||||
val subject = Subject.Manager()
|
||||
|
||||
applyTitle(R.string.repo_install_title.res(R.string.app_name.res()))
|
||||
applyMessage(R.string.repo_install_msg.res(subject.title))
|
||||
|
||||
setCancelable(true)
|
||||
|
||||
applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
titleRes = R.string.install
|
||||
onClick { DownloadService.start(context, subject) }
|
||||
onClick { DownloadService.start(context, Subject.Manager()) }
|
||||
}
|
||||
|
||||
if (Info.remote.app.note.isEmpty()) return
|
||||
applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
titleRes = R.string.app_changelog
|
||||
onClick {
|
||||
GlobalScope.launch(Dispatchers.Main.immediate) {
|
||||
MarkDownWindow.show(context, null, Info.remote.app.note)
|
||||
}
|
||||
}
|
||||
titleRes = android.R.string.cancel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,45 @@
|
||||
package com.topjohnwu.magisk.events.dialog
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import io.noties.markwon.Markwon
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.inject
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.cancellation.CancellationException
|
||||
|
||||
abstract class MarkDownDialog : DialogEvent(), KoinComponent {
|
||||
|
||||
private val markwon: Markwon by inject()
|
||||
|
||||
abstract suspend fun getMarkdownText(): String
|
||||
|
||||
@CallSuper
|
||||
override fun build(dialog: MagiskDialog) {
|
||||
with(dialog) {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.markdown_window_md2, null)
|
||||
applyView(view)
|
||||
(ownerActivity as BaseActivity).lifecycleScope.launch {
|
||||
val tv = view.findViewById<TextView>(R.id.md_txt)
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
markwon.setMarkdown(tv, getMarkdownText())
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException)
|
||||
throw e
|
||||
Timber.e(e)
|
||||
tv.post { tv.setText(R.string.download_file_error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@ class ModuleInstallDialog(private val item: OnlineModule) : DialogEvent() {
|
||||
with(dialog) {
|
||||
|
||||
fun download(install: Boolean) {
|
||||
val config = if (install) Action.Flash.Primary else Action.Download
|
||||
val config = if (install) Action.Flash else Action.Download
|
||||
val subject = Subject.Module(item, config)
|
||||
DownloadService.start(context, subject)
|
||||
}
|
||||
|
@@ -3,10 +3,7 @@ package com.topjohnwu.magisk.events.dialog
|
||||
import android.app.ProgressDialog
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -20,12 +17,10 @@ class UninstallDialog : DialogEvent() {
|
||||
titleRes = R.string.restore_img
|
||||
onClick { restore() }
|
||||
}
|
||||
if (Info.remote.uninstaller.link.isNotEmpty()) {
|
||||
dialog.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
titleRes = R.string.complete_uninstall
|
||||
onClick { completeUninstall() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@@ -46,7 +41,7 @@ class UninstallDialog : DialogEvent() {
|
||||
}
|
||||
|
||||
private fun completeUninstall() {
|
||||
DownloadService.start(dialog.context, Subject.Magisk(Action.Uninstall))
|
||||
FlashFragment.uninstall()
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,8 +21,8 @@ import android.graphics.drawable.AdaptiveIconDrawable
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.system.Os
|
||||
import android.text.PrecomputedText
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -41,11 +41,13 @@ import androidx.core.widget.TextViewCompat
|
||||
import androidx.databinding.BindingAdapter
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.transition.AutoTransition
|
||||
import androidx.transition.TransitionManager
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.AssetHack
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.ResMgr
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
@@ -55,10 +57,26 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Array as JArray
|
||||
|
||||
val packageName: String get() = get<Context>().packageName
|
||||
|
||||
private lateinit var osSymlink: Method
|
||||
private lateinit var os: Any
|
||||
|
||||
fun symlink(oldPath: String, newPath: String) {
|
||||
if (SDK_INT >= 21) {
|
||||
Os.symlink(oldPath, newPath)
|
||||
} else {
|
||||
if (!::osSymlink.isInitialized) {
|
||||
os = Class.forName("libcore.io.Libcore").getField("os").get(null)!!
|
||||
osSymlink = os.javaClass.getMethod("symlink", String::class.java, String::class.java)
|
||||
}
|
||||
osSymlink.invoke(os, oldPath, newPath)
|
||||
}
|
||||
}
|
||||
|
||||
val ServiceInfo.isIsolated get() = (flags and FLAG_ISOLATED_PROCESS) != 0
|
||||
|
||||
@get:SuppressLint("InlinedApi")
|
||||
@@ -83,6 +101,11 @@ fun Context.getBitmap(id: Int): Bitmap {
|
||||
return bitmap
|
||||
}
|
||||
|
||||
val Context.deviceProtectedContext: Context get() =
|
||||
if (SDK_INT >= 24) {
|
||||
createDeviceProtectedStorageContext()
|
||||
} else { this }
|
||||
|
||||
fun Intent.startActivity(context: Context) = context.startActivity(this)
|
||||
|
||||
fun Intent.startActivityWithRoot() {
|
||||
@@ -227,15 +250,13 @@ fun Context.colorStateListCompat(@ColorRes id: Int) = try {
|
||||
null
|
||||
}
|
||||
|
||||
fun Context.drawableCompat(@DrawableRes id: Int) = ContextCompat.getDrawable(this, id)
|
||||
fun Context.drawableCompat(@DrawableRes id: Int) = AppCompatResources.getDrawable(this, id)
|
||||
/**
|
||||
* Pass [start] and [end] dimensions, function will return left and right
|
||||
* with respect to RTL layout direction
|
||||
*/
|
||||
fun Context.startEndToLeftRight(start: Int, end: Int): Pair<Int, Int> {
|
||||
if (SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
|
||||
resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
|
||||
) {
|
||||
if (resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
|
||||
return end to start
|
||||
}
|
||||
return start to end
|
||||
@@ -295,8 +316,21 @@ fun ViewGroup.startAnimations() {
|
||||
)
|
||||
}
|
||||
|
||||
val View.activity: Activity get() {
|
||||
var context = context
|
||||
while(true) {
|
||||
if (context !is ContextWrapper)
|
||||
error("View is not attached to activity")
|
||||
if (context is Activity)
|
||||
return context
|
||||
context = context.baseContext
|
||||
}
|
||||
}
|
||||
|
||||
var View.coroutineScope: CoroutineScope
|
||||
get() = getTag(R.id.coroutineScope) as? CoroutineScope ?: GlobalScope
|
||||
get() = getTag(R.id.coroutineScope) as? CoroutineScope
|
||||
?: (activity as? BaseActivity)?.lifecycleScope
|
||||
?: GlobalScope
|
||||
set(value) = setTag(R.id.coroutineScope, value)
|
||||
|
||||
@set:BindingAdapter("precomputedText")
|
||||
@@ -346,6 +380,16 @@ var TextView.precomputedText: CharSequence
|
||||
}
|
||||
|
||||
fun Int.dpInPx(): Int {
|
||||
val scale = ResMgr.resource.displayMetrics.density
|
||||
val scale = AssetHack.resource.displayMetrics.density
|
||||
return (this * scale + 0.5).toInt()
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
fun getProperty(key: String, def: String): String {
|
||||
runCatching {
|
||||
val clazz = Class.forName("android.os.SystemProperties")
|
||||
val get = clazz.getMethod("get", String::class.java, String::class.java)
|
||||
return get.invoke(clazz, key, def) as String
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
@@ -6,14 +6,12 @@ import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
|
||||
inline fun ZipInputStream.forEach(callback: (ZipEntry) -> Unit) {
|
||||
var entry: ZipEntry? = nextEntry
|
||||
while (entry != null) {
|
||||
callback(entry)
|
||||
@@ -53,7 +51,7 @@ fun String.langTagToLocale(): Locale {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
return Locale.forLanguageTag(this)
|
||||
} else {
|
||||
val tok = split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
val tok = split("[-_]".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (tok.isEmpty()) {
|
||||
return Locale("")
|
||||
}
|
||||
@@ -110,32 +108,3 @@ fun Locale.toLangTag(): String {
|
||||
|
||||
fun SimpleDateFormat.parseOrNull(date: String) =
|
||||
runCatching { parse(date) }.onFailure { Timber.e(it) }.getOrNull()
|
||||
|
||||
// Reflection hacks
|
||||
|
||||
private val loadClass = ClassLoader::class.java.getMethod("loadClass", String::class.java)
|
||||
private val getDeclaredMethod = Class::class.java.getMethod("getDeclaredMethod",
|
||||
String::class.java, arrayOf<Class<*>>()::class.java)
|
||||
private val getDeclaredField = Class::class.java.getMethod("getDeclaredField", String::class.java)
|
||||
|
||||
fun ClassLoader.forceLoadClass(name: String) =
|
||||
runCatching { loadClass.invoke(this, name) }.getOrNull() as Class<*>?
|
||||
|
||||
fun Class<*>.forceGetDeclaredMethod(name: String, vararg types: Class<*>) =
|
||||
(runCatching { getDeclaredMethod.invoke(this, name, types) }.getOrNull() as Method?)?.also {
|
||||
it.isAccessible = true
|
||||
}
|
||||
|
||||
fun Class<*>.forceGetDeclaredField(name: String) =
|
||||
(runCatching { getDeclaredField.invoke(this, name) }.getOrNull() as Field?)?.also {
|
||||
it.isAccessible = true
|
||||
}
|
||||
|
||||
inline fun <reified T> T.forceGetClass(name: String) =
|
||||
T::class.java.classLoader?.forceLoadClass(name)
|
||||
|
||||
fun Class<*>.forceGetField(name: String): Field? =
|
||||
forceGetDeclaredField(name) ?: superclass?.forceGetField(name)
|
||||
|
||||
fun Class<*>.forceGetMethod(name: String, vararg types: Class<*>): Method? =
|
||||
forceGetDeclaredMethod(name, *types) ?: superclass?.forceGetMethod(name, *types)
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package com.topjohnwu.magisk.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
@@ -10,9 +11,7 @@ import android.view.WindowManager
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.navigation.NavDirections
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import com.topjohnwu.magisk.MainDirections
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseUIActivity
|
||||
@@ -22,13 +21,12 @@ import com.topjohnwu.magisk.core.*
|
||||
import com.topjohnwu.magisk.databinding.ActivityMainMd2Binding
|
||||
import com.topjohnwu.magisk.ktx.startAnimations
|
||||
import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
|
||||
import com.topjohnwu.magisk.utils.HideBottomViewOnScrollBehavior
|
||||
import com.topjohnwu.magisk.utils.HideTopViewOnScrollBehavior
|
||||
import com.topjohnwu.magisk.utils.HideableBehavior
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.io.File
|
||||
|
||||
class MainViewModel : BaseViewModel()
|
||||
|
||||
@@ -77,12 +75,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
|
||||
|
||||
setSupportActionBar(binding.mainToolbar)
|
||||
|
||||
binding.mainToolbarWrapper.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
behavior = HideTopViewOnScrollBehavior<MaterialCardView>()
|
||||
}
|
||||
binding.mainBottomBar.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||
behavior = HideBottomViewOnScrollBehavior<MaterialCardView>()
|
||||
}
|
||||
binding.mainNavigation.setOnNavigationItemSelectedListener {
|
||||
getScreen(it.itemId)?.navigate()
|
||||
true
|
||||
@@ -91,7 +83,7 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
|
||||
(currentFragment as? ReselectionTarget)?.onReselected()
|
||||
}
|
||||
|
||||
val section = if (intent.action == ACTION_APPLICATION_PREFERENCES) Const.Nav.SETTINGS
|
||||
val section = if (intent.action == Intent.ACTION_APPLICATION_PREFERENCES) Const.Nav.SETTINGS
|
||||
else intent.getStringExtra(Const.Key.OPEN_SECTION)
|
||||
getScreen(section)?.navigate()
|
||||
|
||||
@@ -198,7 +190,37 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
|
||||
.applyTitle(R.string.unsupport_magisk_title)
|
||||
.applyMessage(R.string.unsupport_magisk_msg, Const.Version.MIN_VERSION)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
|
||||
.cancellable(true)
|
||||
.cancellable(false)
|
||||
.reveal()
|
||||
}
|
||||
|
||||
if (!Info.isEmulator && Info.env.isActive && System.getenv("PATH")
|
||||
?.split(':')
|
||||
?.filterNot { File("$it/magisk").exists() }
|
||||
?.any { File("$it/su").exists() } == true) {
|
||||
MagiskDialog(this)
|
||||
.applyTitle(R.string.unsupport_general_title)
|
||||
.applyMessage(R.string.unsupport_other_su_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
|
||||
.cancellable(false)
|
||||
.reveal()
|
||||
}
|
||||
|
||||
if (applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) {
|
||||
MagiskDialog(this)
|
||||
.applyTitle(R.string.unsupport_general_title)
|
||||
.applyMessage(R.string.unsupport_system_app_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
|
||||
.cancellable(false)
|
||||
.reveal()
|
||||
}
|
||||
|
||||
if (applicationInfo.flags and ApplicationInfo.FLAG_EXTERNAL_STORAGE != 0) {
|
||||
MagiskDialog(this)
|
||||
.applyTitle(R.string.unsupport_general_title)
|
||||
.applyMessage(R.string.unsupport_external_storage_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) { titleRes = android.R.string.ok }
|
||||
.cancellable(false)
|
||||
.reveal()
|
||||
}
|
||||
}
|
||||
@@ -222,11 +244,4 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
|
||||
.reveal()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val ACTION_APPLICATION_PREFERENCES get() =
|
||||
if (Build.VERSION.SDK_INT >= 24) Intent.ACTION_APPLICATION_PREFERENCES
|
||||
else "???"
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,13 +17,12 @@ import com.topjohnwu.magisk.ui.MainActivity
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
import com.topjohnwu.magisk.MainDirections.Companion.actionFlashFragment as toFlash
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragmentArgs as args
|
||||
|
||||
class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>() {
|
||||
|
||||
override val layoutRes = R.layout.fragment_flash_md2
|
||||
override val viewModel by viewModel<FlashViewModel> {
|
||||
parametersOf(args.fromBundle(requireArguments()))
|
||||
parametersOf(FlashFragmentArgs.fromBundle(requireArguments()))
|
||||
}
|
||||
|
||||
private var defaultOrientation = -1
|
||||
@@ -78,7 +77,7 @@ class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>()
|
||||
|
||||
companion object {
|
||||
|
||||
private fun createIntent(context: Context, args: args) =
|
||||
private fun createIntent(context: Context, args: FlashFragmentArgs) =
|
||||
NavDeepLinkBuilder(context)
|
||||
.setGraph(R.navigation.main)
|
||||
.setComponentName(MainActivity::class.java.cmp(context.packageName))
|
||||
@@ -91,59 +90,34 @@ class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>()
|
||||
|
||||
/* Flashing is understood as installing / flashing magisk itself */
|
||||
|
||||
fun flashIntent(context: Context, file: Uri, isSecondSlot: Boolean, id: Int = -1) = args(
|
||||
installer = file,
|
||||
action = flashType(isSecondSlot),
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun flash(file: Uri, isSecondSlot: Boolean, id: Int) = toFlash(
|
||||
installer = file,
|
||||
action = flashType(isSecondSlot),
|
||||
dismissId = id
|
||||
fun flash(isSecondSlot: Boolean) = toFlash(
|
||||
action = flashType(isSecondSlot)
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Patching is understood as injecting img files with magisk */
|
||||
|
||||
fun patchIntent(context: Context, file: Uri, uri: Uri, id: Int = -1) = args(
|
||||
installer = file,
|
||||
fun patch(uri: Uri) = toFlash(
|
||||
action = Const.Value.PATCH_FILE,
|
||||
additionalData = uri,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun patch(file: Uri, uri: Uri, id: Int) = toFlash(
|
||||
installer = file,
|
||||
action = Const.Value.PATCH_FILE,
|
||||
additionalData = uri,
|
||||
dismissId = id
|
||||
additionalData = uri
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Uninstalling is understood as removing magisk entirely */
|
||||
|
||||
fun uninstallIntent(context: Context, file: Uri, id: Int = -1) = args(
|
||||
installer = file,
|
||||
action = Const.Value.UNINSTALL,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun uninstall(file: Uri, id: Int) = toFlash(
|
||||
installer = file,
|
||||
action = Const.Value.UNINSTALL,
|
||||
dismissId = id
|
||||
fun uninstall() = toFlash(
|
||||
action = Const.Value.UNINSTALL
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
|
||||
/* Installing is understood as flashing modules / zips */
|
||||
|
||||
fun installIntent(context: Context, file: Uri, id: Int = -1) = args(
|
||||
installer = file,
|
||||
fun installIntent(context: Context, file: Uri, id: Int = -1) = FlashFragmentArgs(
|
||||
action = Const.Value.FLASH_ZIP,
|
||||
additionalData = file,
|
||||
dismissId = id
|
||||
).let { createIntent(context, it) }
|
||||
|
||||
fun install(file: Uri, id: Int) = toFlash(
|
||||
installer = file,
|
||||
action = Const.Value.FLASH_ZIP,
|
||||
additionalData = file,
|
||||
dismissId = id
|
||||
).let { BaseUIActivity.postDirections(it) }
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import com.topjohnwu.magisk.arch.BaseViewModel
|
||||
import com.topjohnwu.magisk.arch.diffListOf
|
||||
import com.topjohnwu.magisk.arch.itemBindingOf
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.tasks.FlashZip
|
||||
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
@@ -26,9 +27,7 @@ import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FlashViewModel(
|
||||
args: FlashFragmentArgs
|
||||
) : BaseViewModel() {
|
||||
class FlashViewModel(args: FlashFragmentArgs) : BaseViewModel() {
|
||||
|
||||
@get:Bindable
|
||||
var showReboot = Shell.rootAccess()
|
||||
@@ -51,33 +50,35 @@ class FlashViewModel(
|
||||
}
|
||||
|
||||
init {
|
||||
args.dismissId.takeIf { it != -1 }?.also {
|
||||
Notifications.mgr.cancel(it)
|
||||
}
|
||||
val (installer, action, uri) = args
|
||||
startFlashing(installer, uri, action)
|
||||
val (action, uri, id) = args
|
||||
if (id != -1)
|
||||
Notifications.mgr.cancel(id)
|
||||
startFlashing(action, uri)
|
||||
}
|
||||
|
||||
private fun startFlashing(installer: Uri, uri: Uri?, action: String) {
|
||||
private fun startFlashing(action: String, uri: Uri?) {
|
||||
viewModelScope.launch {
|
||||
val result = when (action) {
|
||||
Const.Value.FLASH_ZIP -> {
|
||||
FlashZip(installer, outItems, logItems).exec()
|
||||
FlashZip(uri!!, outItems, logItems).exec()
|
||||
}
|
||||
Const.Value.UNINSTALL -> {
|
||||
showReboot = false
|
||||
FlashZip.Uninstall(installer, outItems, logItems).exec()
|
||||
MagiskInstaller.Uninstall(outItems, logItems).exec()
|
||||
}
|
||||
Const.Value.FLASH_MAGISK -> {
|
||||
MagiskInstaller.Direct(installer, outItems, logItems).exec()
|
||||
if (Info.isEmulator)
|
||||
MagiskInstaller.Emulator(outItems, logItems).exec()
|
||||
else
|
||||
MagiskInstaller.Direct(outItems, logItems).exec()
|
||||
}
|
||||
Const.Value.FLASH_INACTIVE_SLOT -> {
|
||||
MagiskInstaller.SecondSlot(installer, outItems, logItems).exec()
|
||||
MagiskInstaller.SecondSlot(outItems, logItems).exec()
|
||||
}
|
||||
Const.Value.PATCH_FILE -> {
|
||||
uri ?: return@launch
|
||||
showReboot = false
|
||||
MagiskInstaller.Patch(installer, uri, outItems, logItems).exec()
|
||||
MagiskInstaller.Patch(uri, outItems, logItems).exec()
|
||||
}
|
||||
else -> {
|
||||
back()
|
||||
|
@@ -2,6 +2,8 @@ package com.topjohnwu.magisk.ui.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||
import com.topjohnwu.magisk.core.download.BaseDownloader
|
||||
@@ -22,20 +24,32 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
|
||||
BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
|
||||
}
|
||||
|
||||
private fun checkTitle(text: TextView, icon: ImageView) {
|
||||
text.post {
|
||||
if (text.layout.getEllipsisCount(0) != 0) {
|
||||
with (icon) {
|
||||
layoutParams.width = 0
|
||||
layoutParams.height = 0
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
): View {
|
||||
super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
||||
// Set barrier reference IDs in code, since resource IDs will be stripped in release mode
|
||||
binding.homeMagiskWrapper.homeMagiskTitleBarrier.referencedIds =
|
||||
intArrayOf(R.id.home_magisk_button, R.id.home_magisk_title, R.id.home_magisk_icon)
|
||||
binding.homeMagiskWrapper.homeMagiskBarrier.referencedIds =
|
||||
intArrayOf(R.id.home_magisk_latest_version, R.id.home_magisk_installed_version)
|
||||
binding.homeManagerWrapper.homeManagerTitleBarrier.referencedIds =
|
||||
intArrayOf(R.id.home_manager_button, R.id.home_manager_title, R.id.home_manager_icon)
|
||||
// If titles are squished, hide icons
|
||||
with(binding.homeMagiskWrapper) {
|
||||
checkTitle(homeMagiskTitle, homeMagiskIcon)
|
||||
}
|
||||
with(binding.homeManagerWrapper) {
|
||||
checkTitle(homeManagerTitle, homeManagerIcon)
|
||||
}
|
||||
|
||||
return binding.root
|
||||
}
|
||||
@@ -46,11 +60,14 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
|
||||
menu.removeItem(R.id.action_reboot)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||
R.id.action_settings -> HomeFragmentDirections.actionHomeFragmentToSettingsFragment()
|
||||
.navigate()
|
||||
R.id.action_reboot -> RebootEvent.inflateMenu(activity).show()
|
||||
else -> null
|
||||
}?.let { true } ?: super.onOptionsItemSelected(item)
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_settings ->
|
||||
HomeFragmentDirections.actionHomeFragmentToSettingsFragment().navigate()
|
||||
R.id.action_reboot -> RebootEvent.inflateMenu(activity).show()
|
||||
else -> return super.onOptionsItemSelected(item)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,8 +9,6 @@ import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.download.Subject.Manager
|
||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.events.OpenInappLinkEvent
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
@@ -18,8 +16,7 @@ import com.topjohnwu.magisk.events.dialog.EnvFixDialog
|
||||
import com.topjohnwu.magisk.events.dialog.ManagerInstallDialog
|
||||
import com.topjohnwu.magisk.events.dialog.UninstallDialog
|
||||
import com.topjohnwu.magisk.ktx.await
|
||||
import com.topjohnwu.magisk.ktx.packageName
|
||||
import com.topjohnwu.magisk.ktx.res
|
||||
import com.topjohnwu.magisk.utils.asTransitive
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -34,41 +31,46 @@ class HomeViewModel(
|
||||
private val svc: NetworkService
|
||||
) : BaseViewModel() {
|
||||
|
||||
val magiskTitleBarrierIds =
|
||||
intArrayOf(R.id.home_magisk_icon, R.id.home_magisk_title, R.id.home_magisk_button)
|
||||
val magiskDetailBarrierIds =
|
||||
intArrayOf(R.id.home_magisk_installed_version, R.id.home_device_details_ramdisk)
|
||||
val appTitleBarrierIds =
|
||||
intArrayOf(R.id.home_manager_icon, R.id.home_manager_title, R.id.home_manager_button)
|
||||
|
||||
@get:Bindable
|
||||
var isNoticeVisible = Config.safetyNotice
|
||||
set(value) = set(value, field, { field = it }, BR.noticeVisible)
|
||||
|
||||
@get:Bindable
|
||||
var stateMagisk = MagiskState.LOADING
|
||||
set(value) = set(value, field, { field = it }, BR.stateMagisk, BR.showUninstall)
|
||||
val stateMagisk = when {
|
||||
!Info.env.isActive -> MagiskState.NOT_INSTALLED
|
||||
Info.env.magiskVersionCode < BuildConfig.VERSION_CODE -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var stateManager = MagiskState.LOADING
|
||||
set(value) = set(value, field, { field = it }, BR.stateManager)
|
||||
|
||||
@get:Bindable
|
||||
var magiskRemoteVersion = R.string.loading.res()
|
||||
set(value) = set(value, field, { field = it }, BR.magiskRemoteVersion)
|
||||
|
||||
val magiskInstalledVersion get() =
|
||||
"${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})"
|
||||
val magiskInstalledVersion get() = Info.env.run {
|
||||
if (isActive)
|
||||
"$magiskVersionString ($magiskVersionCode)".asTransitive()
|
||||
else
|
||||
R.string.not_available.asTransitive()
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var managerRemoteVersion = R.string.loading.res()
|
||||
var managerRemoteVersion = R.string.loading.asTransitive()
|
||||
set(value) = set(value, field, { field = it }, BR.managerRemoteVersion)
|
||||
|
||||
val managerInstalledVersion = Info.stub?.let {
|
||||
"${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})"
|
||||
} ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
|
||||
val statePackageName = packageName
|
||||
|
||||
@get:Bindable
|
||||
var stateManagerProgress = 0
|
||||
set(value) = set(value, field, { field = it }, BR.stateManagerProgress)
|
||||
|
||||
@get:Bindable
|
||||
val showUninstall get() = Info.env.isActive && state != State.LOADING
|
||||
|
||||
@get:Bindable
|
||||
val showSafetyNet get() = Info.hasGMS && isConnected.get()
|
||||
|
||||
@@ -80,30 +82,25 @@ class HomeViewModel(
|
||||
|
||||
override fun refresh() = viewModelScope.launch {
|
||||
state = State.LOADING
|
||||
svc.fetchUpdate()?.apply {
|
||||
notifyPropertyChanged(BR.showSafetyNet)
|
||||
Info.getRemote(svc)?.apply {
|
||||
state = State.LOADED
|
||||
stateMagisk = when {
|
||||
!Info.env.isActive -> MagiskState.NOT_INSTALLED
|
||||
magisk.isObsolete -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
}
|
||||
|
||||
stateManager = when {
|
||||
app.isObsolete -> MagiskState.OBSOLETE
|
||||
BuildConfig.VERSION_CODE < magisk.versionCode -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
}
|
||||
|
||||
magiskRemoteVersion =
|
||||
"${magisk.version} (${magisk.versionCode})"
|
||||
managerRemoteVersion =
|
||||
"${app.version} (${app.versionCode}) (${stub.versionCode})"
|
||||
"${magisk.version} (${magisk.versionCode}) (${stub.versionCode})".asTransitive()
|
||||
|
||||
launch {
|
||||
ensureEnv()
|
||||
}
|
||||
} ?: apply { state = State.LOADING_FAILED }
|
||||
notifyPropertyChanged(BR.showUninstall)
|
||||
notifyPropertyChanged(BR.showSafetyNet)
|
||||
} ?: {
|
||||
state = State.LOADING_FAILED
|
||||
managerRemoteVersion = R.string.not_available.asTransitive()
|
||||
}()
|
||||
}
|
||||
|
||||
val showTest = false
|
||||
@@ -115,9 +112,8 @@ class HomeViewModel(
|
||||
}.publish()
|
||||
|
||||
fun onProgressUpdate(progress: Float, subject: Subject) {
|
||||
when (subject) {
|
||||
is Manager -> stateManagerProgress = progress.times(100f).roundToInt()
|
||||
}
|
||||
if (subject is Manager)
|
||||
stateManagerProgress = progress.times(100f).roundToInt()
|
||||
}
|
||||
|
||||
fun onLinkPressed(link: String) = OpenInappLinkEvent(link).publish()
|
||||
@@ -125,17 +121,13 @@ class HomeViewModel(
|
||||
fun onDeletePressed() = UninstallDialog().publish()
|
||||
|
||||
fun onManagerPressed() = when (state) {
|
||||
State.LOADED -> ManagerInstallDialog().publish()
|
||||
State.LOADED -> withExternalRW { ManagerInstallDialog().publish() }
|
||||
State.LOADING -> SnackbarEvent(R.string.loading).publish()
|
||||
else -> SnackbarEvent(R.string.no_connection).publish()
|
||||
}
|
||||
|
||||
fun onMagiskPressed() = when (state) {
|
||||
State.LOADED -> withExternalRW {
|
||||
HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish()
|
||||
}
|
||||
State.LOADING -> SnackbarEvent(R.string.loading).publish()
|
||||
else -> SnackbarEvent(R.string.no_connection).publish()
|
||||
fun onMagiskPressed() = withExternalRW {
|
||||
HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish()
|
||||
}
|
||||
|
||||
fun onSafetyNetPressed() =
|
||||
@@ -160,9 +152,4 @@ class HomeViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private val MagiskJson.isObsolete
|
||||
get() = Info.env.isActive && Info.env.magiskVersionCode < versionCode
|
||||
private val ManagerJson.isObsolete
|
||||
get() = BuildConfig.VERSION_CODE < versionCode
|
||||
|
||||
}
|
||||
|
@@ -7,7 +7,6 @@ import android.view.ViewGroup
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||
import com.topjohnwu.magisk.core.download.BaseDownloader
|
||||
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
||||
import com.topjohnwu.magisk.ktx.coroutineScope
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
@@ -23,7 +22,6 @@ class InstallFragment : BaseUIFragment<InstallViewModel, FragmentInstallMd2Bindi
|
||||
|
||||
// Allow markwon to run in viewmodel scope
|
||||
binding.releaseNotes.coroutineScope = viewModel.viewModelScope
|
||||
BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@@ -1,33 +1,35 @@
|
||||
package com.topjohnwu.magisk.ui.install
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseViewModel
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.events.MagiskInstallFileEvent
|
||||
import com.topjohnwu.magisk.events.dialog.SecondSlotWarningDialog
|
||||
import com.topjohnwu.magisk.ui.flash.FlashFragment
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.get
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class InstallViewModel(
|
||||
svc: NetworkService
|
||||
) : BaseViewModel(State.LOADED) {
|
||||
) : BaseViewModel() {
|
||||
|
||||
val isRooted = Shell.rootAccess()
|
||||
val skipOptions = Info.ramdisk && !Info.isFDE && Info.isSAR
|
||||
val skipOptions = Info.isEmulator || (Info.ramdisk && !Info.isFDE && Info.isSAR)
|
||||
val noSecondSlot = !isRooted || Info.isPixel || Info.isVirtualAB || !Info.isAB || Info.isEmulator
|
||||
|
||||
@get:Bindable
|
||||
var step = if (skipOptions) 1 else 0
|
||||
@@ -52,10 +54,6 @@ class InstallViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var progress = 0
|
||||
set(value) = set(value, field, { field = it }, BR.progress)
|
||||
|
||||
@get:Bindable
|
||||
var data: Uri? = null
|
||||
set(value) = set(value, field, { field = it }, BR.data)
|
||||
@@ -67,41 +65,35 @@ class InstallViewModel(
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
notes = svc.fetchString(Info.remote.magisk.note)
|
||||
val context = get<Context>()
|
||||
File(context.cacheDir, "${BuildConfig.VERSION_CODE}.md").run {
|
||||
notes = when {
|
||||
exists() -> readText()
|
||||
Const.Url.CHANGELOG_URL.isEmpty() -> ""
|
||||
else -> {
|
||||
val text = svc.fetchString(Const.Url.CHANGELOG_URL)
|
||||
writeText(text)
|
||||
text
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onProgressUpdate(progress: Float, subject: Subject) {
|
||||
if (subject !is Subject.Magisk) {
|
||||
return
|
||||
}
|
||||
this.progress = progress.times(100).roundToInt()
|
||||
if (this.progress >= 100) {
|
||||
state = State.LOADED
|
||||
} else if (this.progress < -150) {
|
||||
state = State.LOADING_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
fun step(nextStep: Int) {
|
||||
step = nextStep
|
||||
}
|
||||
|
||||
fun install() {
|
||||
DownloadService.start(get(), Subject.Magisk(resolveAction()))
|
||||
when (method) {
|
||||
R.id.method_patch -> FlashFragment.patch(data!!)
|
||||
R.id.method_direct -> FlashFragment.flash(false)
|
||||
R.id.method_inactive_slot -> FlashFragment.flash(true)
|
||||
else -> error("Unknown value")
|
||||
}
|
||||
state = State.LOADING
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
private fun resolveAction() = when (method) {
|
||||
R.id.method_download -> Action.Download
|
||||
R.id.method_patch -> Action.Patch(data!!)
|
||||
R.id.method_direct -> Action.Flash.Primary
|
||||
R.id.method_inactive_slot -> Action.Flash.Secondary
|
||||
else -> error("Unknown value")
|
||||
}
|
||||
}
|
||||
|
@@ -313,10 +313,8 @@ class ModuleViewModel(
|
||||
|
||||
fun infoPressed(item: ModuleItem) {
|
||||
item.repo?.also {
|
||||
if (isConnected.get())
|
||||
OpenReadmeEvent(it).publish()
|
||||
else
|
||||
SnackbarEvent(R.string.no_connection).publish()
|
||||
if (isConnected.get()) OpenReadmeEvent(it).publish()
|
||||
else SnackbarEvent(R.string.no_connection).publish()
|
||||
} ?: return
|
||||
}
|
||||
}
|
||||
|
@@ -61,10 +61,10 @@ object Theme : BaseSettingsItem.Blank() {
|
||||
override val title = R.string.section_theme.asTransitive()
|
||||
}
|
||||
|
||||
// --- Manager
|
||||
// --- App
|
||||
|
||||
object Manager : BaseSettingsItem.Section() {
|
||||
override val title = R.string.manager.asTransitive()
|
||||
object AppSettings : BaseSettingsItem.Section() {
|
||||
override val title = R.string.home_app_title.asTransitive()
|
||||
}
|
||||
|
||||
object ClearRepoCache : BaseSettingsItem.Blank() {
|
||||
@@ -77,8 +77,8 @@ object ClearRepoCache : BaseSettingsItem.Blank() {
|
||||
}
|
||||
|
||||
object Hide : BaseSettingsItem.Input() {
|
||||
override val title = R.string.settings_hide_manager_title.asTransitive()
|
||||
override val description = R.string.settings_hide_manager_summary.asTransitive()
|
||||
override val title = R.string.settings_hide_app_title.asTransitive()
|
||||
override val description = R.string.settings_hide_app_summary.asTransitive()
|
||||
|
||||
override var value = ""
|
||||
set(value) = setV(value, field, { field = it })
|
||||
@@ -106,11 +106,8 @@ object Hide : BaseSettingsItem.Input() {
|
||||
}
|
||||
|
||||
object Restore : BaseSettingsItem.Blank() {
|
||||
override val title = R.string.settings_restore_manager_title.asTransitive()
|
||||
override val description = R.string.settings_restore_manager_summary.asTransitive()
|
||||
override fun refresh() {
|
||||
isEnabled = Info.remote.app.versionCode > 0
|
||||
}
|
||||
override val title = R.string.settings_restore_app_title.asTransitive()
|
||||
override val description = R.string.settings_restore_app_summary.asTransitive()
|
||||
}
|
||||
|
||||
object AddShortcut : BaseSettingsItem.Blank() {
|
||||
@@ -141,21 +138,27 @@ object DownloadPath : BaseSettingsItem.Input() {
|
||||
|
||||
object UpdateChannel : BaseSettingsItem.Selector() {
|
||||
override var value = Config.updateChannel
|
||||
set(value) = setV(value, field, { field = it }) { Config.updateChannel = it }
|
||||
set(value) = setV(value, field, { field = it }) {
|
||||
Config.updateChannel = it
|
||||
Info.remote = Info.EMPTY_REMOTE
|
||||
}
|
||||
|
||||
override val title = R.string.settings_update_channel_title.asTransitive()
|
||||
override val entries: Array<String> = resources.getStringArray(R.array.update_channel).let {
|
||||
if (BuildConfig.DEBUG) it.toMutableList().apply { add("Canary") }.toTypedArray() else it
|
||||
override val entries: Array<String> = resources.getStringArray(R.array.update_channel).apply {
|
||||
if (BuildConfig.VERSION_CODE % 100 == 0)
|
||||
toMutableList().apply { removeAt(Config.Value.CANARY_CHANNEL) }.toTypedArray()
|
||||
}
|
||||
override val description
|
||||
get() = entries.getOrNull(value)?.asTransitive()
|
||||
?: TransitiveText.String(if (value == -1) entries[0] else "Canary")
|
||||
get() = entries.getOrNull(value)?.asTransitive() ?: TransitiveText.String(entries[0])
|
||||
}
|
||||
|
||||
object UpdateChannelUrl : BaseSettingsItem.Input() {
|
||||
override val title = R.string.settings_update_custom.asTransitive()
|
||||
override var value = Config.customChannelUrl
|
||||
set(value) = setV(value, field, { field = it }) { Config.customChannelUrl = it }
|
||||
set(value) = setV(value, field, { field = it }) {
|
||||
Config.customChannelUrl = it
|
||||
Info.remote = Info.EMPTY_REMOTE
|
||||
}
|
||||
override val description get() = value.asTransitive()
|
||||
|
||||
override val inputResult get() = result
|
||||
|
@@ -21,6 +21,7 @@ import com.topjohnwu.magisk.data.database.RepoDao
|
||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||
import com.topjohnwu.magisk.events.RecreateEvent
|
||||
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||
import com.topjohnwu.magisk.ktx.activity
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -54,13 +55,17 @@ class SettingsViewModel(
|
||||
|
||||
// Manager
|
||||
list.addAll(listOf(
|
||||
Manager,
|
||||
AppSettings,
|
||||
UpdateChannel, UpdateChannelUrl, DoHToggle, UpdateChecker, DownloadPath
|
||||
))
|
||||
if (Info.env.isActive) {
|
||||
list.add(ClearRepoCache)
|
||||
if (Const.USER_ID == 0 && Info.isConnected.get())
|
||||
list.add(if (hidden) Restore else Hide)
|
||||
if (Build.VERSION.SDK_INT >= 21 && Const.USER_ID == 0) {
|
||||
if (hidden)
|
||||
list.add(Restore)
|
||||
else if (Info.isConnected.get())
|
||||
list.add(Hide)
|
||||
}
|
||||
}
|
||||
|
||||
// Magisk
|
||||
@@ -101,16 +106,18 @@ class SettingsViewModel(
|
||||
is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().publish()
|
||||
is ClearRepoCache -> clearRepoCache()
|
||||
is SystemlessHosts -> createHosts()
|
||||
is Restore -> HideAPK.restore(view.context)
|
||||
is Restore -> HideAPK.restore(view.activity)
|
||||
is AddShortcut -> AddHomeIconEvent().publish()
|
||||
else -> callback()
|
||||
}
|
||||
|
||||
override fun onItemChanged(view: View, item: BaseSettingsItem) = when (item) {
|
||||
is Language -> RecreateEvent().publish()
|
||||
is UpdateChannel -> openUrlIfNecessary(view)
|
||||
is Hide -> HideAPK.hide(view.context, item.value)
|
||||
else -> Unit
|
||||
override fun onItemChanged(view: View, item: BaseSettingsItem) {
|
||||
when (item) {
|
||||
is Language -> RecreateEvent().publish()
|
||||
is UpdateChannel -> openUrlIfNecessary(view)
|
||||
is Hide -> viewModelScope.launch { HideAPK.hide(view.activity, item.value) }
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
private fun openUrlIfNecessary(view: View) {
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
@@ -13,8 +15,8 @@ import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class HideBottomViewOnScrollBehavior<V : View> : HideBottomViewOnScrollBehavior<V>(),
|
||||
HideableBehavior<V> {
|
||||
class HideBottomViewOnScrollBehavior<V : View>(context: Context, attrs: AttributeSet) :
|
||||
HideBottomViewOnScrollBehavior<V>(), HideableBehavior<V> {
|
||||
|
||||
private var lockState: Boolean = false
|
||||
private var isLaidOut = false
|
||||
@@ -122,4 +124,4 @@ class HideBottomViewOnScrollBehavior<V : View> : HideBottomViewOnScrollBehavior<
|
||||
.setInterpolator(FastOutSlowInInterpolator())
|
||||
.start()
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.animation.TimeInterpolator
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewPropertyAnimator
|
||||
@@ -8,9 +10,8 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.view.ViewCompat
|
||||
import com.google.android.material.animation.AnimationUtils
|
||||
|
||||
class HideTopViewOnScrollBehavior<V : View> :
|
||||
CoordinatorLayout.Behavior<V>(),
|
||||
HideableBehavior<V> {
|
||||
class HideTopViewOnScrollBehavior<V : View>(context: Context, attrs: AttributeSet) :
|
||||
CoordinatorLayout.Behavior<V>(), HideableBehavior<V> {
|
||||
|
||||
companion object {
|
||||
private const val STATE_SCROLLED_DOWN = 1
|
||||
@@ -139,4 +140,4 @@ class HideTopViewOnScrollBehavior<V : View> :
|
||||
.setDuration(duration)
|
||||
.withEndAction { currentAnimator = null }
|
||||
.let { currentAnimator = it }
|
||||
}
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ import android.widget.TextView
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.caverock.androidsvg.SVG
|
||||
import com.caverock.androidsvg.SVGParseException
|
||||
import com.topjohnwu.magisk.core.ResMgr
|
||||
import com.topjohnwu.magisk.core.AssetHack
|
||||
import com.topjohnwu.superuser.internal.WaitRunnable
|
||||
import io.noties.markwon.AbstractMarkwonPlugin
|
||||
import io.noties.markwon.MarkwonSpansFactory
|
||||
@@ -216,7 +216,7 @@ class MarkwonImagePlugin(okHttp: OkHttpClient) : AbstractMarkwonPlugin() {
|
||||
return PictureDrawable(picture)
|
||||
}
|
||||
|
||||
val density: Float = ResMgr.resource.displayMetrics.density
|
||||
val density: Float = AssetHack.resource.displayMetrics.density
|
||||
|
||||
val width = (w * density + .5f).toInt()
|
||||
val height = (h * density + .5f).toInt()
|
||||
@@ -226,7 +226,7 @@ class MarkwonImagePlugin(okHttp: OkHttpClient) : AbstractMarkwonPlugin() {
|
||||
canvas.scale(density, density)
|
||||
svg.renderToCanvas(canvas)
|
||||
|
||||
return BitmapDrawable(ResMgr.resource, bitmap)
|
||||
return BitmapDrawable(AssetHack.resource, bitmap)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import android.content.res.Resources
|
||||
import android.widget.TextView
|
||||
import androidx.databinding.BindingAdapter
|
||||
import androidx.databinding.InverseBindingAdapter
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
|
||||
sealed class TransitiveText {
|
||||
|
||||
@@ -42,13 +41,13 @@ sealed class TransitiveText {
|
||||
}
|
||||
|
||||
|
||||
fun Int.asTransitive(vararg params: Any) = TransitiveText.Res(this, *params)
|
||||
fun CharSequence.asTransitive() = TransitiveText.String(this)
|
||||
fun Int.asTransitive(vararg params: Any): TransitiveText = TransitiveText.Res(this, *params)
|
||||
fun CharSequence.asTransitive(): TransitiveText = TransitiveText.String(this)
|
||||
|
||||
|
||||
@BindingAdapter("android:text")
|
||||
fun TextView.setText(text: TransitiveText) {
|
||||
this.text = text.getText(get())
|
||||
this.text = text.getText(context.resources)
|
||||
}
|
||||
|
||||
@InverseBindingAdapter(attribute = "android:text", event = "android:textAttrChanged")
|
||||
|
@@ -47,7 +47,8 @@ class MagiskDialog(
|
||||
super.onCreate(savedInstanceState)
|
||||
super.setContentView(binding.root)
|
||||
|
||||
val surfaceColor = MaterialColors.getColor(context, R.attr.colorSurfaceSurfaceVariant, javaClass.canonicalName)
|
||||
val default = MaterialColors.getColor(context, R.attr.colorSurface, javaClass.canonicalName)
|
||||
val surfaceColor = MaterialColors.getColor(context, R.attr.colorSurfaceSurfaceVariant, default)
|
||||
val materialShapeDrawable = MaterialShapeDrawable(context, null, R.attr.alertDialogStyle, R.style.MaterialAlertDialog_MaterialComponents)
|
||||
materialShapeDrawable.initializeElevationOverlay(context)
|
||||
materialShapeDrawable.fillColor = ColorStateList.valueOf(surfaceColor)
|
||||
|
@@ -1,54 +0,0 @@
|
||||
package com.topjohnwu.magisk.view
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.TextView
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.coroutineScope
|
||||
import io.noties.markwon.Markwon
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.inject
|
||||
import timber.log.Timber
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
object MarkDownWindow : KoinComponent {
|
||||
|
||||
private val svc: NetworkService by inject()
|
||||
private val markwon: Markwon by inject()
|
||||
|
||||
suspend fun show(activity: Context, title: String?, url: String) {
|
||||
show(activity, title) {
|
||||
svc.fetchString(url)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun show(activity: Context, title: String?, input: suspend () -> String) {
|
||||
val view = LayoutInflater.from(activity).inflate(R.layout.markdown_window_md2, null)
|
||||
|
||||
MagiskDialog(activity)
|
||||
.applyTitle(title ?: "")
|
||||
.applyView(view)
|
||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
titleRes = android.R.string.cancel
|
||||
}
|
||||
.reveal()
|
||||
|
||||
val tv = view.findViewById<TextView>(R.id.md_txt)
|
||||
tv.coroutineScope = CoroutineScope(coroutineContext)
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
markwon.setMarkdown(tv, input())
|
||||
} catch (e: Exception) {
|
||||
if (e is CancellationException)
|
||||
throw e
|
||||
Timber.e(e)
|
||||
tv.post { tv.setText(R.string.download_file_error) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,24 +3,20 @@ package com.topjohnwu.magisk.view
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.graphics.drawable.toIcon
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.core.SplashActivity
|
||||
import com.topjohnwu.magisk.core.cmp
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.getBitmap
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
object Notifications {
|
||||
|
||||
val mgr by lazy { get<Context>().getSystemService<NotificationManager>()!! }
|
||||
@@ -49,29 +45,11 @@ object Notifications {
|
||||
}
|
||||
}
|
||||
|
||||
fun magiskUpdate(context: Context) {
|
||||
val intent = context.intent<SplashActivity>()
|
||||
.putExtra(Const.Key.OPEN_SECTION, "magisk")
|
||||
val stackBuilder = TaskStackBuilder.create(context)
|
||||
stackBuilder.addParentStack(SplashActivity::class.java.cmp(context.packageName))
|
||||
stackBuilder.addNextIntent(intent)
|
||||
val pendingIntent = stackBuilder.getPendingIntent(
|
||||
Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val builder = updateBuilder(context)
|
||||
.setContentTitle(context.getString(R.string.magisk_update_title))
|
||||
.setContentText(context.getString(R.string.manager_download_install))
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
|
||||
mgr.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
||||
fun managerUpdate(context: Context) {
|
||||
val intent = DownloadService.pendingIntent(context, Subject.Manager())
|
||||
|
||||
val builder = updateBuilder(context)
|
||||
.setContentTitle(context.getString(R.string.manager_update_title))
|
||||
.setContentTitle(context.getString(R.string.magisk_update_title))
|
||||
.setContentText(context.getString(R.string.manager_download_install))
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(intent)
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.view
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ShortcutInfo
|
||||
@@ -8,6 +7,8 @@ import android.content.pm.ShortcutManager
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
@@ -24,16 +25,14 @@ object Shortcuts {
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(26)
|
||||
fun addHomeIcon(context: Context) {
|
||||
val manager = context.getSystemService<ShortcutManager>() ?: return
|
||||
val intent = context.packageManager.getLaunchIntentForPackage(context.packageName) ?: return
|
||||
val info = ShortcutInfo.Builder(context, Const.Nav.HOME)
|
||||
.setShortLabel(context.getString(R.string.app_name))
|
||||
val info = ShortcutInfoCompat.Builder(context, Const.Nav.HOME)
|
||||
.setShortLabel(context.getString(R.string.magisk))
|
||||
.setIntent(intent)
|
||||
.setIcon(context.getIcon(R.drawable.ic_launcher))
|
||||
.setIcon(context.getIconCompat(R.drawable.ic_launcher))
|
||||
.build()
|
||||
manager.requestPinShortcut(info, null)
|
||||
ShortcutManagerCompat.requestPinShortcut(context, info, null)
|
||||
}
|
||||
|
||||
private fun Context.getIconCompat(id: Int): IconCompat {
|
||||
|
@@ -19,18 +19,10 @@ public abstract class JarMap implements Closeable {
|
||||
|
||||
LinkedHashMap<String, JarEntry> entryMap;
|
||||
|
||||
public static JarMap open(String file) throws IOException {
|
||||
return new FileMap(new File(file), true, ZipFile.OPEN_READ);
|
||||
}
|
||||
|
||||
public static JarMap open(File file, boolean verify) throws IOException {
|
||||
return new FileMap(file, verify, ZipFile.OPEN_READ);
|
||||
}
|
||||
|
||||
public static JarMap open(String file, boolean verify) throws IOException {
|
||||
return new FileMap(new File(file), verify, ZipFile.OPEN_READ);
|
||||
}
|
||||
|
||||
public static JarMap open(InputStream is, boolean verify) throws IOException {
|
||||
return new StreamMap(is, verify);
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.signing;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@@ -32,6 +33,7 @@ import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Arrays;
|
||||
|
||||
@Keep
|
||||
public class SignBoot {
|
||||
|
||||
private static final int BOOT_IMAGE_HEADER_V1_RECOVERY_DTBO_SIZE_OFFSET = 1632;
|
||||
@@ -88,6 +90,21 @@ public class SignBoot {
|
||||
}
|
||||
}
|
||||
|
||||
private static int fullRead(InputStream in, byte[] b) throws IOException {
|
||||
return fullRead(in, b, 0, b.length);
|
||||
}
|
||||
|
||||
private static int fullRead(InputStream in, byte[] b, int off, int len) throws IOException {
|
||||
int n = 0;
|
||||
while (n < len) {
|
||||
int count = in.read(b, off + n, len - n);
|
||||
if (count <= 0)
|
||||
break;
|
||||
n += count;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public static boolean doSignature(
|
||||
@Nullable X509Certificate cert, @Nullable PrivateKey key,
|
||||
@NonNull InputStream imgIn, @NonNull OutputStream imgOut, @NonNull String target
|
||||
@@ -96,7 +113,7 @@ public class SignBoot {
|
||||
PushBackRWStream in = new PushBackRWStream(imgIn, imgOut);
|
||||
byte[] hdr = new byte[BOOT_IMAGE_HEADER_SIZE_MAXIMUM];
|
||||
// First read the header
|
||||
in.read(hdr);
|
||||
fullRead(in, hdr);
|
||||
int signableSize = getSignableImageSize(hdr);
|
||||
// Unread header
|
||||
in.unread(hdr);
|
||||
@@ -126,7 +143,7 @@ public class SignBoot {
|
||||
try {
|
||||
// Read the header for size
|
||||
byte[] hdr = new byte[BOOT_IMAGE_HEADER_SIZE_MAXIMUM];
|
||||
if (imgIn.read(hdr) != hdr.length) {
|
||||
if (fullRead(imgIn, hdr) != hdr.length) {
|
||||
System.err.println("Unable to read image header");
|
||||
return false;
|
||||
}
|
||||
@@ -135,7 +152,7 @@ public class SignBoot {
|
||||
// Read the rest of the image
|
||||
byte[] rawImg = Arrays.copyOf(hdr, signableSize);
|
||||
int remain = signableSize - hdr.length;
|
||||
if (imgIn.read(rawImg, hdr.length, remain) != remain) {
|
||||
if (fullRead(imgIn, rawImg, hdr.length, remain) != remain) {
|
||||
System.err.println("Unable to read image");
|
||||
return false;
|
||||
}
|
||||
|
@@ -3,9 +3,9 @@
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?colorSecondary" />
|
||||
<solid android:color="@android:color/black" />
|
||||
<corners android:bottomLeftRadius="2dp" android:bottomRightRadius="2dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
</selector>
|
||||
|
@@ -3,9 +3,9 @@
|
||||
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="?colorSecondary" />
|
||||
<solid android:color="@android:color/black" />
|
||||
<corners android:topLeftRadius="2dp" android:topRightRadius="2dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
||||
</selector>
|
||||
|
@@ -35,6 +35,7 @@
|
||||
style="@style/WidgetFoundation.Appbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_behavior="com.topjohnwu.magisk.utils.HideTopViewOnScrollBehavior"
|
||||
app:fitsSystemWindowsInsets="top">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
@@ -76,6 +77,7 @@
|
||||
android:layout_marginBottom="@dimen/l1"
|
||||
android:fitsSystemWindows="false"
|
||||
app:layout_fitsSystemWindowsInsets="bottom"
|
||||
app:layout_behavior="com.topjohnwu.magisk.utils.HideBottomViewOnScrollBehavior"
|
||||
tools:layout_marginBottom="64dp">
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
|
@@ -108,7 +108,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/home_magisk_wrapper" />
|
||||
|
||||
<Space
|
||||
gone="@{!viewModel.showSafetyNet && !viewModel.showUninstall}"
|
||||
gone="@{!viewModel.showSafetyNet && !Info.env.isActive}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/l1" />
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Outlined.Error"
|
||||
gone="@{!viewModel.showUninstall}"
|
||||
goneUnless="@{Info.env.isActive}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
|
@@ -25,306 +25,218 @@
|
||||
app:fitsSystemWindowsInsets="top|bottom"
|
||||
tools:paddingTop="24dp">
|
||||
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/l_50">
|
||||
|
||||
<LinearLayout
|
||||
goneUnless="@{viewModel.loaded && viewModel.progress <= 0}"
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
gone="@{viewModel.skipOptions}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/l_50">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
gone="@{viewModel.skipOptions}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:focusable="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
style="@style/WidgetFoundation.Icon"
|
||||
isSelected="@{viewModel.step > 0}"
|
||||
android:layout_marginStart="@dimen/l_25"
|
||||
app:srcCompat="@drawable/ic_check_circle_md2" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/install_options_title"
|
||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.step != 0}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.step(1)}"
|
||||
android:text="@string/install_next" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
gone="@{viewModel.step != 0}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l_50"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:layout_marginBottom="@dimen/l_50"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="3dp"
|
||||
android:paddingEnd="3dp"
|
||||
tools:layout_gravity="center">
|
||||
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
gone="@{Info.isSAR}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.keepVerity}"
|
||||
android:text="@string/keep_dm_verity"
|
||||
tools:checked="true" />
|
||||
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
goneUnless="@{Info.isFDE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.keepEnc}"
|
||||
android:text="@string/keep_force_encryption"
|
||||
app:tint="?colorPrimary" />
|
||||
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
gone="@{Info.ramdisk}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.recovery}"
|
||||
android:text="@string/recovery_mode"
|
||||
app:tint="?colorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:focusable="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
style="@style/WidgetFoundation.Icon"
|
||||
isSelected="@{viewModel.step > 1}"
|
||||
android:layout_marginStart="@dimen/l_25"
|
||||
app:srcCompat="@drawable/ic_check_circle_md2" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/install_method_title"
|
||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.step != 1}"
|
||||
isEnabled="@{viewModel.method == @id/method_patch ? viewModel.data != null : viewModel.method != -1}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.install()}"
|
||||
android:text="@string/install_start"
|
||||
app:icon="@drawable/ic_forth_md2"
|
||||
app:iconGravity="textEnd" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioGroup
|
||||
gone="@{viewModel.step != 1}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l_50"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:layout_marginBottom="@dimen/l_50"
|
||||
android:checkedButton="@={viewModel.method}"
|
||||
android:paddingStart="3dp"
|
||||
android:paddingEnd="3dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_download"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_zip_only"
|
||||
tools:checked="true" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_patch"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/select_patch_file" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_direct"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
gone="@{!viewModel.rooted}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/direct_install" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_inactive_slot"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
gone="@{!viewModel.isRooted || Info.isPixel || !Info.isAB}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/install_inactive_slot" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/l1"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:focusable="false">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/release_notes"
|
||||
markdownText="@{viewModel.notes}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="15dp"
|
||||
android:textAppearance="@style/AppearanceFoundation.Caption"
|
||||
android:visibility="gone"
|
||||
tools:maxLines="5"
|
||||
tools:text="@tools:sample/lorem/random"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
goneUnless="@{viewModel.loading}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
android:focusable="false">
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/loading"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/l1">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ProgressBar
|
||||
style="@style/WidgetFoundation.ProgressBar"
|
||||
invisible="@{viewModel.progress <= 0}"
|
||||
android:layout_width="100dp"
|
||||
android:layout_gravity="center"
|
||||
android:progress="@{viewModel.progress}" />
|
||||
<ImageView
|
||||
style="@style/WidgetFoundation.Icon"
|
||||
isSelected="@{viewModel.step > 0}"
|
||||
android:layout_marginStart="@dimen/l_25"
|
||||
app:srcCompat="@drawable/ic_check_circle_md2" />
|
||||
|
||||
<ProgressBar
|
||||
style="@style/WidgetFoundation.ProgressBar.Indeterminate"
|
||||
invisibleUnless="@{viewModel.progress <= 0}"
|
||||
android:layout_width="100dp"
|
||||
android:layout_gravity="center" />
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/install_options_title"
|
||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</FrameLayout>
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.step != 0}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.step(1)}"
|
||||
android:text="@string/install_next" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
gone="@{viewModel.step != 0}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l_50"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:layout_marginBottom="@dimen/l_50"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="3dp"
|
||||
android:paddingEnd="3dp"
|
||||
tools:layout_gravity="center">
|
||||
|
||||
<LinearLayout
|
||||
goneUnless="@{viewModel.loaded && viewModel.progress >= 100}"
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
gone="@{Info.isSAR}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.keepVerity}"
|
||||
android:text="@string/keep_dm_verity"
|
||||
tools:checked="true" />
|
||||
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
goneUnless="@{Info.isFDE}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.keepEnc}"
|
||||
android:text="@string/keep_force_encryption"
|
||||
app:tint="?colorPrimary" />
|
||||
|
||||
<CheckBox
|
||||
style="@style/WidgetFoundation.Checkbox"
|
||||
gone="@{Info.ramdisk}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={Config.recovery}"
|
||||
android:text="@string/recovery_mode"
|
||||
app:tint="?colorPrimary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:focusable="false">
|
||||
|
||||
<TextView
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/download_complete"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title" />
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
goneUnless="@{viewModel.loadFailed}"
|
||||
<ImageView
|
||||
style="@style/WidgetFoundation.Icon"
|
||||
isSelected="@{viewModel.step > 1}"
|
||||
android:layout_marginStart="@dimen/l_25"
|
||||
app:srcCompat="@drawable/ic_check_circle_md2" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/install_method_title"
|
||||
android:textAppearance="@style/AppearanceFoundation.Body"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.step != 1}"
|
||||
isEnabled="@{viewModel.method == @id/method_patch ? viewModel.data != null : viewModel.method != -1}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.install()}"
|
||||
android:text="@string/install_start"
|
||||
app:icon="@drawable/ic_forth_md2"
|
||||
app:iconGravity="textEnd" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioGroup
|
||||
gone="@{viewModel.step != 1}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginTop="@dimen/l_50"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:layout_marginBottom="@dimen/l_50"
|
||||
android:checkedButton="@={viewModel.method}"
|
||||
android:paddingStart="3dp"
|
||||
android:paddingEnd="3dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_patch"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/select_patch_file" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_direct"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
gone="@{!viewModel.rooted}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/direct_install" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/method_inactive_slot"
|
||||
style="@style/WidgetFoundation.RadioButton"
|
||||
gone="@{viewModel.noSecondSlot}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/install_inactive_slot" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/WidgetFoundation.Card"
|
||||
gone="@{viewModel.notes.empty}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
android:layout_marginTop="@dimen/l1"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:layout_marginEnd="@dimen/l1"
|
||||
android:focusable="false">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/release_notes"
|
||||
markdownText="@{viewModel.notes}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/download_file_error"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title" />
|
||||
android:layout_margin="15dp"
|
||||
android:textAppearance="@style/AppearanceFoundation.Caption"
|
||||
android:visibility="gone"
|
||||
tools:maxLines="5"
|
||||
tools:text="@tools:sample/lorem/random"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
@@ -46,46 +46,52 @@
|
||||
android:text="@string/magisk"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title"
|
||||
android:textColor="?colorPrimary"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_magisk_icon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/home_magisk_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/home_magisk_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_magisk_icon" />
|
||||
|
||||
<Button
|
||||
<FrameLayout
|
||||
android:id="@+id/home_magisk_button"
|
||||
style="@style/WidgetFoundation.Button"
|
||||
invisible="@{viewModel.stateMagisk != MagiskState.OBSOLETE}"
|
||||
android:enabled="@{viewModel.stateManager != MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onMagiskPressed()}"
|
||||
android:text="@string/update"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_update_md2"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_magisk_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_magisk_title"/>
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_magisk_title"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_magisk_title">
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
invisible="@{viewModel.stateMagisk == MagiskState.OBSOLETE}"
|
||||
android:enabled="@{viewModel.stateManager != MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onMagiskPressed()}"
|
||||
android:text="@string/install"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_install"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_magisk_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_magisk_title"/>
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button"
|
||||
gone="@{viewModel.stateMagisk != MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onMagiskPressed()}"
|
||||
android:text="@string/update"
|
||||
android:textAllCaps="false"
|
||||
android:layout_gravity="end"
|
||||
app:icon="@drawable/ic_update_md2" />
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.stateMagisk == MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:onClick="@{() -> viewModel.onMagiskPressed()}"
|
||||
android:text="@string/install"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_install"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/home_magisk_title_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
tools:constraint_referenced_ids="home_magisk_button,home_magisk_title,home_magisk_icon" />
|
||||
app:referencedIds="@{viewModel.magiskTitleBarrierIds}"
|
||||
tools:constraint_referenced_ids="home_magisk_icon,home_magisk_title,home_magisk_button" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
@@ -105,41 +111,24 @@
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_magisk_latest_version"
|
||||
android:id="@+id/home_magisk_installed_version"
|
||||
style="@style/W.Home.Item.Top"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent"
|
||||
android:text="@string/home_latest_version" />
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{viewModel.loadFailed ? @string/not_available : viewModel.magiskRemoteVersion }"
|
||||
tools:text="20.1 (12345)" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_magisk_installed_version"
|
||||
style="@style/W.Home.Item"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/home_magisk_latest_version">
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent"
|
||||
android:text="@string/home_installed_version" />
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{Info.env.isActive ? viewModel.magiskInstalledVersion : @string/not_available}"
|
||||
tools:text="20.1 (12345)" />
|
||||
android:text="@{viewModel.magiskInstalledVersion}"
|
||||
tools:text="22.0 (22000)" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_device_details_recovery"
|
||||
android:id="@+id/home_device_details_ramdisk"
|
||||
style="@style/W.Home.Item.Bottom"
|
||||
app:layout_constraintStart_toStartOf="@+id/home_magisk_installed_version"
|
||||
app:layout_constraintTop_toBottomOf="@+id/home_magisk_installed_version">
|
||||
@@ -160,7 +149,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="end"
|
||||
tools:constraint_referenced_ids="home_magisk_latest_version,home_magisk_installed_version"/>
|
||||
app:referencedIds="@{viewModel.magiskDetailBarrierIds}"
|
||||
tools:constraint_referenced_ids="home_magisk_installed_version,home_device_details_ramdisk"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_device_details_ab"
|
||||
@@ -181,7 +171,7 @@
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_device_details_sar"
|
||||
style="@style/W.Home.Item"
|
||||
style="@style/W.Home.Item.Bottom"
|
||||
app:layout_constraintStart_toStartOf="@+id/home_device_details_ab"
|
||||
app:layout_constraintTop_toBottomOf="@+id/home_device_details_ab">
|
||||
|
||||
@@ -196,23 +186,6 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/home_device_details_crypto"
|
||||
style="@style/W.Home.Item.Bottom"
|
||||
app:layout_constraintStart_toStartOf="@+id/home_device_details_sar"
|
||||
app:layout_constraintTop_toBottomOf="@+id/home_device_details_sar">
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent"
|
||||
android:text="Crypto" />
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{Info.cryptoText}"
|
||||
tools:text="N/A" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -43,48 +43,56 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/l1"
|
||||
android:text="@string/manager"
|
||||
android:text="@string/home_app_title"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title"
|
||||
android:textColor="?colorPrimary"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_manager_icon"
|
||||
app:layout_constraintEnd_toStartOf="@+id/home_manager_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/home_manager_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/manager" />
|
||||
tools:text="@string/home_app_title" />
|
||||
|
||||
<Button
|
||||
<FrameLayout
|
||||
android:id="@+id/home_manager_button"
|
||||
style="@style/WidgetFoundation.Button"
|
||||
invisible="@{viewModel.stateManager != MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onManagerPressed()}"
|
||||
android:text="@string/update"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_update_md2"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_manager_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_manager_title"/>
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_manager_title"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_manager_title">
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
invisible="@{viewModel.stateManager == MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onManagerPressed()}"
|
||||
android:text="@string/install"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_install"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/home_manager_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/home_manager_title"/>
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button"
|
||||
gone="@{viewModel.stateManager != MagiskState.OBSOLETE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{() -> viewModel.onManagerPressed()}"
|
||||
android:text="@string/update"
|
||||
android:textAllCaps="false"
|
||||
android:layout_gravity="end"
|
||||
app:icon="@drawable/ic_update_md2" />
|
||||
|
||||
<Button
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
gone="@{viewModel.stateManager != MagiskState.UP_TO_DATE}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:onClick="@{() -> viewModel.onManagerPressed()}"
|
||||
android:text="@string/install"
|
||||
android:textAllCaps="false"
|
||||
app:icon="@drawable/ic_install"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/home_manager_title_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="bottom"
|
||||
tools:constraint_referenced_ids="home_manager_button,home_manager_title,home_manager_icon" />
|
||||
app:referencedIds="@{viewModel.appTitleBarrierIds}"
|
||||
tools:constraint_referenced_ids="home_manager_icon,home_manager_title,home_manager_button" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
@@ -115,8 +123,8 @@
|
||||
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{viewModel.loadFailed ? @string/not_available : viewModel.managerRemoteVersion}"
|
||||
tools:text="8.0.0 (123) (10)" />
|
||||
android:text="@{viewModel.managerRemoteVersion}"
|
||||
tools:text="22.0 (22000) (16)" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -133,7 +141,7 @@
|
||||
<TextView
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{viewModel.managerInstalledVersion}"
|
||||
tools:text="8.0.0 (123) (10)" />
|
||||
tools:text="22.0 (22000) (16)" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -150,7 +158,7 @@
|
||||
<TextView
|
||||
android:id="@+id/home_manager_extra_connection_value"
|
||||
style="@style/W.Home.ItemContent.Right"
|
||||
android:text="@{viewModel.statePackageName}"
|
||||
android:text="@{context.packageName}"
|
||||
tools:text="com.topjohnwu.magisk" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@@ -64,7 +64,7 @@
|
||||
app:layout_constraintStart_toEndOf="@+id/hide_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="@string/app_name" />
|
||||
tools:text="@string/magisk" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hide_package"
|
||||
|
@@ -58,7 +58,7 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/app_name" />
|
||||
tools:text="@string/magisk" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/log_date"
|
||||
|
@@ -29,14 +29,15 @@
|
||||
tools:layout_gravity="center"
|
||||
tools:minHeight="?listPreferredItemHeightSmall">
|
||||
|
||||
<View
|
||||
<ImageView
|
||||
android:id="@+id/track_top"
|
||||
invisible="@{isTop}"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:alpha=".3"
|
||||
android:background="@drawable/bg_line_bottom_rounded"
|
||||
app:tint="?colorSecondary"
|
||||
app:srcCompat="@drawable/bg_line_bottom_rounded"
|
||||
app:layout_constraintBottom_toTopOf="@+id/track_bullet"
|
||||
app:layout_constraintEnd_toEndOf="@+id/track_bullet"
|
||||
app:layout_constraintStart_toStartOf="@+id/track_bullet"
|
||||
@@ -54,14 +55,15 @@
|
||||
app:tint="@color/color_primary_error_transient"
|
||||
tools:srcCompat="@drawable/ic_check_md2" />
|
||||
|
||||
<View
|
||||
<ImageView
|
||||
android:id="@+id/track_bottom"
|
||||
invisible="@{isBottom}"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:alpha=".3"
|
||||
android:background="@drawable/bg_line_top_rounded"
|
||||
app:tint="?colorSecondary"
|
||||
app:srcCompat="@drawable/bg_line_top_rounded"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/track_bullet"
|
||||
app:layout_constraintStart_toStartOf="@+id/track_bullet"
|
||||
|
@@ -61,7 +61,7 @@
|
||||
app:layout_constraintEnd_toStartOf="@+id/policy_indicator"
|
||||
app:layout_constraintStart_toEndOf="@+id/policy_app_icon"
|
||||
app:layout_constraintTop_toTopOf="@+id/policy_app_icon"
|
||||
tools:text="@string/app_name" />
|
||||
tools:text="@string/magisk" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/policy_package_name"
|
||||
|
@@ -49,10 +49,6 @@
|
||||
android:label="FlashFragment"
|
||||
tools:layout="@layout/fragment_flash_md2">
|
||||
|
||||
<argument
|
||||
android:name="installer"
|
||||
app:argType="android.net.Uri" />
|
||||
|
||||
<argument
|
||||
android:name="action"
|
||||
app:argType="string" />
|
||||
|
1
app/src/main/res/raw/.gitignore
vendored
1
app/src/main/res/raw/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/util_functions.sh
|
@@ -1,8 +1,8 @@
|
||||
## v8.0.7
|
||||
|
||||
- Fix sepolicy rule migration when upgrading
|
||||
|
||||
## v8.0.6
|
||||
|
||||
- Minor UI changes
|
||||
- Update internal scripts
|
||||
|
||||
## v8.0.5
|
||||
|
||||
- Fix sepolicy rule copying
|
||||
|
@@ -7,27 +7,41 @@ run_delay() {
|
||||
}
|
||||
|
||||
env_check() {
|
||||
for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do
|
||||
for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do
|
||||
[ -f $MAGISKBIN/$file ] || return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
fix_env() {
|
||||
cd $MAGISKBIN
|
||||
PATH=/system/bin /system/bin/sh update-binary -x
|
||||
./busybox rm -f update-binary magisk.apk
|
||||
./busybox chmod -R 755 .
|
||||
./magiskinit -x magisk magisk
|
||||
cp_readlink() {
|
||||
if [ -z $2 ]; then
|
||||
cd $1
|
||||
else
|
||||
cp -af $1/. $2
|
||||
cd $2
|
||||
fi
|
||||
for file in *; do
|
||||
if [ -L $file ]; then
|
||||
local full=$(readlink -f $file)
|
||||
rm $file
|
||||
cp -af $full $file
|
||||
fi
|
||||
done
|
||||
chmod -R 755 .
|
||||
cd /
|
||||
}
|
||||
|
||||
direct_install() {
|
||||
rm -rf $MAGISKBIN/* 2>/dev/null
|
||||
fix_env() {
|
||||
# Cleanup and make dirs
|
||||
rm -rf $MAGISKBIN/*
|
||||
mkdir -p $MAGISKBIN 2>/dev/null
|
||||
chmod 700 $NVBASE
|
||||
cp -af $1/. $MAGISKBIN
|
||||
rm -f $MAGISKBIN/new-boot.img
|
||||
cp_readlink $1 $MAGISKBIN
|
||||
rm -rf $1
|
||||
chown -R 0:0 $MAGISKBIN
|
||||
}
|
||||
|
||||
direct_install() {
|
||||
echo "- Flashing new boot image"
|
||||
flash_image $1/new-boot.img $2
|
||||
case $? in
|
||||
@@ -40,10 +54,22 @@ direct_install() {
|
||||
return 2
|
||||
;;
|
||||
esac
|
||||
rm -rf $1
|
||||
|
||||
rm -f $1/new-boot.img
|
||||
fix_env $1
|
||||
run_migrations
|
||||
copy_sepolicy_rules
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
run_uninstaller() {
|
||||
rm -rf /dev/tmp
|
||||
mkdir -p /dev/tmp/install
|
||||
unzip -o "$1" "assets/*" "lib/*" -d /dev/tmp/install
|
||||
INSTALLER=/dev/tmp/install sh /dev/tmp/install/assets/uninstaller.sh dummy 1 "$1"
|
||||
}
|
||||
|
||||
restore_imgs() {
|
||||
[ -z $SHA1 ] && return 1
|
||||
local BACKUPDIR=/data/magisk_backup_$SHA1
|
||||
@@ -63,15 +89,17 @@ restore_imgs() {
|
||||
}
|
||||
|
||||
post_ota() {
|
||||
cd $1
|
||||
cd /data/adb
|
||||
cp -f $1 bootctl
|
||||
rm -f $1
|
||||
chmod 755 bootctl
|
||||
./bootctl hal-info || return
|
||||
[ $(./bootctl get-current-slot) -eq 0 ] && SLOT_NUM=1 || SLOT_NUM=0
|
||||
./bootctl set-active-boot-slot $SLOT_NUM
|
||||
cat << EOF > post-fs-data.d/post_ota.sh
|
||||
${1}/bootctl mark-boot-successful
|
||||
rm -f ${1}/bootctl
|
||||
rm -f ${1}/post-fs-data.d/post_ota.sh
|
||||
/data/adb/bootctl mark-boot-successful
|
||||
rm -f /data/adb/bootctl
|
||||
rm -f /data/adb/post-fs-data.d/post_ota.sh
|
||||
EOF
|
||||
chmod 755 post-fs-data.d/post_ota.sh
|
||||
cd /
|
||||
@@ -172,8 +200,7 @@ grep_prop() { return; }
|
||||
# Initialize
|
||||
#############
|
||||
|
||||
mm_init() {
|
||||
export BOOTMODE=true
|
||||
app_init() {
|
||||
mount_partitions
|
||||
get_flags
|
||||
run_migrations
|
||||
@@ -183,3 +210,5 @@ mm_init() {
|
||||
# Make sure RECOVERYMODE has value
|
||||
[ -z $RECOVERYMODE ] && RECOVERYMODE=false
|
||||
}
|
||||
|
||||
export BOOTMODE=true
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">لا يوجد إتصال</string>
|
||||
<string name="app_changelog">تفاصيل التحديث</string>
|
||||
<string name="manager">المدير</string>
|
||||
<string name="loading">جارٍ التحميل...</string>
|
||||
<string name="update">تحديث</string>
|
||||
<string name="not_available">غير/متوفر</string>
|
||||
<string name="hide">إخفاء</string>
|
||||
<string name="status">الحالة</string>
|
||||
<string name="home_package">الحزمة</string>
|
||||
|
||||
<string name="home_notice_content">تأكد دوما أنك تستعمل إصدار ماجسيك رسمي، التطبيقات المثبتة من الجهات الخارجية ستسبب لك أضراراً</string>
|
||||
<string name="home_support_title">تبرع لنا</string>
|
||||
<string name="home_item_source">الكود المصدري للتطبيق</string>
|
||||
<string name="home_support_content">مـاجـيسك هي، وستظل دوماً، مجانيةً و مفتوحة المصدر، اظهر اهتمامك لنا لكي نبقيها هكذا بدعم مالي صغير</string>
|
||||
<string name="home_status_normal"> الوضـع الطبيعي</string>
|
||||
<string name="home_status_stub"> وضـع STUB</string>
|
||||
<string name="home_installed_version">تم التثبيت</string>
|
||||
<string name="home_latest_version">آخر إصدار</string>
|
||||
<string name="invalid_update_channel">مصدر التحديث غير صالح</string>
|
||||
@@ -43,7 +38,6 @@
|
||||
<string name="install_next">التالي</string>
|
||||
<string name="install_start">هيا، بنا</string>
|
||||
<string name="manager_download_install">اضغط للتنزيل و التثبيت</string>
|
||||
<string name="download_zip_only">تحميل Zip فقط</string>
|
||||
<string name="direct_install">تثبيت مباشر (موصى بها)</string>
|
||||
<string name="install_inactive_slot">التثبيت على المنطقة الغير نشطة (بعد OTA)</string>
|
||||
<string name="install_inactive_slot_msg">سيُجبر جهازك للاقلاع على المنطقة الغير النشطة بعد إعادة التشغيل!\n استخدم هذا الخيار فقط بعد الانتهاء من OTA. استمرار؟</string>
|
||||
@@ -133,10 +127,6 @@
|
||||
<string name="settings_download_path_message">ستحمل الملفات إلى %1$s</string>
|
||||
<string name="settings_clear_cache_title">حذف الذاكرة المؤقتة للإضافات</string>
|
||||
<string name="settings_clear_cache_summary">حذف المعلومات المخزنة محليا، هذا سيجبر التطبيق على التحديث الإضافات عبر الانترنت</string>
|
||||
<string name="settings_hide_manager_title">إخفاء مـاجـيسك Manager</string>
|
||||
<string name="settings_hide_manager_summary">تغيير اسم حزمة التطبيق لتجنب الكشف</string>
|
||||
<string name="settings_restore_manager_title">استعادة مـاجـيسك Manager</string>
|
||||
<string name="settings_restore_manager_summary">استعادة مـاجـيسك Manager مع اسم الحزمة الأصلي</string>
|
||||
<string name="language">اللغة</string>
|
||||
<string name="system_default">(الأفتراضي)</string>
|
||||
<string name="settings_check_update_title">تحقق من التحديثات</string>
|
||||
@@ -195,10 +185,7 @@
|
||||
<string name="progress_channel">إشعارات التقدم</string>
|
||||
<string name="download_complete">اكتمل التنزيل</string>
|
||||
<string name="download_file_error">فشل تنزيل الملف</string>
|
||||
<string name="download_open_parent">أظهر المجلد الرئيسي</string>
|
||||
<string name="download_open_self">أظهر الملف</string>
|
||||
<string name="magisk_update_title">تحديث مـاجـيسك متوفر!</string>
|
||||
<string name="manager_update_title">تحديث مـاجـيسك Manager متوفر!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">نعم</string>
|
||||
@@ -212,8 +199,6 @@
|
||||
<string name="flashing">يتم الحرق...</string>
|
||||
<string name="done">تم!</string>
|
||||
<string name="failure">فشل!</string>
|
||||
<string name="hide_manager_title">جار إخفاء مـاجـيسك Manager…</string>
|
||||
<string name="hide_manager_fail_toast">فشل إخفاء مـاجـيسك Manager…</string>
|
||||
<string name="open_link_failed_toast">لم يُعثر على تطبيق لفتح الرابط …</string>
|
||||
<string name="complete_uninstall">إلغاء التثبيت بالكامل</string>
|
||||
<string name="restore_img">استعادة الصور</string>
|
||||
@@ -221,13 +206,10 @@
|
||||
<string name="restore_done">تم الأستعادة</string>
|
||||
<string name="restore_fail">النسخة الاحتياطية الأصلية غير موجودة!</string>
|
||||
<string name="proprietary_title">تنزيل شفرة الملكية</string>
|
||||
<string name="proprietary_notice">مـاجـيسك برنامج FOSS(السرعة والأمان)،ولا يحتوي على شفرة SafetyNet الخاصة بكوكل.\n\nهل تسمح لـمـاجـيسك بتحميل ملحق GoogleApiClient لفحص SafetyNet?</string>
|
||||
<string name="setup_fail">فشل التضبيط</string>
|
||||
<string name="env_fix_title"> الإعداد الأضافي مطلوب</string>
|
||||
<string name="env_fix_msg">يحتاج جهازك إلى إعداد إضافي ليتسنى لـمـاجـيسك العمل بشكل صحيح. سيتم تنزيل ملف مضغوط لتثبيت مـاجـيسك هل تريد المتابعة؟</string>
|
||||
<string name="setup_msg">جار تضبيت البيئة</string>
|
||||
<string name="authenticate">تصديق</string>
|
||||
<string name="unsupport_magisk_title">إصدار مـاجـيسك غير مدعوم</string>
|
||||
<string name="unsupport_magisk_msg">إصدار الملف أصغر من %1$s.مـاجـيسك لا يدعمها..\n\nسيتصرف التطبيق كأنك لا تملك روت بجهازك.فضلاًً حدث المعجبين باسرع وقت.</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -43,10 +43,7 @@
|
||||
<string name="progress_channel">Nəticə Bildirişləri</string>
|
||||
<string name="download_complete">Yükləmə bitdi</string>
|
||||
<string name="download_file_error">Faylı yükləmək alınmadı</string>
|
||||
<string name="download_open_parent">Valideyn qovluğunda göstər</string>
|
||||
<string name="download_open_self">Faylı göstər</string>
|
||||
<string name="magisk_update_title">Magisk Yeniləməsi Var!</string>
|
||||
<string name="manager_update_title">Magisk Manager Yeniləməsi Var!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">%1$s faylını yüklə</string>
|
||||
@@ -57,10 +54,7 @@
|
||||
<string name="repo_cache_cleared">Repo keşi silindi</string>
|
||||
<string name="manager_download_install">Yükləyib quraşdırmaq üçün toxun.</string>
|
||||
<string name="flashing">Qurulur</string>
|
||||
<string name="hide_manager_title">Magisk Manager gizlədilir…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager\'i gizlətmək alınmadı.</string>
|
||||
<string name="open_link_failed_toast">Keçid açmağa heçbir tətbiq tapılmadı.</string>
|
||||
<string name="download_zip_only">Yalnız Zip yüklə</string>
|
||||
<string name="direct_install">Birdəfəlik Yüklə (Tövsiyə olunur)</string>
|
||||
<string name="select_patch_file">Fayl Seç və Yamaqla</string>
|
||||
<string name="install_inactive_slot">Fəal olmayan slota quraşdır (OTA\'dan sonra)</string>
|
||||
@@ -71,20 +65,14 @@
|
||||
<string name="restore_done">Geri qaytarma bitdi!</string>
|
||||
<string name="restore_fail">Stock nüsxə mövcud deyil!</string>
|
||||
<string name="proprietary_title">Özəl kodu yükləyin</string>
|
||||
<string name="proprietary_notice">Magisk Manager açıq lisenziyalıdır və Google\'ın özəl SafetyNet API kodunu ehtiva etmir.\n\Magisk Managerə SafetyNet yoxlamaları üçün tərkibində GoogleApiClient olan əlavəni yükləməyə icazə verirsiniz?</string>
|
||||
<string name="setup_fail">Quraşdırma alınmadı.</string>
|
||||
<string name="env_fix_title">Əlavə Quraşdırma Lazımdır</string>
|
||||
<string name="env_fix_msg">Cihazınızın Magisk\'in düzgün işləməsi üçün əlavə quraşdırmaya ehtiyacı var . Bu Magisk zip faylını endirəcək, davam etmək istəyirsiniz?</string>
|
||||
<string name="setup_title">Əlavə quraşdırma</string>
|
||||
<string name="setup_msg">Quraşdırma yerinə yetirilir…</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Repo Keşini Təmizlə</string>
|
||||
<string name="settings_clear_cache_summary">Onlayn repolar üçün keşlənmiş məlumatı silin. Bu tətbiqi onlayn şəkildə yenilənməyə məcbur edir.</string>
|
||||
<string name="settings_hide_manager_title">Magisk Manager\'i Gizlə</string>
|
||||
<string name="settings_hide_manager_summary">Magisk Manager\'i təsadüfi adla yenidən sıxışdır.</string>
|
||||
<string name="settings_restore_manager_title">Magisk Manager\'i Geri Qaytar</string>
|
||||
<string name="settings_restore_manager_summary">Magisk Manager\'i orjinal sıxışdırma ilə geri qaytar</string>
|
||||
<string name="language">Dil</string>
|
||||
<string name="system_default">(Sistem Dili)</string>
|
||||
<string name="settings_check_update_title">Yeniləmələri Yoxla</string>
|
||||
|
@@ -13,19 +13,14 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Злучэнне адсутнічае</string>
|
||||
<string name="app_changelog">Спіс змен</string>
|
||||
<string name="manager">Кіраўнік</string>
|
||||
<string name="loading">Загрузка…</string>
|
||||
<string name="update">Абнавіць</string>
|
||||
<string name="not_available">Не</string>
|
||||
<string name="hide">Схаваць</string>
|
||||
<string name="status">Статус</string>
|
||||
<string name="home_package">Пакунак</string>
|
||||
<string name="home_notice_content">Заўсёды правярайце адкуль вы спампоўваеце Magisk Manager. Пакункі, спампаваныя з невядомых крыніц, могуць змяшчаць шкоднасны код.</string>
|
||||
<string name="home_support_title">Падтрымайце нас</string>
|
||||
<string name="home_item_source">Зыходны код</string>
|
||||
<string name="home_support_content">Magisk ёсць і заўсёды будзе бясплатным праектам з адкрытым зыходным кодам. Але вы заўсёды можаце ахвяраваць нам на распрацоўку.</string>
|
||||
<string name="home_status_normal">Звычайны</string>
|
||||
<string name="home_status_stub">Хаванне</string>
|
||||
<string name="home_installed_version">Усталявана</string>
|
||||
<string name="home_latest_version">Апошні</string>
|
||||
<string name="invalid_update_channel">Хібны канал абнаўлення</string>
|
||||
@@ -41,7 +36,6 @@
|
||||
<string name="install_next">Далей</string>
|
||||
<string name="install_start">Усталяваць</string>
|
||||
<string name="manager_download_install">Націсніце, каб спампаваць і ўсталяваць</string>
|
||||
<string name="download_zip_only">Толькі спампаваць Zip з праграмай</string>
|
||||
<string name="direct_install">Непасрэдная ўсталёўка (рэкамендуецца)</string>
|
||||
<string name="install_inactive_slot">Усталяваць у неактыўны слот (пасля OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Ваша прылада ПРЫМУСОВА перазапусціцца ў неактыўны слот!\nВыкарыстоўвайце гэты параметр толькі пасля завяршэння OTA.\nПрацягнуць?</string>
|
||||
@@ -124,10 +118,6 @@
|
||||
<string name="settings_download_path_message">Файлы будуць спампоўвацца ў %1$s</string>
|
||||
<string name="settings_clear_cache_title">Ачыстка кэшу рэпазіторыя</string>
|
||||
<string name="settings_clear_cache_summary">Ачысціць кэш сеціўных рэпазіторыяў. Гэта прымусіць абнавіць кэш</string>
|
||||
<string name="settings_hide_manager_title">Схаваць Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Перапакваць Magisk Manager з выпадковай назвай і назвай пакунка</string>
|
||||
<string name="settings_restore_manager_title">Аднавіць Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Аднавіць Magisk Manager з арыгінальнай назвай і назвай пакунка</string>
|
||||
<string name="language">Мова</string>
|
||||
<string name="system_default">(Сістэмная)</string>
|
||||
<string name="settings_check_update_title">Правяраць на абнаўленні</string>
|
||||
@@ -186,10 +176,7 @@
|
||||
<string name="progress_channel">Апавяшчэнні пра ход выканання</string>
|
||||
<string name="download_complete">Спампоўка завершаная</string>
|
||||
<string name="download_file_error">Не атрымалася спампаваць файл</string>
|
||||
<string name="download_open_parent">Паказаць у каталозе</string>
|
||||
<string name="download_open_self">Паказаць файл</string>
|
||||
<string name="magisk_update_title">Даступна абнаўленне Magisk!</string>
|
||||
<string name="manager_update_title">Даступна абнаўленне Magisk Manager!</string>
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Так</string>
|
||||
<string name="no">Не</string>
|
||||
@@ -202,8 +189,6 @@
|
||||
<string name="flashing">Усталёўка…</string>
|
||||
<string name="done">Завершана!</string>
|
||||
<string name="failure">Не атрымалася</string>
|
||||
<string name="hide_manager_title">Хаванне Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Не атрымалася схаваць Magisk Manager.</string>
|
||||
<string name="open_link_failed_toast">Праграмы для адкрыцця спасылкі не знойдзена</string>
|
||||
<string name="complete_uninstall">Поўнае выдаленне</string>
|
||||
<string name="restore_img">Аднавіць раздзелы</string>
|
||||
@@ -211,16 +196,12 @@
|
||||
<string name="restore_done">Аднаўленне завершана!</string>
|
||||
<string name="restore_fail">Рэзервовая копія адсутнічае!</string>
|
||||
<string name="proprietary_title">Спампаваць прапрыетарны код</string>
|
||||
<string name="proprietary_notice">Magisk Manager - праект з адкрытым зыходным кодам, які не змяшчае прапрыетарны код SafetyNet API.\n\nДазволіць Magisk Manager спампаваць пашырэнне SafetyNet(змяшчае GoogleApiClient)?</string>
|
||||
<string name="setup_fail">Усталяваць не атрымалася</string>
|
||||
<string name="env_fix_title">Патрабуецца дадатковая ўсталёўка</string>
|
||||
<string name="env_fix_msg">Вашай прыладзе для карэктнай працы патрабуецца дадатковая ўсталёўка Magisk. Будзе спампаваны Zip Magisk. Працягнуць?</string>
|
||||
<string name="setup_msg">Наладка асяроддзя…</string>
|
||||
<string name="authenticate">Аўтэнтыфікацыя</string>
|
||||
<string name="unsupport_magisk_title">Непадтрымліваемая версія Magisk</string>
|
||||
<string name="unsupport_magisk_msg">Гэтая версія Magisk Manager не падтрымлівае Magisk версіі ніжэй за %1$s.\n\nПраграма будзе працаваць так, як быццам Magisk не ўсталяваны. Як мага хутчэй абнавіце Magisk.</string>
|
||||
<string name="external_rw_permission_denied">Дайце доступ да сховішча, каб уключыць гэтую функцыю</string>
|
||||
<string name="add_shortcut_title">Дадаць цэтлік на хатні экран</string>
|
||||
<string name="add_shortcut_msg">Пасля хавання Magisk Manager яго значок і назву можа быць цяжка разглядзець. Хочаце дадаць цэтлік на хатні экран?</string>
|
||||
<string name="app_not_found">Не знойдзена праграм для апрацоўкі гэтага дзеяння</string>
|
||||
</resources>
|
||||
|
@@ -46,14 +46,10 @@
|
||||
<string name="magisk_update_title">Налице е нова версия на Magisk.</string>
|
||||
<string name="release_notes">Бележки</string>
|
||||
<string name="repo_cache_cleared">Кешът на хранилището е изчистен.</string>
|
||||
<string name="manager_update_title">Налице е нова версия на Magisk Manager.</string>
|
||||
<string name="manager_download_install">Докоснете за изтегляне и инсталиране.</string>
|
||||
<string name="update_channel">Актуализации на Magisk</string>
|
||||
<string name="flashing">Инсталиране</string>
|
||||
<string name="hide_manager_title">Скриване на Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Скриването на Magisk Manager бе неуспешно.</string>
|
||||
<string name="open_link_failed_toast">Не бе намерено приложение за отваряне на линка.</string>
|
||||
<string name="download_zip_only">Изтегляне само на архив</string>
|
||||
<string name="direct_install">Директно инсталиране (Препоръчва се.)</string>
|
||||
<string name="install_inactive_slot">Инсталиране на неактивен слот (След OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Вашето устройство НАЛОЖИТЕЛНО ще стартира текущия неактивен слот при следващото рестартиране.\nИзползвайте тази опция само след като приключи инсталирането на OTA.\nПродължаване?</string>
|
||||
@@ -64,10 +60,8 @@
|
||||
<string name="restore_done">Възстановяването е успешно!</string>
|
||||
<string name="restore_fail">Не е налице архив на стоковия образ!</string>
|
||||
<string name="proprietary_title">Изтегляне на патентования код</string>
|
||||
<string name="proprietary_notice">Magisk Manager е FOSS и затова не включва патентования код за SafetyNet ППИ на Google.\n\nПозволявате ли на Magisk Manager да изтегли добавката (включва GoogleApiClient) за SafetyNet проверки?</string>
|
||||
<string name="setup_fail">Първоначалната настройка е неуспешна.</string>
|
||||
<string name="env_fix_title">Изисква допълнително настройване</string>
|
||||
<string name="env_fix_msg">Вашето устройство се нуждае от допълнително надстройване на Magisk, за да работи нормално. Ще бъде изтеглен архивът за надстройка на Magisk. Желаете ли да продължите?</string>
|
||||
<string name="setup_title">Допълнително надстройване</string>
|
||||
<string name="setup_msg">Надстройването на средата е в ход…</string>
|
||||
<string name="download_file_error">Грешка при изтеглянето на файла.</string>
|
||||
@@ -75,10 +69,6 @@
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Изчистване кеша на хранилището</string>
|
||||
<string name="settings_clear_cache_summary">Изчистване на кешираната информация на онлайн хранилището за принудителното му обновяване.</string>
|
||||
<string name="settings_hide_manager_title">Скриване на Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Смяна пакетното наименование на Magisk Manager със случайно наименование.</string>
|
||||
<string name="settings_restore_manager_title">Възстановяване на Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Възстановяване на оригиналното пакетно наименование на Magisk Manager.</string>
|
||||
<string name="language">Език</string>
|
||||
<string name="system_default">(Системен)</string>
|
||||
<string name="settings_check_update_title">Проверка за актуализации</string>
|
||||
|
@@ -14,20 +14,17 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Connexió no disponible</string>
|
||||
<string name="app_changelog">Registre de canvis</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Carregant…</string>
|
||||
<string name="update">Actualització</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Amagar</string>
|
||||
<string name="status">Estat</string>
|
||||
<string name="home_package">Paquet</string>
|
||||
<string name="home_app_title">App</string>
|
||||
|
||||
<string name="home_notice_content">Asseguris sempre que està utilitzant un Magisk Manager de codi lliure. Mànagers de fonts desconegudes podrien causar accions malicioses.</string>
|
||||
<string name="home_support_title">Doni\'ns suport</string>
|
||||
<string name="home_notice_content">Descarregui Magisk NOMÉS des de la pàgina oficial de GitHub. Fitxers d\'altres fonts desconegudes poden ser maliciosos!</string>
|
||||
<string name="home_support_title">Doni suport</string>
|
||||
<string name="home_item_source">Codi font</string>
|
||||
<string name="home_support_content">Magisk és, i sempre serà, gratis i codi lliure. De totes maneres, pot mostrar el seu interès fent una petita donació.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Instal·lat</string>
|
||||
<string name="home_latest_version">Última</string>
|
||||
<string name="invalid_update_channel">Canal d\'actualització invàlid</string>
|
||||
@@ -44,7 +41,6 @@
|
||||
<string name="install_next">Següent</string>
|
||||
<string name="install_start">Endavant</string>
|
||||
<string name="manager_download_install">Premi per baixar i instal·lar</string>
|
||||
<string name="download_zip_only">Únicament baixa el ZIP</string>
|
||||
<string name="direct_install">Instal·lació directa (Recomanat)</string>
|
||||
<string name="install_inactive_slot">Instal·la a la ranura inactiva (Després d\'una OTA)</string>
|
||||
<string name="install_inactive_slot_msg">El teu dispositiu serà FORÇAT a arrancar en l\'actual ranura inactiva després del reinici!\nUtilitza aquesta opció NOMÉS quan l\'OTA s\'hagi fet.\nContinuar?</string>
|
||||
@@ -56,6 +52,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Petició de superusuari</string>
|
||||
<string name="touch_filtered_warning">Com que una aplicació està ofuscant la petició de superusuari, Magisk no pot verificar la seva resposta</string>
|
||||
<string name="deny">Denegar</string>
|
||||
<string name="prompt">Preguntar</string>
|
||||
<string name="grant">Permetre</string>
|
||||
@@ -85,7 +82,7 @@
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">No hi ha cap registre. Provi d\'utilitzar aplicacions que requereixen permisos de superusuari.</string>
|
||||
<string name="log_data_magisk_none">Els registre de Magisk estan buits. Això és estrany.</string>
|
||||
<string name="log_data_magisk_none">Els registres de Magisk estan buits. Això és estrany.</string>
|
||||
<string name="menuSaveLog">Desar registre</string>
|
||||
<string name="menuClearLog">Netejar registre ara</string>
|
||||
<string name="logs_cleared">Registre netejat correctament.</string>
|
||||
@@ -97,18 +94,20 @@
|
||||
<string name="safetynet_res_invalid">La resposta és invàlida</string>
|
||||
<string name="safetynet_attest_success">Èxit!</string>
|
||||
<string name="safetynet_attest_failure">Certificació fallida!</string>
|
||||
<string name="safetynet_attest_loading">Només un segon…</string>
|
||||
<string name="safetynet_attest_loading">Esperi uns segons…</string>
|
||||
<string name="safetynet_attest_restart">Intenta de nou</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostra aplicacions del sistema</string>
|
||||
<string name="show_os_app">Mostra aplicacions del SO</string>
|
||||
<string name="hide_filter_hint">Filtra per nom</string>
|
||||
<string name="hide_scroll_up">Vés amunt</string>
|
||||
<string name="hide_filters">Filtres</string>
|
||||
<string name="hide_search">Cerca</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(No hi ha informació)</string>
|
||||
<string name="reboot_userspace">Reinici suau</string>
|
||||
<string name="reboot_recovery">Reiniciar en Mode Recuperació</string>
|
||||
<string name="reboot_bootloader">Reiniciar en Mode Bootloader</string>
|
||||
<string name="reboot_download">Reiniciar en Mode Download</string>
|
||||
@@ -124,7 +123,7 @@
|
||||
<string name="module_section_online">En línia</string>
|
||||
<string name="sorting_order">Ordre de Classificació</string>
|
||||
|
||||
<!--Settings -->
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">Mode del tema</string>
|
||||
<string name="settings_dark_mode_message">Seleccioni el mode que més s\'adeqüi al seu estil!</string>
|
||||
<string name="settings_dark_mode_light">Sempre clar</string>
|
||||
@@ -133,11 +132,11 @@
|
||||
<string name="settings_download_path_title">Directori de baixades</string>
|
||||
<string name="settings_download_path_message">Els arxius es desaran a %1$s</string>
|
||||
<string name="settings_clear_cache_title">Netejar memòria cau del repositori</string>
|
||||
<string name="settings_clear_cache_summary">Neteja la informació en memòria cau per als repositoris en línia. Força a l\'aplicació a actualitzar-se en línia.</string>
|
||||
<string name="settings_hide_manager_title">Amagar Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Torna a empaquetar Magisk Manager amb un nom de paquet a l\'atzar</string>
|
||||
<string name="settings_restore_manager_title">Restaurar Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Restaura Magisk Manager amb el nom de paquet original</string>
|
||||
<string name="settings_clear_cache_summary">Neteja la informació en memòria cau per als repositoris en línia. Força a l\'aplicació a actualitzar-se en línia</string>
|
||||
<string name="settings_hide_app_title">Amagar Magisk Manager</string>
|
||||
<string name="settings_hide_app_summary">Torna a empaquetar Magisk Manager amb un nom de paquet a l\'atzar</string>
|
||||
<string name="settings_restore_app_title">Restaurar Magisk Manager</string>
|
||||
<string name="settings_restore_app_summary">Restaura Magisk Manager amb el nom de paquet original</string>
|
||||
<string name="language">Idioma</string>
|
||||
<string name="system_default">(Idioma del sistema)</string>
|
||||
<string name="settings_check_update_title">Comprovar Actualitzacions</string>
|
||||
@@ -170,6 +169,8 @@
|
||||
<string name="superuser_notification">Notificació de superusuari</string>
|
||||
<string name="settings_su_reauth_title">Demanar després d\'una actualització</string>
|
||||
<string name="settings_su_reauth_summary">Demanar permisos de superusuari novament si una aplicació és actualitzada o reinstal·lada</string>
|
||||
<string name="settings_su_tapjack_title">Activa la protecció contra \'TapJacking\'</string>
|
||||
<string name="settings_su_tapjack_summary">El diàleg per donar permisos de superusuari no respondrà mentre estigui ofuscat per alguna altra finestra o superposició</string>
|
||||
<string name="settings_su_biometric_title">Activar autenticació biomètrica</string>
|
||||
<string name="settings_su_biometric_summary">Utilitza l\'autenticació biomètrica per permetre sol·licituds de superusuari</string>
|
||||
<string name="no_biometric">El dispositiu no suporta o no té establerta configuració biomètrica</string>
|
||||
@@ -177,7 +178,7 @@
|
||||
<string name="setting_add_shortcut_summary">Afegeix una bonica drecera a la pantalla d\'inici en cas que el nom i la icona siguin difícils de reconèixer després d\'amagar l\'aplicació.</string>
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solució per enverinament de DNS en algunes nacions</string>
|
||||
|
||||
|
||||
<string name="multiuser_mode">Mode Multiusuari</string>
|
||||
<string name="settings_owner_only">Només Administrador del Dispositiu</string>
|
||||
<string name="settings_owner_manage">Administrador del Dispositiu</string>
|
||||
@@ -199,10 +200,7 @@
|
||||
<string name="progress_channel">Notificacions de progrés</string>
|
||||
<string name="download_complete">Baixada completada</string>
|
||||
<string name="download_file_error">Error en baixar l\'arxiu</string>
|
||||
<string name="download_open_parent">Mostra\'l al directori principal</string>
|
||||
<string name="download_open_self">Mostra l\'arxiu</string>
|
||||
<string name="magisk_update_title">Actualització de Magisk disponible!</string>
|
||||
<string name="manager_update_title">Actualització de Magisk Manager disponible!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Sí</string>
|
||||
@@ -216,8 +214,7 @@
|
||||
<string name="flashing">Arranjament…</string>
|
||||
<string name="done">Fet!</string>
|
||||
<string name="failure">Fallit</string>
|
||||
<string name="hide_manager_title">Amagant Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">No s\'ha pogut amagar Magisk Manager.</string>
|
||||
<string name="hide_app_title">Amagant Magisk Manager…</string>
|
||||
<string name="open_link_failed_toast">No s\'ha trobat una aplicació per obrir l\'enllaç</string>
|
||||
<string name="complete_uninstall">Desinstal·lació completa</string>
|
||||
<string name="restore_img">Restaura imatges</string>
|
||||
@@ -225,7 +222,7 @@
|
||||
<string name="restore_done">Restauració feta!</string>
|
||||
<string name="restore_fail">La còpia de seguretat de Estock no existeix!</string>
|
||||
<string name="proprietary_title">Baixar codi propietari</string>
|
||||
<string name="proprietary_notice">Magisk Manager és codi lliure i no conté codi de l\'API de SafetyNet, ja que és codi propietari de Google.\n\nVol permetre que Magisk Manager baixi una extensió (que conté la GoogleApiClient) per poder fer la comprovació de SafetyNet?</string>
|
||||
<string name="proprietary_notice">Magisk és codi lliure i no conté codi de l\'API de SafetyNet, ja que és codi propietari de Google.\n\nVol permetre que Magisk Manager baixi una extensió per poder fer la comprovació de SafetyNet?</string>
|
||||
<string name="setup_fail">Instal·lació fallida</string>
|
||||
<string name="env_fix_title">Es requereix instal·lació addicional</string>
|
||||
<string name="env_fix_msg">El teu dispositiu necessita instal·lació addicional per Magisk per funcionar correctament. Es baixarà el ZIP d\'instal·lació de Magisk, vol procedir a la instal·lació ara?</string>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<resources>
|
||||
|
||||
<!--Sections-->
|
||||
<string name="modules">Správce modulů</string>
|
||||
<string name="modules">Moduly</string>
|
||||
<string name="superuser">SuperUser</string>
|
||||
<string name="logs">Protokol</string>
|
||||
<string name="settings">Nastavení</string>
|
||||
@@ -14,21 +14,16 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Žádné připojení</string>
|
||||
<string name="app_changelog">Seznam změn</string>
|
||||
<string name="manager">Správce</string>
|
||||
<string name="loading">Načítání…</string>
|
||||
<string name="update">Aktualizovat</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Skrýt</string>
|
||||
<string name="status">Stav</string>
|
||||
<string name="home_package">Balíček</string>
|
||||
|
||||
<string name="home_notice_content">Zkontrolujte, zda používáte Magisk Manager s otevřeným kódem. Správce z neznámého zdroje může provádět nebezpečné akce!</string>
|
||||
<string name="home_support_title">Podpořte nás</string>
|
||||
<string name="home_item_source">Zdroj</string>
|
||||
<string name="home_support_content">Magisk je a vždy bude svobodný s otevřeným kódem. Můžete nám však zaslat malý dar jako poděkování.</string>
|
||||
<string name="home_status_normal">Normální</string>
|
||||
<string name="home_status_stub">Testovací</string>
|
||||
<string name="home_installed_version">Nainstalovaná</string>
|
||||
<string name="home_installed_version">Nainstalovano</string>
|
||||
<string name="home_latest_version">Poslední</string>
|
||||
<string name="invalid_update_channel">Neplatný kanál aktualizace</string>
|
||||
<string name="uninstall_magisk_title">Odinstalovat Magisk</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">Další</string>
|
||||
<string name="install_start">Spustit</string>
|
||||
<string name="manager_download_install">Stiskněte pro stažení a instalaci</string>
|
||||
<string name="download_zip_only">Stáhnout pouze soubor ZIP</string>
|
||||
<string name="direct_install">Přímá instalace (doporučeno)</string>
|
||||
<string name="install_inactive_slot">Instalace do druhého slotu (po OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Vaše zařízení bude po restartu VYNUCENĚ spuštěno do aktuálního neaktivního slotu!\nTuto možnost použijte pouze po dokončení OTA.\nChcete pokračovat?</string>
|
||||
@@ -116,7 +110,7 @@
|
||||
<string name="reboot_bootloader">Restartovat do Bootloader</string>
|
||||
<string name="reboot_download">Restartovat do Download</string>
|
||||
<string name="reboot_edl">Restartovat do EDL</string>
|
||||
<string name="module_version_author">%1$s z %2$s</string>
|
||||
<string name="module_version_author">%1$s od %2$s</string>
|
||||
<string name="module_section_pending">Aktualizace</string>
|
||||
<string name="module_section_pending_action">Aktualizovat vše</string>
|
||||
<string name="module_state_remove">Odstranit</string>
|
||||
@@ -137,13 +131,9 @@
|
||||
<string name="settings_download_path_message">Soubory budou uloženy do %1$s.</string>
|
||||
<string name="settings_clear_cache_title">Smazat mezipaměť</string>
|
||||
<string name="settings_clear_cache_summary">Smažete online informace o použití z mezipaměti, a tím na aplikaci vynutíte obnovení online informací.</string>
|
||||
<string name="settings_hide_manager_title">Skrýt Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Nahradíte Magisk Manager náhodným názvem balíčku.</string>
|
||||
<string name="settings_restore_manager_title">Obnovit Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Obnovíte Magisk Manager na původní název balíčku.</string>
|
||||
<string name="language">Jazyk</string>
|
||||
<string name="system_default">(výchozí podle systému)</string>
|
||||
<string name="settings_check_update_title">Automatické aktualizace</string>
|
||||
<string name="settings_check_update_title">Zkontrolovat aktualizace</string>
|
||||
<string name="settings_check_update_summary">Povolíte pravidelnou kontrolu aktualizace na pozadí.</string>
|
||||
<string name="settings_update_channel_title">Kanál aktualizace</string>
|
||||
<string name="settings_update_stable">Stabilní</string>
|
||||
@@ -204,10 +194,7 @@
|
||||
<string name="progress_channel">Oznámení o průběhu</string>
|
||||
<string name="download_complete">Stahování dokončeno</string>
|
||||
<string name="download_file_error">Chyba při stahování souboru</string>
|
||||
<string name="download_open_parent">Zobrazit výchozí složku</string>
|
||||
<string name="download_open_self">Zobrazit soubor</string>
|
||||
<string name="magisk_update_title">Aktualizace Magisk je dostupná!</string>
|
||||
<string name="manager_update_title">Aktualizace Magisk Manager je dostupná!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">ANO</string>
|
||||
@@ -221,9 +208,6 @@
|
||||
<string name="flashing">Instalování…</string>
|
||||
<string name="done">Hotovo!</string>
|
||||
<string name="failure">Selhalo!</string>
|
||||
<string name="hide_manager_title">Skrývání Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Skrývání Magisk Manager selhalo.</string>
|
||||
<string name="restore_manager_fail_toast">Obnovení Magisk Manager selhalo.</string>
|
||||
<string name="open_link_failed_toast">Nebyla nalezena žádná aplikace pro otevření odkazu.</string>
|
||||
<string name="complete_uninstall">Odinstalovat</string>
|
||||
<string name="restore_img">Obnovit obrazy</string>
|
||||
@@ -231,17 +215,13 @@
|
||||
<string name="restore_done">Obnovení bylo provedeno!</string>
|
||||
<string name="restore_fail">Výchozí záloha neexistuje!</string>
|
||||
<string name="proprietary_title">Stáhnout kód</string>
|
||||
<string name="proprietary_notice">Magisk Manager je FOSS a neobsahuje kód SafetyNet API společnosti Google.\n\nChcete povolit aplikaci Magisk Manager stažení rozšíření (obsahuje GoogleApiClient) pro kontrolu SafetyNet?</string>
|
||||
<string name="setup_fail">Nastavení selhalo</string>
|
||||
<string name="env_fix_title">Vyžaduje se další nastavení</string>
|
||||
<string name="env_fix_msg">Vaše zařízení potřebuje další nastavení, aby Magisk fungoval správně. Stáhne se instalační soubor (.zip) Magisk. Chcete pokračovat?</string>
|
||||
<string name="setup_msg">Nastavení je spuštěno…</string>
|
||||
<string name="authenticate">Ověřit</string>
|
||||
<string name="unsupport_magisk_title">Nepodporovaná verze Magisk</string>
|
||||
<string name="unsupport_magisk_msg">Tato verze Magisk Manager nepodporuje verzi Magisk nižší než %1$s.\n\nMůžete buď ručně aktualizovat Magisk, nebo nainstalovat starší verzi aplikace.</string>
|
||||
<string name="external_rw_permission_denied">Udělte oprávnění pro povolení této funkce.</string>
|
||||
<string name="add_shortcut_title">Přidat odkaz na domovskou obrazovku</string>
|
||||
<string name="add_shortcut_msg">Po skrytí Magisk Manager se může jeho název a ikona těžko rozpoznat. Chcete přidat odkaz na domovskou obrazovku?</string>
|
||||
<string name="app_not_found">Nelze nalézt žádnou aplikaci, která dokáže provést tuto akci.</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,25 +14,23 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Keine Verbindung verfügbar</string>
|
||||
<string name="app_changelog">Änderungen</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Laden…</string>
|
||||
<string name="update">Update</string>
|
||||
<string name="update">Aktualisieren</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Verstecken</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Paket</string>
|
||||
<string name="home_app_title">App</string>
|
||||
|
||||
<string name="home_notice_content">Benutzen Sie nur den quelloffenen Magisk Manager. Magisk von unbekannten Quellen kann zu schädlichen Aktionen führen.</string>
|
||||
<string name="home_notice_content">Laden sie Magisk NUR von der offiziellen Github Seite herunter. Dateien aus unbekannten Quellen können bösartig sein!</string>
|
||||
<string name="home_support_title">Unterstützen Sie uns</string>
|
||||
<string name="home_item_source">Quelle</string>
|
||||
<string name="home_support_content">Magisk ist und wird immer frei und quelloffen sein. Sie können uns jedoch jederzeit mit einer kleinen Spende unterstützen.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Installiert</string>
|
||||
<string name="home_latest_version">Neueste</string>
|
||||
<string name="invalid_update_channel">Ungültiger Update-Kanal</string>
|
||||
<string name="uninstall_magisk_title">Deinstalliere Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Alle Module werden deaktiviert/entfernt!\nRoot wird entfernt!\nIhre Daten werden potentiell verschlüsselt, wenn sie nicht bereits verschlüsselt sind!</string>
|
||||
<string name="home_check_safetynet">SafetyNet überprüfen</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Erzwungene Verschlüsselung beibehalten</string>
|
||||
@@ -43,7 +41,6 @@
|
||||
<string name="install_next">Nächster Schritt</string>
|
||||
<string name="install_start">Los geht\'s</string>
|
||||
<string name="manager_download_install">Tippen zum Herunterladen und Installieren</string>
|
||||
<string name="download_zip_only">Nur Zip herunterladen</string>
|
||||
<string name="direct_install">Direkte Installation (empfohlen)</string>
|
||||
<string name="install_inactive_slot">Installiere in inaktiven Slot (Nach OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Ihr Gerät wird gezwungen, nach einem Neustart in den inaktiven Slot zu booten! Verwenden Sie diese Option nur, wenn OTA abgeschlossen ist.\nWeiter?</string>
|
||||
@@ -51,9 +48,11 @@
|
||||
<string name="select_patch_file">Eine Datei auswählen und patchen</string>
|
||||
<string name="patch_file_msg">Raw Image (*.img) oder ein ODIN tarfile (*.tar) auswählen</string>
|
||||
<string name="reboot_delay_toast">Neustart in 5 Sekunden…</string>
|
||||
<string name="flash_screen_title">Installieren</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser-Anfrage</string>
|
||||
<string name="touch_filtered_warning">Weil eine App eine Superuser-Anfrage verdeckt, kann Magisk Ihre Antwort nicht verifizieren</string>
|
||||
<string name="deny">Verweigern</string>
|
||||
<string name="prompt">Fragen</string>
|
||||
<string name="grant">Gewähren</string>
|
||||
@@ -68,10 +67,10 @@
|
||||
<string name="su_deny_toast">%1$s wurden Superuser-Rechte verweigert</string>
|
||||
<string name="su_snack_grant">Superuser-Rechte für %1$s gewährt</string>
|
||||
<string name="su_snack_deny">Superuser-Rechte für %1$s verweigert</string>
|
||||
<string name="su_snack_notif_on">Benachrichtigungen von %1$s sind aktiviert</string>
|
||||
<string name="su_snack_notif_off">Benachrichtigungen von %1$s sind deaktiviert</string>
|
||||
<string name="su_snack_log_on">Protokollierung von %1$s ist aktiviert</string>
|
||||
<string name="su_snack_log_off">Protokollierung von %1$s ist deaktiviert</string>
|
||||
<string name="su_snack_notif_on">Benachrichtigungen für %1$s sind an</string>
|
||||
<string name="su_snack_notif_off">Benachrichtigungen für %1$s sind aus</string>
|
||||
<string name="su_snack_log_on">Protokollierung für %1$s ist an</string>
|
||||
<string name="su_snack_log_off">Protokollierung für %1$s ist aus</string>
|
||||
<string name="su_revoke_title">Widerrufen?</string>
|
||||
<string name="su_revoke_msg">Bestätigen, dass %1$s-Rechte widerufen werden?</string>
|
||||
<string name="toast">Toast</string>
|
||||
@@ -100,6 +99,7 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">System-Apps anzeigen</string>
|
||||
<string name="show_os_app">OS-Apps anzeigen</string>
|
||||
<string name="hide_filter_hint">Nach Namen filtern</string>
|
||||
<string name="hide_scroll_up">Nach oben scrollen</string>
|
||||
<string name="hide_filters">Filter</string>
|
||||
@@ -107,6 +107,7 @@
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Keine Informationen verfügbar)</string>
|
||||
<string name="reboot_userspace">Sanfter Neustart</string>
|
||||
<string name="reboot_recovery">Neustart zum Recovery</string>
|
||||
<string name="reboot_bootloader">Neustart zum Bootloader</string>
|
||||
<string name="reboot_download">Neustart zum Download</string>
|
||||
@@ -119,8 +120,8 @@
|
||||
<string name="module_action_install_external">Aus dem Speicher installieren</string>
|
||||
<string name="update_available">Update verfügbar</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="sorting_order">Sortierreihenfolge</string>
|
||||
<string name="external_rw_permission_denied">Gewähre den Speicher-Zugriff, um diese Funtion zu aktivieren.</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Themen-Modus</string>
|
||||
@@ -132,12 +133,12 @@
|
||||
<string name="settings_download_path_message">Dateien werden in %1$s gespeichert</string>
|
||||
<string name="settings_clear_cache_title">Repo-Cache leeren</string>
|
||||
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen des Online-Repos. Erzwingt eine Aktualisierung</string>
|
||||
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
|
||||
<string name="settings_hide_manager_summary">Magisk Manager mit zufälligem Paketnamen neu packen</string>
|
||||
<string name="settings_restore_manager_title">Magisk Manager wiederherstellen</string>
|
||||
<string name="settings_restore_manager_summary">Magisk Manager mit ursprünglichem Paketnamen wiederherstellen</string>
|
||||
<string name="settings_hide_app_title">Verstecke die Magisk App</string>
|
||||
<string name="settings_hide_app_summary">Installiere eine Proxy-App mit zufälliger Paket-ID und benutzerdefiniertem App-Label</string>
|
||||
<string name="settings_restore_app_title">Stelle die Magisk App wiederher</string>
|
||||
<string name="settings_restore_app_summary">Blende die App wieder ein und stelle die original APK wieder her</string>
|
||||
<string name="language">Sprache</string>
|
||||
<string name="system_default">(Systemstandard)</string>
|
||||
<string name="system_default">Systemstandard</string>
|
||||
<string name="settings_check_update_title">Auf Aktualisierungen prüfen</string>
|
||||
<string name="settings_check_update_summary">Regelmäßig im Hintergrund auf Aktualisierungen prüfen</string>
|
||||
<string name="settings_update_channel_title">Aktualisierungs-Kanal</string>
|
||||
@@ -166,12 +167,17 @@
|
||||
<string name="auto_response">Automatisch beantworten</string>
|
||||
<string name="request_timeout">Zeitlimit für Anfrage</string>
|
||||
<string name="superuser_notification">Superuser-Benachrichtigung</string>
|
||||
<string name="settings_su_reauth_title">Nach Aktualisierung erneut authentifizieren</string>
|
||||
<string name="settings_su_reauth_summary">Superuser-Zugriff nach App-Aktualisierung erneut abfragen</string>
|
||||
<string name="settings_su_reauth_title">Nach Aktualisierung erneut zertifizieren</string>
|
||||
<string name="settings_su_reauth_summary">Superuser-Berechtigungen nach App-Aktualisierung erneut authentifizieren</string>
|
||||
<string name="settings_su_tapjack_title">Tapjacking-Schutz aktivieren</string>
|
||||
<string name="settings_su_tapjack_summary">Das Dialogfeld der Superuser-Eingabeaufforderung reagiert nicht auf Eingaben, wenn es durch ein anderes Fenster oder Überlagerung verdeckt wird</string>
|
||||
<string name="settings_su_biometric_title">Biometrische Authentifizierung aktivieren</string>
|
||||
<string name="settings_su_biometric_summary">Biometrische Authentifizierung verwenden, um Superuser-Anfragen zu ermöglichen</string>
|
||||
<string name="no_biometric">Nicht unterstütztes Gerät oder keine biometrischen Einstellungen aktiviert</string>
|
||||
<string name="settings_su_biometric_summary">Biometrie verwenden, um Superuser-Anfragen zuzulassen</string>
|
||||
<string name="no_biometric">Gerät unterstützt keine biometrischen Daten oder ist nicht mit diesen konfiguriert</string>
|
||||
<string name="settings_customization">Personalisierung</string>
|
||||
<string name="setting_add_shortcut_summary">Hinzufügen einer hübschen Startbildschirm-Verknüpfung, falls der Name und das Symbol nach dem Ausblenden der App schwer zu erkennen sind</string>
|
||||
<string name="settings_doh_title">DNS über HTTPS</string>
|
||||
<string name="settings_doh_description">Umgehung des DNS-Poisoning in einigen Ländern</string>
|
||||
|
||||
<string name="multiuser_mode">Mehrbenutzermodus</string>
|
||||
<string name="settings_owner_only">Nur der Gerätebesitzer</string>
|
||||
@@ -194,10 +200,7 @@
|
||||
<string name="progress_channel">Fortschrittsmitteilungen</string>
|
||||
<string name="download_complete">Download abgeschlossen</string>
|
||||
<string name="download_file_error">Fehler beim herunterladen der Datei</string>
|
||||
<string name="download_open_parent">Im übergeordneten Ordner anzeigen</string>
|
||||
<string name="download_open_self">Datei anzeigen</string>
|
||||
<string name="magisk_update_title">Magisk Update verfügbar!</string>
|
||||
<string name="manager_update_title">Magisk Manager Update verfügbar!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Ja</string>
|
||||
@@ -211,8 +214,7 @@
|
||||
<string name="flashing">Flashen…</string>
|
||||
<string name="done">Fertig!</string>
|
||||
<string name="failure">Fehlgeschlagen</string>
|
||||
<string name="hide_manager_title">Magisk Manager ausblenden…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager ausblenden fehlgeschlagen.</string>
|
||||
<string name="hide_app_title">Verstecke die Magisk App…</string>
|
||||
<string name="open_link_failed_toast">Keine App zum öffnen des Links gefunden</string>
|
||||
<string name="complete_uninstall">Vollständig deinstallieren</string>
|
||||
<string name="restore_img">Image wiederherstellen</string>
|
||||
@@ -220,13 +222,17 @@
|
||||
<string name="restore_done">Wiederherstellen fertig!</string>
|
||||
<string name="restore_fail">Stock-Sicherung existiert nicht!</string>
|
||||
<string name="proprietary_title">Proprietären Code herunterladen</string>
|
||||
<string name="proprietary_notice">Magisk Manager ist FOSS und enthält nicht den proprietären SafetyNet-API-Code von Google.\n\nWollen Sie Magisk Manager erlauben, eine Erweiterung (enthält GoogleApiClient) für SafetyNet-Prüfungen herunterzuladen?</string>
|
||||
<string name="proprietary_notice">Magisk ist FOSS und enthält keinen Code für Google\'s proprietäre SafetyNet API.\n\nWillst du eine proprietäre Erweiterung für Safetynet Überprüfungen herunterladen?</string>
|
||||
<string name="setup_fail">Setup fehlgeschlagen</string>
|
||||
<string name="env_fix_title">Zusätzliche Einrichtung erforderlich</string>
|
||||
<string name="env_fix_msg">Ihr Gerät muss zusätzlich eingerichtet werden, damit Magisk ordnungsgemäß funktioniert. Es wird das Magisk Setup-Zip herunterladen, möchten Sie jetzt fortfahren?</string>
|
||||
<string name="env_fix_msg">Magisk braucht ein zusätzliches Setup, um auf deinem Gerät zu funktionieren. Willst du fortfahren und dein Gerät neustarten?</string>
|
||||
<string name="setup_msg">Laufzeitumgebung einrichten…</string>
|
||||
<string name="authenticate">Authentifizieren</string>
|
||||
<string name="unsupport_magisk_title">Nicht unterstützte Magisk-Version</string>
|
||||
<string name="unsupport_magisk_msg">Diese Version von Magisk Manager unterstützt keine Magisk-Version kleiner als %1$s.\n\nDie App verhält sich, als ob kein Magisk installiert wäre. Bitte Magisk so schnell wie möglich aktualisieren.</string>
|
||||
<string name="unsupport_magisk_msg">Diese Version der App unterstütz keine Magisk version niedriger, als %1$s.\n\nDie App wird sich verhalten, als wäre Magisk nicht installiert, bitte aktualisiere Magisk so schnell, wie möglich.</string>
|
||||
<string name="external_rw_permission_denied">Speichererlaubnis erteilen, um diese Funktion zu aktivieren</string>
|
||||
<string name="add_shortcut_title">Verknüpfung zum Startbildschirm hinzufügen</string>
|
||||
<string name="add_shortcut_msg">Nachdem du diese App versteckst, wird der Name und das Symbol eventuell schwer zu erkennen sein. Möchten sie zum Startbildschirm eine schöne Verknüpfung hinzufügen?</string>
|
||||
<string name="app_not_found">Keine App gefunden, die diese Aktion verarbeitet</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,123 +1,63 @@
|
||||
<resources>
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Modules</string>
|
||||
|
||||
<!--Sections-->
|
||||
<string name="modules">Επεκτάσεις</string>
|
||||
<string name="superuser">Υπερχρήστης</string>
|
||||
<string name="logs">Αρχείο Καταγραφής</string>
|
||||
<string name="settings">Ρυθμίσεις</string>
|
||||
<string name="refresh">Ανανέωση τοπικών δεδομένων</string>
|
||||
<string name="install">Εγκατάσταση</string>
|
||||
<string name="section_home">Αρχική</string>
|
||||
<string name="section_theme">Θέματα</string>
|
||||
<string name="safetynet">SafetyNet</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
|
||||
<string name="invalid_update_channel">Λανθασμένο κανάλι ενημέρωσης</string>
|
||||
<string name="safetynet_api_error">Σφάλμα του SafetyNet API</string>
|
||||
<string name="safetynet_res_invalid">Η απόκριση είναι άκυρη</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="keep_force_encryption">Διατήρηση επιβεβλημένης κρυπτογράφησης</string>
|
||||
<string name="keep_dm_verity">Διατήρηση dm-verity</string>
|
||||
<string name="uninstall_magisk_title">Απεγκατάσταση Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Όλα τα modules θα απενεργοποιηθούν/αφαιρεθούν. Το root θα αφαιρεθεί και ενδέχεται να κρυπτογραφηθούν τα δεδομένα σας, εάν δεν είναι κρυπτογραφημένα</string>
|
||||
<string name="update">Ενημέρωση</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Δεν δόθηκαν πληροφορίες)</string>
|
||||
<string name="reboot_recovery">Επανεκκίνηση στο Recovery</string>
|
||||
<string name="reboot_bootloader">Επανεκκίνηση στο Bootloader</string>
|
||||
<string name="reboot_download">Επανεκκίνηση για λήψη</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
|
||||
<string name="home_installed_version">Εγκαταστάθηκε</string>
|
||||
<string name="sorting_order">Ταξινόμηση κατά</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">"Αποθήκευση καταγραφής "</string>
|
||||
<string name="menuClearLog">Εκκαθάριση αρχείου καταγραφής τώρα</string>
|
||||
<string name="logs_cleared">Το αρχείο καταγραφής εκκαθαρίστηκε επιτυχώς</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<!--Home-->
|
||||
<string name="no_connection">Δεν υπάρχει διαθέσιμη σύνδεση</string>
|
||||
<string name="app_changelog">Καταγραφή αλλαγών εφαρμογής</string>
|
||||
<string name="loading">Φόρτωση…</string>
|
||||
<string name="update">Ενημέρωση</string>
|
||||
<string name="not_available">Μη διαθέσιμο</string>
|
||||
<string name="hide">Απόκρυψη</string>
|
||||
<string name="home_package">Πακέτο</string>
|
||||
<string name="home_app_title">Εφαρμογή</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">Εγκατάσταση %1$s</string>
|
||||
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
|
||||
<string name="download">Λήψη</string>
|
||||
<string name="reboot">Επανεκκίνηση</string>
|
||||
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
|
||||
<string name="release_notes">Σημειώσεις έκδοσης</string>
|
||||
<string name="repo_cache_cleared">Η Repo cache καθαρίστηκε</string>
|
||||
<string name="manager_update_title">Νέα Ενημέρωση Magisk Manager Διαθέσιμη!</string>
|
||||
<string name="home_notice_content">Κάντε λήψη του Magisk ΜΟΝΟ από την επίσημη σελίδα του GitHub. Τα αρχεία από άγνωστες πηγές μπορεί να είναι κακόβουλα!</string>
|
||||
<string name="home_support_title">Υποστήριξη</string>
|
||||
<string name="home_item_source">Πηγή</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">Όλα τα modules θα απενεργοποιηθούν/αφαιρεθούν. Το root θα αφαιρεθεί και ενδέχεται να κρυπτογραφηθούν τα δεδομένα σας, εάν δεν είναι κρυπτογραφημένα!</string>
|
||||
<string name="home_check_safetynet">Έλεγχος SafetyNet</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Διατήρηση επιβεβλημένης κρυπτογράφησης</string>
|
||||
<string name="keep_dm_verity">Διατήρηση AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Μέσω Recovery mode</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="update_channel">Ενημερώσεις Magisk</string>
|
||||
<string name="flashing">Γίνεται flash</string>
|
||||
<string name="hide_manager_title">Κρύβοντας το Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Η απόκρυψη του Magisk Manager απέτυχε…</string>
|
||||
<string name="download_zip_only">Λήψη Zip Μόνο</string>
|
||||
<string name="direct_install">Απευθείας Εγκατάσταση (Προτείνεται)</string>
|
||||
<string name="complete_uninstall">Πλήρης απεγκατάσταση</string>
|
||||
<string name="restore_done">Η ανάκτηση έγινε!</string>
|
||||
<string name="restore_fail">Δεν υπάρχει αντίγραφο ασφαλείας!</string>
|
||||
<string name="proprietary_title">Λήψη Ιδιόκτητου Κώδικα</string>
|
||||
<string name="proprietary_notice">Το Magisk Manager είναι FOSS οπότε δεν περιέχει της Google τον ιδιόκτητο κώδικα του SafetyNet API.\n\nΕπιτρέπετε στο Magisk Manager να κατεβάσει μια επέκταση (περιέχει το GoogleApiClient) για ελέγχους του SafetyNet?</string>
|
||||
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
|
||||
<string name="install_inactive_slot">Εγκατάσταση στο ανενεργό Slot (Μετά από OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Η συσκευή σας θα αναγκαστεί να εκκινήσει στο τρέχον ανενεργό Slot μετά από επανεκκίνηση!\nΧρησιμοποιήστε αυτήν την επιλογή μόνο αφού ολοκληρωθεί το OTA.\nΣυνέχεια;</string>
|
||||
<string name="setup_title">Πρόσθετη εγκατάσταση</string>
|
||||
<string name="select_patch_file">Επέλεξε και κάνε Patch ένα αρχείο</string>
|
||||
<string name="patch_file_msg">Επέλεξε μία raw εικόνα (*.img) ή ένα ODIN tarfile (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Επανεκκίνηση σε 5 δευτερόλεπτα…</string>
|
||||
<string name="flash_screen_title">Εγκατάσταση</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Εκκαθάριση προσωρινής μνήμης αποθετηρίων</string>
|
||||
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για απευθείας συνδεδεμένα αποθετήρια, αναγκάζει την εφαρμογή να κάνει ανανέωση σε απευθείας σύνδεση</string>
|
||||
<string name="settings_hide_manager_title">Απόκρυψη του Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Ανασυγκρότηση του Magisk Manager με τυχαίο όνομα πακέτου</string>
|
||||
<string name="language">Γλώσσα</string>
|
||||
<string name="system_default">(Προεπιλογή Συστήματος)</string>
|
||||
<string name="settings_update_channel_title">Κανάλι Ενημερώσεων</string>
|
||||
<string name="settings_update_stable">Σταθερό</string>
|
||||
<string name="settings_update_beta">Δοκιμαστικό</string>
|
||||
<string name="settings_update_custom">Custom</string>
|
||||
<string name="settings_update_custom_msg">Εισαγωγή ενός custom URL</string>
|
||||
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
|
||||
|
||||
<string name="settings_su_app_adb">Εφαρμογές και ADB</string>
|
||||
<string name="settings_su_app">Εφαρμογές μόνο</string>
|
||||
<string name="settings_su_adb">ADB μόνο</string>
|
||||
<string name="settings_su_disable">Απενεργοποιημένο</string>
|
||||
<string name="settings_su_request_10">10 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_15">15 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_20">20 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_30">30 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_45">45 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_60">60 δευτερόλεπτα</string>
|
||||
<string name="superuser_access">Πρόσβαση Υπερχρήστη</string>
|
||||
<string name="auto_response">Αυτόματη Απόκριση</string>
|
||||
<string name="request_timeout">Χρονικό όριο Αιτήματος</string>
|
||||
<string name="superuser_notification">Ειδοποίηση Υπερχρήστη</string>
|
||||
<string name="settings_su_reauth_title">Επαναπιστοποίηση μετά από αναβάθμιση</string>
|
||||
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
|
||||
|
||||
<string name="multiuser_mode">Λειτουργία Πολλών Χρηστών</string>
|
||||
<string name="settings_owner_only">Μόνο Ιδιοκτήτης Συσκευής</string>
|
||||
<string name="settings_owner_manage">Διαχειριζόμενη από τον Ιδιοκτήτη</string>
|
||||
<string name="settings_user_independent">Ανεξάρτητη από τον χρήστη</string>
|
||||
<string name="owner_only_summary">Μόνο ο ιδιοκτήτης έχει πρόσβαση root</string>
|
||||
<string name="owner_manage_summary">Μόνο ο ιδιοκτήτης μπορεί να διαχειριστεί την πρόσβαση root και να δεχτεί προτροπές αίτημάτων</string>
|
||||
<string name="user_indepenent_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">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
|
||||
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
|
||||
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Αίτημα υπερχρήστη</string>
|
||||
<string name="touch_filtered_warning">Επειδή μια εφαρμογή αποκρύπτει ένα αίτημα υπερχρήστη, το Magisk δεν μπορεί να επαληθεύσει την απάντησή σας</string>
|
||||
<string name="deny">Άρνηση</string>
|
||||
<string name="prompt">Προτροπή</string>
|
||||
<string name="grant">Αποδοχή</string>
|
||||
<string name="su_warning">Δίνει πλήρη πρόσβαση στη συσκευή σας.\nΑρνηθείτε αν δεν είστε σίγουρος/η!</string>
|
||||
<string name="forever">Πάντα</string>
|
||||
<string name="forever">Μόνιμα</string>
|
||||
<string name="once">Μία φορά</string>
|
||||
<string name="tenmin">10 λεπτά</string>
|
||||
<string name="twentymin">20 λεπτά</string>
|
||||
@@ -136,6 +76,163 @@
|
||||
<string name="toast">Αναδυόμενο παράθυρο</string>
|
||||
<string name="none">Κανένα</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="superuser_toggle_notification">Ειδοποιήσεις</string>
|
||||
<string name="superuser_toggle_revoke">Ανακάλεσε</string>
|
||||
<string name="superuser_policy_none">Καμία εφαρμογή δεν έχει ζητήσει άδεια υπερχρήστη.</string>
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Δεν υπάρχουν αρχεία καταγραφής, δοκιμάστε να χρησιμοποιήσετε περισσότερο τις εφαρμογές με δυνατότητα SU</string>
|
||||
<string name="log_data_magisk_none">Τα αρχεία καταγραφής του Magisk είναι κενά, αυτό είναι περίεργο</string>
|
||||
<string name="menuSaveLog">Αποθήκευση καταγραφής</string>
|
||||
<string name="menuClearLog">Εκκαθάριση αρχείου καταγραφής</string>
|
||||
<string name="logs_cleared">Το αρχείο καταγραφής εκκαθαρίστηκε επιτυχώς</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">UID Στόχος: %1$d</string>
|
||||
</resources>
|
||||
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">Σφάλμα του SafetyNet API</string>
|
||||
<string name="safetynet_res_invalid">Η απόκριση είναι άκυρη</string>
|
||||
<string name="safetynet_attest_success">Η πιστοποίηση ήταν επιτυχής!</string>
|
||||
<string name="safetynet_attest_failure">Η πιστοποίηση απέτυχε!</string>
|
||||
<string name="safetynet_attest_loading">Μισό λεπτό…</string>
|
||||
<string name="safetynet_attest_restart">Προσπάθησε ξανά</string>
|
||||
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">Εμφάνιση εφαρμογών συστήματος</string>
|
||||
<string name="show_os_app">Εμφάνιση εφαρμογών OS</string>
|
||||
<string name="hide_filter_hint">Φιλτράρισμα</string>
|
||||
<string name="hide_scroll_up">Μετακίνηση</string>
|
||||
<string name="hide_filters">Φίλτρα</string>
|
||||
<string name="hide_search">Αναζήτηση</string>
|
||||
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(Δεν δόθηκαν πληροφορίες)</string>
|
||||
<string name="reboot_userspace">Soft επανεκκίνηση</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="module_version_author">%1$s από %2$s</string>
|
||||
<string name="module_section_pending">Ενημερώσεις</string>
|
||||
<string name="module_section_pending_action">Ενημέρωση όλων</string>
|
||||
<string name="module_state_remove">Αφαίρεση</string>
|
||||
<string name="module_state_restore">Επαναφορά</string>
|
||||
<string name="module_action_install_external">Εγκατάσταση από χώρο αποθήκευσης</string>
|
||||
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="sorting_order">Ταξινόμηση κατά</string>
|
||||
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">Λειτουργία θέματος</string>
|
||||
<string name="settings_dark_mode_message">Επιλέξτε τη λειτουργία που ταιριάζει καλύτερα στο στυλ σας!</string>
|
||||
<string name="settings_dark_mode_light">Πάντα Light</string>
|
||||
<string name="settings_dark_mode_system">Ακολούθησε το σύστημα</string>
|
||||
<string name="settings_dark_mode_dark">Πάντα Dark</string>
|
||||
<string name="settings_download_path_title">Διαδρομή λήψης</string>
|
||||
<string name="settings_download_path_message">Τα αρχεία θα αποθηκευτούν στο %1$s</string>
|
||||
<string name="settings_clear_cache_title">Εκκαθάριση προσωρινής μνήμης αποθετηρίων</string>
|
||||
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για απευθείας συνδεδεμένα αποθετήρια, αναγκάζει την εφαρμογή να κάνει ανανέωση σε απευθείας σύνδεση</string>
|
||||
<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="language">Γλώσσα</string>
|
||||
<string name="system_default">(Προεπιλογή Συστήματος)</string>
|
||||
<string name="settings_check_update_title">Έλεγχος Ενημερώσεων</string>
|
||||
<string name="settings_check_update_summary">Περιοδικά ελέγχετε για ενημερώσεις στο παρασκήνιο</string>
|
||||
<string name="settings_update_channel_title">Κανάλι Ενημερώσεων</string>
|
||||
<string name="settings_update_stable">Σταθερό</string>
|
||||
<string name="settings_update_beta">Δοκιμαστικό</string>
|
||||
<string name="settings_update_custom">Προσαρμοσμένο</string>
|
||||
<string name="settings_update_custom_msg">Εισαγωγή ενός custom URL</string>
|
||||
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
|
||||
<string name="settings_hosts_toast">Προσθήκη αρθρώματος systemless hosts</string>
|
||||
<string name="settings_app_name_hint">Νέο όνομα</string>
|
||||
<string name="settings_app_name_helper">Η εφαρμογή θα επανασυσκευαστεί με αυτό το όνομα</string>
|
||||
<string name="settings_app_name_error">Μη έγκυρη μορφή</string>
|
||||
<string name="settings_su_app_adb">Εφαρμογές και ADB</string>
|
||||
<string name="settings_su_app">Εφαρμογές μόνο</string>
|
||||
<string name="settings_su_adb">ADB μόνο</string>
|
||||
<string name="settings_su_disable">Απενεργοποιημένο</string>
|
||||
<string name="settings_su_request_10">10 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_15">15 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_20">20 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_30">30 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_45">45 δευτερόλεπτα</string>
|
||||
<string name="settings_su_request_60">60 δευτερόλεπτα</string>
|
||||
<string name="superuser_access">Πρόσβαση Υπερχρήστη</string>
|
||||
<string name="auto_response">Αυτόματη Απόκριση</string>
|
||||
<string name="request_timeout">Χρονικό όριο Αιτήματος</string>
|
||||
<string name="superuser_notification">Ειδοποίηση Υπερχρήστη</string>
|
||||
<string name="settings_su_reauth_title">Επαναπιστοποίηση μετά από αναβάθμιση</string>
|
||||
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
|
||||
<string name="settings_su_tapjack_title">Ενεργοποίηση προστασίας Tapjacking</string>
|
||||
<string name="settings_su_tapjack_summary">Το παράθυρο διαλόγου προτροπής του υπερχρήστη δεν αποκρίνεται στην είσοδο ενώ κρύβεται από οποιοδήποτε άλλο παράθυρο</string>
|
||||
<string name="settings_su_biometric_title">Ενεργοποίηση βιομετρικού ελέγχου ταυτότητας</string>
|
||||
<string name="settings_su_biometric_summary">Χρησιμοποιήστε βιομετρικό έλεγχο ταυτότητας για να επιτρέψετε αιτήματα υπερχρηστών</string>
|
||||
<string name="no_biometric">Δεν υποστηρίζεται η συσκευή ή δεν υπάρχει καμία βιομετρική ρύθμιση</string>
|
||||
<string name="settings_customization">Προσαρμογή</string>
|
||||
<string name="setting_add_shortcut_summary">Προσθέστε μια όμορφη συντόμευση στην αρχική οθόνη σε περίπτωση που το όνομα και το εικονίδιο είναι δύσκολο να αναγνωριστούν αφού κρύψετε την εφαρμογή</string>
|
||||
<string name="settings_doh_title">DNS μέσω HTTPS</string>
|
||||
<string name="settings_doh_description">Λύση DNS poisoning για μερικά έθνη</string>
|
||||
|
||||
<string name="multiuser_mode">Λειτουργία Πολλών Χρηστών</string>
|
||||
<string name="settings_owner_only">Μόνο Ιδιοκτήτης Συσκευής</string>
|
||||
<string name="settings_owner_manage">Διαχειριζόμενη από τον Ιδιοκτήτη</string>
|
||||
<string name="settings_user_independent">Ανεξάρτητη από τον χρήστη</string>
|
||||
<string name="owner_only_summary">Μόνο ο ιδιοκτήτης έχει πρόσβαση root</string>
|
||||
<string name="owner_manage_summary">Μόνο ο ιδιοκτήτης μπορεί να διαχειριστεί την πρόσβαση root και να δεχτεί προτροπές αίτημάτων</string>
|
||||
<string name="user_indepenent_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">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
|
||||
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
|
||||
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Ενημερώσεις Magisk</string>
|
||||
<string name="progress_channel">Ειδοποιήσεις προόδου</string>
|
||||
<string name="download_complete">Η λήψη ολοκληρώθηκε</string>
|
||||
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
|
||||
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Ναι</string>
|
||||
<string name="no">Όχι</string>
|
||||
<string name="repo_install_title">Εγκατάσταση %1$s</string>
|
||||
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
|
||||
<string name="download">Λήψη</string>
|
||||
<string name="reboot">Επανεκκίνηση</string>
|
||||
<string name="release_notes">Σημειώσεις έκδοσης</string>
|
||||
<string name="repo_cache_cleared">Πραγματοποιήθηκε εκκαθάριση της προσωρινής μνήμης του Repository</string>
|
||||
<string name="flashing">Προγραμματισμός σε εξέλιξη</string>
|
||||
<string name="done">Ολοκληρώθηκε</string>
|
||||
<string name="failure">Αποτυχία</string>
|
||||
<string name="hide_app_title">Απόκρυψη της εφαρμογής Magisk…</string>
|
||||
<string name="open_link_failed_toast">Δεν βρέθηκε εφαρμογή για άνοιγμα του συνδέσμου</string>
|
||||
<string name="complete_uninstall">Πλήρης απεγκατάσταση</string>
|
||||
<string name="restore_img">Επαναφορά Images</string>
|
||||
<string name="restore_img_msg">Επαναφορά…</string>
|
||||
<string name="restore_done">Η επαναφορά πραγματοποιήθηκε</string>
|
||||
<string name="restore_fail">Δεν υπάρχει αντίγραφο ασφαλείας!</string>
|
||||
<string name="proprietary_title">Λήψη Ιδιόκτητου Κώδικα</string>
|
||||
<string name="proprietary_notice">Το Magisk είναι FOSS και δεν περιλαμβάνει κώδικα για το ιδιόκτητο SafetyNet API της Google.\n\nΘέλετε να κατεβάσετε μια ιδιόκτητη επέκταση για ελέγχους SafetyNet;</string>
|
||||
<string name="setup_fail">Η εγκατάσταση απέτυχε</string>
|
||||
<string name="env_fix_title">Απαιτείται πρόσθετη εγκατάσταση</string>
|
||||
<string name="env_fix_msg">Η συσκευή σας χρειάζεται πρόσθετη ρύθμιση για να λειτουργεί σωστά το Magisk. Θέλετε να συνεχίσετε και να επανεκκινήσετε;</string>
|
||||
<string name="setup_msg">Τρέχει η εγκατάσταση περιβάλλοντος…</string>
|
||||
<string name="authenticate">Αυθεντικοποίηση</string>
|
||||
<string name="unsupport_magisk_title">Μη υποστηριζόμενη έκδοση Magisk</string>
|
||||
<string name="unsupport_magisk_msg">Αυτή η έκδοση της εφαρμογής δεν υποστηρίζει έκδοση Magisk χαμηλότερη από %1$s.\n\nΗ εφαρμογή θα συμπεριφέρεται σαν να μην έχει εγκατασταθεί το Magisk, αναβαθμίστε το Magisk το συντομότερο δυνατό.</string>
|
||||
<string name="external_rw_permission_denied">Παραχωρήστε άδεια αποθήκευσης για να ενεργοποιήσετε αυτήν τη λειτουργία</string>
|
||||
<string name="add_shortcut_title">Προσθέστε συντόμευση στην αρχική οθόνη</string>
|
||||
<string name="add_shortcut_msg">Μετά την απόκρυψη αυτής της εφαρμογής, το όνομα και το εικονίδιο της ενδέχεται να είναι δύσκολο να αναγνωριστούν. Θέλετε να προσθέσετε μια όμορφη συντόμευση στην αρχική οθόνη;</string>
|
||||
|
||||
<string name="app_not_found">Δεν βρέθηκε εφαρμογή που να χειρίζεται αυτήν την ενέργεια</string>
|
||||
|
||||
</resources>
|
@@ -14,20 +14,17 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Conexión no disponible</string>
|
||||
<string name="app_changelog">Registro de cambios</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Cargando…</string>
|
||||
<string name="update">Actualizar</string>
|
||||
<string name="not_available">No disponible</string>
|
||||
<string name="hide">Ocultar</string>
|
||||
<string name="status">Estado</string>
|
||||
<string name="home_package">Paquete</string>
|
||||
<string name="home_app_title">App</string>
|
||||
|
||||
<string name="home_notice_content">Siempre asegúrate de que estás usando el software de código abierto Magisk Manager. Un Manager de fuente desconocida puede realizar acciones maliciosas.</string>
|
||||
<string name="home_notice_content">Descarga Magisk SÓLO de la página de GitHub oficial. Archivos de fuentes desconocidas pueden resultar maliciosos!</string>
|
||||
<string name="home_support_title">Apóyenos</string>
|
||||
<string name="home_item_source">Código fuente</string>
|
||||
<string name="home_support_content">Magisk es, y siempre será gratuito y de código abierto. Sin embargo, puede apoyarnos enviando una pequeña donación.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Instalado</string>
|
||||
<string name="home_latest_version">Última</string>
|
||||
<string name="invalid_update_channel">Canal de actualización inválido</string>
|
||||
@@ -44,7 +41,6 @@
|
||||
<string name="install_next">Siguiente</string>
|
||||
<string name="install_start">Comencemos</string>
|
||||
<string name="manager_download_install">Pulse para descargar e instalar</string>
|
||||
<string name="download_zip_only">Descargar sólo el archivo ZIP</string>
|
||||
<string name="direct_install">Instalación directa (recomendado)</string>
|
||||
<string name="install_inactive_slot">Instalar en ranura inactiva (después de OTA)</string>
|
||||
<string name="install_inactive_slot_msg">¡Su dispositivo será forzado a arrancar en la ranura inactiva actual después de un reinicio!\nSólo use esta opción después de que OTA haya terminado.\n¿Continuar?</string>
|
||||
@@ -56,6 +52,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Petición de superusuario</string>
|
||||
<string name="touch_filtered_warning">Como otra app está escondiendo la solicitud de superusuario, Magisk no puede verificar tu respuesta</string>
|
||||
<string name="deny">Denegar</string>
|
||||
<string name="prompt">Preguntar</string>
|
||||
<string name="grant">Permitir</string>
|
||||
@@ -101,7 +98,8 @@
|
||||
<string name="safetynet_attest_restart">Inténtelo de nuevo</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostrar sistema</string>
|
||||
<string name="show_system_app">Mostrar apps del sistema</string>
|
||||
<string name="show_os_app">Mostrar apps del OS</string>
|
||||
<string name="hide_filter_hint">Filtrar por nombre</string>
|
||||
<string name="hide_scroll_up">Subir</string>
|
||||
<string name="hide_filters">Filtros</string>
|
||||
@@ -109,6 +107,7 @@
|
||||
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(No hay información)</string>
|
||||
<string name="reboot_userspace">Reinicio suave</string>
|
||||
<string name="reboot_recovery">Reiniciar en modo recovery</string>
|
||||
<string name="reboot_bootloader">Reiniciar en modo bootloader</string>
|
||||
<string name="reboot_download">Reiniciar en modo download</string>
|
||||
@@ -134,10 +133,10 @@
|
||||
<string name="settings_download_path_message">Los archivos se guardarán en %1$s</string>
|
||||
<string name="settings_clear_cache_title">Limpiar caché del repositorio</string>
|
||||
<string name="settings_clear_cache_summary">Limpiar la información en caché para los repositorios en línea, fuerza a la aplicación a actualizar en línea</string>
|
||||
<string name="settings_hide_manager_title">Ocultar Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Re-empaquetar Magisk Manager con un nombre de paquete al azar</string>
|
||||
<string name="settings_restore_manager_title">Restaurar Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Restaura Magisk Manager con el paquete original</string>
|
||||
<string name="settings_hide_app_title">Esconder la app de Magisk</string>
|
||||
<string name="settings_hide_app_summary">Instalar una nueva app proxy con una ID de paquete aleatoria y una etiqueta personalizada</string>
|
||||
<string name="settings_restore_app_title">Restaurar la app de Magisk</string>
|
||||
<string name="settings_restore_app_summary">Descubrir la app y restaurarla al APK original</string>
|
||||
<string name="language">Idioma</string>
|
||||
<string name="system_default">(Idioma del sistema)</string>
|
||||
<string name="settings_check_update_title">Comprobar Actualizaciones</string>
|
||||
@@ -201,10 +200,7 @@
|
||||
<string name="progress_channel">Notificaciones de progreso</string>
|
||||
<string name="download_complete">Descarga Completa</string>
|
||||
<string name="download_file_error">Error descargando archivo</string>
|
||||
<string name="download_open_parent">Mostrar en carpeta principal</string>
|
||||
<string name="download_open_self">Mostrar archivo</string>
|
||||
<string name="magisk_update_title">¡Actualización de Magisk disponible!</string>
|
||||
<string name="manager_update_title">¡Actualización de Magisk Manager disponible!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Sí</string>
|
||||
@@ -218,8 +214,7 @@
|
||||
<string name="flashing">Flasheando…</string>
|
||||
<string name="done">¡Hecho!</string>
|
||||
<string name="failure">Ha fallado</string>
|
||||
<string name="hide_manager_title">Ocultando Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">La ocultación de Magisk Manager ha fallado…</string>
|
||||
<string name="hide_app_title">Escondiendo la app de Magisk…</string>
|
||||
<string name="open_link_failed_toast">No se encontró ninguna aplicación para abrir el enlace…</string>
|
||||
<string name="complete_uninstall">Desinstalación completa</string>
|
||||
<string name="restore_img">Restaurar imágenes</string>
|
||||
@@ -227,17 +222,17 @@
|
||||
<string name="restore_done">¡Restauración Terminada!</string>
|
||||
<string name="restore_fail">¡El respaldo de la imagen boot Stock no existe!</string>
|
||||
<string name="proprietary_title">Descargar código propietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager es un software libre por lo que no contiene el código API de SafetyNet (código propietario de Google).\n\n ¿Desea permitir que Magisk Manager descargue una extensión (que contiene GoogleApiClient) para comprobar el estado de SafetyNet?</string>
|
||||
<string name="proprietary_notice">Magisk es FOSS y no incluye código de la API de SafetyNet, propiedad de Google.\n\n¿Quieres descargar una extensión propietaria para las comprobaciones de SafetyNet?</string>
|
||||
<string name="setup_fail">Instalación fallida</string>
|
||||
<string name="env_fix_title">Se requiere una instalación adicional</string>
|
||||
<string name="env_fix_msg">Su dispositivo requiere una instalación adicional para que Magisk funcione correctamente. Se descargará el zip de instalación de Magisk, ¿desea continuar ahora?</string>
|
||||
<string name="env_fix_msg">Tu dispositivo necesita configuración adicional para el correcto funcionamiento de Magisk. ¿Quieres proceder y reiniciar?</string>
|
||||
<string name="setup_msg">Ejecutando configuración de entorno…</string>
|
||||
<string name="authenticate">Autenticar</string>
|
||||
<string name="unsupport_magisk_title">Versión de Magisk no soportada</string>
|
||||
<string name="unsupport_magisk_msg">Esta versión de Magisk Manager no admite versiones de Magisk inferiores a %1$s.\n\nLa aplicación se comportará como si no estuviera instalado Magisk, actualícelo tan pronto como sea posible.</string>
|
||||
<string name="unsupport_magisk_msg">Esta versión de la app no soporta versiones de Magisk inferiores a la %1$s.\n\nLa aplicación se comportará como si no tuvieses Magisk instalado, por favor actualiza Magisk tan pronto como sea posible.</string>
|
||||
<string name="external_rw_permission_denied">Conceder permiso de almacenamiento para habilitar esta funcionalidad</string>
|
||||
<string name="add_shortcut_title">Añadir un atajo a la pantalla de inicio</string>
|
||||
<string name="add_shortcut_msg">Después de esconder el Magisk Manager, su nombre e icono podría ser difícil de reconocer. ¿Quieres añadir un bonito atajo a la pantalla de inicio?</string>
|
||||
<string name="add_shortcut_msg">Tras esconder la app, su nombre e icono pueden resultar difíciles de reconocer. ¿Quieres añadir un acceso directo más bonito a la pantalla principal?</string>
|
||||
<string name="app_not_found">No se ha encontrado ninguna app para manejar esta acción</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Ühendus puudub</string>
|
||||
<string name="app_changelog">Muudatuste logi</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Laadimine…</string>
|
||||
<string name="update">Uuenda</string>
|
||||
<string name="not_available">puudub</string>
|
||||
<string name="hide">Peida</string>
|
||||
<string name="status">Olek</string>
|
||||
<string name="home_package">Pakett</string>
|
||||
|
||||
<string name="home_notice_content">Veendu alati, et kasutad avatud lähtekoodiga Magisk Manageri. Tundmatust allikast pärinev Manager võib teha pahatahtlikke toiminguid.</string>
|
||||
<string name="home_support_title">Toeta meid</string>
|
||||
<string name="home_item_source">Lähtekood</string>
|
||||
<string name="home_support_content">Magisk on ja jääb alati tasuta ning avatud lähtekoodiga kättesaadavaks. Siiski, sa võid meile väikese annetuse näol toetust üles näidata.</string>
|
||||
<string name="home_status_normal">Tavaline</string>
|
||||
<string name="home_status_stub">Makett</string>
|
||||
<string name="home_installed_version">Installitud</string>
|
||||
<string name="home_latest_version">Viimatine</string>
|
||||
<string name="invalid_update_channel">Sobimatu uuenduste kanal</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">Edasi</string>
|
||||
<string name="install_start">Läksime</string>
|
||||
<string name="manager_download_install">Vajuta allalaadimiseks ja installimiseks.</string>
|
||||
<string name="download_zip_only">Laadi ainult ZIP alla</string>
|
||||
<string name="direct_install">Otsene install (soovitatud)</string>
|
||||
<string name="install_inactive_slot">Installi ebaaktiivsesse lahtrisse (pärast üle-õhu uuendust)</string>
|
||||
<string name="install_inactive_slot_msg">Sinu seade SUNNITAKSE peale taaskäivitust käivituma praegusesse ebaaktiivsesse lahtrisse!\nKasuta seda valikut vaid peale üle-õhu uuenduse teostamist.\nJätkad?</string>
|
||||
@@ -134,10 +128,6 @@
|
||||
<string name="settings_download_path_message">Failid salvestatakse kausta %1$s</string>
|
||||
<string name="settings_clear_cache_title">Tühjenda hoidla vahemälu</string>
|
||||
<string name="settings_clear_cache_summary">Tühjenda vahemälus olev teave võrgus olevate hoidlate kohta. See sunnib rakendust võrgust värskendama</string>
|
||||
<string name="settings_hide_manager_title">Peida Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Paki Magisk Manager juhusliku paketi- ja rakenduse nimega ümber</string>
|
||||
<string name="settings_restore_manager_title">Taasta Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Taasta Magisk Manageri originaalpakett</string>
|
||||
<string name="language">Keel</string>
|
||||
<string name="system_default">(Süsteemi vaikesäte)</string>
|
||||
<string name="settings_check_update_title">Kontrolli uuendusi</string>
|
||||
@@ -199,10 +189,7 @@
|
||||
<string name="progress_channel">Edenemise teated</string>
|
||||
<string name="download_complete">Allalaadimine valmis</string>
|
||||
<string name="download_file_error">Faili allalaadimisel esines viga</string>
|
||||
<string name="download_open_parent">Kuva ülemkaustas</string>
|
||||
<string name="download_open_self">Kuva fail</string>
|
||||
<string name="magisk_update_title">Magiski uuendus on saadaval!</string>
|
||||
<string name="manager_update_title">Magisk Manageri uuendus on saadaval!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Jah</string>
|
||||
@@ -216,8 +203,6 @@
|
||||
<string name="flashing">Välgutamine…</string>
|
||||
<string name="done">Valmis!</string>
|
||||
<string name="failure">Ebaõnnestus</string>
|
||||
<string name="hide_manager_title">Magisk Manageri peitmine…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manageri peitmine ebaõnnestus.</string>
|
||||
<string name="open_link_failed_toast">Lingi avamiseks sobivat rakendust ei leitud.</string>
|
||||
<string name="complete_uninstall">Täielik eemaldus</string>
|
||||
<string name="restore_img">Taasta tõmmised</string>
|
||||
@@ -225,17 +210,13 @@
|
||||
<string name="restore_done">Taastamine valmis!</string>
|
||||
<string name="restore_fail">Originaalne varundus puudub!</string>
|
||||
<string name="proprietary_title">Laadi alla suletud koodi</string>
|
||||
<string name="proprietary_notice">Magisk Manager on vaba ja avatud lähtekoodiga ning ei sisalda Google\'i suletud SafetyNeti API koodi.\n\nKas lubad Magisk Manageril SafetyNeti kontrollide jaoks laadida alla laiendus (sisaldab GoogleApiClienti)?</string>
|
||||
<string name="setup_fail">Seadistus ebaõnnnestus</string>
|
||||
<string name="env_fix_title">Vajab lisaseadistust</string>
|
||||
<string name="env_fix_msg">Sinu seade vajab Magiski korralikuks toimimiseks lisaseadistust. Laadime alla Magiski seadistus-ZIPi, kas soovid kohe jätkata?</string>
|
||||
<string name="setup_msg">Käivitan keskkonnaseadistust…</string>
|
||||
<string name="authenticate">Autendi</string>
|
||||
<string name="unsupport_magisk_title">Mittetoetatud Magiski versioon</string>
|
||||
<string name="unsupport_magisk_msg">See Magisk Manageri versioon ei toeta Magiski versiooni, mis on vanem kui %1$s.\n\nRakendus käitub nii, nagu Magisk ei oleks paigaldatud, palun uuenda Magisk nii ruttu kui võimalik.</string>
|
||||
<string name="external_rw_permission_denied">Selle funktsionaalsuse lubamiseks anna mäluruumi haldamise luba</string>
|
||||
<string name="add_shortcut_title">Lisa avakuvale otsetee</string>
|
||||
<string name="add_shortcut_msg">Pärast Magisk Manageri peitmist võib selle nimi ja ikoon muutuda raskelt tuvastatavaks. Kas soovid avakuvale ilusa otsetee lisada?</string>
|
||||
<string name="app_not_found">Selle tegevuse teostamiseks ei leitud ühtegi rakendust</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">هیچ اتصالی وجود ندارد</string>
|
||||
<string name="app_changelog">تغییرات</string>
|
||||
<string name="manager">مدیریت</string>
|
||||
<string name="loading">در حال بارگذاری…</string>
|
||||
<string name="update">بروزرسانی کردن</string>
|
||||
<string name="not_available">غیر/قابل دسترسی</string>
|
||||
<string name="hide">پنهان کردن</string>
|
||||
<string name="status">وضعیت</string>
|
||||
<string name="home_package">پکیج</string>
|
||||
|
||||
<string name="home_notice_content">همیشه اطمینان حاصل کنید که از نسخه متن باز Magisk Manager استفاده می کنید. توجه داشته باشد نصب این نرم افزار از منبع ناشناخته میتواند به دستگاه شما آسیب برساند و اطلاعات شما را در معرض خطر قرار دهد.</string>
|
||||
<string name="home_support_title">حمایت ما</string>
|
||||
<string name="home_item_source">منبع</string>
|
||||
<string name="home_support_content">این برنامه (Magisk) رایگان و متن باز است و همیشه خواهد ماند. اگرچه شما میتواند با دونیت خود نشان دهد که به ما اهمیت می دهید.</string>
|
||||
<string name="home_status_normal">وضعیت عادی</string>
|
||||
<string name="home_status_stub">وضعیت Stub</string>
|
||||
<string name="home_installed_version">نصب شده</string>
|
||||
<string name="home_latest_version">آخرین نسخه</string>
|
||||
<string name="invalid_update_channel">کانال بروزرسانی نامعتبر است</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">بعدی</string>
|
||||
<string name="install_start">بزن بریم</string>
|
||||
<string name="manager_download_install">برای دانلود و نصب فشار دهید</string>
|
||||
<string name="download_zip_only">فقط zip را دانلود شود</string>
|
||||
<string name="direct_install">نصب مستقیم (توصیه می شود)</string>
|
||||
<string name="install_inactive_slot">نصب در حافظه غیر فعال (بعد OTA)</string>
|
||||
<string name="install_inactive_slot_msg">بعد از راه اندازی مجدد دستگاه شما مجبور به راه اندازی در حافظه غیرفعال فعلی می شود! \nفقط پس از انجام OTA از این گزینه استفاده کنید. \nادامه می دهید؟</string>
|
||||
@@ -131,10 +125,6 @@
|
||||
<string name="settings_download_path_message">فایل ها در %1$s ذخیره خواهند شد.</string>
|
||||
<string name="settings_clear_cache_title">پاک کردن حافظه پنهان</string>
|
||||
<string name="settings_clear_cache_summary">پاک کردن اطلاعات ذخیره شده برای ریپوسیتوری های آنلاین. این کار برنامه را مجبور به دریافت دوباره اطللاعات هنگام آنلاین شدن میکند</string>
|
||||
<string name="settings_hide_manager_title">پنهان کردن Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">پکیج بندی مجدد Magisk Manager با نام تصادفی برای پکیج ها و برنامه ها</string>
|
||||
<string name="settings_restore_manager_title">بازگرداندن Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">بازگرداندن Magisk Manager نام اصلی پکیج ها و برنامه ها</string>
|
||||
<string name="language">زبان</string>
|
||||
<string name="system_default">(پیش فرض سیستم)</string>
|
||||
<string name="settings_check_update_title">چک کردن بروز رسانی ها</string>
|
||||
@@ -194,10 +184,7 @@
|
||||
<string name="progress_channel">Progress اعلان</string>
|
||||
<string name="download_complete">دانلود کامل شد</string>
|
||||
<string name="download_file_error">خطا در دانلود فایل</string>
|
||||
<string name="download_open_parent">نمایش پوشه</string>
|
||||
<string name="download_open_self">نمایش فایل</string>
|
||||
<string name="magisk_update_title">بروزرسانی Magisk در دسترس است!</string>
|
||||
<string name="manager_update_title">بروزرسانی Magisk Manager در دسترس است!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">بله</string>
|
||||
@@ -211,8 +198,6 @@
|
||||
<string name="flashing">ر حال فلش کردن…</string>
|
||||
<string name="done">تمام!</string>
|
||||
<string name="failure">ناموفق</string>
|
||||
<string name="hide_manager_title">قایم شدن Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">پنهان کردن Magisk Manager ناموفق بود.</string>
|
||||
<string name="open_link_failed_toast">هیچ برنامه ای برای باز کردن لینک یافت نشد</string>
|
||||
<string name="complete_uninstall">کامل کردن حذف</string>
|
||||
<string name="restore_img">بازیابی تصاویر</string>
|
||||
@@ -220,16 +205,12 @@
|
||||
<string name="restore_done">بازیابی انجام شد!</string>
|
||||
<string name="restore_fail">نسخه پشتیبان استک موجود نیست!</string>
|
||||
<string name="proprietary_title">دانلود کد اختصاصی</string>
|
||||
<string name="proprietary_notice">برنامه Magisk Manager رایگان و متن باز است و حاوی کد اختصاصی Google\'s SafetyNet API نیست.\n\nآیا به Magisk Manager اجازه برای بررسی اکستنشن SafetyNet (شامل GoogleApiClient) می دهید؟</string>
|
||||
<string name="setup_fail">نصب انجام نشد</string>
|
||||
<string name="env_fix_title">به تنظیمات اضافی نیاز دارد</string>
|
||||
<string name="env_fix_msg">دستگاه شما برای کار صحیح Magisk به تنظیمات اضافی نیاز دارد. این کار نصب Magisk zip را بارگیری می کند. میخوای الان ادامه بدی؟</string>
|
||||
<string name="setup_msg">راه اندازی محیط نصب…</string>
|
||||
<string name="authenticate">اعتبار دادن</string>
|
||||
<string name="unsupport_magisk_title">نسخه پشتیبانی نشده Magisk</string>
|
||||
<string name="unsupport_magisk_msg">این نسخه از Magisk Manager از نسخه Magisk کمتر از پشتیبانی نمی کند %1$s.\n\nاین برنامه به گونه ای رفتار می کند که گویی هیچ Magisk نصب نشده است ، لطفاً در اسرع وقت Magisk را ارتقا دهید.</string>
|
||||
<string name="external_rw_permission_denied">برای فعال کردن این قابلیت ، اجازه دسترسی به حافظه بدهید</string>
|
||||
<string name="add_shortcut_title">اضافه کردن میانبر را به صفحه</string>
|
||||
<string name="add_shortcut_msg">پس از پنهان کردن ManagerMagisk ، ممکن است تشخیص نام و نماد آن دشوار باشد. آیا می خواهید یک میانبر زیبا به صفحه اصلی اضافه کنید؟</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,20 +14,16 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Aucune connexion disponible</string>
|
||||
<string name="app_changelog">Journal des modifications</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Chargement…</string>
|
||||
<string name="update">Mettre à jour</string>
|
||||
<string name="not_available">non disponible</string>
|
||||
<string name="hide">Masquer</string>
|
||||
<string name="status">État</string>
|
||||
<string name="home_package">Paquet</string>
|
||||
|
||||
<string name="home_notice_content">Assurez‑vous de toujours utiliser la version libre de Magisk Manager. Une version provenant d’une source inconnue peut effectuer des actions malveillantes.</string>
|
||||
<string name="home_notice_content">Téléchargez Magisk SEULEMENT depuis la page Github officielle. Les fichiers provenant de sources inconnues peuvent être malveillants !</string>
|
||||
<string name="home_support_title">Soutenez‑nous</string>
|
||||
<string name="home_item_source">Sources</string>
|
||||
<string name="home_support_content">Magisk est, et sera toujours, libre et open source. Vous pouvez cependant nous témoigner de votre soutien en envoyant un petit don.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Installé</string>
|
||||
<string name="home_latest_version">Dernière</string>
|
||||
<string name="invalid_update_channel">Canal de mise à jour invalide</string>
|
||||
@@ -44,7 +40,6 @@
|
||||
<string name="install_next">Suivant</string>
|
||||
<string name="install_start">C’est parti</string>
|
||||
<string name="manager_download_install">Appuyez pour le télécharger et l’installer</string>
|
||||
<string name="download_zip_only">Télécharger le ZIP sans l’installer</string>
|
||||
<string name="direct_install">Installation directe (recommandée)</string>
|
||||
<string name="install_inactive_slot">Installer dans l’espace inactif (après mise à jour OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Votre appareil sera obligatoirement réamorcé à partir de l’espace (slot) actuellement inactif après son redémarrage !\nN’utilisez uniquement cette option qu’après que la mise à jour OTA a été effectuée.\nVoulez‑vous continuer ?</string>
|
||||
@@ -137,10 +132,10 @@
|
||||
<string name="settings_download_path_message">Les fichiers seront enregistrés sous %1$s</string>
|
||||
<string name="settings_clear_cache_title">Vider le cache des dépôts</string>
|
||||
<string name="settings_clear_cache_summary">Effacer les informations en cache concerant les dépôts en ligne. Ceci force l’application à télécharger des informations à jour.</string>
|
||||
<string name="settings_hide_manager_title">Masquer Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Réempaqueter Magisk Manager avec des noms de paquet et d’application aléatoires.</string>
|
||||
<string name="settings_restore_manager_title">Restaurer Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Restaurer Magisk Manager avec ses noms de paquet et d’application d’origine.</string>
|
||||
<string name="settings_hide_app_title">Masquer l’application Magisk</string>
|
||||
<string name="settings_hide_app_summary">Installer une application intermédiaire avec un ID de package aléatoire et un nom personnalisé</string>
|
||||
<string name="settings_restore_app_title">Restorer l’application Magisk</string>
|
||||
<string name="settings_restore_app_summary">Démasquer l’application et la restaurer à son APK d’origine</string>
|
||||
<string name="language">Langue</string>
|
||||
<string name="system_default">(langue par défaut du système)</string>
|
||||
<string name="settings_check_update_title">Vérifier les mises à jour</string>
|
||||
@@ -204,10 +199,7 @@
|
||||
<string name="progress_channel">Notifications de progression</string>
|
||||
<string name="download_complete">Téléchargement terminé</string>
|
||||
<string name="download_file_error">Erreur lors du téléchargement du fichier</string>
|
||||
<string name="download_open_parent">Afficher le dossier parent</string>
|
||||
<string name="download_open_self">Afficher le fichier</string>
|
||||
<string name="magisk_update_title">Une mise à jour de Magisk est disponible !</string>
|
||||
<string name="manager_update_title">Une mise à jour de Magisk Manager est disponible !</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Oui</string>
|
||||
@@ -221,27 +213,25 @@
|
||||
<string name="flashing">Écriture dans la mémoire Flash…</string>
|
||||
<string name="done">Terminé !</string>
|
||||
<string name="failure">Erreur</string>
|
||||
<string name="hide_manager_title">Masquage de Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Le masquage de Magisk Manager a échoué.</string>
|
||||
<string name="hide_app_title">Masquage de l’application Magisk…</string>
|
||||
<string name="open_link_failed_toast">Aucune application permettant d’ouvrir le lien n’a été trouvée</string>
|
||||
<string name="restore_manager_fail_toast">Échec de la restauration de Magisk Manager</string>
|
||||
<string name="complete_uninstall">Désinstallation complète</string>
|
||||
<string name="restore_img">Restauration des images</string>
|
||||
<string name="restore_img_msg">Restauration…</string>
|
||||
<string name="restore_done">Restauration effectuée !</string>
|
||||
<string name="restore_fail">La sauvegarde par défaut n’existe pas !</string>
|
||||
<string name="proprietary_title">Téléchargement de code propriétaire</string>
|
||||
<string name="proprietary_notice">Magisk Manager est un logiciel libre et ne contient pas le code propriétaire de l’API SafetyNet de Google. Autorisez‑vous Magisk Manager à télécharger une extension (contenant GoogleApiClient) permettant d’effectuer les contrôles SafetyNet ?</string>
|
||||
<string name="proprietary_notice">L’application Magisk est un logiciel libre et ne contient pas de code propriétaire de l’API SafetyNet de Google. Souhaitez-vous télécharger une extension permettant d’effectuer les contrôles SafetyNet ?</string>
|
||||
<string name="setup_fail">Échec de l’installation</string>
|
||||
<string name="env_fix_title">Installation supplémentaire requise</string>
|
||||
<string name="env_fix_msg">Votre appareil a besoin d’une installation supplémentaire afin que Magisk fonctionne correctement. Un fichier ZIP d’installation pour Magisk doit être téléchargé. Voulez‑vous effectuer cette installation maintenant ?</string>
|
||||
<string name="env_fix_msg">Votre appareil a besoin d’une installation supplémentaire afin que Magisk fonctionne correctement. Voulez-vous effectuer cette installation maintenant et redémarrer ?</string>
|
||||
<string name="setup_msg">Configuration de l’environnement en cours…</string>
|
||||
<string name="authenticate">Authentification</string>
|
||||
<string name="unsupport_magisk_title">Version de Magisk non prise en charge</string>
|
||||
<string name="unsupport_magisk_msg">Cette version de Magisk Manager ne prend pas en charge les versions de Magisk inférieures à %1$s.\n\nL’application se comportera comme si Magisk n’était pas installé. Veuillez mettre à jour Magisk aussi vite que possible.</string>
|
||||
<string name="unsupport_magisk_msg">Cette version de Magisk ne prend pas en charge les versions de Magisk inférieures à %1$s.\n\nL’application se comportera comme si Magisk n’était pas installé. Veuillez mettre à jour Magisk aussi vite que possible.</string>
|
||||
<string name="external_rw_permission_denied">Permettre l’accès au stockage pour activer cette fonctionnalité</string>
|
||||
<string name="add_shortcut_title">Ajouter un raccourci à l’écran d’accueil</string>
|
||||
<string name="add_shortcut_msg">Après avoir caché Magisk Manager, son nom et son icône peuvent devenir difficiles à reconnaître. Voulez‑vous ajouter un joli raccourci vers l’écran d’accueil ?</string>
|
||||
<string name="add_shortcut_msg">Après avoir masqué Magisk, son nom et son icône peuvent devenir difficiles à reconnaître. Voulez‑vous ajouter un joli raccourci vers l’écran d’accueil ?</string>
|
||||
<string name="app_not_found">Aucune application trouvée pour traiter cette action</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">कोई कनेक्शन उपलब्ध नहीं है</string>
|
||||
<string name="app_changelog">बदलाव</string>
|
||||
<string name="manager">मैनेजर</string>
|
||||
<string name="loading">लोड हो रहा है…</string>
|
||||
<string name="update">अपडेट करें</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">छिपाएँ</string>
|
||||
<string name="status">स्थिति</string>
|
||||
<string name="home_package">पैकेज</string>
|
||||
|
||||
<string name="home_notice_content">हमेशा सुनिश्चित करें कि आप ओपन-सोर्स मैजिक मैनेजर का उपयोग कर रहे हैं। अज्ञात स्रोत के प्रबंधक दुर्भावनापूर्ण कार्य कर सकते हैं।</string>
|
||||
<string name="home_support_title">हमें सहयोग दीजिये</string>
|
||||
<string name="home_item_source">स्रोत</string>
|
||||
<string name="home_support_content">मैजिस्क है, और हमेशा मुफ्त और ओपन-सोर्स रहेगा। हालाँकि आप एक छोटा सा दान भेजकर यह दिखा सकते हैं कि आप देख-भाल करते हैं।</string>
|
||||
<string name="home_status_normal">साधारण</string>
|
||||
<string name="home_status_stub">स्टब</string>
|
||||
<string name="home_installed_version">इंस्टॉल्ड</string>
|
||||
<string name="home_latest_version">नवीनतम</string>
|
||||
<string name="invalid_update_channel">अमान्य अपडेट चैनल</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">आगे</string>
|
||||
<string name="install_start">तो चलिए शुरू करते हैं!</string>
|
||||
<string name="manager_download_install">डाउनलोड और इंस्टॉल करने के लिए दबाएं</string>
|
||||
<string name="download_zip_only">केवल ज़िप डाउनलोड करें</string>
|
||||
<string name="direct_install">प्रत्यक्ष इंस्टॉल (अनुशंसित)</string>
|
||||
<string name="install_inactive_slot">निष्क्रिय स्लॉट में इंस्टॉल करें (OTA के बाद)</string>
|
||||
<string name="install_inactive_slot_msg">आपका डिवाइस रीबूट होने के बाद वर्तमान निष्क्रिय स्लॉट में बूट करने के लिए मजबूर किया जाएगा!\n इस विकल्प का उपयोग सिर्फ OTA हो जाने के बाद करें।\n जारी रखें?</string>
|
||||
@@ -136,10 +130,6 @@
|
||||
<string name="settings_download_path_message">फ़ाइलों को %1$s में सहेजा जाएगा</string>
|
||||
<string name="settings_clear_cache_title">रेपो कैश साफ़ करें</string>
|
||||
<string name="settings_clear_cache_summary">ऑनलाइन रेपो के लिए कैश्ड जानकारी साफ़ करें। यह एप्लिकेशन को ऑनलाइन रिफ्रेश करने के लिए मजबूर करता है</string>
|
||||
<string name="settings_hide_manager_title">मैजिस्क मैनेजर छिपाएं</string>
|
||||
<string name="settings_hide_manager_summary">बेतरतीब पैकेज और ऐप नामों के साथ मैगिस्क मैनेजर को रिपैकेज करें</string>
|
||||
<string name="settings_restore_manager_title">मैजिस्क मैनेजर को रिस्टोर करें</string>
|
||||
<string name="settings_restore_manager_summary">मूल पैकेज और ऐप नाम के साथ मैजिस्क मैनेजर को रिस्टोर करें</string>
|
||||
<string name="language">भाषा</string>
|
||||
<string name="system_default">(सिस्टम डिफ़ॉल्ट)</string>
|
||||
<string name="settings_check_update_title">अपडेट जांचें</string>
|
||||
@@ -201,10 +191,7 @@
|
||||
<string name="progress_channel">प्रगति सूचनाएँ</string>
|
||||
<string name="download_complete">डाउनलोड सम्पन्न हुआ</string>
|
||||
<string name="download_file_error">फ़ाइल डाउनलोड करने में त्रुटि</string>
|
||||
<string name="download_open_parent">मूल फ़ोल्डर में दिखाएं</string>
|
||||
<string name="download_open_self">फ़ाइल दिखाएँ</string>
|
||||
<string name="magisk_update_title">मैजिस्क अपडेट उपलब्ध!</string>
|
||||
<string name="manager_update_title">मैजिस्क मैनेजर के लिए अपडेट उपलब्ध है!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">हाँ</string>
|
||||
@@ -218,9 +205,6 @@
|
||||
<string name="flashing">फ़्लैश हो रहा है...</string>
|
||||
<string name="done">सफल हुआ!</string>
|
||||
<string name="failure">असफल हुआ</string>
|
||||
<string name="hide_manager_title">मैजिस्क मैनेजर को छिपा रहे हैं...</string>
|
||||
<string name="hide_manager_fail_toast">मैजिस्क मैनेजर छिपाना विफल हुआ</string>
|
||||
<string name="restore_manager_fail_toast">मैजिस्क मैनेजर को रिस्टोर करना विफल हुआ</string>
|
||||
<string name="open_link_failed_toast">लिंक खोलने के लिए कोई एप्लिकेशन नहीं मिला</string>
|
||||
<string name="complete_uninstall">पूर्ण रूप से अनइंस्टॉल करें</string>
|
||||
<string name="restore_img">इमेज रिस्टोर करें</string>
|
||||
@@ -228,17 +212,13 @@
|
||||
<string name="restore_done">रिस्टोर सफल हुआ!</string>
|
||||
<string name="restore_fail">स्टॉक बैकअप मौजूद नहीं है!</string>
|
||||
<string name="proprietary_title">मालिकाना कोड डाउनलोड करें</string>
|
||||
<string name="proprietary_notice">मैजिस्क मैनेजर एक मुफ्त और ओपन-सोर्स ऐप है जो गूगल के मालिकाना सेफ्टीनेट कोड का इस्तेमाल नहीं करता। क्या आप मैजिस्क मैनेजर को सेफ्टीनेट की जांच के लिए एक एक्सटेंशन डाऊनलोड करने की अनुमति प्रदान करना चाहेंगे?</string>
|
||||
<string name="setup_fail">सेटअप असफल हुआ</string>
|
||||
<string name="env_fix_title">अतिरिक्त सेटअप की ज़रूरत है</string>
|
||||
<string name="env_fix_msg">आपके डिवाइस पर मैजिस्क को सही से काम करने के लिए अतिरिक्त सेटअप की ज़रूरत है। यह एक मैजिस्क सेटअप ज़िप डाउनलोड करेगा, क्या आप आगे बढ़ना चाहेंगे?</string>
|
||||
<string name="setup_msg">वातावरण सेटअप चल रहा है...</string>
|
||||
<string name="authenticate">प्रमाणित करें</string>
|
||||
<string name="unsupport_magisk_title">असमर्थित मैजिस्क संस्करण</string>
|
||||
<string name="unsupport_magisk_msg">मैजिस्क मैनेजर का यह संस्करण मैजिस्क संस्करण %1$s से कम का समर्थन नहीं करता। \n\nऐप इस तरह व्यवहार करेगा जैसे मैजिस्क इंस्टॉल नहीं है, कृपया मैजिस्क को जल्द अपग्रेड करें।</string>
|
||||
<string name="external_rw_permission_denied">इसका उपयोग करने के लिए स्टोरेज अनुमति प्रदान करें</string>
|
||||
<string name="add_shortcut_title">होम स्क्रीन पर शॉर्टकट जोड़ें</string>
|
||||
<string name="add_shortcut_msg">मैजिस्क मैनेजर को छिपाने के बाद इसका नाम और आइकॉन पहचानना मुश्किल हो सकता है, क्या आप एक अच्छा दिखने वाला शॉर्टकट होम स्क्रीन पर जोड़ना चाहेंगे?</string>
|
||||
<string name="app_not_found">इस एक्शन को संभालने के लिए कोई एप्लिकेशन नहीं मिली</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -15,20 +15,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Nema dostupne veze</string>
|
||||
<string name="app_changelog">Popis izmjena</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Učitavanje…</string>
|
||||
<string name="update">Ažuriraj</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Sakrij</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Paket</string>
|
||||
|
||||
<string name="home_notice_content">Uvijek provjerite koristite li Magisk Manager s otvorenim kodom. Manager nepoznatog izvora može izvoditi zlonamjerne radnje.</string>
|
||||
<string name="home_support_title">Podržite nas</string>
|
||||
<string name="home_item_source">Izvor</string>
|
||||
<string name="home_support_content">Magisk je i uvijek će biti besplatan i otvoren. Međutim, možete nam pokazati da vam je stalo slanjem male donacije.</string>
|
||||
<string name="home_status_normal">Normalno</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Instalirana</string>
|
||||
<string name="home_latest_version">Najnovija</string>
|
||||
<string name="invalid_update_channel">Nevažeći kanal ažuriranja</string>
|
||||
@@ -45,7 +40,6 @@
|
||||
<string name="install_next">Dalje</string>
|
||||
<string name="install_start">Krenimo</string>
|
||||
<string name="manager_download_install">Dodirnite za preuzimanje i instalaciju</string>
|
||||
<string name="download_zip_only">Preuzmi samo zip</string>
|
||||
<string name="direct_install">Izravna instalacija (preporučeno)</string>
|
||||
<string name="install_inactive_slot">Instaliraj u neaktivni utor (Nakon OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Vaš će se uređaj prisiliti pokrenuti s trenutnog neaktivnog mjesta nakon ponovnog pokretanja!\nKoristite tu opciju samo nakon što je OTA dovršena.\nContinue?</string>
|
||||
@@ -134,10 +128,6 @@
|
||||
<string name="settings_download_path_message">Datoteke će biti spremljene u %1$s</string>
|
||||
<string name="settings_clear_cache_title">Obriši predmemoriju repozitorija</string>
|
||||
<string name="settings_clear_cache_summary">Obrišite predmemorirane podatke za mrežne repozitorije. To prisiljava aplikaciju da se osvježi na mreži</string>
|
||||
<string name="settings_hide_manager_title">Sakrij Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Prepakiraj Magisk Manager s nasumičnim nazivima paketa i aplikacija</string>
|
||||
<string name="settings_restore_manager_title">Vrati Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Vrati Magisk Manager s izvornim nazivima paketa i aplikacija</string>
|
||||
<string name="language">Jezik</string>
|
||||
<string name="system_default">(Zadano sustavom)</string>
|
||||
<string name="settings_check_update_title">Provjeri za ažuriranja</string>
|
||||
@@ -199,10 +189,7 @@
|
||||
<string name="progress_channel">Obavijesti o napretku</string>
|
||||
<string name="download_complete">Preuzimanje završeno</string>
|
||||
<string name="download_file_error">Pogreška pri preuzimanju datoteke</string>
|
||||
<string name="download_open_parent">Prikaži u nadređenoj mapi</string>
|
||||
<string name="download_open_self">Prikaži datoteku</string>
|
||||
<string name="magisk_update_title">Dostupno je Magisk ažuriranje!</string>
|
||||
<string name="manager_update_title">Dostupno je Magisk Manager ažuriranje! </string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Da</string>
|
||||
@@ -216,8 +203,6 @@
|
||||
<string name="flashing">Apliciranje…</string>
|
||||
<string name="done">Dovršeno!</string>
|
||||
<string name="failure">Nije uspjelo</string>
|
||||
<string name="hide_manager_title">Skrivanje Magisk Manager-a…</string>
|
||||
<string name="hide_manager_fail_toast">Skrivanje Magisk Manager-a nije uspjelo.</string>
|
||||
<string name="open_link_failed_toast">Nije pronađena aplikacija za otvaranje veze</string>
|
||||
<string name="complete_uninstall">Dovršite deinstalaciju</string>
|
||||
<string name="restore_img">Vrati Images</string>
|
||||
@@ -225,16 +210,12 @@
|
||||
<string name="restore_done">Vraćanje je dovršeno!</string>
|
||||
<string name="restore_fail">Izvorna Sig. kopija ne postoji!</string>
|
||||
<string name="proprietary_title">Preuzmite vlasnički kod</string>
|
||||
<string name="proprietary_notice">Magisk Manager je FOSS i ne sadrži Googleov zaštićeni API sigurnosni kod.\n\nHoćete li dopustiti Magisk Manageru da preuzme proširenje (sadrži GoogleApiClient) za SafetyNet provjeru?</string>
|
||||
<string name="setup_fail">Postavljanje nije uspjelo</string>
|
||||
<string name="env_fix_title">Zahtijeva dodatno postavljanje</string>
|
||||
<string name="env_fix_msg">Vašem je uređaju potrebno dodatno postavljanje kako bi Magisk ispravno radio. Preuzet će se zip za postavljanje Magiska, želite li nastaviti sada?</string>
|
||||
<string name="setup_msg">Postavljanje okruženja za pokretanje…</string>
|
||||
<string name="authenticate">Potvrdi</string>
|
||||
<string name="unsupport_magisk_title">Nepodržana Magisk verzija</string>
|
||||
<string name="unsupport_magisk_msg">Ova verzija Magisk Manager-a ne podržava Magisk verziju nižu od %1$s.\n\nAplikacija će se ponašati kao da nije instaliran Magisk, ažurirajte Magisk što je prije moguće.</string>
|
||||
<string name="external_rw_permission_denied">Odobrite dopuštenje za pohranu da biste omogućili ovu funkciju</string>
|
||||
<string name="add_shortcut_title">Dodaj prečac na početni zaslon</string>
|
||||
<string name="add_shortcut_msg">Nakon skrivanja Magisk Manager-a, njegov naziv i ikonu moglo bi postati teško prepoznati. Želite li dodati lijepi prečac na početni zaslon?</string>
|
||||
<string name="app_not_found">Nije pronađena nijedna aplikacijaza obradu ove radnju</string>
|
||||
</resources>
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">Koneksi tidak tersedia</string>
|
||||
<string name="app_changelog">Catatan perubahan</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Memuat…</string>
|
||||
<string name="update">Update</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Tutup</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Paket</string>
|
||||
|
||||
<string name="home_notice_content">Pastikan selalu menggunakan Magisk Manager dari sumber terbuka. Manager dari sumber yang tidak dikenal dapat melakukan tindakan jahat!</string>
|
||||
<string name="home_support_title">Dukung kami</string>
|
||||
<string name="home_item_source">Sumber</string>
|
||||
<string name="home_support_content">Magisk gratis dan bersumber terbuka, dan akan selalu seperti itu. Bagaimanapun juga Anda dapat menunjukan kepedulian Anda kepada kami dengan mengirimkan sedikit donasi.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Terinstal</string>
|
||||
<string name="home_latest_version">Terbaru</string>
|
||||
<string name="invalid_update_channel">Kanal update tidak valid</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">Berikutnya</string>
|
||||
<string name="install_start">Mulai</string>
|
||||
<string name="manager_download_install">Sentuh untuk download dan instal</string>
|
||||
<string name="download_zip_only">Download zip saja</string>
|
||||
<string name="direct_install">Langsung instal (Disarankan)</string>
|
||||
<string name="install_inactive_slot">Instal pada slot nonaktif (Setelah OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Perangkat Anda akan DIPAKSA boot ke slot yang saat ini tidak aktif setelah perangkat dinyalakan ulang!\nGunakan opsi ini hanya setelah proses OTA selesai.\nLanjutkan?</string>
|
||||
@@ -137,10 +131,6 @@
|
||||
<string name="settings_download_path_message">File akan disimpan ke %1$s</string>
|
||||
<string name="settings_clear_cache_title">Hapus cache repo</string>
|
||||
<string name="settings_clear_cache_summary">Hapus cache informasi repo online. Tindakan ini memaksa aplikasi untuk memperbarui repo online</string>
|
||||
<string name="settings_hide_manager_title">Sembunyikan Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Kemas ulang Magisk Manager dengan nama paket dan nama aplikasi secara acak</string>
|
||||
<string name="settings_restore_manager_title">Pulihkan Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Pulihkan Magisk Manager dengan nama paket dan nama aplikasi aslinya</string>
|
||||
<string name="language">Bahasa</string>
|
||||
<string name="system_default">(Default sistem)</string>
|
||||
<string name="settings_check_update_title">Periksa update</string>
|
||||
@@ -204,10 +194,7 @@
|
||||
<string name="progress_channel">Notifikasi Kemajuan</string>
|
||||
<string name="download_complete">Download selesai</string>
|
||||
<string name="download_file_error">Kesalahan saat mendownload file</string>
|
||||
<string name="download_open_parent">Tampilkan dalam folder</string>
|
||||
<string name="download_open_self">Tampilkan file</string>
|
||||
<string name="magisk_update_title">Update Magisk tersedia!</string>
|
||||
<string name="manager_update_title">Update Magisk Manager tersedia!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Ya</string>
|
||||
@@ -221,9 +208,6 @@
|
||||
<string name="flashing">Memasang…</string>
|
||||
<string name="done">Selesai!</string>
|
||||
<string name="failure">Gagal!</string>
|
||||
<string name="hide_manager_title">Menyembunyikan Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Gagal menyembunyikan Magisk Manager.</string>
|
||||
<string name="restore_manager_fail_toast">Gagal memulihkan Magisk Manager</string>
|
||||
<string name="open_link_failed_toast">Tidak ditemukan aplikasi untuk membuka link ini</string>
|
||||
<string name="complete_uninstall">Uninstal penuh</string>
|
||||
<string name="restore_img">Pulihkan image</string>
|
||||
@@ -231,17 +215,13 @@
|
||||
<string name="restore_done">Pemulihan selesai!</string>
|
||||
<string name="restore_fail">Cadangan stock tidak ada!</string>
|
||||
<string name="proprietary_title">Download kode proprieter</string>
|
||||
<string name="proprietary_notice">Magisk Manager adalah aplikasi FOSS dan tidak memiliki kode proprieter API SafetyNet Google.\n\nMaukah mengizinkan Magisk Manager untuk mendownload ekstensi (berisi GoogleApiClient) untuk memeriksa SafetyNet?</string>
|
||||
<string name="setup_fail">Penyiapan gagal</string>
|
||||
<string name="env_fix_title">Perlu penyiapan tambahan</string>
|
||||
<string name="env_fix_msg">Perangkat Anda memerlukan penyiapan tambahan agar Magisk bekerja dengan baik. Perangkat akan mendownload zip untuk penyiapan Magisk, apakah Anda ingin melanjutkan sekarang?</string>
|
||||
<string name="setup_msg">Memproses penyiapan lingkungan…</string>
|
||||
<string name="authenticate">Autentikasi</string>
|
||||
<string name="unsupport_magisk_title">Versi Magisk tidak didukung</string>
|
||||
<string name="unsupport_magisk_msg">Versi Magisk Manager ini tidak mendukung Magisk di bawah versi %1$s.\n\nAplikasi akan berperilaku seolah-olah Magisk tidak terinstal, harap meningkatkan Magisk sesegera mungkin.</string>
|
||||
<string name="external_rw_permission_denied">Berikan izin akses ke penyimpanan untuk mengaktifkan fungsi ini</string>
|
||||
<string name="add_shortcut_title">Tambahkan pintasan ke layar utama</string>
|
||||
<string name="add_shortcut_msg">Setelah menyembunyikan Magisk Manager, nama dan ikonnya mungkin menjadi sulit untuk dikenali. Apakah Anda ingin menambahkan pintasan yang menarik pada layar utama?</string>
|
||||
<string name="app_not_found">Tidak ditemukan aplikasi untuk menangani tindakan ini</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -13,22 +13,17 @@
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">Connessione non disponibile</string>
|
||||
<string name="home_notice_content">Assicurarsi di utilizzare la versione open source di Magisk Manager. Se proveniente da fonti sconosciute, potrebbe eseguire azioni dannose.</string>
|
||||
<string name="hide">Hide</string>
|
||||
<string name="app_changelog">Changelog</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="home_status_stub">Nascosto</string>
|
||||
<string name="home_latest_version">Ultima</string>
|
||||
<string name="home_installed_version">Installata</string>
|
||||
<string name="home_support_title">Supportaci</string>
|
||||
<string name="home_item_source">Codice sorgente</string>
|
||||
<string name="home_support_content">Magisk è e sempre sarà gratuito ed open source. Puoi comunque mostrarci il tuo apprezzamento inviando una piccola donazione.</string>
|
||||
<string name="home_package">Pacchetto</string>
|
||||
<string name="home_status_normal">Normale</string>
|
||||
<string name="home_check_safetynet">Controlla SafetyNet</string>
|
||||
<string name="loading">Caricamento…</string>
|
||||
<string name="not_available">N/D</string>
|
||||
<string name="status">Stato</string>
|
||||
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
|
||||
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi!\nIl root verrà rimosso e i tuoi dati potrebbero essere criptati, nel caso non lo siano già.</string>
|
||||
@@ -43,7 +38,6 @@
|
||||
<string name="install_next">Avanti</string>
|
||||
<string name="install_start">Andiamo!</string>
|
||||
<string name="manager_download_install">Apri questa notifica per scaricare e installare</string>
|
||||
<string name="download_zip_only">Scarica solo il file zip</string>
|
||||
<string name="direct_install">Installazione diretta (raccomandata)</string>
|
||||
<string name="install_inactive_slot">Installa nello slot inattivo (dopo un aggiornamento OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Questo dispositivo verrà FORZATO ad avviarsi usando lo slot inattivo!\nUsa questo metodo solo dopo che un aggiornamento OTA è stato installato.\nVuoi continuare?</string>
|
||||
@@ -136,10 +130,6 @@
|
||||
<string name="settings_download_path_message">I file verranno salvati in %1$s</string>
|
||||
<string name="settings_clear_cache_title">Svuota cache repository</string>
|
||||
<string name="settings_clear_cache_summary">Svuota la cache dei repository. In questo modo l\'app sarà costretta a recuperare le informazioni online</string>
|
||||
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome pacchetto e app casuali</string>
|
||||
<string name="settings_restore_manager_title">Ripristina Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Ripristina Magisk Manager con il nome pacchetto e app originali</string>
|
||||
<string name="language">Lingua</string>
|
||||
<string name="system_default">(Sistema)</string>
|
||||
<string name="settings_check_update_title">Controlla aggiornamenti</string>
|
||||
@@ -203,10 +193,7 @@
|
||||
<string name="progress_channel">Notifiche di avanzamento</string>
|
||||
<string name="download_complete">Download completato</string>
|
||||
<string name="download_file_error">Errore durante il download del file</string>
|
||||
<string name="download_open_parent">Mostra nella cartella padre</string>
|
||||
<string name="download_open_self">Mostra file</string>
|
||||
<string name="magisk_update_title">È disponibile un aggiornamento di Magisk!</string>
|
||||
<string name="manager_update_title">È disponibile un aggiornamento di Magisk Manager!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Sì</string>
|
||||
@@ -220,9 +207,6 @@
|
||||
<string name="flashing">Flash in corso…</string>
|
||||
<string name="done">Completato!</string>
|
||||
<string name="failure">Fallito</string>
|
||||
<string name="hide_manager_title">Nascondendo Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Non è stato possibile nascondere Magisk Manager.</string>
|
||||
<string name="restore_manager_fail_toast">Non è stato possibile ripristinare Magisk Manager.</string>
|
||||
<string name="open_link_failed_toast">Nessuna app disponibile per aprire il link</string>
|
||||
<string name="complete_uninstall">Disinstalla completamente</string>
|
||||
<string name="restore_img">Ripristina immagini</string>
|
||||
@@ -230,17 +214,13 @@
|
||||
<string name="restore_done">Ripristino completato!</string>
|
||||
<string name="restore_fail">Non esiste un backup dell\'immagine di boot originale!</string>
|
||||
<string name="proprietary_title">Scarica codice proprietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager è un software libero e open source e non contiene codice proprietario delle API SafetyNet di Google.\n\nVuoi scaricare un\'estensione (contenente GoogleApiClient) per controllare lo stato di SafetyNet?</string>
|
||||
<string name="setup_fail">Configurazione fallita</string>
|
||||
<string name="env_fix_title">Configurazione aggiuntiva richiesta</string>
|
||||
<string name="env_fix_msg">Il tuo dispositivo necessita di una configurazione aggiuntiva per far funzionare Magisk correttamente. Verrà scaricato il file zip di Magisk, vuoi procedere ora?</string>
|
||||
<string name="setup_msg">Configurazione dell\'ambiente in corso…</string>
|
||||
<string name="authenticate">Autentica</string>
|
||||
<string name="unsupport_magisk_title">Versione di Magisk non supportata</string>
|
||||
<string name="unsupport_magisk_msg">Questa versione di Magisk Manager non supporta versioni di Magisk inferiori a %1$s.\n\nQuesta app si comporterà come se non fosse installato Magisk, che deve essere aggiornato per procedere all\'utilizzo.</string>
|
||||
<string name="external_rw_permission_denied">Consenti l\'accesso alla memoria del dispositivo per abilitare questa opzione</string>
|
||||
<string name="add_shortcut_title">Aggiungi collegamento alla schermata iniziale</string>
|
||||
<string name="add_shortcut_msg">Dopo aver nascosto Magisk Manager, il suo nome e la sua icona potrebbero diventare difficili da riconoscere. Vuoi aggiungere una scorciatoia alla schermata principale?</string>
|
||||
<string name="app_not_found">Nessuna app disponibile per gestire quest\'azione</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,26 +14,21 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">אין חיבור זמין</string>
|
||||
<string name="app_changelog">רשימת שינויים</string>
|
||||
<string name="manager">מנהל</string>
|
||||
<string name="loading">טוען…</string>
|
||||
<string name="update">עדכון</string>
|
||||
<string name="not_available">ל/ז</string>
|
||||
<string name="hide">הסתרה</string>
|
||||
<string name="status">סטטוס</string>
|
||||
<string name="home_package">חבילה</string>
|
||||
|
||||
<string name="home_notice_content">ודא שאתה משתמש במנהל Magisk המשתמש בקוד פתוח. מנהל ממקור לא ידוע יכול לבצע פעולות זדוניות.</string>
|
||||
<string name="home_support_title">תמיכה בנו</string>
|
||||
<string name="home_item_source">מקור</string>
|
||||
<string name="home_support_content">Magisk היה ותמיד יהיה בעל קוד מקור פתוח. עם זאת אתה יכול להראות לנו שאכפת לך על ידי שליחת תרומה קטנה.</string>
|
||||
<string name="home_status_normal">רגיל</string>
|
||||
<string name="home_status_stub">חלקי</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="home_check_safetynet">בדיקת SafetyNet</string>
|
||||
<string name="home_check_safetynet">בדיקת SafetyNet</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">שמירה על הצפנה בכח</string>
|
||||
@@ -44,20 +39,19 @@
|
||||
<string name="install_next">הבא</string>
|
||||
<string name="install_start">צא לדרך</string>
|
||||
<string name="manager_download_install">לחץ להורדה והתקנה</string>
|
||||
<string name="download_zip_only">הורד ZIP בלבד</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="setup_title">התקנה נוספת</string>
|
||||
<string name="select_patch_file">בחר ותקן קובץ</string>
|
||||
<string name="select_patch_file">בחר והתקן קובץ</string>
|
||||
<string name="patch_file_msg">בחר תמונה גולמית (*.img) או ODIN קובץ tar (*.tar)</string>
|
||||
<string name="reboot_delay_toast">מאתחל בעוד 5 שניות…</string>
|
||||
<string name="flash_screen_title">התקנה</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">בקשות משתמש על</string>
|
||||
<string name="touch_filtered_warning">מכיוון שאפליקציה מסתירה בקשה של משתמש על, Magisk לא יכולה לאמת את תגובתך</string>
|
||||
<string name="deny">דחה</string>
|
||||
<string name="touch_filtered_warning">מכיוון שיישום מסתיר בקשה של משתמש על, Magisk לא יכול לאמת את תגובתך</string>
|
||||
<string name="deny">דחה</string>
|
||||
<string name="prompt">מיידי</string>
|
||||
<string name="grant">הענק</string>
|
||||
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nדחה באם אינך בטוח!</string>
|
||||
@@ -103,7 +97,7 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">הצגת יישומי מערכת</string>
|
||||
<string name="show_os_app">הצגת יישומי מערכת הפעלה</string>
|
||||
<string name="show_os_app">הצגת יישומי מערכת הפעלה</string>
|
||||
<string name="hide_filter_hint">סינון לפי שם</string>
|
||||
<string name="hide_scroll_up">גלול למעלה</string>
|
||||
<string name="hide_filters">מסננים</string>
|
||||
@@ -111,7 +105,7 @@
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(לא סופק מידע)</string>
|
||||
<string name="reboot_userspace">אתחול מהיר</string>
|
||||
<string name="reboot_userspace">אתחול מהיר</string>
|
||||
<string name="reboot_recovery">אתחול למצב שחזור</string>
|
||||
<string name="reboot_bootloader">אתחול מצב מנהל האתחול</string>
|
||||
<string name="reboot_download">אתחול מצב הורדה</string>
|
||||
@@ -137,10 +131,6 @@
|
||||
<string name="settings_download_path_message">הקבצים ישמרו אל %1$s</string>
|
||||
<string name="settings_clear_cache_title">נקה מטמון ריפו</string>
|
||||
<string name="settings_clear_cache_summary">נקה מידע זיכרון מטמון עבור ריפו מקוונים, זה יכריח את היישום לרענן באופן מקוון</string>
|
||||
<string name="settings_hide_manager_title">הסתר את מנהל Magisk</string>
|
||||
<string name="settings_hide_manager_summary">ארוז מחדש את מנהל Magisk עם חבילה ושם אקראיים</string>
|
||||
<string name="settings_restore_manager_title">שחזר את מנהל Magisk</string>
|
||||
<string name="settings_restore_manager_summary">שחזר את מנהל Magisk עם חבילה ושם מקוריים</string>
|
||||
<string name="language">שפה</string>
|
||||
<string name="system_default">(ברירת מחדל מערכת)</string>
|
||||
<string name="settings_check_update_title">בדוק עדכונים</string>
|
||||
@@ -178,9 +168,9 @@
|
||||
<string name="settings_su_biometric_summary">השתמש באימות ביומטרי כדי לאפשר בקשות לשימוש במשתמש על</string>
|
||||
<string name="no_biometric">התקן לא נתמך או הגדרות ביומטריות אינן מאופשרות</string>
|
||||
<string name="settings_customization">התאמה אישית</string>
|
||||
<string name="setting_add_shortcut_summary">הוסף קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת האפליקציה</string>
|
||||
<string name="setting_add_shortcut_summary">הוסף קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת היישום</string>
|
||||
<string name="settings_doh_title">DNS על HTTPS</string>
|
||||
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
|
||||
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
|
||||
<string name="multiuser_mode">מצב מרובה משתמשים</string>
|
||||
<string name="settings_owner_only">בעל ההתקן בלבד</string>
|
||||
<string name="settings_owner_manage">אחראי ניהול ההתקן</string>
|
||||
@@ -202,10 +192,7 @@
|
||||
<string name="progress_channel">התראות התקדמות</string>
|
||||
<string name="download_complete">ההורדה הושלמה</string>
|
||||
<string name="download_file_error">שגיאה בהורדת קובץ</string>
|
||||
<string name="download_open_parent">הצג בתיקיית אב</string>
|
||||
<string name="download_open_self">הצג קובץ</string>
|
||||
<string name="magisk_update_title">עדכון Magisk זמין!</string>
|
||||
<string name="manager_update_title">עדכון מנהל Magisk זמין!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">כן</string>
|
||||
@@ -219,26 +206,19 @@
|
||||
<string name="flashing">צורב…</string>
|
||||
<string name="done">בוצע!</string>
|
||||
<string name="failure">נכשל</string>
|
||||
<string name="hide_manager_title">מסתיר את מנהל Magisk…</string>
|
||||
<string name="hide_manager_fail_toast">הסתרת מנהל Magisk כשלה.</string>
|
||||
<string name="restore_manager_fail_toast">שחזור מנהל Magisk נכשל</string>
|
||||
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
|
||||
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
|
||||
<string name="complete_uninstall">הסרה מלאה</string>
|
||||
<string name="restore_img">שיחזור תמונות</string>
|
||||
<string name="restore_img_msg">משחזר…</string>
|
||||
<string name="restore_done">השיחזור בוצע!</string>
|
||||
<string name="restore_fail">גיבוי מקורי אינו קיים!</string>
|
||||
<string name="proprietary_title">הורד קוד קנייני</string>
|
||||
<string name="proprietary_notice">מנהל Magisk הוא חינמי ובעל קוד מקור פתוח ואינו מכיל את קוד ה-API של SafetyNet הקנייני של גוגל.\n\nהאם תרשה למנהל Magisk להוריד את הסיומת (מכיל את GoogleApiClient) לבדיקות SafetyNet?</string>
|
||||
<string name="setup_fail">ההתקנה כשלה</string>
|
||||
<string name="env_fix_title">דורש התקנה נוספת</string>
|
||||
<string name="env_fix_msg">ההתקן שלך זקוק להתקנה נוספת בכדי ש-Magisk יעבוד כראוי. זה יוריד קובץ התקנה zip של Magisk, האם ברצונך להמשיך?</string>
|
||||
<string name="setup_msg">הגדרת סביבת ריצה…</string>
|
||||
<string name="authenticate">אימות</string>
|
||||
<string name="unsupport_magisk_title">גרסת Magisk אינה נתמכת</string>
|
||||
<string name="unsupport_magisk_msg">גרסה זו של מנהל Magisk אינה תומכת בגרסת Magisk הנמוכה מ-%1$s.\n\nהיישום יתנהג כאילו לא הותקן Magisk, אנא שדרג את Magisk בהקדם האפשרי.</string>
|
||||
<string name="external_rw_permission_denied">הענק הרשאת אחסון להפעלת פונקציונליות זו</string>
|
||||
<string name="add_shortcut_title">הוסף קיצור דרך למסך הבית</string>
|
||||
<string name="add_shortcut_msg">לאחר שהסתיר את Magisk Manager, השם והסמל שלו עשויים להיות קשים לזיהוי. האם אתה רוצה להוסיף קיצור דרך יפה למסך הבית?</string>
|
||||
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
|
||||
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
|
||||
</resources>
|
||||
|
@@ -1,89 +1,143 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<!--Sections-->
|
||||
<string name="modules">モジュール</string>
|
||||
<string name="superuser">スーパーユーザー</string>
|
||||
<string name="logs">ログ</string>
|
||||
<string name="settings">設定</string>
|
||||
<string name="refresh">ローカルデータの更新</string>
|
||||
<string name="install">インストール</string>
|
||||
<string name="unsupport_magisk_title">対応していない Magisk バージョン</string>
|
||||
<string name="section_home">ホーム</string>
|
||||
<string name="section_theme">テーマ</string>
|
||||
<string name="safetynet">SafetyNet</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<!--Home-->
|
||||
<string name="no_connection">インターネット接続なし</string>
|
||||
<string name="app_changelog">アプリの更新履歴</string>
|
||||
<string name="loading">読み込み中…</string>
|
||||
<string name="update">更新</string>
|
||||
<string name="not_available">なし</string>
|
||||
<string name="hide">隠す</string>
|
||||
<string name="home_package">パッケージ</string>
|
||||
<string name="home_app_title">アプリ</string>
|
||||
|
||||
<string name="home_notice_content">Magisk は必ず公式 GitHub ページからダウンロードしてください。その他の提供元では悪意あるコードを含んでいる可能性があります!</string>
|
||||
<string name="home_support_title">サポートする</string>
|
||||
<string name="home_item_source">ソース</string>
|
||||
<string name="home_support_content">Magisk はフリーでオープンソースです。少額の寄付を送ることで、あなたが Magisk を大切にしていることを示せます。</string>
|
||||
<string name="home_installed_version">インストール済</string>
|
||||
<string name="home_latest_version">最新版</string>
|
||||
<string name="invalid_update_channel">不正な更新チャンネルです</string>
|
||||
<string name="safetynet_api_error">SafetyNet API エラー</string>
|
||||
<string name="safetynet_res_invalid">応答が不正です</string>
|
||||
<string name="uninstall_magisk_title">Magisk のアンインストール</string>
|
||||
<string name="uninstall_magisk_msg">すべてのモジュールが無効化/削除されます。\nアンインストール後は root が無効化され、ストレージが暗号化されていない場合、暗号化される場合があります。</string>
|
||||
<string name="home_check_safetynet">SafetyNet のチェック</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">強制的な暗号化を維持する</string>
|
||||
<string name="keep_dm_verity">AVB 2.0/dm-verity を維持する</string>
|
||||
<string name="uninstall_magisk_title">Magisk のアンインストール</string>
|
||||
<string name="uninstall_magisk_msg">すべてのモジュールが無効化/削除されます。Root も無効化され、ストレージが暗号化されていない場合、暗号化される場合があります</string>
|
||||
<string name="update">更新</string>
|
||||
<string name="recovery_mode">リカバリーモード</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="setup_title">追加セットアップ</string>
|
||||
<string name="select_patch_file">パッチするファイルの選択</string>
|
||||
<string name="patch_file_msg">イメージファイル (*.img) または ODIN tar ファイル (*.tar) を選択してください</string>
|
||||
<string name="reboot_delay_toast">5秒後に再起動します…</string>
|
||||
<string name="flash_screen_title">インストール</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(情報がありません)</string>
|
||||
<string name="reboot_recovery">Recovery へ再起動</string>
|
||||
<string name="reboot_bootloader">Bootloader へ再起動</string>
|
||||
<string name="reboot_download">Download へ再起動</string>
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">スーパーユーザー権限の要求</string>
|
||||
<string name="touch_filtered_warning">スーパーユーザー権限の要求ダイアログが他のアプリで隠れているため、Magisk はあなたの応答を確認できません。</string>
|
||||
<string name="deny">拒否</string>
|
||||
<string name="prompt">尋ねる</string>
|
||||
<string name="grant">許可</string>
|
||||
<string name="su_warning">端末への完全なアクセスを許可します。\nもし確信が持てなければ拒否してください!</string>
|
||||
<string name="forever">今後も</string>
|
||||
<string name="once">今回のみ</string>
|
||||
<string name="tenmin">10 分</string>
|
||||
<string name="twentymin">20 分</string>
|
||||
<string name="thirtymin">30 分</string>
|
||||
<string name="sixtymin">60 分</string>
|
||||
<string name="su_allow_toast">%1$s のスーパーユーザー権限を許可しました</string>
|
||||
<string name="su_deny_toast">%1$s のスーパーユーザー権限を拒否しました</string>
|
||||
<string name="su_snack_grant">%1$s のスーパーユーザー権限を許可しました</string>
|
||||
<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_revoke_title">確認</string>
|
||||
<string name="su_revoke_msg">%1$s の権限を取り消しますか?</string>
|
||||
<string name="toast">トースト通知</string>
|
||||
<string name="none">なし</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">更新あり</string>
|
||||
<string name="home_installed_version">インストール済</string>
|
||||
<string name="sorting_order">並び順</string>
|
||||
<string name="superuser_toggle_notification">通知</string>
|
||||
<string name="superuser_toggle_revoke">取り消し</string>
|
||||
<string name="superuser_policy_none">スーパーユーザー権限の許可を求めたアプリはまだありません。</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<!--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="pid">PID: %1$d</string>
|
||||
<string name="target_uid">ターゲット UID: %1$d</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">アプリの更新履歴</string>
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">SafetyNet API エラー</string>
|
||||
<string name="safetynet_res_invalid">応答が不正です</string>
|
||||
<string name="safetynet_attest_success">成功!</string>
|
||||
<string name="safetynet_attest_failure">認証失敗!</string>
|
||||
<string name="safetynet_attest_loading">お待ちください…</string>
|
||||
<string name="safetynet_attest_restart">やり直す</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Magisk の更新</string>
|
||||
<string name="progress_channel">進捗通知</string>
|
||||
<string name="download_complete">ダウンロード完了</string>
|
||||
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
|
||||
<string name="magisk_update_title">新しい Magisk の更新が利用可能です!</string>
|
||||
<string name="manager_update_title">Magisk Manager の更新があります!</string>
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">システムアプリを表示</string>
|
||||
<string name="show_os_app">OS アプリを表示</string>
|
||||
<string name="hide_filter_hint">名前で絞り込み</string>
|
||||
<string name="hide_scroll_up">上へ</string>
|
||||
<string name="hide_filters">絞り込み</string>
|
||||
<string name="hide_search">検索</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">%1$s をインストール</string>
|
||||
<string name="repo_install_msg">%1$s をインストールしますか?</string>
|
||||
<string name="download">ダウンロード</string>
|
||||
<string name="reboot">再起動</string>
|
||||
<string name="release_notes">更新履歴</string>
|
||||
<string name="repo_cache_cleared">リポジトリのキャッシュを消去しました</string>
|
||||
<string name="manager_download_install">タップでダウンロードしてインストールします</string>
|
||||
<string name="flashing">書き込み中</string>
|
||||
<string name="hide_manager_title">Magisk Manager を隠しています…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager を隠せませんでした…</string>
|
||||
<string name="open_link_failed_toast">このリンクを開けるアプリがありません</string>
|
||||
<string name="download_zip_only">ZIP のみダウンロード</string>
|
||||
<string name="direct_install">直接インストール (推奨)</string>
|
||||
<string name="install_inactive_slot">Inactive Slot にインストール (OTA 後)</string>
|
||||
<string name="install_inactive_slot_msg">お使いのデバイスは再起動後に現在の Inactive Slot で強制的に起動されます!\nこのオプションは OTA の完了後にのみ使用してください。\n続行しますか?</string>
|
||||
<string name="complete_uninstall">完全にアンインストール</string>
|
||||
<string name="restore_img">イメージのリストア</string>
|
||||
<string name="restore_img_msg">リストア中…</string>
|
||||
<string name="restore_done">リストア完了!</string>
|
||||
<string name="restore_fail">Stock のバックアップがありません!</string>
|
||||
<string name="proprietary_title">プロプライエタリコードのダウンロード</string>
|
||||
<string name="proprietary_notice">Magisk Manager は FOSS であるため、Google のプロプライエタリな SafetyNet API コードを含んでいません。\n\nMagisk Manager が SafetyNet チェックのための拡張機能 (GoogleApiClient を含む) をダウンロードすることを許可しますか?</string>
|
||||
<string name="setup_fail">セットアップに失敗しました。</string>
|
||||
<string name="env_fix_title">追加のセットアップが必要</string>
|
||||
<string name="env_fix_msg">Magisk を正常に機能させるには、お使いのデバイスに追加のセットアップが必要です。Magisk のセットアップ用zipをダウンロードすることになりますが、今すぐ続行しますか?</string>
|
||||
<string name="setup_title">追加セットアップ</string>
|
||||
<string name="setup_msg">環境セットアップを実行中…</string>
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(情報なし)</string>
|
||||
<string name="reboot_userspace">ソフトリブート</string>
|
||||
<string name="reboot_recovery">Recovery へ再起動</string>
|
||||
<string name="reboot_bootloader">Bootloader へ再起動</string>
|
||||
<string name="reboot_download">Download へ再起動</string>
|
||||
<string name="reboot_edl">EDL へ再起動</string>
|
||||
<string name="module_version_author">%1$s 開発者:%2$s</string>
|
||||
<string name="module_section_pending">更新</string>
|
||||
<string name="module_section_pending_action">すべて更新</string>
|
||||
<string name="module_state_remove">削除</string>
|
||||
<string name="module_state_restore">復元</string>
|
||||
<string name="module_action_install_external">ストレージからインストール</string>
|
||||
<string name="update_available">更新あり</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">オンライン</string>
|
||||
<string name="sorting_order">並び順</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_download_path_title">ダウンロードの場所</string>
|
||||
<!--Settings-->
|
||||
<string name="settings_dark_mode_title">テーマモード</string>
|
||||
<string name="settings_dark_mode_message">あなたの好きなスタイルを選びましょう!</string>
|
||||
<string name="settings_dark_mode_light">常にライト</string>
|
||||
<string name="settings_dark_mode_system">システムに合わせる</string>
|
||||
<string name="settings_dark_mode_dark">常にダーク</string>
|
||||
<string name="settings_download_path_title">ダウンロードパス</string>
|
||||
<string name="settings_download_path_message">ファイルは %1$s に保存されます</string>
|
||||
<string name="settings_clear_cache_title">キャッシュを消去</string>
|
||||
<string name="settings_clear_cache_summary">オンラインリポジトリのキャッシュされた情報を消去し、アプリをオンラインで更新します</string>
|
||||
<string name="settings_hide_manager_title">Magisk Manager を隠す</string>
|
||||
<string name="settings_hide_manager_summary">Magisk Manager をランダムなパッケージ名で再パックします</string>
|
||||
<string name="settings_restore_manager_title">Magisk Manager を復元</string>
|
||||
<string name="settings_restore_manager_summary">元のパッケージで Magisk Manager を復元します</string>
|
||||
<string name="language">言語</string>
|
||||
<string name="settings_hide_app_title">Magisk アプリを隠す</string>
|
||||
<string name="settings_hide_app_summary">ランダムなパッケージ ID とカスタムアプリラベルのプロキシアプリをインストールします</string>
|
||||
<string name="settings_restore_app_title">Magisk アプリを復元する</string>
|
||||
<string name="settings_restore_app_summary">隠すのを止めて、元の APK をインストールします</string>
|
||||
<string name="language">言語 (Language)</string>
|
||||
<string name="system_default">(システム標準)</string>
|
||||
<string name="settings_check_update_title">更新をチェック</string>
|
||||
<string name="settings_check_update_summary">バックグラウンドで定期的に更新をチェックします</string>
|
||||
@@ -92,36 +146,45 @@
|
||||
<string name="settings_update_beta">ベータ版</string>
|
||||
<string name="settings_update_custom">カスタム</string>
|
||||
<string name="settings_update_custom_msg">カスタム URL を入力</string>
|
||||
<string name="settings_magiskhide_summary">さまざまな検出からMagiskを隠します</string>
|
||||
<string name="settings_magiskhide_summary">さまざまな検出から Magisk を隠します</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">広告ブロックアプリのための Systemless hosts サポートを有効化します</string>
|
||||
<string name="settings_hosts_toast">Systemless hosts モジュールを追加しました</string>
|
||||
|
||||
<string name="settings_app_name_hint">新しい名前</string>
|
||||
<string name="settings_app_name_helper">アプリはこの名前で再パッケージされます</string>
|
||||
<string name="settings_app_name_error">不正な形式</string>
|
||||
<string name="settings_su_app_adb">アプリと ADB</string>
|
||||
<string name="settings_su_app">アプリのみ</string>
|
||||
<string name="settings_su_adb">ADB のみ</string>
|
||||
<string name="settings_su_disable">無効</string>
|
||||
<string name="settings_su_request_10">10秒</string>
|
||||
<string name="settings_su_request_15">15秒</string>
|
||||
<string name="settings_su_request_20">20秒</string>
|
||||
<string name="settings_su_request_30">30秒</string>
|
||||
<string name="settings_su_request_45">45秒</string>
|
||||
<string name="settings_su_request_60">60秒</string>
|
||||
<string name="superuser_access">スーパーユーザーアクセス</string>
|
||||
<string name="settings_su_request_10">10 秒</string>
|
||||
<string name="settings_su_request_15">15 秒</string>
|
||||
<string name="settings_su_request_20">20 秒</string>
|
||||
<string name="settings_su_request_30">30 秒</string>
|
||||
<string name="settings_su_request_45">45 秒</string>
|
||||
<string name="settings_su_request_60">60 秒</string>
|
||||
<string name="superuser_access">スーパーユーザー権限</string>
|
||||
<string name="auto_response">自動応答</string>
|
||||
<string name="request_timeout">リクエストタイムアウト</string>
|
||||
<string name="request_timeout">要求のタイムアウト</string>
|
||||
<string name="superuser_notification">スーパーユーザー通知</string>
|
||||
<string name="settings_su_reauth_title">アップグレード後の再認証</string>
|
||||
<string name="settings_su_reauth_summary">アプリのアップグレード後にスーパーユーザー権限を再認証します</string>
|
||||
<string name="settings_su_tapjack_title">タップジャッキング保護を有効にする</string>
|
||||
<string name="settings_su_tapjack_summary">他のウィンドウやオーバーレイで表示されている間は、スーパーユーザー権限の要求ダイアログが入力に応答しないようにします</string>
|
||||
<string name="settings_su_biometric_title">生体認証の有効化</string>
|
||||
<string name="settings_su_biometric_summary">スーパーユーザーのリクエスト時に生体認証を使用します</string>
|
||||
<string name="settings_su_biometric_summary">スーパーユーザー権限の要求時に生体認証を使用します</string>
|
||||
<string name="no_biometric">生体認証に対応していないか、有効化されていません</string>
|
||||
<string name="settings_customization">カスタマイズ</string>
|
||||
<string name="setting_add_shortcut_summary">アプリを隠した後に見つけられなくなったときは、ここでホーム画面にショートカットを追加できます</string>
|
||||
<string name="settings_doh_title">DNS over HTTPS</string>
|
||||
<string name="settings_doh_description">一部の国での DNS ポイズニングを回避します</string>
|
||||
|
||||
<string name="multiuser_mode">マルチユーザーモード</string>
|
||||
<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="owner_manage_summary">端末の管理者のみがスーパーユーザー権限を管理し、要求を受け付けられます</string>
|
||||
<string name="user_indepenent_summary">ユーザー毎にそれぞれスーパーユーザー権限を設定できます</string>
|
||||
|
||||
<string name="mount_namespace_mode">名前空間のマウントモード</string>
|
||||
@@ -132,108 +195,44 @@
|
||||
<string name="requester_summary">root セッションはリクエスト者の名前空間を継承します</string>
|
||||
<string name="isolate_summary">root セッション毎に分離された名前空間を使用します</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">スーパーユーザーリクエスト</string>
|
||||
<string name="deny">拒否</string>
|
||||
<string name="prompt">プロンプト</string>
|
||||
<string name="grant">許可</string>
|
||||
<string name="su_warning">端末への完全なアクセスを許可します。\nもし確信が持てなければ拒否してください!</string>
|
||||
<string name="forever">今後も</string>
|
||||
<string name="once">一度だけ</string>
|
||||
<string name="tenmin">10分</string>
|
||||
<string name="twentymin">20分</string>
|
||||
<string name="thirtymin">30分</string>
|
||||
<string name="sixtymin">60分</string>
|
||||
<string name="su_allow_toast">%1$s はスーパーユーザー権限を許可されました</string>
|
||||
<string name="su_deny_toast">%1$s はスーパーユーザー権限を拒否されました</string>
|
||||
<string name="su_snack_grant">%1$s のスーパーユーザー権限が許可されました</string>
|
||||
<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_revoke_title">確認</string>
|
||||
<string name="su_revoke_msg">%1$s の権限を取り消しますか?</string>
|
||||
<string name="toast">トースト通知</string>
|
||||
<string name="none">なし</string>
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Magisk の更新</string>
|
||||
<string name="progress_channel">進捗通知</string>
|
||||
<string name="download_complete">ダウンロード完了</string>
|
||||
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
|
||||
<string name="magisk_update_title">Magisk の更新があります!</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">ターゲット UID: %1$d</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">システムアプリを表示</string>
|
||||
<string name="authenticate">認証</string>
|
||||
<string name="failure">失敗</string>
|
||||
<string name="done">完了!</string>
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">はい</string>
|
||||
<string name="no">いいえ</string>
|
||||
<string name="reboot_edl">EDL へ再起動</string>
|
||||
<string name="settings_app_name_hint">新しい名前</string>
|
||||
<string name="settings_app_name_helper">アプリはこの名前で再パッケージされます</string>
|
||||
<string name="settings_app_name_error">不正なフォーマット</string>
|
||||
<string name="no_biometric">サポートされていないデバイスまたは生体認証が有効化されていません</string>
|
||||
<string name="hide">隠す</string>
|
||||
<string name="status">状態</string>
|
||||
<string name="home_package">パッケージ</string>
|
||||
<string name="home_latest_version">最新版</string>
|
||||
<string name="home_support_title">支援する</string>
|
||||
<string name="home_support_content">Magisk はフリーでオープンソースです。少額の寄付を送ることで、あなたが Magisk を大切にしていることを示すことができます。</string>
|
||||
<string name="settings_customization">カスタマイズ</string>
|
||||
<string name="section_theme">テーマ</string>
|
||||
<string name="settings_dark_mode_light">常にライト</string>
|
||||
<string name="settings_dark_mode_system">システムに従う</string>
|
||||
<string name="settings_dark_mode_dark">常にダーク</string>
|
||||
<string name="settings_dark_mode_title">テーマモード</string>
|
||||
<string name="section_home">ホーム</string>
|
||||
<string name="no_connection">接続がありません</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="safetynet">SafetyNet</string>
|
||||
<string name="loading">読み込み中…</string>
|
||||
<string name="install_options_title">オプション</string>
|
||||
<string name="install_method_title">メソッド</string>
|
||||
<string name="install_next">次</string>
|
||||
<string name="install_start">Let\'s go</string>
|
||||
<string name="safetynet_attest_loading">しばらくお待ちください…</string>
|
||||
<string name="safetynet_attest_restart">やり直す</string>
|
||||
<string name="home_status_stub">スタブ</string>
|
||||
<string name="recovery_mode">リカバリーモード</string>
|
||||
<string name="home_notice_content">必ずオープンソースの Magisk Manager を使用していることを確認してください。ソース不明の Manager は悪意のある動作を行う可能性があります。</string>
|
||||
<string name="hide_scroll_up">上へ</string>
|
||||
<string name="hide_filters">フィルタ</string>
|
||||
<string name="hide_search">検索</string>
|
||||
<string name="hide_filter_hint">名前でフィルタ</string>
|
||||
<string name="safetynet_attest_success">成功!</string>
|
||||
<string name="safetynet_attest_failure">認証失敗!</string>
|
||||
<string name="module_version_author">%1$s %2$s による</string>
|
||||
<string name="module_state_remove">削除</string>
|
||||
<string name="module_section_pending_action">全て更新</string>
|
||||
<string name="module_section_pending">更新</string>
|
||||
<string name="module_action_install_external">ストレージからインストール</string>
|
||||
<string name="module_state_restore">復元</string>
|
||||
<string name="log_data_magisk_none">奇妙なことに、Magisk のログは空です。</string>
|
||||
<string name="log_data_none">ログがないので、もっとスーパーユーザを使用するアプリを使ってみてください。</string>
|
||||
<string name="superuser_policy_none">スーパーユーザーの許可を求めるアプリはまだありません。</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="refresh">ローカルデータの更新</string>
|
||||
<string name="home_item_source">ソース</string>
|
||||
<string name="select_patch_file">パッチするファイルの選択</string>
|
||||
<string name="patch_file_msg">イメージファイル (*.img) または ODIN tar ファイル (*.tar) を選択してください</string>
|
||||
<string name="superuser_toggle_notification">通知</string>
|
||||
<string name="flash_screen_title">インストレーション</string>
|
||||
<string name="reboot_delay_toast">5秒で再起動します…</string>
|
||||
<string name="superuser_toggle_revoke">取り消し</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="settings_dark_mode_message">自分のスタイルに合ったモードを選択!</string>
|
||||
<string name="external_rw_permission_denied">この機能を有効にするためにストレージの許可を付与</string>
|
||||
<string name="download_open_parent">"親フォルダに表示 "</string>
|
||||
<string name="download_open_self">ファイルを表示</string>
|
||||
<string name="unsupport_magisk_msg">このバージョンの Magisk Manager は、%1$s 以下の Magisk バージョンには対応していません。 アプリは Magisk がインストールされていないかのように動作しますので、できるだけ早く Magisk をアップグレードしてください。</string>
|
||||
<string name="home_check_safetynet">SafetyNet のチェック</string>
|
||||
<string name="home_status_normal">ノーマル</string>
|
||||
<string name="module_section_online">オンライン</string>
|
||||
<string name="setting_add_shortcut_summary">アプリを隠した後に名前やアイコンが分かりづらい場合ホーム画面にショートカットを追加する</string>
|
||||
<string name="repo_install_title">%1$s をインストール</string>
|
||||
<string name="repo_install_msg">%1$s をインストールしますか?</string>
|
||||
<string name="download">ダウンロード</string>
|
||||
<string name="reboot">再起動</string>
|
||||
<string name="release_notes">更新履歴</string>
|
||||
<string name="repo_cache_cleared">リポジトリのキャッシュを消去しました</string>
|
||||
<string name="flashing">書き込み中…</string>
|
||||
<string name="done">完了!</string>
|
||||
<string name="failure">失敗!</string>
|
||||
<string name="hide_app_title">Magisk アプリを隠しています…</string>
|
||||
<string name="open_link_failed_toast">このリンクを開けるアプリがありません</string>
|
||||
<string name="complete_uninstall">完全にアンインストール</string>
|
||||
<string name="restore_img">イメージのリストア</string>
|
||||
<string name="restore_img_msg">リストア中…</string>
|
||||
<string name="restore_done">リストア完了!</string>
|
||||
<string name="restore_fail">Stock のバックアップがありません!</string>
|
||||
<string name="proprietary_title">プロプライエタリコードのダウンロード</string>
|
||||
<string name="proprietary_notice">Magisk は FOSSであり、Google のプロプライエタリな SafetyNet API のコードは含まれていません。\n\nSafetyNet チェック用の拡張機能をダウンロードしますか?</string>
|
||||
<string name="setup_fail">セットアップに失敗しました</string>
|
||||
<string name="env_fix_title">追加のセットアップが必要です</string>
|
||||
<string name="env_fix_msg">Magisk を正常に動作させるために追加のセットアップが必要です。今すぐ再起動しますか?</string>
|
||||
<string name="setup_msg">追加セットアップを実行中…</string>
|
||||
<string name="authenticate">認証</string>
|
||||
<string name="unsupport_magisk_title">対応していない Magisk バージョンです</string>
|
||||
<string name="unsupport_magisk_msg">このバージョンのアプリではバージョン %1$s 以下の Magisk に対応していません。\n\nアプリで Magisk を使えないため、すぐに Magisk を更新してください</string>
|
||||
<string name="external_rw_permission_denied">この機能を有効にするにはストレージ権限を許可してください</string>
|
||||
<string name="add_shortcut_title">ホーム画面にショートカットを追加</string>
|
||||
<string name="add_shortcut_msg">Magisk Manager を隠した後、名前やアイコンは分かりづらくなります。ホーム画面にショートカットを追加しますか?</string>
|
||||
<string name="add_shortcut_msg">アプリを隠すと、アプリ名やアイコンが判別しにくいことがあります。分かりやすいようホーム画面にショートカットを追加しますか?</string>
|
||||
<string name="app_not_found">このアクションを扱えるアプリがありません</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,25 +14,23 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">კავშირი არ არის</string>
|
||||
<string name="app_changelog">ცვლილებები</string>
|
||||
<string name="manager">მენეჯერი</string>
|
||||
<string name="loading">იტვირთება…</string>
|
||||
<string name="update">განახლება</string>
|
||||
<string name="not_available">ხელმიუწვდომელია</string>
|
||||
<string name="hide">დამალვა</string>
|
||||
<string name="status">სტატუსი</string>
|
||||
<string name="home_package">პაკეტი</string>
|
||||
<string name="home_app_title">აპი</string>
|
||||
|
||||
<string name="home_notice_content">დარწმუნებული იყავით რომ Magisk მენეჯერის წყარო-გახსნილ ვერსიას ხმარობთ. დახურული წყაროს მქონე მენეჯემა შეიძლება მოწყობილობა დააზიანოს.</string>
|
||||
<string name="home_notice_content">გადმოიწერეთ Magisk მხოლოდ ოფიციალური GitHub-ის გვერდიდან. სხვა წყაროებიდან გადმოწერილი ფაილები შესაძლოა სახიფათო იყოს!</string>
|
||||
<string name="home_support_title">მხარდაჭერა</string>
|
||||
<string name="home_item_source">წყარო</string>
|
||||
<string name="home_support_content">Magisk-ი არის და ყოველთვის იქნება უფასო და წყარო-გახსნილი. მაგრამ თქვენ შეგიძლიათ დახმარება გაგვიწიოთ პატარა დონაციით.</string>
|
||||
<string name="home_status_normal">ნორმალური</string>
|
||||
<string name="home_status_stub">დინამიური</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">ყველა მოდული იქნება წაშლილი/გამორთული!\nRoot-ი წაიშლება!\nთქვენი მონაცემები დაიშიფრება!</string>
|
||||
<string name="home_check_safetynet">SafetyNet-ის შემოწმება</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">შიფრირება ყოველთვის იყოს ჩართული</string>
|
||||
@@ -43,7 +41,6 @@
|
||||
<string name="install_next">შემდეგი</string>
|
||||
<string name="install_start">დაწყება</string>
|
||||
<string name="manager_download_install">დააჭირეთ გადმოსაწერად და შემდგომ დასაყენებლად</string>
|
||||
<string name="download_zip_only">მხოლოდ Zip-ის გადმოწერა</string>
|
||||
<string name="direct_install">აქვე დაინსტალირება (რეკომენდირებულია)</string>
|
||||
<string name="install_inactive_slot">არააქტიურ სლოტში დაყენება (სისტემის განახლების შემდეგ)</string>
|
||||
<string name="install_inactive_slot_msg">თქვენი მოწყობილობა გადაიტვირთება არააქატიურ სლოტში!\nგამოიყენეთ ეს ოფცია მხოლოდ სისტემის განახლების დროს.\nგავაგრძელოთ?</string>
|
||||
@@ -55,6 +52,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">სუპერმომხმარებლის ნებართვის მოთხოვნა</string>
|
||||
<string name="touch_filtered_warning">სხვა აპი ხელს უშლის Magisk-ს თქვენი პასუხის დადასტურებაში</string>
|
||||
<string name="deny">აკრძალვა</string>
|
||||
<string name="prompt">კითხვა</string>
|
||||
<string name="grant">დართვა</string>
|
||||
@@ -101,6 +99,7 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">სისტემის პროგრამების ჩვენება</string>
|
||||
<string name="show_os_app">ოპერაციული სისტემის აპების ჩვენება</string>
|
||||
<string name="hide_filter_hint">ფილტრაცია სახელის მიხედვით</string>
|
||||
<string name="hide_scroll_up">მაღლა ასქროლვა</string>
|
||||
<string name="hide_filters">ფილტრები</string>
|
||||
@@ -108,6 +107,7 @@
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(ინფორმაცია არ არის მითითებული)</string>
|
||||
<string name="reboot_userspace">სისტემის გადატვირთვა</string>
|
||||
<string name="reboot_recovery">Recovery-ში გადატვირთვა</string>
|
||||
<string name="reboot_bootloader">Bootloader-ში გადატვირთვა</string>
|
||||
<string name="reboot_download">Download-ში გადატვირთვა</string>
|
||||
@@ -120,8 +120,8 @@
|
||||
<string name="module_action_install_external">მახსოვრობიდან დაინსტალირება</string>
|
||||
<string name="update_available">ხელმისაწვდომია განახლება</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">ონლაინი</string>
|
||||
<string name="sorting_order">სორტირება</string>
|
||||
<string name="external_rw_permission_denied">დართეთ მეხსიერებასთან წვდომის ნებართვა ამ ფუნქციის გამოსაყნებლად</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">თემების ჩამონათვალი</string>
|
||||
@@ -133,10 +133,10 @@
|
||||
<string name="settings_download_path_message">ფაილები შეინახება %1$s-ში</string>
|
||||
<string name="settings_clear_cache_title">რეპოზიტორიების ქეშის წაშლა</string>
|
||||
<string name="settings_clear_cache_summary">რეპოზიტორიებისთვის ქეშის წაშლა. ეს დაარეფრეშებს პროგრამას</string>
|
||||
<string name="settings_hide_manager_title">Magisk მენეჯერის დამალვა</string>
|
||||
<string name="settings_hide_manager_summary">Magisk მენეჯერის რეპაკეტირება რანდომ პაკეტის სახელებით</string>
|
||||
<string name="settings_restore_manager_title">Magisk მენეჯერის პაკეტის სახელის აღდგენა</string>
|
||||
<string name="settings_restore_manager_summary">Magisk მენეჯერის აღდგენა ორიგინალი პაკეტის სახელით</string>
|
||||
<string name="settings_hide_app_title">Magisk-ის აპის დამალვა</string>
|
||||
<string name="settings_hide_app_summary">დაყენდეს ამოუცნობელი აპი შემთხვევითი პაკეტის ID-ით და განსხვავებული სახელით</string>
|
||||
<string name="settings_restore_app_title">Magisk-ის აპის დაბრუნება</string>
|
||||
<string name="settings_restore_app_summary">აპის თავდაპირველ მდგომარეობაზე დაბრუნება</string>
|
||||
<string name="language">ენა</string>
|
||||
<string name="system_default">(სისტემის რჩეული)</string>
|
||||
<string name="settings_check_update_title">განახლებების შემოწმება</string>
|
||||
@@ -169,10 +169,15 @@
|
||||
<string name="superuser_notification">სუპერმომხმარებლის შეტყობინება</string>
|
||||
<string name="settings_su_reauth_title">რეაუტენთიფიკაცია განახლების შემდეგ</string>
|
||||
<string name="settings_su_reauth_summary">სუპერმომხმარებლის ნებართვის რეაუტენთიფიკაცია აპის განახლების შემდეგ</string>
|
||||
<string name="settings_su_tapjack_title">Tapjacking-სგან თავის დაცვა</string> <!-- TODO: tapjacking has no direct translation; must make something up later -->
|
||||
<string name="settings_su_tapjack_summary">superuser-ის დიალოგის ღილაკებზე დაჭერა არ იქნება შესაძლებელი თუ სხვა აპი არის მასზე გადახურული</string>
|
||||
<string name="settings_su_biometric_title">ბიომეტრიკული აუტენთიფიკაციის ჩართვა</string>
|
||||
<string name="settings_su_biometric_summary">ბიომეტრიკული აუტენთიფიკაციის გამოყენება სუპერმომხმარებლის ნებართვის გასაცემად</string>
|
||||
<string name="no_biometric">შეუთავსებელი მოწყობილობა ან არასწორად დაყენებული ბიომეტრიკული პარამეტრები</string>
|
||||
<string name="settings_customization">პერსონალიზაცია</string>
|
||||
<string name="setting_add_shortcut_summary">ლამაზი ხატულის დამატება საწყისს ეკრანზე, იმ შემთხვევაში თუ აპის ამოცნობა არის რთული დამალვის შემდეგ</string>
|
||||
<string name="settings_doh_title">DNS HTTPS-ზე</string>
|
||||
<string name="settings_doh_description">DNS-ის ლიმიტების მოხსნა კონკრეტულ სახელმწიფოებში</string>
|
||||
|
||||
<string name="multiuser_mode">მრავალმომხმარებლიანი რეჟიმი</string>
|
||||
<string name="settings_owner_only">მხოლოდ მოწყობილობის მფლობელი</string>
|
||||
@@ -195,10 +200,7 @@
|
||||
<string name="progress_channel">პროგრესის შეტყობინებები</string>
|
||||
<string name="download_complete">გადმოწერა დასრულებულია</string>
|
||||
<string name="download_file_error">შეცდომა გადმოწერის დროს</string>
|
||||
<string name="download_open_parent">მშობელ საქაღდეში ნახვა</string>
|
||||
<string name="download_open_self">ფაილის ჩვენება</string>
|
||||
<string name="magisk_update_title">ხელმისაწვდომია Magisk-ის განახლება!</string>
|
||||
<string name="manager_update_title">ხელმისაწვდომია Magisk მენეჯერის განახლება!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">დიახ</string>
|
||||
@@ -212,8 +214,7 @@
|
||||
<string name="flashing">მიმდინარეობს ჩაშენება…</string>
|
||||
<string name="done">დასრულდა!</string>
|
||||
<string name="failure">ჩაიშალა</string>
|
||||
<string name="hide_manager_title">ვმალავთ Magisk მენეჯერს…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk მენეჯრის დამალვა ჩაიშალა.</string>
|
||||
<string name="hide_app_title">ვმალავთ Magisk-ის აპს…</string>
|
||||
<string name="open_link_failed_toast">ლინკის გამხსნელი აპლიკაცია ვერ მოიძებნა</string>
|
||||
<string name="complete_uninstall">დეინსტალაციის დასრულება</string>
|
||||
<string name="restore_img">სურათის აღდგენა</string>
|
||||
@@ -221,13 +222,17 @@
|
||||
<string name="restore_done">აღდგენა დასრულდა!</string>
|
||||
<string name="restore_fail">საწყისი რეზერვი არ არსებობს!</string>
|
||||
<string name="proprietary_title">კუთვნილი კოდის გადმოწერა</string>
|
||||
<string name="proprietary_notice">Magisk მენეჯერი არის უფასო და კოდ-გახსნილი, იგი არ შეიცავს Google-ის კუთვნილ SafetyNet API-ს კოდს.\n\nდართავთ Magisk მენეჯერს ამ გაფართოების გადმოწერას (ასევე შეიცავს GoogleApiClient-ს) SafetyNet-ის შესამოწმებლად?</string>
|
||||
<string name="proprietary_notice">Magisk-ი არის უფასო და გახსნილი წყაროს მქონე პროგრამა, იგი არ შეიცავს Google-ის კუთვნილ SafetyNet API-ს კოდს.\n\nგსურთ კუთვნილი დამატების გადმოწერა SafetyNet-ის შესამოწმებლად?</string>
|
||||
<string name="setup_fail">ინსტალაცია ჩაიშალა</string>
|
||||
<string name="env_fix_title">სჭირდება დამატებითი გამართვა</string>
|
||||
<string name="env_fix_msg">თქვენს მოწყობილობას სჭრიდება დამატებითი გამართვა იმისთვის რომ Magisk-მა იმუშავოს. გადმოწერილი იქნება "Magisk setup.zip" ფაილი, გსურთ გაგრძელება?</string>
|
||||
<string name="env_fix_msg">თქვენს მოწყობილობას სჭრიდება დამატებითი გამართვა იმისთვის რომ Magisk-მა იმუშავოს. გადმოიწერება "Magisk setup.zip" ფაილი, გსურთ გაგრძელება?</string>
|
||||
<string name="setup_msg">მიმდინარეობს ინტერფეისის ინსტალაცია…</string>
|
||||
<string name="authenticate">აუტენთიფიკაცია</string>
|
||||
<string name="unsupport_magisk_title">შეუთავსებელი Magisk-ის ვერსია</string>
|
||||
<string name="unsupport_magisk_msg">ამ ვერსიის Magisk მენეჯერთან არ არის მხარდაჭერილი %1$s-ზე დაბალი Magisk-ის ვერსია.\n\nპროგრამა ისე ირეაგირებს, თითქოს Magisk-ი არ არის დაყენებული, გთხოვთ განაახლოთ Magisk-ი რაც შეიძლება მალე.</string>
|
||||
<string name="unsupport_magisk_msg">ეს აპის ვერსია შეუთავსებსლია Magisk-ის %1$s-ზე ნაკლებ ვერსიებთან.\n\nაპს ეგონება, რომ Magisk-ი არაა დაყენებული, გთხოვთ გაანხალოთ Magisk-ი დროულად.</string>
|
||||
<string name="external_rw_permission_denied">დართეთ მეხსიერებასთან წვდომის ნებართვა ამ ფუნქციის გამოსაყნებლად</string>
|
||||
<string name="add_shortcut_title">ხატულის დამატება საწყისს ეკრანზე</string>
|
||||
<string name="add_shortcut_msg">აპის დამალვის შემდეგ, მისი ნახატი და სახელი შეიძლება ამოუცნობი გახდეს. გნებავთ ხატულის დამატება ასწყისს ეკრანზე?</string>
|
||||
<string name="app_not_found">ამ ფუნქციის შესასრულებლად აპი ვერ მოიძებნა</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -14,20 +14,15 @@
|
||||
<!--Home-->
|
||||
<string name="no_connection">사용 가능한 연결 없음</string>
|
||||
<string name="app_changelog">앱 변경 사항</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">로딩중…</string>
|
||||
<string name="update">업데이트</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">숨기기</string>
|
||||
<string name="status">상태</string>
|
||||
<string name="home_package">패키지</string>
|
||||
|
||||
<string name="home_notice_content">항상 오픈 소스 Magisk Manager를 사용하고 있는지 확인하십시오. 출처를 알 수 없는 Manager는 악의적인 작업을 수행 할 수 있습니다.</string>
|
||||
<string name="home_support_title">후원하기</string>
|
||||
<string name="home_item_source">소스</string>
|
||||
<string name="home_support_content">Magisk는 항상 무료일 것이며, 오픈소스일 것입니다. 그러나 소액의 후원을 통해 관심을 표할 수 있습니다.</string>
|
||||
<string name="home_status_normal">정상</string>
|
||||
<string name="home_status_stub">스텁</string>
|
||||
<string name="home_installed_version">설치됨</string>
|
||||
<string name="home_latest_version">최신</string>
|
||||
<string name="invalid_update_channel">올바르지 않은 업데이트 채널</string>
|
||||
@@ -44,7 +39,6 @@
|
||||
<string name="install_next">다음</string>
|
||||
<string name="install_start">설치</string>
|
||||
<string name="manager_download_install">눌러서 다운로드하고 설치</string>
|
||||
<string name="download_zip_only">Zip만 다운로드</string>
|
||||
<string name="direct_install">바로 설치 (권장됨)</string>
|
||||
<string name="install_inactive_slot">비활성 슬롯에 설치 (OTA 이후)</string>
|
||||
<string name="install_inactive_slot_msg">기기를 다시 시작한 후에는 현재 비활성 상태인 슬롯으로 강제로 부팅됩니다!\nOTA 업데이트 후에만 이 옵션을 사용하십시오.\n계속하시겠습니까?</string>
|
||||
@@ -134,10 +128,6 @@
|
||||
<string name="settings_download_path_message">파일이 %1$s에 저장됩니다</string>
|
||||
<string name="settings_clear_cache_title">저장소 캐시 비우기</string>
|
||||
<string name="settings_clear_cache_summary">온라인 저장소에 대해 캐시된 정보를 지우고, 온라인에서 정보를 강제로 새로 고칩니다.</string>
|
||||
<string name="settings_hide_manager_title">Magisk Manager 숨기기</string>
|
||||
<string name="settings_hide_manager_summary">무작위 패키지 이름으로 Magisk Manager를 다시 패키징합니다.</string>
|
||||
<string name="settings_restore_manager_title">Magisk Manager 복구</string>
|
||||
<string name="settings_restore_manager_summary">기존 패키지 이름으로 Magisk Manager를 복원합니다.</string>
|
||||
<string name="language">언어</string>
|
||||
<string name="system_default">(시스템 기본값)</string>
|
||||
<string name="settings_check_update_title">업데이트 확인</string>
|
||||
@@ -200,10 +190,7 @@
|
||||
<string name="progress_channel">진행 상황</string>
|
||||
<string name="download_complete">다운로드 완료</string>
|
||||
<string name="download_file_error">파일 다운로드 오류</string>
|
||||
<string name="download_open_parent">상위 폴더에서 보기</string>
|
||||
<string name="download_open_self">파일 보기</string>
|
||||
<string name="magisk_update_title">새 버전의 Magisk를 사용할 수 있습니다!</string>
|
||||
<string name="manager_update_title">새 버전의 Magisk Manager를 사용할 수 있습니다!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">예</string>
|
||||
@@ -217,8 +204,6 @@
|
||||
<string name="flashing">플래싱 중…</string>
|
||||
<string name="done">완료!</string>
|
||||
<string name="failure">실패</string>
|
||||
<string name="hide_manager_title">Magisk Manager를 숨기는 중…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager를 숨기는 데 실패하였습니다.</string>
|
||||
<string name="open_link_failed_toast">링크를 열 수 있는 앱이 없습니다.</string>
|
||||
<string name="complete_uninstall">완전히 제거</string>
|
||||
<string name="restore_img">이미지 복구</string>
|
||||
@@ -226,17 +211,13 @@
|
||||
<string name="restore_done">복구 완료!</string>
|
||||
<string name="restore_fail">순정 백업이 존재하지 않습니다!</string>
|
||||
<string name="proprietary_title">사유 코드 다운로드</string>
|
||||
<string name="proprietary_notice">Magisk Manager는 자유 오픈 소스 소프트웨어이며, 구글의 사유 SafetyNet API 코드를 포함하지 않습니다.\n\nMagisk Manager가 SafetyNet 상태 확인을 위해 (GoogleApiClient를 포함하는) 확장 기능을 다운로드하도록 허가하시겠습니까?</string>
|
||||
<string name="setup_fail">설치 실패</string>
|
||||
<string name="env_fix_title">추가 설정 필요</string>
|
||||
<string name="env_fix_msg">이 기기에서 Magisk가 제대로 작동하기 위해선 추가 설정이 필요합니다. Magisk 설치 zip이 다운로드 될 것인데, 계속 진행하시겠습니까?</string>
|
||||
<string name="setup_msg">환경 설정 진행 중…</string>
|
||||
<string name="authenticate">인증</string>
|
||||
<string name="unsupport_magisk_title">지원되지 않는 Magisk 버전</string>
|
||||
<string name="unsupport_magisk_msg">이 버전의 Magisk Manager는 %1$s 미만 버전의 Magisk를 지원하지 않습니다.\n\n이 앱은 Magisk가 설치되지 않은 것처럼 동작하게 되니, Magisk를 가능한 빨리 업데이트하십시오.</string>
|
||||
<string name="external_rw_permission_denied">해당 기능을 사용하려면 저장소 권한을 허용해 주십시오.</string>
|
||||
<string name="add_shortcut_title">홈 화면에 바로가기 추가</string>
|
||||
<string name="add_shortcut_msg">Magisk Manager를 숨긴 후, 아이콘과 이름을 알아보기 힘들 수도 있습니다. 홈 화면에 알아보기 쉬운 바로가기를 추가하시겠습니까?</string>
|
||||
<string name="app_not_found">해당 작업을 처리할 어플리케이션이 없습니다.</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -46,13 +46,9 @@
|
||||
<string name="magisk_update_title">Atsirado nauja Magisk versija!</string>
|
||||
<string name="release_notes">Pakeitimai</string>
|
||||
<string name="repo_cache_cleared">Repo failai išvalyti</string>
|
||||
<string name="manager_update_title">Atsirado naujas Magisk Manager atnaujinimas!</string>
|
||||
<string name="manager_download_install">Paspauskite, kad atsisiųstumėte ir instaliuotumėte</string>
|
||||
<string name="update_channel">Magisk Atnaujinimai</string>
|
||||
<string name="flashing">Instaliuojama</string>
|
||||
<string name="hide_manager_title">Magisk Manager paslėpiamas…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager paslėpimas žlugo…</string>
|
||||
<string name="download_zip_only">Atsisiųsti zip failą</string>
|
||||
<string name="direct_install">Tiesioginis instaliavimas (Rekomenduojamas)</string>
|
||||
<string name="complete_uninstall">Pilnas pašalinimas</string>
|
||||
<string name="restore_img">Atstatyti boot failą</string>
|
||||
@@ -60,10 +56,8 @@
|
||||
<string name="restore_done">Atstatymas įvykdytas!</string>
|
||||
<string name="restore_fail">Gamyklinis atstatymo failas neegzistuoja!</string>
|
||||
<string name="proprietary_title">Atsisiųsti patentuotą kodą</string>
|
||||
<string name="proprietary_notice">Magisk Manager yra FOSS todėl neturi Google patentuoto SafetyNet API kodo.\n\nAr jūs leidžiate Magisk Manager atsisiųsti papildinį (turintį GoogleApiClient) SafetyNet paieškai?</string>
|
||||
<string name="setup_fail">Pasiruošimas nesėkmingas</string>
|
||||
<string name="env_fix_title">Reikalingas papildomas pasiruošimas</string>
|
||||
<string name="env_fix_msg">Kad Magisk veiktų tinkamai, jūsų įrenginiui reikia papildomo paruošimo. Tai atsisiųs papildomą Magisk zip failą, ar norite tęsti?</string>
|
||||
<string name="setup_title">Papildomas pasiruošimas</string>
|
||||
<string name="setup_msg">Paruošiama aplinka…</string>
|
||||
<string name="download_file_error">Atsisiunčiant failą įvyko klaida</string>
|
||||
@@ -71,10 +65,6 @@
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Išvalyti nereikalingus saugyklos failus</string>
|
||||
<string name="settings_clear_cache_summary">Išvalyti patalpintą informaciją talpykloms internete, priverčia perkrauti interneto jungtį</string>
|
||||
<string name="settings_hide_manager_title">Paslėpti Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Perpakuoti Magisk Manager su atsitiktiniu pakuotės pavadinimu</string>
|
||||
<string name="settings_restore_manager_title">Grąžinti Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Grąžinti Magisk Manager su orginalia pakuote</string>
|
||||
<string name="language">Kalba</string>
|
||||
<string name="system_default">(Sistemos)</string>
|
||||
<string name="settings_check_update_title">Automatiškas atnaujinimų ieškojimas</string>
|
||||
|
@@ -43,11 +43,9 @@
|
||||
<string name="download_complete">Преземањето е завршено</string>
|
||||
<string name="download_file_error">Грешка при преземање на фајлот</string>
|
||||
<string name="magisk_update_title">Достапно е ажурирање на Magisk!</string>
|
||||
<string name="manager_update_title">Достапно е ажурирање на Magisk Manager!</string>
|
||||
|
||||
<!-- Installation -->
|
||||
<string name="manager_download_install">Притисни за преземање и инсталирање.</string>
|
||||
<string name="download_zip_only">Преземи само Zip датотека</string>
|
||||
<string name="direct_install">Директна инсталација (Препорачано)</string>
|
||||
<string name="install_inactive_slot">Инсталирај во неактивен слот (по ОТА)</string>
|
||||
<string name="install_inactive_slot_msg">Вашиот уред ќе биде ПРИНУДЕН да се подигне на тековниот неактивен слот по рестартирањето!\nОваа опција користете ја само откако OTA ажурирање е направено.\nПродолжи?</string>
|
||||
@@ -65,8 +63,6 @@
|
||||
<string name="repo_cache_cleared">Кешот од репозиториумот е исчистен</string>
|
||||
|
||||
<string name="flashing">Применувам</string>
|
||||
<string name="hide_manager_title">Сокриј го Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Сокривањето на Magisk Manager е неуспешно.</string>
|
||||
<string name="open_link_failed_toast">Не е пронајдена апликација за отворање на врската.</string>
|
||||
<string name="complete_uninstall">Целосно деинсталирање</string>
|
||||
<string name="restore_img">Врати image датотеки</string>
|
||||
@@ -74,19 +70,13 @@
|
||||
<string name="restore_done">Враќањето заврши!</string>
|
||||
<string name="restore_fail">Не постои оригинална резервна копија!</string>
|
||||
<string name="proprietary_title">Превземи патентиран код</string>
|
||||
<string name="proprietary_notice">Magisk Manager е FOSS апликација и затоа не содржи код од SafetyNet API кој е во сопственост на Google.\n\nДали ќе дозволите Magisk Manager да преземе проширување (содржи GoogleApiClient) за SafetyNet проверка?</string>
|
||||
<string name="setup_fail">Поставувањето е неуспешно.</string>
|
||||
<string name="env_fix_title">Потребни е дополнително поставување</string>
|
||||
<string name="env_fix_msg">На Вашиот уред му е потребно дополнително поставување за Magisk да работи нормално. Ќе се преземе ZIP фајлот за поставување на Magisk, дали сакате да продолжите?</string>
|
||||
<string name="setup_msg">Надградба на работната околина…</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Исчисти го кешот од репозиториумот</string>
|
||||
<string name="settings_clear_cache_summary">Исчисти ги кешираните информации за онлајн репозиториумот. Ова ја принудува апликацијата да се освежи онлајн.</string>
|
||||
<string name="settings_hide_manager_title">Сокриј го Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Препакувај го Magisk Manager со случајно име на пакет.</string>
|
||||
<string name="settings_restore_manager_title">Врати го Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Врати го Magisk Manager со оригиналното име на пакет</string>
|
||||
<string name="language">Јазик</string>
|
||||
<string name="system_default">(Стандарден системски)</string>
|
||||
<string name="settings_check_update_title">Провери за ажурирања</string>
|
||||
|
@@ -44,7 +44,6 @@
|
||||
<string name="download_complete">Nedlastingen er fullført</string>
|
||||
<string name="download_file_error">Feil under nedlasting av fil</string>
|
||||
<string name="magisk_update_title">En Magisk-oppdatering er tilgjengelig!</string>
|
||||
<string name="manager_update_title">En Magisk Manager-oppdatering er tilgjengelig!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">Installer %1$s</string>
|
||||
@@ -55,10 +54,7 @@
|
||||
<string name="repo_cache_cleared">Repomellomlageret ble tømt</string>
|
||||
<string name="manager_download_install">Trykk for å laste ned og installere.</string>
|
||||
<string name="flashing">Flashing</string>
|
||||
<string name="hide_manager_title">Skjuler Magisk Manager …</string>
|
||||
<string name="hide_manager_fail_toast">Skjulingen av Magisk Manager mislyktes.</string>
|
||||
<string name="open_link_failed_toast">Ingen apper som kunne åpne denne lenken ble funnet.</string>
|
||||
<string name="download_zip_only">Bare last ned ZIPen</string>
|
||||
<string name="direct_install">Direkteinstallasjon (Anbefalt)</string>
|
||||
<string name="install_inactive_slot">Installer til et inaktivt felt (Etter OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Enheten din vil bli TVUNGET til å starte opp på det som for øyeblikket er et inaktivt felt, etter en omstart!\nBare bruk dette alternativet etter at OTA-oppdateringen er ferdig.\nVil du fortsette?</string>
|
||||
@@ -68,20 +64,14 @@
|
||||
<string name="restore_done">Gjenopprettingen er fullført!</string>
|
||||
<string name="restore_fail">Sikkerhetskopien av mobilens eget oppstartsbilde!</string>
|
||||
<string name="proprietary_title">Last ned proprietær kode</string>
|
||||
<string name="proprietary_notice">Magisk Manager bruker FOSSS, og kommer ikke med Googles proprietære SafetyNet-API-kode.\n\nVil du tillate Magisk Manager å laste ned utvidelse (som inneholder GoogleApiClient) for å kjøre SafetyNet-sjekker?</string>
|
||||
<string name="setup_fail">Oppsettet mislyktes.</string>
|
||||
<string name="env_fix_title">Krever ekstra oppsett</string>
|
||||
<string name="env_fix_msg">Enheten din krever ekstra oppsett for at Magisk skal kunne fungere ordentlig. Den vil laste ned Magisk-oppsetts-ZIP-filen, vil du fortsette med det nå?</string>
|
||||
<string name="setup_title">Ekstra oppsett</string>
|
||||
<string name="setup_msg">Kjører appmiljøoppsettet …</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Tøm repomellomlageret</string>
|
||||
<string name="settings_clear_cache_summary">Tøm den mellomlagrede informasjonen til nettrepoer. Dette tvinger appen til å oppfriskes på nett.</string>
|
||||
<string name="settings_hide_manager_title">Skjul Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Pakk inn Magisk Manager på nytt med et tilfeldig pakkenavn.</string>
|
||||
<string name="settings_restore_manager_title">Gjenopprett Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Gjenopprett Magisk Manager med den opprinnelige pakken</string>
|
||||
<string name="language">Språk</string>
|
||||
<string name="system_default">(Systemets standard)</string>
|
||||
<string name="settings_check_update_title">Let etter oppdateringer</string>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user