mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 08:37:25 +00:00
Compare commits
114 Commits
manager-v8
...
manager-v8
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2d5cf8a6fe | ||
![]() |
290959f74c | ||
![]() |
4d9f58ee72 | ||
![]() |
9241246de6 | ||
![]() |
58a5d52b78 | ||
![]() |
2906178ac3 | ||
![]() |
e0afbb647b | ||
![]() |
50be50cf6a | ||
![]() |
77a9d3a5bc | ||
![]() |
f9c7a4c933 | ||
![]() |
2b759b84b0 | ||
![]() |
1e45c63ea5 | ||
![]() |
b14a260827 | ||
![]() |
ade1597e03 | ||
![]() |
2739d3cb67 | ||
![]() |
dc5e78e142 | ||
![]() |
e9759a5868 | ||
![]() |
e7ab802498 | ||
![]() |
42672c2e27 | ||
![]() |
e65d61d313 | ||
![]() |
076da5c7c4 | ||
![]() |
9deaf2507c | ||
![]() |
5c114c67de | ||
![]() |
d904cb0441 | ||
![]() |
bd1dd9d863 | ||
![]() |
afebe734b8 | ||
![]() |
e21a78164e | ||
![]() |
1e0f96d0fd | ||
![]() |
bf650332d8 | ||
![]() |
f32e0af830 | ||
![]() |
4c94f90e5d | ||
![]() |
ffb4224640 | ||
![]() |
89fff4830b | ||
![]() |
16e4c67992 | ||
![]() |
cf47214ee4 | ||
![]() |
0feab753fb | ||
![]() |
d0b6318b90 | ||
![]() |
966e23b846 | ||
![]() |
5b8a1fc2a7 | ||
![]() |
02ea3ca525 | ||
![]() |
0632b146b8 | ||
![]() |
1b0b180761 | ||
![]() |
0d11f73a1d | ||
![]() |
533cb8eb58 | ||
![]() |
8ac1181e9a | ||
![]() |
5ca1892eb0 | ||
![]() |
e32db6a0e8 | ||
![]() |
82fff615d6 | ||
![]() |
24a8f0808d | ||
![]() |
4a7c3c06bc | ||
![]() |
da93bbc1fe | ||
![]() |
fa2dbe981e | ||
![]() |
ce6cceae8b | ||
![]() |
7b26e8b818 | ||
![]() |
2da5fcb00b | ||
![]() |
a079966f97 | ||
![]() |
468796c23d | ||
![]() |
5833aadef5 | ||
![]() |
eb261c8026 | ||
![]() |
a4c48847d1 | ||
![]() |
43288be091 | ||
![]() |
1ad7a6fe93 | ||
![]() |
4e0a3f5e72 | ||
![]() |
d7c33f647d | ||
![]() |
9087207dc0 | ||
![]() |
2760f37e6b | ||
![]() |
3fa3426032 | ||
![]() |
2e4dc91b96 | ||
![]() |
aaaaa3d044 | ||
![]() |
1edc4449d5 | ||
![]() |
f3cd4da026 | ||
![]() |
872c55207c | ||
![]() |
339ca6d666 | ||
![]() |
4aeac3b8f4 | ||
![]() |
d625beb7f3 | ||
![]() |
735b65c50c | ||
![]() |
efb1eab327 | ||
![]() |
49d4785da0 | ||
![]() |
28e65ce383 | ||
![]() |
c3b6a48373 | ||
![]() |
a42ebd429b | ||
![]() |
8f89010752 | ||
![]() |
105a18f719 | ||
![]() |
eb04ca4c4a | ||
![]() |
6092d7ca88 | ||
![]() |
66cad101c0 | ||
![]() |
0a14f43f9c | ||
![]() |
311c1f0dfd | ||
![]() |
0499588107 | ||
![]() |
d4d837a562 | ||
![]() |
fbcbb20178 | ||
![]() |
0914700fc6 | ||
![]() |
eeced2fb5b | ||
![]() |
6509e3d4f5 | ||
![]() |
317052604b | ||
![]() |
5538f7168c | ||
![]() |
dcb9e4cd93 | ||
![]() |
d9382f59bf | ||
![]() |
403a0c770a | ||
![]() |
f0f1cdc501 | ||
![]() |
4e272b70ef | ||
![]() |
8dc62a0232 | ||
![]() |
9225b47568 | ||
![]() |
d462873e74 | ||
![]() |
fc19b50290 | ||
![]() |
333fe6da0e | ||
![]() |
75fcda9f81 | ||
![]() |
44ba2a9903 | ||
![]() |
2fceb1ad96 | ||
![]() |
bacb5fa462 | ||
![]() |
67f8dc494e | ||
![]() |
3e4caabecb | ||
![]() |
dcd5183b24 | ||
![]() |
d80c6b42a6 |
@@ -15,17 +15,17 @@ Here are some feature highlights:
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/download/manager-v7.5.1/MagiskManager-v7.5.1.apk)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.2/MagiskManager-v8.0.2.apk)
|
||||
[](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-debug.apk)
|
||||
<br>
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v20.4)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v20.4)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.0)
|
||||
|
||||
## Useful Links
|
||||
|
||||
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
|
||||
- [Frequently Asked Questions](https://topjohnwu.github.io/Magisk/faq.html)
|
||||
- [Full Official Docs](https://topjohnwu.github.io/Magisk/)
|
||||
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
||||
- [Magisk Troubleshoot Wiki](https://www.didgeridoohan.com/magisk/HomePage) (by [@Didgeridoohan](https://github.com/Didgeridoohan))
|
||||
|
||||
## Android Version Support
|
||||
@@ -56,7 +56,7 @@ For Magisk Manager crashes, record and upload the logcat when the crash occurs.
|
||||
- macOS: `export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"`
|
||||
- Linux: `export PATH="/path/to/androidstudio/jre/bin:$PATH"`
|
||||
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
|
||||
- Set environment variable `ANDROID_HOME` to the Android SDK folder (can be found in Android Studio settings)
|
||||
- Set environment variable `ANDROID_SDK_ROOT` to the Android SDK folder (can be found in Android Studio settings)
|
||||
- Run `./build.py ndk` to let the script download and install NDK for you
|
||||
- Set configurations in `config.prop`. A sample `config.prop.sample` is provided.
|
||||
- To start building, run `build.py` to see your options. \
|
||||
|
@@ -51,11 +51,12 @@ android {
|
||||
|
||||
packagingOptions {
|
||||
exclude("/META-INF/**")
|
||||
exclude("/androidsupportmultidexversion.txt")
|
||||
exclude("/org/bouncycastle/**")
|
||||
exclude("/kotlin/**")
|
||||
exclude("/kotlinx/**")
|
||||
exclude("/okhttp3/**")
|
||||
exclude("/*.txt")
|
||||
exclude("/*.bin")
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
@@ -82,6 +83,7 @@ dependencies {
|
||||
|
||||
implementation("com.github.topjohnwu:jtar:1.0.0")
|
||||
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
|
||||
implementation("com.github.topjohnwu:lz4-java:1.7.1")
|
||||
implementation("com.jakewharton.timber:timber:4.7.1")
|
||||
|
||||
val vBAdapt = "4.0.0"
|
||||
@@ -118,11 +120,11 @@ dependencies {
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}")
|
||||
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
|
||||
|
||||
val vMoshi = "1.10.0"
|
||||
val vMoshi = "1.11.0"
|
||||
implementation("com.squareup.moshi:moshi:${vMoshi}")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
|
||||
|
||||
val vRoom = "2.2.5"
|
||||
val vRoom = "2.3.0-alpha03"
|
||||
implementation("androidx.room:room-runtime:${vRoom}")
|
||||
implementation("androidx.room:room-ktx:${vRoom}")
|
||||
kapt("androidx.room:room-compiler:${vRoom}")
|
||||
@@ -132,7 +134,7 @@ dependencies {
|
||||
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
|
||||
|
||||
implementation("androidx.biometric:biometric:1.0.1")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.0.1")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.browser:browser:1.2.0")
|
||||
implementation("androidx.preference:preference:1.1.1")
|
||||
@@ -141,7 +143,7 @@ dependencies {
|
||||
implementation("androidx.work:work-runtime-ktx:2.4.0")
|
||||
implementation("androidx.transition:transition:1.3.1")
|
||||
implementation("androidx.multidex:multidex:2.0.1")
|
||||
implementation("androidx.core:core-ktx:1.3.1")
|
||||
implementation("androidx.core:core-ktx:1.3.2")
|
||||
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.0.0")
|
||||
implementation("com.google.android.material:material:1.2.1")
|
||||
}
|
||||
|
6
app/proguard-rules.pro
vendored
6
app/proguard-rules.pro
vendored
@@ -35,12 +35,6 @@
|
||||
void onResponse(org.json.JSONObject);
|
||||
}
|
||||
|
||||
# Fragments
|
||||
# TODO: Remove when AGP 4.1 release
|
||||
# https://issuetracker.google.com/issues/142601969
|
||||
-keep,allowobfuscation class * extends androidx.fragment.app.Fragment
|
||||
-keepnames class androidx.navigation.fragment.NavHostFragment
|
||||
|
||||
# Strip Timber verbose and debug logging
|
||||
-assumenosideeffects class timber.log.Timber.Tree {
|
||||
public void v(**);
|
||||
|
@@ -12,12 +12,6 @@
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<provider
|
||||
android:name="a.p"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@@ -1,7 +0,0 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.FileProvider;
|
||||
|
||||
public class p extends FileProvider {
|
||||
/* Stub */
|
||||
}
|
@@ -8,7 +8,6 @@ import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.OpenableColumns;
|
||||
@@ -34,8 +33,6 @@ public class FileProvider extends ContentProvider {
|
||||
|
||||
private PathStrategy mStrategy;
|
||||
|
||||
public static ProviderCallHandler callHandler;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
@@ -131,13 +128,6 @@ public class FileProvider extends ContentProvider {
|
||||
return file.delete() ? 1 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
if (callHandler != null)
|
||||
return callHandler.call(getContext(), method, arg, extras);
|
||||
return Bundle.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode)
|
||||
throws FileNotFoundException {
|
||||
|
@@ -1,8 +0,0 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
public interface ProviderCallHandler {
|
||||
Bundle call(Context context, String method, String arg, Bundle extras);
|
||||
}
|
@@ -30,6 +30,6 @@ repositories {
|
||||
dependencies {
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
|
||||
api("org.bouncycastle:bcprov-jdk15on:1.66")
|
||||
api("org.bouncycastle:bcpkix-jdk15on:1.66")
|
||||
api("org.bouncycastle:bcprov-jdk15on:1.67")
|
||||
api("org.bouncycastle:bcpkix-jdk15on:1.67")
|
||||
}
|
||||
|
@@ -4,11 +4,10 @@
|
||||
package="com.topjohnwu.magisk">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="28" />
|
||||
android:maxSdkVersion="29" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
@@ -65,6 +64,15 @@
|
||||
<!-- DownloadService -->
|
||||
<service android:name="a.j" />
|
||||
|
||||
<!-- FileProvider -->
|
||||
<provider
|
||||
android:name="a.p"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:directBootAware="true"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
</provider>
|
||||
|
||||
<!-- Hardcode GMS version -->
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.version"
|
||||
|
@@ -2,7 +2,8 @@
|
||||
package a
|
||||
|
||||
import com.topjohnwu.magisk.core.App
|
||||
import com.topjohnwu.magisk.core.GeneralReceiver
|
||||
import com.topjohnwu.magisk.core.Provider
|
||||
import com.topjohnwu.magisk.core.Receiver
|
||||
import com.topjohnwu.magisk.core.SplashActivity
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
@@ -22,8 +23,10 @@ class e : App {
|
||||
constructor(o: Any) : super(o)
|
||||
}
|
||||
|
||||
class h : GeneralReceiver()
|
||||
class h : Receiver()
|
||||
|
||||
class j : DownloadService()
|
||||
|
||||
class m : SuRequestActivity()
|
||||
|
||||
class p : Provider()
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.arch
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
@@ -41,11 +40,6 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
||||
AppCompatDelegate.setDefaultNightMode(theme)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
currentFragment?.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(themeRes)
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -76,6 +70,10 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
||||
ensureInsets()
|
||||
}
|
||||
|
||||
fun setAccessibilityDelegate(delegate: View.AccessibilityDelegate?) {
|
||||
viewRoot.rootView.accessibilityDelegate = delegate
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.requestRefresh()
|
||||
@@ -85,7 +83,7 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
|
||||
return currentFragment?.onKeyEvent(event) == true || super.dispatchKeyEvent(event)
|
||||
}
|
||||
|
||||
override fun onEventDispatched(event: ViewEvent) = when(event) {
|
||||
override fun onEventDispatched(event: ViewEvent) = when (event) {
|
||||
is ContextExecutor -> event(this)
|
||||
is ActivityExecutor -> event(this)
|
||||
else -> Unit
|
||||
|
@@ -17,7 +17,7 @@ import com.topjohnwu.magisk.ktx.startAnimations
|
||||
abstract class BaseUIFragment<VM : BaseViewModel, Binding : ViewDataBinding> :
|
||||
Fragment(), BaseUIComponent<VM> {
|
||||
|
||||
protected val activity get() = requireActivity() as BaseUIActivity<*, *>
|
||||
val activity get() = requireActivity() as BaseUIActivity<*, *>
|
||||
protected lateinit var binding: Binding
|
||||
protected abstract val layoutRes: Int
|
||||
|
||||
|
@@ -9,18 +9,18 @@ import me.tatarka.bindingcollectionadapter2.BindingRecyclerViewAdapter
|
||||
import me.tatarka.bindingcollectionadapter2.ItemBinding
|
||||
import me.tatarka.bindingcollectionadapter2.OnItemBind
|
||||
|
||||
inline fun <T : ComparableRvItem<*>> diffListOf(
|
||||
fun <T : ComparableRvItem<*>> diffListOf(
|
||||
vararg newItems: T
|
||||
) = diffListOf(newItems.toList())
|
||||
|
||||
inline fun <T : ComparableRvItem<*>> diffListOf(
|
||||
fun <T : ComparableRvItem<*>> diffListOf(
|
||||
newItems: List<T>
|
||||
) = DiffObservableList(object : DiffObservableList.Callback<T> {
|
||||
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
|
||||
override fun areContentsTheSame(oldItem: T, newItem: T) = oldItem.genericContentSameAs(newItem)
|
||||
}).also { it.update(newItems) }
|
||||
|
||||
inline fun <T : ComparableRvItem<*>> filterableListOf(
|
||||
fun <T : ComparableRvItem<*>> filterableListOf(
|
||||
vararg newItems: T
|
||||
) = FilterableDiffObservableList(object : DiffObservableList.Callback<T> {
|
||||
override fun areItemsTheSame(oldItem: T, newItem: T) = oldItem.genericItemSameAs(newItem)
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package com.topjohnwu.magisk.arch
|
||||
|
||||
import android.content.Context
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
/**
|
||||
@@ -23,5 +22,5 @@ interface ActivityExecutor {
|
||||
}
|
||||
|
||||
interface FragmentExecutor {
|
||||
operator fun invoke(fragment: Fragment)
|
||||
operator fun invoke(fragment: BaseUIFragment<*, *>)
|
||||
}
|
||||
|
@@ -10,8 +10,6 @@ import androidx.multidex.MultiDex
|
||||
import androidx.work.WorkManager
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.FileProvider
|
||||
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||
import com.topjohnwu.magisk.core.utils.IODispatcherExecutor
|
||||
import com.topjohnwu.magisk.core.utils.RootInit
|
||||
import com.topjohnwu.magisk.core.utils.updateConfig
|
||||
@@ -36,7 +34,6 @@ open class App() : Application() {
|
||||
.setInitializers(RootInit::class.java)
|
||||
.setTimeout(2))
|
||||
Shell.EXECUTOR = IODispatcherExecutor()
|
||||
FileProvider.callHandler = SuCallbackHandler
|
||||
|
||||
// Always log full stack trace with Timber
|
||||
Timber.plant(Timber.DebugTree())
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Xml
|
||||
@@ -9,19 +10,16 @@ import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.core.magiskdb.SettingsDao
|
||||
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||
import com.topjohnwu.magisk.core.utils.defaultLocale
|
||||
import com.topjohnwu.magisk.core.utils.refreshLocale
|
||||
import com.topjohnwu.magisk.data.preference.PreferenceModel
|
||||
import com.topjohnwu.magisk.data.repository.DBConfig
|
||||
import com.topjohnwu.magisk.di.Protected
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.inject
|
||||
import com.topjohnwu.magisk.ui.theme.Theme
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import com.topjohnwu.superuser.io.SuFileInputStream
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
||||
object Config : PreferenceModel, DBConfig {
|
||||
|
||||
@@ -29,6 +27,15 @@ object Config : PreferenceModel, DBConfig {
|
||||
override val settingsDao: SettingsDao by inject()
|
||||
override val context: Context by inject(Protected)
|
||||
|
||||
@get:SuppressLint("ApplySharedPref")
|
||||
val prefsFile: File get() {
|
||||
// Flush prefs to disk
|
||||
prefs.edit().apply {
|
||||
remove(Key.ASKED_HOME)
|
||||
}.commit()
|
||||
return File("${context.filesDir.parent}/shared_prefs", "${fileName}.xml")
|
||||
}
|
||||
|
||||
object Key {
|
||||
// db configs
|
||||
const val ROOT_ACCESS = "root_access"
|
||||
@@ -43,6 +50,7 @@ object Config : PreferenceModel, DBConfig {
|
||||
const val SU_AUTO_RESPONSE = "su_auto_response"
|
||||
const val SU_NOTIFICATION = "su_notification"
|
||||
const val SU_REAUTH = "su_reauth"
|
||||
const val SU_TAPJACK = "su_tapjack"
|
||||
const val CHECK_UPDATES = "check_update"
|
||||
const val UPDATE_CHANNEL = "update_channel"
|
||||
const val CUSTOM_CHANNEL = "custom_channel"
|
||||
@@ -119,7 +127,7 @@ object Config : PreferenceModel, DBConfig {
|
||||
var repoOrder by preference(Key.REPO_ORDER, Value.ORDER_DATE)
|
||||
|
||||
var suDefaultTimeout by preferenceStrInt(Key.SU_REQUEST_TIMEOUT, 10)
|
||||
var suAutoReponse by preferenceStrInt(Key.SU_AUTO_RESPONSE, Value.SU_PROMPT)
|
||||
var suAutoResponse by preferenceStrInt(Key.SU_AUTO_RESPONSE, Value.SU_PROMPT)
|
||||
var suNotification by preferenceStrInt(Key.SU_NOTIFICATION, Value.NOTIFICATION_TOAST)
|
||||
var updateChannel by preferenceStrInt(Key.UPDATE_CHANNEL, defaultChannel)
|
||||
|
||||
@@ -127,8 +135,9 @@ object Config : PreferenceModel, DBConfig {
|
||||
var darkTheme by preference(Key.DARK_THEME, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||
var themeOrdinal by preference(Key.THEME_ORDINAL, Theme.Piplup.ordinal)
|
||||
var suReAuth by preference(Key.SU_REAUTH, false)
|
||||
var suTapjack by preference(Key.SU_TAPJACK, true)
|
||||
var checkUpdate by preference(Key.CHECK_UPDATES, true)
|
||||
var doh by preference(Key.DOH, defaultLocale.country == "CN")
|
||||
var doh by preference(Key.DOH, false)
|
||||
var magiskHide by preference(Key.MAGISKHIDE, true)
|
||||
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
||||
|
||||
@@ -150,8 +159,12 @@ object Config : PreferenceModel, DBConfig {
|
||||
|
||||
private const val SU_FINGERPRINT = "su_fingerprint"
|
||||
|
||||
fun initialize() {
|
||||
prefs.edit { parsePrefs() }
|
||||
fun load(pkg: String) {
|
||||
try {
|
||||
context.contentResolver.openInputStream(Provider.PREFS_URI(pkg))?.use {
|
||||
prefs.edit { parsePrefs(it) }
|
||||
}
|
||||
} catch (e: IOException) {}
|
||||
|
||||
prefs.edit {
|
||||
// Settings migration
|
||||
@@ -173,10 +186,8 @@ object Config : PreferenceModel, DBConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private fun SharedPreferences.Editor.parsePrefs() {
|
||||
val config = SuFile.open("/data/adb", Const.MANAGER_CONFIGS)
|
||||
if (config.exists()) runCatching {
|
||||
val input = SuFileInputStream(config)
|
||||
private fun SharedPreferences.Editor.parsePrefs(input: InputStream) {
|
||||
runCatching {
|
||||
val parser = Xml.newPullParser()
|
||||
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
|
||||
parser.setInput(input, "UTF-8")
|
||||
@@ -220,21 +231,6 @@ object Config : PreferenceModel, DBConfig {
|
||||
else -> parser.next()
|
||||
}
|
||||
}
|
||||
config.delete()
|
||||
}
|
||||
}
|
||||
|
||||
fun export() {
|
||||
// Flush prefs to disk
|
||||
prefs.edit().apply {
|
||||
remove(Key.ASKED_HOME)
|
||||
}.commit()
|
||||
val context = get<Context>(Protected)
|
||||
val xml = File(
|
||||
"${context.filesDir.parent}/shared_prefs",
|
||||
"${context.packageName}_preferences.xml"
|
||||
)
|
||||
Shell.su("cat $xml > /data/adb/${Const.MANAGER_CONFIGS}").exec()
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,13 +12,12 @@ object Const {
|
||||
|
||||
// Versions
|
||||
const val SNET_EXT_VER = 15
|
||||
const val SNET_REVISION = "d494bc726e86166913a13629e3b1336728ec5d7f"
|
||||
const val BOOTCTL_REVISION = "a6c47f86f10b310358afa9dbe837037dd5d561df"
|
||||
const val SNET_REVISION = "18ab78817087c337ae0edd1ecac38aec49217880"
|
||||
const val BOOTCTL_REVISION = "18ab78817087c337ae0edd1ecac38aec49217880"
|
||||
|
||||
// Misc
|
||||
const val ANDROID_MANIFEST = "AndroidManifest.xml"
|
||||
const val MAGISK_INSTALL_LOG_FILENAME = "magisk_install_log_%s.log"
|
||||
const val MANAGER_CONFIGS = ".tmp.magisk.config"
|
||||
val USER_ID = Process.myUid() / 100000
|
||||
|
||||
object Version {
|
||||
@@ -33,12 +32,12 @@ object Const {
|
||||
|
||||
object ID {
|
||||
const val FETCH_ZIP = 2
|
||||
const val SELECT_BOOT = 3
|
||||
const val SELECT_FILE = 3
|
||||
const val MAX_ACTIVITY_RESULT = 10
|
||||
|
||||
// notifications
|
||||
const val MAGISK_UPDATE_NOTIFICATION_ID = 4
|
||||
const val APK_UPDATE_NOTIFICATION_ID = 5
|
||||
const val DTBO_NOTIFICATION_ID = 7
|
||||
const val HIDE_MANAGER_NOTIFICATION_ID = 8
|
||||
const val UPDATE_NOTIFICATION_CHANNEL = "update"
|
||||
const val PROGRESS_NOTIFICATION_CHANNEL = "progress"
|
||||
@@ -46,22 +45,20 @@ object Const {
|
||||
}
|
||||
|
||||
object Url {
|
||||
const val ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip"
|
||||
const val PATREON_URL = "https://www.patreon.com/topjohnwu"
|
||||
const val SOURCE_CODE_URL = "https://github.com/topjohnwu/Magisk"
|
||||
|
||||
const val GITHUB_RAW_URL = "https://raw.githubusercontent.com/"
|
||||
const val GITHUB_API_URL = "https://api.github.com/users/Magisk-Modules-Repo/"
|
||||
const val GITHUB_API_URL = "https://api.github.com/"
|
||||
const val GITHUB_PAGE_URL = "https://topjohnwu.github.io/magisk_files/"
|
||||
const val JS_DELIVR_URL = "https://cdn.jsdelivr.net/gh/"
|
||||
const val OFFICIAL_REPO = "https://magisk-modules-repo.github.io/submission/modules.json"
|
||||
}
|
||||
|
||||
object Key {
|
||||
// others
|
||||
const val LINK_KEY = "Link"
|
||||
const val IF_NONE_MATCH = "If-None-Match"
|
||||
const val ETAG_KEY = "ETag"
|
||||
// intents
|
||||
const val OPEN_SECTION = "section"
|
||||
const val HIDDEN_PKG = "hidden_pkg"
|
||||
}
|
||||
|
||||
object Value {
|
||||
|
@@ -149,7 +149,7 @@ private object ClassMap {
|
||||
App::class.java to a.e::class.java,
|
||||
MainActivity::class.java to a.b::class.java,
|
||||
SplashActivity::class.java to a.c::class.java,
|
||||
GeneralReceiver::class.java to a.h::class.java,
|
||||
Receiver::class.java to a.h::class.java,
|
||||
DownloadService::class.java to a.j::class.java,
|
||||
SuRequestActivity::class.java to a.m::class.java
|
||||
)
|
||||
|
39
app/src/main/java/com/topjohnwu/magisk/core/Provider.kt
Normal file
39
app/src/main/java/com/topjohnwu/magisk/core/Provider.kt
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ProviderInfo
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.os.ParcelFileDescriptor.MODE_READ_ONLY
|
||||
import com.topjohnwu.magisk.FileProvider
|
||||
import com.topjohnwu.magisk.core.su.SuCallbackHandler
|
||||
import java.io.File
|
||||
|
||||
open class Provider : FileProvider() {
|
||||
|
||||
override fun attachInfo(context: Context, info: ProviderInfo?) {
|
||||
super.attachInfo(context.wrap(), info)
|
||||
}
|
||||
|
||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
|
||||
SuCallbackHandler(context!!, method, extras)
|
||||
return Bundle.EMPTY
|
||||
}
|
||||
|
||||
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? {
|
||||
return when (uri.encodedPath ?: return null) {
|
||||
"/apk_file" -> ParcelFileDescriptor.open(File(context!!.packageCodePath), MODE_READ_ONLY)
|
||||
"/prefs_file" -> ParcelFileDescriptor.open(Config.prefsFile, MODE_READ_ONLY)
|
||||
else -> super.openFile(uri, mode)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun APK_URI(pkg: String) =
|
||||
Uri.Builder().scheme("content").authority("$pkg.provider").path("apk_file").build()
|
||||
|
||||
fun PREFS_URI(pkg: String) =
|
||||
Uri.Builder().scheme("content").authority("$pkg.provider").path("prefs_file").build()
|
||||
}
|
||||
}
|
@@ -11,7 +11,7 @@ import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.inject
|
||||
|
||||
open class GeneralReceiver : BaseReceiver() {
|
||||
open class Receiver : BaseReceiver() {
|
||||
|
||||
private val policyDB: PolicyDao by inject()
|
||||
|
@@ -3,9 +3,9 @@ package com.topjohnwu.magisk.core
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
@@ -29,18 +29,18 @@ open class SplashActivity : Activity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRepackage() {
|
||||
val pkg = Config.suManager
|
||||
if (Config.suManager.isNotEmpty() && packageName == BuildConfig.APPLICATION_ID) {
|
||||
Config.suManager = ""
|
||||
Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec()
|
||||
}
|
||||
if (pkg == packageName) {
|
||||
private fun handleRepackage(pkg: String?) {
|
||||
if (packageName != APPLICATION_ID) {
|
||||
runCatching {
|
||||
// We are the manager, remove com.topjohnwu.magisk as it could be malware
|
||||
packageManager.getApplicationInfo(BuildConfig.APPLICATION_ID, 0)
|
||||
Shell.su("(pm uninstall ${BuildConfig.APPLICATION_ID})& >/dev/null 2>&1").exec()
|
||||
// Hidden, remove com.topjohnwu.magisk if exist as it could be malware
|
||||
packageManager.getApplicationInfo(APPLICATION_ID, 0)
|
||||
Shell.su("(pm uninstall $APPLICATION_ID)& >/dev/null 2>&1").exec()
|
||||
}
|
||||
} else {
|
||||
if (Config.suManager.isNotEmpty())
|
||||
Config.suManager = ""
|
||||
pkg ?: return
|
||||
Shell.su("(pm uninstall $pkg)& >/dev/null 2>&1").exec()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,14 +48,16 @@ open class SplashActivity : Activity() {
|
||||
// Pre-initialize root shell
|
||||
Shell.getShell()
|
||||
|
||||
Config.initialize()
|
||||
handleRepackage()
|
||||
val hiddenPackage = intent.getStringExtra(Const.Key.HIDDEN_PKG)
|
||||
|
||||
Config.load(hiddenPackage ?: APPLICATION_ID)
|
||||
handleRepackage(hiddenPackage)
|
||||
Notifications.setup(this)
|
||||
UpdateCheckService.schedule(this)
|
||||
Shortcuts.setupDynamic(this)
|
||||
|
||||
// Pre-fetch network stuffs
|
||||
get<GithubRawServices>()
|
||||
// Pre-fetch network services
|
||||
get<NetworkService>()
|
||||
|
||||
DONE = true
|
||||
|
||||
|
@@ -3,7 +3,7 @@ package com.topjohnwu.magisk.core
|
||||
import android.content.Context
|
||||
import androidx.work.*
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -15,14 +15,14 @@ import java.util.concurrent.TimeUnit
|
||||
class UpdateCheckService(context: Context, workerParams: WorkerParameters)
|
||||
: CoroutineWorker(context, workerParams), KoinComponent {
|
||||
|
||||
private val magiskRepo: MagiskRepository by inject()
|
||||
private val svc: NetworkService by inject()
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
// Make sure shell initializer was ran
|
||||
withContext(Dispatchers.IO) {
|
||||
Shell.getShell()
|
||||
}
|
||||
return magiskRepo.fetchUpdate()?.let {
|
||||
return svc.fetchUpdate()?.let {
|
||||
if (BuildConfig.VERSION_CODE < it.app.versionCode)
|
||||
Notifications.managerUpdate(applicationContext)
|
||||
else if (Info.env.isActive && Info.env.magiskVersionCode < it.magisk.versionCode)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package com.topjohnwu.magisk.core.base
|
||||
|
||||
import android.Manifest
|
||||
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
@@ -8,22 +8,24 @@ import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.collection.SparseArrayCompat
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||
import com.topjohnwu.magisk.core.wrap
|
||||
import com.topjohnwu.magisk.ktx.set
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import kotlin.random.Random
|
||||
|
||||
typealias RequestCallback = BaseActivity.(Int, Intent?) -> Unit
|
||||
typealias ActivityResultCallback = BaseActivity.(Int, Intent?) -> Unit
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
|
||||
private val resultCallbacks by lazy { SparseArrayCompat<RequestCallback>() }
|
||||
private val resultCallbacks by lazy { SparseArrayCompat<ActivityResultCallback>() }
|
||||
|
||||
override fun applyOverrideConfiguration(config: Configuration?) {
|
||||
// Force applying our preferred local
|
||||
@@ -38,9 +40,8 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
fun withPermission(permission: String, builder: PermissionRequestBuilder.() -> Unit) {
|
||||
val request = PermissionRequestBuilder().apply(builder).build()
|
||||
|
||||
if (permission == Manifest.permission.WRITE_EXTERNAL_STORAGE &&
|
||||
Build.VERSION.SDK_INT >= 29) {
|
||||
// We do not need external rw on 29+
|
||||
if (permission == WRITE_EXTERNAL_STORAGE && Build.VERSION.SDK_INT >= 30) {
|
||||
// We do not need external rw on 30+
|
||||
request.onSuccess()
|
||||
return
|
||||
}
|
||||
@@ -48,8 +49,11 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED) {
|
||||
request.onSuccess()
|
||||
} else {
|
||||
val requestCode = Random.nextInt(256, 512)
|
||||
resultCallbacks[requestCode] = { result, _ ->
|
||||
var requestCode: Int
|
||||
do {
|
||||
requestCode = Random.nextInt(Const.ID.MAX_ACTIVITY_RESULT + 1, 1 shl 15)
|
||||
} while (resultCallbacks.containsKey(requestCode))
|
||||
resultCallbacks[requestCode] = { result, _ ->
|
||||
if (result > 0)
|
||||
request.onSuccess()
|
||||
else
|
||||
@@ -60,7 +64,7 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
fun withExternalRW(builder: PermissionRequestBuilder.() -> Unit) {
|
||||
withPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, builder = builder)
|
||||
withPermission(WRITE_EXTERNAL_STORAGE, builder = builder)
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
@@ -79,16 +83,17 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
resultCallbacks[requestCode]?.also {
|
||||
resultCallbacks[requestCode]?.also { callback ->
|
||||
resultCallbacks.remove(requestCode)
|
||||
it(this, resultCode, data)
|
||||
callback(this, resultCode, data)
|
||||
}
|
||||
}
|
||||
|
||||
fun startActivityForResult(intent: Intent, requestCode: Int, listener: RequestCallback) {
|
||||
resultCallbacks[requestCode] = listener
|
||||
fun startActivityForResult(intent: Intent, requestCode: Int, callback: ActivityResultCallback) {
|
||||
resultCallbacks[requestCode] = callback
|
||||
try {
|
||||
startActivityForResult(intent, requestCode)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
|
@@ -16,15 +16,6 @@ sealed class Action : Parcelable {
|
||||
|
||||
}
|
||||
|
||||
sealed class APK : Action() {
|
||||
|
||||
@Parcelize
|
||||
object Upgrade : APK()
|
||||
|
||||
@Parcelize
|
||||
object Restore : APK()
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
object Download : Action()
|
||||
|
||||
|
@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.base.BaseService
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.checkSum
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.core.utils.ProgressInputStream
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.withStreams
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -34,7 +34,7 @@ abstract class BaseDownloader : BaseService(), KoinComponent {
|
||||
private val notifications = Collections.synchronizedMap(HashMap<Int, Notification.Builder>())
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
val service: GithubRawServices by inject()
|
||||
val service: NetworkService by inject()
|
||||
|
||||
// -- Service overrides
|
||||
|
||||
@@ -117,7 +117,7 @@ abstract class BaseDownloader : BaseService(), KoinComponent {
|
||||
fun Subject.notifyID() = hashCode()
|
||||
|
||||
private fun notifyFail(subject: Subject) = lastNotify(subject.notifyID()) {
|
||||
broadcast(-1f, subject)
|
||||
broadcast(-2f, subject)
|
||||
it.setContentText(getString(R.string.download_file_error))
|
||||
.setSmallIcon(android.R.drawable.stat_notify_error)
|
||||
.setOngoing(false)
|
||||
|
@@ -73,10 +73,7 @@ open class DownloadService : BaseDownloader() {
|
||||
}
|
||||
|
||||
private fun Notification.Builder.setIntent(subject: Manager)
|
||||
= when (subject.action) {
|
||||
APK.Upgrade -> setContentIntent(APKInstall.installIntent(context, subject.file.toFile()))
|
||||
else -> setContentIntent(Intent())
|
||||
}
|
||||
= setContentIntent(APKInstall.installIntent(context, subject.file.toFile()))
|
||||
|
||||
private fun Notification.Builder.setContentIntent(intent: Intent) =
|
||||
setContentIntent(
|
||||
|
@@ -5,20 +5,16 @@ import androidx.core.net.toFile
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action.APK.Restore
|
||||
import com.topjohnwu.magisk.core.download.Action.APK.Upgrade
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.PatchAPK
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.ktx.relaunchApp
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import java.io.File
|
||||
|
||||
private fun Context.patch(apk: File) {
|
||||
val patched = File(apk.parent, "patched.apk")
|
||||
PatchAPK.patch(this, apk.path, patched.path, packageName, applicationInfo.nonLocalizedLabel)
|
||||
HideAPK.patch(this, apk.path, patched.path, packageName, applicationInfo.nonLocalizedLabel)
|
||||
apk.delete()
|
||||
patched.renameTo(apk)
|
||||
}
|
||||
@@ -31,7 +27,7 @@ private fun BaseDownloader.notifyHide(id: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun BaseDownloader.upgrade(subject: Subject.Manager) {
|
||||
suspend fun BaseDownloader.handleAPK(subject: Subject.Manager) {
|
||||
val apk = subject.file.toFile()
|
||||
val id = subject.notifyID()
|
||||
if (isRunningAsStub) {
|
||||
@@ -53,20 +49,3 @@ private suspend fun BaseDownloader.upgrade(subject: Subject.Manager) {
|
||||
patch(apk)
|
||||
}
|
||||
}
|
||||
|
||||
private fun BaseDownloader.restore(apk: File, id: Int) {
|
||||
update(id) {
|
||||
it.setProgress(0, 0, true)
|
||||
.setProgress(0, 0, true)
|
||||
.setContentTitle(getString(R.string.restore_img_msg))
|
||||
.setContentText("")
|
||||
}
|
||||
Config.export()
|
||||
Shell.su("pm install $apk && pm uninstall $packageName").exec()
|
||||
}
|
||||
|
||||
suspend fun BaseDownloader.handleAPK(subject: Subject.Manager) =
|
||||
when (subject.action) {
|
||||
is Upgrade -> upgrade(subject)
|
||||
is Restore -> restore(subject.file.toFile(), subject.notifyID())
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||
import com.topjohnwu.magisk.core.model.StubJson
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.ktx.cachedFile
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
@@ -26,10 +26,10 @@ sealed class Subject : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
class Module(
|
||||
val module: Repo,
|
||||
val module: OnlineModule,
|
||||
override val action: Action
|
||||
) : Subject() {
|
||||
override val url: String get() = module.zipUrl
|
||||
override val url: String get() = module.zip_url
|
||||
override val title: String get() = module.downloadFilename
|
||||
|
||||
@IgnoredOnParcel
|
||||
@@ -40,16 +40,12 @@ sealed class Subject : Parcelable {
|
||||
|
||||
@Parcelize
|
||||
class Manager(
|
||||
override val action: Action.APK,
|
||||
private val app: ManagerJson = Info.remote.app,
|
||||
val stub: StubJson = Info.remote.stub
|
||||
) : Subject() {
|
||||
|
||||
override val title: String
|
||||
get() = "MagiskManager-${app.version}(${app.versionCode})"
|
||||
|
||||
override val url: String
|
||||
get() = app.link
|
||||
override val action get() = Action.Download
|
||||
override val title: String get() = "MagiskManager-${app.version}(${app.versionCode})"
|
||||
override val url: String get() = app.link
|
||||
|
||||
@IgnoredOnParcel
|
||||
override val file by lazy {
|
||||
|
@@ -41,3 +41,29 @@ data class StubJson(
|
||||
val versionCode: Int = -1,
|
||||
val link: String = ""
|
||||
) : Parcelable
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class ModuleJson(
|
||||
val id: String,
|
||||
val last_update: Long,
|
||||
val prop_url: String,
|
||||
val zip_url: String,
|
||||
val notes_url: String
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class RepoJson(
|
||||
val name: String,
|
||||
val last_update: Long,
|
||||
val modules: List<ModuleJson>
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class CommitInfo(
|
||||
val sha: String
|
||||
)
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class BranchInfo(
|
||||
val commit: CommitInfo
|
||||
)
|
||||
|
@@ -1,41 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.model.module
|
||||
|
||||
abstract class BaseModule : Comparable<BaseModule> {
|
||||
abstract var id: String
|
||||
protected set
|
||||
abstract var name: String
|
||||
protected set
|
||||
abstract var author: String
|
||||
protected set
|
||||
abstract var version: String
|
||||
protected set
|
||||
abstract var versionCode: Int
|
||||
protected set
|
||||
abstract var description: String
|
||||
protected set
|
||||
|
||||
@Throws(NumberFormatException::class)
|
||||
protected fun parseProps(props: List<String>) {
|
||||
for (line in props) {
|
||||
val prop = line.split("=".toRegex(), 2).map { it.trim() }
|
||||
if (prop.size != 2)
|
||||
continue
|
||||
|
||||
val key = prop[0]
|
||||
val value = prop[1]
|
||||
if (key.isEmpty() || key[0] == '#')
|
||||
continue
|
||||
|
||||
when (key) {
|
||||
"id" -> id = value
|
||||
"name" -> name = value
|
||||
"version" -> version = value
|
||||
"versionCode" -> versionCode = value.toInt()
|
||||
"author" -> author = value
|
||||
"description" -> description = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override operator fun compareTo(other: BaseModule) = name.compareTo(other.name, true)
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
package com.topjohnwu.magisk.core.model.module
|
||||
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class LocalModule(path: String) : Module() {
|
||||
override var id: String = ""
|
||||
override var name: String = ""
|
||||
override var author: String = ""
|
||||
override var version: String = ""
|
||||
override var versionCode: Int = -1
|
||||
override var description: String = ""
|
||||
|
||||
private val removeFile = SuFile(path, "remove")
|
||||
private val disableFile = SuFile(path, "disable")
|
||||
private val updateFile = SuFile(path, "update")
|
||||
private val ruleFile = SuFile(path, "sepolicy.rule")
|
||||
|
||||
val updated: Boolean get() = updateFile.exists()
|
||||
|
||||
var enable: Boolean
|
||||
get() = !disableFile.exists()
|
||||
set(enable) {
|
||||
val dir = "$PERSIST/$id"
|
||||
if (enable) {
|
||||
disableFile.delete()
|
||||
if (Const.Version.isCanary())
|
||||
Shell.su("copy_sepolicy_rules").submit()
|
||||
else
|
||||
Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit()
|
||||
} else {
|
||||
!disableFile.createNewFile()
|
||||
if (Const.Version.isCanary())
|
||||
Shell.su("copy_sepolicy_rules").submit()
|
||||
else
|
||||
Shell.su("rm -rf $dir").submit()
|
||||
}
|
||||
}
|
||||
|
||||
var remove: Boolean
|
||||
get() = removeFile.exists()
|
||||
set(remove) {
|
||||
if (remove) {
|
||||
removeFile.createNewFile()
|
||||
if (Const.Version.isCanary())
|
||||
Shell.su("copy_sepolicy_rules").submit()
|
||||
else
|
||||
Shell.su("rm -rf $PERSIST/$id").submit()
|
||||
} else {
|
||||
!removeFile.delete()
|
||||
if (Const.Version.isCanary())
|
||||
Shell.su("copy_sepolicy_rules").submit()
|
||||
else
|
||||
Shell.su("cp -af $ruleFile $PERSIST/$id").submit()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
runCatching {
|
||||
parseProps(Shell.su("dos2unix < $path/module.prop").exec().out)
|
||||
}
|
||||
|
||||
if (id.isEmpty()) {
|
||||
val sep = path.lastIndexOf('/')
|
||||
id = path.substring(sep + 1)
|
||||
}
|
||||
|
||||
if (name.isEmpty()) {
|
||||
name = id
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val PERSIST get() = "${Const.MAGISKTMP}/mirror/persist/magisk"
|
||||
|
||||
suspend fun installed() = withContext(Dispatchers.IO) {
|
||||
SuFile(Const.MAGISK_PATH)
|
||||
.listFiles { _, name -> name != "lost+found" && name != ".core" }
|
||||
.orEmpty()
|
||||
.filter { !it.isFile }
|
||||
.map { LocalModule("${Const.MAGISK_PATH}/${it.name}") }
|
||||
.sortedBy { it.name.toLowerCase() }
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,77 +1,41 @@
|
||||
package com.topjohnwu.magisk.core.model.module
|
||||
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.io.SuFile
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
abstract class Module : Comparable<Module> {
|
||||
abstract var id: String
|
||||
protected set
|
||||
abstract var name: String
|
||||
protected set
|
||||
abstract var author: String
|
||||
protected set
|
||||
abstract var version: String
|
||||
protected set
|
||||
abstract var versionCode: Int
|
||||
protected set
|
||||
abstract var description: String
|
||||
protected set
|
||||
|
||||
class Module(path: String) : BaseModule() {
|
||||
override var id: String = ""
|
||||
override var name: String = ""
|
||||
override var author: String = ""
|
||||
override var version: String = ""
|
||||
override var versionCode: Int = -1
|
||||
override var description: String = ""
|
||||
@Throws(NumberFormatException::class)
|
||||
protected fun parseProps(props: List<String>) {
|
||||
for (line in props) {
|
||||
val prop = line.split("=".toRegex(), 2).map { it.trim() }
|
||||
if (prop.size != 2)
|
||||
continue
|
||||
|
||||
private val removeFile = SuFile(path, "remove")
|
||||
private val disableFile = SuFile(path, "disable")
|
||||
private val updateFile = SuFile(path, "update")
|
||||
private val ruleFile = SuFile(path, "sepolicy.rule")
|
||||
val key = prop[0]
|
||||
val value = prop[1]
|
||||
if (key.isEmpty() || key[0] == '#')
|
||||
continue
|
||||
|
||||
val updated: Boolean get() = updateFile.exists()
|
||||
|
||||
var enable: Boolean
|
||||
get() = !disableFile.exists()
|
||||
set(enable) {
|
||||
val dir = "$PERSIST/$id"
|
||||
if (enable) {
|
||||
Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit()
|
||||
disableFile.delete()
|
||||
} else {
|
||||
Shell.su("rm -rf $dir").submit()
|
||||
!disableFile.createNewFile()
|
||||
when (key) {
|
||||
"id" -> id = value
|
||||
"name" -> name = value
|
||||
"version" -> version = value
|
||||
"versionCode" -> versionCode = value.toInt()
|
||||
"author" -> author = value
|
||||
"description" -> description = value
|
||||
}
|
||||
}
|
||||
|
||||
var remove: Boolean
|
||||
get() = removeFile.exists()
|
||||
set(remove) {
|
||||
if (remove) {
|
||||
Shell.su("rm -rf $PERSIST/$id").submit()
|
||||
removeFile.createNewFile()
|
||||
} else {
|
||||
Shell.su("cp -af $ruleFile $PERSIST/$id").submit()
|
||||
!removeFile.delete()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
runCatching {
|
||||
parseProps(Shell.su("dos2unix < $path/module.prop").exec().out)
|
||||
}
|
||||
|
||||
if (id.isEmpty()) {
|
||||
val sep = path.lastIndexOf('/')
|
||||
id = path.substring(sep + 1)
|
||||
}
|
||||
|
||||
if (name.isEmpty()) {
|
||||
name = id
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val PERSIST get() = "${Const.MAGISKTMP}/mirror/persist/magisk"
|
||||
|
||||
suspend fun installed() = withContext(Dispatchers.IO) {
|
||||
SuFile(Const.MAGISK_PATH)
|
||||
.listFiles { _, name -> name != "lost+found" && name != ".core" }
|
||||
.orEmpty()
|
||||
.filter { !it.isFile }
|
||||
.map { Module("${Const.MAGISK_PATH}/${it.name}") }
|
||||
.sortedBy { it.name.toLowerCase() }
|
||||
}
|
||||
}
|
||||
override operator fun compareTo(other: Module) = name.compareTo(other.name, true)
|
||||
}
|
||||
|
@@ -0,0 +1,66 @@
|
||||
package com.topjohnwu.magisk.core.model.module
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.topjohnwu.magisk.core.model.ModuleJson
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.legalFilename
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "modules")
|
||||
@Parcelize
|
||||
data class OnlineModule(
|
||||
@PrimaryKey override var id: String,
|
||||
override var name: String = "",
|
||||
override var author: String = "",
|
||||
override var version: String = "",
|
||||
override var versionCode: Int = -1,
|
||||
override var description: String = "",
|
||||
val last_update: Long,
|
||||
val prop_url: String,
|
||||
val zip_url: String,
|
||||
val notes_url: String
|
||||
) : Module(), Parcelable {
|
||||
|
||||
private val svc: NetworkService get() = get()
|
||||
|
||||
constructor(info: ModuleJson) : this(
|
||||
id = info.id,
|
||||
last_update = info.last_update,
|
||||
prop_url = info.prop_url,
|
||||
zip_url = info.zip_url,
|
||||
notes_url = info.notes_url
|
||||
)
|
||||
|
||||
val lastUpdate get() = Date(last_update)
|
||||
val lastUpdateString get() = DATE_FORMAT.format(lastUpdate)
|
||||
val downloadFilename get() = "$name-$version($versionCode).zip".legalFilename()
|
||||
|
||||
suspend fun notes() = svc.fetchString(notes_url)
|
||||
|
||||
@Throws(IllegalRepoException::class)
|
||||
suspend fun load() {
|
||||
try {
|
||||
val rawProps = svc.fetchString(prop_url)
|
||||
val props = rawProps.split("\\n".toRegex()).dropLastWhile { it.isEmpty() }
|
||||
parseProps(props)
|
||||
} catch (e: Exception) {
|
||||
throw IllegalRepoException("Repo [$id] parse error:", e)
|
||||
}
|
||||
|
||||
if (versionCode < 0) {
|
||||
throw IllegalRepoException("Repo [$id] does not contain versionCode")
|
||||
}
|
||||
}
|
||||
|
||||
class IllegalRepoException(msg: String, cause: Throwable? = null) : Exception(msg, cause)
|
||||
|
||||
companion object {
|
||||
private val DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
|
||||
}
|
||||
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
package com.topjohnwu.magisk.core.model.module
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.data.repository.StringRepository
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.legalFilename
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "repos")
|
||||
@Parcelize
|
||||
data class Repo(
|
||||
@PrimaryKey override var id: String,
|
||||
override var name: String,
|
||||
override var author: String,
|
||||
override var version: String,
|
||||
override var versionCode: Int,
|
||||
override var description: String,
|
||||
var last_update: Long
|
||||
) : BaseModule(), Parcelable {
|
||||
|
||||
private val stringRepo: StringRepository get() = get()
|
||||
|
||||
val lastUpdate get() = Date(last_update)
|
||||
|
||||
val lastUpdateString: String get() = dateFormat.format(lastUpdate)
|
||||
|
||||
val downloadFilename: String get() = "$name-$version($versionCode).zip".legalFilename()
|
||||
|
||||
suspend fun readme() = stringRepo.getReadme(this)
|
||||
|
||||
val zipUrl: String get() = Const.Url.ZIP_URL.format(id)
|
||||
|
||||
constructor(id: String) : this(id, "", "", "", -1, "", 0)
|
||||
|
||||
@Throws(IllegalRepoException::class)
|
||||
private fun loadProps(props: String) {
|
||||
props.split("\\n".toRegex()).dropLastWhile { it.isEmpty() }.runCatching {
|
||||
parseProps(this)
|
||||
}.onFailure {
|
||||
throw IllegalRepoException("Repo [$id] parse error: " + it.message)
|
||||
}
|
||||
|
||||
if (versionCode < 0) {
|
||||
throw IllegalRepoException("Repo [$id] does not contain versionCode")
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IllegalRepoException::class)
|
||||
suspend fun update(lastUpdate: Date? = null) {
|
||||
lastUpdate?.let { last_update = it.time }
|
||||
loadProps(stringRepo.getMetadata(this))
|
||||
}
|
||||
|
||||
class IllegalRepoException(message: String) : Exception(message)
|
||||
|
||||
companion object {
|
||||
val dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
|
||||
}
|
||||
}
|
@@ -7,14 +7,12 @@ import android.os.Bundle
|
||||
import android.os.Process
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.ProviderCallHandler
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
import com.topjohnwu.magisk.core.model.su.SuPolicy
|
||||
import com.topjohnwu.magisk.core.model.su.toLog
|
||||
import com.topjohnwu.magisk.core.model.su.toPolicy
|
||||
import com.topjohnwu.magisk.core.wrap
|
||||
import com.topjohnwu.magisk.data.repository.LogRepository
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.startActivity
|
||||
@@ -26,18 +24,13 @@ import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
object SuCallbackHandler : ProviderCallHandler {
|
||||
object SuCallbackHandler {
|
||||
|
||||
const val REQUEST = "request"
|
||||
const val LOG = "log"
|
||||
const val NOTIFY = "notify"
|
||||
const val TEST = "test"
|
||||
|
||||
override fun call(context: Context, method: String, arg: String?, extras: Bundle?): Bundle? {
|
||||
invoke(context.wrap(), method, extras)
|
||||
return Bundle.EMPTY
|
||||
}
|
||||
|
||||
operator fun invoke(context: Context, action: String?, data: Bundle?) {
|
||||
data ?: return
|
||||
|
||||
|
@@ -36,7 +36,7 @@ class SuRequestHandler(
|
||||
if (policy.packageName == BuildConfig.APPLICATION_ID)
|
||||
return false
|
||||
|
||||
when (Config.suAutoReponse) {
|
||||
when (Config.suAutoResponse) {
|
||||
Config.Value.SU_AUTO_DENY -> {
|
||||
respond(SuPolicy.DENY, 0)
|
||||
return false
|
||||
|
@@ -1,20 +1,20 @@
|
||||
package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.BuildConfig.APPLICATION_ID
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.*
|
||||
import com.topjohnwu.magisk.core.utils.AXML
|
||||
import com.topjohnwu.magisk.core.utils.Keygen
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.inject
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.Notifications
|
||||
import com.topjohnwu.signing.JarMap
|
||||
import com.topjohnwu.signing.SignApk
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -28,25 +28,27 @@ import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
|
||||
object PatchAPK {
|
||||
object HideAPK {
|
||||
|
||||
private const val ALPHA = "abcdefghijklmnopqrstuvwxyz"
|
||||
private const val ALPHADOTS = "$ALPHA....."
|
||||
|
||||
private const val APP_ID = "com.topjohnwu.magisk"
|
||||
private const val APP_NAME = "Magisk Manager"
|
||||
|
||||
// Some arbitrary limit
|
||||
const val MAX_LABEL_LENGTH = 32
|
||||
|
||||
private fun genPackageName(): CharSequence {
|
||||
private val svc: NetworkService by inject()
|
||||
private val Context.APK_URI get() = Provider.APK_URI(packageName)
|
||||
private val Context.PREFS_URI get() = Provider.PREFS_URI(packageName)
|
||||
|
||||
private fun genPackageName(): String {
|
||||
val random = SecureRandom()
|
||||
val len = 5 + random.nextInt(15)
|
||||
val builder = StringBuilder(len)
|
||||
var next: Char
|
||||
var prev = 0.toChar()
|
||||
for (i in 0 until len) {
|
||||
next = if (prev == '.' || i == len - 1) {
|
||||
next = if (prev == '.' || prev == 0.toChar() || i == len - 1) {
|
||||
ALPHA[random.nextInt(ALPHA.length)]
|
||||
} else {
|
||||
ALPHADOTS[random.nextInt(ALPHADOTS.length)]
|
||||
@@ -59,20 +61,20 @@ object PatchAPK {
|
||||
val idx = random.nextInt(len - 1)
|
||||
builder[idx] = '.'
|
||||
}
|
||||
return builder
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun patch(
|
||||
context: Context,
|
||||
apk: String, out: String,
|
||||
pkg: CharSequence, label: CharSequence
|
||||
pkg: String, label: CharSequence
|
||||
): Boolean {
|
||||
try {
|
||||
val jar = JarMap.open(apk)
|
||||
val je = jar.getJarEntry(Const.ANDROID_MANIFEST)
|
||||
val xml = AXML(jar.getRawData(je))
|
||||
|
||||
if (!xml.findAndPatch(APP_ID to pkg.toString(), APP_NAME to label.toString()))
|
||||
if (!xml.findAndPatch(APPLICATION_ID to pkg, APP_NAME to label.toString()))
|
||||
return false
|
||||
|
||||
// Write apk changes
|
||||
@@ -91,7 +93,6 @@ object PatchAPK {
|
||||
val dlStub = !isRunningAsStub && SDK_INT >= 28 && Const.Version.atLeast_20_2()
|
||||
val src = if (dlStub) {
|
||||
val stub = File(context.cacheDir, "stub.apk")
|
||||
val svc = get<GithubRawServices>()
|
||||
try {
|
||||
svc.fetchFile(Info.remote.stub.link).byteStream().use {
|
||||
it.writeTo(stub)
|
||||
@@ -117,23 +118,73 @@ object PatchAPK {
|
||||
if (!Shell.su("adb_pm_install $repack").exec().isSuccess)
|
||||
return false
|
||||
|
||||
Config.suManager = pkg.toString()
|
||||
Config.export()
|
||||
Shell.su("pm uninstall $APP_ID").submit()
|
||||
context.apply {
|
||||
val intent = packageManager.getLaunchIntentForPackage(pkg) ?: return false
|
||||
Config.suManager = pkg
|
||||
grantUriPermission(pkg, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
grantUriPermission(pkg, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun hideManager(context: Context, label: String) {
|
||||
val progress = Notifications.progress(context, context.getString(R.string.hide_manager_title))
|
||||
Notifications.mgr.notify(Const.ID.HIDE_MANAGER_NOTIFICATION_ID, progress.build())
|
||||
@Suppress("DEPRECATION")
|
||||
fun hide(context: Context, label: String) {
|
||||
val dialog = ProgressDialog.show(context, context.getString(R.string.hide_manager_title), "", true)
|
||||
GlobalScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
patchAndHide(context, label)
|
||||
}
|
||||
if (!result)
|
||||
if (!result) {
|
||||
Utils.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG)
|
||||
Notifications.mgr.cancel(Const.ID.HIDE_MANAGER_NOTIFICATION_ID)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadAndRestore(context: Context): Boolean {
|
||||
val apk = if (isRunningAsStub) {
|
||||
DynAPK.current(context)
|
||||
} else {
|
||||
File(context.cacheDir, "manager.apk").also { apk ->
|
||||
try {
|
||||
svc.fetchFile(Info.remote.app.link).byteStream().use {
|
||||
it.writeTo(apk)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Shell.su("adb_pm_install $apk").exec().isSuccess)
|
||||
return false
|
||||
|
||||
context.apply {
|
||||
val intent = packageManager.getLaunchIntentForPackage(APPLICATION_ID) ?: return false
|
||||
Config.suManager = ""
|
||||
grantUriPermission(APPLICATION_ID, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
grantUriPermission(APPLICATION_ID, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
intent.putExtra(Const.Key.HIDDEN_PKG, packageName)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun restore(context: Context) {
|
||||
val dialog = ProgressDialog.show(context, context.getString(R.string.restore_img_msg), "", true)
|
||||
GlobalScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
downloadAndRestore(context)
|
||||
}
|
||||
if (!result) {
|
||||
Utils.toast(R.string.restore_manager_fail_toast, Toast.LENGTH_LONG)
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.di.Protected
|
||||
import com.topjohnwu.magisk.events.dialog.EnvFixDialog
|
||||
import com.topjohnwu.magisk.ktx.reboot
|
||||
@@ -29,6 +29,7 @@ import com.topjohnwu.superuser.io.SuFileInputStream
|
||||
import com.topjohnwu.superuser.io.SuFileOutputStream
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.jpountz.lz4.LZ4FrameInputStream
|
||||
import org.kamranzafar.jtar.TarEntry
|
||||
import org.kamranzafar.jtar.TarHeader
|
||||
import org.kamranzafar.jtar.TarInputStream
|
||||
@@ -38,6 +39,7 @@ import org.koin.core.get
|
||||
import org.koin.core.inject
|
||||
import timber.log.Timber
|
||||
import java.io.*
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
@@ -51,7 +53,7 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
private val logs: MutableList<String>
|
||||
private var tarOut: TarOutputStream? = null
|
||||
|
||||
private val service: GithubRawServices by inject()
|
||||
private val service: NetworkService by inject()
|
||||
protected val context: Context by inject()
|
||||
|
||||
protected constructor() {
|
||||
@@ -97,8 +99,7 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun extractZip(): Boolean {
|
||||
val arch: String
|
||||
arch = if (Build.VERSION.SDK_INT >= 21) {
|
||||
val arch = if (Build.VERSION.SDK_INT >= 21) {
|
||||
val abis = listOf(*Build.SUPPORTED_ABIS)
|
||||
if (abis.contains("x86")) "x86" else "arm"
|
||||
} else {
|
||||
@@ -163,21 +164,36 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
val tarOut = TarOutputStream(output)
|
||||
TarInputStream(input).use { tarIn ->
|
||||
lateinit var entry: TarEntry
|
||||
|
||||
fun decompressedStream() =
|
||||
if (entry.name.contains(".lz4")) LZ4FrameInputStream(tarIn) else tarIn
|
||||
|
||||
while (tarIn.nextEntry?.let { entry = it } != null) {
|
||||
if (entry.name.contains("boot.img") ||
|
||||
(Config.recovery && entry.name.contains("recovery.img"))) {
|
||||
val name = entry.name
|
||||
val name = entry.name.replace(".lz4", "")
|
||||
console.add("-- Extracting: $name")
|
||||
|
||||
val extract = File(installDir, name)
|
||||
FileOutputStream(extract).use { tarIn.copyTo(it) }
|
||||
if (name.contains(".lz4")) {
|
||||
console.add("-- Decompressing: $name")
|
||||
"./magiskboot decompress $extract".sh()
|
||||
FileOutputStream(extract).use { decompressedStream().copyTo(it) }
|
||||
} else if (entry.name.contains("vbmeta.img")) {
|
||||
val rawData = ByteArrayOutputStream().let {
|
||||
decompressedStream().copyTo(it)
|
||||
it.toByteArray()
|
||||
}
|
||||
// Valid vbmeta.img should be at least 256 bytes
|
||||
if (rawData.size < 256)
|
||||
continue
|
||||
|
||||
// Patch flags to AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
|
||||
console.add("-- Patching: vbmeta.img")
|
||||
ByteBuffer.wrap(rawData).putInt(120, 2)
|
||||
tarOut.putNextEntry(newEntry("vbmeta.img", rawData.size.toLong()))
|
||||
tarOut.write(rawData)
|
||||
} else {
|
||||
console.add("-- Copying: " + entry.name)
|
||||
console.add("-- Copying: ${entry.name}")
|
||||
tarOut.putNextEntry(entry)
|
||||
tarIn.copyTo(tarOut)
|
||||
tarIn.copyTo(tarOut, bufferSize = 1024 * 1024)
|
||||
}
|
||||
}
|
||||
val boot = SuFile.open(installDir, "boot.img")
|
||||
@@ -274,7 +290,7 @@ abstract class MagiskInstallImpl : KoinComponent {
|
||||
srcBoot = File(installDir, "boot.img").path
|
||||
}
|
||||
|
||||
var isSigned = false
|
||||
var isSigned: Boolean
|
||||
try {
|
||||
SuFileInputStream(srcBoot).use {
|
||||
isSigned = SignBoot.verifySignature(it, null)
|
||||
|
@@ -1,119 +1,42 @@
|
||||
package com.topjohnwu.magisk.core.tasks
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.data.database.RepoDao
|
||||
import com.topjohnwu.magisk.data.network.GithubApiServices
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.synchronized
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
import java.net.HttpURLConnection
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
class RepoUpdater(
|
||||
private val api: GithubApiServices,
|
||||
private val svc: NetworkService,
|
||||
private val repoDB: RepoDao
|
||||
) {
|
||||
|
||||
private fun String.trimEtag() = substring(indexOf('\"'), lastIndexOf('\"') + 1)
|
||||
|
||||
private suspend fun forcedReload(cached: MutableSet<String>) = coroutineScope {
|
||||
cached.forEach {
|
||||
launch {
|
||||
val repo = repoDB.getRepo(it)!!
|
||||
try {
|
||||
repo.update()
|
||||
repoDB.addRepo(repo)
|
||||
} catch (e: Repo.IllegalRepoException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun loadRepos(
|
||||
repos: List<GithubRepoInfo>,
|
||||
cached: MutableSet<String>
|
||||
) = coroutineScope {
|
||||
repos.forEach {
|
||||
// Skip submission
|
||||
if (it.id == "submission")
|
||||
return@forEach
|
||||
launch {
|
||||
val repo = repoDB.getRepo(it.id)?.apply { cached.remove(it.id) } ?: Repo(it.id)
|
||||
try {
|
||||
repo.update(it.pushDate)
|
||||
repoDB.addRepo(repo)
|
||||
} catch (e: Repo.IllegalRepoException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class PageResult {
|
||||
SUCCESS,
|
||||
CACHED,
|
||||
ERROR
|
||||
}
|
||||
|
||||
private suspend fun loadPage(
|
||||
cached: MutableSet<String>,
|
||||
page: Int = 1,
|
||||
etag: String = ""
|
||||
): PageResult = coroutineScope {
|
||||
runCatching {
|
||||
val result = api.fetchRepos(page, etag)
|
||||
result.run {
|
||||
if (code() == HttpURLConnection.HTTP_NOT_MODIFIED)
|
||||
return@coroutineScope PageResult.CACHED
|
||||
|
||||
if (!isSuccessful)
|
||||
return@coroutineScope PageResult.ERROR
|
||||
|
||||
if (page == 1)
|
||||
repoDB.etagKey = headers()[Const.Key.ETAG_KEY].orEmpty().trimEtag()
|
||||
|
||||
val repoLoad = async { loadRepos(body()!!, cached) }
|
||||
val next = if (headers()[Const.Key.LINK_KEY].orEmpty().contains("next")) {
|
||||
async { loadPage(cached, page + 1) }
|
||||
} else {
|
||||
async { PageResult.SUCCESS }
|
||||
}
|
||||
repoLoad.await()
|
||||
return@coroutineScope next.await()
|
||||
}
|
||||
}.getOrElse {
|
||||
Timber.e(it)
|
||||
PageResult.ERROR
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun run(forced: Boolean) = withContext(Dispatchers.IO) {
|
||||
val cached = HashSet(repoDB.repoIDList).synchronized()
|
||||
when (loadPage(cached, etag = repoDB.etagKey)) {
|
||||
PageResult.CACHED -> if (forced) forcedReload(cached)
|
||||
PageResult.SUCCESS -> repoDB.removeRepos(cached)
|
||||
PageResult.ERROR -> Unit
|
||||
val cachedMap = HashMap<String, Date>().also { map ->
|
||||
repoDB.getModuleStubs().forEach { map[it.id] = Date(it.last_update) }
|
||||
}.synchronized()
|
||||
svc.fetchRepoInfo()?.let { info ->
|
||||
coroutineScope {
|
||||
info.modules.forEach {
|
||||
launch {
|
||||
val lastUpdated = cachedMap.remove(it.id)
|
||||
if (forced || lastUpdated?.before(Date(it.last_update)) != false) {
|
||||
try {
|
||||
val repo = OnlineModule(it).apply { load() }
|
||||
repoDB.addModule(repo)
|
||||
} catch (e: OnlineModule.IllegalRepoException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
repoDB.removeModules(cachedMap.keys)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val dateFormat: SimpleDateFormat =
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).apply {
|
||||
timeZone = TimeZone.getTimeZone("UTC")
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class GithubRepoInfo(
|
||||
val name: String,
|
||||
val pushed_at: String
|
||||
) {
|
||||
val id get() = name
|
||||
|
||||
@Transient
|
||||
val pushDate = dateFormat.parse(pushed_at)!!
|
||||
}
|
||||
|
@@ -66,8 +66,8 @@ object MediaStoreUtils {
|
||||
}
|
||||
|
||||
private fun queryFile(displayName: String): UriFile? {
|
||||
if (Build.VERSION.SDK_INT < 29) {
|
||||
// Before official general purpose MediaStore API exists, fallback to file based I/O
|
||||
if (Build.VERSION.SDK_INT < 30) {
|
||||
// Fallback to file based I/O pre Android 11
|
||||
val parent = File(Environment.getExternalStorageDirectory(), relativePath)
|
||||
parent.mkdirs()
|
||||
return LegacyUriFile(File(parent, displayName))
|
||||
@@ -101,7 +101,7 @@ object MediaStoreUtils {
|
||||
|
||||
fun Uri.inputStream() = cr.openInputStream(this) ?: throw FileNotFoundException()
|
||||
|
||||
fun Uri.outputStream() = cr.openOutputStream(this) ?: throw FileNotFoundException()
|
||||
fun Uri.outputStream() = cr.openOutputStream(this, "rwt") ?: throw FileNotFoundException()
|
||||
|
||||
val Uri.displayName: String get() {
|
||||
if (scheme == "file") {
|
||||
|
@@ -1,67 +0,0 @@
|
||||
@file:JvmMultifileClass
|
||||
|
||||
package com.topjohnwu.magisk.data.database
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Query
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
|
||||
interface RepoBase {
|
||||
|
||||
fun getRepos(offset: Int, limit: Int = LIMIT): List<Repo>
|
||||
fun searchRepos(query: String, offset: Int, limit: Int = LIMIT): List<Repo>
|
||||
|
||||
@Query("SELECT * FROM repos WHERE id = :id AND versionCode > :versionCode LIMIT 1")
|
||||
fun getUpdatableRepoById(id: String, versionCode: Int): Repo?
|
||||
|
||||
@Query("SELECT * FROM repos WHERE id = :id LIMIT 1")
|
||||
fun getRepoById(id: String): Repo?
|
||||
|
||||
companion object {
|
||||
const val LIMIT = 10
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface RepoByUpdatedDao : RepoBase {
|
||||
|
||||
@Query("SELECT * FROM repos ORDER BY last_update DESC LIMIT :limit OFFSET :offset")
|
||||
override fun getRepos(offset: Int, limit: Int): List<Repo>
|
||||
|
||||
@Query(
|
||||
"""SELECT *
|
||||
FROM repos
|
||||
WHERE
|
||||
(author LIKE '%' || :query || '%') ||
|
||||
(name LIKE '%' || :query || '%') ||
|
||||
(description LIKE '%' || :query || '%')
|
||||
ORDER BY last_update DESC
|
||||
LIMIT :limit
|
||||
OFFSET :offset"""
|
||||
)
|
||||
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
||||
|
||||
}
|
||||
|
||||
@Dao
|
||||
interface RepoByNameDao : RepoBase {
|
||||
|
||||
@Query("SELECT * FROM repos ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset")
|
||||
override fun getRepos(offset: Int, limit: Int): List<Repo>
|
||||
|
||||
@Query(
|
||||
"""SELECT *
|
||||
FROM repos
|
||||
WHERE
|
||||
(author LIKE '%' || :query || '%') ||
|
||||
(name LIKE '%' || :query || '%') ||
|
||||
(description LIKE '%' || :query || '%')
|
||||
ORDER BY name COLLATE NOCASE
|
||||
LIMIT :limit
|
||||
OFFSET :offset"""
|
||||
)
|
||||
override fun searchRepos(query: String, offset: Int, limit: Int): List<Repo>
|
||||
|
||||
|
||||
}
|
@@ -2,72 +2,89 @@ package com.topjohnwu.magisk.data.database
|
||||
|
||||
import androidx.room.*
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Database(version = 6, entities = [Repo::class, RepoEtag::class], exportSchema = false)
|
||||
@Database(version = 8, entities = [OnlineModule::class], exportSchema = false)
|
||||
abstract class RepoDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun repoDao() : RepoDao
|
||||
abstract fun repoByUpdatedDao(): RepoByUpdatedDao
|
||||
abstract fun repoByNameDao(): RepoByNameDao
|
||||
}
|
||||
|
||||
@Dao
|
||||
abstract class RepoDao(private val db: RepoDatabase) {
|
||||
|
||||
val repoIDList get() = getRepoID().map { it.id }
|
||||
|
||||
val repos: List<Repo> get() = when (Config.repoOrder) {
|
||||
Config.Value.ORDER_NAME -> getReposNameOrder()
|
||||
else -> getReposDateOrder()
|
||||
}
|
||||
|
||||
var etagKey: String
|
||||
set(value) = addEtagRaw(RepoEtag(0, value))
|
||||
get() = etagRaw()?.key.orEmpty()
|
||||
|
||||
suspend fun clear() = withContext(Dispatchers.IO) { db.clearAllTables() }
|
||||
|
||||
@Query("SELECT * FROM repos ORDER BY last_update DESC")
|
||||
protected abstract fun getReposDateOrder(): List<Repo>
|
||||
|
||||
@Query("SELECT * FROM repos ORDER BY name COLLATE NOCASE")
|
||||
protected abstract fun getReposNameOrder(): List<Repo>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
abstract fun addRepo(repo: Repo)
|
||||
|
||||
@Query("SELECT * FROM repos WHERE id = :id")
|
||||
abstract fun getRepo(id: String): Repo?
|
||||
|
||||
@Query("SELECT id FROM repos")
|
||||
protected abstract fun getRepoID(): List<RepoID>
|
||||
abstract fun addModule(repo: OnlineModule)
|
||||
|
||||
@Delete
|
||||
abstract fun removeRepo(repo: Repo)
|
||||
abstract fun removeModule(repo: OnlineModule)
|
||||
|
||||
@Query("DELETE FROM repos WHERE id = :id")
|
||||
abstract fun removeRepo(id: String)
|
||||
@Query("DELETE FROM modules WHERE id = :id")
|
||||
abstract fun removeModule(id: String)
|
||||
|
||||
@Query("DELETE FROM repos WHERE id IN (:idList)")
|
||||
abstract fun removeRepos(idList: Collection<String>)
|
||||
@Query("DELETE FROM modules WHERE id IN (:idList)")
|
||||
abstract fun removeModules(idList: Collection<String>)
|
||||
|
||||
@Query("SELECT * FROM etag")
|
||||
protected abstract fun etagRaw(): RepoEtag?
|
||||
@Query("SELECT * FROM modules WHERE id = :id")
|
||||
abstract fun getModule(id: String): OnlineModule?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
protected abstract fun addEtagRaw(etag: RepoEtag)
|
||||
@Query("SELECT id, last_update FROM modules")
|
||||
abstract fun getModuleStubs(): List<ModuleStub>
|
||||
|
||||
fun getModules(offset: Int, limit: Int = LIMIT) = when (Config.repoOrder) {
|
||||
Config.Value.ORDER_NAME -> getNameOrder(offset, limit)
|
||||
else -> getDateOrder(offset, limit)
|
||||
}
|
||||
|
||||
fun searchModules(query: String, offset: Int, limit: Int = LIMIT) = when (Config.repoOrder) {
|
||||
Config.Value.ORDER_NAME -> searchNameOrder(query, offset, limit)
|
||||
else -> searchDateOrder(query, offset, limit)
|
||||
}
|
||||
|
||||
@Query("SELECT * FROM modules WHERE id = :id AND versionCode > :versionCode LIMIT 1")
|
||||
abstract fun getUpdatableModule(id: String, versionCode: Int): OnlineModule?
|
||||
|
||||
@Query("SELECT * FROM modules ORDER BY last_update DESC LIMIT :limit OFFSET :offset")
|
||||
protected abstract fun getDateOrder(offset: Int, limit: Int): List<OnlineModule>
|
||||
|
||||
@Query("SELECT * FROM modules ORDER BY name COLLATE NOCASE LIMIT :limit OFFSET :offset")
|
||||
protected abstract fun getNameOrder(offset: Int, limit: Int): List<OnlineModule>
|
||||
|
||||
@Query(
|
||||
"""SELECT *
|
||||
FROM modules
|
||||
WHERE
|
||||
(author LIKE '%' || :query || '%') ||
|
||||
(name LIKE '%' || :query || '%') ||
|
||||
(description LIKE '%' || :query || '%')
|
||||
ORDER BY last_update DESC
|
||||
LIMIT :limit
|
||||
OFFSET :offset"""
|
||||
)
|
||||
protected abstract fun searchDateOrder(query: String, offset: Int, limit: Int): List<OnlineModule>
|
||||
|
||||
@Query(
|
||||
"""SELECT *
|
||||
FROM modules
|
||||
WHERE
|
||||
(author LIKE '%' || :query || '%') ||
|
||||
(name LIKE '%' || :query || '%') ||
|
||||
(description LIKE '%' || :query || '%')
|
||||
ORDER BY name COLLATE NOCASE
|
||||
LIMIT :limit
|
||||
OFFSET :offset"""
|
||||
)
|
||||
protected abstract fun searchNameOrder(query: String, offset: Int, limit: Int): List<OnlineModule>
|
||||
|
||||
companion object {
|
||||
const val LIMIT = 10
|
||||
}
|
||||
}
|
||||
|
||||
data class RepoID(
|
||||
@PrimaryKey val id: String
|
||||
data class ModuleStub(
|
||||
@PrimaryKey val id: String,
|
||||
val last_update: Long
|
||||
)
|
||||
|
||||
@Entity(tableName = "etag")
|
||||
data class RepoEtag(
|
||||
@PrimaryKey val id: Int,
|
||||
val key: String
|
||||
)
|
||||
|
||||
|
@@ -1,87 +0,0 @@
|
||||
package com.topjohnwu.magisk.data.network
|
||||
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import com.topjohnwu.magisk.core.tasks.GithubRepoInfo
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.*
|
||||
|
||||
interface GithubPageServices {
|
||||
|
||||
@GET("stable.json")
|
||||
suspend fun fetchStableUpdate(): UpdateInfo
|
||||
|
||||
@GET("beta.json")
|
||||
suspend fun fetchBetaUpdate(): UpdateInfo
|
||||
}
|
||||
|
||||
interface GithubRawServices {
|
||||
|
||||
//region topjohnwu/magisk_files
|
||||
|
||||
@GET("$MAGISK_FILES/master/stable.json")
|
||||
suspend fun fetchStableUpdate(): UpdateInfo
|
||||
|
||||
@GET("$MAGISK_FILES/master/beta.json")
|
||||
suspend fun fetchBetaUpdate(): UpdateInfo
|
||||
|
||||
@GET("$MAGISK_FILES/canary/debug.json")
|
||||
suspend fun fetchCanaryUpdate(): UpdateInfo
|
||||
|
||||
@GET
|
||||
suspend fun fetchCustomUpdate(@Url url: String): UpdateInfo
|
||||
|
||||
@GET("$MAGISK_FILES/{$REVISION}/snet.jar")
|
||||
@Streaming
|
||||
suspend fun fetchSafetynet(@Path(REVISION) revision: String = Const.SNET_REVISION): ResponseBody
|
||||
|
||||
@GET("$MAGISK_FILES/{$REVISION}/bootctl")
|
||||
@Streaming
|
||||
suspend fun fetchBootctl(@Path(REVISION) revision: String = Const.BOOTCTL_REVISION): ResponseBody
|
||||
|
||||
@GET("$MAGISK_MASTER/scripts/module_installer.sh")
|
||||
@Streaming
|
||||
suspend fun fetchInstaller(): ResponseBody
|
||||
|
||||
@GET("$MAGISK_MODULES/{$MODULE}/master/{$FILE}")
|
||||
suspend fun fetchModuleFile(@Path(MODULE) id: String, @Path(FILE) file: String): String
|
||||
|
||||
//endregion
|
||||
|
||||
/**
|
||||
* This method shall be used exclusively for fetching files from urls from previous requests.
|
||||
* Him, who uses it in a wrong way, shall die in an eternal flame.
|
||||
* */
|
||||
@GET
|
||||
@Streaming
|
||||
suspend fun fetchFile(@Url url: String): ResponseBody
|
||||
|
||||
@GET
|
||||
suspend fun fetchString(@Url url: String): String
|
||||
|
||||
|
||||
companion object {
|
||||
private const val REVISION = "revision"
|
||||
private const val MODULE = "module"
|
||||
private const val FILE = "file"
|
||||
|
||||
|
||||
private const val MAGISK_FILES = "topjohnwu/magisk_files"
|
||||
private const val MAGISK_MASTER = "topjohnwu/Magisk/master"
|
||||
private const val MAGISK_MODULES = "Magisk-Modules-Repo"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
interface GithubApiServices {
|
||||
|
||||
@GET("repos")
|
||||
suspend fun fetchRepos(
|
||||
@Query("page") page: Int,
|
||||
@Header(Const.Key.IF_NONE_MATCH) etag: String,
|
||||
@Query("sort") sort: String = "pushed",
|
||||
@Query("per_page") count: Int = 100
|
||||
): Response<List<GithubRepoInfo>>
|
||||
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package com.topjohnwu.magisk.data.network
|
||||
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.model.BranchInfo
|
||||
import com.topjohnwu.magisk.core.model.RepoJson
|
||||
import com.topjohnwu.magisk.core.model.UpdateInfo
|
||||
import okhttp3.ResponseBody
|
||||
import retrofit2.http.*
|
||||
|
||||
private const val REVISION = "revision"
|
||||
private const val BRANCH = "branch"
|
||||
private const val REPO = "repo"
|
||||
|
||||
const val MAGISK_FILES = "topjohnwu/magisk_files"
|
||||
const val MAGISK_MAIN = "topjohnwu/Magisk"
|
||||
|
||||
interface GithubPageServices {
|
||||
|
||||
@GET("stable.json")
|
||||
suspend fun fetchStableUpdate(): UpdateInfo
|
||||
|
||||
@GET("beta.json")
|
||||
suspend fun fetchBetaUpdate(): UpdateInfo
|
||||
}
|
||||
|
||||
interface JSDelivrServices {
|
||||
|
||||
@GET("$MAGISK_FILES@{$REVISION}/snet")
|
||||
@Streaming
|
||||
suspend fun fetchSafetynet(@Path(REVISION) revision: String = Const.SNET_REVISION): ResponseBody
|
||||
|
||||
@GET("$MAGISK_FILES@{$REVISION}/bootctl")
|
||||
@Streaming
|
||||
suspend fun fetchBootctl(@Path(REVISION) revision: String = Const.BOOTCTL_REVISION): ResponseBody
|
||||
|
||||
@GET("$MAGISK_FILES@{$REVISION}/canary.json")
|
||||
suspend fun fetchCanaryUpdate(@Path(REVISION) revision: String): UpdateInfo
|
||||
|
||||
@GET("$MAGISK_MAIN@{$REVISION}/scripts/module_installer.sh")
|
||||
@Streaming
|
||||
suspend fun fetchInstaller(@Path(REVISION) revision: String): ResponseBody
|
||||
}
|
||||
|
||||
interface RawServices {
|
||||
|
||||
@GET
|
||||
suspend fun fetchCustomUpdate(@Url url: String): UpdateInfo
|
||||
|
||||
@GET
|
||||
suspend fun fetchRepoInfo(@Url url: String): RepoJson
|
||||
|
||||
@GET
|
||||
@Streaming
|
||||
suspend fun fetchFile(@Url url: String): ResponseBody
|
||||
|
||||
@GET
|
||||
suspend fun fetchString(@Url url: String): String
|
||||
|
||||
}
|
||||
|
||||
interface GithubApiServices {
|
||||
|
||||
@GET("repos/{$REPO}/branches/{$BRANCH}")
|
||||
@Headers("Accept: application/vnd.github.v3+json")
|
||||
suspend fun fetchBranch(
|
||||
@Path(REPO, encoded = true) repo: String,
|
||||
@Path(BRANCH) branch: String
|
||||
): BranchInfo
|
||||
}
|
||||
|
@@ -11,16 +11,14 @@ interface PreferenceModel {
|
||||
|
||||
val fileName: String
|
||||
get() = "${context.packageName}_preferences"
|
||||
val commitPrefs: Boolean
|
||||
get() = false
|
||||
|
||||
val prefs: SharedPreferences
|
||||
get() = context.getSharedPreferences(fileName, Context.MODE_PRIVATE)
|
||||
|
||||
fun preferenceStrInt(
|
||||
name: String,
|
||||
default: Int,
|
||||
writeDefault: Boolean = false,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = object: ReadWriteProperty<PreferenceModel, Int> {
|
||||
val base = StringProperty(name, default.toString(), commit)
|
||||
override fun getValue(thisRef: PreferenceModel, property: KProperty<*>): Int =
|
||||
@@ -33,37 +31,37 @@ interface PreferenceModel {
|
||||
fun preference(
|
||||
name: String,
|
||||
default: Boolean,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = BooleanProperty(name, default, commit)
|
||||
|
||||
fun preference(
|
||||
name: String,
|
||||
default: Float,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = FloatProperty(name, default, commit)
|
||||
|
||||
fun preference(
|
||||
name: String,
|
||||
default: Int,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = IntProperty(name, default, commit)
|
||||
|
||||
fun preference(
|
||||
name: String,
|
||||
default: Long,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = LongProperty(name, default, commit)
|
||||
|
||||
fun preference(
|
||||
name: String,
|
||||
default: String,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = StringProperty(name, default, commit)
|
||||
|
||||
fun preference(
|
||||
name: String,
|
||||
default: Set<String>,
|
||||
commit: Boolean = commitPrefs
|
||||
commit: Boolean = false
|
||||
) = StringSetProperty(name, default, commit)
|
||||
|
||||
}
|
||||
|
@@ -1,39 +0,0 @@
|
||||
package com.topjohnwu.magisk.data.repository
|
||||
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.data.network.GithubPageServices
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
|
||||
class MagiskRepository(
|
||||
private val rawSvc: GithubRawServices,
|
||||
private val pageSvc: GithubPageServices
|
||||
) {
|
||||
|
||||
suspend fun fetchUpdate() = try {
|
||||
var info = when (Config.updateChannel) {
|
||||
Config.Value.DEFAULT_CHANNEL, Config.Value.STABLE_CHANNEL -> pageSvc.fetchStableUpdate()
|
||||
Config.Value.BETA_CHANNEL -> pageSvc.fetchBetaUpdate()
|
||||
Config.Value.CANARY_CHANNEL -> rawSvc.fetchCanaryUpdate()
|
||||
Config.Value.CUSTOM_CHANNEL -> rawSvc.fetchCustomUpdate(Config.customChannelUrl)
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
if (info.magisk.versionCode < Info.env.magiskVersionCode &&
|
||||
Config.updateChannel == Config.Value.DEFAULT_CHANNEL) {
|
||||
Config.updateChannel = Config.Value.BETA_CHANNEL
|
||||
info = pageSvc.fetchBetaUpdate()
|
||||
}
|
||||
Info.remote = info
|
||||
info
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
null
|
||||
} catch (e: HttpException) {
|
||||
Timber.e(e)
|
||||
null
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
package com.topjohnwu.magisk.data.repository
|
||||
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Config.Value.BETA_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.CANARY_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.CUSTOM_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.DEFAULT_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Config.Value.STABLE_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.model.*
|
||||
import com.topjohnwu.magisk.data.network.*
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
|
||||
class NetworkService(
|
||||
private val pages: GithubPageServices,
|
||||
private val raw: RawServices,
|
||||
private val jsd: JSDelivrServices,
|
||||
private val api: GithubApiServices
|
||||
) {
|
||||
suspend fun fetchUpdate() = safe {
|
||||
var info = when (Config.updateChannel) {
|
||||
DEFAULT_CHANNEL, STABLE_CHANNEL -> fetchStableUpdate()
|
||||
BETA_CHANNEL -> fetchBetaUpdate()
|
||||
CANARY_CHANNEL -> fetchCanaryUpdate()
|
||||
CUSTOM_CHANNEL -> fetchCustomUpdate(Config.customChannelUrl)
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
if (info.magisk.versionCode < Info.env.magiskVersionCode &&
|
||||
Config.updateChannel == DEFAULT_CHANNEL
|
||||
) {
|
||||
Config.updateChannel = BETA_CHANNEL
|
||||
info = fetchBetaUpdate()
|
||||
}
|
||||
Info.remote = info
|
||||
info
|
||||
}
|
||||
|
||||
// UpdateInfo
|
||||
private suspend fun fetchStableUpdate() = pages.fetchStableUpdate()
|
||||
private suspend fun fetchBetaUpdate() = pages.fetchBetaUpdate()
|
||||
private suspend fun fetchCustomUpdate(url: String) = raw.fetchCustomUpdate(url)
|
||||
private suspend fun fetchCanaryUpdate(): UpdateInfo {
|
||||
val sha = fetchCanaryVersion()
|
||||
val info = jsd.fetchCanaryUpdate(sha)
|
||||
|
||||
fun genCDNUrl(name: String) = "${Const.Url.JS_DELIVR_URL}${MAGISK_FILES}@${sha}/${name}"
|
||||
fun ManagerJson.updateCopy() = copy(link = genCDNUrl(link), note = genCDNUrl(note))
|
||||
fun MagiskJson.updateCopy() = copy(link = genCDNUrl(link), note = genCDNUrl(note))
|
||||
fun StubJson.updateCopy() = copy(link = genCDNUrl(link))
|
||||
fun UninstallerJson.updateCopy() = copy(link = genCDNUrl(link))
|
||||
|
||||
return info.copy(
|
||||
app = info.app.updateCopy(),
|
||||
magisk = info.magisk.updateCopy(),
|
||||
stub = info.stub.updateCopy(),
|
||||
uninstaller = info.uninstaller.updateCopy()
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun <T> safe(factory: () -> T): T? {
|
||||
return try {
|
||||
factory()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> wrap(factory: () -> T): T {
|
||||
return try {
|
||||
factory()
|
||||
} catch (e: HttpException) {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Modules related
|
||||
suspend fun fetchRepoInfo(url: String = Const.Url.OFFICIAL_REPO) = safe {
|
||||
raw.fetchRepoInfo(url)
|
||||
}
|
||||
|
||||
// Fetch files
|
||||
suspend fun fetchSafetynet() = wrap { jsd.fetchSafetynet() }
|
||||
suspend fun fetchBootctl() = wrap { jsd.fetchBootctl() }
|
||||
suspend fun fetchInstaller() = wrap {
|
||||
val sha = fetchMainVersion()
|
||||
jsd.fetchInstaller(sha)
|
||||
}
|
||||
suspend fun fetchFile(url: String) = wrap { raw.fetchFile(url) }
|
||||
suspend fun fetchString(url: String) = wrap { raw.fetchString(url) }
|
||||
|
||||
private suspend fun fetchCanaryVersion() = api.fetchBranch(MAGISK_FILES, "canary").commit.sha
|
||||
private suspend fun fetchMainVersion() = api.fetchBranch(MAGISK_MAIN, "master").commit.sha
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
package com.topjohnwu.magisk.data.repository
|
||||
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
|
||||
class StringRepository(
|
||||
private val api: GithubRawServices
|
||||
) {
|
||||
|
||||
suspend fun getString(url: String) = api.fetchString(url)
|
||||
|
||||
suspend fun getMetadata(repo: Repo) = api.fetchModuleFile(repo.id, "module.prop")
|
||||
|
||||
suspend fun getReadme(repo: Repo) = api.fetchModuleFile(repo.id, "README.md")
|
||||
|
||||
}
|
@@ -200,12 +200,12 @@ fun RecyclerView.setDividers(dividerVertical: Drawable?, dividerHorizontal: Draw
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("app:icon")
|
||||
@BindingAdapter("icon")
|
||||
fun Button.setIconRes(res: Int) {
|
||||
(this as MaterialButton).setIconResource(res)
|
||||
}
|
||||
|
||||
@BindingAdapter("app:icon")
|
||||
@BindingAdapter("icon")
|
||||
fun Button.setIcon(drawable: Drawable) {
|
||||
(this as MaterialButton).icon = drawable
|
||||
}
|
||||
|
@@ -17,8 +17,6 @@ val databaseModule = module {
|
||||
single { StringDao() }
|
||||
single { createRepoDatabase(get()) }
|
||||
single { get<RepoDatabase>().repoDao() }
|
||||
single { get<RepoDatabase>().repoByNameDao() }
|
||||
single { get<RepoDatabase>().repoByUpdatedDao() }
|
||||
single { createSuLogDatabase(get(Protected)).suLogDao() }
|
||||
single { RepoUpdater(get(), get()) }
|
||||
}
|
||||
|
@@ -3,12 +3,14 @@ package com.topjohnwu.magisk.di
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.topjohnwu.magisk.BuildConfig
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.data.network.GithubApiServices
|
||||
import com.topjohnwu.magisk.data.network.GithubPageServices
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.data.network.JSDelivrServices
|
||||
import com.topjohnwu.magisk.data.network.RawServices
|
||||
import com.topjohnwu.magisk.ktx.precomputedText
|
||||
import com.topjohnwu.magisk.net.Networking
|
||||
import com.topjohnwu.magisk.net.NoSSLv3SocketFactory
|
||||
@@ -19,6 +21,7 @@ import okhttp3.Dns
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.dnsoverhttps.DnsOverHttps
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.koin.dsl.module
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||
@@ -29,16 +32,15 @@ import java.net.UnknownHostException
|
||||
val networkingModule = module {
|
||||
single { createOkHttpClient(get()) }
|
||||
single { createRetrofit(get()) }
|
||||
single { createApiService<GithubRawServices>(get(), Const.Url.GITHUB_RAW_URL) }
|
||||
single { createApiService<RawServices>(get(), Const.Url.GITHUB_RAW_URL) }
|
||||
single { createApiService<GithubApiServices>(get(), Const.Url.GITHUB_API_URL) }
|
||||
single { createApiService<GithubPageServices>(get(), Const.Url.GITHUB_PAGE_URL) }
|
||||
single { createApiService<JSDelivrServices>(get(), Const.Url.JS_DELIVR_URL) }
|
||||
single { createMarkwon(get(), get()) }
|
||||
}
|
||||
|
||||
private class DnsResolver(client: OkHttpClient) : Dns {
|
||||
|
||||
private var dohError = false
|
||||
private val poisonedHosts = listOf("raw.githubusercontent.com")
|
||||
private val doh by lazy {
|
||||
DnsOverHttps.Builder().client(client)
|
||||
.url(HttpUrl.get("https://cloudflare-dns.com/dns-query"))
|
||||
@@ -58,16 +60,12 @@ private class DnsResolver(client: OkHttpClient) : Dns {
|
||||
}
|
||||
|
||||
override fun lookup(hostname: String): List<InetAddress> {
|
||||
return if (!dohError && Config.doh && poisonedHosts.contains(hostname)) {
|
||||
if (Config.doh) {
|
||||
try {
|
||||
doh.lookup(hostname)
|
||||
} catch (e: UnknownHostException) {
|
||||
dohError = true
|
||||
Dns.SYSTEM.lookup(hostname)
|
||||
}
|
||||
} else {
|
||||
Dns.SYSTEM.lookup(hostname)
|
||||
return doh.lookup(hostname)
|
||||
} catch (e: UnknownHostException) {}
|
||||
}
|
||||
return Dns.SYSTEM.lookup(hostname)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,10 +73,11 @@ private class DnsResolver(client: OkHttpClient) : Dns {
|
||||
fun createOkHttpClient(context: Context): OkHttpClient {
|
||||
val builder = OkHttpClient.Builder()
|
||||
|
||||
// val httpLoggingInterceptor = HttpLoggingInterceptor().apply {
|
||||
// level = HttpLoggingInterceptor.Level.HEADERS
|
||||
// }
|
||||
// builder.addInterceptor(httpLoggingInterceptor)
|
||||
if (BuildConfig.DEBUG) {
|
||||
builder.addInterceptor(HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BASIC
|
||||
})
|
||||
}
|
||||
|
||||
if (!Networking.init(context)) {
|
||||
Info.hasGMS = false
|
||||
|
@@ -1,13 +1,11 @@
|
||||
package com.topjohnwu.magisk.di
|
||||
|
||||
import com.topjohnwu.magisk.data.repository.LogRepository
|
||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||
import com.topjohnwu.magisk.data.repository.StringRepository
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import org.koin.dsl.module
|
||||
|
||||
|
||||
val repositoryModule = module {
|
||||
single { MagiskRepository(get(), get()) }
|
||||
single { LogRepository(get()) }
|
||||
single { StringRepository(get()) }
|
||||
single { NetworkService(get(), get(), get(), get()) }
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ val viewModelModules = module {
|
||||
viewModel { HideViewModel() }
|
||||
viewModel { HomeViewModel(get()) }
|
||||
viewModel { LogViewModel(get()) }
|
||||
viewModel { ModuleViewModel(get(), get(), get()) }
|
||||
viewModel { ModuleViewModel(get(), get()) }
|
||||
viewModel { SafetynetViewModel() }
|
||||
viewModel { SettingsViewModel(get()) }
|
||||
viewModel { SuperuserViewModel(get(), get()) }
|
||||
|
@@ -1,45 +0,0 @@
|
||||
package com.topjohnwu.magisk.events
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresPermission
|
||||
import androidx.navigation.NavDirections
|
||||
import com.topjohnwu.magisk.MainDirections
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.ActivityExecutor
|
||||
import com.topjohnwu.magisk.arch.BaseUIActivity
|
||||
import com.topjohnwu.magisk.arch.ViewEvent
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
|
||||
class InstallExternalModuleEvent : ViewEvent(), ActivityExecutor {
|
||||
|
||||
@RequiresPermission(allOf = [Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE])
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||
intent.type = "application/zip"
|
||||
try {
|
||||
activity.startActivityForResult(intent, Const.ID.FETCH_ZIP)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): NavDirections? {
|
||||
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
|
||||
val data = data.data
|
||||
if (data != null) {
|
||||
return MainDirections.actionFlashFragment(data, Const.Value.FLASH_ZIP)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,8 +1,11 @@
|
||||
package com.topjohnwu.magisk.events
|
||||
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.MenuItem
|
||||
import android.widget.PopupMenu
|
||||
import androidx.core.content.getSystemService
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.superuser.Shell
|
||||
@@ -13,6 +16,7 @@ object RebootEvent {
|
||||
private fun reboot(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_reboot_normal -> systemReboot()
|
||||
R.id.action_reboot_userspace -> systemReboot("userspace")
|
||||
R.id.action_reboot_bootloader -> systemReboot("bootloader")
|
||||
R.id.action_reboot_download -> systemReboot("download")
|
||||
R.id.action_reboot_edl -> systemReboot("edl")
|
||||
@@ -25,6 +29,9 @@ object RebootEvent {
|
||||
fun inflateMenu(activity: BaseActivity): PopupMenu {
|
||||
val themeWrapper = ContextThemeWrapper(activity, R.style.Foundation_PopupMenu)
|
||||
val menu = PopupMenu(themeWrapper, activity.findViewById(R.id.action_reboot))
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R &&
|
||||
activity.getSystemService<PowerManager>()?.isRebootingUserspaceSupported == true)
|
||||
menu.menu.getItem(R.id.action_reboot_userspace).isVisible = true
|
||||
activity.menuInflater.inflate(R.menu.menu_reboot, menu.menu)
|
||||
menu.setOnMenuItemClickListener(::reboot)
|
||||
return menu
|
||||
|
@@ -35,11 +35,9 @@ class SnackbarEvent private constructor(
|
||||
) = Snackbar.make(view, message, length).apply(builder).show()
|
||||
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
if (activity is BaseUIActivity<*, *>) {
|
||||
snackbar(activity.snackbarView,
|
||||
msg.getText(activity.resources).toString(),
|
||||
length, builder)
|
||||
}
|
||||
snackbar(activity.snackbarView,
|
||||
msg.getText(activity.resources).toString(),
|
||||
length, builder)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,12 +4,16 @@ import android.app.Activity
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.navigation.NavDirections
|
||||
import com.topjohnwu.magisk.MainDirections
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.*
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.base.ActivityResultCallback
|
||||
import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.view.MarkDownWindow
|
||||
import com.topjohnwu.magisk.view.Shortcuts
|
||||
@@ -19,10 +23,10 @@ class ViewActionEvent(val action: BaseActivity.() -> Unit) : ViewEvent(), Activi
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) = action(activity)
|
||||
}
|
||||
|
||||
class OpenChangelogEvent(val item: Repo) : ViewEventWithScope(), ContextExecutor {
|
||||
class OpenReadmeEvent(val item: OnlineModule) : ViewEventWithScope(), ContextExecutor {
|
||||
override fun invoke(context: Context) {
|
||||
scope.launch {
|
||||
MarkDownWindow.show(context, null, item::readme)
|
||||
MarkDownWindow.show(context, null, item::notes)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,9 +59,11 @@ class DieEvent : ViewEvent(), ActivityExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
class ShowUIEvent : ViewEvent(), ActivityExecutor {
|
||||
class ShowUIEvent(private val delegate: View.AccessibilityDelegate?)
|
||||
: ViewEvent(), ActivityExecutor {
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
activity.setContentView()
|
||||
activity.setAccessibilityDelegate(delegate)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,27 +73,16 @@ class RecreateEvent : ViewEvent(), ActivityExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
class RequestFileEvent : ViewEvent(), ActivityExecutor {
|
||||
class MagiskInstallFileEvent(private val callback: ActivityResultCallback)
|
||||
: ViewEvent(), ActivityExecutor {
|
||||
override fun invoke(activity: BaseUIActivity<*, *>) {
|
||||
Intent(Intent.ACTION_GET_CONTENT)
|
||||
.setType("*/*")
|
||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||
.also {
|
||||
try {
|
||||
activity.startActivityForResult(it, REQUEST_CODE)
|
||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val REQUEST_CODE = 10
|
||||
fun resolve(requestCode: Int, resultCode: Int, data: Intent?) = data
|
||||
?.takeIf { resultCode == Activity.RESULT_OK }
|
||||
?.takeIf { requestCode == REQUEST_CODE }
|
||||
?.data
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT).setType("*/*")
|
||||
try {
|
||||
activity.startActivityForResult(intent, Const.ID.SELECT_FILE, callback)
|
||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,3 +101,22 @@ class AddHomeIconEvent : ViewEvent(), ContextExecutor {
|
||||
Shortcuts.addHomeIcon(context)
|
||||
}
|
||||
}
|
||||
|
||||
class SelectModuleEvent : ViewEvent(), FragmentExecutor {
|
||||
override fun invoke(fragment: BaseUIFragment<*, *>) {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT).setType("application/zip")
|
||||
try {
|
||||
fragment.apply {
|
||||
activity.startActivityForResult(intent, Const.ID.FETCH_ZIP) { code, intent ->
|
||||
if (code == Activity.RESULT_OK && intent != null) {
|
||||
intent.data?.also {
|
||||
MainDirections.actionFlashFragment(it, Const.Value.FLASH_ZIP).navigate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Utils.toast(R.string.app_not_found, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.events.dialog
|
||||
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.ktx.res
|
||||
@@ -16,7 +15,7 @@ class ManagerInstallDialog : DialogEvent() {
|
||||
|
||||
override fun build(dialog: MagiskDialog) {
|
||||
with(dialog) {
|
||||
val subject = Subject.Manager(Action.APK.Upgrade)
|
||||
val subject = Subject.Manager()
|
||||
|
||||
applyTitle(R.string.repo_install_title.res(R.string.app_name.res()))
|
||||
applyMessage(R.string.repo_install_msg.res(subject.title))
|
||||
|
@@ -5,10 +5,10 @@ import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
|
||||
class ModuleInstallDialog(private val item: Repo) : DialogEvent() {
|
||||
class ModuleInstallDialog(private val item: OnlineModule) : DialogEvent() {
|
||||
|
||||
override fun build(dialog: MagiskDialog) {
|
||||
with(dialog) {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.events.dialog
|
||||
|
||||
import android.app.ProgressDialog
|
||||
import android.widget.Toast
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
@@ -17,8 +18,7 @@ class UninstallDialog : DialogEvent() {
|
||||
.applyMessage(R.string.uninstall_magisk_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
titleRes = R.string.restore_img
|
||||
preventDismiss = true
|
||||
onClick { restore(dialog) }
|
||||
onClick { restore() }
|
||||
}
|
||||
if (Info.remote.uninstaller.link.isNotEmpty()) {
|
||||
dialog.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||
@@ -28,13 +28,12 @@ class UninstallDialog : DialogEvent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun restore(dialog: MagiskDialog) {
|
||||
dialog.applyTitle(R.string.restore_img)
|
||||
.applyMessage(R.string.restore_img_msg)
|
||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||
title = ""
|
||||
}
|
||||
.cancellable(false)
|
||||
@Suppress("DEPRECATION")
|
||||
private fun restore() {
|
||||
val dialog = ProgressDialog(dialog.context).apply {
|
||||
setMessage(dialog.context.getString(R.string.restore_img_msg))
|
||||
show()
|
||||
}
|
||||
|
||||
Shell.su("restore_imgs").submit { result ->
|
||||
dialog.dismiss()
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.ktx
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@@ -7,7 +8,6 @@ import android.content.ContextWrapper
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ComponentInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.PackageManager.*
|
||||
import android.content.res.Configuration
|
||||
@@ -57,29 +57,31 @@ import java.lang.reflect.Array as JArray
|
||||
|
||||
val packageName: String get() = get<Context>().packageName
|
||||
|
||||
val PackageInfo.processes
|
||||
get() = activities?.processNames.orEmpty() +
|
||||
services?.processNames.orEmpty() +
|
||||
receivers?.processNames.orEmpty() +
|
||||
providers?.processNames.orEmpty()
|
||||
|
||||
val Array<out ComponentInfo>.processNames get() = mapNotNull { it.processName }
|
||||
|
||||
val ApplicationInfo.packageInfo: PackageInfo get() {
|
||||
val ApplicationInfo.processes: List<String> @SuppressLint("InlinedApi") get() {
|
||||
val pm = get<PackageManager>()
|
||||
|
||||
return try {
|
||||
val appProcessName = processName ?: packageName
|
||||
val baseFlag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES
|
||||
val packageInfo = try {
|
||||
val request = GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS
|
||||
pm.getPackageInfo(packageName, request)
|
||||
pm.getPackageInfo(packageName, baseFlag or request)
|
||||
} catch (e: NameNotFoundException) { // EdXposed hooked, issue#3276
|
||||
return listOf(appProcessName)
|
||||
} catch (e: Exception) {
|
||||
// Exceed binder data transfer limit, fetch each component type separately
|
||||
pm.getPackageInfo(packageName, 0).apply {
|
||||
pm.getPackageInfo(packageName, baseFlag).apply {
|
||||
runCatching { activities = pm.getPackageInfo(packageName, GET_ACTIVITIES).activities }
|
||||
runCatching { services = pm.getPackageInfo(packageName, GET_SERVICES).services }
|
||||
runCatching { receivers = pm.getPackageInfo(packageName, GET_RECEIVERS).receivers }
|
||||
runCatching { providers = pm.getPackageInfo(packageName, GET_PROVIDERS).providers }
|
||||
}
|
||||
}
|
||||
fun Array<out ComponentInfo>.processNames() = map { it.processName ?: appProcessName }
|
||||
return with(packageInfo) {
|
||||
activities?.processNames().orEmpty() +
|
||||
services?.processNames().orEmpty() +
|
||||
receivers?.processNames().orEmpty() +
|
||||
providers?.processNames().orEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.rawResource(id: Int) = resources.openRawResource(id)
|
||||
|
@@ -39,14 +39,19 @@ class HideItem(
|
||||
get() = state
|
||||
set(value) = set(value, state, { state = it }, BR.hiddenState) {
|
||||
if (value == true) {
|
||||
processes.filterNot { it.isHidden }
|
||||
processes
|
||||
.filterNot { it.isHidden }
|
||||
.filter { isExpanded || it.process.name == it.process.packageName }
|
||||
} else {
|
||||
processes
|
||||
.filter { it.isHidden }
|
||||
.filter { isExpanded || it.process.name == it.process.packageName }
|
||||
}.forEach { it.toggle() }
|
||||
}
|
||||
|
||||
init {
|
||||
processes.forEach { it.addOnPropertyChangedCallback(BR.hidden) { recalculateChecked() } }
|
||||
addOnPropertyChangedCallback(BR.expanded) { recalculateChecked() }
|
||||
recalculateChecked()
|
||||
}
|
||||
|
||||
@@ -57,10 +62,14 @@ class HideItem(
|
||||
|
||||
private fun recalculateChecked() {
|
||||
itemsChecked = processes.count { it.isHidden }
|
||||
state = when (itemsChecked) {
|
||||
0 -> false
|
||||
processes.size -> true
|
||||
else -> null
|
||||
state = if (isExpanded) {
|
||||
when (itemsChecked) {
|
||||
0 -> false
|
||||
processes.size -> true
|
||||
else -> null
|
||||
}
|
||||
} else {
|
||||
processes.find { it.isHidden && it.process.name == it.process.packageName } != null
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,9 @@
|
||||
package com.topjohnwu.magisk.ui.hide
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Process
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.BR
|
||||
@@ -11,7 +13,6 @@ import com.topjohnwu.magisk.arch.filterableListOf
|
||||
import com.topjohnwu.magisk.arch.itemBindingOf
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.ktx.packageInfo
|
||||
import com.topjohnwu.magisk.ktx.packageName
|
||||
import com.topjohnwu.magisk.ktx.processes
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
@@ -27,14 +28,20 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
|
||||
@get:Bindable
|
||||
var isShowSystem = Config.showSystemApp
|
||||
set(value) = set(value, field, { field = it }, BR.showSystem){
|
||||
set(value) = set(value, field, { field = it }, BR.showSystem) {
|
||||
Config.showSystemApp = it
|
||||
submitQuery()
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var isShowOS = false
|
||||
set(value) = set(value, field, { field = it }, BR.showOS) {
|
||||
submitQuery()
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var query = ""
|
||||
set(value) = set(value, field, { field = it }, BR.query){
|
||||
set(value) = set(value, field, { field = it }, BR.query) {
|
||||
submitQuery()
|
||||
}
|
||||
|
||||
@@ -46,6 +53,7 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
it.bindExtra(BR.viewModel, this)
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun refresh() = viewModelScope.launch {
|
||||
if (!Utils.showSuperUser()) {
|
||||
state = State.LOADING_FAILED
|
||||
@@ -55,9 +63,9 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
val (apps, diff) = withContext(Dispatchers.Default) {
|
||||
val pm = get<PackageManager>()
|
||||
val hides = Shell.su("magiskhide --ls").exec().out.map { HideTarget(it) }
|
||||
val apps = pm.getInstalledApplications(0)
|
||||
val apps = pm.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES)
|
||||
.asSequence()
|
||||
.filter { it.enabled && it.uid >= 10000 && !blacklist.contains(it.packageName) }
|
||||
.filter { it.enabled && !blacklist.contains(it.packageName) }
|
||||
.map { HideAppInfo(it, pm) }
|
||||
.map { createTarget(it, hides) }
|
||||
.filter { it.processes.isNotEmpty() }
|
||||
@@ -75,7 +83,7 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
private fun createTarget(info: HideAppInfo, hideList: List<HideTarget>): HideAppTarget {
|
||||
val pkg = info.packageName
|
||||
val hidden = hideList.filter { it.packageName == pkg }
|
||||
val processNames = info.packageInfo.processes.distinct()
|
||||
val processNames = info.processes.distinct()
|
||||
val processes = processNames.map { name ->
|
||||
HideProcessInfo(name, pkg, hidden.any { name == it.process })
|
||||
}
|
||||
@@ -88,8 +96,14 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
items.filter {
|
||||
fun showHidden() = it.itemsChecked != 0
|
||||
|
||||
fun filterSystem() =
|
||||
isShowSystem || it.info.flags and ApplicationInfo.FLAG_SYSTEM == 0
|
||||
fun filterSystem() = isShowSystem || it.info.flags and ApplicationInfo.FLAG_SYSTEM == 0
|
||||
|
||||
fun isApp(uid: Int) = run {
|
||||
val appId: Int = uid % 100000
|
||||
appId >= Process.FIRST_APPLICATION_UID && appId <= Process.LAST_APPLICATION_UID
|
||||
}
|
||||
|
||||
fun filterOS() = (isShowSystem && isShowOS) || isApp(it.info.uid)
|
||||
|
||||
fun filterQuery(): Boolean {
|
||||
fun inName() = it.info.label.contains(query, true)
|
||||
@@ -98,7 +112,7 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
return inName() || inPackage() || inProcesses()
|
||||
}
|
||||
|
||||
showHidden() || (filterSystem() && filterQuery())
|
||||
showHidden() || (filterSystem() && filterOS() && filterQuery())
|
||||
}
|
||||
state = State.LOADED
|
||||
}
|
||||
@@ -121,4 +135,3 @@ class HideViewModel : BaseViewModel(), Queryable {
|
||||
) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -57,7 +57,9 @@ sealed class IconLink : RvItem() {
|
||||
|
||||
object App : PayPal(), AppDev
|
||||
|
||||
object Main : PayPal(), MainDev
|
||||
object Main : PayPal() {
|
||||
override val name: String get() = "magiskdonate"
|
||||
}
|
||||
}
|
||||
|
||||
object Patreon : IconLink() {
|
||||
|
@@ -12,7 +12,7 @@ import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.download.Subject.Manager
|
||||
import com.topjohnwu.magisk.core.model.MagiskJson
|
||||
import com.topjohnwu.magisk.core.model.ManagerJson
|
||||
import com.topjohnwu.magisk.data.repository.MagiskRepository
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.events.OpenInappLinkEvent
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.events.dialog.EnvFixDialog
|
||||
@@ -32,7 +32,7 @@ enum class MagiskState {
|
||||
}
|
||||
|
||||
class HomeViewModel(
|
||||
private val repoMagisk: MagiskRepository
|
||||
private val svc: NetworkService
|
||||
) : BaseViewModel() {
|
||||
|
||||
@get:Bindable
|
||||
@@ -84,7 +84,7 @@ class HomeViewModel(
|
||||
state = State.LOADING
|
||||
notifyPropertyChanged(BR.showUninstall)
|
||||
notifyPropertyChanged(BR.showSafetyNet)
|
||||
repoMagisk.fetchUpdate()?.apply {
|
||||
svc.fetchUpdate()?.apply {
|
||||
state = State.LOADED
|
||||
stateMagisk = when {
|
||||
!Info.env.isActive -> MagiskState.NOT_INSTALLED
|
||||
|
@@ -1,12 +1,14 @@
|
||||
package com.topjohnwu.magisk.ui.install
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.BaseUIFragment
|
||||
import com.topjohnwu.magisk.core.download.BaseDownloader
|
||||
import com.topjohnwu.magisk.databinding.FragmentInstallMd2Binding
|
||||
import com.topjohnwu.magisk.events.RequestFileEvent
|
||||
import com.topjohnwu.magisk.ktx.coroutineScope
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
@@ -15,11 +17,6 @@ class InstallFragment : BaseUIFragment<InstallViewModel, FragmentInstallMd2Bindi
|
||||
override val layoutRes = R.layout.fragment_install_md2
|
||||
override val viewModel by viewModel<InstallViewModel>()
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
viewModel.data = RequestFileEvent.resolve(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
requireActivity().setTitle(R.string.install)
|
||||
@@ -29,4 +26,20 @@ class InstallFragment : BaseUIFragment<InstallViewModel, FragmentInstallMd2Bindi
|
||||
BaseDownloader.observeProgress(this, viewModel::onProgressUpdate)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
viewModel._method = savedInstanceState?.getInt(KEY_CURRENT_METHOD, -1) ?: -1
|
||||
return super.onCreateView(inflater, container, savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putInt(KEY_CURRENT_METHOD, viewModel.method)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_CURRENT_METHOD = "current_method"
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.ui.install
|
||||
|
||||
import android.app.Activity
|
||||
import android.net.Uri
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -10,17 +11,19 @@ import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.data.repository.StringRepository
|
||||
import com.topjohnwu.magisk.events.RequestFileEvent
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.events.MagiskInstallFileEvent
|
||||
import com.topjohnwu.magisk.events.dialog.SecondSlotWarningDialog
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.get
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class InstallViewModel(
|
||||
stringRepo: StringRepository
|
||||
svc: NetworkService
|
||||
) : BaseViewModel(State.LOADED) {
|
||||
|
||||
val isRooted = Shell.rootAccess()
|
||||
@@ -30,12 +33,18 @@ class InstallViewModel(
|
||||
var step = if (skipOptions) 1 else 0
|
||||
set(value) = set(value, field, { field = it }, BR.step)
|
||||
|
||||
var _method = -1
|
||||
|
||||
@get:Bindable
|
||||
var method = -1
|
||||
set(value) = set(value, field, { field = it }, BR.method) {
|
||||
var method
|
||||
get() = _method
|
||||
set(value) = set(value, _method, { _method = it }, BR.method) {
|
||||
when (it) {
|
||||
R.id.method_patch -> {
|
||||
RequestFileEvent().publish()
|
||||
MagiskInstallFileEvent { code, intent ->
|
||||
if (code == Activity.RESULT_OK)
|
||||
data = intent?.data
|
||||
}.publish()
|
||||
}
|
||||
R.id.method_inactive_slot -> {
|
||||
SecondSlotWarningDialog().publish()
|
||||
@@ -57,7 +66,11 @@ class InstallViewModel(
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
notes = stringRepo.getString(Info.remote.magisk.note)
|
||||
try {
|
||||
notes = svc.fetchString(Info.remote.magisk.note)
|
||||
} catch (e: IOException) {
|
||||
Timber.e(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +81,8 @@ class InstallViewModel(
|
||||
this.progress = progress.times(100).roundToInt()
|
||||
if (this.progress >= 100) {
|
||||
state = State.LOADED
|
||||
} else if (this.progress < -150) {
|
||||
state = State.LOADING_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.ui.module
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
@@ -14,7 +13,6 @@ import com.topjohnwu.magisk.arch.ReselectionTarget
|
||||
import com.topjohnwu.magisk.arch.ViewEvent
|
||||
import com.topjohnwu.magisk.core.download.BaseDownloader
|
||||
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
|
||||
import com.topjohnwu.magisk.events.InstallExternalModuleEvent
|
||||
import com.topjohnwu.magisk.ktx.hideKeyboard
|
||||
import com.topjohnwu.magisk.ui.MainActivity
|
||||
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
|
||||
@@ -40,13 +38,6 @@ class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
InstallExternalModuleEvent.onActivityResult(requestCode, resultCode, data)?.also {
|
||||
it.navigate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setHasOptionsMenu(true)
|
||||
|
@@ -3,8 +3,8 @@ package com.topjohnwu.magisk.ui.module
|
||||
import androidx.databinding.Bindable
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.core.model.module.Module
|
||||
import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||
import com.topjohnwu.magisk.core.model.module.OnlineModule
|
||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||
import com.topjohnwu.magisk.databinding.ObservableItem
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
@@ -39,7 +39,7 @@ class SectionTitle(
|
||||
override fun contentSameAs(other: SectionTitle): Boolean = this === other
|
||||
}
|
||||
|
||||
sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
|
||||
sealed class RepoItem(val item: OnlineModule) : ObservableItem<RepoItem>() {
|
||||
override val layoutRes: Int = R.layout.item_repo_md2
|
||||
|
||||
@get:Bindable
|
||||
@@ -51,21 +51,21 @@ sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
|
||||
override fun contentSameAs(other: RepoItem): Boolean = item == other.item
|
||||
override fun itemSameAs(other: RepoItem): Boolean = item.id == other.item.id
|
||||
|
||||
class Update(item: Repo) : RepoItem(item) {
|
||||
class Update(item: OnlineModule) : RepoItem(item) {
|
||||
override val isUpdate get() = true
|
||||
}
|
||||
|
||||
class Remote(item: Repo) : RepoItem(item) {
|
||||
class Remote(item: OnlineModule) : RepoItem(item) {
|
||||
override val isUpdate get() = false
|
||||
}
|
||||
}
|
||||
|
||||
class ModuleItem(val item: Module) : ObservableItem<ModuleItem>() {
|
||||
class ModuleItem(val item: LocalModule) : ObservableItem<ModuleItem>() {
|
||||
|
||||
override val layoutRes = R.layout.item_module_md2
|
||||
|
||||
@get:Bindable
|
||||
var repo: Repo? = null
|
||||
var repo: OnlineModule? = null
|
||||
set(value) = set(value, field, { field = it }, BR.repo)
|
||||
|
||||
@get:Bindable
|
||||
|
@@ -9,13 +9,12 @@ import com.topjohnwu.magisk.arch.*
|
||||
import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.model.module.Module
|
||||
import com.topjohnwu.magisk.core.model.module.LocalModule
|
||||
import com.topjohnwu.magisk.core.tasks.RepoUpdater
|
||||
import com.topjohnwu.magisk.data.database.RepoByNameDao
|
||||
import com.topjohnwu.magisk.data.database.RepoByUpdatedDao
|
||||
import com.topjohnwu.magisk.data.database.RepoDao
|
||||
import com.topjohnwu.magisk.databinding.RvItem
|
||||
import com.topjohnwu.magisk.events.InstallExternalModuleEvent
|
||||
import com.topjohnwu.magisk.events.OpenChangelogEvent
|
||||
import com.topjohnwu.magisk.events.OpenReadmeEvent
|
||||
import com.topjohnwu.magisk.events.SelectModuleEvent
|
||||
import com.topjohnwu.magisk.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.events.dialog.ModuleInstallDialog
|
||||
import com.topjohnwu.magisk.ktx.addOnListChangedCallback
|
||||
@@ -44,8 +43,7 @@ import kotlin.math.roundToInt
|
||||
* */
|
||||
|
||||
class ModuleViewModel(
|
||||
private val repoName: RepoByNameDao,
|
||||
private val repoUpdated: RepoByUpdatedDao,
|
||||
private val repoDB: RepoDao,
|
||||
private val repoUpdater: RepoUpdater
|
||||
) : BaseViewModel(), Queryable {
|
||||
|
||||
@@ -117,12 +115,6 @@ class ModuleViewModel(
|
||||
// ---
|
||||
|
||||
private var refetch = false
|
||||
private val dao
|
||||
get() = when (Config.repoOrder) {
|
||||
Config.Value.ORDER_DATE -> repoUpdated
|
||||
Config.Value.ORDER_NAME -> repoName
|
||||
else -> throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
@@ -186,7 +178,7 @@ class ModuleViewModel(
|
||||
}
|
||||
|
||||
private suspend fun loadInstalled() {
|
||||
val installed = Module.installed().map { ModuleItem(it) }
|
||||
val installed = LocalModule.installed().map { ModuleItem(it) }
|
||||
val diff = withContext(Dispatchers.Default) {
|
||||
itemsInstalled.calculateDiff(installed)
|
||||
}
|
||||
@@ -197,11 +189,11 @@ class ModuleViewModel(
|
||||
val (updates, diff) = withContext(Dispatchers.IO) {
|
||||
itemsInstalled.forEach {
|
||||
launch {
|
||||
it.repo = dao.getRepoById(it.item.id)
|
||||
it.repo = repoDB.getModule(it.item.id)
|
||||
}
|
||||
}
|
||||
val updates = itemsInstalled
|
||||
.mapNotNull { dao.getUpdatableRepoById(it.item.id, it.item.versionCode) }
|
||||
.mapNotNull { repoDB.getUpdatableModule(it.item.id, it.item.versionCode) }
|
||||
.map { RepoItem.Update(it) }
|
||||
val diff = itemsUpdatable.calculateDiff(updates)
|
||||
return@withContext updates to diff
|
||||
@@ -219,7 +211,7 @@ class ModuleViewModel(
|
||||
|
||||
remoteJob = viewModelScope.launch {
|
||||
suspend fun loadRemoteDB(offset: Int) = withContext(Dispatchers.IO) {
|
||||
dao.getRepos(offset).map { RepoItem.Remote(it) }
|
||||
repoDB.getModules(offset).map { RepoItem.Remote(it) }
|
||||
}
|
||||
|
||||
isRemoteLoading = true
|
||||
@@ -253,7 +245,7 @@ class ModuleViewModel(
|
||||
listOf()
|
||||
} else {
|
||||
withContext(Dispatchers.IO) {
|
||||
dao.searchRepos(query, offset).map { RepoItem.Remote(it) }
|
||||
repoDB.searchModules(query, offset).map { RepoItem.Remote(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,18 +303,18 @@ class ModuleViewModel(
|
||||
}
|
||||
|
||||
fun installPressed() = withExternalRW {
|
||||
InstallExternalModuleEvent().publish()
|
||||
SelectModuleEvent().publish()
|
||||
}
|
||||
|
||||
fun infoPressed(item: RepoItem) =
|
||||
if (isConnected.get()) OpenChangelogEvent(item.item).publish()
|
||||
if (isConnected.get()) OpenReadmeEvent(item.item).publish()
|
||||
else SnackbarEvent(R.string.no_connection).publish()
|
||||
|
||||
|
||||
fun infoPressed(item: ModuleItem) {
|
||||
item.repo?.also {
|
||||
if (isConnected.get())
|
||||
OpenChangelogEvent(it).publish()
|
||||
OpenReadmeEvent(it).publish()
|
||||
else
|
||||
SnackbarEvent(R.string.no_connection).publish()
|
||||
} ?: return
|
||||
|
@@ -5,7 +5,7 @@ import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.arch.ContextExecutor
|
||||
import com.topjohnwu.magisk.arch.ViewEventWithScope
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.data.network.GithubRawServices
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.DynamicClassLoader
|
||||
import com.topjohnwu.magisk.ktx.writeTo
|
||||
import com.topjohnwu.magisk.view.MagiskDialog
|
||||
@@ -28,7 +28,7 @@ class CheckSafetyNetEvent(
|
||||
private val callback: (SafetyNetResult) -> Unit = {}
|
||||
) : ViewEventWithScope(), ContextExecutor, KoinComponent, SafetyNetHelper.Callback {
|
||||
|
||||
private val svc by inject<GithubRawServices>()
|
||||
private val svc by inject<NetworkService>()
|
||||
|
||||
private lateinit var apk: File
|
||||
private lateinit var dex: File
|
||||
|
@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.Config
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.UpdateCheckService
|
||||
import com.topjohnwu.magisk.core.tasks.PatchAPK
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
|
||||
import com.topjohnwu.magisk.core.utils.availableLocales
|
||||
@@ -90,7 +90,7 @@ object Hide : BaseSettingsItem.Input() {
|
||||
set(value) = set(value, field, { field = it }, BR.result, BR.error)
|
||||
|
||||
val maxLength
|
||||
get() = PatchAPK.MAX_LABEL_LENGTH
|
||||
get() = HideAPK.MAX_LABEL_LENGTH
|
||||
|
||||
@get:Bindable
|
||||
val isError
|
||||
@@ -99,11 +99,17 @@ object Hide : BaseSettingsItem.Input() {
|
||||
override fun getView(context: Context) = DialogSettingsAppNameBinding
|
||||
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
|
||||
|
||||
override fun refresh() {
|
||||
isEnabled = Info.remote.stub.versionCode > 0
|
||||
}
|
||||
}
|
||||
|
||||
object Restore : BaseSettingsItem.Blank() {
|
||||
override val title = R.string.settings_restore_manager_title.asTransitive()
|
||||
override val description = R.string.settings_restore_manager_summary.asTransitive()
|
||||
override fun refresh() {
|
||||
isEnabled = Info.remote.app.versionCode > 0
|
||||
}
|
||||
}
|
||||
|
||||
object AddShortcut : BaseSettingsItem.Blank() {
|
||||
@@ -189,6 +195,13 @@ object SystemlessHosts : BaseSettingsItem.Blank() {
|
||||
override val description = R.string.settings_hosts_summary.asTransitive()
|
||||
}
|
||||
|
||||
object Tapjack : BaseSettingsItem.Toggle() {
|
||||
override val title = R.string.settings_su_tapjack_title.asTransitive()
|
||||
override var description = R.string.settings_su_tapjack_summary.asTransitive()
|
||||
override var value = Config.suTapjack
|
||||
set(value) = setV(value, field, { field = it }) { Config.suTapjack = it }
|
||||
}
|
||||
|
||||
object Biometrics : BaseSettingsItem.Toggle() {
|
||||
override val title = R.string.settings_su_biometric_title.asTransitive()
|
||||
override var value = Config.suBiometric
|
||||
@@ -288,9 +301,9 @@ object AutomaticResponse : BaseSettingsItem.Selector() {
|
||||
override val entryRes = R.array.auto_response
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value = Config.suAutoReponse
|
||||
override var value = Config.suAutoResponse
|
||||
set(value) = setV(value, field, { field = it }) {
|
||||
Config.suAutoReponse = entryValues[it].toInt()
|
||||
Config.suAutoResponse = entryValues[it].toInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,11 +15,8 @@ import com.topjohnwu.magisk.arch.diffListOf
|
||||
import com.topjohnwu.magisk.arch.itemBindingOf
|
||||
import com.topjohnwu.magisk.core.Const
|
||||
import com.topjohnwu.magisk.core.Info
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.isRunningAsStub
|
||||
import com.topjohnwu.magisk.core.tasks.PatchAPK
|
||||
import com.topjohnwu.magisk.core.tasks.HideAPK
|
||||
import com.topjohnwu.magisk.data.database.RepoDao
|
||||
import com.topjohnwu.magisk.events.AddHomeIconEvent
|
||||
import com.topjohnwu.magisk.events.RecreateEvent
|
||||
@@ -82,7 +79,7 @@ class SettingsViewModel(
|
||||
if (Utils.showSuperUser()) {
|
||||
list.addAll(listOf(
|
||||
Superuser,
|
||||
Biometrics, AccessMode, MultiuserMode, MountNamespaceMode,
|
||||
Tapjack, Biometrics, AccessMode, MultiuserMode, MountNamespaceMode,
|
||||
AutomaticResponse, RequestTimeout, SUNotification
|
||||
))
|
||||
if (Build.VERSION.SDK_INT < 23) {
|
||||
@@ -104,7 +101,7 @@ class SettingsViewModel(
|
||||
is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().publish()
|
||||
is ClearRepoCache -> clearRepoCache()
|
||||
is SystemlessHosts -> createHosts()
|
||||
is Restore -> restoreManager()
|
||||
is Restore -> HideAPK.restore(view.context)
|
||||
is AddShortcut -> AddHomeIconEvent().publish()
|
||||
else -> callback()
|
||||
}
|
||||
@@ -112,7 +109,7 @@ class SettingsViewModel(
|
||||
override fun onItemChanged(view: View, item: BaseSettingsItem) = when (item) {
|
||||
is Language -> RecreateEvent().publish()
|
||||
is UpdateChannel -> openUrlIfNecessary(view)
|
||||
is Hide -> PatchAPK.hideManager(view.context, item.value)
|
||||
is Hide -> HideAPK.hide(view.context, item.value)
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
@@ -142,9 +139,4 @@ class SettingsViewModel(
|
||||
Utils.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun restoreManager() {
|
||||
DownloadService.start(get(), Subject.Manager(Action.APK.Restore))
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,8 +28,8 @@ open class SuRequestActivity : BaseUIActivity<SuRequestViewModel, ActivityReques
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
supportRequestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
lockOrientation()
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
|
||||
WindowManager.LayoutParams.FLAG_SECURE)
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
window.addFlags(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
fun showRequest() {
|
||||
|
@@ -1,11 +1,20 @@
|
||||
package com.topjohnwu.magisk.ui.surequest
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.os.CountDownTimer
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
import android.view.accessibility.AccessibilityNodeInfo
|
||||
import android.view.accessibility.AccessibilityNodeProvider
|
||||
import android.widget.Toast
|
||||
import androidx.databinding.Bindable
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.topjohnwu.magisk.BR
|
||||
@@ -22,6 +31,7 @@ import com.topjohnwu.magisk.events.DieEvent
|
||||
import com.topjohnwu.magisk.events.ShowUIEvent
|
||||
import com.topjohnwu.magisk.events.dialog.BiometricEvent
|
||||
import com.topjohnwu.magisk.ui.superuser.SpinnerRvItem
|
||||
import com.topjohnwu.magisk.utils.Utils
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import kotlinx.coroutines.launch
|
||||
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
|
||||
@@ -51,6 +61,19 @@ class SuRequestViewModel(
|
||||
var grantEnabled = false
|
||||
set(value) = set(value, field, { field = it }, BR.grantEnabled)
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
val grantTouchListener = View.OnTouchListener { _: View, event: MotionEvent ->
|
||||
// Filter obscured touches by consuming them.
|
||||
if (event.flags and MotionEvent.FLAG_WINDOW_IS_OBSCURED != 0
|
||||
|| event.flags and MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED != 0) {
|
||||
if (event.action == MotionEvent.ACTION_UP) {
|
||||
Utils.toast(R.string.touch_filtered_warning, Toast.LENGTH_SHORT)
|
||||
}
|
||||
return@OnTouchListener Config.suTapjack
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) }
|
||||
val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply {
|
||||
itemBinding = ItemBinding.of { binding, _, item ->
|
||||
@@ -104,7 +127,7 @@ class SuRequestViewModel(
|
||||
timer = SuTimer(millis, 1000).apply { start() }
|
||||
|
||||
// Actually show the UI
|
||||
ShowUIEvent().publish()
|
||||
ShowUIEvent(if (Config.suTapjack) EmptyAccessibilityDelegate else null).publish()
|
||||
}
|
||||
|
||||
private fun respond(action: Int) {
|
||||
@@ -141,4 +164,18 @@ class SuRequestViewModel(
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Invisible for accessibility services
|
||||
object EmptyAccessibilityDelegate : View.AccessibilityDelegate() {
|
||||
override fun sendAccessibilityEvent(host: View?, eventType: Int) {}
|
||||
override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?) = true
|
||||
override fun sendAccessibilityEventUnchecked(host: View?, event: AccessibilityEvent?) {}
|
||||
override fun dispatchPopulateAccessibilityEvent(host: View?, event: AccessibilityEvent?) = true
|
||||
override fun onPopulateAccessibilityEvent(host: View?, event: AccessibilityEvent?) {}
|
||||
override fun onInitializeAccessibilityEvent(host: View?, event: AccessibilityEvent?) {}
|
||||
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {}
|
||||
override fun addExtraDataToAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo, extraDataKey: String, arguments: Bundle?) {}
|
||||
override fun onRequestSendAccessibilityEvent(host: ViewGroup?, child: View?, event: AccessibilityEvent?): Boolean = false
|
||||
override fun getAccessibilityNodeProvider(host: View?): AccessibilityNodeProvider? = null
|
||||
}
|
||||
}
|
||||
|
@@ -55,15 +55,15 @@ class EndlessRecyclerScrollListener(
|
||||
val visibleItemPosition = if (direction == Direction.BOTTOM) {
|
||||
when (layoutManager) {
|
||||
is StaggeredGridLayoutManager ->
|
||||
layoutManager.findLastVisibleItemPositions(null).max() ?: 0
|
||||
layoutManager.findLastVisibleItemPositions(null).maxOrNull() ?: 0
|
||||
is GridLayoutManager -> layoutManager.findLastVisibleItemPosition()
|
||||
is LinearLayoutManager -> layoutManager.findLastVisibleItemPosition()
|
||||
else -> throw IllegalArgumentException("Only LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager are supported")
|
||||
}
|
||||
} else {
|
||||
when (layoutManager) {
|
||||
is StaggeredGridLayoutManager -> layoutManager.findFirstVisibleItemPositions(null).min()
|
||||
?: 0
|
||||
is StaggeredGridLayoutManager ->
|
||||
layoutManager.findFirstVisibleItemPositions(null).minOrNull() ?: 0
|
||||
is GridLayoutManager -> layoutManager.findFirstVisibleItemPosition()
|
||||
is LinearLayoutManager -> layoutManager.findFirstVisibleItemPosition()
|
||||
else -> throw IllegalArgumentException("Only LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager are supported")
|
||||
|
@@ -228,7 +228,7 @@ class MagiskDialog(
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
val items = list.mapIndexed { i, it -> DialogItem(it, i) }
|
||||
val items = list.mapIndexed { i, cs -> DialogItem(cs, i) }
|
||||
val binding = itemBindingOf<DialogItem> { it.bindExtra(BR.listener, actualListener) }
|
||||
.let { ItemBinding.of(it) }
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.TextView
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.repository.StringRepository
|
||||
import com.topjohnwu.magisk.data.repository.NetworkService
|
||||
import com.topjohnwu.magisk.ktx.coroutineScope
|
||||
import io.noties.markwon.Markwon
|
||||
import kotlinx.coroutines.CancellationException
|
||||
@@ -18,12 +18,12 @@ import kotlin.coroutines.coroutineContext
|
||||
|
||||
object MarkDownWindow : KoinComponent {
|
||||
|
||||
private val repo: StringRepository by inject()
|
||||
private val svc: NetworkService by inject()
|
||||
private val markwon: Markwon by inject()
|
||||
|
||||
suspend fun show(activity: Context, title: String?, url: String) {
|
||||
show(activity, title) {
|
||||
repo.getString(url)
|
||||
svc.fetchString(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,6 @@ import com.topjohnwu.magisk.core.Const.ID.PROGRESS_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.core.Const.ID.UPDATE_NOTIFICATION_CHANNEL
|
||||
import com.topjohnwu.magisk.core.SplashActivity
|
||||
import com.topjohnwu.magisk.core.cmp
|
||||
import com.topjohnwu.magisk.core.download.Action
|
||||
import com.topjohnwu.magisk.core.download.DownloadService
|
||||
import com.topjohnwu.magisk.core.download.Subject
|
||||
import com.topjohnwu.magisk.core.intent
|
||||
@@ -46,7 +45,6 @@ object Notifications {
|
||||
setChannelId(UPDATE_NOTIFICATION_CHANNEL)
|
||||
} else {
|
||||
setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
setVibrate(longArrayOf(0, 100, 100, 100))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +68,7 @@ object Notifications {
|
||||
}
|
||||
|
||||
fun managerUpdate(context: Context) {
|
||||
val intent = DownloadService.pendingIntent(context, Subject.Manager(Action.APK.Upgrade))
|
||||
val intent = DownloadService.pendingIntent(context, Subject.Manager())
|
||||
|
||||
val builder = updateBuilder(context)
|
||||
.setContentTitle(context.getString(R.string.manager_update_title))
|
||||
|
@@ -138,6 +138,7 @@
|
||||
<Button
|
||||
android:id="@+id/grant_btn"
|
||||
style="@style/WidgetFoundation.Button.Text"
|
||||
onTouch="@{viewModel.grantTouchListener}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
@@ -306,6 +306,23 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
goneUnless="@{viewModel.loadFailed}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/download_file_error"
|
||||
android:textAppearance="@style/AppearanceFoundation.Title" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
@@ -47,7 +47,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/hide_filter_title_filter">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/hide_filter_chip"
|
||||
android:id="@+id/hide_filter_system_chip"
|
||||
style="@style/Widget.MaterialComponents.Chip.Filter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -60,6 +60,20 @@
|
||||
app:chipBackgroundColor="?colorSurfaceVariant"
|
||||
tools:checked="true" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/hide_filter_os_chip"
|
||||
style="@style/Widget.MaterialComponents.Chip.Filter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="@={viewModel.showOS}"
|
||||
android:nextFocusRight="@id/hide_filter_chip_data"
|
||||
android:nextFocusDown="@id/hide_filter_search_field"
|
||||
android:text="@string/show_os_app"
|
||||
android:textAppearance="@style/AppearanceFoundation.Caption"
|
||||
app:checkedIcon="@drawable/ic_check_md2"
|
||||
app:chipBackgroundColor="?colorSurfaceVariant"
|
||||
tools:checked="true" />
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/hide_filter_chip_data"
|
||||
style="@style/Widget.MaterialComponents.Chip.Entry"
|
||||
@@ -136,7 +150,7 @@
|
||||
android:id="@+id/hide_filter_done"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:nextFocusLeft="@id/hide_filter_chip"
|
||||
android:nextFocusLeft="@id/hide_filter_system_chip"
|
||||
app:backgroundTint="?colorPrimary"
|
||||
app:elevation="0dp"
|
||||
app:fabSize="mini"
|
||||
|
@@ -5,6 +5,15 @@
|
||||
android:id="@+id/action_reboot_normal"
|
||||
android:title="@string/reboot" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reboot_userspace"
|
||||
android:title="@string/reboot_userspace"
|
||||
android:visible="false" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reboot_recovery"
|
||||
android:title="@string/reboot_recovery" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reboot_bootloader"
|
||||
android:title="@string/reboot_bootloader" />
|
||||
@@ -17,8 +26,4 @@
|
||||
android:id="@+id/action_reboot_edl"
|
||||
android:title="@string/reboot_edl" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_reboot_recovery"
|
||||
android:title="@string/reboot_recovery" />
|
||||
|
||||
</menu>
|
@@ -1,6 +1,5 @@
|
||||
## v8.0.0
|
||||
## v8.0.3
|
||||
|
||||
- 100% full app rewrite! Will highlight functional changes below.
|
||||
- Add detailed device info in home screen to assist user installation
|
||||
- Support Magisk v21.0 communication protocol
|
||||
- Support patching modern Samsung `AP.tar`
|
||||
- Switch to the new Magisk Module Repo setup in preparation to allow 3rd party repos
|
||||
- Add tapjacking protection on Superuser request dialog
|
||||
- Stability changes and bug fixes
|
||||
|
@@ -90,7 +90,7 @@ EOF
|
||||
}
|
||||
|
||||
adb_pm_install() {
|
||||
local tmp=/data/local/tmp/patched.apk
|
||||
local tmp=/data/local/tmp/temp.apk
|
||||
cp -f "$1" $tmp
|
||||
chmod 644 $tmp
|
||||
su 2000 -c pm install $tmp || pm install $tmp
|
||||
|
@@ -31,6 +31,7 @@
|
||||
<string name="invalid_update_channel">Хібны канал абнаўлення</string>
|
||||
<string name="uninstall_magisk_title">Выдаліць Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Усе модулі будуць адключаныя/выдаленыя!\nRoot будзе выдалены!\nВашыя даныя будуць зашыфраваныя!</string>
|
||||
<string name="home_check_safetynet">Праверка SafetyNet</string>
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Прымусова захаваць шыфраванне</string>
|
||||
<string name="keep_dm_verity">Захаваць AVB 2.0/dm-verity</string>
|
||||
@@ -97,7 +98,7 @@
|
||||
<string name="hide_scroll_up">Уверх</string>
|
||||
<string name="hide_filters">Фільтры</string>
|
||||
<string name="hide_search">Пошук</string>
|
||||
<!--Module Fragment-->
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(Няма інфармацыі)</string>
|
||||
<string name="reboot_recovery">Перазапуск у Recovery</string>
|
||||
<string name="reboot_bootloader">Перазапуск у Bootloader</string>
|
||||
@@ -111,8 +112,8 @@
|
||||
<string name="module_action_install_external">Усталяваць са сховішча</string>
|
||||
<string name="update_available">Даступныя абнаўленні</string>
|
||||
<string name="module_installed">Усталяваныя</string>
|
||||
<string name="module_section_online">Анлайн</string>
|
||||
<string name="sorting_order">Парадак сартавання</string>
|
||||
<string name="external_rw_permission_denied">Дайце доступ да сховішча, каб уключыць гэтую функцыю</string>
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Рэжым афармлення</string>
|
||||
<string name="settings_dark_mode_message">Абярыце рэжым, які вам больш даспадобы!</string>
|
||||
@@ -163,6 +164,9 @@
|
||||
<string name="settings_su_biometric_summary">Выкарыстанне біяметрычнай аўтэнтыфікацыі для запытаў правоў суперкарыстальніка</string>
|
||||
<string name="no_biometric">Не падтрымліваецца прыладай альбо не ўключана ў наладах</string>
|
||||
<string name="settings_customization">Персаналізацыя</string>
|
||||
<string name="setting_add_shortcut_summary">Дадаць на хатні экран прыгожы цэтлік на той выпадак, калі пасля хавання праграмы будзе цяжка разглядзець значок і назву</string>
|
||||
<string name="settings_doh_title">DNS паверх HTTPS</string>
|
||||
<string name="settings_doh_description">Абыходны шлях для DNS у некаторых краінах</string>
|
||||
<string name="multiuser_mode">Шматкарыстальніцкі рэжым</string>
|
||||
<string name="settings_owner_only">Толькі ўладальнік</string>
|
||||
<string name="settings_owner_manage">Кіраванне ўладальнікам</string>
|
||||
@@ -215,4 +219,8 @@
|
||||
<string name="authenticate">Аўтэнтыфікацыя</string>
|
||||
<string name="unsupport_magisk_title">Непадтрымліваемая версія Magisk</string>
|
||||
<string name="unsupport_magisk_msg">Гэтая версія Magisk Manager не падтрымлівае Magisk версіі ніжэй за %1$s.\n\nПраграма будзе працаваць так, як быццам Magisk не ўсталяваны. Як мага хутчэй абнавіце Magisk.</string>
|
||||
<string name="external_rw_permission_denied">Дайце доступ да сховішча, каб уключыць гэтую функцыю</string>
|
||||
<string name="add_shortcut_title">Дадаць цэтлік на хатні экран</string>
|
||||
<string name="add_shortcut_msg">Пасля хавання Magisk Manager яго значок і назву можа быць цяжка разглядзець. Хочаце дадаць цэтлік на хатні экран?</string>
|
||||
<string name="app_not_found">Не знойдзена праграм для апрацоўкі гэтага дзеяння</string>
|
||||
</resources>
|
||||
|
@@ -175,7 +175,9 @@
|
||||
<string name="no_biometric">El dispositiu no suporta o no té establerta configuració biomètrica</string>
|
||||
<string name="settings_customization">Personalització</string>
|
||||
<string name="setting_add_shortcut_summary">Afegeix una bonica drecera a la pantalla d\'inici en cas que el nom i la icona siguin difícils de reconèixer després d\'amagar l\'aplicació.</string>
|
||||
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solució per enverinament de DNS en algunes nacions</string>
|
||||
|
||||
<string name="multiuser_mode">Mode Multiusuari</string>
|
||||
<string name="settings_owner_only">Només Administrador del Dispositiu</string>
|
||||
<string name="settings_owner_manage">Administrador del Dispositiu</string>
|
||||
@@ -234,5 +236,6 @@
|
||||
<string name="external_rw_permission_denied">Ha de donar permís d\'emmagatzematge per activar aquesta funcionalitat</string>
|
||||
<string name="add_shortcut_title">Afegeix una drecera a la pantalla d\'inici</string>
|
||||
<string name="add_shortcut_msg">Després d\'amagar Magisk Manager, el seu nom i icona poden ser difícils de reconèixer. Vols afegir una bonica drecera a la teva pantalla d\'inici?</string>
|
||||
<string name="app_not_found">No s\'ha trobat una aplicació per emprar aquesta acció</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -20,7 +20,7 @@
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Verstecken</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Packet</string>
|
||||
<string name="home_package">Paket</string>
|
||||
|
||||
<string name="home_notice_content">Benutzen Sie nur den quelloffenen Magisk Manager. Magisk von unbekannten Quellen kann zu schädlichen Aktionen führen.</string>
|
||||
<string name="home_support_title">Unterstützen Sie uns</string>
|
||||
@@ -55,9 +55,9 @@
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser-Anfrage</string>
|
||||
<string name="deny">Verweigern</string>
|
||||
<string name="prompt">Sofort</string>
|
||||
<string name="prompt">Fragen</string>
|
||||
<string name="grant">Gewähren</string>
|
||||
<string name="su_warning">Gewähren Sie vollen Zugriff auf Ihr Gerät. Den Zugriff verweigern, wenn Sie sich nicht sicher sind!</string>
|
||||
<string name="su_warning">Sie gewähren vollen Zugriff auf Ihr Gerät. Verweigern Sie den Zugriff, wenn Sie sich nicht sicher sind!</string>
|
||||
<string name="forever">Für immer</string>
|
||||
<string name="once">Einmalig</string>
|
||||
<string name="tenmin">10 Minuten</string>
|
||||
@@ -179,7 +179,7 @@
|
||||
<string name="settings_user_independent">Benutzerunabhängig</string>
|
||||
<string name="owner_only_summary">Nur der Besitzer hat Root-Zugriff</string>
|
||||
<string name="owner_manage_summary">Nur der Besitzer verwaltet den Root-Zugriff und erhält Zugriffsanfragen</string>
|
||||
<string name="user_indepenent_summary">Jeder Nutzer hat seine eingenen Root-Regeln</string>
|
||||
<string name="user_indepenent_summary">Jeder Nutzer hat seine eigenen Root-Regeln</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mount Namespace Modus</string>
|
||||
<string name="settings_ns_global">Globaler Namespace</string>
|
||||
@@ -193,7 +193,7 @@
|
||||
<string name="update_channel">Magisk Updates</string>
|
||||
<string name="progress_channel">Fortschrittsmitteilungen</string>
|
||||
<string name="download_complete">Download abgeschlossen</string>
|
||||
<string name="download_file_error">Fehler beim Datei herunterladen</string>
|
||||
<string name="download_file_error">Fehler beim herunterladen der Datei</string>
|
||||
<string name="download_open_parent">Im übergeordneten Ordner anzeigen</string>
|
||||
<string name="download_open_self">Datei anzeigen</string>
|
||||
<string name="magisk_update_title">Magisk Update verfügbar!</string>
|
||||
@@ -222,7 +222,7 @@
|
||||
<string name="proprietary_title">Proprietären Code herunterladen</string>
|
||||
<string name="proprietary_notice">Magisk Manager ist FOSS und enthält nicht den proprietären SafetyNet-API-Code von Google.\n\nWollen Sie Magisk Manager erlauben, eine Erweiterung (enthält GoogleApiClient) für SafetyNet-Prüfungen herunterzuladen?</string>
|
||||
<string name="setup_fail">Setup fehlgeschlagen</string>
|
||||
<string name="env_fix_title">Erfordert zusätzliche Einrichtung</string>
|
||||
<string name="env_fix_title">Zusätzliche Einrichtung erforderlich</string>
|
||||
<string name="env_fix_msg">Ihr Gerät muss zusätzlich eingerichtet werden, damit Magisk ordnungsgemäß funktioniert. Es wird das Magisk Setup-Zip herunterladen, möchten Sie jetzt fortfahren?</string>
|
||||
<string name="setup_msg">Laufzeitumgebung einrichten…</string>
|
||||
<string name="authenticate">Authentifizieren</string>
|
||||
|
@@ -175,6 +175,8 @@
|
||||
<string name="no_biometric">Dispositivo no compatible o las configuraciones biométricas no están habilitadas</string>
|
||||
<string name="settings_customization">Personalización</string>
|
||||
<string name="setting_add_shortcut_summary">Añade un bonito atajo en la pantalla de inicio en caso de que el nombre y el icono sean difíciles de reconocer después de ocultar la aplicación</string>
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Evitar envenenamiento de DNS en algunos países</string>
|
||||
|
||||
<string name="multiuser_mode">Modo multiusuario</string>
|
||||
<string name="settings_owner_only">Sólo administrador del dispositivo</string>
|
||||
@@ -234,5 +236,6 @@
|
||||
<string name="external_rw_permission_denied">Conceder permiso de almacenamiento para habilitar esta funcionalidad</string>
|
||||
<string name="add_shortcut_title">Añadir un atajo a la pantalla de inicio</string>
|
||||
<string name="add_shortcut_msg">Después de esconder el Magisk Manager, su nombre e icono podría ser difícil de reconocer. ¿Quieres añadir un bonito atajo a la pantalla de inicio?</string>
|
||||
<string name="app_not_found">No se ha encontrado ninguna app para manejar esta acción</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,55 +1,48 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<!--Sections-->
|
||||
<string name="modules">Moodulid</string>
|
||||
<string name="superuser">Superkasutaja</string>
|
||||
<string name="logs">Logi</string>
|
||||
<string name="logs">Logid</string>
|
||||
<string name="settings">Seaded</string>
|
||||
<string name="refresh">Värskenda kohalikud andmed</string>
|
||||
<string name="install">Installi</string>
|
||||
<string name="unsupport_magisk_title">Mittetoetatud Magisk\'i versioon</string>
|
||||
<string name="section_home">Kodu</string>
|
||||
<string name="section_theme">Teemad</string>
|
||||
<string name="safetynet">SafetyNet</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<!--Home-->
|
||||
<string name="no_connection">Ühendus puudub</string>
|
||||
<string name="app_changelog">Muudatuste logi</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Laadimine…</string>
|
||||
<string name="update">Uuenda</string>
|
||||
<string name="not_available">puudub</string>
|
||||
<string name="hide">Peida</string>
|
||||
<string name="status">Olek</string>
|
||||
<string name="home_package">Pakett</string>
|
||||
|
||||
<string name="home_notice_content">Veendu alati, et kasutad avatud lähtekoodiga Magisk Manageri. Tundmatust allikast pärinev Manager võib teha pahatahtlikke toiminguid.</string>
|
||||
<string name="home_support_title">Toeta meid</string>
|
||||
<string name="home_item_source">Lähtekood</string>
|
||||
<string name="home_support_content">Magisk on ja jääb alati tasuta ning avatud lähtekoodiga kättesaadavaks. Siiski, sa võid meile väikese annetuse näol toetust üles näidata.</string>
|
||||
<string name="home_status_normal">Tavaline</string>
|
||||
<string name="home_status_stub">Makett</string>
|
||||
<string name="home_installed_version">Installitud</string>
|
||||
<string name="home_latest_version">Viimatine</string>
|
||||
<string name="invalid_update_channel">Sobimatu uuenduste kanal</string>
|
||||
<string name="safetynet_api_error">SafetyNet\'i API viga</string>
|
||||
<string name="safetynet_res_invalid">Vastus on sobimatu.</string>
|
||||
<string name="uninstall_magisk_title">Eemalda Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Kõik moodulid keelatakse/eemaldatakse!\nJuurkasutaja eemaldatakse!\nSinu andmeid võidakse krüpteerida, kui need juba ei ole krüpteeritud!</string>
|
||||
<string name="home_check_safetynet">Kontrolli SafetyNeti</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Säilita sunnitud krüpteering</string>
|
||||
<string name="keep_dm_verity">Säilita AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Taastusrežiim</string>
|
||||
<string name="uninstall_magisk_title">Eemalda Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Kõik moodulid keelatakse/eemaldatakse. Juurkasutaja eemaldatakse ning su andmed potensiaalselt krüpteeritakse, kui need ei ole juba krüpteeritud.</string>
|
||||
<string name="update">Uuenda</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Info puudub)</string>
|
||||
<string name="reboot_recovery">Taaskäivita taastusesse</string>
|
||||
<string name="reboot_bootloader">Taaskäivita käivitushaldurisse</string>
|
||||
<string name="reboot_download">Taaskäivita allalaadimisrežiimi</string>
|
||||
<string name="reboot_edl">Taaskäivita EDL\'i</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Uuendus saadaval</string>
|
||||
<string name="home_installed_version">Installitud</string>
|
||||
<string name="sorting_order">Sorteerimisjärjekord</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">Salvesta logi</string>
|
||||
<string name="menuClearLog">Tühjenda logi nüüd</string>
|
||||
<string name="logs_cleared">Logi edukalt tühjendatud.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">Muutuste logi</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Magisk\'i uuendused</string>
|
||||
<string name="progress_channel">Edenemise teated</string>
|
||||
<string name="download_complete">Allalaadimine valmis</string>
|
||||
<string name="download_file_error">Faili allalaadimisel esines viga</string>
|
||||
<string name="download_open_parent">Kuva ülemkaustas</string>
|
||||
<string name="download_open_self">Kuva fail</string>
|
||||
<string name="magisk_update_title">Magisk\'ile on uuendus saadaval!</string>
|
||||
<string name="manager_update_title">Magisk Manager\'ile on uuendus saadaval!</string>
|
||||
|
||||
<!-- Installation -->
|
||||
<string name="install_options_title">Valikud</string>
|
||||
<string name="install_method_title">Meetod</string>
|
||||
<string name="install_next">Edasi</string>
|
||||
<string name="install_start">Läksime</string>
|
||||
<string name="manager_download_install">Vajuta allalaadimiseks ja installimiseks.</string>
|
||||
<string name="download_zip_only">Laadi ainult ZIP alla</string>
|
||||
<string name="direct_install">Otsene install (soovitatud)</string>
|
||||
@@ -59,42 +52,92 @@
|
||||
<string name="select_patch_file">Vali ja paika fail</string>
|
||||
<string name="patch_file_msg">Vali toortõmmis (*.img) või ODIN tar-fail (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Taaskäivitamine 5 sekundi pärast…</string>
|
||||
<string name="flash_screen_title">Installimine</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<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>
|
||||
<string name="reboot">Taaskäivita</string>
|
||||
<string name="release_notes">Väljalaske märkmed</string>
|
||||
<string name="repo_cache_cleared">Hoidla vahemälu tühjendatud</string>
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superkasutaja taotlus</string>
|
||||
<string name="deny">Keela</string>
|
||||
<string name="prompt">Küsi</string>
|
||||
<string name="grant">Luba</string>
|
||||
<string name="su_warning">Annab täieliku ligipääsu sinu seadmele.\nKui sa pole kindel, keela!</string>
|
||||
<string name="forever">Igavesti</string>
|
||||
<string name="once">Üks kord</string>
|
||||
<string name="tenmin">10 min</string>
|
||||
<string name="twentymin">20 min</string>
|
||||
<string name="thirtymin">30 min</string>
|
||||
<string name="sixtymin">60 min</string>
|
||||
<string name="su_allow_toast">Rakendusele %1$s anti superkasutaja õigused</string>
|
||||
<string name="su_deny_toast">Rakendusel %1$s keelati superkasutaja õigused</string>
|
||||
<string name="su_snack_grant">Superkasutaja õigused antud rakendusele %1$s</string>
|
||||
<string name="su_snack_deny">Superkasutaja õigused keelatud rakendusele %1$s</string>
|
||||
<string name="su_snack_notif_on">Teavitused lubatud rakendusele %1$s</string>
|
||||
<string name="su_snack_notif_off">Teavitused keelatud rakendusele %1$s</string>
|
||||
<string name="su_snack_log_on">Logimine lubatud rakendusele %1$s</string>
|
||||
<string name="su_snack_log_off">Logimine keelatud rakendusele %1$s</string>
|
||||
<string name="su_revoke_title">Eemaldad?</string>
|
||||
<string name="su_revoke_msg">Kinnitad rakenduse %1$s õiguste eemaldamise?</string>
|
||||
<string name="toast">Hüpik</string>
|
||||
<string name="none">Puudub</string>
|
||||
|
||||
<string name="flashing">Välgutamine</string>
|
||||
<string name="done">Valmis!</string>
|
||||
<string name="failure">Ebaõnnestus</string>
|
||||
<string name="hide_manager_title">Peidan Magisk Manager\'i…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager\'i peitmine ebaõnnestus.</string>
|
||||
<string name="open_link_failed_toast">Lingi avamiseks sobivat rakendust ei leitud.</string>
|
||||
<string name="complete_uninstall">Täielik eemaldus</string>
|
||||
<string name="restore_img">Taasta tõmmised</string>
|
||||
<string name="restore_img_msg">Taastamine…</string>
|
||||
<string name="restore_done">Taastamine valmis!</string>
|
||||
<string name="restore_fail">Originaalne varundus puudub!</string>
|
||||
<string name="proprietary_title">Laadi alla suletud koodi</string>
|
||||
<string name="proprietary_notice">Magisk Manager on vaba ja avatud lähtekoodiga ning ei sisalda Google\'i suletud SafetyNet\'i API koodi.\n\nKas lubad Magisk Manager\'il SafetyNet\'i kontrollide jaoks laadida alla laiendus (sisaldab GoogleApiClient\'i)?</string>
|
||||
<string name="setup_fail">Seadistus ebaõnnnestus.</string>
|
||||
<string name="env_fix_title">Vajab lisaseadistust</string>
|
||||
<string name="env_fix_msg">Sinu seade vajab lisaseadistust, et Magisk töötaks korralikult. Laadime alla Magisk\'i seadistus-zip\'i, kas soovid kohe jätkata?</string>
|
||||
<string name="setup_msg">Käivitan keskkonnaseadistust…</string>
|
||||
<string name="superuser_toggle_notification">Teavitused</string>
|
||||
<string name="superuser_toggle_revoke">Eemalda</string>
|
||||
<string name="superuser_policy_none">Ükski rakendus ei ole veel superkasutaja õigusi küsinud.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Sa oled logivaba, proovi oma superkasutaja õigustega rakendusi rohkem kasutada.</string>
|
||||
<string name="log_data_magisk_none">Magiski logid on tühjad, see on imelik.</string>
|
||||
<string name="menuSaveLog">Salvesta logi</string>
|
||||
<string name="menuClearLog">Tühjenda logi nüüd</string>
|
||||
<string name="logs_cleared">Logi edukalt tühjendatud.</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Siht-UID: %1$d</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">SafetyNeti API viga</string>
|
||||
<string name="safetynet_res_invalid">Vastus on sobimatu</string>
|
||||
<string name="safetynet_attest_success">Edukas!</string>
|
||||
<string name="safetynet_attest_failure">Atesteerimine ebaõnnestus!</string>
|
||||
<string name="safetynet_attest_loading">Oota üks hetk…</string>
|
||||
<string name="safetynet_attest_restart">Proovi uuesti</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Kuva süsteemirakendused</string>
|
||||
<string name="hide_filter_hint">Filtreeri nime järgi</string>
|
||||
<string name="hide_scroll_up">Keri üles</string>
|
||||
<string name="hide_filters">Filtrid</string>
|
||||
<string name="hide_search">Otsing</string>
|
||||
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(Info puudub)</string>
|
||||
<string name="reboot_recovery">Taaskäivita taastusesse</string>
|
||||
<string name="reboot_bootloader">Taaskäivita käivitushaldurisse</string>
|
||||
<string name="reboot_download">Taaskäivita allalaadimisrežiimi</string>
|
||||
<string name="reboot_edl">Taaskäivita EDLi</string>
|
||||
<string name="module_version_author">%1$s autorilt %2$s</string>
|
||||
<string name="module_section_pending">Uuendused</string>
|
||||
<string name="module_section_pending_action">Uuenda kõik</string>
|
||||
<string name="module_state_remove">Eemalda</string>
|
||||
<string name="module_state_restore">Taasta</string>
|
||||
<string name="module_action_install_external">Installi sisemälust</string>
|
||||
<string name="update_available">Uuendus saadaval</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">Võrgus</string>
|
||||
<string name="sorting_order">Sorteerimisjärjekord</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Teema režiim</string>
|
||||
<string name="settings_dark_mode_message">Vali režiim, mis ühtib sinu stiiliga!</string>
|
||||
<string name="settings_dark_mode_light">Alati hele</string>
|
||||
<string name="settings_dark_mode_system">Järgi süsteemi</string>
|
||||
<string name="settings_dark_mode_dark">Alati tume</string>
|
||||
<string name="settings_download_path_title">Allalaadimise failitee</string>
|
||||
<string name="settings_download_path_message">Failid salvestatakse kausta %1$s</string>
|
||||
<string name="settings_clear_cache_title">Tühjenda hoidla vahemälu</string>
|
||||
<string name="settings_clear_cache_summary">Tühjenda vahemälus olev teave võrgus olevate hoidlate kohta. See sunnib rakendust võrgust värskendama.</string>
|
||||
<string name="settings_clear_cache_summary">Tühjenda vahemälus olev teave võrgus olevate hoidlate kohta. See sunnib rakendust võrgust värskendama</string>
|
||||
<string name="settings_hide_manager_title">Peida Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Taaspaki Magisk Manager juhusliku nimega.</string>
|
||||
<string name="settings_hide_manager_summary">Paki Magisk Manager juhusliku paketi- ja rakenduse nimega ümber</string>
|
||||
<string name="settings_restore_manager_title">Taasta Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Taasta Magisk Manager\'i originaalpakett</string>
|
||||
<string name="settings_restore_manager_summary">Taasta Magisk Manageri originaalpakett</string>
|
||||
<string name="language">Keel</string>
|
||||
<string name="system_default">(Süsteemi vaikesäte)</string>
|
||||
<string name="settings_check_update_title">Kontrolli uuendusi</string>
|
||||
@@ -107,8 +150,10 @@
|
||||
<string name="settings_magiskhide_summary">Peida Magisk erinevate tuvastuste eest</string>
|
||||
<string name="settings_hosts_title">Süsteemivaba hosts</string>
|
||||
<string name="settings_hosts_summary">Süsteemivaba hosts-tugi reklaamiblokeerijatest rakendustele</string>
|
||||
<string name="settings_hosts_toast">Süsteemivaba hosts\'i moodul lisatud</string>
|
||||
|
||||
<string name="settings_hosts_toast">Süsteemivaba hostsi moodul lisatud</string>
|
||||
<string name="settings_app_name_hint">Uus nimi</string>
|
||||
<string name="settings_app_name_helper">Rakendus pakitakse selle nimega</string>
|
||||
<string name="settings_app_name_error">Sobimatu vorming</string>
|
||||
<string name="settings_su_app_adb">Rakendused ja ADB</string>
|
||||
<string name="settings_su_app">Ainult rakendused</string>
|
||||
<string name="settings_su_adb">Ainult ADB</string>
|
||||
@@ -122,56 +167,75 @@
|
||||
<string name="superuser_access">Superkasutaja ligipääs</string>
|
||||
<string name="auto_response">Automaatne vastus</string>
|
||||
<string name="request_timeout">Taotluse ajalõpp</string>
|
||||
<string name="superuser_notification">Superkasutaja teade</string>
|
||||
<string name="settings_su_reauth_title">Taas-autendi peale täiendust</string>
|
||||
<string name="settings_su_reauth_summary">Taas-autendi superkasutaja õigused peale rakenduse täiendamist</string>
|
||||
<string name="superuser_notification">Superkasutaja teavitus</string>
|
||||
<string name="settings_su_reauth_title">Taas-autendi peale uuendust</string>
|
||||
<string name="settings_su_reauth_summary">Taas-autendi superkasutaja õigused peale rakenduse uuendamist</string>
|
||||
<string name="settings_su_biometric_title">Luba biomeetriaga autentimine</string>
|
||||
<string name="settings_su_biometric_summary">Kasuta superkasutaja taotluste kinnitamiseks biomeetrilist autentimist</string>
|
||||
<string name="no_biometric">Mittetoetatud seade või ükski biomeetriaseadistus pole lubatud</string>
|
||||
<string name="settings_customization">Kohandamine</string>
|
||||
<string name="setting_add_shortcut_summary">Lisa avakuvale ilus otsetee, juhul kui nime ja ikooni on pärast rakenduse peitmist raske tuvastada</string>
|
||||
<string name="settings_doh_title">DNS üle HTTPSi</string>
|
||||
<string name="settings_doh_description">Väldi mõnes riigis DNSi mürgitamist</string>
|
||||
|
||||
<string name="multiuser_mode">Mitmikkasutaja režiim</string>
|
||||
<string name="settings_owner_only">Ainult seadme omanik</string>
|
||||
<string name="settings_owner_manage">Seadme omaniku hallatud</string>
|
||||
<string name="settings_user_independent">Kasutajast sõltumatu</string>
|
||||
<string name="owner_only_summary">Ainult omanikul on juurkasutaja õigused.</string>
|
||||
<string name="owner_manage_summary">Ainult omanik saab hallata juurkasutaja ligipääsu ja saada taotlusküsimusi.</string>
|
||||
<string name="owner_only_summary">Ainult omanikul on juurkasutaja õigused</string>
|
||||
<string name="owner_manage_summary">Ainult omanik saab hallata juurkasutaja ligipääsu ja saada taotlusküsimusi</string>
|
||||
<string name="user_indepenent_summary">Igal kasutajal on oma isiklikud juurkasutaja reeglid.</string>
|
||||
|
||||
<string name="mount_namespace_mode">Nimeruumi monteerimisrežiim</string>
|
||||
<string name="settings_ns_global">Globaalne nimeruum</string>
|
||||
<string name="settings_ns_requester">Võta nimeruum üle</string>
|
||||
<string name="settings_ns_isolate">Isoleeritud nimeruum</string>
|
||||
<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="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>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superkasutaja taotlus</string>
|
||||
<string name="deny">Keela</string>
|
||||
<string name="prompt">Küsi</string>
|
||||
<string name="grant">Luba</string>
|
||||
<string name="su_warning">Annab täieliku ligipääsu sinu seadmele.\nKeela, kui sa pole kindel!</string>
|
||||
<string name="forever">Igavesti</string>
|
||||
<string name="once">Üks kord</string>
|
||||
<string name="tenmin">10 min</string>
|
||||
<string name="twentymin">20 min</string>
|
||||
<string name="thirtymin">30 min</string>
|
||||
<string name="sixtymin">60 min</string>
|
||||
<string name="su_allow_toast">Rakendusele %1$s anti superkasutaja õigused</string>
|
||||
<string name="su_deny_toast">Rakendusel %1$s keelati superkasutaja õigused</string>
|
||||
<string name="su_snack_grant">Superkasutaja õigused antud rakendusele %1$s</string>
|
||||
<string name="su_snack_deny">Superkasutaja õigused keelatud rakendusele %1$s</string>
|
||||
<string name="su_snack_notif_on">Teated lubatud rakendusele %1$s</string>
|
||||
<string name="su_snack_notif_off">Teated keelatud rakendusele %1$s</string>
|
||||
<string name="su_snack_log_on">Logimine lubatud rakendusele %1$s</string>
|
||||
<string name="su_snack_log_off">Logimine keelatud rakendusele %1$s</string>
|
||||
<string name="su_revoke_title">Eemaldad?</string>
|
||||
<string name="su_revoke_msg">Kinnitad rakenduse %1$s õiguste eemaldamise?</string>
|
||||
<string name="toast">Hüpik</string>
|
||||
<string name="none">Puudub</string>
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Magiski uuendused</string>
|
||||
<string name="progress_channel">Edenemise teated</string>
|
||||
<string name="download_complete">Allalaadimine valmis</string>
|
||||
<string name="download_file_error">Faili allalaadimisel esines viga</string>
|
||||
<string name="download_open_parent">Kuva ülemkaustas</string>
|
||||
<string name="download_open_self">Kuva fail</string>
|
||||
<string name="magisk_update_title">Magiski uuendus on saadaval!</string>
|
||||
<string name="manager_update_title">Magisk Manageri uuendus on saadaval!</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Siht-UID: %1$d</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Kuva süsteemirakendused</string>
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Jah</string>
|
||||
<string name="no">Ei</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>
|
||||
<string name="reboot">Taaskäivita</string>
|
||||
<string name="release_notes">Väljalaskemärkmed</string>
|
||||
<string name="repo_cache_cleared">Hoidla vahemälu tühjendatud</string>
|
||||
<string name="flashing">Välgutamine…</string>
|
||||
<string name="done">Valmis!</string>
|
||||
<string name="failure">Ebaõnnestus</string>
|
||||
<string name="hide_manager_title">Magisk Manageri peitmine…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manageri peitmine ebaõnnestus.</string>
|
||||
<string name="open_link_failed_toast">Lingi avamiseks sobivat rakendust ei leitud.</string>
|
||||
<string name="complete_uninstall">Täielik eemaldus</string>
|
||||
<string name="restore_img">Taasta tõmmised</string>
|
||||
<string name="restore_img_msg">Taastamine…</string>
|
||||
<string name="restore_done">Taastamine valmis!</string>
|
||||
<string name="restore_fail">Originaalne varundus puudub!</string>
|
||||
<string name="proprietary_title">Laadi alla suletud koodi</string>
|
||||
<string name="proprietary_notice">Magisk Manager on vaba ja avatud lähtekoodiga ning ei sisalda Google\'i suletud SafetyNeti API koodi.\n\nKas lubad Magisk Manageril SafetyNeti kontrollide jaoks laadida alla laiendus (sisaldab GoogleApiClienti)?</string>
|
||||
<string name="setup_fail">Seadistus ebaõnnnestus</string>
|
||||
<string name="env_fix_title">Vajab lisaseadistust</string>
|
||||
<string name="env_fix_msg">Sinu seade vajab Magiski korralikuks toimimiseks lisaseadistust. Laadime alla Magiski seadistus-ZIPi, kas soovid kohe jätkata?</string>
|
||||
<string name="setup_msg">Käivitan keskkonnaseadistust…</string>
|
||||
<string name="authenticate">Autendi</string>
|
||||
<string name="unsupport_magisk_title">Mittetoetatud Magiski versioon</string>
|
||||
<string name="unsupport_magisk_msg">See Magisk Manageri versioon ei toeta Magiski versiooni, mis on vanem kui %1$s.\n\nRakendus käitub nii, nagu Magisk ei oleks paigaldatud, palun uuenda Magisk nii ruttu kui võimalik.</string>
|
||||
<string name="external_rw_permission_denied">Selle funktsionaalsuse lubamiseks anna mäluruumi haldamise luba</string>
|
||||
<string name="add_shortcut_title">Lisa avakuvale otsetee</string>
|
||||
<string name="add_shortcut_msg">Pärast Magisk Manageri peitmist võib selle nimi ja ikoon muutuda raskelt tuvastatavaks. Kas soovid avakuvale ilusa otsetee lisada?</string>
|
||||
<string name="app_not_found">Selle tegevuse teostamiseks ei leitud ühtegi rakendust</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -56,6 +56,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Demande d’accès super‑utilisateur</string>
|
||||
<string name="touch_filtered_warning">Parce qu’une application obscurcit une demande du super-utilisateur, Magisk ne peut pas vérifier votre réponse</string>
|
||||
<string name="deny">Refuser</string>
|
||||
<string name="prompt">Demander</string>
|
||||
<string name="grant">Accorder</string>
|
||||
@@ -102,13 +103,15 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Afficher les applications système</string>
|
||||
<string name="show_os_app">Afficher les applis système</string>
|
||||
<string name="hide_filter_hint">Filtrer par nom</string>
|
||||
<string name="hide_scroll_up">Faire défiler vers le haut</string>
|
||||
<string name="hide_filters">Filtres</string>
|
||||
<string name="hide_search">Rechercher</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(aucune info transmise)</string>
|
||||
<string name="reboot_userspace">Redémarrage en douceur</string>
|
||||
<string name="reboot_recovery">Redémarrer en mode récupération</string>
|
||||
<string name="reboot_bootloader">Redémarrer en mode amorçage</string>
|
||||
<string name="reboot_download">Redémarrer en mode téléchargement</string>
|
||||
@@ -170,6 +173,8 @@
|
||||
<string name="superuser_notification">Notification super‑utilisateur</string>
|
||||
<string name="settings_su_reauth_title">S’authentifier à nouveau après la mise à niveau</string>
|
||||
<string name="settings_su_reauth_summary">Redemander une authentification pour autoriser l’accès en super‑utilisateur après une mise à jour de l’application</string>
|
||||
<string name="settings_su_tapjack_title">Activer Protection Détournement de Clic</string>
|
||||
<string name="settings_su_tapjack_summary">Le dialogue d’invite du super-utilisateur ne répondra pas à la saisie lorsqu’il est masqué par une autre fenêtre ou un recouvrement</string>
|
||||
<string name="settings_su_biometric_title">Activer l’authentification biométrique</string>
|
||||
<string name="settings_su_biometric_summary">Utiliser l’authentification biométrique pour autoriser les accès en super‑utilisateur</string>
|
||||
<string name="no_biometric">L’appareil n’est pas pris en charge ou alors aucun paramètre biométrique n’est activé</string>
|
||||
@@ -219,6 +224,7 @@
|
||||
<string name="hide_manager_title">Masquage de Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Le masquage de Magisk Manager a échoué.</string>
|
||||
<string name="open_link_failed_toast">Aucune application permettant d’ouvrir le lien n’a été trouvée</string>
|
||||
<string name="restore_manager_fail_toast">Échec de la restauration de Magisk Manager</string>
|
||||
<string name="complete_uninstall">Désinstallation complète</string>
|
||||
<string name="restore_img">Restauration des images</string>
|
||||
<string name="restore_img_msg">Restauration…</string>
|
||||
@@ -234,7 +240,8 @@
|
||||
<string name="unsupport_magisk_title">Version de Magisk non prise en charge</string>
|
||||
<string name="unsupport_magisk_msg">Cette version de Magisk Manager ne prend pas en charge les versions de Magisk inférieures à %1$s.\n\nL’application se comportera comme si Magisk n’était pas installé. Veuillez mettre à jour Magisk aussi vite que possible.</string>
|
||||
<string name="external_rw_permission_denied">Permettre l’accès au stockage pour activer cette fonctionnalité</string>
|
||||
<string name="add_shortcut_title">Ajouter un raccourcis à l’écran d’accueil</string>
|
||||
<string name="add_shortcut_msg">Après avoir caché Magisk Manager, son nom et son icône peuvent devenir difficiles à reconnaître. Voulez-vous ajouter un joli raccourci vers l’écran d’accueil ?</string>
|
||||
<string name="add_shortcut_title">Ajouter un raccourci à l’écran d’accueil</string>
|
||||
<string name="add_shortcut_msg">Après avoir caché Magisk Manager, son nom et son icône peuvent devenir difficiles à reconnaître. Voulez‑vous ajouter un joli raccourci vers l’écran d’accueil ?</string>
|
||||
<string name="app_not_found">Aucune application trouvée pour traiter cette action</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,177 +1,244 @@
|
||||
<resources>
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<!--Sections-->
|
||||
<string name="modules">मॉड्यूल</string>
|
||||
<string name="superuser">उत्तम उपयोगकर्ता</string>
|
||||
<string name="logs">अभिलेख</string>
|
||||
<string name="superuser">सुपर यूज़र</string>
|
||||
<string name="logs">लॉग्स</string>
|
||||
<string name="settings">सेटिंग्स</string>
|
||||
<string name="install">स्थापित करें</string>
|
||||
<string name="unsupport_magisk_title">असमर्थित Magisk संस्करण</string>
|
||||
<string name="refresh">स्थानीय डेटा रिफ्रेश करें</string>
|
||||
<string name="install">इंस्टॉल</string>
|
||||
<string name="section_home">घर</string>
|
||||
<string name="section_theme">थीम</string>
|
||||
<string name="safetynet">सेफ्टीनेट</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="invalid_update_channel">अमान्य अपडेट चैनल</string>
|
||||
<string name="safetynet_api_error">SafetyNet API त्रुटि</string>
|
||||
<string name="safetynet_res_invalid">अनुक्रिया अमान्य है.</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="uninstall_magisk_title">Magisk की स्थापना रद्द करें</string>
|
||||
<string name="uninstall_magisk_msg">सभी मॉड्यूल अक्षम/हटा दिए जाएंगे. रुट और आपका संभावित रूप से एन्क्रिप्ट डाटा हटा दिया जाएगा.</string>
|
||||
<!--Home-->
|
||||
<string name="no_connection">कोई कनेक्शन उपलब्ध नहीं है</string>
|
||||
<string name="app_changelog">बदलाव</string>
|
||||
<string name="manager">मैनेजर</string>
|
||||
<string name="loading">लोड हो रहा है…</string>
|
||||
<string name="update">अपडेट करें</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">छिपाएँ</string>
|
||||
<string name="status">स्थिति</string>
|
||||
<string name="home_package">पैकेज</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(कोई जानकारी प्रदान नहीं की गई)</string>
|
||||
<string name="reboot_recovery">रिकवरी मोड में रिबूट करें</string>
|
||||
<string name="reboot_bootloader">बूटलोडर में रिबूट करें</string>
|
||||
<string name="reboot_download">डाउनलोड में रिबूट करें</string>
|
||||
<string name="reboot_edl">EDL मोड में रिबूट करें</string>
|
||||
<string name="home_notice_content">हमेशा सुनिश्चित करें कि आप ओपन-सोर्स मैजिक मैनेजर का उपयोग कर रहे हैं। अज्ञात स्रोत के प्रबंधक दुर्भावनापूर्ण कार्य कर सकते हैं।</string>
|
||||
<string name="home_support_title">हमें सहयोग दीजिये</string>
|
||||
<string name="home_item_source">स्रोत</string>
|
||||
<string name="home_support_content">मैजिस्क है, और हमेशा मुफ्त और ओपन-सोर्स रहेगा। हालाँकि आप एक छोटा सा दान भेजकर यह दिखा सकते हैं कि आप देख-भाल करते हैं।</string>
|
||||
<string name="home_status_normal">साधारण</string>
|
||||
<string name="home_status_stub">स्टब</string>
|
||||
<string name="home_installed_version">इंस्टॉल्ड</string>
|
||||
<string name="home_latest_version">नवीनतम</string>
|
||||
<string name="invalid_update_channel">अमान्य अपडेट चैनल</string>
|
||||
<string name="uninstall_magisk_title">मैजिस्क को अनइंस्टॉल करें</string>
|
||||
<string name="uninstall_magisk_msg">सभी मॉड्यूल्स को निष्क्रिय/हटा दिया जाएगा!\n रूट को हटा दिया जाएगा!\n आपका डेटा संभावित रूप से एन्क्रिप्ट किया गया है यदि पहले से नहीं है!</string>
|
||||
<string name="home_check_safetynet">सेफ्टीनेट की जाँच करें</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">अपडेट उपलब्ध है</string>
|
||||
<string name="home_installed_version">स्थापित</string>
|
||||
<string name="sorting_order">छँटाई क्रम </string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">अभिलेख सेव करें</string>
|
||||
<string name="menuClearLog">अभिलेख साफ़ करें</string>
|
||||
<string name="logs_cleared">अभिलेख सफलतापूर्वक साफ़ हो गया.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<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>
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">फ़ोर्स एन्क्रिप्शन को संरक्षित रखें</string>
|
||||
<string name="keep_dm_verity">AVB 2.0/dm-verity को संरक्षित रखें</string>
|
||||
<string name="recovery_mode">रिकवरी मोड</string>
|
||||
<string name="install_options_title">विकल्प</string>
|
||||
<string name="install_method_title">तरीका</string>
|
||||
<string name="install_next">आगे</string>
|
||||
<string name="install_start">तो चलिए शुरू करते हैं!</string>
|
||||
<string name="manager_download_install">डाउनलोड और इंस्टॉल करने के लिए दबाएं</string>
|
||||
<string name="download_zip_only">केवल ज़िप डाउनलोड करें</string>
|
||||
<string name="direct_install">प्रत्यक्ष इंस्टॉल (अनुशंसित)</string>
|
||||
<string name="install_inactive_slot">निष्क्रिय स्लॉट में इंस्टॉल करें (OTA के बाद)</string>
|
||||
<string name="install_inactive_slot_msg">आपका डिवाइस रीबूट होने के बाद वर्तमान निष्क्रिय स्लॉट में बूट करने के लिए मजबूर किया जाएगा!\n इस विकल्प का उपयोग सिर्फ OTA हो जाने के बाद करें।\n जारी रखें?</string>
|
||||
<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="release_notes">रिलीज नोट्स</string>
|
||||
<string name="repo_cache_cleared">Repo cache साफ़ हो गया</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="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_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_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_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="settings_su_reauth_title">अपग्रेड के बाद फिर से प्रमाणित करें</string>
|
||||
<string name="settings_su_reauth_summary">एप्लीकेशन अपग्रेड होने के बाद उत्तम उपयोगकर्ता की अनुमतियों को फिर से प्रमाणित करें</string>
|
||||
|
||||
<string name="multiuser_mode">बहु उपयोगकर्ता मोड</string>
|
||||
<string name="settings_owner_only">केवल डिवाइस का मालिक</string>
|
||||
<string name="settings_owner_manage">केवल डिवाइस के मालिक द्वौरा प्रभंदित</string>
|
||||
<string name="settings_user_independent">उपयोगकर्ता स्वतंत्र</string>
|
||||
<string name="owner_only_summary">केवल मालिक के पास ही रूट की पहुँच है.</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="patch_file_msg">एक रॉ छवि (* .img) या एक ODIN tarfile (* .tar) का चयन करें</string>
|
||||
<string name="reboot_delay_toast">5 सेकंड में रिबूट हो रहा है...</string>
|
||||
<string name="flash_screen_title">इंस्टॉलेशन</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">उत्तम उपयोगकर्ता का अनुरोध</string>
|
||||
<string name="su_request_title">सुपरयूज़र अनुरोध</string>
|
||||
<string name="deny">इंकार करें</string>
|
||||
<string name="prompt">आदेश</string>
|
||||
<string name="prompt">संकेत दिखाएँ</string>
|
||||
<string name="grant">अनुमति दें</string>
|
||||
<string name="su_warning">यह आपके डिवाइस की पूरी पहुँच की अनुमति देगा. यदि आप सुनिश्चित नहीं हैं तो इंकार करें!</string>
|
||||
<string name="su_warning">यह आपके डिवाइस की पूरी पहुँच की अनुमति देगा,\n यदि आप सुनिश्चित नहीं हैं तो इंकार करें!</string>
|
||||
<string name="forever">सदैव</string>
|
||||
<string name="once">एक बार</string>
|
||||
<string name="tenmin">10 मिनट</string>
|
||||
<string name="tenmin">10 मिनिट</string>
|
||||
<string name="twentymin">20 मिनट</string>
|
||||
<string name="thirtymin">30 मिनट</string>
|
||||
<string name="sixtymin">60 मिनट</string>
|
||||
<string name="su_allow_toast">%1$s को उत्तम उपयोगकर्ता के अधिकार की अनुमति दी गई</string>
|
||||
<string name="su_deny_toast">%1$s को उत्तम उपयोगकर्ता के अधिकार से इनकार किया गया</string>
|
||||
<string name="su_snack_grant">%1$s को उत्तम उपयोगकर्ता के अधिकार की अनुमति है</string>
|
||||
<string name="su_snack_deny">%1$s को उत्तम उपयोगकर्ता के अधिकार की अनुमति नहीं है</string>
|
||||
<string name="su_snack_notif_on">%1$s की सूचनाएं सक्षम हैं</string>
|
||||
<string name="su_snack_notif_off">%1$s की सूचनाएं अक्षम हैं</string>
|
||||
<string name="su_snack_log_on">%1$s के लिए अभिलेख सक्षम है</string>
|
||||
<string name="su_snack_log_off">%1$s के लिए अभिलेख अक्षम है</string>
|
||||
<string name="su_revoke_title">वापस लें?</string>
|
||||
<string name="su_revoke_msg">%1$s के अधिकारों को वापस लेने की पुष्टि करें?</string>
|
||||
<string name="toast">पॉप-अप नोट</string>
|
||||
<string name="su_allow_toast"> %1$s को सुपरयूज़र अधिकार प्रदान किया गया</string>
|
||||
<string name="su_deny_toast"> %1$s को सुपरयूज़र अधिकार से इंकार किया गया</string>
|
||||
<string name="su_snack_grant"> %1$s को सुपरयूज़र अधिकार प्रदान किए गए </string>
|
||||
<string name="su_snack_deny"> %1$s के सुपरयूज़र अधिकारों को अस्वीकार कर दिया गया है</string>
|
||||
<string name="su_snack_notif_on"> %1$s की सूचनाएं सक्षम हैं</string>
|
||||
<string name="su_snack_notif_off"> %1$s की सूचनाएं अक्षम हैं</string>
|
||||
<string name="su_snack_log_on"> %1$s की लॉगिंग सक्षम है</string>
|
||||
<string name="su_snack_log_off"> %1$s की लॉगिंग अक्षम है</string>
|
||||
<string name="su_revoke_title">अधिकार वापस लें?</string>
|
||||
<string name="su_revoke_msg"> %1$s के अधिकारों को रद्द करने की पुष्टि करें?</string>
|
||||
<string name="toast">पॉप-अप सूचना</string>
|
||||
<string name="none">कोई नहीं</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="superuser_toggle_notification">सूचनाएं</string>
|
||||
<string name="superuser_toggle_revoke">अधिकार वापस लें</string>
|
||||
<string name="superuser_policy_none">किसी भी ऐप ने अभी तक सुपरयूज़र की अनुमति नहीं मांगी है।</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">कोई लॉग नहीं, अपने सुपरयूज़र सक्षम एप्लिकेशन का अधिक उपयोग करने का प्रयास करें।</string>
|
||||
<string name="log_data_magisk_none">मैजिस्क लॉग खाली हैं, यह अजीब है।</string>
|
||||
<string name="menuSaveLog">लॉग सहेजे</string>
|
||||
<string name="menuClearLog">लॉग साफ़ करें</string>
|
||||
<string name="logs_cleared">लॉग सफलतापूर्वक साफ़ किया गया।</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">लक्ष्य UID: %1$d</string>
|
||||
<string name="target_uid">लक्षित UID: %1$d</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">सेफ्टीनेट एपीआई त्रुटि</string>
|
||||
<string name="safetynet_res_invalid">प्रतिक्रिया अमान्य है</string>
|
||||
<string name="safetynet_attest_success">सफलता!</string>
|
||||
<string name="safetynet_attest_failure">सत्यापन विफल!</string>
|
||||
<string name="safetynet_attest_loading">सिर्फ एक सेकंड…</string>
|
||||
<string name="safetynet_attest_restart">पुनः प्रयास करें</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">सिस्टम ऍप्लिकेशन्स दिखाएं</string>
|
||||
<string name="show_system_app">सिस्टम ऐप्स दिखाएं</string>
|
||||
<string name="show_os_app">OS एप्लिकेशन दिखाएं</string>
|
||||
<string name="hide_filter_hint">नाम से फ़िल्टर करें</string>
|
||||
<string name="hide_scroll_up">ऊपर स्क्रॉल करें</string>
|
||||
<string name="hide_filters">फिल्टर</string>
|
||||
<string name="hide_search">खोजें</string>
|
||||
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(कोई जानकारी नहीं दी गई)</string>
|
||||
<string name="reboot_userspace">सॉफ्ट रिबूट</string>
|
||||
<string name="reboot_recovery">रिकवरी रिबूट</string>
|
||||
<string name="reboot_bootloader">बूटलोडर रिबूट</string>
|
||||
<string name="reboot_download">डाउनलोड मोड रिबूट</string>
|
||||
<string name="reboot_edl">EDL रिबूट</string>
|
||||
<string name="module_version_author"> %2$s के द्वारा %1$s</string>
|
||||
<string name="module_section_pending">अपडेट्स</string>
|
||||
<string name="module_section_pending_action">सभी अपडेट करें</string>
|
||||
<string name="module_state_remove">हटाएँ</string>
|
||||
<string name="module_state_restore">रिस्टोर करें</string>
|
||||
<string name="module_action_install_external">स्टोरेज से इनस्टॉल करें</string>
|
||||
<string name="update_available">अपडेट उपलब्ध</string>
|
||||
<string name="module_installed">इंस्टॉल्ड</string>
|
||||
<string name="module_section_online">ऑनलाइन</string>
|
||||
<string name="sorting_order">क्रमबद्ध तरीका</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">थीम मोड</string>
|
||||
<string name="settings_dark_mode_message">ऐसी थीम का चयन करें जो आपकी शैली के अनुकूल हो!</string>
|
||||
<string name="settings_dark_mode_light">हमेशा सफेद रंग वाली</string>
|
||||
<string name="settings_dark_mode_system">सिस्टम के अनुसार</string>
|
||||
<string name="settings_dark_mode_dark">हमेशा गहरे रंग वाली</string>
|
||||
<string name="settings_download_path_title">डाउनलोड पथ</string>
|
||||
<string name="settings_download_path_message">फ़ाइलों को %1$s में सहेजा जाएगा</string>
|
||||
<string name="settings_clear_cache_title">रेपो कैश साफ़ करें</string>
|
||||
<string name="settings_clear_cache_summary">ऑनलाइन रेपो के लिए कैश्ड जानकारी साफ़ करें। यह एप्लिकेशन को ऑनलाइन रिफ्रेश करने के लिए मजबूर करता है</string>
|
||||
<string name="settings_hide_manager_title">मैजिस्क मैनेजर छिपाएं</string>
|
||||
<string name="settings_hide_manager_summary">बेतरतीब पैकेज और ऐप नामों के साथ मैगिस्क मैनेजर को रिपैकेज करें</string>
|
||||
<string name="settings_restore_manager_title">मैजिस्क मैनेजर को रिस्टोर करें</string>
|
||||
<string name="settings_restore_manager_summary">मूल पैकेज और ऐप नाम के साथ मैजिस्क मैनेजर को रिस्टोर करें</string>
|
||||
<string name="language">भाषा</string>
|
||||
<string name="system_default">(सिस्टम डिफ़ॉल्ट)</string>
|
||||
<string name="settings_check_update_title">अपडेट जांचें</string>
|
||||
<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_magiskhide_summary">विभिन्न रूप की खोजों से बचने के लिए मैजिस्क को छिपाएं</string>
|
||||
<string name="settings_hosts_title">सिस्टमलेस होस्ट</string>
|
||||
<string name="settings_hosts_summary">Adblock ऐप्स के लिए सिस्टमलेस होस्ट सपोर्ट</string>
|
||||
<string name="settings_hosts_toast">सिस्टमलेस होस्ट मॉड्यूल जोड़ा गया</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">ऐप्स और एडीबी</string>
|
||||
<string name="settings_su_app">केवल ऐप्स</string>
|
||||
<string name="settings_su_adb">केवल एडीबी</string>
|
||||
<string name="settings_su_disable">बंद है</string>
|
||||
<string name="settings_su_request_10">10 सेकंड</string>
|
||||
<string name="settings_su_request_15">15 सेकंड</string>
|
||||
<string name="settings_su_request_20">20 सेकंड</string>
|
||||
<string name="settings_su_request_30">30 सेकंड</string>
|
||||
<string name="settings_su_request_45">45 सेकंड</string>
|
||||
<string name="settings_su_request_60">60 सेकंड</string>
|
||||
<string name="superuser_access">सुपरयूज़र एक्सेस</string>
|
||||
<string name="auto_response">स्वचालित प्रतिक्रिया</string>
|
||||
<string name="request_timeout">अनुरोध की समय समाप्ति सीमा</string>
|
||||
<string name="superuser_notification">सुपरयूज़र सूचना</string>
|
||||
<string name="settings_su_reauth_title">अपग्रेड के बाद प्रमाणीकरण</string>
|
||||
<string name="settings_su_reauth_summary">एक ऐप अपडेट होने के बाद सुपरयूज़र अनुमति प्रमाणित करें</string>
|
||||
<string name="settings_su_biometric_title">बायोमेट्रिक प्रमाणीकरण सक्षम करें</string>
|
||||
<string name="settings_su_biometric_summary">सुपरयूज़र अनुरोधों की अनुमति देने के लिए बायोमेट्रिक प्रमाणीकरण का उपयोग करें</string>
|
||||
<string name="no_biometric">असमर्थित डिवाइस या कोई बायोमेट्रिक सेटिंग सक्षम नहीं हैं</string>
|
||||
<string name="settings_customization">कस्टमाईजेशन</string>
|
||||
<string name="setting_add_shortcut_summary">ऐप को छिपाने के बाद नाम और आइकन को पहचानना मुश्किल है, तो होम स्क्रीन में एक सुंदर शॉर्टकट जोड़ें</string>
|
||||
<string name="settings_doh_title">DNS पर HTTPS</string>
|
||||
<string name="settings_doh_description">कुछ राष्ट्रों में चल रही DNS विषाक्तता का समाधान</string>
|
||||
|
||||
<string name="multiuser_mode">बहु उपयोगकर्ता मोड</string>
|
||||
<string name="settings_owner_only">केवल डिवाइस का मालिक</string>
|
||||
<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>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">मैजिस्क अपडेट</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">मैजिस्क अपडेट उपलब्ध!</string>
|
||||
<string name="manager_update_title">मैजिस्क मैनेजर के लिए अपडेट उपलब्ध है!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">हाँ</string>
|
||||
<string name="no">नहीं</string>
|
||||
<string name="repo_install_title">इंस्टॉल %1$s</string>
|
||||
<string name="repo_install_msg">क्या आप अभी %1$s इंस्टॉल करना चाहते हैं?</string>
|
||||
<string name="download">डाउनलोड</string>
|
||||
<string name="reboot">रीबूट</string>
|
||||
<string name="release_notes">रिलीज नोट्स</string>
|
||||
<string name="repo_cache_cleared">रेपो कैश साफ़ किया</string>
|
||||
<string name="flashing">फ़्लैश हो रहा है...</string>
|
||||
<string name="done">सफल हुआ!</string>
|
||||
<string name="failure">असफल हुआ</string>
|
||||
<string name="hide_manager_title">मैजिस्क मैनेजर को छिपा रहे हैं...</string>
|
||||
<string name="hide_manager_fail_toast">मैजिस्क मैनेजर छिपाना विफल हुआ</string>
|
||||
<string name="restore_manager_fail_toast">मैजिस्क मैनेजर को रिस्टोर करना विफल हुआ</string>
|
||||
<string name="open_link_failed_toast">लिंक खोलने के लिए कोई एप्लिकेशन नहीं मिला</string>
|
||||
<string name="complete_uninstall">पूर्ण रूप से अनइंस्टॉल करें</string>
|
||||
<string name="restore_img">इमेज रिस्टोर करें</string>
|
||||
<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">मैजिस्क मैनेजर एक मुफ्त और ओपन-सोर्स ऐप है जो गूगल के मालिकाना सेफ्टीनेट कोड का इस्तेमाल नहीं करता। क्या आप मैजिस्क मैनेजर को सेफ्टीनेट की जांच के लिए एक एक्सटेंशन डाऊनलोड करने की अनुमति प्रदान करना चाहेंगे?</string>
|
||||
<string name="setup_fail">सेटअप असफल हुआ</string>
|
||||
<string name="env_fix_title">अतिरिक्त सेटअप की ज़रूरत है</string>
|
||||
<string name="env_fix_msg">आपके डिवाइस पर मैजिस्क को सही से काम करने के लिए अतिरिक्त सेटअप की ज़रूरत है। यह एक मैजिस्क सेटअप ज़िप डाउनलोड करेगा, क्या आप आगे बढ़ना चाहेंगे?</string>
|
||||
<string name="setup_msg">वातावरण सेटअप चल रहा है...</string>
|
||||
<string name="authenticate">प्रमाणित करें</string>
|
||||
<string name="unsupport_magisk_title">असमर्थित मैजिस्क संस्करण</string>
|
||||
<string name="unsupport_magisk_msg">मैजिस्क मैनेजर का यह संस्करण मैजिस्क संस्करण %1$s से कम का समर्थन नहीं करता। \n\nऐप इस तरह व्यवहार करेगा जैसे मैजिस्क इंस्टॉल नहीं है, कृपया मैजिस्क को जल्द अपग्रेड करें।</string>
|
||||
<string name="external_rw_permission_denied">इसका उपयोग करने के लिए स्टोरेज अनुमति प्रदान करें</string>
|
||||
<string name="add_shortcut_title">होम स्क्रीन पर शॉर्टकट जोड़ें</string>
|
||||
<string name="add_shortcut_msg">मैजिस्क मैनेजर को छिपाने के बाद इसका नाम और आइकॉन पहचानना मुश्किल हो सकता है, क्या आप एक अच्छा दिखने वाला शॉर्टकट होम स्क्रीन पर जोड़ना चाहेंगे?</string>
|
||||
<string name="app_not_found">इस एक्शन को संभालने के लिए कोई एप्लिकेशन नहीं मिली</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -6,112 +6,61 @@
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="logs">Zapisnik događaja</string>
|
||||
<string name="settings">Postavke</string>
|
||||
<string name="refresh">Osvježite lokalne podatke</string>
|
||||
<string name="install">Instaliranje</string>
|
||||
<string name="section_home">Početna</string>
|
||||
<string name="section_theme">Teme</string>
|
||||
<string name="safetynet">SafetyNet</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<!--Home-->
|
||||
<string name="no_connection">Nema dostupne veze</string>
|
||||
<string name="app_changelog">Popis izmjena</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Učitavanje…</string>
|
||||
<string name="update">Ažuriraj</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Sakrij</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Paket</string>
|
||||
|
||||
<string name="safetynet_api_error">SafetyNet API greška</string>
|
||||
<string name="safetynet_res_invalid">Odgovor je nevažeći</string>
|
||||
<string name="home_notice_content">Uvijek provjerite koristite li Magisk Manager s otvorenim kodom. Manager nepoznatog izvora može izvoditi zlonamjerne radnje.</string>
|
||||
<string name="home_support_title">Podržite nas</string>
|
||||
<string name="home_item_source">Izvor</string>
|
||||
<string name="home_support_content">Magisk je i uvijek će biti besplatan i otvoren. Međutim, možete nam pokazati da vam je stalo slanjem male donacije.</string>
|
||||
<string name="home_status_normal">Normalno</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Instalirana</string>
|
||||
<string name="home_latest_version">Najnovija</string>
|
||||
<string name="invalid_update_channel">Nevažeći kanal ažuriranja</string>
|
||||
<string name="uninstall_magisk_title">Deinstaliraj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Svi će moduli biti onemogućeni/uklonjeni!\nRoot će biti uklonjen!\nVaši su podaci potencijalno šifrirani, ako već nisu!</string>
|
||||
<string name="home_check_safetynet">Provjeri SafetyNet</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Zadrži prisilno šifirannje</string>
|
||||
<string name="keep_dm_verity">Zadrži AVB 2.0/dm-verity</string>
|
||||
<string name="uninstall_magisk_title">Deinstaliraj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Svi moduli će biti onemogućeni/uklonjeni. Root će biti uklonjen i potencijalno šifrirati Vaše podatke, ukoliko Vaši podaci trenutačno nisu šifrirani</string>
|
||||
<string name="update">Ažuriraj</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nema podataka)</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Ažuriranje dostupno</string>
|
||||
<string name="home_installed_version">Instalirano</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">"Spremi zapisnik "</string>
|
||||
<string name="menuClearLog">Očisti zapisnik sada</string>
|
||||
<string name="logs_cleared">Zapisnik je uspješno izbrisan</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="app_changelog">Popis izmjena aplikacije</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<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>
|
||||
<string name="reboot">Ponovno podizanje sustava</string>
|
||||
<string name="magisk_update_title">Dostupno je novo Magisk ažuriranje!</string>
|
||||
<string name="release_notes">Bilješke o izdavanju aplikacije</string>
|
||||
<string name="repo_cache_cleared">Predmemorija repozitorija izbrisana</string>
|
||||
<string name="manager_update_title">Dostupno je novo ažuriranje Magisk Manager aplikacije!</string>
|
||||
<string name="manager_download_install">Pritisnite za preuzimanje i instalaciju</string>
|
||||
<string name="update_channel">Magisk ažuriranja</string>
|
||||
<string name="flashing">Apliciranje</string>
|
||||
<string name="hide_manager_title">Skrivanje Magisk Manager aplikacije…</string>
|
||||
<string name="hide_manager_fail_toast">Skrivanje Magisk Manager nije uspjelo</string>
|
||||
<string name="recovery_mode">Recovery način</string>
|
||||
<string name="install_options_title">Opcije</string>
|
||||
<string name="install_method_title">Metoda</string>
|
||||
<string name="install_next">Dalje</string>
|
||||
<string name="install_start">Krenimo</string>
|
||||
<string name="manager_download_install">Dodirnite za preuzimanje i instalaciju</string>
|
||||
<string name="download_zip_only">Preuzmi samo zip</string>
|
||||
<string name="direct_install">Izravna instalacija (preporuča se)</string>
|
||||
<string name="complete_uninstall">Potpuna deinstalacija</string>
|
||||
<string name="restore_done">Obnova je dovršena!</string>
|
||||
<string name="restore_fail">Stock backup does not exist!</string>
|
||||
<string name="proprietary_title">Preuzmite vlasnički kod</string>
|
||||
<string name="proprietary_notice">Magisk Manager je FOSS aplikacija te ne sadrži Googleov SafetyNet API kod.\n\nDopuštate li Magisk Manager aplikaciji da preuzme proširenje (sadrži GoogleApiClient) za SafetyNet provjere?</string>
|
||||
<string name="download_file_error">Pogreška prilikom preuzimanja datoteke</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_clear_cache_title">Izbriši predmemoriju repozitorija</string>
|
||||
<string name="settings_clear_cache_summary">Izbrišite predmemorirane informacije za online repozitorij, prisiljavajući aplikaciju da se osvježi online</string>
|
||||
<string name="settings_hide_manager_title">Sakrij Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Privremeno sakrij Magisk Manager.\nTo će instalirati novu aplikaciju pod nazivom \"Otkrij Magisk Manager\"</string>
|
||||
<string name="language">Jezik</string>
|
||||
<string name="system_default">(Zadana postavka sustava)</string>
|
||||
<string name="settings_update_channel_title">Kanal ažuriranja</string>
|
||||
<string name="settings_update_stable">Stabilno</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
|
||||
<string name="settings_magiskhide_summary">Sakrij Magisk od raznih detekcija</string>
|
||||
<string name="settings_hosts_title">Systemless hostovi</string>
|
||||
<string name="settings_hosts_summary">Systemless hostovi podržavaju Adblock aplikacije</string>
|
||||
|
||||
<string name="settings_su_app_adb">Aplikacije i ADB</string>
|
||||
<string name="settings_su_app">Samo aplikacije</string>
|
||||
<string name="settings_su_adb">Samo ADB</string>
|
||||
<string name="settings_su_disable">Onemogućeno</string>
|
||||
<string name="settings_su_request_10">10 sekundi</string>
|
||||
<string name="settings_su_request_15">15 sekundi</string>
|
||||
<string name="settings_su_request_20">20 sekundi</string>
|
||||
<string name="settings_su_request_30">30 sekundi</string>
|
||||
<string name="settings_su_request_45">45 sekundi</string>
|
||||
<string name="settings_su_request_60">60 sekundi</string>
|
||||
<string name="superuser_access">Superuser pristup</string>
|
||||
<string name="auto_response">Automatski odgovor</string>
|
||||
<string name="request_timeout">Vremensko ograničenje zahtjeva</string>
|
||||
<string name="superuser_notification">Superuser obavijest</string>
|
||||
<string name="settings_su_reauth_title">Ponovno provjerite autentičnost nakon ažuriranja</string>
|
||||
<string name="settings_su_reauth_summary">Ponovno provjerite autentičnost Superuser dopuštenja nakon ažuriranja aplikacije</string>
|
||||
|
||||
<string name="multiuser_mode">Višekorisnički način rada</string>
|
||||
<string name="settings_owner_only">Samo vlasnik uređaja</string>
|
||||
<string name="settings_owner_manage">Upravljano od strane vlasnika uređaja</string>
|
||||
<string name="settings_user_independent">Neovisno o korisniku</string>
|
||||
<string name="owner_only_summary">Samo vlasnik ima root pristup</string>
|
||||
<string name="owner_manage_summary">Samo vlasnik može upravljati root pristupom i primati zahtjeve za root pristup</string>
|
||||
<string name="user_indepenent_summary">Svaki korisnik ima vlastita root pravila</string>
|
||||
|
||||
<string name="mount_namespace_mode">Postavljanje imenskog prostora</string>
|
||||
<string name="settings_ns_global">Globalni imenski prostor</string>
|
||||
<string name="settings_ns_requester">Naslijediti imenski prostor</string>
|
||||
<string name="settings_ns_isolate">Izolirani imenski prostor</string>
|
||||
<string name="global_summary">Sve root sesije koriste globalni imenski prostor</string>
|
||||
<string name="requester_summary">Root sesije će naslijediti imenski prostor tražitelja</string>
|
||||
<string name="isolate_summary">Svaka root sesija ima svoj vlastiti imenski prostor</string>
|
||||
<string name="direct_install">Izravna instalacija (preporučeno)</string>
|
||||
<string name="install_inactive_slot">Instaliraj u neaktivni utor (Nakon OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Vaš će se uređaj prisiliti pokrenuti s trenutnog neaktivnog mjesta nakon ponovnog pokretanja!\nKoristite tu opciju samo nakon što je OTA dovršena.\nContinue?</string>
|
||||
<string name="setup_title">Dodatno postavljanje</string>
|
||||
<string name="select_patch_file">Odaberite patch datoteku</string>
|
||||
<string name="patch_file_msg">Odaberite raw (*.img) ili ODIN tarfile (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Ponovno pokretanje za 5 sekundi…</string>
|
||||
<string name="flash_screen_title">Instalacija</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser zahtjev</string>
|
||||
<string name="deny">Odbij</string>
|
||||
<string name="prompt">Upitaj</string>
|
||||
<string name="prompt">Upit</string>
|
||||
<string name="grant">Odobri</string>
|
||||
<string name="su_warning">Omogućuje potpuni pristup Vašem uređaju.\nOdbijte ako niste sigurni!</string>
|
||||
<string name="su_warning">Odobren puni pristup vašem uređaju.\nOdbijte ako niste sigurni!</string>
|
||||
<string name="forever">Zauvijek</string>
|
||||
<string name="once">Jednom</string>
|
||||
<string name="tenmin">10 min</string>
|
||||
@@ -131,7 +80,161 @@
|
||||
<string name="toast">Pop-up</string>
|
||||
<string name="none">Nijedan</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="superuser_toggle_notification">Obavijesti</string>
|
||||
<string name="superuser_toggle_revoke">Opozovi</string>
|
||||
<string name="superuser_policy_none">Još nijedna aplikacija nije zatražila Superuser prava.</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Nemate zapisnika, pokušajte više upotrebljavati svoje aplikacije s omogućenim SU.</string>
|
||||
<string name="log_data_magisk_none">Zapisnici Magiska su prazni, to je čudno.</string>
|
||||
<string name="menuSaveLog">Spremi zapisnik</string>
|
||||
<string name="menuClearLog">Izbriši zapisnik</string>
|
||||
<string name="logs_cleared">Zapisnik uspješno izbrisan.</string>
|
||||
<string name="pid">PID: %1$d</string>
|
||||
<string name="target_uid">Ciljani UID: %1$d</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">SafetyNet API greška</string>
|
||||
<string name="safetynet_res_invalid">Odgovor je nevažeći</string>
|
||||
<string name="safetynet_attest_success">Uspjeh!</string>
|
||||
<string name="safetynet_attest_failure">Provjera nije uspjela!</string>
|
||||
<string name="safetynet_attest_loading">Samo trenutak…</string>
|
||||
<string name="safetynet_attest_restart">Pokušajte ponovo</string>
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Prikaži sistemske aplikacije</string>
|
||||
<string name="hide_filter_hint">Filtriraj prema nazivu</string>
|
||||
<string name="hide_scroll_up">Pomicanje gore</string>
|
||||
<string name="hide_filters">Filteri</string>
|
||||
<string name="hide_search">Traži</string>
|
||||
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(Nema podataka)</string>
|
||||
<string name="reboot_recovery">Ponovo pokreni u Recovery</string>
|
||||
<string name="reboot_bootloader">Ponovo pokreni u Bootloader</string>
|
||||
<string name="reboot_download">Ponovo pokreni u Download</string>
|
||||
<string name="reboot_edl">Ponovo pokreni u EDL</string>
|
||||
<string name="module_version_author">%1$s od %2$s</string>
|
||||
<string name="module_section_pending">Ažuriranja</string>
|
||||
<string name="module_section_pending_action">Ažuriraj sve</string>
|
||||
<string name="module_state_remove">Ukloni</string>
|
||||
<string name="module_state_restore">Vrati</string>
|
||||
<string name="module_action_install_external">Instaliraj iz pohrane</string>
|
||||
<string name="update_available">Ažuriranje dostupno</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="sorting_order">Redoslijed sortiranja</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Teme</string>
|
||||
<string name="settings_dark_mode_message">Odaberite temu koja najbolje odgovara vašem stilu!</string>
|
||||
<string name="settings_dark_mode_light">Uvijek svijetla</string>
|
||||
<string name="settings_dark_mode_system">Prati sustav</string>
|
||||
<string name="settings_dark_mode_dark">Uvijek crna</string>
|
||||
<string name="settings_download_path_title">Putanja preuzimanja</string>
|
||||
<string name="settings_download_path_message">Datoteke će biti spremljene u %1$s</string>
|
||||
<string name="settings_clear_cache_title">Obriši predmemoriju repozitorija</string>
|
||||
<string name="settings_clear_cache_summary">Obrišite predmemorirane podatke za mrežne repozitorije. To prisiljava aplikaciju da se osvježi na mreži</string>
|
||||
<string name="settings_hide_manager_title">Sakrij Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Prepakiraj Magisk Manager s nasumičnim nazivima paketa i aplikacija</string>
|
||||
<string name="settings_restore_manager_title">Vrati Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Vrati Magisk Manager s izvornim nazivima paketa i aplikacija</string>
|
||||
<string name="language">Jezik</string>
|
||||
<string name="system_default">(Zadano sustavom)</string>
|
||||
<string name="settings_check_update_title">Provjeri za ažuriranja</string>
|
||||
<string name="settings_check_update_summary">Povremeno provjeravaj ima li ažuriranja u pozadini</string>
|
||||
<string name="settings_update_channel_title">Kanal ažuriranja</string>
|
||||
<string name="settings_update_stable">Stabilna</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Vlastiti kanal</string>
|
||||
<string name="settings_update_custom_msg">Umetnite prilagođeni URL</string>
|
||||
<string name="settings_magiskhide_summary">Sakrij Magisk od različitih oblika otkrivanja</string>
|
||||
<string name="settings_hosts_title">Hostovi bez sistema</string>
|
||||
<string name="settings_hosts_summary">Podrška za hostove bez sistema za Adblock aplikacije</string>
|
||||
<string name="settings_hosts_toast">Dodan je modul hosta bez sistema</string>
|
||||
<string name="settings_app_name_hint">Novi naziv</string>
|
||||
<string name="settings_app_name_helper">Aplikacija će se prepakirati na ovaj naziv</string>
|
||||
<string name="settings_app_name_error">Nevažeći format</string>
|
||||
<string name="settings_su_app_adb">Aplikacije i ADB</string>
|
||||
<string name="settings_su_app">Samo aplikacije</string>
|
||||
<string name="settings_su_adb">Samo ADB</string>
|
||||
<string name="settings_su_disable">Onemogućeno</string>
|
||||
<string name="settings_su_request_10">10 sekundi</string>
|
||||
<string name="settings_su_request_15">15 sekundi</string>
|
||||
<string name="settings_su_request_20">20 sekundi</string>
|
||||
<string name="settings_su_request_30">30 sekundi</string>
|
||||
<string name="settings_su_request_45">45 sekundi</string>
|
||||
<string name="settings_su_request_60">60 sekundi</string>
|
||||
<string name="superuser_access">Superuser pristup</string>
|
||||
<string name="auto_response">Automatski odgovor</string>
|
||||
<string name="request_timeout">Vremensko ograničenje zahtjeva</string>
|
||||
<string name="superuser_notification">Superuser obavijest</string>
|
||||
<string name="settings_su_reauth_title">Ponovno provjerite autentičnost nakon ažuriranja</string>
|
||||
<string name="settings_su_reauth_summary">Ponovno provjerite autentičnost Superuser-a dopuštenja nakon ažuriranja aplikacije</string>
|
||||
<string name="settings_su_biometric_title">Omogući biometrijsku provjeru autentičnosti</string>
|
||||
<string name="settings_su_biometric_summary">Koristi biometrijsku provjeru autentičnosti da biste omogućili zahtjeve Superuser-a</string>
|
||||
<string name="no_biometric">Nepodržani uređaj ili nije omogućena biometrijska provjera autentičnosti</string>
|
||||
<string name="settings_customization">Prilagodba</string>
|
||||
<string name="setting_add_shortcut_summary">Dodajte lijepi prečac na početni zaslon u slučaju da je naziv i ikonu teško prepoznati nakon skrivanja aplikacije</string>
|
||||
<string name="settings_doh_title">DNS preko HTTPS-a</string>
|
||||
<string name="settings_doh_description">Zaobilazno trovanje DNS-om u nekim zemljama</string>
|
||||
|
||||
<string name="multiuser_mode">Višekorisnički način rada</string>
|
||||
<string name="settings_owner_only">Samo vlasnik uređaja</string>
|
||||
<string name="settings_owner_manage">Upravljano od strane vlasnika uređaja</string>
|
||||
<string name="settings_user_independent">Neovisno o korisniku</string>
|
||||
<string name="owner_only_summary">Samo vlasnik ima root pristup</string>
|
||||
<string name="owner_manage_summary">Samo vlasnik može upravljati root pristupom i primati zahtjeve za root pristup</string>
|
||||
<string name="user_indepenent_summary">Svaki korisnik ima vlastita root pravila</string>
|
||||
|
||||
<string name="mount_namespace_mode">Postavljanje imenskog prostora</string>
|
||||
<string name="settings_ns_global">Globalni imenski prostor</string>
|
||||
<string name="settings_ns_requester">Naslijediti imenski prostor</string>
|
||||
<string name="settings_ns_isolate">Izolirani imenski prostor</string>
|
||||
<string name="global_summary">Sve root sesije koriste globalni imenski prostor</string>
|
||||
<string name="requester_summary">Root sesije će naslijediti imenski prostor tražitelja</string>
|
||||
<string name="isolate_summary">Svaka root sesija ima svoj vlastiti imenski prostor</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Magisk Ažuriranja</string>
|
||||
<string name="progress_channel">Obavijesti o napretku</string>
|
||||
<string name="download_complete">Preuzimanje završeno</string>
|
||||
<string name="download_file_error">Pogreška pri preuzimanju datoteke</string>
|
||||
<string name="download_open_parent">Prikaži u nadređenoj mapi</string>
|
||||
<string name="download_open_self">Prikaži datoteku</string>
|
||||
<string name="magisk_update_title">Dostupno je Magisk ažuriranje!</string>
|
||||
<string name="manager_update_title">Dostupno je Magisk Manager ažuriranje! </string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Da</string>
|
||||
<string name="no">Ne</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>
|
||||
<string name="reboot">Ponovno pokreni</string>
|
||||
<string name="release_notes">Bilješke o izdavanju aplikacije</string>
|
||||
<string name="repo_cache_cleared">Predmemorija repozitorija izbrisana</string>
|
||||
<string name="flashing">Apliciranje…</string>
|
||||
<string name="done">Dovršeno!</string>
|
||||
<string name="failure">Nije uspjelo</string>
|
||||
<string name="hide_manager_title">Skrivanje Magisk Manager-a…</string>
|
||||
<string name="hide_manager_fail_toast">Skrivanje Magisk Manager-a nije uspjelo.</string>
|
||||
<string name="open_link_failed_toast">Nije pronađena aplikacija za otvaranje veze</string>
|
||||
<string name="complete_uninstall">Dovršite deinstalaciju</string>
|
||||
<string name="restore_img">Vrati Images</string>
|
||||
<string name="restore_img_msg">Vraćanje…</string>
|
||||
<string name="restore_done">Vraćanje je dovršeno!</string>
|
||||
<string name="restore_fail">Izvorna Sig. kopija ne postoji!</string>
|
||||
<string name="proprietary_title">Preuzmite vlasnički kod</string>
|
||||
<string name="proprietary_notice">Magisk Manager je FOSS i ne sadrži Googleov zaštićeni API sigurnosni kod.\n\nHoćete li dopustiti Magisk Manageru da preuzme proširenje (sadrži GoogleApiClient) za SafetyNet provjeru?</string>
|
||||
<string name="setup_fail">Postavljanje nije uspjelo</string>
|
||||
<string name="env_fix_title">Zahtijeva dodatno postavljanje</string>
|
||||
<string name="env_fix_msg">Vašem je uređaju potrebno dodatno postavljanje kako bi Magisk ispravno radio. Preuzet će se zip za postavljanje Magiska, želite li nastaviti sada?</string>
|
||||
<string name="setup_msg">Postavljanje okruženja za pokretanje…</string>
|
||||
<string name="authenticate">Potvrdi</string>
|
||||
<string name="unsupport_magisk_title">Nepodržana Magisk verzija</string>
|
||||
<string name="unsupport_magisk_msg">Ova verzija Magisk Manager-a ne podržava Magisk verziju nižu od %1$s.\n\nAplikacija će se ponašati kao da nije instaliran Magisk, ažurirajte Magisk što je prije moguće.</string>
|
||||
<string name="external_rw_permission_denied">Odobrite dopuštenje za pohranu da biste omogućili ovu funkciju</string>
|
||||
<string name="add_shortcut_title">Dodaj prečac na početni zaslon</string>
|
||||
<string name="add_shortcut_msg">Nakon skrivanja Magisk Manager-a, njegov naziv i ikonu moglo bi postati teško prepoznati. Želite li dodati lijepi prečac na početni zaslon?</string>
|
||||
<string name="app_not_found">Nije pronađena nijedna aplikacijaza obradu ove radnju</string>
|
||||
</resources>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="logs">Log</string>
|
||||
<string name="settings">Setelan</string>
|
||||
<string name="refresh">Perbarui Data Lokal</string>
|
||||
<string name="refresh">Perbarui data lokal</string>
|
||||
<string name="install">Instal</string>
|
||||
<string name="section_home">Beranda</string>
|
||||
<string name="section_theme">Tema</string>
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<!--Home-->
|
||||
<string name="no_connection">Koneksi tidak tersedia</string>
|
||||
<string name="app_changelog">Daftar perubahan</string>
|
||||
<string name="app_changelog">Catatan perubahan</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Memuat…</string>
|
||||
<string name="update">Update</string>
|
||||
@@ -22,15 +22,15 @@
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Paket</string>
|
||||
|
||||
<string name="home_notice_content">Pastikan Anda selalu menggunakan Magisk Manager dari sumber terbuka. Manager dari sumber yang tidak dikenal dapat melakukan tindak kejahatan.</string>
|
||||
<string name="home_support_title">Dukung Kami</string>
|
||||
<string name="home_notice_content">Pastikan selalu menggunakan Magisk Manager dari sumber terbuka. Manager dari sumber yang tidak dikenal dapat melakukan tindakan jahat.</string>
|
||||
<string name="home_support_title">Dukung kami</string>
|
||||
<string name="home_item_source">Sumber</string>
|
||||
<string name="home_support_content">Magisk gratis dan bersumber terbuka, dan akan selalu seperti itu. Bagaimanapun juga Anda dapat menunjukan kepedulian Anda kepada kami dengan mengirimkan sedikit donasi.</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="home_status_stub">Stub</string>
|
||||
<string name="home_installed_version">Terinstal</string>
|
||||
<string name="home_latest_version">Terbaru</string>
|
||||
<string name="invalid_update_channel">Kanal Update Tidak Valid</string>
|
||||
<string name="invalid_update_channel">Kanal update tidak valid</string>
|
||||
<string name="uninstall_magisk_title">Uninstal Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Semua modul akan dinonaktifkan/dihapus!\nRoot akan dihapus!\nData Anda berpotensi terenkripsi jika belum!</string>
|
||||
<string name="home_check_safetynet">Pemeriksaan SafetyNet</string>
|
||||
@@ -42,20 +42,21 @@
|
||||
<string name="install_options_title">Opsi</string>
|
||||
<string name="install_method_title">Metode</string>
|
||||
<string name="install_next">Berikutnya</string>
|
||||
<string name="install_start">Mari mulai</string>
|
||||
<string name="manager_download_install">Tekan untuk download dan instal</string>
|
||||
<string name="download_zip_only">Download Zip Saja</string>
|
||||
<string name="direct_install">Langsung Instal (Disarankan)</string>
|
||||
<string name="install_inactive_slot">Instal pada Slot Nonaktif (Setelah OTA)</string>
|
||||
<string name="install_start">Mulai</string>
|
||||
<string name="manager_download_install">Sentuh untuk download dan instal</string>
|
||||
<string name="download_zip_only">Download zip saja</string>
|
||||
<string name="direct_install">Langsung instal (Disarankan)</string>
|
||||
<string name="install_inactive_slot">Instal pada slot nonaktif (Setelah OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Perangkat Anda akan DIPAKSA boot ke slot yang saat ini tidak aktif setelah perangkat dinyalakan ulang!\nGunakan opsi ini hanya setelah proses OTA selesai.\nLanjutkan?</string>
|
||||
<string name="setup_title">Penyiapan Tambahan</string>
|
||||
<string name="select_patch_file">Pilih dan Tambal File</string>
|
||||
<string name="setup_title">Penyiapan tambahan</string>
|
||||
<string name="select_patch_file">Pilih dan tambal file</string>
|
||||
<string name="patch_file_msg">Pilih mentahan image (*.img) atau file tar ODIN (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Memulai kembali dalam 5 detik…</string>
|
||||
<string name="flash_screen_title">Instalasi</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Permintaan Superuser</string>
|
||||
<string name="su_request_title">Permintaan superuser</string>
|
||||
<string name="touch_filtered_warning">Karena terdapat aplikasi yang menghalangi dialog permintaan superuser, Magisk tidak dapat memverifikasi respons Anda</string>
|
||||
<string name="deny">Tolak</string>
|
||||
<string name="prompt">Ajukan</string>
|
||||
<string name="grant">Izinkan</string>
|
||||
@@ -66,14 +67,14 @@
|
||||
<string name="twentymin">20 mnt</string>
|
||||
<string name="thirtymin">30 mnt</string>
|
||||
<string name="sixtymin">60 mnt</string>
|
||||
<string name="su_allow_toast">%1$s mendapatkan hak Superuser</string>
|
||||
<string name="su_deny_toast">%1$s ditolak atas hak Superuser</string>
|
||||
<string name="su_snack_grant">Hak Superuser untuk %1$s diberikan</string>
|
||||
<string name="su_snack_deny">Hak Superuser untuk %1$s ditolak</string>
|
||||
<string name="su_snack_notif_on">Notifikasi untuk %1$s diaktifkan</string>
|
||||
<string name="su_snack_notif_off">Notifikasi untuk %1$s dinonaktifkan</string>
|
||||
<string name="su_snack_log_on">Log untuk %1$s diaktifkan</string>
|
||||
<string name="su_snack_log_off">Log untuk %1$s dinonaktifkan</string>
|
||||
<string name="su_allow_toast">%1$s mendapatkan hak superuser</string>
|
||||
<string name="su_deny_toast">%1$s ditolak atas hak superuser</string>
|
||||
<string name="su_snack_grant">Hak superuser %1$s diberikan</string>
|
||||
<string name="su_snack_deny">Hak superuser %1$s ditolak</string>
|
||||
<string name="su_snack_notif_on">Notifikasi %1$s diaktifkan</string>
|
||||
<string name="su_snack_notif_off">Notifikasi %1$s dinonaktifkan</string>
|
||||
<string name="su_snack_log_on">Pencatatan log %1$s diaktifkan</string>
|
||||
<string name="su_snack_log_off">Pencatatan log %1$s dinonaktifkan</string>
|
||||
<string name="su_revoke_title">Cabut?</string>
|
||||
<string name="su_revoke_msg">Konfirmasi untuk mencabut hak %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
@@ -102,13 +103,15 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Tampilkan aplikasi sistem</string>
|
||||
<string name="show_os_app">Tampilkan aplikasi OS</string>
|
||||
<string name="hide_filter_hint">Filter menurut nama</string>
|
||||
<string name="hide_scroll_up">Gulir ke atas</string>
|
||||
<string name="hide_filters">Filter</string>
|
||||
<string name="hide_search">Penelusuran</string>
|
||||
<string name="hide_search">Telusuri</string>
|
||||
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(Info tidak tersedia)</string>
|
||||
<string name="reboot_userspace">Nyalakan ulang secara halus</string>
|
||||
<string name="reboot_recovery">Nyalakan ke mode Recovery</string>
|
||||
<string name="reboot_bootloader">Nyalakan ke mode Bootloader</string>
|
||||
<string name="reboot_download">Nyalakan ke mode Download</string>
|
||||
@@ -119,36 +122,36 @@
|
||||
<string name="module_state_remove">Hapus</string>
|
||||
<string name="module_state_restore">Pulihkan</string>
|
||||
<string name="module_action_install_external">Instal dari penyimpanan</string>
|
||||
<string name="update_available">Update Tersedia</string>
|
||||
<string name="update_available">Update tersedia</string>
|
||||
<string name="module_installed">@string/home_installed_version</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="sorting_order">Urutan Sortir</string>
|
||||
<string name="sorting_order">Urutan sortir</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Mode Tema</string>
|
||||
<string name="settings_dark_mode_title">Mode tema</string>
|
||||
<string name="settings_dark_mode_message">Pilih mode yang paling cocok dengan gaya Anda!</string>
|
||||
<string name="settings_dark_mode_light">Selalu Terang</string>
|
||||
<string name="settings_dark_mode_system">Ikuti Sistem</string>
|
||||
<string name="settings_dark_mode_dark">Selalu Gelap</string>
|
||||
<string name="settings_dark_mode_light">Selalu terang</string>
|
||||
<string name="settings_dark_mode_system">Ikuti sistem</string>
|
||||
<string name="settings_dark_mode_dark">Selalu gelap</string>
|
||||
<string name="settings_download_path_title">Lokasi download</string>
|
||||
<string name="settings_download_path_message">File akan disimpan ke %1$s</string>
|
||||
<string name="settings_clear_cache_title">Hapus Cache Repositori</string>
|
||||
<string name="settings_clear_cache_summary">Hapus cache informasi repositori online. Tindakan ini memaksa aplikasi untuk memperbarui repositori online</string>
|
||||
<string name="settings_clear_cache_title">Hapus cache repo</string>
|
||||
<string name="settings_clear_cache_summary">Hapus cache informasi repo online. Tindakan ini memaksa aplikasi untuk memperbarui repo online</string>
|
||||
<string name="settings_hide_manager_title">Sembunyikan Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Kemas ulang Magisk Manager dengan nama paket dan nama aplikasi secara acak</string>
|
||||
<string name="settings_restore_manager_title">Pulihkan Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Pulihkan Magisk Manager dengan nama paket dan nama aplikasi aslinya</string>
|
||||
<string name="language">Bahasa</string>
|
||||
<string name="system_default">(Default Sistem)</string>
|
||||
<string name="settings_check_update_title">Periksa Update</string>
|
||||
<string name="system_default">(Default sistem)</string>
|
||||
<string name="settings_check_update_title">Periksa update</string>
|
||||
<string name="settings_check_update_summary">Periksa update secara berkala di latar belakang</string>
|
||||
<string name="settings_update_channel_title">Kanal Update</string>
|
||||
<string name="settings_update_channel_title">Kanal update</string>
|
||||
<string name="settings_update_stable">Stabil</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Kanal Khusus</string>
|
||||
<string name="settings_update_custom">Kanal khusus</string>
|
||||
<string name="settings_update_custom_msg">Masukkan URL khusus</string>
|
||||
<string name="settings_magiskhide_summary">Sembunyikan Magisk dari berbagai bentuk pendeteksian</string>
|
||||
<string name="settings_hosts_title">Host Systemless</string>
|
||||
<string name="settings_hosts_title">Host systemless</string>
|
||||
<string name="settings_hosts_summary">Dukungan host secara systemless untuk aplikasi pemblokir iklan</string>
|
||||
<string name="settings_hosts_toast">Menambahkan modul host systemless</string>
|
||||
<string name="settings_app_name_hint">Nama baru</string>
|
||||
@@ -164,45 +167,47 @@
|
||||
<string name="settings_su_request_30">30 detik</string>
|
||||
<string name="settings_su_request_45">45 detik</string>
|
||||
<string name="settings_su_request_60">60 detik</string>
|
||||
<string name="superuser_access">Akses Superuser</string>
|
||||
<string name="auto_response">Respons Otomatis</string>
|
||||
<string name="request_timeout">Batas Waktu Permintaan</string>
|
||||
<string name="superuser_notification">Notifikasi Superuser</string>
|
||||
<string name="superuser_access">Akses superuser</string>
|
||||
<string name="auto_response">Respons otomatis</string>
|
||||
<string name="request_timeout">Batas waktu permintaan</string>
|
||||
<string name="superuser_notification">Notifikasi superuser</string>
|
||||
<string name="settings_su_reauth_title">Autentikasi ulang setelah upgrade</string>
|
||||
<string name="settings_su_reauth_summary">Autentikasi ulang izin superuser setelah aplikasi diupgrade</string>
|
||||
<string name="settings_su_biometric_title">Aktifkan Autentikasi Biometrik</string>
|
||||
<string name="settings_su_reauth_summary">Autentikasi ulang izin akses superuser setelah aplikasi diupgrade</string>
|
||||
<string name="settings_su_tapjack_title">Aktifkan perlindungan tapjacking</string>
|
||||
<string name="settings_su_tapjack_summary">Dialog permintaan superuser tidak akan menanggapi masukan saat terhalangi oleh lapisan atau jendela lainnya</string>
|
||||
<string name="settings_su_biometric_title">Aktifkan autentikasi biometrik</string>
|
||||
<string name="settings_su_biometric_summary">Gunakan autentikasi biometrik untuk mengizinkan permintaan superuser</string>
|
||||
<string name="no_biometric">Perangkat tidak didukung atau setelan biometrik tidak diaktifkan</string>
|
||||
<string name="settings_customization">Penyesuaian</string>
|
||||
<string name="no_biometric">Perangkat tidak mendukung atau setelan biometrik tidak diaktifkan</string>
|
||||
<string name="settings_customization">Personalisasi</string>
|
||||
<string name="setting_add_shortcut_summary">Tambahkan pintasan yang menarik pada layar utama seandainya nama dan ikon sulit untuk dikenali setelah menyembunyikan aplikasi</string>
|
||||
<string name="settings_doh_title">DNS melalui HTTPS</string>
|
||||
<string name="settings_doh_description">Solusi untuk permasalahan DNS di beberapa negara</string>
|
||||
<string name="settings_doh_description">Solusi untuk DNS poisoning di beberapa negara</string>
|
||||
|
||||
<string name="multiuser_mode">Mode Multi Pengguna</string>
|
||||
<string name="settings_owner_only">Pemilik Perangkat Saja</string>
|
||||
<string name="settings_owner_manage">Pemilik Perangkat Mengelola</string>
|
||||
<string name="settings_user_independent">Pengguna Independen</string>
|
||||
<string name="multiuser_mode">Mode multi pengguna</string>
|
||||
<string name="settings_owner_only">Pemilik perangkat saja</string>
|
||||
<string name="settings_owner_manage">Pemilik perangkat mengelola</string>
|
||||
<string name="settings_user_independent">Pengguna independen</string>
|
||||
<string name="owner_only_summary">Hanya pemilik yang memiliki akses root</string>
|
||||
<string name="owner_manage_summary">Hanya pemilik yang dapat mengelola akses root dan menerima pesan permintaan</string>
|
||||
<string name="user_indepenent_summary">Setiap pengguna memiliki aturan root mereka sendiri</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mode Ruang-nama Mount</string>
|
||||
<string name="settings_ns_global">Ruang-nama Global</string>
|
||||
<string name="settings_ns_requester">Ruang-nama Warisan</string>
|
||||
<string name="settings_ns_isolate">Ruang-nama Terpisah</string>
|
||||
<string name="global_summary">Seluruh sesi root menggunakan ruang-nama mount global</string>
|
||||
<string name="mount_namespace_mode">Mode ruang-nama mount</string>
|
||||
<string name="settings_ns_global">Ruang-nama global</string>
|
||||
<string name="settings_ns_requester">Ruang-nama warisan</string>
|
||||
<string name="settings_ns_isolate">Ruang-nama terpisah</string>
|
||||
<string name="global_summary">Semua sesi root menggunakan ruang-nama mount 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>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Update Magisk</string>
|
||||
<string name="progress_channel">Notifikasi Berjalan</string>
|
||||
<string name="progress_channel">Notifikasi Kemajuan</string>
|
||||
<string name="download_complete">Download selesai</string>
|
||||
<string name="download_file_error">Kesalahan saat mendownload file</string>
|
||||
<string name="download_open_parent">Tampilkan dalam folder</string>
|
||||
<string name="download_open_self">Tampilkan file</string>
|
||||
<string name="magisk_update_title">Update Magisk Tersedia!</string>
|
||||
<string name="manager_update_title">Update Magisk Manager Tersedia!</string>
|
||||
<string name="magisk_update_title">Update Magisk tersedia!</string>
|
||||
<string name="manager_update_title">Update Magisk Manager tersedia!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Ya</string>
|
||||
@@ -212,29 +217,31 @@
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Nyalakan ulang</string>
|
||||
<string name="release_notes">Catatan rilis</string>
|
||||
<string name="repo_cache_cleared">Cache repositori dihapus</string>
|
||||
<string name="repo_cache_cleared">Cache repo dihapus</string>
|
||||
<string name="flashing">Memasang…</string>
|
||||
<string name="done">Selesai!</string>
|
||||
<string name="failure">Gagal</string>
|
||||
<string name="hide_manager_title">Menyembunyikan Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Gagal menyembunyikan Magisk Manager.</string>
|
||||
<string name="restore_manager_fail_toast">Gagal memulihkan Magisk Manager</string>
|
||||
<string name="open_link_failed_toast">Tidak ditemukan aplikasi untuk membuka link ini</string>
|
||||
<string name="complete_uninstall">Uninstal Penuh</string>
|
||||
<string name="restore_img">Pulihkan Image</string>
|
||||
<string name="complete_uninstall">Uninstal penuh</string>
|
||||
<string name="restore_img">Pulihkan image</string>
|
||||
<string name="restore_img_msg">Memulihkan…</string>
|
||||
<string name="restore_done">Pemulihan selesai!</string>
|
||||
<string name="restore_fail">Cadangan stock tidak ada!</string>
|
||||
<string name="proprietary_title">Download Kode Proprietari</string>
|
||||
<string name="proprietary_notice">Magisk Manager adalah aplikasi FOSS dan tidak membawa kode proprietari API SafetyNet Google.\n\nMaukah mengizinkan Magisk Manager untuk mendownload ekstensi (berisi GoogleApiClient) untuk memriksa SafetyNet?</string>
|
||||
<string name="proprietary_title">Download kode proprieter</string>
|
||||
<string name="proprietary_notice">Magisk Manager adalah aplikasi FOSS dan tidak memiliki kode proprieter API SafetyNet Google.\n\nMaukah mengizinkan Magisk Manager untuk mendownload ekstensi (berisi GoogleApiClient) untuk memeriksa SafetyNet?</string>
|
||||
<string name="setup_fail">Penyiapan gagal</string>
|
||||
<string name="env_fix_title">Perlu Penyiapan Tambahan</string>
|
||||
<string name="env_fix_title">Perlu penyiapan tambahan</string>
|
||||
<string name="env_fix_msg">Perangkat Anda memerlukan penyiapan tambahan agar Magisk bekerja dengan baik. Perangkat akan mendownload zip untuk penyiapan Magisk, apakah Anda ingin melanjutkan sekarang?</string>
|
||||
<string name="setup_msg">Memproses penyiapan lingkungan…</string>
|
||||
<string name="authenticate">Autentikasi</string>
|
||||
<string name="unsupport_magisk_title">Versi Magisk Tidak Didukung</string>
|
||||
<string name="unsupport_magisk_title">Versi Magisk tidak didukung</string>
|
||||
<string name="unsupport_magisk_msg">Versi Magisk Manager ini tidak mendukung Magisk di bawah versi %1$s.\n\nAplikasi akan berperilaku seolah-olah Magisk tidak terinstal, harap meningkatkan Magisk sesegera mungkin.</string>
|
||||
<string name="external_rw_permission_denied">Berikan izin akses ke penyimpanan untuk mengaktifkan fungsi ini</string>
|
||||
<string name="add_shortcut_title">Tambahkan pintasan ke layar utama</string>
|
||||
<string name="add_shortcut_msg">Setelah menyembunyikan Magisk Manager, nama dan ikonnya mungkin menjadi sulit untuk dikenali. Apakah Anda ingin menambahkan pintasan yang menarik pada layar utama?</string>
|
||||
<string name="app_not_found">Tidak ditemukan aplikasi untuk menangani tindakan ini</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="superuser">Accesso root</string>
|
||||
<string name="logs">Registro eventi</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="refresh">Aggiorna dati locali</string>
|
||||
@@ -17,15 +17,18 @@
|
||||
<string name="hide">Hide</string>
|
||||
<string name="app_changelog">Changelog</string>
|
||||
<string name="manager">Manager</string>
|
||||
|
||||
<string name="home_status_stub">Nascosto</string>
|
||||
<string name="home_latest_version">Ultima</string>
|
||||
<string name="home_installed_version">Installata</string>
|
||||
<string name="home_support_title">Supportaci</string>
|
||||
<string name="home_item_source">Codice sorgente</string>
|
||||
<string name="home_support_content">Magisk è e sempre sarà gratuito ed open source. Puoi comunque mostrarci il tuo apprezzamento inviando una piccola donazione.</string>
|
||||
|
||||
<string name="home_package">Pacchetto</string>
|
||||
|
||||
<string name="home_status_normal">Normale</string>
|
||||
|
||||
<string name="home_check_safetynet">Controlla SafetyNet</string>
|
||||
<string name="loading">Caricamento…</string>
|
||||
<string name="not_available">N/D</string>
|
||||
<string name="status">Stato</string>
|
||||
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
|
||||
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi!\nIl root verrà rimosso e i tuoi dati potrebbero essere criptati, nel caso non lo siano già.</string>
|
||||
@@ -34,7 +37,7 @@
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
|
||||
<string name="keep_dm_verity">Mantieni AVB 2.0/dm-verity</string>
|
||||
<string name="recovery_mode">Recovery Mode</string>
|
||||
<string name="recovery_mode">Modalità recovery</string>
|
||||
<string name="install_options_title">Opzioni</string>
|
||||
<string name="install_method_title">Metodo</string>
|
||||
<string name="install_next">Avanti</string>
|
||||
@@ -42,18 +45,19 @@
|
||||
<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="install_inactive_slot">Installa nello slot inattivo (dopo un aggiornamento OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Questo dispositivo verrà FORZATO ad avviarsi usando lo slot inattivo!\nUsa questo metodo solo dopo che un aggiornamento OTA è stato installato.\nVuoi continuare?</string>
|
||||
<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>
|
||||
<string name="flash_screen_title">Installazione</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Richiesta Superuser</string>
|
||||
<string name="su_request_title">Richiesta di accesso root</string>
|
||||
<string name="deny">Nega</string>
|
||||
<string name="prompt">Chiedi</string>
|
||||
<string name="grant">Accetta</string>
|
||||
<string name="grant">Consenti</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>
|
||||
@@ -61,22 +65,22 @@
|
||||
<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="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_allow_toast">%1$s ha ottenuto i permessi di root</string>
|
||||
<string name="su_deny_toast">%1$s non ha ottenuto i permessi di root</string>
|
||||
<string name="su_snack_grant">%1$s potrà ottenere i permessi di root</string>
|
||||
<string name="su_snack_deny">%1$s non potrà più ottenere i permessi di root</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_snack_log_on">Registrazione eventi abilitata per %1$s</string>
|
||||
<string name="su_snack_log_off">Registrazione eventi disabilitata per %1$s</string>
|
||||
<string name="su_revoke_title">Conferma revoca</string>
|
||||
<string name="su_revoke_msg">Confermi la revoca dei diritti a %1$s?</string>
|
||||
<string name="su_revoke_msg">Confermi la revoca dei permessi a %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Nessuno</string>
|
||||
|
||||
<string name="superuser_toggle_notification">Notifiche</string>
|
||||
<string name="superuser_toggle_revoke">Revoca</string>
|
||||
<string name="superuser_policy_none">Nessuna app ha ancora chiesto i permessi di superuser.</string>
|
||||
<string name="superuser_policy_none">Nessuna app ha ancora chiesto i permessi di root.</string>
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Non ci sono eventi, prova ad utilizzare un\'app che richiede i diritti di root.</string>
|
||||
@@ -90,7 +94,7 @@
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">Errore nelle API SafetyNet</string>
|
||||
<string name="safetynet_res_invalid">La risposta non è valida</string>
|
||||
<string name="safetynet_attest_success">Successo!</string>
|
||||
<string name="safetynet_attest_success">Attestazione riuscita!</string>
|
||||
<string name="safetynet_attest_failure">Attestazione fallita!</string>
|
||||
<string name="safetynet_attest_loading">Solo un secondo…</string>
|
||||
<string name="safetynet_attest_restart">Prova di nuovo</string>
|
||||
@@ -104,18 +108,19 @@
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nessuna informazione)</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>
|
||||
<string name="reboot_edl">Riavvia in EDL</string>
|
||||
<string name="reboot_recovery">Riavvia in recovery</string>
|
||||
<string name="reboot_bootloader">Riavvia in bootloader</string>
|
||||
<string name="reboot_download">Riavvia in modalità download</string>
|
||||
<string name="reboot_edl">Riavvia in modalità EDL</string>
|
||||
<string name="module_version_author">%1$s di %2$s</string>
|
||||
<string name="module_section_pending">Aggiornamenti</string>
|
||||
<string name="module_section_pending_action">Aggiorna tutto</string>
|
||||
<string name="module_state_remove">Rimuovi</string>
|
||||
<string name="module_state_restore">Ripristina</string>
|
||||
<string name="module_action_install_external">Installa dalla memoria</string>
|
||||
<string name="module_action_install_external">Installa dal dispositivo</string>
|
||||
<string name="module_installed">Installato</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="update_available">Aggiornamento disponibile</string>
|
||||
<string name="home_installed_version">Installato</string>
|
||||
<string name="sorting_order">Ordina per</string>
|
||||
|
||||
<!--Settings -->
|
||||
@@ -127,7 +132,7 @@
|
||||
<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_clear_cache_summary">Svuota la cache dei repository. In questo modo l\'app sarà costretta a recuperare le informazioni online</string>
|
||||
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome pacchetto e app casuali</string>
|
||||
<string name="settings_restore_manager_title">Ripristina Magisk Manager</string>
|
||||
@@ -139,12 +144,12 @@
|
||||
<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">Canale personalizzato</string>
|
||||
<string name="settings_update_custom_msg">Inserisci un URL personalizzato</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_magiskhide_summary">Nasconde Magisk da numerosi sistemi di rilevazione</string>
|
||||
<string name="settings_hosts_title">File hosts systemless</string>
|
||||
<string name="settings_hosts_summary">Supporto al file hosts systemless per le app che bloccano le pubblicità</string>
|
||||
<string name="settings_hosts_toast">Aggiunto modulo per il supporto al file hosts systemless</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>
|
||||
@@ -158,27 +163,27 @@
|
||||
<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="superuser_access">Accesso root</string>
|
||||
<string name="auto_response">Azione predefinita</string>
|
||||
<string name="request_timeout">Timeout richiesta</string>
|
||||
<string name="superuser_notification">Notifica Superuser</string>
|
||||
<string name="superuser_notification">Notifica di accesso root</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_reauth_summary">Richiedi nuovamente i permessi di root dopo l\'aggiornamento di un\'app</string>
|
||||
<string name="settings_su_biometric_title">Abilita autenticazione biometrica</string>
|
||||
<string name="settings_su_biometric_summary">Utilizza l\'autenticazione biometrica per accettare le richieste superuser</string>
|
||||
<string name="settings_su_biometric_summary">Utilizza l\'autenticazione biometrica per accettare le richieste di accesso root</string>
|
||||
<string name="no_biometric">Il dispositivo non è supportato o le impostazioni biometriche sono disattivate</string>
|
||||
<string name="settings_customization">Personalizzazione</string>
|
||||
<string name="setting_add_shortcut_summary">Aggiungi un collegamento alla schermata iniziale se il nome e l\'icona sono difficili da riconoscere dopo aver nascosto l\'App</string>
|
||||
<string name="setting_add_shortcut_summary">Aggiungi un collegamento alla schermata iniziale se il nome e l\'icona sono difficili da riconoscere dopo aver nascosto l\'app</string>
|
||||
<string name="settings_doh_title">DNS over HTTPS</string>
|
||||
<string name="settings_doh_description">Soluzione alternativa al DNS poisoning in alcune nazioni</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 proprie regole di root indpendenti</string>
|
||||
<string name="settings_owner_only">Solo per il proprietario del dispositivo</string>
|
||||
<string name="settings_owner_manage">Gestito dal proprietario del dispositivo</string>
|
||||
<string name="settings_user_independent">Indipendente dall\'utente</string>
|
||||
<string name="owner_only_summary">Solo il proprietario possiede i permessi di root</string>
|
||||
<string name="owner_manage_summary">Solo il proprietario può gestire l\'accesso root e ricevere le richieste dalle app</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le proprie regole di root indipendenti</string>
|
||||
|
||||
<string name="mount_namespace_mode">Modalità mount namespace</string>
|
||||
<string name="settings_ns_global">Namespace globale</string>
|
||||
@@ -206,20 +211,20 @@
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Riavvia</string>
|
||||
<string name="release_notes">Note di rilascio</string>
|
||||
<string name="repo_cache_cleared">La cache delle repository è stata svuotata</string>
|
||||
<string name="repo_cache_cleared">La cache dei repository è stata svuotata</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="complete_uninstall">Disinstallazione completa</string>
|
||||
<string name="restore_img">Ripristina Immagini</string>
|
||||
<string name="complete_uninstall">Disinstalla completamente</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="restore_fail">Non esiste un backup dell\'immagine di boot originale!</string>
|
||||
<string name="proprietary_title">Scarica codice proprietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager è 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="proprietary_notice">Magisk Manager è un software libero e open source e non contiene codice proprietario delle API SafetyNet di Google.\n\nVuoi scaricare un\'estensione (contenente GoogleApiClient) per controllare lo stato di SafetyNet?</string>
|
||||
<string name="setup_fail">Configurazione fallita</string>
|
||||
<string name="env_fix_title">Configurazione aggiuntiva richiesta</string>
|
||||
<string name="env_fix_msg">Il tuo dispositivo necessita di una configurazione aggiuntiva per far funzionare Magisk correttamente. Verrà scaricato il file zip di Magisk, vuoi procedere ora?</string>
|
||||
@@ -227,8 +232,9 @@
|
||||
<string name="authenticate">Autentica</string>
|
||||
<string name="unsupport_magisk_title">Versione di Magisk non supportata</string>
|
||||
<string name="unsupport_magisk_msg">Questa versione di Magisk Manager non supporta versioni di Magisk inferiori a %1$s.\n\nQuesta app si comporterà come se non fosse installato Magisk, che deve essere aggiornato per procedere all\'utilizzo.</string>
|
||||
<string name="external_rw_permission_denied">Concedi i permessi alla memoria per abilitare questa opzione</string>
|
||||
<string name="external_rw_permission_denied">Consenti l\'accesso alla memoria del dispositivo per abilitare questa opzione</string>
|
||||
<string name="add_shortcut_title">Aggiungi collegamento alla schermata iniziale</string>
|
||||
<string name="add_shortcut_msg">Dopo aver nascosto Magisk Manager, il suo nome e la sua icona potrebbero diventare difficili da riconoscere. Vuoi aggiungere una scorciatoia alla schermata principale?</string>
|
||||
<string name="app_not_found">Nessuna app disponibile per gestire quest\'azione</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -16,16 +16,16 @@
|
||||
<string name="app_changelog">Wijzigingslog</string>
|
||||
<string name="manager">Beheer</string>
|
||||
<string name="loading">Bezig met laden…</string>
|
||||
<string name="update">Update</string>
|
||||
<string name="update">Updaten</string>
|
||||
<string name="not_available">Niet beschikbaar</string>
|
||||
<string name="hide">Verbergen</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Pakket</string>
|
||||
|
||||
<string name="home_notice_content">Zorg ervoor dat je altijd de opensourceversie van Magisk Manager gebruikt. Magisk Manager van een onbekende bron kan schade veroorzaken.</string>
|
||||
<string name="home_notice_content">Zorg er voor dat je altijd de opensourceversie van Magisk Manager gebruikt. Magisk Manager van een onbekende bron kan schade veroorzaken.</string>
|
||||
<string name="home_support_title">Ondersteun ons</string>
|
||||
<string name="home_item_source">Broncode</string>
|
||||
<string name="home_support_content">Magisk is en zal altijd gratis en open source blijven, maar als je wilt kun je een kleine donatie doen.</string>
|
||||
<string name="home_support_content">Magisk is en zal altijd gratis en open source blijven, maar als je wilt, kun je een kleine donatie doen.</string>
|
||||
<string name="home_status_normal">Normaal</string>
|
||||
<string name="home_status_stub">Inactief</string>
|
||||
<string name="home_installed_version">Geïnstalleerd</string>
|
||||
@@ -33,6 +33,8 @@
|
||||
<string name="invalid_update_channel">Ongeldig updatekanaal</string>
|
||||
<string name="uninstall_magisk_title">Magisk deïnstalleren</string>
|
||||
<string name="uninstall_magisk_msg">Alle modules worden uitgeschakeld/verwijderd!\nRoot wordt verwijderd!\nJe gegevens worden, als ze dat nog niet waren, mogelijk versleuteld!</string>
|
||||
<string name="home_check_safetynet">SafetyNet controleren</string>
|
||||
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Afgedwongen versleuteling behouden</string>
|
||||
@@ -49,7 +51,7 @@
|
||||
<string name="install_inactive_slot_msg">Je apparaat wordt GEDWONGEN opgestart in de huidige inactieve sleuf na het herstarten!\nGebruik deze optie alleen NA het installeren van een OTA-update.\nWil je doorgaan?</string>
|
||||
<string name="setup_title">Installatie afronden</string>
|
||||
<string name="select_patch_file">Kies en patch een bestand</string>
|
||||
<string name="patch_file_msg">Kies een schijfkopie (*.img) of een ODIN-tarbestand (*.tar)</string>
|
||||
<string name="patch_file_msg">Kies een schijfkopie (*.img) of ODIN-tarbestand (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Je apparaat wordt over 5 seconden herstart…</string>
|
||||
<string name="flash_screen_title">Installatie</string>
|
||||
|
||||
@@ -60,15 +62,15 @@
|
||||
<string name="grant">Toestaan</string>
|
||||
<string name="su_warning">Verleent volledige toegang tot je apparaat.\nBij twijfel, altijd weigeren!</string>
|
||||
<string name="forever">Permanent</string>
|
||||
<string name="once">Eénmalig</string>
|
||||
<string name="once">Eenmalig</string>
|
||||
<string name="tenmin">10 min</string>
|
||||
<string name="twentymin">20 min</string>
|
||||
<string name="thirtymin">30 min</string>
|
||||
<string name="sixtymin">60 min</string>
|
||||
<string name="su_allow_toast">%1$s beschikt nu over superuserrechten</string>
|
||||
<string name="su_deny_toast">Superusermachtiging van %1$s geweigerd</string>
|
||||
<string name="su_deny_toast">Superuserrecht van %1$s geweigerd</string>
|
||||
<string name="su_snack_grant">%1$s beschikt nu over superuserrechten</string>
|
||||
<string name="su_snack_deny">Superusermachtiging van %1$s geweigerd</string>
|
||||
<string name="su_snack_deny">Superuserrecht van %1$s geweigerd</string>
|
||||
<string name="su_snack_notif_on">%1$s-meldingen ingeschakeld</string>
|
||||
<string name="su_snack_notif_off">%1$s-meldingen uitgeschakeld</string>
|
||||
<string name="su_snack_log_on">%1$s wordt nu gelogd</string>
|
||||
@@ -102,14 +104,14 @@
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Systeemapps tonen</string>
|
||||
<string name="hide_filter_hint">Filteren op naam</string>
|
||||
<string name="hide_scroll_up">Omhoogscrollen</string>
|
||||
<string name="hide_scroll_up">Omhoog scrollen</string>
|
||||
<string name="hide_filters">Filters</string>
|
||||
<string name="hide_search">Zoeken</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(geen informatie verstrekt)</string>
|
||||
<string name="reboot_recovery">Herstelmodus starten</string>
|
||||
<string name="reboot_bootloader">Opstartlader starten</string>
|
||||
<string name="reboot_recovery">Recovery starten</string>
|
||||
<string name="reboot_bootloader">Bootloader starten</string>
|
||||
<string name="reboot_download">Downloadmodus starten</string>
|
||||
<string name="reboot_edl">EDL starten</string>
|
||||
<string name="module_version_author">%1$s van %2$s</string>
|
||||
@@ -138,7 +140,6 @@
|
||||
<string name="settings_restore_manager_summary">Herstelt Magisk Manager\'s oorspronkelijke naam.</string>
|
||||
<string name="language">Taal</string>
|
||||
<string name="system_default">(systeemstandaard)</string>
|
||||
<string name="settings_check_update_title">Controleren op updates</string>
|
||||
<string name="settings_check_update_summary">Controleer automatisch op updates op de achtergrond.</string>
|
||||
<string name="settings_update_channel_title">Updatekanaal</string>
|
||||
<string name="settings_update_stable">Stabiel</string>
|
||||
@@ -228,6 +229,9 @@
|
||||
<string name="authenticate">Goedkeuren</string>
|
||||
<string name="unsupport_magisk_title">Niet-ondersteunde Magisk-versie</string>
|
||||
<string name="unsupport_magisk_msg">Deze versie van Magisk Manager heeft geen ondersteuning voor Magisk-versies ouder dan %1$s.\n\nDe app werkt, maar doet alsof Magisk niet geïnstalleerd is. Update Magisk zo spoedig mogelijk.</string>
|
||||
<string name="external_rw_permission_denied">Verleen de opslagmachtiging om deze functie te kunnen gebruiken</string>
|
||||
|
||||
<string name="external_rw_permission_denied">Verleen het opslagrecht om deze functie gebruiken</string>
|
||||
<string name="add_shortcut_title">Snelkoppeling maken op startscherm</string>
|
||||
<string name="add_shortcut_msg">Als je Magisk Manager verbergt, herken je de naam en het pictogram mogelijk niet meer. Wil je een mooie snelkoppeling plaatsen op je startscherm?</string>
|
||||
<string name="app_not_found">Er is geen app op je apparaat die deze handeling kan uitvoeren</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
<string name="status">Status</string>
|
||||
<string name="home_package">Pakiet</string>
|
||||
|
||||
<string name="home_notice_content">Zawsze upewnij się, że używasz otwartoźródłowego Magisk Managera. Manager z nieznanego źródła może wykonywać złośliwe działania.</string>
|
||||
<string name="home_notice_content">Zawsze upewnij się, że używasz otwartoźródłowego Managera Magisk. Manager z nieznanego źródła może wykonywać złośliwe działania.</string>
|
||||
<string name="home_support_title">Wesprzyj nas</string>
|
||||
<string name="home_item_source">Źródło</string>
|
||||
<string name="home_support_content">Magisk jest i zawsze będzie darmowy i otwarty. Niemniej możesz nam pokazać, że Ci zależy, wysyłając drobną darowiznę.</string>
|
||||
@@ -31,26 +31,28 @@
|
||||
<string name="home_installed_version">Zainstalowany</string>
|
||||
<string name="home_latest_version">Ostatni</string>
|
||||
<string name="invalid_update_channel">Nieprawidłowy kanał aktualizacji</string>
|
||||
<string name="uninstall_magisk_title">Odinstaluj Magiska</string>
|
||||
<string name="uninstall_magisk_msg">Wszystkie moduły zostaną wyłączone/usunięte!\nRoot zostanie usunięty!\nTwoje dane zostaną potencjalnie zaszyfrowane, jeżeli obecnie nie są!</string>
|
||||
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Wszystkie moduły zostaną wyłączone/usunięte!\nRoot zostanie usunięty!\nTwoje dane mogą zostać potencjalnie zaszyfrowane, jeśli jeszcze nie są!</string>
|
||||
<string name="home_check_safetynet">Sprawdź SafetyNet</string>
|
||||
|
||||
<!--Install-->
|
||||
<string name="keep_force_encryption">Zachowaj force encryption (wymuszenie szyfrowania)</string>
|
||||
<string name="keep_dm_verity">Zachowaj AVB 2.0/dm-verity (weryfikację procesu bootowania)</string>
|
||||
<string name="keep_dm_verity">Zachowaj AVB 2.0/dm-verity (weryfikację rozruchu)</string>
|
||||
<string name="recovery_mode">Tryb Recovery</string>
|
||||
<string name="install_options_title">Opcje</string>
|
||||
<string name="install_method_title">Metoda</string>
|
||||
<string name="install_next">Dalej</string>
|
||||
<string name="install_start">Zaczynajmy</string>
|
||||
<string name="manager_download_install">Kliknij aby pobrać i zainstalować</string>
|
||||
<string name="download_zip_only">Tylko pobierz paczkę 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_msg">Po reboocie WYMUSZONE zostanie uruchomienie twojego urządzenia z aktualnie nieaktywnego slotu!\nUżywaj tej opcji wyłącznie po zakończonej aktualizacji OTA.\nKontynuować?</string>
|
||||
<string name="manager_download_install">Naciśnij, aby pobrać i zainstalować</string>
|
||||
<string name="download_zip_only">Pobierz tylko paczkę Zip</string>
|
||||
<string name="direct_install">Bezpośrednia instalacja (zalecana)</string>
|
||||
<string name="install_inactive_slot">Zainstaluj w nieaktywnym gnieździe (po OTA)</string>
|
||||
<string name="install_inactive_slot_msg">Po restarcie twoje urządzenie zostanie ZMUSZONE do uruchomienia z aktualnie nieaktywnego gniazda!\nUżyj tej opcji wyłącznie po ukończeniu aktualizacji OTA.\nKontynuować?</string>
|
||||
<string name="setup_title">Dodatkowa konfiguracja</string>
|
||||
<string name="select_patch_file">Wybierz i zmodyfikuj plik</string>
|
||||
<string name="select_patch_file">Wybierz i załataj plik</string>
|
||||
<string name="patch_file_msg">Wybierz obraz raw (*.img) lub plik tar ODIN (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Ponowne uruchomienie za 5 sekund…</string>
|
||||
<string name="flash_screen_title">Instalacja</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Żądanie dostępu do Superusera</string>
|
||||
@@ -83,7 +85,7 @@
|
||||
|
||||
<!--Logs-->
|
||||
<string name="log_data_none">Logi są puste, spróbuj użyć aplikacji wymagających roota.</string>
|
||||
<string name="log_data_magisk_none">Logi Magiska są puste, to dziwne.</string>
|
||||
<string name="log_data_magisk_none">Logi Magisk są puste, to jest dziwne.</string>
|
||||
<string name="menuSaveLog">Zapisz log</string>
|
||||
<string name="menuClearLog">Wyczyść log</string>
|
||||
<string name="logs_cleared">Log został pomyślnie wyczyszczony.</string>
|
||||
@@ -100,17 +102,19 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Pokaż aplikacje systemowe</string>
|
||||
<string name="show_os_app">Pokaż aplikacje OS</string>
|
||||
<string name="hide_filter_hint">Filtruj według nazwy</string>
|
||||
<string name="hide_scroll_up">Przewiń do góry</string>
|
||||
<string name="hide_filters">Filtry</string>
|
||||
<string name="hide_search">Szukaj</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<!--Module -->
|
||||
<string name="no_info_provided">(Nie umieszczono informacji)</string>
|
||||
<string name="reboot_recovery">Reboot do Recovery</string>
|
||||
<string name="reboot_bootloader">Reboot do Bootloadera</string>
|
||||
<string name="reboot_download">Reboot do Download</string>
|
||||
<string name="reboot_edl">Reboot do EDL</string>
|
||||
<string name="reboot_userspace">Miękki reboot</string>
|
||||
<string name="reboot_recovery">Reboot do trybu Recovery</string>
|
||||
<string name="reboot_bootloader">Reboot do trybu Bootloader</string>
|
||||
<string name="reboot_download">Reboot do trybu Download</string>
|
||||
<string name="reboot_edl">Reboot do trybu EDL</string>
|
||||
<string name="module_version_author">%1$s by %2$s</string>
|
||||
<string name="module_section_pending">Aktualizacje</string>
|
||||
<string name="module_section_pending_action">Zaktualizuj wszystkie</string>
|
||||
@@ -119,8 +123,8 @@
|
||||
<string name="module_action_install_external">Zainstaluj z pamięci</string>
|
||||
<string name="update_available">Dostępna aktualizacja</string>
|
||||
<string name="module_installed">Zainstalowane</string>
|
||||
<string name="module_section_online">Online</string>
|
||||
<string name="sorting_order">Kolejność sortowania</string>
|
||||
<string name="external_rw_permission_denied">Zezwól na dostęp do pamięci wewnętrznej, aby włączyć tę funkcjonalność.</string>
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Tryb motywu</string>
|
||||
@@ -129,26 +133,26 @@
|
||||
<string name="settings_dark_mode_system">Ustawienie systemowe</string>
|
||||
<string name="settings_dark_mode_dark">Zawsze ciemny</string>
|
||||
<string name="settings_download_path_title">Ścieżka pobierania plików</string>
|
||||
<string name="settings_download_path_message">Pliki pobrane przez Managera będą zapisywane do %1$s</string>
|
||||
<string name="settings_clear_cache_title">Wyczyść pamięć cache repozytorium</string>
|
||||
<string name="settings_clear_cache_summary">Wyczyść zapisane informacje o repozytoriach. Wymuszone zostanie odświeżenie informacji online</string>
|
||||
<string name="settings_hide_manager_title">Ukryj Magisk Managera</string>
|
||||
<string name="settings_hide_manager_summary">Przepakuj Magisk Managera z losowymi nazwami pakietu oraz aplikacji</string>
|
||||
<string name="settings_restore_manager_title">Przywróć Magisk Managera</string>
|
||||
<string name="settings_restore_manager_summary">Przywróć Magisk Managera z oryginalnymi nazwami pakietu oraz aplikacji</string>
|
||||
<string name="settings_download_path_message">Pliki zostaną zapisane do %1$s</string>
|
||||
<string name="settings_clear_cache_title">Wyczyść pamięć podr. repozytoriów</string>
|
||||
<string name="settings_clear_cache_summary">Wyczyść informacje z pamięci podr. dotyczące repozytoriów. Zmusza to aplikację do odświeżenia informacji online</string>
|
||||
<string name="settings_hide_manager_title">Ukryj Managera Magisk</string>
|
||||
<string name="settings_hide_manager_summary">Przepakuj Managera Magisk z losowymi nazwami pakietu i aplikacji</string>
|
||||
<string name="settings_restore_manager_title">Przywróć Managera Magisk</string>
|
||||
<string name="settings_restore_manager_summary">Przywróć Managera Magisk z oryginalnymi nazwami pakietu i aplikacji</string>
|
||||
<string name="language">Język</string>
|
||||
<string name="system_default">(Domyślny systemowy)</string>
|
||||
<string name="settings_check_update_title">Sprawdzanie aktualizacji</string>
|
||||
<string name="settings_check_update_summary">Regularnie sprawdzaj dostępność aktualizacji w tle</string>
|
||||
<string name="settings_check_update_summary">Okresowo sprawdzaj dostępność aktualizacji w tle</string>
|
||||
<string name="settings_update_channel_title">Kanał aktualizacji</string>
|
||||
<string name="settings_update_stable">Stabilny</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Własny</string>
|
||||
<string name="settings_update_custom_msg">Wprowadź adres URL własnego repozytorium</string>
|
||||
<string name="settings_magiskhide_summary">Ukryj Magiska przed wieloma metodami detekcji</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Włącz wsparcie Systemless dla aplikacji typu Adblock</string>
|
||||
<string name="settings_hosts_toast">Dodano moduł Systemless Hosts</string>
|
||||
<string name="settings_update_custom">Własny kanał</string>
|
||||
<string name="settings_update_custom_msg">Wprowadź adres URL własnego kanału</string>
|
||||
<string name="settings_magiskhide_summary">Ukryj Magisk przed różnymi formami detekcji</string>
|
||||
<string name="settings_hosts_title">Hosty Systemless</string>
|
||||
<string name="settings_hosts_summary">Wsparcie hostów Systemless dla aplikacji typu Adblock</string>
|
||||
<string name="settings_hosts_toast">Dodano moduł hostów Systemless</string>
|
||||
<string name="settings_app_name_hint">Nowa nazwa</string>
|
||||
<string name="settings_app_name_helper">Aplikacja zostanie przepakowana do tej nazwy</string>
|
||||
<string name="settings_app_name_error">Błędny format</string>
|
||||
@@ -167,18 +171,21 @@
|
||||
<string name="request_timeout">Limit czasu żądania</string>
|
||||
<string name="superuser_notification">Powiadomienia Superusera</string>
|
||||
<string name="settings_su_reauth_title">Ponowienie uwierzytelniania po aktualizacji</string>
|
||||
<string name="settings_su_reauth_summary">Ponowienie dostępu do uprawnień Superusera po aktualizacji aplikacji</string>
|
||||
<string name="settings_su_reauth_summary">Ponowienie dostępu do uprawnień Superusera po uaktualnieniu aplikacji</string>
|
||||
<string name="settings_su_biometric_title">Uwierzytelnianie biometryczne</string>
|
||||
<string name="settings_su_biometric_summary">Używaj uwierzytelniania biometrycznego (np. odcisku palca) aby przyznać uprawnienia Superusera</string>
|
||||
<string name="no_biometric">Urządzenie jest nieobsługiwane lub ustawienia biometryczne nie są włączone</string>
|
||||
<string name="settings_customization">Personalizacja</string>
|
||||
<string name="setting_add_shortcut_summary">Dodaj ładny skrót na ekranie głównym na wypadek, gdyby nazwa i ikona były trudne do rozpoznania po ukryciu aplikacji</string>
|
||||
<string name="settings_doh_title">DNS over HTTPS</string>
|
||||
<string name="settings_doh_description">Zapobiegaj zatruwaniu DNS (DNS poisoning) w niektórych krajach</string>
|
||||
|
||||
<string name="multiuser_mode">Tryb wielu użytkowników (Multiuser)</string>
|
||||
<string name="settings_owner_only">Tylko właściciel urządzenia</string>
|
||||
<string name="settings_owner_manage">Zarządzanie przez właściciela urządzenia</string>
|
||||
<string name="settings_user_independent">Niezależni użytkownicy</string>
|
||||
<string name="owner_only_summary">Tylko właściciel ma dostęp do roota</string>
|
||||
<string name="owner_manage_summary">Tylko właściciel może zarządzać ustawieniami dostępu do roota i otrzymywać zapytania o dostęp</string>
|
||||
<string name="owner_manage_summary">Tylko właściciel może zarządzać ustawieniami dostępu do roota i otrzymywać żądania dostępu</string>
|
||||
<string name="user_indepenent_summary">Każdy użytkownik ma niezależne ustawienia dostępu do roota</string>
|
||||
|
||||
<string name="mount_namespace_mode">Tryb przestrzeni nazw montowania</string>
|
||||
@@ -186,47 +193,52 @@
|
||||
<string name="settings_ns_requester">Dziedziczona przestrzeń nazw</string>
|
||||
<string name="settings_ns_isolate">Izolowana przestrzeń nazw</string>
|
||||
<string name="global_summary">Wszystkie sesje roota będą używać globalnej przestrzeni nazw montowania</string>
|
||||
<string name="requester_summary">Sesje roota odziedziczą przestrzeń nazw od wywołującego</string>
|
||||
<string name="isolate_summary">Każda sesja roota dostanie własną, izolowaną przestrzeń nazw</string>
|
||||
<string name="requester_summary">Sesje roota odziedziczą przestrzeń nazw od żądającego</string>
|
||||
<string name="isolate_summary">Każda sesja roota otrzyma własną, izolowaną przestrzeń nazw</string>
|
||||
|
||||
<!--Notifications-->
|
||||
<string name="update_channel">Aktualizacja Magiska</string>
|
||||
<string name="progress_channel">Informacja o postępie</string>
|
||||
<string name="update_channel">Aktualizacja Magisk</string>
|
||||
<string name="progress_channel">Powiadomienia o postępach</string>
|
||||
<string name="download_complete">Pobieranie zakończone</string>
|
||||
<string name="download_file_error">Błąd pobierania pliku</string>
|
||||
<string name="download_open_parent">Pokaż w katalogu nadrzędnym</string>
|
||||
<string name="download_open_self">Pokaż plik</string>
|
||||
<string name="magisk_update_title">Aktualizacja Magiska dostępna!</string>
|
||||
<string name="manager_update_title">Aktualizacja Magisk Managera dostępna!</string>
|
||||
<string name="magisk_update_title">Aktualizacja Magisk dostępna!</string>
|
||||
<string name="manager_update_title">Aktualizacja Managera Magisk dostępna!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="yes">Tak</string>
|
||||
<string name="no">Nie</string>
|
||||
<string name="repo_install_title">Instalacja %1$s</string>
|
||||
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
|
||||
<string name="repo_install_msg">Czy chcesz teraz zainstalować %1$s ?</string>
|
||||
<string name="download">Pobierz</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
<string name="release_notes">Lista zmian</string>
|
||||
<string name="repo_cache_cleared">Pamięć cache repozytorium została wyczyszczona</string>
|
||||
<string name="repo_cache_cleared">Wyczyszczono pamięć podręczną repozytoriów</string>
|
||||
<string name="flashing">Flashowanie…</string>
|
||||
<string name="done">Gotowe!</string>
|
||||
<string name="failure">Błąd</string>
|
||||
<string name="hide_manager_title">Ukrywanie Magisk Managera…</string>
|
||||
<string name="hide_manager_fail_toast">Błąd ukrycia Magisk Managera.</string>
|
||||
<string name="hide_manager_title">Ukrywanie Managera Magisk…</string>
|
||||
<string name="hide_manager_fail_toast">Ukrycie Managera Magisk nie powiodło się</string>
|
||||
<string name="restore_manager_fail_toast">Przywrócenie Managera Magisk nie powiodło się</string>
|
||||
<string name="open_link_failed_toast">Nie znaleziono aplikacji do otwarcia linku</string>
|
||||
<string name="complete_uninstall">Odinstaluj całkowicie</string>
|
||||
<string name="restore_img">Przywróć obrazy</string>
|
||||
<string name="restore_img_msg">Przywracanie…</string>
|
||||
<string name="restore_done">Przywracanie zakończone!</string>
|
||||
<string name="restore_fail">Kopia zapasowa nie istnieje!</string>
|
||||
<string name="proprietary_title">Pobierz własny kod</string>
|
||||
<string name="proprietary_notice">Magisk Manager to FOSS (wolne i otwarte oprogramowanie) i nie zawiera własnościowego kodu Google - SafetyNet API.\n\nCzy zezwolić Magisk Managerowi na pobranie rozszerzenia (zawierającego GoogleApiClient) w celu sprawdzenia SafetyNet?</string>
|
||||
<string name="proprietary_title">Pobierz kod własnościowy</string>
|
||||
<string name="proprietary_notice">Magisk Manager to FOSS (wolne i otwarte oprogramowanie) i nie zawiera własnościowego kodu Google - SafetyNet API.\n\nCzy chcesz zezwolić Managerowi Magisk na pobranie rozszerzenia (zawierającego GoogleApiClient) w celu sprawdzenia SafetyNet?</string>
|
||||
<string name="setup_fail">Konfiguracja nieudana</string>
|
||||
<string name="env_fix_title">Wymaga dodatkowej konfiguracji</string>
|
||||
<string name="env_fix_msg">Twoje urządzenie potrzebuje dodatkowej konfiguracji, aby Magisk działał prawidłowo. Spowoduje to pobranie paczki instalacyjnej Magisk, czy chcesz kontynuować?</string>
|
||||
<string name="env_fix_msg">Twoje urządzenie potrzebuje dodatkowej konfiguracji, aby Magisk działał poprawnie. Spowoduje to pobranie pliku instalacyjnego Magisk, czy chcesz kontynuować?</string>
|
||||
<string name="setup_msg">Uruchamianie środowiska konfiguracji…</string>
|
||||
<string name="authenticate">Uwierzytelnianie</string>
|
||||
<string name="unsupport_magisk_title">Nieobsługiwana wersja Magiska</string>
|
||||
<string name="unsupport_magisk_msg">Ta wersja Magisk Managera nie obsługuje wersji Magiska poniżej %1$s.\n\nAplikacja będzie działać tak, jakby Magisk nie był zainstalowany. Zaktualizuj Magiska jak najszybciej.</string>
|
||||
<string name="unsupport_magisk_title">Nieobsługiwana wersja Magisk</string>
|
||||
<string name="unsupport_magisk_msg">Ta wersja Managera Magisk nie obsługuje wersji Magisk niższej niż %1$s.\n\nAplikacja będzie się zachowywać tak, jakby Magisk nie był zainstalowany. Zaktualizuj Magisk jak najszybciej.</string>
|
||||
<string name="external_rw_permission_denied">Zezwól na dostęp do pamięci wewnętrznej, aby włączyć tę funkcję.</string>
|
||||
<string name="add_shortcut_title">Utwórz skrót na ekranie głównym</string>
|
||||
<string name="add_shortcut_msg">Po ukryciu Managera Magisk, jego nazwa i ikona mogą stać się trudne do rozpoznania. Czy chcesz dodać ładny skrót na ekranie głównym?</string>
|
||||
<string name="app_not_found">Nie znaleziono aplikacji do wykonania tej czynności</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -5,6 +5,7 @@
|
||||
<string name="superuser">Superusuário</string>
|
||||
<string name="logs">Registros</string>
|
||||
<string name="settings">Configurações</string>
|
||||
<string name="refresh">Atualizar Dados Locais</string>
|
||||
<string name="install">Instalar</string>
|
||||
<string name="section_home">Início</string>
|
||||
<string name="section_theme">Temas</string>
|
||||
@@ -23,8 +24,6 @@
|
||||
<string name="home_package">Pacote</string>
|
||||
<string name="home_status_normal">Normal</string>
|
||||
<string name="invalid_update_channel">Canal de atualização inválido</string>
|
||||
<string name="safetynet_api_error">Erro do API SafetyNet</string>
|
||||
<string name="safetynet_res_invalid">A resposta é inválida</string>
|
||||
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Todos os módulos serão desativados/removidos!\nA raiz será removida!\nSeus dados potencialmente criptografados, se ainda não estiverem!</string>
|
||||
<string name="update">Atualização</string>
|
||||
@@ -46,6 +45,7 @@
|
||||
<string name="select_patch_file">Selecione e corrija um arquivo</string>
|
||||
<string name="patch_file_msg">Selecione uma imagem bruta (*.img) ou um arquivo tarin ODIN (*.tar)</string>
|
||||
<string name="reboot_delay_toast">Reiniciando em 5 segundos…</string>
|
||||
<string name="flash_screen_title">Instalação</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Solicitação de Superusuário</string>
|
||||
@@ -86,6 +86,8 @@
|
||||
<string name="target_uid">Alvo UID: %1$d</string>
|
||||
|
||||
<!--SafetyNet-->
|
||||
<string name="safetynet_api_error">Erro API SafetyNet</string>
|
||||
<string name="safetynet_res_invalid">A resposta é inválida</string>
|
||||
<string name="safetynet_attest_success">Sucesso!</string>
|
||||
<string name="safetynet_attest_failure">O certificado falhou!</string>
|
||||
<string name="safetynet_attest_loading">Aguarde…</string>
|
||||
@@ -113,6 +115,7 @@
|
||||
<string name="update_available">Atualização disponível</string>
|
||||
<string name="home_installed_version">Instalado</string>
|
||||
<string name="sorting_order">Ordem de classificação</string>
|
||||
|
||||
|
||||
<!--Settings -->
|
||||
<string name="settings_dark_mode_title">Modo de tema</string>
|
||||
@@ -121,6 +124,7 @@
|
||||
<string name="settings_dark_mode_system">Baseado no Sistema</string>
|
||||
<string name="settings_dark_mode_dark">Sempre Escuro</string><![CDATA[
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -170,7 +174,10 @@
|
||||
<string name="settings_su_biometric_summary">Use a autenticação biométrica para permitir solicitações de superusuário</string>
|
||||
<string name="no_biometric">Dispositivo não suportado ou nenhuma configuração biométrica está ativada</string>
|
||||
<string name="settings_customization">Personalizações</string>
|
||||
|
||||
<string name="setting_add_shortcut_summary">Adicione um atalho na tela inicial, caso o nome e o ícone sejam difíceis de reconhecer logo após ocultar o aplicativo</string>
|
||||
<string name="settings_doh_title">DNS sobre HTTPS</string>
|
||||
<string name="settings_doh_description">Solução alternativa para envenenamento de DNS em alguns países</string>
|
||||
|
||||
<string name="multiuser_mode">Modo multiusuário</string>
|
||||
<string name="settings_owner_only">Somente proprietário do dispositivo</string>
|
||||
<string name="settings_owner_manage">Gerenciado pelo proprietário do dispositivo</string>
|
||||
@@ -227,4 +234,8 @@
|
||||
<string name="authenticate">Autenticar</string>
|
||||
<string name="unsupport_magisk_title">Versão Magisk não suportada</string>
|
||||
<string name="unsupport_magisk_msg">Esta versão do Magisk Manager não suporta a versão Magisk inferior a %1$s. \n\nO aplicativo se comportará como se não houvesse Magisk instalado, atualize o Magisk o mais rápido possível.</string>
|
||||
<string name="add_shortcut_title">Adicionar atalho à tela inicial</string>
|
||||
<string name="add_shortcut_msg">Depois de ocultar o Magisk Manager, seu nome e ícone podem se tornar difíceis de reconhecer. Você quer adicionar um atalho bonito para a tela inicial?</string>
|
||||
<string name="app_not_found">Nenhum aplicativo encontrado para realizar esta ação</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
<string name="manager">Manager</string>
|
||||
<string name="loading">Загрузка…</string>
|
||||
<string name="update">Обновить</string>
|
||||
<string name="not_available">Н/Д</string>
|
||||
<string name="not_available">N/A</string>
|
||||
<string name="hide">Скрыть</string>
|
||||
<string name="status">Режим</string>
|
||||
<string name="home_package">Имя пакета</string>
|
||||
@@ -56,6 +56,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Запрос прав суперпользователя</string>
|
||||
<string name="touch_filtered_warning">Обнаружены наложения экрана, обработка запроса недоступна</string>
|
||||
<string name="deny">Запретить</string>
|
||||
<string name="prompt">Запросить</string>
|
||||
<string name="grant">Разрешить</string>
|
||||
@@ -102,6 +103,7 @@
|
||||
|
||||
<!--MagiskHide-->
|
||||
<string name="show_system_app">Системные приложения</string>
|
||||
<string name="show_os_app">Встроенные приложения</string>
|
||||
<string name="hide_filter_hint">Введите имя</string>
|
||||
<string name="hide_scroll_up">Вверх</string>
|
||||
<string name="hide_filters">Сортировка</string>
|
||||
@@ -109,11 +111,12 @@
|
||||
|
||||
<!--Module-->
|
||||
<string name="no_info_provided">(Нет информации)</string>
|
||||
<string name="reboot_userspace">Перезапуск оболочки</string>
|
||||
<string name="reboot_recovery">Перезагрузка в Recovery</string>
|
||||
<string name="reboot_bootloader">Перезагрузка в Bootloader</string>
|
||||
<string name="reboot_download">Перезагрузка в Download</string>
|
||||
<string name="reboot_edl">Перезагрузка в EDL</string>
|
||||
<string name="module_version_author">Версия: %1$s\nАвтор: %2$s</string>
|
||||
<string name="module_version_author">%1$s от %2$s</string>
|
||||
<string name="module_section_pending">Обновления</string>
|
||||
<string name="module_section_pending_action">Обновить всё</string>
|
||||
<string name="module_state_remove">Удалить</string>
|
||||
@@ -170,6 +173,8 @@
|
||||
<string name="superuser_notification">Уведомления суперпользователя</string>
|
||||
<string name="settings_su_reauth_title">Повторная аутентификация</string>
|
||||
<string name="settings_su_reauth_summary">Повторный запрос прав суперпользователя после обновления приложений</string>
|
||||
<string name="settings_su_tapjack_title">Защита от перехвата ввода</string>
|
||||
<string name="settings_su_tapjack_summary">Окно запроса прав суперпользователя будет неактивно пока активированы наложения экрана</string>
|
||||
<string name="settings_su_biometric_title">Биометрическая аутентификация</string>
|
||||
<string name="settings_su_biometric_summary">Использовать биометрическую аутентификацию для запросов прав суперпользователя</string>
|
||||
<string name="no_biometric">Функция не поддерживается устройством или не заданы настройки блокировки экрана</string>
|
||||
@@ -218,6 +223,7 @@
|
||||
<string name="failure">Ошибка!</string>
|
||||
<string name="hide_manager_title">Скрытие Magisk Manager…</string>
|
||||
<string name="hide_manager_fail_toast">Не удалось пересобрать Magisk Manager</string>
|
||||
<string name="restore_manager_fail_toast">Не удалось восстановить Magisk Manager</string>
|
||||
<string name="open_link_failed_toast">Приложения для открытия ссылки не найдены</string>
|
||||
<string name="complete_uninstall">Полное удаление</string>
|
||||
<string name="restore_img">Восстановить разделы</string>
|
||||
@@ -236,5 +242,6 @@
|
||||
<string name="external_rw_permission_denied">Пожалуйста, предоставьте доступ к хранилищу!</string>
|
||||
<string name="add_shortcut_title">Создание ярлыка</string>
|
||||
<string name="add_shortcut_msg">После скрытия Magisk Manager его имя и иконка могут быть неудобны для восприятия. Хотите создать ярлык на рабочем столе?</string>
|
||||
<string name="app_not_found">Приложение для обработки этого действия не найдено</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -56,6 +56,7 @@
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Požiadavka superužívateľa</string>
|
||||
<string name="touch_filtered_warning">Pretože aplikácia zakrýva požiadavku superužívateľa, Magisk nemôže overiť vašu odpoveď</string>
|
||||
<string name="deny">Zamietnuť</string>
|
||||
<string name="prompt">Výzva</string>
|
||||
<string name="grant">Udeliť</string>
|
||||
@@ -102,6 +103,7 @@
|
||||
|
||||
<!-- MagiskHide -->
|
||||
<string name="show_system_app">Zobraziť systémové aplikácie</string>
|
||||
<string name="show_os_app">Zobraziť aplikácie OS</string>
|
||||
<string name="hide_filter_hint">Filtrovať podľa názvu</string>
|
||||
<string name="hide_scroll_up">Posunúť nahor</string>
|
||||
<string name="hide_filters">Filtre</string>
|
||||
@@ -109,6 +111,7 @@
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nie sú k dispozícii žiadne informácie)</string>
|
||||
<string name="reboot_userspace">Softvérový reštart</string>
|
||||
<string name="reboot_recovery">Reštartovať do Recovery</string>
|
||||
<string name="reboot_bootloader">Reštartovať do Bootloader</string>
|
||||
<string name="reboot_download">Reštartovať do Download</string>
|
||||
@@ -172,6 +175,8 @@
|
||||
<string name="superuser_notification">Upozornenia Superužívateľa</string>
|
||||
<string name="settings_su_reauth_title">Overenie autentifikácie po upgrade</string>
|
||||
<string name="settings_su_reauth_summary">Overí autentifikáciu oprávnení Superužívateľa po upgrade aplikácie</string>
|
||||
<string name="settings_su_tapjack_title">Povoliť ochranu pred tapjackingom</string>
|
||||
<string name="settings_su_tapjack_summary">Dialógové okno superužívateľa nebude reagovať na zadanie, ak je zakryté alebo prekryté iným oknom</string>
|
||||
<string name="settings_su_biometric_title">Povoliť biometrické overenie</string>
|
||||
<string name="settings_su_biometric_summary">Použije biometrickú autentifikáciu na povolenie žiadostí Superužívateľa</string>
|
||||
<string name="no_biometric">Nepodporované zariadenie alebo žiadne biometrické nastavenia nie sú povolené</string>
|
||||
@@ -218,8 +223,9 @@
|
||||
<string name="flashing">Flashovanie...</string>
|
||||
<string name="done">Hotovo!</string>
|
||||
<string name="failure">Zlyhalo</string>
|
||||
<string name="hide_manager_title">Skrytie Magisk Managera…</string>
|
||||
<string name="hide_manager_fail_toast">Skrytie Magisk Manager zlyhalo.</string>
|
||||
<string name="hide_manager_title">Skrývanie Magisk Managera…</string>
|
||||
<string name="hide_manager_fail_toast">Skrytie Magisk Managera zlyhalo</string>
|
||||
<string name="restore_manager_fail_toast">Obnovenie Magisk Managera zlyhalo</string>
|
||||
<string name="open_link_failed_toast">Nepodarilo sa nájsť vhodnú aplikáciu na otvorenie odkazu</string>
|
||||
<string name="complete_uninstall">Úplne odinštalovať</string>
|
||||
<string name="restore_img">Obnoviť obrazy</string>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user