mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 15:27:25 +00:00
Compare commits
91 Commits
manager-v7
...
v20.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7da97489cc | ||
![]() |
a9f11b28c8 | ||
![]() |
b31d986c8d | ||
![]() |
2dad751889 | ||
![]() |
c85b1c56af | ||
![]() |
6dd34aec47 | ||
![]() |
4cd154675f | ||
![]() |
d8d72f92b3 | ||
![]() |
a30f5b175f | ||
![]() |
8277896ca1 | ||
![]() |
493068c073 | ||
![]() |
f4299fbea8 | ||
![]() |
10ce11d671 | ||
![]() |
0f34457a10 | ||
![]() |
34c65e13bc | ||
![]() |
17a77e2577 | ||
![]() |
0f219e5ae6 | ||
![]() |
353c3c7d81 | ||
![]() |
0a89edf3b0 | ||
![]() |
e7155837d7 | ||
![]() |
31e003bda5 | ||
![]() |
490e4d3180 | ||
![]() |
dc9f69bab0 | ||
![]() |
fdf04f77f2 | ||
![]() |
5e87483f34 | ||
![]() |
f7aa451591 | ||
![]() |
321d11c2c6 | ||
![]() |
ee447bc4ce | ||
![]() |
31153e4366 | ||
![]() |
7693024c29 | ||
![]() |
9628700a2f | ||
![]() |
38576173cb | ||
![]() |
19a769c12e | ||
![]() |
3c1db7d2f7 | ||
![]() |
626507093a | ||
![]() |
588b3d14a3 | ||
![]() |
815efa7791 | ||
![]() |
97a691ce2f | ||
![]() |
9d948f2c2b | ||
![]() |
0b87108174 | ||
![]() |
7fc7809cfc | ||
![]() |
c30be20e49 | ||
![]() |
25c64db0a1 | ||
![]() |
676e9c6593 | ||
![]() |
d459859361 | ||
![]() |
2be0cef446 | ||
![]() |
294db93fde | ||
![]() |
7f971f7173 | ||
![]() |
5c7b59524d | ||
![]() |
5133e5910e | ||
![]() |
1512c350df | ||
![]() |
a5fc7891a6 | ||
![]() |
3eb9633231 | ||
![]() |
ac67b48247 | ||
![]() |
81b65ea646 | ||
![]() |
45c1f6bc27 | ||
![]() |
0d31e5c8b1 | ||
![]() |
6378abf454 | ||
![]() |
f8fcaadb5b | ||
![]() |
0b5fd3ee76 | ||
![]() |
d010cb7e42 | ||
![]() |
71136d7347 | ||
![]() |
a18c552ddf | ||
![]() |
9656878ef3 | ||
![]() |
7ded7de39a | ||
![]() |
0f74e89b44 | ||
![]() |
953c40b083 | ||
![]() |
271b0287d8 | ||
![]() |
96a8a2a8b8 | ||
![]() |
75306f658f | ||
![]() |
325d9a0b86 | ||
![]() |
a02493fbaa | ||
![]() |
9c27d691dd | ||
![]() |
935bd01f59 | ||
![]() |
eeb5d669f6 | ||
![]() |
78daa2eb62 | ||
![]() |
40eda05a30 | ||
![]() |
9f9de8c43b | ||
![]() |
a910c8ccd8 | ||
![]() |
43bda2d4a4 | ||
![]() |
c7033dd757 | ||
![]() |
5673a9bace | ||
![]() |
34ff764515 | ||
![]() |
1b3a009da7 | ||
![]() |
a49002bb2c | ||
![]() |
7342fc2307 | ||
![]() |
9867a3bd60 | ||
![]() |
5ffb9eaa5b | ||
![]() |
b05b688267 | ||
![]() |
f3d7f85063 | ||
![]() |
de969a9dab |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -2,8 +2,8 @@ out
|
||||
*.zip
|
||||
*.jks
|
||||
*.apk
|
||||
config.prop
|
||||
update.sh
|
||||
/config.prop
|
||||
/update.sh
|
||||
|
||||
# Built binaries
|
||||
native/out
|
||||
|
@@ -30,13 +30,12 @@ Furthermore, Magisk provides a **Systemless Interface** to alter the system (or
|
||||
|
||||
## Translations
|
||||
|
||||
Default string resources for Magisk Manager are scattered throughout
|
||||
Default string resources for Magisk Manager and its stub APK are located here:
|
||||
|
||||
- `app/src/main/res/values/strings.xml`
|
||||
- `stub/src/main/res/values/strings.xml`
|
||||
- `shared/src/main/res/values/strings.xml`
|
||||
|
||||
Translate each and place them in the respective locations (`<module>/src/main/res/values-<lang>/strings.xml`).
|
||||
Translate each and place them in the respective locations (`[module]/src/main/res/values-[lang]/strings.xml`).
|
||||
|
||||
## Signature Verification
|
||||
|
||||
|
@@ -75,7 +75,7 @@ dependencies {
|
||||
implementation "${bindingAdapter}:${vBAdapt}"
|
||||
implementation "${bindingAdapter}-recyclerview:${vBAdapt}"
|
||||
|
||||
def vMarkwon = '4.1.1'
|
||||
def vMarkwon = '4.1.2'
|
||||
implementation "io.noties.markwon:core:${vMarkwon}"
|
||||
implementation "io.noties.markwon:html:${vMarkwon}"
|
||||
implementation "io.noties.markwon:image:${vMarkwon}"
|
||||
@@ -112,7 +112,7 @@ dependencies {
|
||||
replacedBy('com.github.topjohnwu:room-runtime')
|
||||
}
|
||||
}
|
||||
def vRoom = "2.2.0"
|
||||
def vRoom = "2.2.1"
|
||||
implementation "com.github.topjohnwu:room-runtime:${vRoom}"
|
||||
kapt "androidx.room:room-compiler:${vRoom}"
|
||||
|
||||
@@ -123,11 +123,12 @@ dependencies {
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0-beta05'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0-rc01'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.2.0-rc01'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.work:work-runtime:2.2.0'
|
||||
implementation 'androidx.transition:transition:1.2.0'
|
||||
implementation 'androidx.transition:transition:1.3.0-rc01'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.1.0-beta01'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha01'
|
||||
}
|
||||
|
6
app/proguard-rules.pro
vendored
6
app/proguard-rules.pro
vendored
@@ -32,7 +32,11 @@
|
||||
-keep,allowobfuscation class * extends com.topjohnwu.magisk.base.DelegateWorker
|
||||
|
||||
# BootSigner
|
||||
-keepclassmembers class com.topjohnwu.signing.BootSigner { *; }
|
||||
-keep class a.a { *; }
|
||||
|
||||
# Workaround R8 bug
|
||||
-keep,allowobfuscation class com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
||||
-keepclassmembers class a.e { *; }
|
||||
|
||||
# Strip logging
|
||||
-assumenosideeffects class timber.log.Timber.Tree { *; }
|
||||
|
5
app/res-ids.txt
Normal file
5
app/res-ids.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
com.topjohnwu.magisk:color/xxxxxxxx = 0x7f010000
|
||||
com.topjohnwu.magisk:drawable/xxxxxxxx = 0x7f020000
|
||||
com.topjohnwu.magisk:string/xxxxxxxx = 0x7f030000
|
||||
com.topjohnwu.magisk:style/xxxxxxxx = 0x7f040000
|
||||
com.topjohnwu.magisk:xml/xxxxxxxx = 0x7f050000
|
@@ -1,4 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
** Special Requirements **
|
||||
|
||||
This AndroidManifest.xml will be copied into the stub
|
||||
APK to allow APK delegation. This is why these special
|
||||
requirements exist.
|
||||
|
||||
* Class names *
|
||||
Class names a.a, a.c, a.e should not be changed as they are used
|
||||
externally. All other class names can be changed.
|
||||
|
||||
* Resource IDs *
|
||||
All resource IDs referred in AndroidManifest.xml is required to be
|
||||
included into the "shared" module to make the ID match with stub.
|
||||
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.topjohnwu.magisk">
|
||||
@@ -11,41 +29,46 @@
|
||||
|
||||
<application
|
||||
android:name="a.e"
|
||||
android:appComponentFactory="a.a"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/MagiskTheme"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
|
||||
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning"
|
||||
tools:replace="android:appComponentFactory">
|
||||
|
||||
<!-- Activities -->
|
||||
<!-- Splash -->
|
||||
|
||||
<activity
|
||||
android:name="a.b"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true" />
|
||||
<activity
|
||||
android:name="a.c"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Main -->
|
||||
|
||||
<activity
|
||||
android:name="a.b"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true" />
|
||||
|
||||
<!-- Flashing -->
|
||||
|
||||
<activity
|
||||
android:name="a.f"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:screenOrientation="nosensor"
|
||||
android:theme="@style/MagiskTheme.Flashing" />
|
||||
android:screenOrientation="nosensor" />
|
||||
|
||||
<!-- Superuser -->
|
||||
|
||||
<activity
|
||||
android:name="a.m"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:directBootAware="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="false"
|
||||
android:theme="@style/MagiskTheme.SU" />
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Receiver -->
|
||||
|
||||
@@ -53,6 +76,7 @@
|
||||
android:name="a.h"
|
||||
android:directBootAware="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.REBOOT" />
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
@@ -64,9 +88,10 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Service -->
|
||||
<!-- DownloadService -->
|
||||
|
||||
<service android:name="a.j"
|
||||
<service
|
||||
android:name="a.j"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Hardcode GMS version -->
|
||||
@@ -74,6 +99,12 @@
|
||||
android:name="com.google.android.gms.version"
|
||||
android:value="12451000" />
|
||||
|
||||
<!-- Initialize WorkManager on-demand -->
|
||||
<provider
|
||||
android:name="androidx.work.impl.WorkManagerInitializer"
|
||||
android:authorities="${applicationId}.workmanager-init"
|
||||
tools:node="remove" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@@ -1,13 +1,22 @@
|
||||
package a;
|
||||
|
||||
import androidx.core.app.AppComponentFactory;
|
||||
|
||||
import com.topjohnwu.magisk.utils.PatchAPK;
|
||||
import com.topjohnwu.signing.BootSigner;
|
||||
|
||||
import androidx.annotation.Keep;
|
||||
public class a extends AppComponentFactory {
|
||||
|
||||
@Keep
|
||||
public class a extends BootSigner {
|
||||
@Deprecated
|
||||
public static boolean patchAPK(String in, String out, String pkg) {
|
||||
return PatchAPK.patch(in, out, pkg);
|
||||
}
|
||||
|
||||
public static boolean patchAPK(String in, String out, String pkg, String label) {
|
||||
return PatchAPK.patch(in, out, pkg, label);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
BootSigner.main(args);
|
||||
}
|
||||
}
|
||||
|
@@ -3,5 +3,11 @@ package a;
|
||||
import com.topjohnwu.magisk.App;
|
||||
|
||||
public class e extends App {
|
||||
/* stub */
|
||||
public e() {
|
||||
super();
|
||||
}
|
||||
|
||||
public e(Object o) {
|
||||
super(o);
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import android.content.res.Configuration
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.multidex.MultiDex
|
||||
import androidx.room.Room
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.impl.WorkDatabase
|
||||
import androidx.work.impl.WorkDatabase_Impl
|
||||
import com.topjohnwu.magisk.data.database.RepoDatabase
|
||||
@@ -13,20 +14,25 @@ import com.topjohnwu.magisk.data.database.RepoDatabase_Impl
|
||||
import com.topjohnwu.magisk.di.ActivityTracker
|
||||
import com.topjohnwu.magisk.di.koinModules
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.utils.LocaleManager
|
||||
import com.topjohnwu.magisk.utils.RootUtils
|
||||
import com.topjohnwu.magisk.extensions.unwrap
|
||||
import com.topjohnwu.magisk.utils.RootInit
|
||||
import com.topjohnwu.magisk.utils.updateConfig
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.core.context.startKoin
|
||||
import timber.log.Timber
|
||||
|
||||
open class App : Application() {
|
||||
open class App() : Application() {
|
||||
|
||||
constructor(o: Any) : this() {
|
||||
Info.stub = DynAPK.load(o)
|
||||
}
|
||||
|
||||
init {
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||
Shell.Config.setFlags(Shell.FLAG_MOUNT_MASTER or Shell.FLAG_USE_MAGISK_BUSYBOX)
|
||||
Shell.Config.verboseLogging(BuildConfig.DEBUG)
|
||||
Shell.Config.addInitializers(RootUtils::class.java)
|
||||
Shell.Config.addInitializers(RootInit::class.java)
|
||||
Shell.Config.setTimeout(2)
|
||||
Room.setFactory {
|
||||
when (it) {
|
||||
@@ -38,22 +44,42 @@ open class App : Application() {
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base)
|
||||
// Basic setup
|
||||
if (BuildConfig.DEBUG)
|
||||
MultiDex.install(base)
|
||||
Timber.plant(Timber.DebugTree())
|
||||
|
||||
// Some context magic
|
||||
val app: Application
|
||||
val impl: Context
|
||||
if (base is Application) {
|
||||
app = base
|
||||
impl = base.baseContext
|
||||
} else {
|
||||
app = this
|
||||
impl = base
|
||||
}
|
||||
val wrapped = impl.wrap()
|
||||
super.attachBaseContext(wrapped)
|
||||
|
||||
// Normal startup
|
||||
startKoin {
|
||||
androidContext(this@App)
|
||||
androidContext(wrapped)
|
||||
modules(koinModules)
|
||||
}
|
||||
ResourceMgr.init(impl)
|
||||
app.registerActivityLifecycleCallbacks(get<ActivityTracker>())
|
||||
WorkManager.initialize(impl.wrapJob(), androidx.work.Configuration.Builder().build())
|
||||
}
|
||||
|
||||
registerActivityLifecycleCallbacks(get<ActivityTracker>())
|
||||
LocaleManager.setLocale(this)
|
||||
// This is required as some platforms expect ContextImpl
|
||||
override fun getBaseContext(): Context {
|
||||
return super.getBaseContext().unwrap()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
LocaleManager.setLocale(this)
|
||||
resources.updateConfig(newConfig)
|
||||
if (!isRunningAsStub)
|
||||
super.onConfigurationChanged(newConfig)
|
||||
}
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
package com.topjohnwu.magisk
|
||||
|
||||
import com.topjohnwu.magisk.model.download.DownloadService
|
||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
||||
import com.topjohnwu.magisk.model.update.UpdateCheckService
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
import com.topjohnwu.magisk.ui.flash.FlashActivity
|
||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||
|
||||
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,
|
||||
FlashActivity::class.java to a.f::class.java,
|
||||
UpdateCheckService::class.java to a.g::class.java,
|
||||
GeneralReceiver::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 <T : Class<*>>get(c: Class<*>): T {
|
||||
return map.getOrElse(c) { throw IllegalArgumentException() } as T
|
||||
}
|
||||
}
|
@@ -32,8 +32,9 @@ object Config : PreferenceModel, DBConfig {
|
||||
const val ROOT_ACCESS = "root_access"
|
||||
const val SU_MULTIUSER_MODE = "multiuser_mode"
|
||||
const val SU_MNT_NS = "mnt_ns"
|
||||
const val SU_MANAGER = "requester"
|
||||
const val SU_FINGERPRINT = "su_fingerprint"
|
||||
const val SU_MANAGER = "requester"
|
||||
const val KEYSTORE = "keystore"
|
||||
|
||||
// prefs
|
||||
const val SU_REQUEST_TIMEOUT = "su_request_timeout"
|
||||
@@ -97,7 +98,12 @@ object Config : PreferenceModel, DBConfig {
|
||||
}
|
||||
|
||||
private val defaultChannel =
|
||||
if (Utils.isCanary) Value.CANARY_DEBUG_CHANNEL
|
||||
if (Utils.isCanary) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Value.CANARY_DEBUG_CHANNEL
|
||||
else
|
||||
Value.CANARY_CHANNEL
|
||||
}
|
||||
else Value.DEFAULT_CHANNEL
|
||||
|
||||
var downloadPath by preference(Key.DOWNLOAD_PATH, Environment.DIRECTORY_DOWNLOADS)
|
||||
@@ -123,6 +129,7 @@ object Config : PreferenceModel, DBConfig {
|
||||
var suMultiuserMode by dbSettings(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY)
|
||||
var suFingerprint by dbSettings(Key.SU_FINGERPRINT, false)
|
||||
var suManager by dbStrings(Key.SU_MANAGER, "", true)
|
||||
var keyStoreRaw by dbStrings(Key.KEYSTORE, "", true)
|
||||
|
||||
// Always return a path in external storage where we can write
|
||||
val downloadDirectory get() =
|
||||
@@ -131,9 +138,6 @@ object Config : PreferenceModel, DBConfig {
|
||||
fun initialize() = prefs.edit {
|
||||
parsePrefs(this)
|
||||
|
||||
if (!prefs.contains(Key.UPDATE_CHANNEL))
|
||||
putString(Key.UPDATE_CHANNEL, defaultChannel.toString())
|
||||
|
||||
// Get actual state
|
||||
putBoolean(Key.COREONLY, Const.MAGISK_DISABLE_FILE.exists())
|
||||
|
||||
@@ -142,6 +146,9 @@ object Config : PreferenceModel, DBConfig {
|
||||
putString(Key.SU_MNT_NS, suMntNamespaceMode.toString())
|
||||
putString(Key.SU_MULTIUSER_MODE, suMultiuserMode.toString())
|
||||
putBoolean(Key.SU_FINGERPRINT, FingerprintHelper.useFingerprint())
|
||||
}.also {
|
||||
if (!prefs.contains(Key.UPDATE_CHANNEL))
|
||||
prefs.edit().putString(Key.UPDATE_CHANNEL, defaultChannel.toString()).apply()
|
||||
}
|
||||
|
||||
private fun parsePrefs(editor: SharedPreferences.Editor) = editor.apply {
|
||||
@@ -205,4 +212,4 @@ object Config : PreferenceModel, DBConfig {
|
||||
Shell.su("cat $xml > /data/adb/${Const.MANAGER_CONFIGS}").exec()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -22,8 +22,9 @@ object Const {
|
||||
const val MANAGER_CONFIGS = ".tmp.magisk.config"
|
||||
val USER_ID = Process.myUid() / 100000
|
||||
|
||||
object MagiskVersion {
|
||||
object Version {
|
||||
const val MIN_SUPPORT = 18000
|
||||
const val CONNECT_MODE = 20002
|
||||
}
|
||||
|
||||
object ID {
|
||||
|
199
app/src/main/java/com/topjohnwu/magisk/Hacks.kt
Normal file
199
app/src/main/java/com/topjohnwu/magisk/Hacks.kt
Normal file
@@ -0,0 +1,199 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.topjohnwu.magisk
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.job.JobInfo
|
||||
import android.app.job.JobScheduler
|
||||
import android.app.job.JobWorkItem
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.res.AssetManager
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.annotation.StringRes
|
||||
import com.topjohnwu.magisk.extensions.langTagToLocale
|
||||
import com.topjohnwu.magisk.model.download.DownloadService
|
||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
||||
import com.topjohnwu.magisk.model.update.UpdateCheckService
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
import com.topjohnwu.magisk.ui.flash.FlashActivity
|
||||
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
|
||||
import com.topjohnwu.magisk.utils.currentLocale
|
||||
import com.topjohnwu.magisk.utils.defaultLocale
|
||||
import com.topjohnwu.magisk.utils.refreshLocale
|
||||
import com.topjohnwu.magisk.utils.updateConfig
|
||||
import java.util.*
|
||||
|
||||
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.wrapJob(): Context = object : GlobalResContext(this) {
|
||||
|
||||
override fun getApplicationContext(): Context {
|
||||
return 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Class<*>.cmp(pkg: String = BuildConfig.APPLICATION_ID): ComponentName {
|
||||
val name = ClassMap[this].name
|
||||
return ComponentName(pkg, Info.stub?.componentMap?.get(name) ?: name)
|
||||
}
|
||||
|
||||
fun Context.intent(c: Class<*>): Intent {
|
||||
val cls = ClassMap[c]
|
||||
return Info.stub?.let {
|
||||
val className = it.componentMap.getOrElse(cls.name) { cls.name }
|
||||
Intent().setComponent(ComponentName(this, className))
|
||||
} ?: Intent(this, cls)
|
||||
}
|
||||
|
||||
private open class GlobalResContext(base: Context) : ContextWrapper(base) {
|
||||
open val mRes: Resources get() = ResourceMgr.resource
|
||||
private val loader by lazy { javaClass.classLoader!! }
|
||||
|
||||
override fun getResources(): Resources {
|
||||
return mRes
|
||||
}
|
||||
|
||||
override fun getClassLoader(): ClassLoader {
|
||||
return loader
|
||||
}
|
||||
|
||||
override fun createConfigurationContext(config: Configuration): Context {
|
||||
return ResContext(super.createConfigurationContext(config))
|
||||
}
|
||||
}
|
||||
|
||||
private class ResContext(base: Context) : GlobalResContext(base) {
|
||||
override val mRes by lazy { base.resources.patch() }
|
||||
|
||||
private fun Resources.patch(): Resources {
|
||||
updateConfig()
|
||||
if (isRunningAsStub)
|
||||
assets.addAssetPath(ResourceMgr.resApk)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
object ResourceMgr {
|
||||
|
||||
lateinit var resource: Resources
|
||||
lateinit var resApk: String
|
||||
|
||||
fun init(context: Context) {
|
||||
resource = context.resources
|
||||
refreshLocale()
|
||||
if (isRunningAsStub) {
|
||||
resApk = DynAPK.current(context).path
|
||||
resource.assets.addAssetPath(resApk)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = 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)
|
||||
}
|
||||
|
||||
private fun JobInfo.patch(): JobInfo {
|
||||
// We need to patch the component of JobInfo to access WorkManager SystemJobService
|
||||
|
||||
val name = service.className
|
||||
val component = ComponentName(
|
||||
service.packageName,
|
||||
Info.stub!!.componentMap[name] ?: name)
|
||||
|
||||
// Clone the JobInfo except component
|
||||
val builder = JobInfo.Builder(id, component)
|
||||
.setExtras(extras)
|
||||
.setTransientExtras(transientExtras)
|
||||
.setClipData(clipData, clipGrantFlags)
|
||||
.setRequiredNetwork(requiredNetwork)
|
||||
.setEstimatedNetworkBytes(estimatedNetworkDownloadBytes, estimatedNetworkUploadBytes)
|
||||
.setRequiresCharging(isRequireCharging)
|
||||
.setRequiresDeviceIdle(isRequireDeviceIdle)
|
||||
.setRequiresBatteryNotLow(isRequireBatteryNotLow)
|
||||
.setRequiresStorageNotLow(isRequireStorageNotLow)
|
||||
.also {
|
||||
triggerContentUris?.let { uris ->
|
||||
for (uri in uris)
|
||||
it.addTriggerContentUri(uri)
|
||||
}
|
||||
}
|
||||
.setTriggerContentUpdateDelay(triggerContentUpdateDelay)
|
||||
.setTriggerContentMaxDelay(triggerContentMaxDelay)
|
||||
.setImportantWhileForeground(isImportantWhileForeground)
|
||||
.setPrefetch(isPrefetch)
|
||||
.setPersisted(isPersisted)
|
||||
|
||||
if (isPeriodic) {
|
||||
builder.setPeriodic(intervalMillis, flexMillis)
|
||||
} else {
|
||||
if (minLatencyMillis > 0)
|
||||
builder.setMinimumLatency(minLatencyMillis)
|
||||
if (maxExecutionDelayMillis > 0)
|
||||
builder.setOverrideDeadline(maxExecutionDelayMillis)
|
||||
}
|
||||
if (!isRequireDeviceIdle)
|
||||
builder.setBackoffCriteria(initialBackoffMillis, backoffPolicy)
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
FlashActivity::class.java to a.f::class.java,
|
||||
UpdateCheckService::class.java to a.g::class.java,
|
||||
GeneralReceiver::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) { throw IllegalArgumentException() }
|
||||
}
|
@@ -1,26 +1,62 @@
|
||||
package com.topjohnwu.magisk
|
||||
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.model.entity.UpdateInfo
|
||||
import com.topjohnwu.magisk.utils.CachedValue
|
||||
import com.topjohnwu.magisk.utils.KObservableField
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
|
||||
val isRunningAsStub get() = Info.stub != null
|
||||
|
||||
object Info {
|
||||
|
||||
var magiskVersionCode = -1
|
||||
val envRef = CachedValue { loadState() }
|
||||
|
||||
var magiskVersionString = ""
|
||||
|
||||
var remote = UpdateInfo()
|
||||
val env by envRef // Local
|
||||
var remote = UpdateInfo() // Remote
|
||||
var stub: DynAPK.Data? = null // Stub
|
||||
|
||||
var keepVerity = false
|
||||
var keepEnc = false
|
||||
var recovery = false
|
||||
|
||||
fun loadMagiskInfo() {
|
||||
runCatching {
|
||||
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
|
||||
magiskVersionCode = ShellUtils.fastCmd("magisk -V").toInt()
|
||||
Config.magiskHide = Shell.su("magiskhide --status").exec().isSuccess
|
||||
val isConnected by lazy {
|
||||
KObservableField(false).also { field ->
|
||||
ReactiveNetwork.observeNetworkConnectivity(get())
|
||||
.subscribeK {
|
||||
field.value = it.available()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadState() = runCatching {
|
||||
val str = ShellUtils.fastCmd("magisk -v").split(":".toRegex())[0]
|
||||
val code = ShellUtils.fastCmd("magisk -V").toInt()
|
||||
val hide = Shell.su("magiskhide --status").exec().isSuccess
|
||||
var mode = -1
|
||||
if (code >= Const.Version.CONNECT_MODE) {
|
||||
mode = Shell.su("magisk --connect-mode").exec().code
|
||||
if (mode == 0) {
|
||||
// Manually trigger broadcast test
|
||||
Shell.su("magisk --broadcast-test").exec()
|
||||
}
|
||||
}
|
||||
Env(code, str, hide, mode)
|
||||
}.getOrElse { Env() }
|
||||
|
||||
class Env(
|
||||
val magiskVersionCode: Int = -1,
|
||||
val magiskVersionString: String = "",
|
||||
hide: Boolean = false,
|
||||
var connectionMode: Int = -1
|
||||
) {
|
||||
val magiskHide get() = Config.magiskHide
|
||||
|
||||
init {
|
||||
Config.magiskHide = hide
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,12 +15,13 @@ import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.base.viewmodel.BaseViewModel
|
||||
import com.topjohnwu.magisk.extensions.set
|
||||
import com.topjohnwu.magisk.model.events.EventHandler
|
||||
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
|
||||
import com.topjohnwu.magisk.utils.LocaleManager
|
||||
import com.topjohnwu.magisk.utils.currentLocale
|
||||
import com.topjohnwu.magisk.wrap
|
||||
import kotlin.random.Random
|
||||
|
||||
typealias RequestCallback = BaseActivity<*, *>.(Int, Intent?) -> Unit
|
||||
@@ -31,9 +32,8 @@ abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
||||
protected lateinit var binding: Binding
|
||||
protected abstract val layoutRes: Int
|
||||
protected abstract val viewModel: ViewModel
|
||||
protected open val themeRes: Int = R.style.MagiskTheme
|
||||
protected open val snackbarView get() = binding.root
|
||||
protected open val navHostId: Int = 0
|
||||
protected open val defaultPosition: Int = 0
|
||||
|
||||
private val resultCallbacks by lazy { SparseArrayCompat<RequestCallback>() }
|
||||
|
||||
@@ -53,10 +53,11 @@ abstract class BaseActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(LocaleManager.getLocaleContext(base))
|
||||
super.attachBaseContext(base.wrap(false))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(themeRes)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
viewModel.viewEvents.observe(this, viewEventObserver)
|
||||
|
17
app/src/main/java/com/topjohnwu/magisk/base/BaseReceiver.kt
Normal file
17
app/src/main/java/com/topjohnwu/magisk/base/BaseReceiver.kt
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.topjohnwu.magisk.base
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import com.topjohnwu.magisk.wrap
|
||||
import org.koin.core.KoinComponent
|
||||
|
||||
abstract class BaseReceiver : BroadcastReceiver(), KoinComponent {
|
||||
|
||||
final override fun onReceive(context: Context, intent: Intent?) {
|
||||
onReceive(context.wrap() as ContextWrapper, intent)
|
||||
}
|
||||
|
||||
abstract fun onReceive(context: ContextWrapper, intent: Intent?)
|
||||
}
|
12
app/src/main/java/com/topjohnwu/magisk/base/BaseService.kt
Normal file
12
app/src/main/java/com/topjohnwu/magisk/base/BaseService.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package com.topjohnwu.magisk.base
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import com.topjohnwu.magisk.wrap
|
||||
import org.koin.core.KoinComponent
|
||||
|
||||
abstract class BaseService : Service(), KoinComponent {
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base.wrap())
|
||||
}
|
||||
}
|
@@ -1,28 +1,24 @@
|
||||
package com.topjohnwu.magisk.base.viewmodel
|
||||
|
||||
import android.app.Activity
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.topjohnwu.magisk.extensions.doOnSubscribeUi
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.model.events.BackPressEvent
|
||||
import com.topjohnwu.magisk.model.events.PermissionEvent
|
||||
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||
import com.topjohnwu.magisk.utils.KObservableField
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.subjects.PublishSubject
|
||||
import com.topjohnwu.magisk.Info.isConnected as gIsConnected
|
||||
|
||||
|
||||
abstract class BaseViewModel(
|
||||
initialState: State = State.LOADING
|
||||
) : LoadingViewModel(initialState) {
|
||||
|
||||
val isConnected = KObservableField(false)
|
||||
|
||||
init {
|
||||
ReactiveNetwork.observeNetworkConnectivity(get())
|
||||
.subscribeK { isConnected.value = it.available() }
|
||||
.add()
|
||||
val isConnected = object : KObservableField<Boolean>(gIsConnected.value, gIsConnected) {
|
||||
override fun get(): Boolean {
|
||||
return gIsConnected.value
|
||||
}
|
||||
}
|
||||
|
||||
fun withView(action: Activity.() -> Unit) {
|
||||
|
@@ -29,7 +29,7 @@ class MagiskRepository(
|
||||
else -> throw IllegalArgumentException()
|
||||
}.flatMap {
|
||||
// If remote version is lower than current installed, try switching to beta
|
||||
if (it.magisk.versionCode < Info.magiskVersionCode
|
||||
if (it.magisk.versionCode < Info.env.magiskVersionCode
|
||||
&& Config.updateChannel == Config.Value.DEFAULT_CHANNEL) {
|
||||
Config.updateChannel = Config.Value.BETA_CHANNEL
|
||||
apiRaw.fetchBetaUpdate()
|
||||
@@ -74,4 +74,4 @@ class MagiskRepository(
|
||||
) }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package com.topjohnwu.magisk.extensions
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ComponentInfo
|
||||
@@ -10,19 +12,30 @@ import android.content.pm.PackageManager.*
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Canvas
|
||||
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.provider.OpenableColumns
|
||||
import android.view.View
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import com.topjohnwu.magisk.utils.FileProvider
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.FileProvider
|
||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.utils.currentLocale
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import java.io.File
|
||||
import java.io.FileNotFoundException
|
||||
import java.lang.reflect.Array as JArray
|
||||
|
||||
val packageName: String get() = get<Context>().packageName
|
||||
|
||||
@@ -91,8 +104,129 @@ fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
||||
fun Context.readUri(uri: Uri) =
|
||||
contentResolver.openInputStream(uri) ?: throw FileNotFoundException()
|
||||
|
||||
fun Context.getBitmap(id: Int): Bitmap {
|
||||
var drawable = AppCompatResources.getDrawable(this, id)!!
|
||||
if (drawable is BitmapDrawable)
|
||||
return drawable.bitmap
|
||||
if (SDK_INT >= 26 && drawable is AdaptiveIconDrawable) {
|
||||
drawable = LayerDrawable(arrayOf(drawable.background, drawable.foreground))
|
||||
}
|
||||
val bitmap = Bitmap.createBitmap(
|
||||
drawable.intrinsicWidth, drawable.intrinsicHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
drawable.draw(canvas)
|
||||
return bitmap
|
||||
}
|
||||
|
||||
fun Intent.startActivity(context: Context) = context.startActivity(this)
|
||||
|
||||
fun Intent.startActivityWithRoot() {
|
||||
val args = mutableListOf("am", "start", "--user", Const.USER_ID.toString())
|
||||
val cmd = toCommand(args).joinToString(" ")
|
||||
Shell.su(cmd).submit()
|
||||
}
|
||||
|
||||
fun Intent.toCommand(args: MutableList<String> = mutableListOf()): MutableList<String> {
|
||||
action?.also {
|
||||
args.add("-a")
|
||||
args.add(it)
|
||||
}
|
||||
component?.also {
|
||||
args.add("-n")
|
||||
args.add(it.flattenToString())
|
||||
}
|
||||
data?.also {
|
||||
args.add("-d")
|
||||
args.add(it.toString())
|
||||
}
|
||||
categories?.also {
|
||||
for (cat in it) {
|
||||
args.add("-c")
|
||||
args.add(cat)
|
||||
}
|
||||
}
|
||||
type?.also {
|
||||
args.add("-t")
|
||||
args.add(it)
|
||||
}
|
||||
extras?.also {
|
||||
loop@ for (key in it.keySet()) {
|
||||
val v = it[key] ?: continue
|
||||
var value: Any = v
|
||||
val arg: String
|
||||
when {
|
||||
v is String -> arg = "--es"
|
||||
v is Boolean -> arg = "--ez"
|
||||
v is Int -> arg = "--ei"
|
||||
v is Long -> arg = "--el"
|
||||
v is Float -> arg = "--ef"
|
||||
v is Uri -> arg = "--eu"
|
||||
v is ComponentName -> {
|
||||
arg = "--ecn"
|
||||
value = v.flattenToString()
|
||||
}
|
||||
v is List<*> -> {
|
||||
if (v.isEmpty())
|
||||
continue@loop
|
||||
|
||||
arg = if (v[0] is Int)
|
||||
"--eial"
|
||||
else if (v[0] is Long)
|
||||
"--elal"
|
||||
else if (v[0] is Float)
|
||||
"--efal"
|
||||
else if (v[0] is String)
|
||||
"--esal"
|
||||
else
|
||||
continue@loop /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (o in v) {
|
||||
sb.append(o.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
}
|
||||
v.javaClass.isArray -> {
|
||||
arg = if (v is IntArray)
|
||||
"--eia"
|
||||
else if (v is LongArray)
|
||||
"--ela"
|
||||
else if (v is FloatArray)
|
||||
"--efa"
|
||||
else if (v is Array<*> && v.isArrayOf<String>())
|
||||
"--esa"
|
||||
else
|
||||
continue@loop /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
val len = JArray.getLength(v)
|
||||
for (i in 0 until len) {
|
||||
sb.append(JArray.get(v, i)!!.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
}
|
||||
else -> continue@loop
|
||||
} /* Unsupported */
|
||||
|
||||
args.add(arg)
|
||||
args.add(key)
|
||||
args.add(value.toString())
|
||||
}
|
||||
}
|
||||
args.add("-f")
|
||||
args.add(flags.toString())
|
||||
return args
|
||||
}
|
||||
|
||||
fun File.provide(context: Context = get()): Uri {
|
||||
return FileProvider.getUriForFile(context, context.packageName + ".provider", this)
|
||||
}
|
||||
@@ -157,3 +291,18 @@ fun Context.startEndToLeftRight(start: Int, end: Int): Pair<Int, Int> {
|
||||
}
|
||||
|
||||
fun Context.openUrl(url: String) = Utils.openLink(this, url.toUri())
|
||||
|
||||
@Suppress("FunctionName")
|
||||
inline fun <reified T> T.DynamicClassLoader(apk: File)
|
||||
= DynamicClassLoader(apk, T::class.java.classLoader)
|
||||
|
||||
fun Context.unwrap() : Context {
|
||||
var context = this
|
||||
while (true) {
|
||||
if (context is ContextWrapper)
|
||||
context = context.baseContext
|
||||
else
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
@@ -25,3 +25,5 @@ fun String.trimEmptyToNull(): String? = if (isBlank()) null else this
|
||||
fun String.legalFilename() = replace(" ", "_").replace("'", "").replace("\"", "")
|
||||
.replace("$", "").replace("`", "").replace("*", "").replace("/", "_")
|
||||
.replace("#", "").replace("@", "").replace("\\", "_")
|
||||
|
||||
fun String.isEmptyInternal() = isNullOrBlank()
|
@@ -1,17 +1,17 @@
|
||||
package com.topjohnwu.magisk.model.download
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.webkit.MimeTypeMap
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.extensions.chooser
|
||||
import com.topjohnwu.magisk.extensions.exists
|
||||
import com.topjohnwu.magisk.extensions.provide
|
||||
import com.topjohnwu.magisk.intent
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.*
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.Flash.Secondary
|
||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||
@@ -63,20 +63,20 @@ open class DownloadService : RemoteFileService() {
|
||||
remove(id)
|
||||
when (subject.configuration) {
|
||||
is APK.Upgrade -> APKInstall.install(this, subject.file)
|
||||
else -> Unit
|
||||
is APK.Restore -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
override fun NotificationCompat.Builder.addActions(subject: DownloadSubject)
|
||||
override fun Notification.Builder.addActions(subject: DownloadSubject)
|
||||
= when (subject) {
|
||||
is Magisk -> addActionsInternal(subject)
|
||||
is Module -> addActionsInternal(subject)
|
||||
is Manager -> addActionsInternal(subject)
|
||||
}
|
||||
|
||||
private fun NotificationCompat.Builder.addActionsInternal(subject: Magisk)
|
||||
private fun Notification.Builder.addActionsInternal(subject: Magisk)
|
||||
= when (val conf = subject.configuration) {
|
||||
Download -> this.apply {
|
||||
fileIntent(subject.file.parentFile!!)
|
||||
@@ -92,7 +92,7 @@ open class DownloadService : RemoteFileService() {
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun NotificationCompat.Builder.addActionsInternal(subject: Module)
|
||||
private fun Notification.Builder.addActionsInternal(subject: Module)
|
||||
= when (subject.configuration) {
|
||||
Download -> this.apply {
|
||||
fileIntent(subject.file.parentFile!!)
|
||||
@@ -106,19 +106,19 @@ open class DownloadService : RemoteFileService() {
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun NotificationCompat.Builder.addActionsInternal(subject: Manager)
|
||||
private fun Notification.Builder.addActionsInternal(subject: Manager)
|
||||
= when (subject.configuration) {
|
||||
APK.Upgrade -> setContentIntent(APKInstall.installIntent(context, subject.file))
|
||||
else -> this
|
||||
}
|
||||
|
||||
@Suppress("ReplaceSingleLineLet")
|
||||
private fun NotificationCompat.Builder.setContentIntent(intent: Intent) =
|
||||
private fun Notification.Builder.setContentIntent(intent: Intent) =
|
||||
PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT)
|
||||
.let { setContentIntent(it) }
|
||||
|
||||
@Suppress("ReplaceSingleLineLet")
|
||||
private fun NotificationCompat.Builder.addAction(icon: Int, title: Int, intent: Intent) =
|
||||
private fun Notification.Builder.addAction(icon: Int, title: Int, intent: Intent) =
|
||||
PendingIntent.getActivity(context, nextInt(), intent, PendingIntent.FLAG_ONE_SHOT)
|
||||
.let { addAction(icon, getString(title), it) }
|
||||
|
||||
@@ -140,8 +140,7 @@ open class DownloadService : RemoteFileService() {
|
||||
inline operator fun invoke(context: Context, argBuilder: Builder.() -> Unit) {
|
||||
val app = context.applicationContext
|
||||
val builder = Builder().apply(argBuilder)
|
||||
val intent = Intent(app, ClassMap[DownloadService::class.java])
|
||||
.putExtra(ARG_URL, builder.subject)
|
||||
val intent = app.intent(DownloadService::class.java).putExtra(ARG_URL, builder.subject)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
app.startForegroundService(intent)
|
||||
@@ -152,4 +151,4 @@ open class DownloadService : RemoteFileService() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,43 +1,47 @@
|
||||
package com.topjohnwu.magisk.model.download
|
||||
|
||||
import android.content.ComponentName
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.extensions.writeTo
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Restore
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration.APK.Upgrade
|
||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.utils.PatchAPK
|
||||
import com.topjohnwu.magisk.utils.RootUtils
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
|
||||
private fun RemoteFileService.patchPackage(apk: File, id: Int) {
|
||||
if (packageName != BuildConfig.APPLICATION_ID) {
|
||||
update(id) { notification ->
|
||||
notification.setProgress(0, 0, true)
|
||||
.setProgress(0, 0, true)
|
||||
.setContentTitle(getString(R.string.hide_manager_title))
|
||||
.setContentText("")
|
||||
}
|
||||
val patched = File(apk.parent, "patched.apk")
|
||||
try {
|
||||
// Try using the new APK to patch itself
|
||||
val loader = DynamicClassLoader(apk)
|
||||
loader.loadClass("a.a")
|
||||
.getMethod("patchAPK", String::class.java, String::class.java, String::class.java)
|
||||
.invoke(null, apk.path, patched.path, packageName)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
// Fallback to use the current implementation
|
||||
PatchAPK.patch(apk.path, patched.path, packageName)
|
||||
}
|
||||
private fun RemoteFileService.patch(apk: File, id: Int) {
|
||||
if (packageName == BuildConfig.APPLICATION_ID)
|
||||
return
|
||||
|
||||
update(id) { notification ->
|
||||
notification.setProgress(0, 0, true)
|
||||
.setProgress(0, 0, true)
|
||||
.setContentTitle(getString(R.string.hide_manager_title))
|
||||
.setContentText("")
|
||||
}
|
||||
val patched = File(apk.parent, "patched.apk")
|
||||
PatchAPK.patch(apk, patched, packageName, applicationInfo.nonLocalizedLabel.toString())
|
||||
apk.delete()
|
||||
patched.renameTo(apk)
|
||||
}
|
||||
|
||||
private fun RemoteFileService.upgrade(apk: File, id: Int) {
|
||||
if (isRunningAsStub) {
|
||||
// Move to upgrade location
|
||||
apk.copyTo(DynAPK.update(this), overwrite = true)
|
||||
apk.delete()
|
||||
patched.renameTo(apk)
|
||||
if (Info.stub!!.version < Info.remote.stub.versionCode) {
|
||||
// We also want to upgrade stub
|
||||
service.fetchFile(Info.remote.stub.link).blockingGet().byteStream().use {
|
||||
it.writeTo(apk)
|
||||
}
|
||||
patch(apk, id)
|
||||
} else {
|
||||
// Simply relaunch the app
|
||||
ProcessPhoenix.triggerRebirth(this)
|
||||
}
|
||||
} else {
|
||||
patch(apk, id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,15 +55,11 @@ private fun RemoteFileService.restore(apk: File, id: Int) {
|
||||
Config.export()
|
||||
// Make it world readable
|
||||
apk.setReadable(true, false)
|
||||
if (Shell.su("pm install $apk").exec().isSuccess) {
|
||||
val component = ComponentName(BuildConfig.APPLICATION_ID,
|
||||
ClassMap.get<Class<*>>(SplashActivity::class.java).name)
|
||||
RootUtils.rmAndLaunch(packageName, component)
|
||||
}
|
||||
Shell.su("pm install $apk && pm uninstall $packageName").exec()
|
||||
}
|
||||
|
||||
fun RemoteFileService.handleAPK(subject: DownloadSubject.Manager)
|
||||
= when (subject.configuration) {
|
||||
is Upgrade -> patchPackage(subject.file, subject.hashCode())
|
||||
is Upgrade -> upgrade(subject.file, subject.hashCode())
|
||||
is Restore -> restore(subject.file, subject.hashCode())
|
||||
}
|
||||
|
@@ -1,24 +1,22 @@
|
||||
package com.topjohnwu.magisk.model.download
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import com.topjohnwu.magisk.base.BaseService
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import org.koin.core.KoinComponent
|
||||
import java.util.*
|
||||
import kotlin.random.Random.Default.nextInt
|
||||
|
||||
abstract class NotificationService : Service(), KoinComponent {
|
||||
abstract class NotificationService : BaseService(), KoinComponent {
|
||||
|
||||
abstract val defaultNotification: NotificationCompat.Builder
|
||||
abstract val defaultNotification: Notification.Builder
|
||||
|
||||
private val manager by lazy { NotificationManagerCompat.from(this) }
|
||||
private val hasNotifications get() = notifications.isNotEmpty()
|
||||
|
||||
private val notifications =
|
||||
Collections.synchronizedMap(mutableMapOf<Int, NotificationCompat.Builder>())
|
||||
Collections.synchronizedMap(mutableMapOf<Int, Notification.Builder>())
|
||||
|
||||
override fun onTaskRemoved(rootIntent: Intent?) {
|
||||
super.onTaskRemoved(rootIntent)
|
||||
@@ -30,7 +28,7 @@ abstract class NotificationService : Service(), KoinComponent {
|
||||
|
||||
fun update(
|
||||
id: Int,
|
||||
body: (NotificationCompat.Builder) -> Unit = {}
|
||||
body: (Notification.Builder) -> Unit = {}
|
||||
) {
|
||||
val notification = notifications.getOrPut(id) { defaultNotification }
|
||||
|
||||
@@ -43,7 +41,7 @@ abstract class NotificationService : Service(), KoinComponent {
|
||||
|
||||
protected fun finishNotify(
|
||||
id: Int,
|
||||
editBody: (NotificationCompat.Builder) -> NotificationCompat.Builder? = { null }
|
||||
editBody: (Notification.Builder) -> Notification.Builder? = { null }
|
||||
) : Int {
|
||||
val currentNotification = remove(id)?.run(editBody)
|
||||
|
||||
@@ -62,11 +60,11 @@ abstract class NotificationService : Service(), KoinComponent {
|
||||
// ---
|
||||
|
||||
private fun notify(id: Int, notification: Notification) {
|
||||
manager.notify(id, notification)
|
||||
Notifications.mgr.notify(id, notification)
|
||||
}
|
||||
|
||||
private fun cancel(id: Int) {
|
||||
manager.cancel(id)
|
||||
Notifications.mgr.cancel(id)
|
||||
}
|
||||
|
||||
protected fun remove(id: Int) = notifications.remove(id).also {
|
||||
@@ -84,4 +82,4 @@ abstract class NotificationService : Service(), KoinComponent {
|
||||
// --
|
||||
|
||||
override fun onBind(p0: Intent?): IBinder? = null
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package com.topjohnwu.magisk.model.download
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Notification
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.di.NullActivity
|
||||
@@ -22,9 +22,9 @@ import java.io.InputStream
|
||||
|
||||
abstract class RemoteFileService : NotificationService() {
|
||||
|
||||
private val service: GithubRawServices by inject()
|
||||
val service: GithubRawServices by inject()
|
||||
|
||||
override val defaultNotification: NotificationCompat.Builder
|
||||
override val defaultNotification
|
||||
get() = Notifications.progress(this, "")
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
@@ -108,11 +108,11 @@ abstract class RemoteFileService : NotificationService() {
|
||||
@Throws(Throwable::class)
|
||||
protected abstract fun onFinished(subject: DownloadSubject, id: Int)
|
||||
|
||||
protected abstract fun NotificationCompat.Builder.addActions(subject: DownloadSubject)
|
||||
: NotificationCompat.Builder
|
||||
protected abstract fun Notification.Builder.addActions(subject: DownloadSubject)
|
||||
: Notification.Builder
|
||||
|
||||
companion object {
|
||||
const val ARG_URL = "arg_url"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,8 @@ import se.ansman.kotshi.JsonSerializable
|
||||
data class UpdateInfo(
|
||||
val app: ManagerJson = ManagerJson(),
|
||||
val uninstaller: UninstallerJson = UninstallerJson(),
|
||||
val magisk: MagiskJson = MagiskJson()
|
||||
val magisk: MagiskJson = MagiskJson(),
|
||||
val stub: StubJson = StubJson()
|
||||
)
|
||||
|
||||
@JsonSerializable
|
||||
@@ -33,3 +34,9 @@ data class ManagerJson(
|
||||
val link: String = "",
|
||||
val note: String = ""
|
||||
) : Parcelable
|
||||
|
||||
@JsonSerializable
|
||||
data class StubJson(
|
||||
val versionCode: Int = -1,
|
||||
val link: String = ""
|
||||
)
|
||||
|
@@ -1,16 +1,15 @@
|
||||
package com.topjohnwu.magisk.model.receiver
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.Info
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.base.BaseReceiver
|
||||
import com.topjohnwu.magisk.data.database.PolicyDao
|
||||
import com.topjohnwu.magisk.data.database.base.su
|
||||
import com.topjohnwu.magisk.extensions.inject
|
||||
import com.topjohnwu.magisk.extensions.reboot
|
||||
import com.topjohnwu.magisk.extensions.startActivity
|
||||
import com.topjohnwu.magisk.extensions.startActivityWithRoot
|
||||
import com.topjohnwu.magisk.model.download.DownloadService
|
||||
import com.topjohnwu.magisk.model.entity.ManagerJson
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||
@@ -20,8 +19,10 @@ import com.topjohnwu.magisk.utils.SuLogger
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import org.koin.core.inject
|
||||
import timber.log.Timber
|
||||
|
||||
open class GeneralReceiver : BroadcastReceiver() {
|
||||
open class GeneralReceiver : BaseReceiver() {
|
||||
|
||||
private val policyDB: PolicyDao by inject()
|
||||
|
||||
@@ -36,8 +37,19 @@ open class GeneralReceiver : BroadcastReceiver() {
|
||||
return intent.data?.encodedSchemeSpecificPart.orEmpty()
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
override fun onReceive(context: ContextWrapper, intent: Intent?) {
|
||||
intent ?: return
|
||||
|
||||
// Debug messages
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d(intent.action)
|
||||
intent.extras?.let { bundle ->
|
||||
bundle.keySet().forEach {
|
||||
Timber.d("[%s]=[%s]", it, bundle[it])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when (intent.action ?: return) {
|
||||
Intent.ACTION_REBOOT, Intent.ACTION_BOOT_COMPLETED -> {
|
||||
val action = intent.getStringExtra("action")
|
||||
@@ -51,16 +63,26 @@ open class GeneralReceiver : BroadcastReceiver() {
|
||||
}
|
||||
when (action) {
|
||||
REQUEST -> {
|
||||
val i = Intent(context, ClassMap[SuRequestActivity::class.java])
|
||||
val i = context.intent(SuRequestActivity::class.java)
|
||||
.setAction(action)
|
||||
.putExtra("socket", intent.getStringExtra("socket"))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
|
||||
context.startActivity(i)
|
||||
if (SDK_INT >= 29) {
|
||||
// Android Q does not allow starting activity from background
|
||||
i.startActivityWithRoot()
|
||||
} else {
|
||||
i.startActivity(context)
|
||||
}
|
||||
}
|
||||
LOG -> SuLogger.handleLogs(context, intent)
|
||||
NOTIFY -> SuLogger.handleNotify(context, intent)
|
||||
TEST -> {
|
||||
val mode = intent.getIntExtra("mode", 1 shl 1)
|
||||
if (mode > Info.env.connectionMode)
|
||||
Info.env.connectionMode = mode
|
||||
Shell.su("magisk --connect-mode $mode").submit()
|
||||
}
|
||||
LOG -> SuLogger.handleLogs(intent)
|
||||
NOTIFY -> SuLogger.handleNotify(intent)
|
||||
TEST -> Shell.su("magisk --use-broadcast").submit()
|
||||
}
|
||||
}
|
||||
Intent.ACTION_PACKAGE_REPLACED ->
|
||||
|
@@ -20,7 +20,7 @@ class UpdateCheckService : DelegateWorker() {
|
||||
magiskRepo.fetchUpdate().blockingGet()
|
||||
if (BuildConfig.VERSION_CODE < Info.remote.app.versionCode)
|
||||
Notifications.managerUpdate(applicationContext)
|
||||
else if (Info.magiskVersionCode < Info.remote.magisk.versionCode)
|
||||
else if (Info.env.magiskVersionCode < Info.remote.magisk.versionCode)
|
||||
Notifications.magiskUpdate(applicationContext)
|
||||
ListenableWorker.Result.success()
|
||||
}.getOrElse {
|
||||
|
@@ -266,7 +266,7 @@ abstract class MagiskInstaller {
|
||||
|
||||
val patched = File(installDir, "new-boot.img")
|
||||
if (isSigned) {
|
||||
console.add("- Signing boot image with test keys")
|
||||
console.add("- Signing boot image with verity keys")
|
||||
val signed = File(installDir, "signed.img")
|
||||
try {
|
||||
withStreams(SuFileInputStream(patched), signed.outputStream().buffered()) {
|
||||
|
@@ -7,8 +7,6 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.ncapdevi.fragnav.FragNavController
|
||||
import com.ncapdevi.fragnav.FragNavTransactionOptions
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.Const.Key.OPEN_SECTION
|
||||
import com.topjohnwu.magisk.Info
|
||||
import com.topjohnwu.magisk.R
|
||||
@@ -17,6 +15,7 @@ import com.topjohnwu.magisk.base.BaseFragment
|
||||
import com.topjohnwu.magisk.databinding.ActivityMainBinding
|
||||
import com.topjohnwu.magisk.extensions.addOnPropertyChangedCallback
|
||||
import com.topjohnwu.magisk.extensions.snackbar
|
||||
import com.topjohnwu.magisk.intent
|
||||
import com.topjohnwu.magisk.model.events.*
|
||||
import com.topjohnwu.magisk.model.navigation.MagiskAnimBuilder
|
||||
import com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent
|
||||
@@ -40,8 +39,8 @@ open class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(), Na
|
||||
|
||||
override val layoutRes: Int = R.layout.activity_main
|
||||
override val viewModel: MainViewModel by viewModel()
|
||||
override val navHostId: Int = R.id.main_nav_host
|
||||
override val defaultPosition: Int = 0
|
||||
private val navHostId: Int = R.id.main_nav_host
|
||||
private val defaultPosition: Int = 0
|
||||
|
||||
private val navigationController by lazy {
|
||||
FragNavController(supportFragmentManager, navHostId)
|
||||
@@ -61,7 +60,7 @@ open class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(), Na
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (!SplashActivity.DONE) {
|
||||
startActivity(Intent(this, ClassMap[SplashActivity::class.java]))
|
||||
startActivity(intent(SplashActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
||||
@@ -155,11 +154,11 @@ open class MainActivity : BaseActivity<MainViewModel, ActivityMainBinding>(), Na
|
||||
private fun checkHideSection() {
|
||||
val menu = binding.navView.menu
|
||||
menu.findItem(R.id.magiskHideFragment).isVisible =
|
||||
Shell.rootAccess() && Config.magiskHide
|
||||
Shell.rootAccess() && Info.env.magiskHide
|
||||
menu.findItem(R.id.modulesFragment).isVisible =
|
||||
Shell.rootAccess() && Info.magiskVersionCode >= 0
|
||||
Shell.rootAccess() && Info.env.magiskVersionCode >= 0
|
||||
menu.findItem(R.id.reposFragment).isVisible =
|
||||
(viewModel.isConnected.value && Shell.rootAccess() && Info.magiskVersionCode >= 0)
|
||||
(viewModel.isConnected.value && Shell.rootAccess() && Info.env.magiskVersionCode >= 0)
|
||||
menu.findItem(R.id.logFragment).isVisible =
|
||||
Shell.rootAccess()
|
||||
menu.findItem(R.id.superuserFragment).isVisible =
|
||||
|
@@ -1,27 +1,31 @@
|
||||
package com.topjohnwu.magisk.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
import com.topjohnwu.superuser.Shell
|
||||
|
||||
open class SplashActivity : AppCompatActivity() {
|
||||
open class SplashActivity : Activity() {
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
super.attachBaseContext(base.wrap())
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
Shell.getShell {
|
||||
if (Info.magiskVersionCode > 0 && Info.magiskVersionCode < Const.MagiskVersion.MIN_SUPPORT) {
|
||||
if (Info.env.magiskVersionCode > 0 && Info.env.magiskVersionCode < Const.Version.MIN_SUPPORT) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.unsupport_magisk_title)
|
||||
.setMessage(R.string.unsupport_magisk_message)
|
||||
.setNegativeButton(R.string.ok, null)
|
||||
.setNegativeButton(android.R.string.ok, null)
|
||||
.setOnDismissListener { finish() }
|
||||
.show()
|
||||
} else {
|
||||
@@ -56,7 +60,7 @@ open class SplashActivity : AppCompatActivity() {
|
||||
// Setup shortcuts
|
||||
Shortcuts.setup(this)
|
||||
|
||||
val intent = Intent(this, ClassMap[MainActivity::class.java])
|
||||
val intent = intent(MainActivity::class.java)
|
||||
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION))
|
||||
DONE = true
|
||||
startActivity(intent)
|
||||
|
@@ -6,12 +6,12 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.net.toUri
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.base.BaseActivity
|
||||
import com.topjohnwu.magisk.databinding.ActivityFlashBinding
|
||||
import com.topjohnwu.magisk.extensions.snackbar
|
||||
import com.topjohnwu.magisk.intent
|
||||
import com.topjohnwu.magisk.model.events.BackPressEvent
|
||||
import com.topjohnwu.magisk.model.events.PermissionEvent
|
||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||
@@ -23,6 +23,7 @@ import java.io.File
|
||||
open class FlashActivity : BaseActivity<FlashViewModel, ActivityFlashBinding>() {
|
||||
|
||||
override val layoutRes: Int = R.layout.activity_flash
|
||||
override val themeRes: Int = R.style.MagiskTheme_Flashing
|
||||
override val viewModel: FlashViewModel by viewModel {
|
||||
val uri = intent.data ?: let { finish(); Uri.EMPTY }
|
||||
val additionalUri = intent.getParcelableExtra(Const.Key.FLASH_DATA) ?: uri
|
||||
@@ -59,7 +60,7 @@ open class FlashActivity : BaseActivity<FlashViewModel, ActivityFlashBinding>()
|
||||
|
||||
companion object {
|
||||
|
||||
private fun intent(context: Context) = Intent(context, ClassMap[FlashActivity::class.java])
|
||||
private fun intent(context: Context) = context.intent(FlashActivity::class.java)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
private fun intent(context: Context, file: File) = intent(context).setData(file.toUri())
|
||||
|
||||
|
@@ -9,11 +9,11 @@ import com.topjohnwu.magisk.base.BaseActivity
|
||||
import com.topjohnwu.magisk.base.BaseFragment
|
||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||
import com.topjohnwu.magisk.databinding.FragmentMagiskBinding
|
||||
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.extensions.openUrl
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.extensions.writeTo
|
||||
import com.topjohnwu.magisk.model.events.*
|
||||
import com.topjohnwu.magisk.utils.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.utils.SafetyNetHelper
|
||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||
import com.topjohnwu.magisk.view.dialogs.*
|
||||
@@ -87,8 +87,8 @@ class HomeFragment : BaseFragment<HomeViewModel, FragmentMagiskBinding>(),
|
||||
.setTitle(R.string.proprietary_title)
|
||||
.setMessage(R.string.proprietary_notice)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.yes) { _, _ -> download() }
|
||||
.setNegativeButton(R.string.no_thanks) { _, _ -> viewModel.finishSafetyNetCheck(-2) }
|
||||
.setPositiveButton(android.R.string.yes) { _, _ -> download() }
|
||||
.setNegativeButton(android.R.string.no) { _, _ -> viewModel.finishSafetyNetCheck(-2) }
|
||||
.show()
|
||||
}
|
||||
|
||||
|
@@ -77,7 +77,7 @@ class HomeViewModel(
|
||||
""
|
||||
}
|
||||
|
||||
val safetyNetTitle = KObservableField(R.string.safetyNet_check_text)
|
||||
val safetyNetTitle = KObservableField(R.string.safetyNet_check_text.res())
|
||||
val ctsState = KObservableField(SafetyNetState.IDLE)
|
||||
val basicIntegrityState = KObservableField(SafetyNetState.IDLE)
|
||||
val safetyNetState = Observer(ctsState, basicIntegrityState) {
|
||||
@@ -107,10 +107,10 @@ class HomeViewModel(
|
||||
Info.recovery = it ?: return@addOnPropertyChangedCallback
|
||||
}
|
||||
isConnected.addOnPropertyChangedCallback {
|
||||
if (it == true) refresh()
|
||||
if (it == true) refresh(false)
|
||||
}
|
||||
|
||||
refresh()
|
||||
refresh(false)
|
||||
}
|
||||
|
||||
fun paypalPressed() = OpenLinkEvent(Const.Url.PAYPAL_URL).publish()
|
||||
@@ -135,7 +135,7 @@ class HomeViewModel(
|
||||
fun safetyNetPressed() {
|
||||
ctsState.value = SafetyNetState.LOADING
|
||||
basicIntegrityState.value = SafetyNetState.LOADING
|
||||
safetyNetTitle.value = R.string.checking_safetyNet_status
|
||||
safetyNetTitle.value = R.string.checking_safetyNet_status.res()
|
||||
|
||||
UpdateSafetyNetEvent().publish()
|
||||
}
|
||||
@@ -144,7 +144,7 @@ class HomeViewModel(
|
||||
response and 0x0F == 0 -> {
|
||||
val hasCtsPassed = response and SafetyNetHelper.CTS_PASS != 0
|
||||
val hasBasicIntegrityPassed = response and SafetyNetHelper.BASIC_PASS != 0
|
||||
safetyNetTitle.value = R.string.safetyNet_check_success
|
||||
safetyNetTitle.value = R.string.safetyNet_check_success.res()
|
||||
ctsState.value = if (hasCtsPassed) {
|
||||
SafetyNetState.PASS
|
||||
} else {
|
||||
@@ -164,13 +164,17 @@ class HomeViewModel(
|
||||
ctsState.value = SafetyNetState.IDLE
|
||||
basicIntegrityState.value = SafetyNetState.IDLE
|
||||
safetyNetTitle.value = when (response) {
|
||||
SafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid
|
||||
else -> R.string.safetyNet_api_error
|
||||
SafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid.res()
|
||||
else -> R.string.safetyNet_api_error.res()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
@JvmOverloads
|
||||
fun refresh(invalidate: Boolean = true) {
|
||||
if (invalidate)
|
||||
Info.envRef.invalidate()
|
||||
|
||||
hasRoot.value = Shell.rootAccess()
|
||||
|
||||
val fetchUpdate = if (isConnected.value)
|
||||
@@ -179,7 +183,8 @@ class HomeViewModel(
|
||||
Completable.complete()
|
||||
|
||||
Completable.fromAction {
|
||||
Info.loadMagiskInfo()
|
||||
// Ensure value is ready
|
||||
Info.env
|
||||
}.andThen(fetchUpdate)
|
||||
.applyViewModel(this)
|
||||
.doOnSubscribeUi {
|
||||
@@ -187,7 +192,7 @@ class HomeViewModel(
|
||||
_managerState.value = MagiskState.LOADING
|
||||
ctsState.value = SafetyNetState.IDLE
|
||||
basicIntegrityState.value = SafetyNetState.IDLE
|
||||
safetyNetTitle.value = R.string.safetyNet_check_text
|
||||
safetyNetTitle.value = R.string.safetyNet_check_text.res()
|
||||
}.subscribeK {
|
||||
updateSelf()
|
||||
ensureEnv()
|
||||
@@ -197,33 +202,40 @@ class HomeViewModel(
|
||||
|
||||
private fun refreshVersions() {
|
||||
magiskCurrentVersion.value = if (magiskState.value != MagiskState.NOT_INSTALLED) {
|
||||
version.format(Info.magiskVersionString, Info.magiskVersionCode)
|
||||
VERSION_FMT.format(Info.env.magiskVersionString, Info.env.magiskVersionCode)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
managerCurrentVersion.value = version
|
||||
.format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
|
||||
managerCurrentVersion.value = if (isRunningAsStub) MGR_VER_FMT
|
||||
.format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, Info.stub!!.version)
|
||||
else
|
||||
VERSION_FMT.format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
|
||||
}
|
||||
|
||||
private fun updateSelf() {
|
||||
magiskState.value = when (Info.magiskVersionCode) {
|
||||
in Int.MIN_VALUE until 0 -> MagiskState.NOT_INSTALLED
|
||||
!in Info.remote.magisk.versionCode..Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
magiskState.value = when (Info.env.magiskVersionCode) {
|
||||
in Int.MIN_VALUE .. 0 -> MagiskState.NOT_INSTALLED
|
||||
in 1 until Info.remote.magisk.versionCode -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
}
|
||||
|
||||
magiskLatestVersion.value = version
|
||||
.format(Info.remote.magisk.version, Info.remote.magisk.versionCode)
|
||||
magiskLatestVersion.value =
|
||||
VERSION_FMT.format(Info.remote.magisk.version, Info.remote.magisk.versionCode)
|
||||
|
||||
_managerState.value = when (Info.remote.app.versionCode) {
|
||||
in Int.MIN_VALUE until 0 -> MagiskState.NOT_INSTALLED //wrong update channel
|
||||
in (BuildConfig.VERSION_CODE + 1)..Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
else -> MagiskState.UP_TO_DATE
|
||||
in Int.MIN_VALUE .. 0 -> MagiskState.NOT_INSTALLED //wrong update channel
|
||||
in (BuildConfig.VERSION_CODE + 1) .. Int.MAX_VALUE -> MagiskState.OBSOLETE
|
||||
else -> {
|
||||
if (Info.stub?.version ?: Int.MAX_VALUE < Info.remote.stub.versionCode)
|
||||
MagiskState.OBSOLETE
|
||||
else
|
||||
MagiskState.UP_TO_DATE
|
||||
}
|
||||
}
|
||||
|
||||
managerLatestVersion.value = version
|
||||
.format(Info.remote.app.version, Info.remote.app.versionCode)
|
||||
managerLatestVersion.value = MGR_VER_FMT
|
||||
.format(Info.remote.app.version, Info.remote.app.versionCode, Info.remote.stub.versionCode)
|
||||
}
|
||||
|
||||
private fun ensureEnv() {
|
||||
@@ -240,7 +252,8 @@ class HomeViewModel(
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val version = "%s (%d)"
|
||||
private const val VERSION_FMT = "%s (%d)"
|
||||
private const val MGR_VER_FMT = "%s (%d) (%d)"
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -8,12 +8,12 @@ import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.base.BaseFragment
|
||||
import com.topjohnwu.magisk.databinding.FragmentModulesBinding
|
||||
import com.topjohnwu.magisk.extensions.reboot
|
||||
import com.topjohnwu.magisk.intent
|
||||
import com.topjohnwu.magisk.model.events.OpenFilePickerEvent
|
||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
||||
import com.topjohnwu.magisk.ui.flash.FlashActivity
|
||||
@@ -28,7 +28,7 @@ class ModulesFragment : BaseFragment<ModuleViewModel, FragmentModulesBinding>()
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
|
||||
// Get the URI of the selected file
|
||||
val intent = Intent(activity, ClassMap[FlashActivity::class.java])
|
||||
val intent = activity.intent(FlashActivity::class.java)
|
||||
intent.setData(data.data).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
@@ -13,20 +13,16 @@ import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceCategory
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.base.BasePreferenceFragment
|
||||
import com.topjohnwu.magisk.data.database.RepoDao
|
||||
import com.topjohnwu.magisk.databinding.CustomDownloadDialogBinding
|
||||
import com.topjohnwu.magisk.databinding.DialogCustomNameBinding
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.extensions.toLangTag
|
||||
import com.topjohnwu.magisk.model.download.DownloadService
|
||||
import com.topjohnwu.magisk.model.entity.internal.Configuration
|
||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||
import com.topjohnwu.magisk.model.observer.Observer
|
||||
import com.topjohnwu.magisk.net.Networking
|
||||
import com.topjohnwu.magisk.utils.*
|
||||
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -56,6 +52,7 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
preferenceManager.setStorageDeviceProtected()
|
||||
setPreferencesFromResource(R.xml.app_settings, rootKey)
|
||||
|
||||
// Get preferences
|
||||
updateChannel = findPreference(Config.Key.UPDATE_CHANNEL)!!
|
||||
rootConfig = findPreference(Config.Key.ROOT_ACCESS)!!
|
||||
autoRes = findPreference(Config.Key.SU_AUTO_RESPONSE)!!
|
||||
@@ -69,17 +66,68 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
val magiskCategory = findPreference<PreferenceCategory>("magisk")!!
|
||||
val suCategory = findPreference<PreferenceCategory>("superuser")!!
|
||||
val hideManager = findPreference<Preference>("hide")!!
|
||||
hideManager.setOnPreferenceClickListener {
|
||||
PatchAPK.hideManager(requireContext())
|
||||
true
|
||||
val restoreManager = findPreference<Preference>("restore")!!
|
||||
|
||||
// Remove/Disable entries
|
||||
|
||||
// Only show canary channels if user is already on canary channel
|
||||
// or the user have already chosen canary channel
|
||||
if (!Utils.isCanary && Config.updateChannel < Config.Value.CANARY_CHANNEL) {
|
||||
// Remove the last 2 entries
|
||||
val entries = updateChannel.entries
|
||||
updateChannel.entries = entries.copyOf(entries.size - 2)
|
||||
}
|
||||
val restoreManager = findPreference<Preference>("restore")
|
||||
restoreManager?.setOnPreferenceClickListener {
|
||||
DownloadService(requireContext()) {
|
||||
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
||||
|
||||
// Remove dangerous settings in secondary user
|
||||
if (Const.USER_ID > 0) {
|
||||
suCategory.removePreference(multiuserConfig)
|
||||
}
|
||||
|
||||
// Remove re-authentication option on Android O, it will not work
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
suCategory.removePreference(reauth)
|
||||
}
|
||||
|
||||
// Disable fingerprint option if not possible
|
||||
if (!FingerprintHelper.canUseFingerprint()) {
|
||||
fingerprint.isEnabled = false
|
||||
fingerprint.isChecked = false
|
||||
fingerprint.setSummary(R.string.disable_fingerprint)
|
||||
}
|
||||
|
||||
if (Const.USER_ID == 0 && Info.isConnected.value && Shell.rootAccess()) {
|
||||
if (activity.packageName == BuildConfig.APPLICATION_ID) {
|
||||
generalCatagory.removePreference(restoreManager)
|
||||
hideManager.setOnPreferenceClickListener {
|
||||
showManagerNameDialog {
|
||||
PatchAPK.hideManager(requireContext(), it)
|
||||
}
|
||||
true
|
||||
}
|
||||
} else {
|
||||
generalCatagory.removePreference(hideManager)
|
||||
restoreManager.setOnPreferenceClickListener {
|
||||
DownloadService(requireContext()) {
|
||||
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
// Remove if not primary user, no connection, or no root
|
||||
generalCatagory.removePreference(restoreManager)
|
||||
generalCatagory.removePreference(hideManager)
|
||||
}
|
||||
|
||||
if (!Utils.showSuperUser()) {
|
||||
preferenceScreen.removePreference(suCategory)
|
||||
}
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
preferenceScreen.removePreference(magiskCategory)
|
||||
generalCatagory.removePreference(hideManager)
|
||||
}
|
||||
|
||||
findPreference<Preference>("clear")?.setOnPreferenceClickListener {
|
||||
Completable.fromAction { repoDB.clear() }.subscribeK {
|
||||
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT)
|
||||
@@ -123,58 +171,7 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
|
||||
setLocalePreference(findPreference(Config.Key.LOCALE)!!)
|
||||
|
||||
/* We only show canary channels if user is already on canary channel
|
||||
* or the user have already chosen canary channel */
|
||||
if (!Utils.isCanary && Config.updateChannel < Config.Value.CANARY_CHANNEL) {
|
||||
// Remove the last 2 entries
|
||||
val entries = updateChannel.entries
|
||||
updateChannel.entries = entries.copyOf(entries.size - 2)
|
||||
|
||||
}
|
||||
|
||||
setSummary()
|
||||
|
||||
// Disable dangerous settings in secondary user
|
||||
if (Const.USER_ID > 0) {
|
||||
suCategory.removePreference(multiuserConfig)
|
||||
}
|
||||
|
||||
// Disable re-authentication option on Android O, it will not work
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
reauth.isEnabled = false
|
||||
reauth.isChecked = false
|
||||
reauth.setSummary(R.string.android_o_not_support)
|
||||
}
|
||||
|
||||
// Disable fingerprint option if not possible
|
||||
if (!FingerprintHelper.canUseFingerprint()) {
|
||||
fingerprint.isEnabled = false
|
||||
fingerprint.isChecked = false
|
||||
fingerprint.setSummary(R.string.disable_fingerprint)
|
||||
}
|
||||
|
||||
if (Shell.rootAccess() && Const.USER_ID == 0) {
|
||||
if (activity.packageName == BuildConfig.APPLICATION_ID) {
|
||||
generalCatagory.removePreference(restoreManager)
|
||||
} else {
|
||||
if (!Networking.checkNetworkStatus(requireContext())) {
|
||||
generalCatagory.removePreference(restoreManager)
|
||||
}
|
||||
generalCatagory.removePreference(hideManager)
|
||||
}
|
||||
} else {
|
||||
generalCatagory.removePreference(restoreManager)
|
||||
generalCatagory.removePreference(hideManager)
|
||||
}
|
||||
|
||||
if (!Utils.showSuperUser()) {
|
||||
preferenceScreen.removePreference(suCategory)
|
||||
}
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
preferenceScreen.removePreference(magiskCategory)
|
||||
generalCatagory.removePreference(hideManager)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSharedPreferenceChanged(prefs: SharedPreferences, key: String) {
|
||||
@@ -201,7 +198,7 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
Shell.su("magiskhide --disable").submit()
|
||||
}
|
||||
Config.Key.LOCALE -> {
|
||||
LocaleManager.setLocale(activity.application)
|
||||
refreshLocale()
|
||||
activity.recreate()
|
||||
}
|
||||
Config.Key.CHECK_UPDATES -> Utils.scheduleUpdateCheck(activity)
|
||||
@@ -225,27 +222,12 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
|
||||
private fun setLocalePreference(lp: ListPreference) {
|
||||
lp.isEnabled = false
|
||||
availableLocales.map {
|
||||
val names = mutableListOf<String>()
|
||||
val values = mutableListOf<String>()
|
||||
|
||||
names.add(
|
||||
LocaleManager.getString(defaultLocale, R.string.system_default)
|
||||
)
|
||||
values.add("")
|
||||
|
||||
it.forEach { locale ->
|
||||
names.add(locale.getDisplayName(locale))
|
||||
values.add(locale.toLangTag())
|
||||
}
|
||||
|
||||
Pair(names.toTypedArray(), values.toTypedArray())
|
||||
}.subscribeK { (names, values) ->
|
||||
lp.isEnabled = true
|
||||
lp.entries = names
|
||||
lp.entryValues = values
|
||||
lp.summary = currentLocale.getDisplayName(currentLocale)
|
||||
}
|
||||
availableLocales.subscribeK { (names, values) ->
|
||||
lp.isEnabled = true
|
||||
lp.entries = names
|
||||
lp.entryValues = values
|
||||
lp.summary = currentLocale.getDisplayName(currentLocale)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setSummary(key: String) {
|
||||
@@ -297,8 +279,8 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.settings_update_custom)
|
||||
.setView(v)
|
||||
.setPositiveButton(R.string.ok) { _, _ -> onSuccess(url.text.toString()) }
|
||||
.setNegativeButton(R.string.close) { _, _ -> onCancel() }
|
||||
.setPositiveButton(android.R.string.ok) { _, _ -> onSuccess(url.text.toString()) }
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ -> onCancel() }
|
||||
.setOnCancelListener { onCancel() }
|
||||
.show()
|
||||
}
|
||||
@@ -322,11 +304,35 @@ class SettingsFragment : BasePreferenceFragment() {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.settings_download_path_title)
|
||||
.setView(binding.root)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
Utils.ensureDownloadPath(data.text.value)?.let { onSuccess(data.text.value) }
|
||||
?: Utils.toast(R.string.settings_download_path_error, Toast.LENGTH_SHORT)
|
||||
}
|
||||
.setNegativeButton(R.string.close, null)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun showManagerNameDialog(
|
||||
crossinline onSuccess: (String) -> Unit
|
||||
) {
|
||||
val data = ManagerNameData()
|
||||
val view = DialogCustomNameBinding
|
||||
.inflate(LayoutInflater.from(requireContext()))
|
||||
.also { it.data = data }
|
||||
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.settings_app_name)
|
||||
.setView(view.root)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
if (view.dialogNameInput.error.isNullOrBlank()) {
|
||||
onSuccess(data.name.value)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
inner class ManagerNameData {
|
||||
val name = KObservableField(resources.getString(R.string.re_app_name))
|
||||
}
|
||||
}
|
||||
|
@@ -42,6 +42,11 @@ class SuperuserViewModel(
|
||||
|
||||
init {
|
||||
rxBus.register<PolicyEnableEvent>()
|
||||
.filter {
|
||||
val isIgnored = it.item == ignoreNext
|
||||
if (isIgnored) ignoreNext = null
|
||||
!isIgnored
|
||||
}
|
||||
.subscribeK { togglePolicy(it.item, it.enable) }
|
||||
.add()
|
||||
rxBus.register<PolicyUpdateEvent>()
|
||||
@@ -84,8 +89,8 @@ class SuperuserViewModel(
|
||||
CustomAlertDialog(this)
|
||||
.setTitle(R.string.su_revoke_title)
|
||||
.setMessage(getString(R.string.su_revoke_msg, item.item.appName))
|
||||
.setPositiveButton(R.string.yes) { _, _ -> updateState() }
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setPositiveButton(android.R.string.yes) { _, _ -> updateState() }
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.setCancelable(true)
|
||||
.show()
|
||||
}
|
||||
@@ -144,4 +149,4 @@ class SuperuserViewModel(
|
||||
private fun deletePolicy(policy: MagiskPolicy) =
|
||||
policyDB.delete(policy.uid).andThen(Single.just(policy))
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.ui.surequest
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.Window
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.base.BaseActivity
|
||||
@@ -18,6 +17,7 @@ import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
open class SuRequestActivity : BaseActivity<SuRequestViewModel, ActivityRequestBinding>() {
|
||||
|
||||
override val layoutRes: Int = R.layout.activity_request
|
||||
override val themeRes: Int = R.style.MagiskTheme_SU
|
||||
override val viewModel: SuRequestViewModel by viewModel()
|
||||
|
||||
override fun onBackPressed() {
|
||||
@@ -30,19 +30,17 @@ open class SuRequestActivity : BaseActivity<SuRequestViewModel, ActivityRequestB
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val intent = intent
|
||||
val action = intent.action
|
||||
|
||||
if (TextUtils.equals(action, GeneralReceiver.REQUEST)) {
|
||||
if (!viewModel.handleRequest(intent))
|
||||
finish()
|
||||
return
|
||||
when (intent?.action) {
|
||||
GeneralReceiver.REQUEST -> {
|
||||
if (!viewModel.handleRequest(intent))
|
||||
finish()
|
||||
return
|
||||
}
|
||||
GeneralReceiver.LOG -> SuLogger.handleLogs(this, intent)
|
||||
GeneralReceiver.NOTIFY -> SuLogger.handleNotify(this, intent)
|
||||
}
|
||||
|
||||
if (TextUtils.equals(action, GeneralReceiver.LOG))
|
||||
SuLogger.handleLogs(intent)
|
||||
else if (TextUtils.equals(action, GeneralReceiver.NOTIFY))
|
||||
SuLogger.handleNotify(intent)
|
||||
|
||||
finish()
|
||||
}
|
||||
|
||||
|
22
app/src/main/java/com/topjohnwu/magisk/utils/CachedValue.kt
Normal file
22
app/src/main/java/com/topjohnwu/magisk/utils/CachedValue.kt
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
class CachedValue<T>(private val factory: () -> T) : Lazy<T> {
|
||||
|
||||
private var _val : T? = null
|
||||
|
||||
override val value: T
|
||||
get() {
|
||||
val local = _val
|
||||
return local ?: synchronized(this) {
|
||||
_val ?: factory().also { _val = it }
|
||||
}
|
||||
}
|
||||
|
||||
override fun isInitialized() = _val != null
|
||||
|
||||
fun invalidate() {
|
||||
synchronized(this) {
|
||||
_val = null
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager.widget.ViewPager
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.extensions.replaceRandomWithSpecial
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
@@ -220,4 +221,11 @@ fun getScrollPosition(view: RecyclerView) = (view.layoutManager as? LinearLayout
|
||||
@BindingAdapter("isEnabled")
|
||||
fun setEnabled(view: View, isEnabled: Boolean) {
|
||||
view.isEnabled = isEnabled
|
||||
}
|
||||
|
||||
@BindingAdapter("error")
|
||||
fun TextInputLayout.setErrorString(error: String) {
|
||||
val newError = error.let { if (it.isEmpty()) null else it }
|
||||
if (this.error == null && newError == null) return
|
||||
this.error = newError
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import dalvik.system.DexClassLoader
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
|
||||
@Suppress("FunctionName")
|
||||
inline fun <reified T> T.DynamicClassLoader(apk: File) = DynamicClassLoader(apk, T::class.java.classLoader)
|
||||
|
||||
class DynamicClassLoader(apk: File, parent: ClassLoader?)
|
||||
: DexClassLoader(apk.path, apk.parent, null, parent) {
|
||||
|
||||
private val base by lazy { Any::class.java.classLoader!! }
|
||||
|
||||
@Throws(ClassNotFoundException::class)
|
||||
override fun loadClass(name: String, resolve: Boolean) : Class<*>
|
||||
= findLoadedClass(name) ?: runCatching {
|
||||
base.loadClass(name)
|
||||
}.getOrElse {
|
||||
runCatching {
|
||||
findClass(name)
|
||||
}.getOrElse { err ->
|
||||
runCatching {
|
||||
parent.loadClass(name)
|
||||
}.getOrElse { throw err }
|
||||
}
|
||||
}
|
||||
|
||||
override fun getResource(name: String) = base.getResource(name)
|
||||
?: findResource(name)
|
||||
?: parent?.getResource(name)
|
||||
|
||||
@Throws(IOException::class)
|
||||
override fun getResources(name: String): Enumeration<URL> {
|
||||
val resources = mutableListOf(
|
||||
base.getResources(name),
|
||||
findResources(name), parent.getResources(name))
|
||||
return object : Enumeration<URL> {
|
||||
override fun hasMoreElements(): Boolean {
|
||||
while (true) {
|
||||
if (resources.isEmpty())
|
||||
return false
|
||||
if (!resources[0].hasMoreElements()) {
|
||||
resources.removeAt(0)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun nextElement(): URL {
|
||||
if (!hasMoreElements())
|
||||
throw NoSuchElementException()
|
||||
return resources[0].nextElement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -9,15 +9,11 @@ import java.io.Serializable
|
||||
* You can define if wrapped type is Nullable or not.
|
||||
* You can use kotlin get/set syntax for value
|
||||
*/
|
||||
class KObservableField<T> : ObservableField<T>, Serializable {
|
||||
open class KObservableField<T> : ObservableField<T>, Serializable {
|
||||
|
||||
var value: T
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
notifyChange()
|
||||
}
|
||||
}
|
||||
get() = get()
|
||||
set(value) { set(value) }
|
||||
|
||||
constructor(init: T) {
|
||||
value = init
|
||||
@@ -27,23 +23,8 @@ class KObservableField<T> : ObservableField<T>, Serializable {
|
||||
value = init
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Needed for data binding, use KObservableField.value syntax from code",
|
||||
replaceWith = ReplaceWith("value")
|
||||
)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun get(): T {
|
||||
return value
|
||||
return super.get() as T
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
message = "Needed for data binding, use KObservableField.value = ... syntax from code",
|
||||
replaceWith = ReplaceWith("value = newValue")
|
||||
)
|
||||
override fun set(newValue: T) {
|
||||
value = newValue
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "KObservableField(value=$value)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
143
app/src/main/java/com/topjohnwu/magisk/utils/Keygen.kt
Normal file
143
app/src/main/java/com/topjohnwu/magisk/utils/Keygen.kt
Normal file
@@ -0,0 +1,143 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.util.Base64
|
||||
import android.util.Base64OutputStream
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.di.koinModules
|
||||
import com.topjohnwu.signing.CryptoUtils.readCertificate
|
||||
import com.topjohnwu.signing.CryptoUtils.readPrivateKey
|
||||
import com.topjohnwu.superuser.internal.InternalUtils
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
|
||||
import org.koin.core.context.GlobalContext
|
||||
import org.koin.core.context.startKoin
|
||||
import timber.log.Timber
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.math.BigInteger
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.KeyStore
|
||||
import java.security.MessageDigest
|
||||
import java.security.PrivateKey
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
private interface CertKeyProvider {
|
||||
val cert: X509Certificate
|
||||
val key: PrivateKey
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
class Keygen: CertKeyProvider {
|
||||
|
||||
companion object {
|
||||
private const val ALIAS = "magisk"
|
||||
private val PASSWORD get() = "magisk".toCharArray()
|
||||
private const val TESTKEY_CERT = "61ed377e85d386a8dfee6b864bd85b0bfaa5af81"
|
||||
private const val ALPHANUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
private const val BASE64_FLAG = Base64.NO_PADDING or Base64.NO_WRAP
|
||||
}
|
||||
|
||||
private val start = Calendar.getInstance()
|
||||
private val end = Calendar.getInstance().apply { add(Calendar.YEAR, 30) }
|
||||
|
||||
override val cert get() = provider.cert
|
||||
override val key get() = provider.key
|
||||
|
||||
private val provider: CertKeyProvider
|
||||
|
||||
inner class KeyStoreProvider : CertKeyProvider {
|
||||
private val ks by lazy { init() }
|
||||
override val cert by lazy { ks.getCertificate(ALIAS) as X509Certificate }
|
||||
override val key by lazy { ks.getKey(ALIAS, PASSWORD) as PrivateKey }
|
||||
}
|
||||
|
||||
class TestProvider : CertKeyProvider {
|
||||
override val cert by lazy {
|
||||
readCertificate(javaClass.getResourceAsStream("/keys/testkey.x509.pem"))
|
||||
}
|
||||
override val key by lazy {
|
||||
readPrivateKey(javaClass.getResourceAsStream("/keys/testkey.pk8"))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// This object could possibly be accessed from an external app
|
||||
// Get context from reflection into Android's framework
|
||||
val context = InternalUtils.getContext()
|
||||
val pm = context.packageManager
|
||||
val info = pm.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)
|
||||
val sig = info.signatures[0]
|
||||
val digest = MessageDigest.getInstance("SHA1")
|
||||
val chksum = digest.digest(sig.toByteArray())
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (b in chksum) {
|
||||
sb.append("%02x".format(0xFF and b.toInt()))
|
||||
}
|
||||
|
||||
provider = if (sb.toString() == TESTKEY_CERT) {
|
||||
// The app was signed by the test key, continue to use it (legacy mode)
|
||||
TestProvider()
|
||||
} else {
|
||||
KeyStoreProvider()
|
||||
}
|
||||
}
|
||||
|
||||
private fun randomString(): String {
|
||||
val rand = kotlin.random.Random.Default
|
||||
val len = rand.nextInt(5, 10)
|
||||
val sb = StringBuilder(len)
|
||||
for (i in 0..len) {
|
||||
val idx = rand.nextInt(ALPHANUM.length)
|
||||
sb.append(ALPHANUM[idx])
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
private fun init(): KeyStore {
|
||||
GlobalContext.getOrNull() ?: {
|
||||
// Invoked externally, do some basic initialization
|
||||
startKoin {
|
||||
modules(koinModules)
|
||||
}
|
||||
Timber.plant(Timber.DebugTree())
|
||||
}()
|
||||
|
||||
val raw = Config.keyStoreRaw
|
||||
val ks = KeyStore.getInstance("PKCS12")
|
||||
if (raw.isEmpty()) {
|
||||
ks.load(null)
|
||||
} else {
|
||||
GZIPInputStream(Base64.decode(raw, BASE64_FLAG).inputStream()).use {
|
||||
ks.load(it, PASSWORD)
|
||||
}
|
||||
}
|
||||
|
||||
// Keys already exist
|
||||
if (ks.containsAlias(ALIAS))
|
||||
return ks
|
||||
|
||||
// Generate new private key and certificate
|
||||
val kp = KeyPairGenerator.getInstance("RSA").apply { initialize(4096) }.genKeyPair()
|
||||
val dname = X500Name("CN=${randomString()}")
|
||||
val builder = JcaX509v3CertificateBuilder(dname, BigInteger(160, Random()),
|
||||
start.time, end.time, dname, kp.public)
|
||||
val signer = JcaContentSignerBuilder("SHA256WithRSA").build(kp.private)
|
||||
val cert = JcaX509CertificateConverter().getCertificate(builder.build(signer))
|
||||
|
||||
// Store them into keystore
|
||||
ks.setKeyEntry(ALIAS, kp.private, PASSWORD, arrayOf(cert))
|
||||
val bytes = ByteArrayOutputStream()
|
||||
GZIPOutputStream(Base64OutputStream(bytes, BASE64_FLAG)).use {
|
||||
ks.store(it, PASSWORD)
|
||||
}
|
||||
Config.keyStoreRaw = bytes.toString("UTF-8")
|
||||
|
||||
return ks
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.StringRes
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.extensions.inject
|
||||
import com.topjohnwu.magisk.extensions.langTagToLocale
|
||||
import com.topjohnwu.superuser.internal.InternalUtils
|
||||
import io.reactivex.Single
|
||||
import java.util.*
|
||||
|
||||
var currentLocale = Locale.getDefault()!!
|
||||
private set
|
||||
|
||||
val defaultLocale = Locale.getDefault()!!
|
||||
|
||||
val availableLocales = Single.fromCallable {
|
||||
val compareId = R.string.app_changelog
|
||||
val res: Resources by inject()
|
||||
mutableListOf<Locale>().apply {
|
||||
// Add default locale
|
||||
add(Locale.ENGLISH)
|
||||
|
||||
// Add some special locales
|
||||
add(Locale.TAIWAN)
|
||||
add(Locale("pt", "BR"))
|
||||
|
||||
// Other locales
|
||||
val otherLocales = res.assets.locales
|
||||
.map { it.langTagToLocale() }
|
||||
.distinctBy { LocaleManager.getString(it, compareId) }
|
||||
|
||||
listOf("", "").toTypedArray()
|
||||
|
||||
addAll(otherLocales)
|
||||
}.sortedWith(Comparator { a, b ->
|
||||
a.getDisplayName(a).toLowerCase(a)
|
||||
.compareTo(b.getDisplayName(b).toLowerCase(b))
|
||||
})
|
||||
}.cache()!!
|
||||
|
||||
object LocaleManager {
|
||||
|
||||
fun setLocale(wrapper: ContextWrapper) {
|
||||
val localeConfig = Config.locale
|
||||
currentLocale = when {
|
||||
localeConfig.isEmpty() -> defaultLocale
|
||||
else -> localeConfig.langTagToLocale()
|
||||
}
|
||||
Locale.setDefault(currentLocale)
|
||||
InternalUtils.replaceBaseContext(wrapper, getLocaleContext(wrapper, currentLocale))
|
||||
}
|
||||
|
||||
fun getLocaleContext(context: Context, locale: Locale = currentLocale): Context {
|
||||
val config = Configuration(context.resources.configuration)
|
||||
config.setLocale(locale)
|
||||
return context.createConfigurationContext(config)
|
||||
}
|
||||
|
||||
fun getString(locale: Locale, @StringRes id: Int): String {
|
||||
return getLocaleContext(get(), locale).getString(id)
|
||||
}
|
||||
}
|
89
app/src/main/java/com/topjohnwu/magisk/utils/Locales.kt
Normal file
89
app/src/main/java/com/topjohnwu/magisk/utils/Locales.kt
Normal file
@@ -0,0 +1,89 @@
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.ResourceMgr
|
||||
import com.topjohnwu.magisk.extensions.langTagToLocale
|
||||
import com.topjohnwu.magisk.extensions.toLangTag
|
||||
import io.reactivex.Single
|
||||
import java.util.*
|
||||
import kotlin.Comparator
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
var currentLocale: Locale = Locale.getDefault()
|
||||
|
||||
@SuppressLint("ConstantLocale")
|
||||
val defaultLocale: Locale = Locale.getDefault()
|
||||
|
||||
val availableLocales = Single.fromCallable {
|
||||
val compareId = R.string.app_changelog
|
||||
val config = ResourceMgr.resource.configuration
|
||||
val metrics = ResourceMgr.resource.displayMetrics
|
||||
val res = Resources(ResourceMgr.resource.assets, metrics, config)
|
||||
|
||||
val locales = mutableListOf<Locale>().apply {
|
||||
// Add default locale
|
||||
add(Locale.ENGLISH)
|
||||
|
||||
// Add some special locales
|
||||
add(Locale.TAIWAN)
|
||||
add(Locale("pt", "BR"))
|
||||
|
||||
// Other locales
|
||||
val otherLocales = ResourceMgr.resource.assets.locales
|
||||
.map { it.langTagToLocale() }
|
||||
.distinctBy {
|
||||
config.setLocale(it)
|
||||
res.updateConfiguration(config, metrics)
|
||||
res.getString(compareId)
|
||||
}
|
||||
|
||||
addAll(otherLocales)
|
||||
}.sortedWith(Comparator { a, b ->
|
||||
a.getDisplayName(a).toLowerCase(a)
|
||||
.compareTo(b.getDisplayName(b).toLowerCase(b))
|
||||
})
|
||||
|
||||
config.setLocale(defaultLocale)
|
||||
res.updateConfiguration(config, metrics)
|
||||
val defName = res.getString(R.string.system_default)
|
||||
|
||||
// Restore back to current locale
|
||||
config.setLocale(currentLocale)
|
||||
res.updateConfiguration(config, metrics)
|
||||
|
||||
Pair(locales, defName)
|
||||
}.map { (locales, defName) ->
|
||||
val names = ArrayList<String>(locales.size + 1)
|
||||
val values = ArrayList<String>(locales.size + 1)
|
||||
|
||||
names.add(defName)
|
||||
values.add("")
|
||||
|
||||
locales.forEach { locale ->
|
||||
names.add(locale.getDisplayName(locale))
|
||||
values.add(locale.toLangTag())
|
||||
}
|
||||
|
||||
Pair(names.toTypedArray(), values.toTypedArray())
|
||||
}.cache()!!
|
||||
|
||||
fun Resources.updateConfig(config: Configuration = configuration) {
|
||||
config.setLocale(currentLocale)
|
||||
updateConfiguration(config, displayMetrics)
|
||||
}
|
||||
|
||||
fun refreshLocale() {
|
||||
val localeConfig = Config.locale
|
||||
currentLocale = when {
|
||||
localeConfig.isEmpty() -> defaultLocale
|
||||
else -> localeConfig.langTagToLocale()
|
||||
}
|
||||
Locale.setDefault(currentLocale)
|
||||
ResourceMgr.resource.updateConfig()
|
||||
}
|
@@ -1,11 +1,14 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.extensions.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.extensions.subscribeK
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
import com.topjohnwu.magisk.extensions.writeTo
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.signing.JarMap
|
||||
import com.topjohnwu.signing.SignAPK
|
||||
@@ -47,81 +50,86 @@ object PatchAPK {
|
||||
}
|
||||
|
||||
private fun findAndPatch(xml: ByteArray, from: String, to: String): Boolean {
|
||||
if (from.length != to.length)
|
||||
if (to.length > from.length)
|
||||
return false
|
||||
val buf = ByteBuffer.wrap(xml).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer()
|
||||
val offList = mutableListOf<Int>()
|
||||
var i = 0
|
||||
while (i < buf.length - from.length) {
|
||||
var match = true
|
||||
for (j in 0 until from.length) {
|
||||
loop@ while (i < buf.length - from.length) {
|
||||
for (j in from.indices) {
|
||||
if (buf.get(i + j) != from[j]) {
|
||||
match = false
|
||||
break
|
||||
++i
|
||||
continue@loop
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
offList.add(i)
|
||||
i += from.length
|
||||
}
|
||||
++i
|
||||
offList.add(i)
|
||||
i += from.length
|
||||
}
|
||||
if (offList.isEmpty())
|
||||
return false
|
||||
|
||||
val toBuf = to.toCharArray().copyOf(from.length)
|
||||
for (off in offList) {
|
||||
buf.position(off)
|
||||
buf.put(to)
|
||||
buf.put(toBuf)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun findAndPatch(xml: ByteArray, a: Int, b: Int): Boolean {
|
||||
val buf = ByteBuffer.wrap(xml).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
|
||||
val len = xml.size / 4
|
||||
for (i in 0 until len) {
|
||||
if (buf.get(i) == a) {
|
||||
buf.put(i, b)
|
||||
return true
|
||||
private fun patchAndHide(context: Context, label: String): Boolean {
|
||||
// If not running as stub, and we are compatible with stub, use stub
|
||||
val src = if (!isRunningAsStub && SDK_INT >= 28 && Info.env.connectionMode == 3) {
|
||||
val stub = File(context.cacheDir, "stub.apk")
|
||||
val svc = get<GithubRawServices>()
|
||||
runCatching {
|
||||
svc.fetchFile(Info.remote.stub.link).blockingGet().byteStream().use {
|
||||
it.writeTo(stub)
|
||||
}
|
||||
}.onFailure {
|
||||
Timber.e(it)
|
||||
return false
|
||||
}
|
||||
stub.path
|
||||
} else {
|
||||
context.packageCodePath
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun patchAndHide(context: Context): Boolean {
|
||||
// Generate a new app with random package name
|
||||
val repack = File(context.filesDir, "patched.apk")
|
||||
// Generate a new random package name and signature
|
||||
val repack = File(context.cacheDir, "patched.apk")
|
||||
val pkg = genPackageName("com.", BuildConfig.APPLICATION_ID.length)
|
||||
Config.keyStoreRaw = ""
|
||||
|
||||
if (!patch(context.packageCodePath, repack.path, pkg))
|
||||
if (!patch(src, repack.path, pkg, label))
|
||||
return false
|
||||
|
||||
// Install the application
|
||||
repack.setReadable(true, false)
|
||||
if (!Shell.su("pm install $repack").exec().isSuccess)
|
||||
if (!Shell.su("force_pm_install $repack").exec().isSuccess)
|
||||
return false
|
||||
|
||||
Config.suManager = pkg
|
||||
Config.export()
|
||||
RootUtils.rmAndLaunch(BuildConfig.APPLICATION_ID,
|
||||
ComponentName(pkg, ClassMap.get<Class<*>>(SplashActivity::class.java).name))
|
||||
Shell.su("pm uninstall ${BuildConfig.APPLICATION_ID}").submit()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun patch(apk: String, out: String, pkg: String): Boolean {
|
||||
@JvmOverloads
|
||||
fun patch(apk: String, out: String, pkg: String, label: String = "Manager"): Boolean {
|
||||
try {
|
||||
val jar = JarMap(apk)
|
||||
val je = jar.getJarEntry(Const.ANDROID_MANIFEST)
|
||||
val xml = jar.getRawData(je)
|
||||
|
||||
if (!findAndPatch(xml, BuildConfig.APPLICATION_ID, pkg) ||
|
||||
!findAndPatch(xml, R.string.app_name, R.string.re_app_name))
|
||||
!findAndPatch(xml, "Magisk Manager", label))
|
||||
return false
|
||||
|
||||
// Write apk changes
|
||||
jar.getOutputStream(je).write(xml)
|
||||
SignAPK.sign(jar, FileOutputStream(out).buffered())
|
||||
val keys = Keygen()
|
||||
SignAPK.sign(keys.cert, keys.key, jar, FileOutputStream(out).buffered())
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
@@ -130,11 +138,36 @@ object PatchAPK {
|
||||
return true
|
||||
}
|
||||
|
||||
fun hideManager(context: Context) {
|
||||
fun patch(apk: File, out: File, pkg: String, label: String): Boolean {
|
||||
try {
|
||||
if (apk.length() < 1 shl 18) {
|
||||
// APK is smaller than 256K, must be stub
|
||||
return patch(apk.path, out.path, pkg, label)
|
||||
}
|
||||
|
||||
// Try using the new APK to patch itself
|
||||
val loader = DynamicClassLoader(apk)
|
||||
val cls = loader.loadClass("a.a")
|
||||
|
||||
for (m in cls.declaredMethods) {
|
||||
val pars = m.parameterTypes
|
||||
if (pars.size == 4 && pars[0] == String::class.java) {
|
||||
return m.invoke(null, apk.path, out.path, pkg, label) as Boolean
|
||||
}
|
||||
}
|
||||
throw Exception("No matching method found")
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
// Fallback to use the current implementation
|
||||
return patch(apk.path, out.path, pkg, label)
|
||||
}
|
||||
}
|
||||
|
||||
fun hideManager(context: Context, label: String) {
|
||||
Completable.fromAction {
|
||||
val progress = Notifications.progress(context, context.getString(R.string.hide_manager_title))
|
||||
Notifications.mgr.notify(Const.ID.HIDE_MANAGER_NOTIFICATION_ID, progress.build())
|
||||
if (!patchAndHide(context))
|
||||
if (!patchAndHide(context, label))
|
||||
Utils.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG)
|
||||
Notifications.mgr.cancel(Const.ID.HIDE_MANAGER_NOTIFICATION_ID)
|
||||
}.subscribeK()
|
||||
|
44
app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt
Normal file
44
app/src/main/java/com/topjohnwu/magisk/utils/RootInit.kt
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.Context
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.Info
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.extensions.rawResource
|
||||
import com.topjohnwu.magisk.wrap
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
|
||||
class RootInit : Shell.Initializer() {
|
||||
|
||||
override fun onInit(context: Context, shell: Shell): Boolean {
|
||||
return init(context.wrap(), shell)
|
||||
}
|
||||
|
||||
fun init(context: Context, shell: Shell): Boolean {
|
||||
// Invalidate env state if shell is recreated
|
||||
Info.envRef.invalidate()
|
||||
|
||||
val job = shell.newJob()
|
||||
if (shell.isRoot) {
|
||||
job.add(context.rawResource(R.raw.util_functions))
|
||||
.add(context.rawResource(R.raw.utils))
|
||||
Const.MAGISK_DISABLE_FILE = SuFile("/cache/.disable_magisk")
|
||||
} else {
|
||||
job.add(context.rawResource(R.raw.nonroot_utils))
|
||||
}
|
||||
|
||||
job.add("mount_partitions",
|
||||
"get_flags",
|
||||
"run_migrations",
|
||||
"export BOOTMODE=true")
|
||||
.exec()
|
||||
|
||||
Info.keepVerity = ShellUtils.fastCmd("echo \$KEEPVERITY").toBoolean()
|
||||
Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean()
|
||||
Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean()
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
@@ -1,158 +0,0 @@
|
||||
package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.Info
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.extensions.rawResource
|
||||
import com.topjohnwu.magisk.extensions.toShellCmd
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import java.util.*
|
||||
import java.lang.reflect.Array as RArray
|
||||
|
||||
fun Intent.toCommand(args: MutableList<String>) {
|
||||
if (action != null) {
|
||||
args.add("-a")
|
||||
args.add(action!!)
|
||||
}
|
||||
if (component != null) {
|
||||
args.add("-n")
|
||||
args.add(component!!.flattenToString())
|
||||
}
|
||||
if (data != null) {
|
||||
args.add("-d")
|
||||
args.add(dataString!!)
|
||||
}
|
||||
if (categories != null) {
|
||||
for (cat in categories) {
|
||||
args.add("-c")
|
||||
args.add(cat)
|
||||
}
|
||||
}
|
||||
if (type != null) {
|
||||
args.add("-t")
|
||||
args.add(type!!)
|
||||
}
|
||||
val extras = extras
|
||||
if (extras != null) {
|
||||
loop@ for (key in extras.keySet()) {
|
||||
val v = extras.get(key) ?: continue
|
||||
var value: Any = v
|
||||
val arg: String
|
||||
when {
|
||||
v is String -> arg = "--es"
|
||||
v is Boolean -> arg = "--ez"
|
||||
v is Int -> arg = "--ei"
|
||||
v is Long -> arg = "--el"
|
||||
v is Float -> arg = "--ef"
|
||||
v is Uri -> arg = "--eu"
|
||||
v is ComponentName -> {
|
||||
arg = "--ecn"
|
||||
value = v.flattenToString()
|
||||
}
|
||||
v is ArrayList<*> -> {
|
||||
if (v.size <= 0)
|
||||
/* Impossible to know the type due to type erasure */
|
||||
continue@loop
|
||||
|
||||
arg = if (v[0] is Int)
|
||||
"--eial"
|
||||
else if (v[0] is Long)
|
||||
"--elal"
|
||||
else if (v[0] is Float)
|
||||
"--efal"
|
||||
else if (v[0] is String)
|
||||
"--esal"
|
||||
else
|
||||
continue@loop /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
for (o in v) {
|
||||
sb.append(o.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
}
|
||||
v.javaClass.isArray -> {
|
||||
arg = if (v is IntArray)
|
||||
"--eia"
|
||||
else if (v is LongArray)
|
||||
"--ela"
|
||||
else if (v is FloatArray)
|
||||
"--efa"
|
||||
else if (v is Array<*> && v.isArrayOf<String>())
|
||||
"--esa"
|
||||
else
|
||||
continue@loop /* Unsupported */
|
||||
|
||||
val sb = StringBuilder()
|
||||
val len = RArray.getLength(v)
|
||||
for (i in 0 until len) {
|
||||
sb.append(RArray.get(v, i)!!.toString().replace(",", "\\,"))
|
||||
sb.append(',')
|
||||
}
|
||||
// Remove trailing comma
|
||||
sb.deleteCharAt(sb.length - 1)
|
||||
value = sb
|
||||
}
|
||||
else -> continue@loop
|
||||
} /* Unsupported */
|
||||
|
||||
args.add(arg)
|
||||
args.add(key)
|
||||
args.add(value.toString())
|
||||
}
|
||||
}
|
||||
args.add("-f")
|
||||
args.add(flags.toString())
|
||||
}
|
||||
|
||||
fun startActivity(intent: Intent) {
|
||||
if (intent.component == null)
|
||||
return
|
||||
val args = ArrayList<String>()
|
||||
args.add("am")
|
||||
args.add("start")
|
||||
intent.toCommand(args)
|
||||
Shell.su(args.toShellCmd()).exec()
|
||||
}
|
||||
|
||||
class RootUtils : Shell.Initializer() {
|
||||
|
||||
override fun onInit(context: Context, shell: Shell): Boolean {
|
||||
val job = shell.newJob()
|
||||
if (shell.isRoot) {
|
||||
job.add(context.rawResource(R.raw.util_functions))
|
||||
.add(context.rawResource(R.raw.utils))
|
||||
Const.MAGISK_DISABLE_FILE = SuFile("/cache/.disable_magisk")
|
||||
Info.loadMagiskInfo()
|
||||
} else {
|
||||
job.add(context.rawResource(R.raw.nonroot_utils))
|
||||
}
|
||||
|
||||
job.add("mount_partitions",
|
||||
"get_flags",
|
||||
"run_migrations",
|
||||
"export BOOTMODE=true")
|
||||
.exec()
|
||||
|
||||
Info.keepVerity = ShellUtils.fastCmd("echo \$KEEPVERITY").toBoolean()
|
||||
Info.keepEnc = ShellUtils.fastCmd("echo \$KEEPFORCEENCRYPT").toBoolean()
|
||||
Info.recovery = ShellUtils.fastCmd("echo \$RECOVERYMODE").toBoolean()
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun rmAndLaunch(rm: String, component: ComponentName) {
|
||||
Shell.su("(rm_launch $rm ${component.flattenToString()})").exec()
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,14 +2,13 @@ package com.topjohnwu.magisk.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Process
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.database.PolicyDao
|
||||
import com.topjohnwu.magisk.data.repository.LogRepository
|
||||
import com.topjohnwu.magisk.extensions.inject
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.model.entity.MagiskPolicy
|
||||
import com.topjohnwu.magisk.model.entity.toLog
|
||||
import com.topjohnwu.magisk.model.entity.toPolicy
|
||||
@@ -17,15 +16,13 @@ import java.util.*
|
||||
|
||||
object SuLogger {
|
||||
|
||||
private val context: Context by inject()
|
||||
|
||||
fun handleLogs(intent: Intent) {
|
||||
fun handleLogs(context: Context, intent: Intent) {
|
||||
|
||||
val fromUid = intent.getIntExtra("from.uid", -1)
|
||||
if (fromUid < 0) return
|
||||
if (fromUid == Process.myUid()) return
|
||||
|
||||
val pm: PackageManager by inject()
|
||||
val pm = context.packageManager
|
||||
|
||||
val notify: Boolean
|
||||
val data = intent.extras
|
||||
@@ -36,7 +33,7 @@ object SuLogger {
|
||||
}.getOrElse { return }
|
||||
} else {
|
||||
// Doesn't report whether notify or not, check database ourselves
|
||||
val policyDB: PolicyDao by inject()
|
||||
val policyDB = get<PolicyDao>()
|
||||
val policy = policyDB.fetch(fromUid).blockingGet() ?: return
|
||||
notify = policy.notification
|
||||
policy
|
||||
@@ -46,7 +43,7 @@ object SuLogger {
|
||||
return
|
||||
|
||||
if (notify)
|
||||
handleNotify(policy)
|
||||
handleNotify(context, policy)
|
||||
|
||||
val toUid = intent.getIntExtra("to.uid", -1)
|
||||
if (toUid < 0) return
|
||||
@@ -62,11 +59,11 @@ object SuLogger {
|
||||
date = Date()
|
||||
)
|
||||
|
||||
val logRepo: LogRepository by inject()
|
||||
val logRepo = get<LogRepository>()
|
||||
logRepo.put(log).blockingGet()?.printStackTrace()
|
||||
}
|
||||
|
||||
private fun handleNotify(policy: MagiskPolicy) {
|
||||
private fun handleNotify(context: Context, policy: MagiskPolicy) {
|
||||
if (policy.notification && Config.suNotification == Config.Value.NOTIFICATION_TOAST) {
|
||||
Utils.toast(
|
||||
context.getString(
|
||||
@@ -80,16 +77,16 @@ object SuLogger {
|
||||
}
|
||||
}
|
||||
|
||||
fun handleNotify(intent: Intent) {
|
||||
fun handleNotify(context: Context, intent: Intent) {
|
||||
val fromUid = intent.getIntExtra("from.uid", -1)
|
||||
if (fromUid < 0) return
|
||||
if (fromUid == Process.myUid()) return
|
||||
runCatching {
|
||||
val packageManager: PackageManager by inject()
|
||||
val policy = fromUid.toPolicy(packageManager)
|
||||
val pm = context.packageManager
|
||||
val policy = fromUid.toPolicy(pm)
|
||||
.copy(policy = intent.getIntExtra("policy", -1))
|
||||
if (policy.policy >= 0)
|
||||
handleNotify(policy)
|
||||
handleNotify(context, policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ object Utils {
|
||||
.setRequiresDeviceIdle(true)
|
||||
.build()
|
||||
val request = PeriodicWorkRequest
|
||||
.Builder(ClassMap[UpdateCheckService::class.java], 12, TimeUnit.HOURS)
|
||||
.Builder(ClassMap[UpdateCheckService::class.java] as Class<Worker>, 12, TimeUnit.HOURS)
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
|
||||
|
@@ -48,7 +48,7 @@ object MarkDownWindow : KoinComponent {
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(title)
|
||||
.setView(mv)
|
||||
.setNegativeButton(R.string.close) { dialog, _ -> dialog.dismiss() }
|
||||
.setNegativeButton(android.R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
@@ -1,100 +1,120 @@
|
||||
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.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import com.topjohnwu.magisk.ClassMap
|
||||
import com.topjohnwu.magisk.Const
|
||||
import com.topjohnwu.magisk.Info
|
||||
import com.topjohnwu.magisk.R
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.graphics.drawable.toIcon
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.Const.ID.UPDATE_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.extensions.get
|
||||
import com.topjohnwu.magisk.extensions.getBitmap
|
||||
import com.topjohnwu.magisk.model.receiver.GeneralReceiver
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
|
||||
object Notifications {
|
||||
|
||||
val mgr by lazy { NotificationManagerCompat.from(get()) }
|
||||
val mgr by lazy { get<Context>().getSystemService<NotificationManager>()!! }
|
||||
|
||||
fun setup(context: Context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mgr.deleteNotificationChannel("magisk_notification")
|
||||
var channel = NotificationChannel(Const.ID.UPDATE_NOTIFICATION_CHANNEL,
|
||||
if (SDK_INT >= 26) {
|
||||
var channel = NotificationChannel(UPDATE_NOTIFICATION_CHANNEL,
|
||||
context.getString(R.string.update_channel), NotificationManager.IMPORTANCE_DEFAULT)
|
||||
mgr.createNotificationChannel(channel)
|
||||
channel = NotificationChannel(Const.ID.PROGRESS_NOTIFICATION_CHANNEL,
|
||||
channel = NotificationChannel(PROGRESS_NOTIFICATION_CHANNEL,
|
||||
context.getString(R.string.progress_channel), NotificationManager.IMPORTANCE_LOW)
|
||||
mgr.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBuilder(context: Context): Notification.Builder {
|
||||
return Notification.Builder(context).apply {
|
||||
val bitmap = context.getBitmap(R.drawable.ic_magisk_outline)
|
||||
setLargeIcon(bitmap)
|
||||
if (SDK_INT >= 26) {
|
||||
setSmallIcon(bitmap.toIcon())
|
||||
setChannelId(UPDATE_NOTIFICATION_CHANNEL)
|
||||
} else {
|
||||
setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
setVibrate(longArrayOf(0, 100, 100, 100))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun magiskUpdate(context: Context) {
|
||||
val intent = Intent(context, ClassMap[SplashActivity::class.java])
|
||||
intent.putExtra(Const.Key.OPEN_SECTION, "magisk")
|
||||
val intent = context.intent(SplashActivity::class.java)
|
||||
.putExtra(Const.Key.OPEN_SECTION, "magisk")
|
||||
val stackBuilder = TaskStackBuilder.create(context)
|
||||
stackBuilder.addParentStack(ClassMap.get<Class<*>>(SplashActivity::class.java))
|
||||
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 = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(context.getString(R.string.magisk_update_title))
|
||||
.setContentText(context.getString(R.string.manager_download_install))
|
||||
.setVibrate(longArrayOf(0, 100, 100, 100))
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
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 = Intent(context, ClassMap[GeneralReceiver::class.java])
|
||||
intent.action = Const.Key.BROADCAST_MANAGER_UPDATE
|
||||
intent.putExtra(Const.Key.INTENT_SET_APP, Info.remote.app)
|
||||
val intent = context.intent(GeneralReceiver::class.java)
|
||||
.setAction(Const.Key.BROADCAST_MANAGER_UPDATE)
|
||||
.putExtra(Const.Key.INTENT_SET_APP, Info.remote.app)
|
||||
|
||||
val pendingIntent = PendingIntent.getBroadcast(context,
|
||||
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(context.getString(R.string.manager_update_title))
|
||||
.setContentText(context.getString(R.string.manager_download_install))
|
||||
.setVibrate(longArrayOf(0, 100, 100, 100))
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
val builder = updateBuilder(context)
|
||||
.setContentTitle(context.getString(R.string.manager_update_title))
|
||||
.setContentText(context.getString(R.string.manager_download_install))
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent)
|
||||
|
||||
mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
||||
fun dtboPatched(context: Context) {
|
||||
val intent = Intent(context, ClassMap[GeneralReceiver::class.java])
|
||||
val intent = context.intent(GeneralReceiver::class.java)
|
||||
.setAction(Const.Key.BROADCAST_REBOOT)
|
||||
val pendingIntent = PendingIntent.getBroadcast(context,
|
||||
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
||||
val builder = NotificationCompat.Builder(context, Const.ID.UPDATE_NOTIFICATION_CHANNEL)
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(context.getString(R.string.dtbo_patched_title))
|
||||
.setContentText(context.getString(R.string.dtbo_patched_reboot))
|
||||
.setVibrate(longArrayOf(0, 100, 100, 100))
|
||||
.addAction(R.drawable.ic_refresh, context.getString(R.string.reboot), pendingIntent)
|
||||
val builder = updateBuilder(context)
|
||||
.setContentTitle(context.getString(R.string.dtbo_patched_title))
|
||||
.setContentText(context.getString(R.string.dtbo_patched_reboot))
|
||||
|
||||
if (SDK_INT >= 23) {
|
||||
val action = Notification.Action.Builder(
|
||||
context.getBitmap(R.drawable.ic_refresh).toIcon(),
|
||||
context.getString(R.string.reboot), pendingIntent).build()
|
||||
builder.addAction(action)
|
||||
} else {
|
||||
builder.addAction(
|
||||
R.drawable.ic_refresh,
|
||||
context.getString(R.string.reboot), pendingIntent)
|
||||
}
|
||||
|
||||
mgr.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build())
|
||||
}
|
||||
|
||||
fun progress(context: Context, title: CharSequence): NotificationCompat.Builder {
|
||||
val builder = NotificationCompat.Builder(context, Const.ID.PROGRESS_NOTIFICATION_CHANNEL)
|
||||
builder.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setContentTitle(title)
|
||||
.setProgress(0, 0, true)
|
||||
.setOngoing(true)
|
||||
fun progress(context: Context, title: CharSequence): Notification.Builder {
|
||||
val builder = if (SDK_INT >= 26) {
|
||||
Notification.Builder(context, PROGRESS_NOTIFICATION_CHANNEL)
|
||||
} else {
|
||||
Notification.Builder(context).setPriority(Notification.PRIORITY_LOW)
|
||||
}
|
||||
builder.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setContentTitle(title)
|
||||
.setProgress(0, 0, true)
|
||||
.setOngoing(true)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,10 @@ import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.graphics.drawable.toAdaptiveIcon
|
||||
import androidx.core.graphics.drawable.toIcon
|
||||
import com.topjohnwu.magisk.*
|
||||
import com.topjohnwu.magisk.extensions.getBitmap
|
||||
import com.topjohnwu.magisk.ui.SplashActivity
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -15,57 +18,82 @@ import com.topjohnwu.superuser.Shell
|
||||
object Shortcuts {
|
||||
|
||||
fun setup(context: Context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
if (Build.VERSION.SDK_INT >= 25) {
|
||||
val manager = context.getSystemService(ShortcutManager::class.java)
|
||||
manager?.dynamicShortcuts = getShortCuts(context)
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N_MR1)
|
||||
@RequiresApi(api = 25)
|
||||
private fun getShortCuts(context: Context): List<ShortcutInfo> {
|
||||
val shortCuts = mutableListOf<ShortcutInfo>()
|
||||
val root = Shell.rootAccess()
|
||||
val intent = context.intent(SplashActivity::class.java)
|
||||
|
||||
fun getIcon(id: Int): Icon {
|
||||
return if (Build.VERSION.SDK_INT >= 26)
|
||||
context.getBitmap(id).toAdaptiveIcon()
|
||||
else
|
||||
context.getBitmap(id).toIcon()
|
||||
}
|
||||
|
||||
if (Utils.showSuperUser()) {
|
||||
shortCuts.add(ShortcutInfo.Builder(context, "superuser")
|
||||
shortCuts.add(
|
||||
ShortcutInfo.Builder(context, "superuser")
|
||||
.setShortLabel(context.getString(R.string.superuser))
|
||||
.setIntent(Intent(context, ClassMap[SplashActivity::class.java])
|
||||
.setIntent(
|
||||
Intent(intent)
|
||||
.putExtra(Const.Key.OPEN_SECTION, "superuser")
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||
.setIcon(Icon.createWithResource(context, R.drawable.sc_superuser))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
)
|
||||
.setIcon(getIcon(R.drawable.sc_superuser))
|
||||
.setRank(0)
|
||||
.build())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
if (root && Config.magiskHide) {
|
||||
shortCuts.add(ShortcutInfo.Builder(context, "magiskhide")
|
||||
if (root && Info.env.magiskHide) {
|
||||
shortCuts.add(
|
||||
ShortcutInfo.Builder(context, "magiskhide")
|
||||
.setShortLabel(context.getString(R.string.magiskhide))
|
||||
.setIntent(Intent(context, ClassMap[SplashActivity::class.java])
|
||||
.setIntent(
|
||||
Intent(intent)
|
||||
.putExtra(Const.Key.OPEN_SECTION, "magiskhide")
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||
.setIcon(Icon.createWithResource(context, R.drawable.sc_magiskhide))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
)
|
||||
.setIcon(getIcon(R.drawable.sc_magiskhide))
|
||||
.setRank(1)
|
||||
.build())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
if (!Config.coreOnly && root && Info.magiskVersionCode >= 0) {
|
||||
shortCuts.add(ShortcutInfo.Builder(context, "modules")
|
||||
if (!Config.coreOnly && root && Info.env.magiskVersionCode >= 0) {
|
||||
shortCuts.add(
|
||||
ShortcutInfo.Builder(context, "modules")
|
||||
.setShortLabel(context.getString(R.string.modules))
|
||||
.setIntent(Intent(context, ClassMap[SplashActivity::class.java])
|
||||
.setIntent(
|
||||
Intent(intent)
|
||||
.putExtra(Const.Key.OPEN_SECTION, "modules")
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||
.setIcon(Icon.createWithResource(context, R.drawable.sc_extension))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
)
|
||||
.setIcon(getIcon(R.drawable.sc_extension))
|
||||
.setRank(3)
|
||||
.build())
|
||||
shortCuts.add(ShortcutInfo.Builder(context, "downloads")
|
||||
.build()
|
||||
)
|
||||
shortCuts.add(
|
||||
ShortcutInfo.Builder(context, "downloads")
|
||||
.setShortLabel(context.getString(R.string.downloads))
|
||||
.setIntent(Intent(context, ClassMap[SplashActivity::class.java])
|
||||
.setIntent(
|
||||
Intent(intent)
|
||||
.putExtra(Const.Key.OPEN_SECTION, "downloads")
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||
.setIcon(Icon.createWithResource(context, R.drawable.sc_cloud_download))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
)
|
||||
.setIcon(getIcon(R.drawable.sc_cloud_download))
|
||||
.setRank(2)
|
||||
.build())
|
||||
.build()
|
||||
)
|
||||
}
|
||||
return shortCuts
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ class EnvFixDialog(activity: Activity) : CustomAlertDialog(activity) {
|
||||
setTitle(R.string.env_fix_title)
|
||||
setMessage(R.string.env_fix_msg)
|
||||
setCancelable(true)
|
||||
setPositiveButton(R.string.yes) { _, _ ->
|
||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
||||
val pd = ProgressDialog.show(activity,
|
||||
activity.getString(R.string.setup_title),
|
||||
activity.getString(R.string.setup_msg))
|
||||
@@ -46,6 +46,6 @@ class EnvFixDialog(activity: Activity) : CustomAlertDialog(activity) {
|
||||
}
|
||||
}.exec()
|
||||
}
|
||||
setNegativeButton(R.string.no_thanks, null)
|
||||
setNegativeButton(android.R.string.no, null)
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ class FingerprintAuthDialog(activity: Activity, private val callback: () -> Unit
|
||||
binding.message.compoundDrawablePadding = Utils.dpInPx(20)
|
||||
binding.message.gravity = Gravity.CENTER
|
||||
setMessage(R.string.auth_fingerprint)
|
||||
setNegativeButton(R.string.close) { _, _ ->
|
||||
setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
helper?.cancel()
|
||||
failureCallback?.invoke()
|
||||
}
|
||||
|
@@ -62,12 +62,12 @@ internal class InstallMethodDialog(activity: BaseActivity<*, *>, options: List<S
|
||||
.setTitle(R.string.warning)
|
||||
.setMessage(R.string.install_inactive_slot_msg)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.yes) { _, _ ->
|
||||
.setPositiveButton(android.R.string.yes) { _, _ ->
|
||||
DownloadService(activity) {
|
||||
subject = DownloadSubject.Magisk(Configuration.Flash.Secondary)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/su_request_background" />
|
||||
<background android:drawable="@color/light" />
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_cloud_download"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/su_request_background" />
|
||||
<background android:drawable="@color/light" />
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_extension"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/su_request_background" />
|
||||
<background android:drawable="@color/light" />
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_magiskhide"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/su_request_background" />
|
||||
<background android:drawable="@color/light" />
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_superuser"
|
||||
|
@@ -4,6 +4,6 @@
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="@color/primary_dark"
|
||||
android:fillColor="@color/dark"
|
||||
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM17,13l-5,5 -5,-5h3V9h4v4h3z"/>
|
||||
</vector>
|
||||
|
@@ -4,6 +4,6 @@
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="@color/primary_dark"
|
||||
android:fillColor="@color/dark"
|
||||
android:pathData="M20.5,11H19V7c0,-1.1 -0.9,-2 -2,-2h-4V3.5C13,2.12 11.88,1 10.5,1S8,2.12 8,3.5V5H4c-1.1,0 -1.99,0.9 -1.99,2v3.8H3.5c1.49,0 2.7,1.21 2.7,2.7s-1.21,2.7 -2.7,2.7H2V20c0,1.1 0.9,2 2,2h3.8v-1.5c0,-1.49 1.21,-2.7 2.7,-2.7 1.49,0 2.7,1.21 2.7,2.7V22H17c1.1,0 2,-0.9 2,-2v-4h1.5c1.38,0 2.5,-1.12 2.5,-2.5S21.88,11 20.5,11z"/>
|
||||
</vector>
|
||||
|
@@ -5,6 +5,6 @@
|
||||
android:width="24dp">
|
||||
<path
|
||||
android:fillAlpha="1.00"
|
||||
android:fillColor="@color/primary_dark"
|
||||
android:fillColor="@color/dark"
|
||||
android:pathData="M200.6,24.2C231.8,24.2 263,33 289.6,49.5C304.7,58.8 318.2,70.7 329.8,84.1C351.5,109.6 365.2,141.7 368.8,175C373.6,217.4 361.5,261.5 335.5,295.5C334.2,297.1 332.8,298.7 331.9,300.7C341.7,310.1 351,320 360.9,329.3C322.7,339.3 284.5,349.6 246.3,359.9C256.4,323.5 266,287 275.7,250.5C262.4,250.5 249.1,250.5 235.8,250.5C228.5,269.8 221.2,289.1 214.1,308.4C205.9,308.6 197.8,308.5 189.6,308.5C188.4,306.7 187.1,304.9 185.9,303C192.4,285.5 199.1,268 205.6,250.5C189.5,250.6 173.4,250.3 157.4,250.6C150.4,270 142.9,289.2 135.8,308.5C129.8,308.5 123.9,308.4 117.9,308.6C130.4,317.8 144,325.6 158.9,330.3C171.9,334.6 185.6,336.6 199.4,336.7C199.4,349.4 199.3,362.1 199.4,374.8C165.8,374.9 132.2,364.5 104.4,345.6C91.7,337 80.3,326.5 70.2,314.9C48.5,289.4 34.8,257.3 31.2,224C26.3,180.4 39.2,134.9 66.8,100.7C67.2,99.9 67.7,99.2 68.1,98.4C58.3,88.9 49,79 39.1,69.7C77.3,59.7 115.6,49.4 153.7,39.1C143.6,75.7 133.8,112.5 124.1,149.3C137.9,149.3 151.7,149.2 165.5,149.3C172.9,130 180.2,110.6 187.3,91.2C195.5,90.8 203.7,91 211.8,91C213,92.8 214.3,94.6 215.5,96.3C209.1,114 202.3,131.6 195.8,149.2C211.8,149.3 227.8,149.2 243.9,149.3C251.2,129.9 258.3,110.3 265.8,90.9C271.5,90.8 277.3,91.6 282.9,90.4C280.2,89.5 278.1,87.7 275.9,86.1C254,70.7 227.4,62.2 200.6,62.3C200.6,49.6 200.7,36.9 200.6,24.2M292.5,100C286.4,116.4 280.2,132.8 274,149.3C280.9,149.2 287.8,149.3 294.7,149.2C296,150.8 297.3,152.4 298.6,153.9C297.1,162.1 295.7,170.3 294.3,178.5C283.9,178.5 273.4,178.5 262.9,178.5C257.5,192.7 252.1,206.9 246.9,221.2C258.7,221.3 270.5,221.1 282.3,221.3C283.5,222.9 284.8,224.4 286.1,225.9C284.9,233.7 283.4,241.4 282.1,249.1C281.6,251 283.6,252.1 284.6,253.3C291.5,259.8 297.7,266.9 304.8,273.1C312.9,262.1 319.6,250.1 324.2,237.3C334.3,208.7 334.2,176.7 323.7,148.3C317,130.1 306.4,113.4 292.5,100M95.2,125.9C86.2,138 79,151.4 74.5,165.8C65.3,194.4 66.4,226.3 77.6,254.2C84.6,271.5 95.1,287.4 108.7,300.1C114.9,283.6 121.3,267.1 127.2,250.5C121.5,250.5 115.8,250.5 110,250.5C108.6,250.4 106.7,251 105.8,249.5C104.5,247.9 102.3,246.3 102.9,244.1C104.2,236.5 105.5,228.9 106.8,221.2C117.4,221.2 128.1,221.4 138.7,221.1C143.9,206.9 149.3,192.7 154.6,178.5C142.9,178.4 131.1,178.6 119.3,178.4C117.6,177.3 116.4,175.3 115,173.8C116.3,165.8 117.9,157.9 119,150C118.3,148.2 116.6,147.1 115.3,145.7C108.6,139.2 102.3,132.1 95.2,125.9M168.8,221.2C184.8,221.2 200.8,221.3 216.8,221.2C222.2,207 227.5,192.8 232.8,178.5C216.8,178.5 200.7,178.5 184.6,178.5C179.4,192.8 174,207 168.8,221.2Z"/>
|
||||
</vector>
|
||||
|
@@ -4,6 +4,6 @@
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/primary_dark"
|
||||
android:fillColor="@color/dark"
|
||||
android:pathData="M5.41,21L6.12,17H2.12L2.47,15H6.47L7.53,9H3.53L3.88,7H7.88L8.59,3H10.59L9.88,7H15.88L16.59,3H18.59L17.88,7H21.88L21.53,9H17.53L16.47,15H20.47L20.12,17H16.12L15.41,21H13.41L14.12,17H8.12L7.41,21H5.41M9.53,9L8.47,15H14.47L15.53,9H9.53Z" />
|
||||
</vector>
|
@@ -32,7 +32,7 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<FrameLayout
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/main_nav_host"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
|
46
app/src/main/res/layout/dialog_custom_name.xml
Normal file
46
app/src/main/res/layout/dialog_custom_name.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
|
||||
<import type="com.topjohnwu.magisk.extensions.XStringKt" />
|
||||
|
||||
<variable
|
||||
name="data"
|
||||
type="com.topjohnwu.magisk.ui.settings.SettingsFragment.ManagerNameData" />
|
||||
|
||||
</data>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/margin_generic"
|
||||
android:paddingTop="@dimen/margin_generic"
|
||||
android:paddingEnd="@dimen/margin_generic">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/dialog_name_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/settings_app_name_hint"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="14"
|
||||
app:counterOverflowTextColor="@color/colorError"
|
||||
app:error="@{data.name.length() > 14 || data.name.empty || XStringKt.isEmptyInternal(data.name) ? @string/settings_app_name_error : @string/empty}"
|
||||
app:errorEnabled="true"
|
||||
app:helperText="@string/settings_app_name_helper">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@={data.name}"
|
||||
tools:text="@string/re_app_name" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
@@ -15,8 +15,6 @@
|
||||
|
||||
<import type="com.topjohnwu.magisk.R" />
|
||||
|
||||
<import type="com.topjohnwu.magisk.extensions.XStringKt" />
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.topjohnwu.magisk.ui.home.HomeViewModel" />
|
||||
@@ -239,7 +237,7 @@
|
||||
android:layout_marginRight="@dimen/margin_generic"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:text="@{XStringKt.res(viewModel.safetyNetTitle)}"
|
||||
android:text="@{viewModel.safetyNetTitle}"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeTextType="uniform"
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# v7.3.5
|
||||
- Sort installed modules by name
|
||||
- Better pre-5.0 support
|
||||
- Fix potential issues when patching tar files
|
||||
# v7.4.0
|
||||
- Hide Magisk Manager with stub APKs on Android 9.0+. Not all devices will be supported, please refer to Magisk v20.1 release notes.
|
||||
- Allow customizing app name when hiding Magisk Manager
|
||||
- Generate random keys to sign the hidden Magisk Manager to prevent signature detections
|
||||
- Fix fingerprint UI infinite loop
|
||||
|
@@ -110,8 +110,12 @@ EOF
|
||||
cd /
|
||||
}
|
||||
|
||||
rm_launch() {
|
||||
pm uninstall $1
|
||||
am start -n $2
|
||||
exit
|
||||
force_pm_install() {
|
||||
local APK=$1
|
||||
local VERIFY=`settings get global package_verifier_enable`
|
||||
[ "$VERIFY" -eq 1 ] && settings put global package_verifier_enable 0
|
||||
pm install -r $APK
|
||||
local res=$?
|
||||
[ "$VERIFY" -eq 1 ] && settings put global package_verifier_enable 1
|
||||
return $res
|
||||
}
|
||||
|
@@ -1,174 +1,224 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<resources>
|
||||
<string name="advanced_settings_title">إعدادات متقدمة</string>
|
||||
<string name="app_changelog">تغييرات التطبيق</string>
|
||||
<string name="author">انشئ بواسطة %1$s</string>
|
||||
<string name="auto_response">استجابة تلقائية</string>
|
||||
<string name="checking_for_updates">البحث عن تحديثات…</string>
|
||||
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
|
||||
<string name="close">إغلاق</string>
|
||||
<string name="command">الأمر: %1$s</string>
|
||||
<string name="deny">رفض</string>
|
||||
<string name="disable_file_created">سيتم تعطيل الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_removed">سيتم تمكين الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="download">التنزيل</string>
|
||||
<string name="downloads">التنزيلات</string>
|
||||
<string name="forever">للابد</string>
|
||||
<string name="grant">سماح</string>
|
||||
<string name="install">التثبيت</string>
|
||||
<string name="installed">مثبت</string>
|
||||
<string name="keep_dm_verity">إبقاء AVB 2.0/dm-verity</string>
|
||||
<string name="keep_force_encryption">الحفاظ علي قوه التشفير</string>
|
||||
<string name="log">السجل</string>
|
||||
<string name="logs_cleared">تم حذف السجل بنجاح</string>
|
||||
<string name="magisk_update_title">تحديث Magisk جديد متوفر!</string>
|
||||
<string name="magisk_version_error">Magisk غير مثبت</string>
|
||||
<string name="menuClearLog">حذف السجل الآن</string>
|
||||
<string name="menuReload">إعادة تحميل</string>
|
||||
<string name="modules">الإضافات</string>
|
||||
<string name="multiuser_mode">وضع تعدد المستخدمين</string>
|
||||
<string name="no_apps_found">لا توجد تطبيقات</string>
|
||||
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
|
||||
<string name="no_modules_found">لم يعثر على الإضافات</string>
|
||||
<string name="none">بدون</string>
|
||||
<string name="not_installed">غير مثبت</string>
|
||||
<string name="once">مرة</string>
|
||||
<string name="owner_manage_summary">يمكن للمالك فقط إدارة صلاحيات الروت وتلقي مطالبات الطلب</string>
|
||||
<string name="owner_only_summary">المالك فقط لديه صلاحيات الروت</string>
|
||||
<string name="prompt">طلب</string>
|
||||
<string name="reboot">إعادة التشغيل</string>
|
||||
<string name="release_notes">ملاحظات الإصدار</string>
|
||||
<string name="remove_file_created">سيتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_deleted">لن يتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="repo_cache_cleared">تم مسح الذاكرة المؤقته للمستودع</string>
|
||||
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
|
||||
<string name="repo_install_title">تثبيت %1$s</string>
|
||||
<string name="request_timeout">مهلة الطلب</string>
|
||||
<string name="request_timeout_summary">%1$d ثانية</string>
|
||||
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
|
||||
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">الاستجابة غير صالحه</string>
|
||||
<string name="settings">الإعدادات</string>
|
||||
<string name="settings_clear_cache_summary">حذف المعلومات المخزنة مؤقتا للمستودع على الانترنت، يجبر التطبيق لتحديث عبر الانترنت</string>
|
||||
<string name="settings_clear_cache_title">حذف الذاكرة المؤقتة للمستودع</string>
|
||||
<string name="settings_core_only_summary">تمكين الميزات الأساسية فقط، لن يتم تحميل جميع الإضافات. MagiskSU، MagiskHide، systemless hosts، و لا يزال ممكنا</string>
|
||||
<string name="settings_core_only_title">Magisk الوضع الأساسي فقط</string>
|
||||
<string name="settings_dark_theme_summary">تفعيل السمة الغامقة</string>
|
||||
<string name="settings_dark_theme_title">السمة الغامقة</string>
|
||||
<string name="settings_general_category">عام</string>
|
||||
<string name="settings_hosts_summary">Systemless يدعم تطبيقات حجب الإعلانات</string>
|
||||
<string name="settings_hosts_title">تمكين المضيفين(الهوست) لـ systemless</string>
|
||||
<string name="settings_magiskhide_summary">إخفاء Magisk من مختلف الاكتشافات</string>
|
||||
<string name="settings_owner_manage">إدارة مالك الجهاز</string>
|
||||
<string name="settings_owner_only">مالك الجهاز فقط</string>
|
||||
<string name="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
|
||||
<string name="settings_su_adb">ADB فقط</string>
|
||||
<string name="settings_su_app">التطبيقات فقط</string>
|
||||
<string name="settings_su_app_adb">التطبيقات و ADB</string>
|
||||
<string name="settings_su_disable">معطل</string>
|
||||
<string name="settings_su_request_10">10 ثواني</string>
|
||||
<string name="settings_su_request_20">20 ثانية</string>
|
||||
<string name="settings_su_request_30">30 ثانية</string>
|
||||
<string name="settings_su_request_60">60 ثانية</string>
|
||||
<string name="settings_user_independent">مستخدم مستقل</string>
|
||||
<string name="sixtymin">60 دقائق</string>
|
||||
<string name="su_allow_toast">%1$s يتم منح صلاحيات Superuser</string>
|
||||
<string name="su_deny_toast">%1$s يتم رفض صلاحيات Superuser</string>
|
||||
<string name="su_request_title">Superuser طلبات</string>
|
||||
<string name="su_revoke_msg">تأكيد لسحب صلاحيات %1$s ?</string>
|
||||
<string name="su_revoke_title">سحب؟</string>
|
||||
<string name="su_snack_deny">Superuser الصلاحيات لـ %1$s تم رفضها</string>
|
||||
<string name="su_snack_grant">Superuser الصلاحيات لـ %1$s تم منحها</string>
|
||||
<string name="su_snack_log_off">السجلات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_log_on">السجلات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_snack_notif_off">الإشعارات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_notif_on">الإشعارات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_warning">"منح حق الوصول الكامل إلى جهازك.
|
||||
رفض إذا كنت غير متأكد!"</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="superuser_access">Superuser صلاحيات</string>
|
||||
<string name="superuser_notification">Superuser إشعارات</string>
|
||||
<string name="target_uid">الهدف UID: %1$d</string>
|
||||
<string name="tenmin">10 دقائق</string>
|
||||
<string name="thirtymin">30 دقائق</string>
|
||||
<string name="toast">ملاحظة منبثقة</string>
|
||||
<string name="twentymin">20 دقائق</string>
|
||||
<string name="uninstall">إلغاء التثبيت</string>
|
||||
<string name="uninstall_magisk_title">إلغاء تثبيت Magisk</string>
|
||||
<string name="update_available">يتوفر تحديث</string>
|
||||
<string name="update_file_created">سيتم تحديث الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="user_indepenent_summary">كل مستخدم لديه قواعد روت منفصلة خاصة به</string>
|
||||
<string name="android_o_not_support">لا يدعم إصدار الأندرويد +8.0</string>
|
||||
<string name="auth_fail">فشل المصادقة</string>
|
||||
<string name="auth_fingerprint">مصادقة البصمة</string>
|
||||
<string name="complete_uninstall">إلغاء التثبيت بالكامل</string>
|
||||
<string name="direct_install">تثبيت مباشر (موصى به)</string>
|
||||
<string name="disable_fingerprint">لم يتم تعيين بصمات الأصابع أو لا يوجد جهاز مدعوم</string>
|
||||
<string name="download_zip_only">تحميل ملف zip فقط</string>
|
||||
<string name="dtbo_patched_reboot">قام مدير Magisk بتصحيح dtbo.img ، يرجى إعادة التشغيل</string>
|
||||
<string name="dtbo_patched_title">تم تصحيح DTBO!</string>
|
||||
<string name="env_fix_msg">يحتاج جهازك إلى إعداد إضافي لـ Magisk للعمل بشكل صحيح. سيتم تنزيل ملف zip لتثبيت Magisk ، هل تريد المتابعة الآن؟</string>
|
||||
<string name="env_fix_title">يتطلب إعداد إضافي</string>
|
||||
<string name="flashing">التثبيت</string>
|
||||
<string name="global_summary">تستخدم كافة جلسات الجذر مساحة الأسم ذات التركيب العالمي</string>
|
||||
<string name="hide_manager_fail_toast">فشل إخفاء مدير Magisk …</string>
|
||||
<string name="hide_manager_title">إخفاء مدير Magisk…</string>
|
||||
<string name="install_inactive_slot">التثبيت على فتحة غير نشطة (بعد OTA)</string>
|
||||
<string name="install_inactive_slot_msg">"سيتم إجبار جهازك للتمهيد على الفتحة غير النشطة الحالية بعد إعادة التشغيل!
|
||||
فقط استخدام هذا الخيار بعد الانتهاء من OTA.
|
||||
استمرار؟"</string>
|
||||
<string name="invalid_update_channel">قناة تحديث غير صالحة</string>
|
||||
<string name="isolate_summary">سيكون لكل جلسة جذر مساحة الاسم الخاصة بها معزولة</string>
|
||||
<string name="language">اللغة</string>
|
||||
<string name="update_channel">تحديثات Magisk</string>
|
||||
<string name="manager_download_install">اضغط للتنزيل والتثبيت</string>
|
||||
<string name="manager_update_title">تحديث مدير Magisk الجديد متوفر!</string>
|
||||
<string name="menuSaveLog">حفظ السجل</string>
|
||||
<string name="mount_namespace_mode">وضع تركيب مساحة الأسم</string>
|
||||
<string name="open_link_failed_toast">لم يتم العثور على تطبيق لفتح الرابط …</string>
|
||||
<string name="proprietary_notice">مدير Magisk هو FOSS ، والذي لا يحتوي على شفرة API الخاصة بشركة SafetyNet الخاصة بشركة Google.
|
||||
|
||||
هل تسمح لـ Magisk Manager بتنزيل ملحق (يحتوي على GoogleApiClient) لعمليات التحقق من SafetyNet؟ "</string>
|
||||
<string name="proprietary_title">تحميل رمز الملكية</string>
|
||||
<string name="reboot_bootloader">إعادة تمهيد إلى وضع Bootloader</string>
|
||||
<string name="reboot_download">إعادة تمهيد إلى وضع التحميل</string>
|
||||
<string name="reboot_recovery">إعادة تمهيد إلى وضع الإسترداد</string>
|
||||
<string name="requester_summary">"سترث جلسات الجذر مساحة الأسماء المطلوبة الخاصة بها"</string>
|
||||
<string name="restore_done">تمت الأستعادة!</string>
|
||||
<string name="restore_fail">النسخ الاحتياطي الأصلي غير موجود!</string>
|
||||
<string name="restore_img">استعادة الصور</string>
|
||||
<string name="restore_img_msg">الأستعادة …</string>
|
||||
<string name="safetyNet_api_error">خطأ SafetyNet API</string>
|
||||
<string name="select_method">حدد الطريقة</string>
|
||||
<string name="settings_check_update_summary">التحقق من التحديثات في الخلفية بشكل دوري</string>
|
||||
<string name="settings_check_update_title">تفقد التحديث</string>
|
||||
<string name="settings_hide_manager_summary">أعد حزم مدير Magisk مع اسم حزمة عشوائية</string>
|
||||
<string name="settings_hide_manager_title">إخفاء مدير Magisk</string>
|
||||
<string name="settings_ns_global">مساحة الاسم العالمية</string>
|
||||
<string name="settings_ns_isolate">مساحة الاسم المعزولة</string>
|
||||
<string name="settings_ns_requester">وراثة مساحة الاسم</string>
|
||||
<string name="settings_restore_manager_summary">استعادة مدير Magisk مع الحزمة الأصلية</string>
|
||||
<string name="settings_restore_manager_title">استعادة مدير Magisk</string>
|
||||
<string name="settings_su_fingerprint_summary">أستخدام ماسح بصمات الأصابع للسماح بطلبات المستخدم المتميز</string>
|
||||
<string name="settings_su_fingerprint_title">تمكين مصادقة البصمة</string>
|
||||
<string name="settings_su_reauth_summary">أعد المصادقة على صلاحيات المستخدم المتميز بعد إجراء ترقيات للتطبيق</string>
|
||||
<string name="settings_su_reauth_title">إعادة المصادقة بعد الترقية</string>
|
||||
<string name="settings_update">تحديث الاعدادات</string>
|
||||
<string name="settings_update_beta">بيتا</string>
|
||||
<string name="settings_update_channel_title">قناة التحديث</string>
|
||||
<string name="settings_update_custom">مخصص</string>
|
||||
<string name="settings_update_custom_msg">أدخل عنوان URL مخصص</string>
|
||||
<string name="settings_update_stable">مستقر</string>
|
||||
<string name="setup_fail">فشل الإعداد</string>
|
||||
<string name="setup_msg">تشغيل إعداد البيئة…</string>
|
||||
<string name="setup_title">إعداد إضافي</string>
|
||||
<string name="sort_by_name">الترتيب حسب الاسم</string>
|
||||
<string name="sort_by_update">فرز حسب آخر تحديث</string>
|
||||
<string name="sorting_order">ترتيب الفرز</string>
|
||||
<string name="system_default">(أفتراضي النظام)</string>
|
||||
<string name="uninstall_magisk_msg">سيتم تعطيل/إزالة جميع الوحدات. ستتم إزالة الجذر ، وربما تشفير بياناتك إذا كانت بياناتك غير مشفرة حالياً</string>
|
||||
<string name="update">تحديث</string>
|
||||
<string name="updated_on">تم التحديث في: %1$s</string>
|
||||
<string name="warning">تحذير</string>
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">الإضافات</string>
|
||||
<string name="downloads">التنزيلات</string>
|
||||
<string name="superuser">المستخدم المتميز</string>
|
||||
<string name="log">السجل</string>
|
||||
<string name="settings">الإعدادات</string>
|
||||
<string name="install">التثبيت</string>
|
||||
<string name="unsupport_magisk_title">إصدار Magisk غير مدعوم</string>
|
||||
<string name="unsupport_magisk_message">لا يدعم هذا الإصدار من Magisk Manager إصدارا لـ Magisk vأقل من 18\n\n بإمكانك تحديث Magisk يدويا أو تثبيت إصدار أدنى.</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk غير مثبت</string>
|
||||
<string name="checking_for_updates">البحث عن تحديثات…</string>
|
||||
<string name="invalid_update_channel">قناة تحديث غير صالحة</string>
|
||||
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
|
||||
<string name="safetyNet_api_error">خطأ SafetyNet API</string>
|
||||
<string name="safetyNet_res_invalid">رد غير صالح</string>
|
||||
<string name="magisk_up_to_date">Magisk محدث</string>
|
||||
<string name="manager_up_to_date">Magisk Manager محدث</string>
|
||||
<string name="advanced_settings_title">إعدادات متقدمة</string>
|
||||
<string name="keep_force_encryption">إبقاء التشفير بقوة</string>
|
||||
<string name="keep_dm_verity">إبقاء AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">نمط الاستعادة</string>
|
||||
<string name="current_installed">التحديث المثبت : %1$s</string>
|
||||
<string name="latest_version">آخر تحديث : %1$s</string>
|
||||
<string name="uninstall">إلغاء التثبيت</string>
|
||||
<string name="uninstall_magisk_title">إلغاء تثبيت Magisk</string>
|
||||
<string name="uninstall_magisk_msg">ستُعطل/ستُحذف جميع الإضافات. سيُحذف الروت ، وربما ستشفر بياناتك إذا لم تكن غير مشفرة حالياً.</string>
|
||||
<string name="update">تحديث</string>
|
||||
<string name="core_only_enabled">(النمط الأساسي فقط ممكن)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
|
||||
<string name="no_modules_found">لم يعثر على أي إضافات</string>
|
||||
<string name="update_file_created">ستُحدث الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_created">ستُحذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_deleted">لن تُحذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_created">ستُعطل الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_removed">ستُمكن الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="author">انشئ من طرف %1$s</string>
|
||||
<string name="reboot_recovery">إعادة التشغيل إلى نمط الاستعادة</string>
|
||||
<string name="reboot_bootloader">إعادة التشغيل إلى نمط Bootloader</string>
|
||||
<string name="reboot_download">إعادة التشغيل إلى نمط التحميل</string>
|
||||
<string name="reboot_edl">إعادة التشغيل إلى نمط EDL</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">يتوفر على تحديث</string>
|
||||
<string name="installed">مثبت</string>
|
||||
<string name="not_installed">غير مثبت</string>
|
||||
<string name="updated_on">حُدث في: %1$s</string>
|
||||
<string name="sorting_order">ترتيب الفرز</string>
|
||||
<string name="sort_by_name">افرز حسب الاسم</string>
|
||||
<string name="sort_by_update">افرز حسب آخر تحديث</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">حفظ السجل</string>
|
||||
<string name="menuReload">إعادة التحميل</string>
|
||||
<string name="menuClearLog">حذف السجل الآن</string>
|
||||
<string name="logs_cleared">حُذف السجل بنجاح</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">تغييرات التطبيق</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="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>
|
||||
|
||||
<!-- Installation -->
|
||||
<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">"سيُجبر جهازك للتشغيل على الفتحة غير النشطة الحالية بعد إعادة التشغيل! استخدم فقط هذا الخيار بعد الانتهاء من OTA. استمرار؟"</string>
|
||||
<string name="select_method">اختر الطريقة</string>
|
||||
<string name="setup_title">إعداد إضافي</string>
|
||||
<string name="select_patch_file">اختر و رقع ملفا</string>
|
||||
<string name="patch_file_msg">اختر ملفا خاما (*.img) أو ملف ODIN tarfile (*.tar)</string>
|
||||
<string name="reboot_delay_toast">إعادة التشغيل خلال خمس ثواني…</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="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
|
||||
<string name="release_notes">ملاحظات الإصدار</string>
|
||||
<string name="repo_cache_cleared">مُسحت الذاكرة المؤقتة للإضافة</string>
|
||||
|
||||
<string name="dtbo_patched_title">رُقع DTBO!</string>
|
||||
<string name="dtbo_patched_reboot">رقع Magisk Manager الملف dtbo.img. يرجى إعادة التشغيل</string>
|
||||
<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="warning">تحذير</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 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_general_category">عام</string>
|
||||
<string name="settings_dark_theme_title">السمة الغامقة</string>
|
||||
<string name="settings_dark_theme_summary">تمكين السمة الغامقة</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="system_default">(النظام المبدئي)</string>
|
||||
<string name="settings_update">تحديث الإعدادات</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">أدخل عنوانا URL مخصصا</string>
|
||||
<string name="settings_core_only_title"> النمط Magisk الأساسي فقط</string>
|
||||
<string name="settings_core_only_summary">تمكين الميزات الأساسية فقط، سيُشغل الإضافات MagiskSU و MagiskHide فقط و لا غيرها.</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_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="request_timeout_summary">%1$d ثانية</string>
|
||||
<string name="settings_su_reauth_title">إعادة المصادقة بعد الترقية</string>
|
||||
<string name="settings_su_reauth_summary">أعد المصادقة على صلاحيات المستخدم المتميز بعد إجراء ترقيات للتطبيق</string>
|
||||
<string name="settings_su_fingerprint_summary">استخدام قارئ بصمات الأصابع للسماح بطلبات المستخدم المتميز</string>
|
||||
<string name="settings_su_fingerprint_title">تمكين مصادقة البصمة</string>
|
||||
<string name="auth_fingerprint">مصادقة البصمة</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="user_indepenent_summary">لكل مستخدم قواعد روت منفصلة خاصة به</string>
|
||||
|
||||
<string name="mount_namespace_mode">نمط تحميل مساحة الاسم</string>
|
||||
<string name="settings_ns_global">مساحة الاسم العامة</string>
|
||||
<string name="settings_ns_requester">وراثة مساحة الاسم</string>
|
||||
<string name="settings_ns_isolate">مساحة الاسم المعزولة</string>
|
||||
<string name="global_summary">تستخدم كافة جلسات العمل للروت مساحة الاسم ذات التركيب العامة</string>
|
||||
<string name="requester_summary">سترث جلسات العمل للروت مساحة الأسماء لطالبيها</string>
|
||||
<string name="isolate_summary">سيكون لكل جلسة عمل للروت مساحة اسم معزولة خاصة بها </string>
|
||||
<string name="disable_fingerprint">لم تُعين بصمات الأصابع أو لا يوجد قارئ بصمات</string>
|
||||
<string name="settings_download_path_error">خطأ عند إنشاء مجلد. عليه أن يكون سهلا الوصول إليه من خلال مجلد التخزين للروت و ألا يكون ملفا.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">طلبات المستخدم المتميز</string>
|
||||
<string name="deny">رفض</string>
|
||||
<string name="prompt">طلب</string>
|
||||
<string name="grant">سماح</string>
|
||||
<string name="su_warning">"منح حق الوصول الكامل إلى جهازك. ارفض إذا كنت غير متأكد!"</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="no_apps_found">لا توجد تطبيقات</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>
|
||||
<string name="auth_fail">فشل المصادقة</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Target UID: %1$d</string>
|
||||
<string name="command">Command: %1$s</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">اظهار برامج النظام</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,122 +1,70 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
|
||||
<string name="modules">Əlavələr</string>
|
||||
|
||||
<string name="downloads">Endirmələr</string>
|
||||
|
||||
<string name="superuser">Superuser</string>
|
||||
|
||||
<string name="log">Log</string>
|
||||
|
||||
<string name="settings">Tənzimləmələr</string>
|
||||
|
||||
<string name="install">Quraşdır</string>
|
||||
|
||||
<string name="unsupport_magisk_title">Dəstəklənməyən Magisk Versiyası</string>
|
||||
|
||||
<string name="unsupport_magisk_message">Magisk Manager\'in bu versiyası Magisk\'in v18.0 versiyasndan aşağısını dəstəkləmir.\n\nMagisk\'i əllə yüksəldə, yaxud tətbiqi əvvəlki versiyalarına qaytara bilərsiniz.</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
|
||||
<string name="magisk_version_error">Magisk yüklənməyib.</string>
|
||||
|
||||
<string name="checking_for_updates">Yeniləmələr yoxlanılır…</string>
|
||||
|
||||
<string name="invalid_update_channel">Etibarsız Yeniləmə Kanalı</string>
|
||||
|
||||
<string name="safetyNet_check_text">SafetyNet vəziyətinə bax</string>
|
||||
|
||||
<string name="checking_safetyNet_status">SafetyNet vəziyəti yoxlanılır…</string>
|
||||
|
||||
<string name="safetyNet_check_success">SafetyNet Uğurla Yoxlanıldı</string>
|
||||
|
||||
<string name="safetyNet_api_error">SafetyNet API Xətası</string>
|
||||
|
||||
<string name="safetyNet_res_invalid">Cavab etibarsızdır.</string>
|
||||
|
||||
<string name="magisk_up_to_date">Magisk ən yenidir</string>
|
||||
|
||||
<string name="manager_up_to_date">Magisk Manager ən yenidir</string>
|
||||
|
||||
<string name="advanced_settings_title">Qabaqcıl Parametrlər</string>
|
||||
|
||||
<string name="keep_force_encryption">Şifrələməyə məcbur etməni qoru</string>
|
||||
|
||||
<string name="keep_dm_verity">AVB 2.0/dm-verity\'i qoru</string>
|
||||
|
||||
<string name="current_installed">Yüklənən: %1$s</string>
|
||||
|
||||
<string name="latest_version">Ən son: %1$s</string>
|
||||
|
||||
<string name="uninstall">Sil</string>
|
||||
|
||||
<string name="uninstall_magisk_title">Magisk\'i Sil</string>
|
||||
|
||||
<string name="uninstall_magisk_msg">Bütün əlavələr ləğv olunacaq/silinəcək. Root silinəcək, və əgər hal-hazırda deyilsə, bütün məlumatlarınız potensiyal olaraq şifrələnəcək.</string>
|
||||
|
||||
<string name="update">Yenilə</string>
|
||||
|
||||
<string name="core_only_enabled">(Yalnız nüvə modu qoşulub)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
|
||||
<string name="no_info_provided">(Məlumat təmin edilməyib)</string>
|
||||
|
||||
<string name="no_modules_found">Əlavələr yoxdur.</string>
|
||||
|
||||
<string name="update_file_created">Əlavə sonrakı yenidən başlatmada yenilənəcək.</string>
|
||||
|
||||
<string name="remove_file_created">Əlavə sonrakı yenidən başlatmada silinəcək.</string>
|
||||
|
||||
<string name="remove_file_deleted">Əlavə sonrakı yenidən başlatmada silinməyəcək.</string>
|
||||
|
||||
<string name="disable_file_created">Əlavə sonrakı yenidən başlatmada qapadılacaq.</string>
|
||||
|
||||
<string name="disable_file_removed">Əlavə sonrakı yenidən başlatmada açılacaq.</string>
|
||||
|
||||
<string name="author">%1$s tərəfindən yaradılıb</string>
|
||||
|
||||
<string name="reboot_recovery">Bərpa rejimində yenidən başlat</string>
|
||||
|
||||
<string name="reboot_bootloader">Bootloader\'ə yenidən başlat</string>
|
||||
|
||||
<string name="reboot_download">Yükləmə rejimində yenidən başlat</string>
|
||||
<string name="reboot_edl">EDL\'ə yenidən başlat</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
|
||||
<string name="update_available">Yeniləmə Var</string>
|
||||
|
||||
<string name="installed">Yüklənib</string>
|
||||
|
||||
<string name="not_installed">Yüklənməyib</string>
|
||||
|
||||
<string name="updated_on">Yeniləmə vaxtı: %1$s</string>
|
||||
|
||||
<string name="sorting_order">Nizamlama Qaydası</string>
|
||||
|
||||
<string name="sort_by_name">Ada görə nizamla</string>
|
||||
|
||||
<string name="sort_by_update">Son yeniləməyə görə nizamla</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
|
||||
<string name="menuSaveLog">Log\'u saxla</string>
|
||||
|
||||
<string name="menuReload">Təzələ</string>
|
||||
|
||||
<string name="menuClearLog">Log\'u indi təmizlə</string>
|
||||
|
||||
<string name="logs_cleared">Log uğurla təmizləndi.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
|
||||
<string name="app_changelog">Yeniliklər</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
|
||||
<string name="update_channel">Magisk Yeniləmələri</string>
|
||||
<string name="progress_channel">Nəticə Bildirişləri</string>
|
||||
<string name="download_complete">Yükləmə bitdi</string>
|
||||
@@ -127,262 +75,135 @@
|
||||
<string name="manager_update_title">Magisk Manager Yeniləməsi Var!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
|
||||
<string name="close">Qapat</string>
|
||||
|
||||
<string name="repo_install_title">%1$s faylını yüklə</string>
|
||||
|
||||
<string name="repo_install_msg">%1$s faylını indi yükləmək istəyirsiniz?</string>
|
||||
|
||||
<string name="download">Yüklə</string>
|
||||
|
||||
<string name="reboot">Yenidən Başlat</string>
|
||||
|
||||
<string name="settings_reboot_toast">Tənzimləmələri saxlamaq üçün yenidən başladın.</string>
|
||||
|
||||
<string name="release_notes">Yeniliklər</string>
|
||||
|
||||
<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="dtbo_patched_title">DTBO yamaqlanıb!</string>
|
||||
|
||||
<string name="dtbo_patched_reboot">Magisk Manager dtbo.img\'ni yamaqladı. Xahiş olunur yenidən başladın.</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>
|
||||
|
||||
<string name="warning">Xəbərdarlıq</string>
|
||||
|
||||
<string name="install_inactive_slot_msg">Cihazınız yenidən başladıldıqdan sonra fəal olmayan slota başlamağa MƏCBUR ediləcək!\nBu seçimi yalnız OTA bitdikdən sonra istifadə edin.\nDavam edirsiniz?</string>
|
||||
|
||||
<string name="select_method">Üsul Seçin</string>
|
||||
|
||||
<string name="complete_uninstall">Silməni Bitir</string>
|
||||
|
||||
<string name="restore_img">Surətləri Qaytar</string>
|
||||
|
||||
<string name="restore_img_msg">Geri qaytarılır…</string>
|
||||
|
||||
<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_general_category">Ümumi</string>
|
||||
|
||||
<string name="settings_dark_theme_title">Qaranlıq Mövzu</string>
|
||||
|
||||
<string name="settings_dark_theme_summary">Qaranlıq mövzunu aç.</string>
|
||||
|
||||
<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_update">Tənzimləmələri Yenilə</string>
|
||||
|
||||
<string name="settings_check_update_title">Yeniləmələri Yoxla</string>
|
||||
|
||||
<string name="settings_check_update_summary">Axraplanda vaxtaşırı yeniləmələri yoxla.</string>
|
||||
|
||||
<string name="settings_update_channel_title">Kanalı Yenilə</string>
|
||||
|
||||
<string name="settings_update_stable">Stabil</string>
|
||||
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
|
||||
<string name="settings_update_custom">Özəl</string>
|
||||
|
||||
<string name="settings_update_custom_msg">Özəl URL daxil edin</string>
|
||||
|
||||
<string name="settings_core_only_title">Magisk Yalnız Nüvə Modu</string>
|
||||
|
||||
<string name="settings_core_only_summary">Yalnız nüvə xüsusiyyətlərini aç. MagiskSU və MagiskHide hələ də açıq qalacaq, amma əlavələr yüklənməyəcək.</string>
|
||||
|
||||
<string name="settings_magiskhide_summary">Magisk\'i fərqli növdə aşkarlamalardan gizləyin.</string>
|
||||
|
||||
<string name="settings_hosts_title">Sistemsiz host\'lar</string>
|
||||
|
||||
<string name="settings_hosts_summary">Adblock tətbiqləri üçün Sistemsiz host dəstəyi.</string>
|
||||
|
||||
<string name="settings_hosts_toast">Sistemsiz host əlavəsi quraşdırıldı</string>
|
||||
|
||||
<string name="settings_su_app_adb">Tətbiqlər və ADB</string>
|
||||
|
||||
<string name="settings_su_app">Yalnız Tətbiqlər</string>
|
||||
|
||||
<string name="settings_su_adb">Yalnız ADB</string>
|
||||
|
||||
<string name="settings_su_disable">Qapalı</string>
|
||||
|
||||
<string name="settings_su_request_10">10 saniyə</string>
|
||||
|
||||
<string name="settings_su_request_15">15 saniyə</string>
|
||||
|
||||
<string name="settings_su_request_20">20 saniyə</string>
|
||||
|
||||
<string name="settings_su_request_30">30 saniyə</string>
|
||||
|
||||
<string name="settings_su_request_45">45 saniyə</string>
|
||||
|
||||
<string name="settings_su_request_60">60 saniyə</string>
|
||||
|
||||
<string name="superuser_access">Superuser İcazəsi</string>
|
||||
|
||||
<string name="auto_response">Avtomatik Cavab</string>
|
||||
|
||||
<string name="request_timeout">İcazə Vaxtaşımı</string>
|
||||
|
||||
<string name="superuser_notification">Superuser Bildirişləri</string>
|
||||
|
||||
<string name="request_timeout_summary">%1$d saniyə</string>
|
||||
|
||||
<string name="settings_su_reauth_title">Yüksəltmədən sonra Yenidən İdentifikasiya et</string>
|
||||
|
||||
<string name="settings_su_reauth_summary">Tətbiq yeniləmələridən sonra superuser icazələrini yenidən identifikasiya et</string>
|
||||
|
||||
<string name="settings_su_fingerprint_title">Barmaq İzi İdentifikasiyasını Aç</string>
|
||||
|
||||
<string name="settings_su_fingerprint_summary">Barmaq izi oxuyucunu superuser icazələri üçün işlət</string>
|
||||
|
||||
<string name="auth_fingerprint">Barmaq izini İdentifikasiya et</string>
|
||||
|
||||
<string name="multiuser_mode">Çox-istifadəçi modu</string>
|
||||
|
||||
<string name="settings_owner_only">Yalnız cihaz sahibi</string>
|
||||
|
||||
<string name="settings_owner_manage">Cihaz sahibinin idarəçiliyində</string>
|
||||
|
||||
<string name="settings_user_independent">İstifadəçidən asılı olmayaraq</string>
|
||||
|
||||
<string name="owner_only_summary">Yalnız cihaz sahibinin root icazəsi var.</string>
|
||||
|
||||
<string name="owner_manage_summary">Yalnız cihaz sahibi root icazələrini redaktə edə və icazə istəkləri qəbul edə bilər.</string>
|
||||
|
||||
<string name="user_indepenent_summary">Hər istifadəçinin ayrı root qaydaları var.</string>
|
||||
|
||||
<string name="mount_namespace_mode">Namespace Modunu Qoş</string>
|
||||
|
||||
<string name="settings_ns_global">Qlobal Namespace</string>
|
||||
|
||||
<string name="settings_ns_requester">Keçmə Namespace</string>
|
||||
|
||||
<string name="settings_ns_isolate">Ayrılmış Namespace</string>
|
||||
|
||||
<string name="global_summary">Bütün root sessyaları qlobal qoşma namespace\'dən istifadə edir.</string>
|
||||
|
||||
<string name="requester_summary">Root sessyaları soruşulan namespace\'ləri birindən digərinə keçirəcək.</string>
|
||||
|
||||
<string name="isolate_summary">Hər bir root sessyasının ayrılmış namespace\'i olacaq.</string>
|
||||
|
||||
<string name="android_o_not_support">Android 8.0+\'da dəstəklənmir.</string>
|
||||
|
||||
<string name="disable_fingerprint">Barmaq izi təyin edilməyib ya da dəstəklənmir.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
||||
<string name="su_request_title">Superuser Tələbi</string>
|
||||
|
||||
<string name="deny">Ləğv et</string>
|
||||
|
||||
<string name="prompt">Yönləndir</string>
|
||||
|
||||
<string name="grant">Təmin et</string>
|
||||
|
||||
<string name="su_warning">Cihazın tam icazəsi ilə təmin edin.\nƏmin deyilsinizsə ləğv edin!</string>
|
||||
|
||||
<string name="forever">Sonsuz</string>
|
||||
|
||||
<string name="once">Bir dəfəlik</string>
|
||||
|
||||
<string name="tenmin">10 dəq</string>
|
||||
|
||||
<string name="twentymin">20 dəq</string>
|
||||
|
||||
<string name="thirtymin">30 dəq</string>
|
||||
|
||||
<string name="sixtymin">60 dəq</string>
|
||||
|
||||
<string name="su_allow_toast">%1$s SuperUser icazəsi ilə təmin edildi</string>
|
||||
|
||||
<string name="su_deny_toast">%1$s SuperUser icazəsi ilə təmin edilmədi</string>
|
||||
|
||||
<string name="no_apps_found">Tətbiq yoxdur</string>
|
||||
|
||||
<string name="su_snack_grant">%1$s üçün Superuser icazəsi verilib</string>
|
||||
|
||||
<string name="su_snack_deny">%1$s üçün Superuser icazəsi verilməyib</string>
|
||||
|
||||
<string name="su_snack_notif_on">%1$s üçün bildirişlər açıqdır</string>
|
||||
|
||||
<string name="su_snack_notif_off">%1$s üçün bildirişlər bağlıdır</string>
|
||||
|
||||
<string name="su_snack_log_on">%1$s üçün giriş açıqdır</string>
|
||||
|
||||
<string name="su_snack_log_off">%1$s üçün giriş bağlıdır</string>
|
||||
|
||||
<string name="su_revoke_title">Ləğv olunsun?</string>
|
||||
|
||||
<string name="su_revoke_msg">%1$s üçün haqları ləğv etməyi təsdiq edirsiniz?</string>
|
||||
|
||||
<string name="toast">Tost</string>
|
||||
|
||||
<string name="none">Heçnə</string>
|
||||
|
||||
<string name="auth_fail">İdentifikasiya xətası</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
|
||||
<string name="pid">PID: %1$d</string>
|
||||
|
||||
<string name="target_uid">Hədəf UID: %1$d</string>
|
||||
|
||||
<string name="command">Komanda: %1$s</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
|
||||
<string name="show_system_app">Sistem tətbiqlərini göstər</string>
|
||||
|
||||
</resources>
|
||||
|
||||
|
@@ -61,7 +61,6 @@
|
||||
<string name="app_changelog">Списък с промени</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Затваряне</string>
|
||||
<string name="repo_install_title">Инсталиране на %1$s</string>
|
||||
<string name="repo_install_msg">Желаете ли да инсталирате %1$s сега?</string>
|
||||
<string name="download">Изтегляне</string>
|
||||
@@ -162,7 +161,6 @@
|
||||
<string name="global_summary">Всички сесии с руут достъп използват глобалното именно пространство.</string>
|
||||
<string name="requester_summary">Всички сесии с руут достъп наследяват именното пространство на запитващото приложение.</string>
|
||||
<string name="isolate_summary">Всички сесии с руут достъп имат собствени именни пространства.</string>
|
||||
<string name="android_o_not_support">Не поддържа Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Не са добавени пръстови отпечатъци или устройството не поддържа тази функция.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -24,6 +24,7 @@
|
||||
<string name="advanced_settings_title">Configuració avançada</string>
|
||||
<string name="keep_force_encryption">Mantenir el xifrat forçat</string>
|
||||
<string name="keep_dm_verity">Mantenir AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Mode de Recuperació</string>
|
||||
<string name="current_installed">Instal·lada: %1$s</string>
|
||||
<string name="latest_version">Última: %1$s</string>
|
||||
<string name="uninstall">Desinstal·lar</string>
|
||||
@@ -75,19 +76,18 @@
|
||||
<string name="manager_update_title">Actualització de Magisk Manager disponible!</string>
|
||||
|
||||
<!-- Installation -->
|
||||
<string name="manager_download_install">Prem per descarregar i instalar.</string>
|
||||
<string name="download_zip_only">Descarrega només el ZIP</string>
|
||||
<string name="manager_download_install">Premi per baixar i instalar.</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>
|
||||
<string name="select_method">Sel·lecciona mètode</string>
|
||||
<string name="select_method">Sel·lecciona un mètode</string>
|
||||
<string name="setup_title">Instal·lació addicional</string>
|
||||
<string name="select_patch_file">Sel·lecciona i arranja un arxiu</string>
|
||||
<string name="patch_file_msg">Sel·lecciona una imatge crua (*.img) o un ODIN tarfile (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Reinici en 5 segons…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Tancar</string>
|
||||
<string name="repo_install_title">Instal·lar %1$s</string>
|
||||
<string name="repo_install_msg">Vols instal·lar %1$s ara?</string>
|
||||
<string name="download">Baixar</string>
|
||||
@@ -110,23 +110,23 @@
|
||||
<string name="restore_img_msg">Restaurant…</string>
|
||||
<string name="restore_done">Restauració feta!</string>
|
||||
<string name="restore_fail">La còpia de seguretat de Stock no existeix!</string>
|
||||
<string name="proprietary_title">Descarrega 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\nPot permetre que Magisk Manager descarregui una extensió que conté el GoogleApiClient per poder fer la comprobació de SafetyNet?</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\nPot permetre que Magisk Manager baixi una extensió que conté el GoogleApiClient per poder fer la comprobació 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 descarregarà el ZIP d\'instal·lació de Magisk , vol procedir a l\'instalació ara?</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 l\'instalació ara?</string>
|
||||
<string name="setup_msg">S\'està executant la configuració de l\'entorn…</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
<string name="settings_dark_theme_title">Tema obscur</string>
|
||||
<string name="settings_dark_theme_summary">Habilitar el tema obscur</string>
|
||||
<string name="settings_download_path_title">Directori de descàrrega</string>
|
||||
<string name="settings_dark_theme_title">Tema fosc</string>
|
||||
<string name="settings_dark_theme_summary">Habilitar el tema fosc</string>
|
||||
<string name="settings_download_path_title">Directori de baixades</string>
|
||||
<string name="settings_download_path_message">Els arxius es desaràn a %1$s</string>
|
||||
<string name="settings_clear_cache_title">Netejar memòria cau del repositori</string>
|
||||
<string name="settings_clear_cache_summary">Neteja l\'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">Re-empaquetar Magisk Manager amb un nom de paquet a l\'atzar</string>
|
||||
<string name="settings_hide_manager_summary">Reempaquetar 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="language">Idioma</string>
|
||||
@@ -146,6 +146,10 @@
|
||||
<string name="settings_hosts_summary">Suport per aplicacions tipus Adblock fora de la partició del sistema</string>
|
||||
<string name="settings_hosts_toast">Agregat el mòdul Systemless Hosts</string>
|
||||
|
||||
<string name="settings_app_name">Escriu el nom desitjat per l\'App</string>
|
||||
<string name="settings_app_name_hint">Nou nom</string>
|
||||
<string name="settings_app_name_helper">Es refarà l\'App amb aquest nom</string>
|
||||
<string name="settings_app_name_error">Format invàl·lid</string>
|
||||
<string name="settings_su_app_adb">Aplicacions y ADB</string>
|
||||
<string name="settings_su_app">Només aplicacions</string>
|
||||
<string name="settings_su_adb">Només ADB</string>
|
||||
@@ -161,8 +165,8 @@
|
||||
<string name="request_timeout">Temps de petició</string>
|
||||
<string name="superuser_notification">Notificació de superusuari</string>
|
||||
<string name="request_timeout_summary">%1$d segons</string>
|
||||
<string name="settings_su_reauth_title">Re-autenticació</string>
|
||||
<string name="settings_su_reauth_summary">Demanar permisos de superusuari novament si una aplicació es actualitzada o reinstal·lada</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_fingerprint_title">Autenticació per Empremta Dactilar</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilitza el sensor d\'Empremta Dactilar per permetre les sol·licituds de superusuari</string>
|
||||
<string name="auth_fingerprint">Autenticar Emprempta Digital</string>
|
||||
@@ -174,7 +178,7 @@
|
||||
<string name="owner_only_summary">Només l\'administrador té accés d\'arrel</string>
|
||||
<string name="owner_manage_summary"> Només l\'administrador pot supervisar l\'acces d\'arrel y rebre sol·licituds d\'altres usuaris</string>
|
||||
<string name="user_indepenent_summary">Tots els usuaris tenen separades les seves pròpies regles d\'arrel </string>
|
||||
|
||||
|
||||
<string name="mount_namespace_mode">Muntar Namespace </string>
|
||||
<string name="settings_ns_global">Namespace Global</string>
|
||||
<string name="settings_ns_requester">Heretar Namespace</string>
|
||||
@@ -182,7 +186,6 @@
|
||||
<string name="global_summary">Totes les sessions d\'arrel utilitzen el suport Namespace Global</string>
|
||||
<string name="requester_summary">Les sessions d\'arrel heretaran les peticiones Namespace</string>
|
||||
<string name="isolate_summary">Totes les sessions d\'arrel tindran la seva pròpia Namespace</string>
|
||||
<string name="android_o_not_support">No es compatible amb Android 8.0+</string>
|
||||
<string name="disable_fingerprint">No s\'han establert empremtes dactilars o no existeix el suport del dispositiu</string>
|
||||
<string name="settings_download_path_error">Error al crear la carpeta. El directori ha de ser accesible desde el directori arrel i no pot ser un arxiu.</string>
|
||||
|
||||
@@ -217,7 +220,7 @@
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">UID de l\'objectiu: %1$d</string>
|
||||
<string name="command">Ordre: %1$s</string>
|
||||
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostra apps del sistema</string>
|
||||
|
||||
|
@@ -84,7 +84,6 @@
|
||||
<string name="reboot_delay_toast">Restartování za 5 sekund…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Zavřít</string>
|
||||
<string name="repo_install_title">Instalovat %1$s</string>
|
||||
<string name="repo_install_msg">Chcete nyní nainstalovat %1$s?</string>
|
||||
<string name="download">Stáhnout</string>
|
||||
@@ -175,7 +174,6 @@
|
||||
<string name="global_summary">Všechny relace root používají globální připojení jmenného prostoru.</string>
|
||||
<string name="requester_summary">Kořenové relace dědí jmenný prostor žadatele.</string>
|
||||
<string name="isolate_summary">Každá relace root bude mít svůj vlastní izolovaný jmenný prostor.</string>
|
||||
<string name="android_o_not_support">Nepodporuje Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Nebyly nastaveny žádné otisky prstů ani žádná podpora zařízení.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -84,7 +84,6 @@
|
||||
<string name="reboot_delay_toast">Neustart in 5 Sekunden…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Schließen</string>
|
||||
<string name="repo_install_title">Installiere %1$s</string>
|
||||
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
|
||||
<string name="download">Herunterladen</string>
|
||||
@@ -177,7 +176,6 @@
|
||||
<string name="global_summary">Alle Root-Sitzungen benutzen den global angelegten Namespace</string>
|
||||
<string name="requester_summary">Root-Sitzungen erben den Namespace des Abfragenden</string>
|
||||
<string name="isolate_summary">Jede Root-Sitzung hat ihren isolierten Namespace</string>
|
||||
<string name="android_o_not_support">Android 8.0+ wird nicht unterstützt</string>
|
||||
<string name="disable_fingerprint">Keine Fingerabdrücke gespeichert oder keine Geräteunterstützung</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -62,7 +62,6 @@
|
||||
<string name="app_changelog">Καταγραφή αλλαγών εφαρμογής</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Κλείσιμο</string>
|
||||
<string name="repo_install_title">Εγκατάσταση %1$s</string>
|
||||
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
|
||||
<string name="download">Λήψη</string>
|
||||
@@ -144,7 +143,6 @@
|
||||
<string name="global_summary">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
|
||||
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
|
||||
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
|
||||
<string name="android_o_not_support">Δεν υποστηρίζεται Android 8.0+</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Αίτημα υπερχρήστη</string>
|
||||
|
@@ -24,7 +24,7 @@
|
||||
<string name="advanced_settings_title">Ajustes avanzados</string>
|
||||
<string name="keep_force_encryption">Mantener cifrado forzado</string>
|
||||
<string name="keep_dm_verity">Mantener AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Modo Recovery</string>
|
||||
<string name="recovery_mode">Modo Recovery</string>
|
||||
<string name="current_installed">Instalada: %1$s</string>
|
||||
<string name="latest_version">Última: %1$s</string>
|
||||
<string name="uninstall">Desinstalar</string>
|
||||
@@ -45,7 +45,7 @@
|
||||
<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>
|
||||
<string name="reboot_edl">Reiniciar en Modo EDL</string>
|
||||
<string name="reboot_edl">Reiniciar en Modo EDL</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Actualización Disponible</string>
|
||||
@@ -72,21 +72,20 @@
|
||||
<string name="download_file_error">Error descargando 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>
|
||||
|
||||
<!-- Installation -->
|
||||
<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">¡Se forzará su dispositivo para que arranque en la ranura inactiva actual después de un reinicio!\nUtilice esta opción solo después de que se haya completado la OTA.\nContinuar?</string>
|
||||
<string name="select_method">Seleccionar Método</string>
|
||||
<string name="setup_title">Configuración Adicional</string>
|
||||
<string name="select_patch_file">Seleccionar y parchear un archivo</string>
|
||||
<string name="patch_file_msg">Seleccione una imagen raw (* .img) o un archivo tar de ODIN (* .tar)</string>
|
||||
<string name="reboot_delay_toast">Reiniciando en 5 segundos…</string>
|
||||
|
||||
|
||||
<!-- Installation -->
|
||||
<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">¡Se forzará su dispositivo para que arranque en la ranura inactiva actual después de un reinicio!\nUtilice esta opción solo después de que se haya completado la OTA.\nContinuar?</string>
|
||||
<string name="select_method">Seleccionar Método</string>
|
||||
<string name="setup_title">Configuración Adicional</string>
|
||||
<string name="select_patch_file">Seleccionar y parchear un archivo</string>
|
||||
<string name="patch_file_msg">Seleccione una imagen raw (* .img) o un archivo tar de ODIN (* .tar)</string>
|
||||
<string name="reboot_delay_toast">Reiniciando en 5 segundos…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Cerrar</string>
|
||||
<string name="repo_install_title">Instalar %1$s</string>
|
||||
<string name="repo_install_msg">¿Quieres instalar %1$s ahora?</string>
|
||||
<string name="download">Descargar</string>
|
||||
@@ -121,7 +120,7 @@
|
||||
<string name="settings_dark_theme_title">Tema oscuro</string>
|
||||
<string name="settings_dark_theme_summary">Habilitar el tema oscuro</string>
|
||||
<string name="settings_download_path_title">Ruta de Descarga</string>
|
||||
<string name="settings_download_path_message">Los archivos se guardarán en %1$s</string>
|
||||
<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>
|
||||
@@ -180,7 +179,6 @@
|
||||
<string name="global_summary">Todas las sesiones de root utilizan el soporte Global Namespace</string>
|
||||
<string name="requester_summary">Las sesiones de root heredarán las peticiones Namespace</string>
|
||||
<string name="isolate_summary">Cada sesión root tendrá su propia Namespace</string>
|
||||
<string name="android_o_not_support">No es compatible con Android 8.0+</string>
|
||||
<string name="disable_fingerprint">No se establecieron huellas dactilares o no existe soporte del dispositivo</string>
|
||||
<string name="settings_download_path_error">Error al crear la carpeta. Debe ser accesible desde el directorio raíz de almacenamiento y no debe ser un archivo.</string>
|
||||
|
||||
@@ -218,5 +216,5 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostrar sistema</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
@@ -88,7 +88,6 @@
|
||||
<string name="reboot_delay_toast">Taaskäivitamine 5 sekundi pärast…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Sulge</string>
|
||||
<string name="repo_install_title">Installi %1$s</string>
|
||||
<string name="repo_install_msg">Kas soovid kohe installida %1$s?</string>
|
||||
<string name="download">Allalaadimine</string>
|
||||
@@ -183,7 +182,6 @@
|
||||
<string name="global_summary">Kõik juurkasutaja sessioonid kasutavad globaalset monteerimise nimeruumi.</string>
|
||||
<string name="requester_summary">Juurkasutaja sessioonid võtavad üle selle taotleja nimeruumi.</string>
|
||||
<string name="isolate_summary">Iga juurkasutaja sessioon saab oma isoleeritud nimeruumi.</string>
|
||||
<string name="android_o_not_support">Ei toeta Androidi versiooni 8.0+.</string>
|
||||
<string name="disable_fingerprint">Sõrmejälgi pole määratud või seade pole toetatud.</string>
|
||||
<string name="settings_download_path_error">Faili loomisel esines viga. See peab olema ligipääsetav mäluruumi juurkaustast ning ei tohi olla fail.</string>
|
||||
|
||||
|
@@ -88,7 +88,6 @@
|
||||
<string name="reboot_delay_toast">Redémarrage dans 5 secondes…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Fermer</string>
|
||||
<string name="repo_install_title">Installer %1$s</string>
|
||||
<string name="repo_install_msg">Voulez‐vous installer %1$s maintenant ?</string>
|
||||
<string name="download">Télécharger</string>
|
||||
@@ -146,7 +145,10 @@
|
||||
<string name="settings_hosts_title">Fichier hosts sans système</string>
|
||||
<string name="settings_hosts_summary">Prise en charge du fichier hosts sans système pour les applications de type AdBlock.</string>
|
||||
<string name="settings_hosts_toast">Ajout d’un module hosts sans système</string>
|
||||
|
||||
<string name="settings_app_name">Taper le nom de l\'application désirée</string>
|
||||
<string name="settings_app_name_hint">Nouveau nom</string>
|
||||
<string name="settings_app_name_helper">L\'application sera réempacter sous ce nom</string>
|
||||
<string name="settings_app_name_error">Format invalide</string>
|
||||
<string name="settings_su_app_adb">Applications et ADB</string>
|
||||
<string name="settings_su_app">Applications uniquement</string>
|
||||
<string name="settings_su_adb">ADB uniquement</string>
|
||||
@@ -183,7 +185,6 @@
|
||||
<string name="global_summary">Toutes les sessions super‐utilisateur utilisent l’espace de noms global du montage.</string>
|
||||
<string name="requester_summary">Les sessions super‐utilisateur hériteront de l’espace de noms de leur demandeur.</string>
|
||||
<string name="isolate_summary">Chaque session super‐utilisateur aura son propre espace de noms isolé.</string>
|
||||
<string name="android_o_not_support">Android 8.0 et supérieurs ne sont pas pris en charge.</string>
|
||||
<string name="disable_fingerprint">Aucune empreinte digitale n’a été définie ou le lecteur d’empreinte n’est pas pris en charge.</string>
|
||||
<string name="settings_download_path_error">Erreur lors de la création du dossier. Il doit être accessible depuis le répertoire racine du stockage et ne doit pas être un fichier.</string>
|
||||
|
||||
|
223
app/src/main/res/values-hi/strings.xml
Normal file
223
app/src/main/res/values-hi/strings.xml
Normal file
@@ -0,0 +1,223 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">मॉड्यूल</string>
|
||||
<string name="downloads">डाउनलोड</string>
|
||||
<string name="superuser">उत्तम उपयोगकर्ता</string>
|
||||
<string name="log">अभिलेख</string>
|
||||
<string name="settings">सेटिंग्स</string>
|
||||
<string name="install">स्थापित करें</string>
|
||||
<string name="unsupport_magisk_title">असमर्थित Magisk संस्करण</string>
|
||||
<string name="unsupport_magisk_message">Magisk Manager का यह संस्करण Magisk के v18.0 संस्करण से कम का समर्थन नहीं करता है.\n\nआप या तो खुद से Magisk को अपग्रेड करें, या फिर एप्लीकेशन को पुराने संस्करण पे डाउनग्रेड करें .</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk स्थापित नहीं है</string>
|
||||
<string name="checking_for_updates">अपडेट्स के लिए जांच हो रही है…</string>
|
||||
<string name="invalid_update_channel">अमान्य अपडेट चैनल</string>
|
||||
<string name="safetyNet_check_text">SafetyNet की जांच शुरू करें</string>
|
||||
<string name="checking_safetyNet_status">SafetyNet के स्थिति की जाँच हो रही है…</string>
|
||||
<string name="safetyNet_check_success">SafetyNet की जांच सफल हुई</string>
|
||||
<string name="safetyNet_api_error">SafetyNet API त्रुटि</string>
|
||||
<string name="safetyNet_res_invalid">अनुक्रिया अमान्य है.</string>
|
||||
<string name="magisk_up_to_date">Magisk अप टू डेट है</string>
|
||||
<string name="manager_up_to_date">Magisk Manager अप टू डेट है</string>
|
||||
<string name="advanced_settings_title">एडवांस सेटिंग्स</string>
|
||||
<string name="keep_force_encryption">बल एन्क्रिप्शन को बनाये रखें</string>
|
||||
<string name="keep_dm_verity">AVB 2.0/dm-verity को बनाये रखें</string>
|
||||
<string name="recovery_mode">रिकवरी मोड</string>
|
||||
<string name="current_installed">स्थापित: %1$s</string>
|
||||
<string name="latest_version">नवीनतम: %1$s</string>
|
||||
<string name="uninstall">स्थापना रद्द करें</string>
|
||||
<string name="uninstall_magisk_title">Magisk की स्थापना रद्द करें</string>
|
||||
<string name="uninstall_magisk_msg">सभी मॉड्यूल अक्षम/हटा दिए जाएंगे. रुट और आपका संभावित रूप से एन्क्रिप्ट डाटा हटा दिया जाएगा.</string>
|
||||
<string name="update">अपडेट करें</string>
|
||||
<string name="core_only_enabled">(केवल मूल मोड समर्थकृत)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(कोई जानकारी प्रदान नहीं की गई)</string>
|
||||
<string name="no_modules_found">कोई मॉड्यूल नहीं मिला</string>
|
||||
<string name="update_file_created">मॉड्यूल अगले रिबूट पे अपडेट किया जाएगा !</string>
|
||||
<string name="remove_file_created">मॉड्यूल अगले रिबूट पे हटाया जाएगा !</string>
|
||||
<string name="remove_file_deleted">मॉड्यूल अगले रिबूट पे नहीं हटाया जाएगा !</string>
|
||||
<string name="disable_file_created">मॉड्यूल अगले रिबूट पे निर्योग्य किया जाएगा !</string>
|
||||
<string name="disable_file_removed">मॉड्यूल अगले रिबूट पे योग्य किया जाएगा !</string>
|
||||
<string name="author">%1$s के द्वारा बनाया गया</string>
|
||||
<string name="reboot_recovery">रिकवरी मोड में रिबूट करें</string>
|
||||
<string name="reboot_bootloader">बूटलोडर में रिबूट करें</string>
|
||||
<string name="reboot_download">डाउनलोड में रिबूट करें</string>
|
||||
<string name="reboot_edl">EDL मोड में रिबूट करें</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">अपडेट उपलब्ध है</string>
|
||||
<string name="installed">स्थापित</string>
|
||||
<string name="not_installed">स्थापित नहीं है</string>
|
||||
<string name="updated_on">%1$s को अपडेट किया गया</string>
|
||||
<string name="sorting_order">छँटाई क्रम </string>
|
||||
<string name="sort_by_name">नाम द्वारा छांटें</string>
|
||||
<string name="sort_by_update">आखिरी अपडेट द्वारा छांटें</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">अभिलेख सेव करें</string>
|
||||
<string name="menuReload">पुनः लोड करें</string>
|
||||
<string name="menuClearLog">अभिलेख साफ़ करें</string>
|
||||
<string name="logs_cleared">अभिलेख सफलतापूर्वक साफ़ हो गया.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">परिवर्तन अभिलेख</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="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>
|
||||
|
||||
<!-- Installation -->
|
||||
<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>
|
||||
<string name="select_method">विधि का चयन करें</string>
|
||||
<string name="setup_title">अतिरिक्त सेटअप</string>
|
||||
<string name="select_patch_file">एक फ़ाइल का चयन और पैच करें</string>
|
||||
<string name="patch_file_msg">एक कच्ची इमेज चुनें (*.img) या एक ODIN tarfile (*.tar)</string>
|
||||
<string name="reboot_delay_toast">5 सेकंड में रिबूट हो रहा है …</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="settings_reboot_toast">सेटिंग्स लागू करने के लिए रिबूट करें.</string>
|
||||
<string name="release_notes">रिलीज नोट्स</string>
|
||||
<string name="repo_cache_cleared">Repo cache साफ़ हो गया</string>
|
||||
|
||||
<string name="dtbo_patched_title">DTBO पैच कर दिया गया!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ने dtbo.img को पैच कर दिया. कृपया रिबूट करें.</string>
|
||||
<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="warning">चेतावनी</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 Manager FOSS है और उस्में Google का मालिकाना 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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">सामान्य</string>
|
||||
<string name="settings_dark_theme_title">डार्क थीम</string>
|
||||
<string name="settings_dark_theme_summary">डार्क थीम सक्षम करें.</string>
|
||||
<string name="settings_download_path_title">डाउनलोड करने की जगह</string>
|
||||
<string name="settings_download_path_message">%1$s में फाइल्स रखी जाएँगी</string>
|
||||
<string name="settings_clear_cache_title">Repo Cache साफ़ करें</string>
|
||||
<string name="settings_clear_cache_summary">ऑनलाइन Repo के लिए Cached जानकारी साफ़ करें. यह एप्लिकेशन को ऑनलाइन रिफ्रेश होने के लिए मजबूर करता है.</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_update">सेटिंग्स अपडेट करें</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">एक कस्टम URL डालें</string>
|
||||
<string name="settings_core_only_title">Magisk का केवल मूल मोड</string>
|
||||
<string name="settings_core_only_summary">केवल मुख्य विशेषताएं सक्षम करें. MagiskSU और MagiskHide अभी भी सक्षम रहेंगे, लेकिन कोई मॉड्यूल लोड नहीं किया जाएगा.</string>
|
||||
<string name="settings_magiskhide_summary">पता लगाने के विभिन्न रूपों से Magisk को छुपाएं.</string>
|
||||
<string name="settings_hosts_title">सिस्टमलेस होस्ट्स</string>
|
||||
<string name="settings_hosts_summary">एडब्लॉक ऍप्लिकेशन्स के लिए सिस्टमलेस होस्ट्स का समर्थन</string>
|
||||
<string name="settings_hosts_toast">सिस्टमलेस होस्ट्स का मॉड्यूल जोड़ दिया गया</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="request_timeout_summary">%1$d सेकंड्स</string>
|
||||
<string name="settings_su_reauth_title">अपग्रेड के बाद फिर से प्रमाणित करें</string>
|
||||
<string name="settings_su_reauth_summary">एप्लीकेशन अपग्रेड होने के बाद उत्तम उपयोगकर्ता की अनुमतियों को फिर से प्रमाणित करें</string>
|
||||
<string name="settings_su_fingerprint_title">फिंगरप्रिंट प्रमाणीकरण सक्षम करें</string>
|
||||
<string name="settings_su_fingerprint_summary">उत्तम उपयोगकर्ता के अनुरोधों की अनुमति के लिए फिंगरप्रिंट स्कैनर का उपयोग करें</string>
|
||||
<string name="auth_fingerprint">फिंगरप्रिंट को प्रमाणित करें</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="user_indepenent_summary">प्रत्येक उपयोगकर्ता का अपना अलग रूट नियम होता है.</string>
|
||||
|
||||
<string name="mount_namespace_mode">माउंट नेमस्पेस मोड</string>
|
||||
<string name="settings_ns_global">वैश्विक नेमस्पेस</string>
|
||||
<string name="settings_ns_requester">नेमस्पेस को इन्हेरिट करें</string>
|
||||
<string name="settings_ns_isolate">संगरोध नेमस्पेस</string>
|
||||
<string name="global_summary">सभी रूट सत्र वैश्विक माउंट नेमस्पेस का उपयोग करते हैं.</string>
|
||||
<string name="requester_summary">रूट सत्रों को उनके अनुरोधकर्ताओं के नेमस्पेस विरासत में मिलेंगे.</string>
|
||||
<string name="isolate_summary">प्रत्येक रूट सत्र का अपना अलग नेमस्पेस होगा.</string>
|
||||
<string name="disable_fingerprint">कोई फ़िंगरप्रिंट नहीं सेट किया गया या डिवाइस का समर्थन नहीं है.</string>
|
||||
<string name="settings_download_path_error">फोल्डर बनाने में त्रुटि. यह स्टोरेज रूट डायरेक्टरी से एक्सेस होना चाहिए और फाइल नहीं होना चाहिए.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">उत्तम उपयोगकर्ता का अनुरोध</string>
|
||||
<string name="deny">इंकार करें</string>
|
||||
<string name="prompt">आदेश</string>
|
||||
<string name="grant">अनुमति दें</string>
|
||||
<string name="su_warning">यह आपके डिवाइस की पूरी पहुँच की अनुमति देगा. यदि आप सुनिश्चित नहीं हैं तो इंकार करें!</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="no_apps_found">कोई एप्लीकेशन नहीं मिला</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>
|
||||
<string name="auth_fail">प्रमाणीकरण विफल हुआ</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">लक्ष्य UID: %1$d</string>
|
||||
<string name="command">Command: %1$s</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">सिस्टम ऍप्लिकेशन्स दिखाएं</string>
|
||||
|
||||
</resources>
|
@@ -55,7 +55,6 @@
|
||||
<string name="app_changelog">Popis izmjena aplikacije</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Zatvori</string>
|
||||
<string name="repo_install_title">Instaliraj %1$s</string>
|
||||
<string name="repo_install_msg">Da li želite instalirati %1$s sada?</string>
|
||||
<string name="download">Preuzmi</string>
|
||||
|
@@ -86,7 +86,6 @@
|
||||
<string name="reboot_delay_toast">Me-reboot dalam 5 detik…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Tutup</string>
|
||||
<string name="repo_install_title">Pasang %1$s</string>
|
||||
<string name="repo_install_msg">Apakah Anda ingin memasang %1$s sekarang?</string>
|
||||
<string name="download">Unduh</string>
|
||||
@@ -181,7 +180,6 @@
|
||||
<string name="global_summary">Semua sesi root menggunakan mount ruang nama global.</string>
|
||||
<string name="requester_summary">Sesi root akan mewarisi ruang nama peminta mereka.</string>
|
||||
<string name="isolate_summary">Setiap sesi root akan memiliki ruang nama tersendiri.</string>
|
||||
<string name="android_o_not_support">Tidak mendukung Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Tidak ada sidik jari diatur atau tidak ada dukungan perangkat.</string>
|
||||
<string name="settings_download_path_error">Kesalahan membuat folder. Folder harus dapat diakses dari direktori penyimpanan root dan bukan merupakan file.</string>
|
||||
|
||||
|
@@ -1,223 +1,225 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="downloads">Download</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="log">Registro eventi</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="install">Installa</string>
|
||||
<string name="unsupport_magisk_title">Versione di Magisk non supportata</string>
|
||||
<string name="unsupport_magisk_message">Questa versione di Magisk Manager non supporta versioni di Magisk inferiori alla v18.0.\n\nPuoi aggiornare manualmente Magisk o tornare a una versione meno recente dell\'app.</string>
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="downloads">Download</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="log">Registro eventi</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="install">Installa</string>
|
||||
<string name="unsupport_magisk_title">Versione di Magisk non supportata</string>
|
||||
<string name="unsupport_magisk_message">Questa versione di Magisk Manager non supporta versioni di Magisk inferiori alla v18.0.\n\nPuoi aggiornare manualmente Magisk o tornare a una versione meno recente dell\'app.</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk non è installato.</string>
|
||||
<string name="checking_for_updates">Controllo aggiornamenti…</string>
|
||||
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
|
||||
<string name="safetyNet_check_text">Tocca per controllare SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">Controllo stato SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Controllo SafetyNet Superato</string>
|
||||
<string name="safetyNet_api_error">Errore API SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">La risposta non è valida.</string>
|
||||
<string name="magisk_up_to_date">Magisk è aggiornato</string>
|
||||
<string name="manager_up_to_date">Magisk Manager è aggiornato</string>
|
||||
<string name="advanced_settings_title">Impostazioni avanzate</string>
|
||||
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
|
||||
<string name="keep_dm_verity">Mantieni AVB 2.0/dm-verity</string>
|
||||
<string name="current_installed">Installata: %1$s</string>
|
||||
<string name="latest_version">Ultima: %1$s</string>
|
||||
<string name="uninstall">Disinstalla</string>
|
||||
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi. Il root verrà rimosso e i tuoi dati potrebbero essere criptati, nel caso non lo siano già.</string>
|
||||
<string name="update">Aggiorna</string>
|
||||
<string name="core_only_enabled">(Modalità solo Core abilitata)</string>
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk non è installato.</string>
|
||||
<string name="checking_for_updates">Controllo aggiornamenti…</string>
|
||||
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
|
||||
<string name="safetyNet_check_text">Tocca per controllare SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">Controllo stato SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Controllo SafetyNet Superato</string>
|
||||
<string name="safetyNet_api_error">Errore API SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">La risposta non è valida</string>
|
||||
<string name="magisk_up_to_date">Magisk è aggiornato</string>
|
||||
<string name="manager_up_to_date">Magisk Manager è aggiornato</string>
|
||||
<string name="advanced_settings_title">Impostazioni avanzate</string>
|
||||
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
|
||||
<string name="keep_dm_verity">Mantieni AVB 2.0/dm-verity</string>
|
||||
<string name="current_installed">Installata: %1$s</string>
|
||||
<string name="latest_version">Ultima: %1$s</string>
|
||||
<string name="uninstall">Disinstalla</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>
|
||||
<string name="update">Aggiorna</string>
|
||||
<string name="core_only_enabled">(Modalità solo Core abilitata)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nessuna informazione)</string>
|
||||
<string name="no_modules_found">Nessun modulo trovato.</string>
|
||||
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio.</string>
|
||||
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio.</string>
|
||||
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio.</string>
|
||||
<string name="author">Creato da: %1$s</string>
|
||||
<string name="reboot_recovery">Riavvia in Recovery</string>
|
||||
<string name="reboot_bootloader">Riavvia in Bootloader</string>
|
||||
<string name="reboot_download">Riavvia in Download Mode</string>
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nessuna informazione)</string>
|
||||
<string name="no_modules_found">Nessun modulo trovato.</string>
|
||||
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio.</string>
|
||||
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio.</string>
|
||||
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio.</string>
|
||||
<string name="author">Creato da: %1$s</string>
|
||||
<string name="reboot_recovery">Riavvia in Recovery</string>
|
||||
<string name="reboot_bootloader">Riavvia in Bootloader</string>
|
||||
<string name="reboot_download">Riavvia in Download Mode</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Aggiornamento disponibile</string>
|
||||
<string name="installed">Installato</string>
|
||||
<string name="not_installed">Non installato</string>
|
||||
<string name="updated_on">Aggiornato il: %1$s</string>
|
||||
<string name="sorting_order">Ordinamento</string>
|
||||
<string name="sort_by_name">Ordina per nome</string>
|
||||
<string name="sort_by_update">Ordina per ultimo aggiornamento</string>
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Aggiornamento disponibile</string>
|
||||
<string name="installed">Installato</string>
|
||||
<string name="not_installed">Non installato</string>
|
||||
<string name="updated_on">Aggiornato il: %1$s</string>
|
||||
<string name="sorting_order">Ordinamento</string>
|
||||
<string name="sort_by_name">Ordina per nome</string>
|
||||
<string name="sort_by_update">Ordina per ultimo aggiornamento</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">Salva registro eventi</string>
|
||||
<string name="menuReload">Ricarica</string>
|
||||
<string name="menuClearLog">Svuota il registro eventi</string>
|
||||
<string name="logs_cleared">Registro eventi svuotato correttamente.</string>
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">Salva registro eventi</string>
|
||||
<string name="menuReload">Ricarica</string>
|
||||
<string name="menuClearLog">Svuota il registro eventi</string>
|
||||
<string name="logs_cleared">Registro eventi svuotato correttamente.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">Novità</string>
|
||||
<string name="app_changelog">Novità</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Aggiornamenti Magisk</string>
|
||||
<string name="progress_channel">Notifiche di avanzamento</string>
|
||||
<string name="download_complete">Download completato</string>
|
||||
<string name="update_channel">Aggiornamenti Magisk</string>
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<!-- Installation -->
|
||||
<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 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 OTA è stato installato.\nVuoi continuare?</string>
|
||||
<string name="select_method">Seleziona un metodo</string>
|
||||
<string name="setup_title">Configurazione aggiuntiva</string>
|
||||
<string name="select_patch_file">Seleziona e aggiorna un file</string>
|
||||
<string name="patch_file_msg">Seleziona un\'immagine in formato .img o un file ODIN .tar</string>
|
||||
<string name="reboot_delay_toast">Riavvio fra 5 secondi…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Chiudi</string>
|
||||
<string name="repo_install_title">Installazione di %1$s</string>
|
||||
<string name="repo_install_msg">Vuoi installare %1$s?</string>
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Riavvia</string>
|
||||
<string name="settings_reboot_toast">Riavvia per applicare i cambiamenti.</string>
|
||||
<string name="release_notes">Note di rilascio</string>
|
||||
<string name="repo_cache_cleared">La cache delle repository è stata svuotata</string>
|
||||
<!-- Installation -->
|
||||
<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 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 OTA è stato installato.\nVuoi continuare?</string>
|
||||
<string name="select_method">Seleziona un metodo</string>
|
||||
<string name="setup_title">Configurazione aggiuntiva</string>
|
||||
<string name="select_patch_file">Seleziona e aggiorna un file</string>
|
||||
<string name="patch_file_msg">Seleziona un\'immagine in formato .img o un file ODIN .tar</string>
|
||||
<string name="reboot_delay_toast">Riavvio fra 5 secondi…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">Installazione di %1$s</string>
|
||||
<string name="repo_install_msg">Vuoi installare %1$s?</string>
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Riavvia</string>
|
||||
<string name="settings_reboot_toast">Riavvia per applicare i cambiamenti</string>
|
||||
<string name="release_notes">Note di rilascio</string>
|
||||
<string name="repo_cache_cleared">La cache delle repository è stata svuotata</string>
|
||||
|
||||
<string name="dtbo_patched_title">DTBO è stato aggiornato!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img. Riavvia per completare.</string>
|
||||
<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="open_link_failed_toast">Nessuna app disponibile per aprire il link.</string>
|
||||
<string name="warning">Attenzione</string>
|
||||
<string name="complete_uninstall">Disinstallazione completa</string>
|
||||
<string name="restore_img">Ripristina Immagini</string>
|
||||
<string name="restore_img_msg">Ripristino…</string>
|
||||
<string name="restore_done">Ripristino completato!</string>
|
||||
<string name="restore_fail">Non esiste un\'immagine originale di boot!</string>
|
||||
<string name="proprietary_title">Scarica codice proprietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager è FOSS e non contiene codice proprietario delle API Google SafetyNet.\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="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img. Riavvia per completare.</string>
|
||||
<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="open_link_failed_toast">Nessuna app disponibile per aprire il link</string>
|
||||
<string name="warning">Attenzione</string>
|
||||
<string name="complete_uninstall">Disinstallazione completa</string>
|
||||
<string name="restore_img">Ripristina Immagini</string>
|
||||
<string name="restore_img_msg">Ripristino…</string>
|
||||
<string name="restore_done">Ripristino completato!</string>
|
||||
<string name="restore_fail">Non esiste un\'immagine originale di boot!</string>
|
||||
<string name="proprietary_title">Scarica codice proprietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager è FOSS e non contiene codice proprietario delle API Google SafetyNet.\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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Generale</string>
|
||||
<string name="settings_dark_theme_title">Tema scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita il tema scuro.</string>
|
||||
<string name="settings_dark_theme_title">Tema scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita il tema scuro</string>
|
||||
<string name="settings_download_path_title">Percorso di download</string>
|
||||
<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 delle repository. Questa opzione forza l\'aggiornamento online dell\'app.</string>
|
||||
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome pacchetto casuale.</string>
|
||||
<string name="settings_restore_manager_title">Ripristina Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Ripristina Magisk Manager con il nome pacchetto originale</string>
|
||||
<string name="language">Lingua</string>
|
||||
<string name="system_default">(Sistema)</string>
|
||||
<string name="settings_update">Impostazioni aggiornamento</string>
|
||||
<string name="settings_check_update_title">Controlla aggiornamenti</string>
|
||||
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti in background.</string>
|
||||
<string name="settings_update_channel_title">Canale di aggiornamento</string>
|
||||
<string name="settings_update_stable">Stabile</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Personalizzato</string>
|
||||
<string name="settings_update_custom_msg">Inserisci un URL personalizzato</string>
|
||||
<string name="settings_core_only_title">Modalità Magisk Core</string>
|
||||
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU e MagiskHide rimarranno abilitati</string>
|
||||
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni.</string>
|
||||
<string name="settings_hosts_title">Host systemless</string>
|
||||
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità.</string>
|
||||
<string name="settings_hosts_toast">Aggiunto modulo per host systemless</string>
|
||||
<string name="settings_clear_cache_title">Svuota cache repository</string>
|
||||
<string name="settings_clear_cache_summary">Svuota la cache delle repository. Questa opzione forza l\'aggiornamento online dell\'app</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_update">Impostazioni aggiornamento</string>
|
||||
<string name="settings_check_update_title">Controlla aggiornamenti</string>
|
||||
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti in background</string>
|
||||
<string name="settings_update_channel_title">Canale di aggiornamento</string>
|
||||
<string name="settings_update_stable">Stabile</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Personalizzato</string>
|
||||
<string name="settings_update_custom_msg">Inserisci un URL personalizzato</string>
|
||||
<string name="settings_core_only_title">Modalità Magisk Core</string>
|
||||
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU e MagiskHide rimarranno abilitati</string>
|
||||
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
|
||||
<string name="settings_hosts_title">Host systemless</string>
|
||||
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità</string>
|
||||
<string name="settings_hosts_toast">Aggiunto modulo per host systemless</string>
|
||||
|
||||
<string name="settings_app_name">Inserisci il nome desiderato per l\'app</string>
|
||||
<string name="settings_app_name_hint">Nuovo nome</string>
|
||||
<string name="settings_app_name_helper">L\'app sarà ricreata con questo nome</string>
|
||||
<string name="settings_app_name_error">Formato non valido</string>
|
||||
<string name="settings_su_app_adb">App e ADB</string>
|
||||
<string name="settings_su_app">Solo app</string>
|
||||
<string name="settings_su_adb">Solo ADB</string>
|
||||
<string name="settings_su_disable">Disabilitato</string>
|
||||
<string name="settings_su_request_10">10 secondi</string>
|
||||
<string name="settings_su_request_15">15 secondi</string>
|
||||
<string name="settings_su_request_20">20 secondi</string>
|
||||
<string name="settings_su_request_30">30 secondi</string>
|
||||
<string name="settings_su_request_45">45 secondi</string>
|
||||
<string name="settings_su_request_60">60 secondi</string>
|
||||
<string name="superuser_access">Accesso Superuser</string>
|
||||
<string name="auto_response">Accesso predefinito</string>
|
||||
<string name="request_timeout">Timeout richiesta</string>
|
||||
<string name="superuser_notification">Notifica Superuser</string>
|
||||
<string name="request_timeout_summary">%1$d secondi</string>
|
||||
<string name="settings_su_reauth_title">Riautentica dopo aggiornamento</string>
|
||||
<string name="settings_su_reauth_summary">Riautentica i permessi Superuser dopo un aggiornamento dell\'app</string>
|
||||
<string name="settings_su_fingerprint_title">Abilita autenticazione impronta</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilizza il sensore di impronte per accettare le richieste Superuser</string>
|
||||
<string name="auth_fingerprint">Conferma impronta</string>
|
||||
<string name="settings_su_app">Solo app</string>
|
||||
<string name="settings_su_adb">Solo ADB</string>
|
||||
<string name="settings_su_disable">Disabilitato</string>
|
||||
<string name="settings_su_request_10">10 secondi</string>
|
||||
<string name="settings_su_request_15">15 secondi</string>
|
||||
<string name="settings_su_request_20">20 secondi</string>
|
||||
<string name="settings_su_request_30">30 secondi</string>
|
||||
<string name="settings_su_request_45">45 secondi</string>
|
||||
<string name="settings_su_request_60">60 secondi</string>
|
||||
<string name="superuser_access">Accesso Superuser</string>
|
||||
<string name="auto_response">Accesso predefinito</string>
|
||||
<string name="request_timeout">Timeout richiesta</string>
|
||||
<string name="superuser_notification">Notifica Superuser</string>
|
||||
<string name="request_timeout_summary">%1$d secondi</string>
|
||||
<string name="settings_su_reauth_title">Riautentica dopo aggiornamento</string>
|
||||
<string name="settings_su_reauth_summary">Riautentica i permessi Superuser dopo un aggiornamento dell\'app</string>
|
||||
<string name="settings_su_fingerprint_title">Abilita autenticazione impronta</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilizza il sensore di impronte per accettare le richieste Superuser</string>
|
||||
<string name="auth_fingerprint">Conferma impronta</string>
|
||||
|
||||
<string name="multiuser_mode">Modalità multiutente</string>
|
||||
<string name="settings_owner_only">Solo proprietario del dispositivo</string>
|
||||
<string name="settings_owner_manage">Gestito dal proprietario utente</string>
|
||||
<string name="settings_user_independent">Idipendente dall\'utente</string>
|
||||
<string name="owner_only_summary">Solo il proprietario ha i permessi di root.</string>
|
||||
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste.</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root indpendenti.</string>
|
||||
<string name="multiuser_mode">Modalità multiutente</string>
|
||||
<string name="settings_owner_only">Solo proprietario del dispositivo</string>
|
||||
<string name="settings_owner_manage">Gestito dal proprietario utente</string>
|
||||
<string name="settings_user_independent">Idipendente dall\'utente</string>
|
||||
<string name="owner_only_summary">Solo il proprietario ha i permessi di root</string>
|
||||
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root indpendenti</string>
|
||||
|
||||
<string name="mount_namespace_mode">Modalità mount namespace</string>
|
||||
<string name="settings_ns_global">Namespace globale</string>
|
||||
<string name="settings_ns_requester">Namespace ereditato</string>
|
||||
<string name="settings_ns_isolate">Namespace isolato</string>
|
||||
<string name="global_summary">Tutte le sessioni di root erediteranno il namespace globale.</string>
|
||||
<string name="requester_summary">Le sessioni di root erediteranno il namespace del loro richiedente.</string>
|
||||
<string name="isolate_summary">Ogni sessione di root avrà il suo namespace isolato.</string>
|
||||
<string name="android_o_not_support">Non è supportato da Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Non è presente alcuna impronta o il dispositivo non è supportato.</string>
|
||||
<string name="settings_download_path_error">Errore durante la creazione della cartella. Deve essere accessibile dalla radice della memoria di archiviazione e non essere un file.</string>
|
||||
<string name="mount_namespace_mode">Modalità mount namespace</string>
|
||||
<string name="settings_ns_global">Namespace globale</string>
|
||||
<string name="settings_ns_requester">Namespace ereditato</string>
|
||||
<string name="settings_ns_isolate">Namespace isolato</string>
|
||||
<string name="global_summary">Tutte le sessioni di root erediteranno il namespace globale</string>
|
||||
<string name="requester_summary">Le sessioni di root erediteranno il namespace del loro richiedente</string>
|
||||
<string name="isolate_summary">Ogni sessione di root avrà il suo namespace isolato</string>
|
||||
<string name="disable_fingerprint">Non è presente alcuna impronta o il dispositivo non è supportato</string>
|
||||
<string name="settings_download_path_error">Errore durante la creazione della cartella. Deve essere accessibile dalla radice della memoria di archiviazione e non essere un file.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Richiesta Superuser</string>
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Richiesta Superuser</string>
|
||||
<string name="deny">Nega</string>
|
||||
<string name="prompt">Chiedi</string>
|
||||
<string name="grant">Concedi</string>
|
||||
<string name="su_warning">Concede il pieno accesso al dispositivo.\nNega se non sei sicuro!</string>
|
||||
<string name="forever">Sempre</string>
|
||||
<string name="once">Una volta</string>
|
||||
<string name="tenmin">10 minuti</string>
|
||||
<string name="twentymin">20 minuti</string>
|
||||
<string name="thirtymin">30 minuti</string>
|
||||
<string name="sixtymin">60 minuti</string>
|
||||
<string name="su_allow_toast">%1$s ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_deny_toast">%1$s non ha ottenuto i permessi Superuser</string>
|
||||
<string name="no_apps_found">Nessuna app trovata</string>
|
||||
<string name="su_snack_grant"> %1$s ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_deny"> %1$s non ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_notif_on">Notifiche per %1$s abilitate</string>
|
||||
<string name="su_snack_notif_off">Notifiche per %1$s disabilitate</string>
|
||||
<string name="su_snack_log_on">Registro eventi abilitato per %1$s</string>
|
||||
<string name="su_snack_log_off">Registro eventi non abilitato per %1$s</string>
|
||||
<string name="prompt">Chiedi</string>
|
||||
<string name="grant">Concedi</string>
|
||||
<string name="su_warning">Concede il pieno accesso al dispositivo.\nNega se non sei sicuro!</string>
|
||||
<string name="forever">Sempre</string>
|
||||
<string name="once">Una volta</string>
|
||||
<string name="tenmin">10 minuti</string>
|
||||
<string name="twentymin">20 minuti</string>
|
||||
<string name="thirtymin">30 minuti</string>
|
||||
<string name="sixtymin">60 minuti</string>
|
||||
<string name="su_allow_toast">%1$s ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_deny_toast">%1$s non ha ottenuto i permessi Superuser</string>
|
||||
<string name="no_apps_found">Nessuna app trovata</string>
|
||||
<string name="su_snack_grant"> %1$s ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_deny"> %1$s non ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_notif_on">Notifiche per %1$s abilitate</string>
|
||||
<string name="su_snack_notif_off">Notifiche per %1$s disabilitate</string>
|
||||
<string name="su_snack_log_on">Registro eventi abilitato per %1$s</string>
|
||||
<string name="su_snack_log_off">Registro eventi non abilitato per %1$s</string>
|
||||
<string name="su_revoke_title">Vuoi revocare?</string>
|
||||
<string name="su_revoke_msg">Confermi la revoca dei diritti di %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Nessuno</string>
|
||||
<string name="auth_fail">Autenticatione fallita</string>
|
||||
<string name="su_revoke_msg">Confermi la revoca dei diritti di %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Nessuno</string>
|
||||
<string name="auth_fail">Autenticatione fallita</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">UID destinazione: %1$d</string>
|
||||
<string name="command">Comando: %1$s</string>
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">UID destinazione: %1$d</string>
|
||||
<string name="command">Comando: %1$s</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostra app di sistema</string>
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Mostra app di sistema</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -72,7 +72,6 @@
|
||||
<string name="manager_update_title">Magisk Managerの更新があります!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">閉じる</string>
|
||||
<string name="repo_install_title">%1$s をインストール</string>
|
||||
<string name="repo_install_msg">%1$s をインストールしますか?</string>
|
||||
<string name="download">ダウンロード</string>
|
||||
@@ -169,7 +168,6 @@
|
||||
<string name="global_summary">すべてのrootセッションがグローバル名前空間を使用します</string>
|
||||
<string name="requester_summary">rootセッションはリクエスト者の名前空間を継承します</string>
|
||||
<string name="isolate_summary">rootセッション毎に分離された名前空間を使用します</string>
|
||||
<string name="android_o_not_support">Android 8.0以降では対応していません</string>
|
||||
<string name="disable_fingerprint">指紋が登録されていないか、お使いの端末でサポートされていません。</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -83,7 +83,6 @@
|
||||
<string name="patch_file_msg">원시 이미지 (*.img) 또는 오딘 tar 파일 (*.tar) 선택</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">닫기</string>
|
||||
<string name="repo_install_title">%1$s 설치</string>
|
||||
<string name="repo_install_msg">정말 %1$s을(를) 설치하시겠습니까?</string>
|
||||
<string name="download">다운로드</string>
|
||||
@@ -176,7 +175,6 @@
|
||||
<string name="global_summary">모든 루트 세션이 전역 마운트 이름공간을 사용합니다.</string>
|
||||
<string name="requester_summary">루트 세션은 요청자의 이름공간을 상속합니다.</string>
|
||||
<string name="isolate_summary">각각의 루트 세션은 자신만의 독립된 이름공간을 사용합니다.</string>
|
||||
<string name="android_o_not_support">안드로이드 8.0 이상 버전에서 사용할 수 없습니다.</string>
|
||||
<string name="disable_fingerprint">지문이 등록되지 않았거나 기기가 지문 인식을 지원하지 않습니다.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -61,7 +61,6 @@
|
||||
<string name="app_changelog">Pakeitimų sąrašas</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Uždaryti</string>
|
||||
<string name="repo_install_title">Instaliuoti %1$s</string>
|
||||
<string name="repo_install_msg">Ar jūs norite instaliuoti %1$s?</string>
|
||||
<string name="download">Atsisiųsti</string>
|
||||
@@ -156,7 +155,6 @@
|
||||
<string name="global_summary">Visos root sesijos naudoja globalią vardų sritį</string>
|
||||
<string name="requester_summary">Root sesijos paveldi jos išprašytojo/s vardų sritį</string>
|
||||
<string name="isolate_summary">Kiekviena root sesija turi savo izoliuotą vardų sritį</string>
|
||||
<string name="android_o_not_support">Įrenginiai su Android 8.0+ nepalaiko šio nustatymo</string>
|
||||
<string name="disable_fingerprint">Jūsų įrenginyje nebuvo surasta pirštų antspaudų arba jūsų įrenginys neturi pirštų antspaudų skaitytuvo</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -84,7 +84,6 @@
|
||||
<string name="reboot_delay_toast">Рестартирање за 5 секунди…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Затвори</string>
|
||||
<string name="repo_install_title">Инсталирај %1$s</string>
|
||||
<string name="repo_install_msg">Дали сакате да го инсталирате %1$s сега?</string>
|
||||
<string name="download">Преземи</string>
|
||||
@@ -175,7 +174,6 @@
|
||||
<string name="global_summary">Сите рут сесии го користат глобалниот именски простор.</string>
|
||||
<string name="requester_summary">Рут сесиите ќе го наследат именскиот простор на нивниот барател.</string>
|
||||
<string name="isolate_summary">Секоја рут сесија ќе има свој изолиран именски простор.</string>
|
||||
<string name="android_o_not_support">Не е поддржано на Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Нема регистрирано отпечатоци од прсти или уредот не ја поддржува оваа функција.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -69,7 +69,6 @@
|
||||
<string name="manager_update_title">En Magisk Manager-oppdatering er tilgjengelig!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Lukk</string>
|
||||
<string name="repo_install_title">Installer %1$s</string>
|
||||
<string name="repo_install_msg">Vil du installere %1$s nå?</string>
|
||||
<string name="download">Last ned</string>
|
||||
@@ -166,7 +165,6 @@
|
||||
<string name="global_summary">Alle root-økter benytter det altdekkende monteringsnavnefeltet.</string>
|
||||
<string name="requester_summary">Root-økter vil arve forespørrerens navnefelt.</string>
|
||||
<string name="isolate_summary">Hver root-økt vil ha sitt eget isolerte navnefelt.</string>
|
||||
<string name="android_o_not_support">Støtter ikke Android ≥8.0.</string>
|
||||
<string name="disable_fingerprint">Ingen fingeravtrykk ble gitt, eller så støttes det ikke av enheten.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -62,7 +62,6 @@
|
||||
<string name="app_changelog">App\'s changelog</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Sluiten</string>
|
||||
<string name="repo_install_title">%1$s installeren</string>
|
||||
<string name="repo_install_msg">Zeker weten %1$s installeren?</string>
|
||||
<string name="download">Downloaden</string>
|
||||
@@ -151,7 +150,6 @@
|
||||
<string name="global_summary">Alle rootsessies gebruiken de globale naamruimte</string>
|
||||
<string name="requester_summary">Rootsessies verkrijgen de verzoeker\'s naamruimte</string>
|
||||
<string name="isolate_summary">Iedere rootsessie heeft een eigen geïsoleerde naamruimte</string>
|
||||
<string name="android_o_not_support">Ondersteunt geen Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Geen vingerafdrukken ingesteld, of geen apparaatondersteuning</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -9,12 +9,12 @@
|
||||
<string name="install">Instaluj</string>
|
||||
<string name="unsupport_magisk_title">Nieobsługiwana Wersja Magisk</string>
|
||||
<string name="unsupport_magisk_message">Ta wersja Magisk Managera nie obsługuje wersji Magisk niższej niż v18.0.\n\nMożesz albo ręcznie zaktualizować Magisk lub obniżyć w aplikacji do starszej wersji.</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk nie jest zainstalowany.</string>
|
||||
<string name="checking_for_updates">Sprawdzanie aktualizacji…</string>
|
||||
<string name="invalid_update_channel">Nieprawidłowy Kanał Aktualizacji</string>
|
||||
<string name="safetyNet_check_text">Dotknij aby sprawdzić SafetyNet</string>
|
||||
<string name="safetyNet_check_text">Dotknij aby sprawdzić SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">Sprawdzanie statusu SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">SafetyNet Poprawny</string>
|
||||
<string name="safetyNet_api_error">SafetyNet API Błędny</string>
|
||||
@@ -28,11 +28,11 @@
|
||||
<string name="latest_version">Ostatnia: %1$s</string>
|
||||
<string name="uninstall">Odinstaluj</string>
|
||||
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Wszystkie moduły będą wyłączone/usunięte. Root zostanie usunięty i przywrócone szyfrowanie danych, jeśli nie są te dane obecnie szyfrowane</string>
|
||||
<string name="uninstall_magisk_msg">Wszystkie moduły będą wyłączone/usunięte. Root zostanie usunięty i przywrócone szyfrowanie danych, jeśli nie są te dane obecnie szyfrowane</string>
|
||||
<string name="update">Pobierz</string>
|
||||
<string name="core_only_enabled">(Włączony tylko tryb jądra)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nie umieszczono informacji)</string>
|
||||
<string name="no_modules_found">Nie znaleziono modułów.</string>
|
||||
<string name="update_file_created">Moduł zostanie zaktualizowany przy następnym restarcie.</string>
|
||||
@@ -45,12 +45,12 @@
|
||||
<string name="reboot_bootloader">Restart do Bootloadera</string>
|
||||
<string name="reboot_download">Restart do Download</string>
|
||||
<string name="reboot_edl">Restart do EDL</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Aktualizacja dostępna</string>
|
||||
<string name="installed">Zainstalowany</string>
|
||||
<string name="not_installed">Nie zainstalowany</string>
|
||||
<string name="updated_on">Zaktualizowano: %1$s</string>
|
||||
<string name="updated_on">Zaktualizowano: %1$s</string>
|
||||
<string name="sorting_order">Kolejność Sortowania</string>
|
||||
<string name="sort_by_name">Sortuj po nazwie</string>
|
||||
<string name="sort_by_update">Sortuj po ostatniej aktualizacji</string>
|
||||
@@ -71,23 +71,22 @@
|
||||
<string name="download_file_error">Błąd pobierania pliku</string>
|
||||
<string name="download_open_parent">Pokaż w folderze nadrzędnym</string>
|
||||
<string name="download_open_self">Pokaż pliki</string>
|
||||
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
|
||||
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
|
||||
<string name="manager_update_title">Nowa Wersja Magisk Manager Dostępna!</string>
|
||||
|
||||
<!-- Installation -->
|
||||
<string name="manager_download_install">Naciśnij aby pobrać i zainstalować</string>
|
||||
<string name="download_zip_only">Pobierz Tylko Zip</string>
|
||||
<!-- Installation -->
|
||||
<string name="manager_download_install">Naciśnij aby pobrać i zainstalować</string>
|
||||
<string name="download_zip_only">Pobierz Tylko Zip</string>
|
||||
<string name="direct_install">Bezpośrednia instalacja (Zalecane)</string>
|
||||
<string name="install_inactive_slot">Zainstaluj do Nieaktywnego Slotu (po OTA)</string>
|
||||
<string name="install_inactive_slot">Zainstaluj do Nieaktywnego Slotu (po OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Urządzenie będzie MUSIAŁO uruchomić się z bieżącego nieaktywnego slotu po restarcie! /\nUżyj tylko tej opcji po zakończeniu OTA.\nKontynuować?</string>
|
||||
<string name="select_method">Wybierz Metodę</string>
|
||||
<string name="setup_title">Dodatkowa konfiguracja</string>
|
||||
<string name="select_method">Wybierz Metodę</string>
|
||||
<string name="setup_title">Dodatkowa konfiguracja</string>
|
||||
<string name="select_patch_file">Wybierz i Wgraj Plik</string>
|
||||
<string name="patch_file_msg">Wybierz obraz raw (*.img) lub plik ODIN tar (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Ponowne uruchomienie za 5 sekund…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Zamknij</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="repo_install_title">Instaluj %1$s</string>
|
||||
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
|
||||
<string name="download">Pobierz</string>
|
||||
@@ -100,14 +99,14 @@
|
||||
<string name="dtbo_patched_reboot">Magisk Manager wgrał dtbo.img. Uruchom ponownie</string>
|
||||
<string name="flashing">Flashowanie</string>
|
||||
<string name="done">Gotowe!</string>
|
||||
<string name="failure">Błąd</string>
|
||||
<string name="hide_manager_title">Ukryj Magisk Manager…</string>
|
||||
<string name="failure">Błąd</string>
|
||||
<string name="hide_manager_title">Ukryj Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Błąd Ukrycia Magisk Managera.</string>
|
||||
<string name="open_link_failed_toast">Nie znaleziono aplikacji pod linkiem.</string>
|
||||
<string name="open_link_failed_toast">Nie znaleziono aplikacji pod linkiem.</string>
|
||||
<string name="warning">Uwaga</string>
|
||||
<string name="complete_uninstall">Odinstalowywanie Zakończone</string>
|
||||
<string name="restore_img">Przywróć Obraz</string>
|
||||
<string name="restore_img_msg">Przywracanie…</string>
|
||||
<string name="restore_img_msg">Przywracanie…</string>
|
||||
<string name="restore_done">Przywracanie zakończone!</string>
|
||||
<string name="restore_fail">Stock backup nie istnieje!</string>
|
||||
<string name="proprietary_title">Pobierz Kod</string>
|
||||
@@ -123,7 +122,7 @@
|
||||
<string name="settings_dark_theme_summary">Włącz ciemny motyw</string>
|
||||
<string name="settings_download_path_title">Pobierz dodatek</string>
|
||||
<string name="settings_download_path_message">Pliki zostaną zapisane w %1$s</string>
|
||||
<string name="settings_clear_cache_title">Wyczyść Pamięć Repozytorium</string>
|
||||
<string name="settings_clear_cache_title">Wyczyść Pamięć Repozytorium</string>
|
||||
<string name="settings_clear_cache_summary">Wymusza na aplikacji odświeżenie repozytorium online.</string>
|
||||
<string name="settings_hide_manager_title">Ukryj Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Przepakowanie Magisk Manager z losową nazwą pakietu</string>
|
||||
@@ -145,7 +144,7 @@
|
||||
<string name="settings_hosts_title">Włącz systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Wsparcie systemless dla aplikacji Adblock</string>
|
||||
<string name="settings_hosts_toast">Dodano moduł systemless hosts</string>
|
||||
|
||||
|
||||
<string name="settings_su_app_adb">Aplikacje i ADB</string>
|
||||
<string name="settings_su_app">Tylko Aplikacje</string>
|
||||
<string name="settings_su_adb">Tylko ADB</string>
|
||||
@@ -166,8 +165,8 @@
|
||||
<string name="settings_su_fingerprint_title">Włącz Uwierzytelnienie Odciskiem Palca</string>
|
||||
<string name="settings_su_fingerprint_summary">Użyj skanera linii papilarnych, aby zezwolić na żądania supersu</string>
|
||||
<string name="auth_fingerprint">Uwierzytelnianie Odciskiem Palca</string>
|
||||
|
||||
<string name="multiuser_mode">Tryb Multiusera</string>
|
||||
|
||||
<string name="multiuser_mode">Tryb Multiusera</string>
|
||||
<string name="settings_owner_only">Tylko Właściciel Urządzenia</string>
|
||||
<string name="settings_owner_manage">Zarządzanie Właścicielami Urządzenia</string>
|
||||
<string name="settings_user_independent">Niezależny Użytkownik</string>
|
||||
@@ -182,11 +181,10 @@
|
||||
<string name="global_summary">Wszystkie sesje root za pomocą globalnej przestrzeni montowań nazw</string>
|
||||
<string name="requester_summary">Sesje Root będzie dziedziczyć prośby i nazwy</string>
|
||||
<string name="isolate_summary">W każdej sesji root będzie miał własną odosobnioną nazwę</string>
|
||||
<string name="android_o_not_support">Brak wsparcia dla Androida 8.0+</string>
|
||||
<string name="disable_fingerprint">Nie ustawiono żadnych odcisków palców lub brak obsługi urządzenia</string>
|
||||
<string name="settings_download_path_error">Błąd podczas tworzenia folderu. Musi być dostępny z głównego katalogu pamięci i nie może być plikiem.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Prośba o dostęp Superusera</string>
|
||||
<string name="deny">Odmów</string>
|
||||
<string name="prompt">Zapytaj</string>
|
||||
@@ -220,5 +218,5 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Pokaż aplikacje systemowe</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
@@ -63,7 +63,6 @@
|
||||
<string name="app_changelog">Registro de mudanças</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Fechar</string>
|
||||
<string name="repo_install_title">Instalar %1$s</string>
|
||||
<string name="repo_install_msg">Instalar %1$s agora?</string>
|
||||
<string name="download">Baixar</string>
|
||||
@@ -153,7 +152,6 @@
|
||||
<string name="global_summary">Todas as sessões root usam montagem de espaço de nome global</string>
|
||||
<string name="requester_summary">As sessões root herdarão espaço de nome de seu solicitante</string>
|
||||
<string name="isolate_summary">Cada sessão root terá seu próprio espaço de nome isolado</string>
|
||||
<string name="android_o_not_support">Não suporta Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Nenhuma impressão digital foi definida ou o dispostivo não tem suporte</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -53,7 +53,6 @@
|
||||
<string name="app_changelog">Lista de alterações da aplicação</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Fechar</string>
|
||||
<string name="repo_install_title">Instalar %1$s</string>
|
||||
<string name="repo_install_msg">Deseja instalar%1$s agora?</string>
|
||||
<string name="download">Transferir</string>
|
||||
|
@@ -87,7 +87,6 @@
|
||||
<string name="reboot_delay_toast">Repornire în 5 secunde…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Închide</string>
|
||||
<string name="repo_install_title">Instalează %1$s</string>
|
||||
<string name="repo_install_msg">Vrei să instalezi acum %1$s?</string>
|
||||
<string name="download">Descarcă</string>
|
||||
@@ -182,7 +181,6 @@
|
||||
<string name="global_summary">Toate sesiunile de root folosesc spațiul de nume global.</string>
|
||||
<string name="requester_summary">Sesiunile de root vor moșteni spațiul de nume al solicitantului.</string>
|
||||
<string name="isolate_summary">Fiecare sesiune de root va avea propriul spațiu de nume izolat.</string>
|
||||
<string name="android_o_not_support">Nu suportă Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Nu au fost setate amprente sau scannerul de amprentă lipsește.</string>
|
||||
<string name="settings_download_path_error">Eroare la crearea dosarului. Acesta trebuie să fie accesibil din directorul rădăcină al stocării și nu trebuie să fie un fișier.</string>
|
||||
|
||||
|
@@ -18,18 +18,18 @@
|
||||
<string name="checking_safetyNet_status">Проверка статуса SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Результат проверки SafetyNet</string>
|
||||
<string name="safetyNet_api_error">Ошибка SafetyNet API</string>
|
||||
<string name="safetyNet_res_invalid">Некорректный ответ.</string>
|
||||
<string name="safetyNet_res_invalid">Некорректный ответ</string>
|
||||
<string name="magisk_up_to_date">Magisk актуален</string>
|
||||
<string name="manager_up_to_date">Magisk Manager актуален</string>
|
||||
<string name="advanced_settings_title">Расширенные опции</string>
|
||||
<string name="keep_force_encryption">Сохранить принудительное шифрование</string>
|
||||
<string name="keep_dm_verity">Сохранить AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Режим Recovery</string>
|
||||
<string name="current_installed">Установлена: %1$s</string>
|
||||
<string name="latest_version">Последняя: %1$s</string>
|
||||
<string name="keep_force_encryption">Не отключать шифрование /data</string>
|
||||
<string name="keep_dm_verity">Не отключать AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Режим установки в recovery</string>
|
||||
<string name="current_installed">Установлен: %1$s</string>
|
||||
<string name="latest_version">Последний: %1$s</string>
|
||||
<string name="uninstall">Удаление</string>
|
||||
<string name="uninstall_magisk_title">Удаление Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Все модули будут отключены/удалены. Root-права будут удалены. Шифрование будет активировано.</string>
|
||||
<string name="uninstall_magisk_msg">Все модули будут отключены/удалены!\nRoot-права будут удалены!\nШифрование будет активировано!</string>
|
||||
<string name="update">Обновить</string>
|
||||
<string name="core_only_enabled">(Активирован режим Magisk Core)</string>
|
||||
|
||||
@@ -76,24 +76,23 @@
|
||||
<string name="manager_update_title">Доступно обновление Magisk Manager!</string>
|
||||
|
||||
<!-- Installation -->
|
||||
<string name="manager_download_install">Нажмите, чтобы загрузить и установить.</string>
|
||||
<string name="download_zip_only">Загрузка установочного ZIP</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="install_inactive_slot">Установка во второй слот (OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Ваше устройство будет принудительно перезагружено в неактивный (противоположный) слот!\nИспользуйте эту опцию только при интеграции после OTA.\nПродолжить?</string>
|
||||
<string name="select_method">Выбор способа</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)</string>
|
||||
<string name="reboot_delay_toast">Перезагрузка через 5 секунд…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Закрыть</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="settings_reboot_toast">Для применения настроек перезагрузите устройство.</string>
|
||||
<string name="settings_reboot_toast">Для применения настроек перезагрузите устройство</string>
|
||||
<string name="release_notes">О версии</string>
|
||||
<string name="repo_cache_cleared">Кэш репозитория очищен</string>
|
||||
|
||||
@@ -102,9 +101,9 @@
|
||||
<string name="flashing">Прошивка…</string>
|
||||
<string name="done">Завершено!</string>
|
||||
<string name="failure">Ошибка</string>
|
||||
<string name="hide_manager_title">Маскировка Magisk Manager…</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="open_link_failed_toast">Не найдено приложений для открытия ссылки</string>
|
||||
<string name="warning">Предупреждение</string>
|
||||
<string name="complete_uninstall">Полное удаление</string>
|
||||
<string name="restore_img">Восстановить разделы</string>
|
||||
@@ -112,8 +111,8 @@
|
||||
<string name="restore_done">Восстановление завершено!</string>
|
||||
<string name="restore_fail">Резервная копия отсутствует!</string>
|
||||
<string name="proprietary_title">Загрузка SafetyNet</string>
|
||||
<string name="proprietary_notice">Magisk Manager — свободно распространяемый продукт, он не содержит собственный код SafetyNet API от Google.\n\nРазрешить Magisk Manager загрузить расширение для проверки SafetyNet? (содержит GoogleApiClient)</string>
|
||||
<string name="setup_fail">Ошибка установки.</string>
|
||||
<string name="proprietary_notice">Magisk Manager — проект с открытым исходным кодом и не содержит проприетарный код SafetyNet API от Google.\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>
|
||||
@@ -121,32 +120,36 @@
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Основные</string>
|
||||
<string name="settings_dark_theme_title">Тёмная тема</string>
|
||||
<string name="settings_dark_theme_summary">Включить тёмное оформление.</string>
|
||||
<string name="settings_dark_theme_summary">Включить тёмное оформление</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_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="settings_restore_manager_summary">Восстановить Magisk Manager с исходным названием и именем пакета</string>
|
||||
<string name="language">Язык</string>
|
||||
<string name="system_default">По умолчанию (Системный)</string>
|
||||
<string name="settings_update">Настройки обновлений</string>
|
||||
<string name="settings_check_update_title">Проверка обновлений</string>
|
||||
<string name="settings_check_update_summary">Периодически проверять наличие обновлений в фоновом режиме.</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">Beta канал</string>
|
||||
<string name="settings_update_custom">Сторонний канал</string>
|
||||
<string name="settings_update_custom_msg">Укажите ссылку</string>
|
||||
<string name="settings_core_only_title">Magisk Core</string>
|
||||
<string name="settings_core_only_summary">Активировать только основные возможности. Модули не будут загружены. MagiskSU и Magisk Hide останутся активными.</string>
|
||||
<string name="settings_magiskhide_summary">Скрыть Magisk от различных обнаружений.</string>
|
||||
<string name="settings_core_only_summary">Активировать только основные возможности. Модули не будут загружены. MagiskSU и Magisk Hide останутся активными</string>
|
||||
<string name="settings_magiskhide_summary">Скрывать Magisk от различных обнаружений</string>
|
||||
<string name="settings_hosts_title">Внесистемные хосты</string>
|
||||
<string name="settings_hosts_summary">Поддержка внесистемных хостов для приложений, блокирующих рекламу.</string>
|
||||
<string name="settings_hosts_summary">Поддержка внесистемных хостов для приложений, блокирующих рекламу</string>
|
||||
<string name="settings_hosts_toast">Добавлен модуль внесистемных хостов</string>
|
||||
|
||||
<string name="settings_app_name">Укажите имя приложения</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>
|
||||
@@ -163,18 +166,18 @@
|
||||
<string name="superuser_notification">Уведомления суперпользователя</string>
|
||||
<string name="request_timeout_summary">%1$d секунд</string>
|
||||
<string name="settings_su_reauth_title">Повторная аутентификация</string>
|
||||
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений.</string>
|
||||
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
|
||||
<string name="settings_su_fingerprint_title">Биометрическая аутентификация</string>
|
||||
<string name="settings_su_fingerprint_summary">Использовать сканер отпечатков пальцев для запросов прав суперпользователя.</string>
|
||||
<string name="auth_fingerprint">Аутентифицировать отпечаток пальца</string>
|
||||
<string name="settings_su_fingerprint_summary">Использовать сканер отпечатков пальцев для запросов прав суперпользователя</string>
|
||||
<string name="auth_fingerprint">Подтвердите отпечаток пальца</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="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>
|
||||
@@ -183,18 +186,17 @@
|
||||
<string name="global_summary">Сессии суперпользователя используют общее пространство имён</string>
|
||||
<string name="requester_summary">Сессии суперпользователя наследуют пространство имён запрашивающего</string>
|
||||
<string name="isolate_summary">Сессии суперпользователя используют изолированные пространства имён</string>
|
||||
<string name="android_o_not_support">Не поддерживается в Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Не поддерживается устройством или не заданы отпечатки</string>
|
||||
<string name="settings_download_path_error">Ошибка создания папки. Она должна быть доступна из корневой директории хранилища и не должна быть файлом.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Запрос прав суперпользователя</string>
|
||||
<string name="deny">Отказать</string>
|
||||
<string name="deny">Запретить</string>
|
||||
<string name="prompt">Запрос</string>
|
||||
<string name="grant">Предоставить</string>
|
||||
<string name="su_warning">Предоставить полный доступ к устройству.\nЕсли не уверены - отклоните данное действие!</string>
|
||||
<string name="grant">Разрешить</string>
|
||||
<string name="su_warning">Разрешить полный доступ к устройству?\nЕсли не уверены - отклоните данное действие!</string>
|
||||
<string name="forever">Навсегда</string>
|
||||
<string name="once">Сейчас</string>
|
||||
<string name="once">Единожды</string>
|
||||
<string name="tenmin">10 мин.</string>
|
||||
<string name="twentymin">20 мин.</string>
|
||||
<string name="thirtymin">30 мин.</string>
|
||||
@@ -220,6 +222,6 @@
|
||||
<string name="command">Команда: %1$s</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Показать системные приложения</string>
|
||||
<string name="show_system_app">Системные приложения</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -72,7 +72,6 @@
|
||||
<string name="manager_update_title">Je dostupná aktualizácia Magisk Manager!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Zavrieť</string>
|
||||
<string name="repo_install_title">Nainštalovať %1$s</string>
|
||||
<string name="repo_install_msg">Chcete teraz nainštalovať %1$s?</string>
|
||||
<string name="download">Stiahnuť</string>
|
||||
@@ -167,7 +166,6 @@
|
||||
<string name="global_summary">Všetky relácie root použijú globálne mount namespace</string>
|
||||
<string name="requester_summary">Relácie root zdedia namespace od požadovateľa</string>
|
||||
<string name="isolate_summary">Každá relácia root bude mať vlastný izolovaný namespace</string>
|
||||
<string name="android_o_not_support">Nepodporuje Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Neboli odoslané žiadne odtlačky prsta alebo ich zariadenie nepodporuje</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -55,7 +55,6 @@
|
||||
<string name="app_changelog">Дневник промена апликације</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Затвори</string>
|
||||
<string name="repo_install_title">Инсталирај %1$s</string>
|
||||
<string name="repo_install_msg">Да ли желите да инсталирате %1$s?</string>
|
||||
<string name="download">Преузми</string>
|
||||
|
@@ -53,7 +53,6 @@
|
||||
<string name="app_changelog">Ändringslogg</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Stäng</string>
|
||||
<string name="repo_install_title">Installera %1$s</string>
|
||||
<string name="repo_install_msg">Vill du installera %1$s ?</string>
|
||||
<string name="download">Ladda ner</string>
|
||||
@@ -62,7 +61,7 @@
|
||||
<string name="settings_reboot_toast">Starta om för att tillämpa inställningar</string>
|
||||
<string name="release_notes">Release notes</string>
|
||||
<string name="repo_cache_cleared">Repo-cache rensad</string>
|
||||
<string name="manager_update_title">En uppdatering av Magisk maneger finns tillgänglig!</string>
|
||||
<string name="manager_update_title">En uppdatering av Magisk Manager finns tillgänglig!</string>
|
||||
<string name="manager_download_install">Tryck för att ladda ner och installera</string>
|
||||
<string name="update_channel">Magiska uppdateringar</string>
|
||||
<string name="download_file_error">Fel vid nerladdning av fil</string>
|
||||
|
@@ -69,7 +69,6 @@
|
||||
<string name="manager_update_title">มีการอัพเดต Magisk Manager!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">ปิด</string>
|
||||
<string name="repo_install_title">ติดตั้ง %1$s</string>
|
||||
<string name="repo_install_msg">ต้องการติดตั้ง %1$s ตอนนี้หรือไม่?</string>
|
||||
<string name="download">ดาวน์โหลด</string>
|
||||
@@ -166,7 +165,6 @@
|
||||
<string name="global_summary">All root sessions use the global mount namespace.</string>
|
||||
<string name="requester_summary">Root sessions will inherit their requester\'s namespace.</string>
|
||||
<string name="isolate_summary">Each root session will have its own isolated namespace.</string>
|
||||
<string name="android_o_not_support">ไม่รองรับ Android 8.0 ขึ้นไป</string>
|
||||
<string name="disable_fingerprint">ไม่มีลายนิ้วมือหรืออุปกรณ์แสกน</string>
|
||||
|
||||
<!--Superuser-->
|
||||
|
@@ -88,7 +88,6 @@
|
||||
<string name="reboot_delay_toast">5 saniye içinde yeniden başlatılacak...</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Kapat</string>
|
||||
<string name="repo_install_title">%1$s yükle</string>
|
||||
<string name="repo_install_msg">%1$s yüklensin mi?</string>
|
||||
<string name="download">İndir</string>
|
||||
@@ -147,6 +146,10 @@
|
||||
<string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz host desteği</string>
|
||||
<string name="settings_hosts_toast">Sistemsiz host modülü eklendi</string>
|
||||
|
||||
<string name="settings_app_name">İstediğiniz uygulama adını yazın</string>
|
||||
<string name="settings_app_name_hint">Yeni ad</string>
|
||||
<string name="settings_app_name_helper">Uygulama bu ad ile yeniden paketlenecek</string>
|
||||
<string name="settings_app_name_error">Geçersiz format</string>
|
||||
<string name="settings_su_app_adb">Uygulamalar ve ADB</string>
|
||||
<string name="settings_su_app">Sadece uygulamalar</string>
|
||||
<string name="settings_su_adb">Sadece ADB</string>
|
||||
@@ -183,9 +186,8 @@
|
||||
<string name="global_summary">Tüm kök oturumları genel bağlama ad alanını kullanır</string>
|
||||
<string name="requester_summary">Kök oturumları, istekte bulunanın ad alanını devralır</string>
|
||||
<string name="isolate_summary">Her bir kök oturumunun kendi izole ad alanı olacaktır</string>
|
||||
<string name="android_o_not_support">Android 8.0 ve üzerinde desteklenmiyor</string>
|
||||
<string name="disable_fingerprint">Parmak izi ayarlanmadı veya cihaz desteği yok</string>
|
||||
<string name="settings_download_path_error">Klasör oluşturma hatası. Depolama kök dizininden erişilebilir olmalı ve bir dosya olmamalıdır.</string>
|
||||
<string name="settings_download_path_error">Klasör oluşturma hatası. Depolama kök dizininden erişilebilir olmalı ve bir dosya olmamalıdır.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Yetkili Kullanıcı İsteği</string>
|
||||
|
@@ -88,7 +88,6 @@
|
||||
<string name="reboot_delay_toast">Перезавантаження через 5 секунд…</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Закрити</string>
|
||||
<string name="repo_install_title">Встановити %1$s</string>
|
||||
<string name="repo_install_msg">Бажаєте встановити %1$s ?</string>
|
||||
<string name="download">Завантажити</string>
|
||||
@@ -106,8 +105,8 @@
|
||||
<string name="hide_manager_fail_toast">Не вдалося приховати Magisk Manager.</string>
|
||||
<string name="open_link_failed_toast">Не знайдено програм для відкриття посилання.</string>
|
||||
<string name="warning">Попередження</string>
|
||||
<string name="complete_uninstall">Видалення виконано</string>
|
||||
<string name="restore_img">Відновити образи</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">Немає резервної копії оригінального boot образу</string>
|
||||
@@ -140,13 +139,17 @@
|
||||
<string name="settings_update_beta">Бета реліз</string>
|
||||
<string name="settings_update_custom">Власний</string>
|
||||
<string name="settings_update_custom_msg">Вставте власний URL</string>
|
||||
<string name="settings_core_only_title">Режим ядра Magisk</string>
|
||||
<string name="settings_core_only_title">Режим Magisk Core</string>
|
||||
<string name="settings_core_only_summary">Увімкнути тільки можливості ядра. MagiskSU i Magisk Hide залишуться увімкненими, проте ніякі модулі не будуть завантажені.</string>
|
||||
<string name="settings_magiskhide_summary">Приховати Magisk від різних форм виявлень.</string>
|
||||
<string name="settings_hosts_title">Позасистемні хости</string>
|
||||
<string name="settings_hosts_summary">Підтримка позасистемних хостів для програм блокування реклами.</string>
|
||||
<string name="settings_hosts_toast">Додано модуль позасистемних хостів</string>
|
||||
|
||||
<string name="settings_app_name">Введіть бажане ім\'я застосунку</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>
|
||||
@@ -183,7 +186,6 @@
|
||||
<string name="global_summary">Всі сеанси Суперкористувача використовують глобальний простір імен.</string>
|
||||
<string name="requester_summary">Сеанси Суперкористувача наслідують простір імен запитувача.</string>
|
||||
<string name="isolate_summary">Кожнен сеанс Суперкористувача має власний ізольований простір імен.</string>
|
||||
<string name="android_o_not_support">Не працює на Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Немає відбитків пальця або пристрій не підтримується.</string>
|
||||
<string name="settings_download_path_error">Помилка створення папки. Вона повинна бути доступна з кореневої директорії сховища і не повинна бути файлом.</string>
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user