mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 05:47:27 +00:00
Compare commits
215 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a54eaf5371 | ||
![]() |
8032bd4bb9 | ||
![]() |
ea1beec2f7 | ||
![]() |
05f2f6820e | ||
![]() |
0f5f15a5ce | ||
![]() |
14ac37e8a5 | ||
![]() |
1fae89cbb6 | ||
![]() |
8b4008798f | ||
![]() |
fd4faf59b8 | ||
![]() |
109891d668 | ||
![]() |
bdea796121 | ||
![]() |
c8813c05c9 | ||
![]() |
1cff08ce5d | ||
![]() |
a868118f6f | ||
![]() |
e5c62f5750 | ||
![]() |
4084e8790b | ||
![]() |
8d931dd773 | ||
![]() |
25d6366297 | ||
![]() |
08cd5b81d1 | ||
![]() |
5d3a8a5b1a | ||
![]() |
79b84da4b8 | ||
![]() |
68b07c5913 | ||
![]() |
553db9124d | ||
![]() |
b495f37299 | ||
![]() |
1915547594 | ||
![]() |
03de29164a | ||
![]() |
86d8b50547 | ||
![]() |
7b04386162 | ||
![]() |
07bfdf3e4d | ||
![]() |
d510224e2a | ||
![]() |
e658f9297d | ||
![]() |
2b502e9a0f | ||
![]() |
59141f9bbe | ||
![]() |
3af66b72f2 | ||
![]() |
422c24bd68 | ||
![]() |
f0f87c8eb9 | ||
![]() |
80dad54119 | ||
![]() |
56a76df28e | ||
![]() |
ee2c801fe0 | ||
![]() |
fc314cc248 | ||
![]() |
fe231a4c80 | ||
![]() |
2e2bbe0a7f | ||
![]() |
857e6e8345 | ||
![]() |
3402981ada | ||
![]() |
f401e577e5 | ||
![]() |
0241a50c6f | ||
![]() |
2a2e1236fc | ||
![]() |
9b170f2b4f | ||
![]() |
51e9ff59de | ||
![]() |
2977dbcded | ||
![]() |
ac60b51035 | ||
![]() |
4c2f33a089 | ||
![]() |
3b071116ac | ||
![]() |
a9f265a591 | ||
![]() |
5b62fc8103 | ||
![]() |
0598f5f89a | ||
![]() |
f723427b8b | ||
![]() |
f69a004c1c | ||
![]() |
1134b18a8b | ||
![]() |
2e4aa507f7 | ||
![]() |
5fb96cdcf4 | ||
![]() |
e8cba3524e | ||
![]() |
7e6b5363f1 | ||
![]() |
29457a1d28 | ||
![]() |
731455f164 | ||
![]() |
b01a8cace6 | ||
![]() |
72db5b4fac | ||
![]() |
ddfd42994e | ||
![]() |
2a9ff9c5ef | ||
![]() |
6d49f05356 | ||
![]() |
85a5e62e36 | ||
![]() |
e67965a381 | ||
![]() |
ec4723096f | ||
![]() |
762b678d24 | ||
![]() |
38fcc57bbf | ||
![]() |
c8c57c74cc | ||
![]() |
0784448c69 | ||
![]() |
de0064af47 | ||
![]() |
baae1fc84f | ||
![]() |
2ab999f4ca | ||
![]() |
c9f390d6e0 | ||
![]() |
af05922ecc | ||
![]() |
299edbf3ab | ||
![]() |
c8abed9d48 | ||
![]() |
3622c49ce1 | ||
![]() |
0462e9a7d9 | ||
![]() |
c3a6091908 | ||
![]() |
ab5fedda0b | ||
![]() |
ba70269398 | ||
![]() |
77fd5fa7de | ||
![]() |
ab74290fe3 | ||
![]() |
3aad9d8166 | ||
![]() |
572e078d87 | ||
![]() |
ee4548230b | ||
![]() |
96b93bd876 | ||
![]() |
927f69fe30 | ||
![]() |
7e9ad5927a | ||
![]() |
6d6b07865e | ||
![]() |
376e7977f0 | ||
![]() |
83ae66daea | ||
![]() |
89e0be0099 | ||
![]() |
ef40c1212e | ||
![]() |
3a2a2a4ffa | ||
![]() |
9592a69986 | ||
![]() |
89be07e1f2 | ||
![]() |
c61c3ae0e9 | ||
![]() |
817350c8c5 | ||
![]() |
3603b7c82b | ||
![]() |
5743c72cca | ||
![]() |
4cdd66ceff | ||
![]() |
d3947d2cfa | ||
![]() |
07718b994a | ||
![]() |
ef9d463bd7 | ||
![]() |
8745c7884e | ||
![]() |
b6965105b7 | ||
![]() |
3d269fe8be | ||
![]() |
be5f00aa1a | ||
![]() |
59ba350f34 | ||
![]() |
803c5377a6 | ||
![]() |
7c12bf7fa1 | ||
![]() |
ca35a9681f | ||
![]() |
9fe5f37337 | ||
![]() |
0742901cd2 | ||
![]() |
5e4d2dedbe | ||
![]() |
411ea56a3e | ||
![]() |
cda57dd4b4 | ||
![]() |
4351de503f | ||
![]() |
6339ba6bfb | ||
![]() |
ef6677f43d | ||
![]() |
a7824af5a8 | ||
![]() |
1eb7d7b7a8 | ||
![]() |
11c33d4447 | ||
![]() |
b8a3cc8b60 | ||
![]() |
27c688252d | ||
![]() |
3e2afd4b1d | ||
![]() |
f45b0686d2 | ||
![]() |
1f3f881f81 | ||
![]() |
ceb51bb14f | ||
![]() |
3e22573d8d | ||
![]() |
79418a3767 | ||
![]() |
40d4683de1 | ||
![]() |
79e5b54ec7 | ||
![]() |
bd81923f2f | ||
![]() |
69560b8ad7 | ||
![]() |
dc413e7b73 | ||
![]() |
7fc00c446b | ||
![]() |
2efc423cf8 | ||
![]() |
8ec3086cdd | ||
![]() |
5fc7079023 | ||
![]() |
bfbd254be7 | ||
![]() |
f8ea43466c | ||
![]() |
75ab1fa570 | ||
![]() |
bf4a46d57c | ||
![]() |
1046dd5eda | ||
![]() |
f9e32a119a | ||
![]() |
dbb8b8a439 | ||
![]() |
2a65c3dc8f | ||
![]() |
f17ec9e9d7 | ||
![]() |
675d6d8328 | ||
![]() |
6dc9ccad75 | ||
![]() |
6add02702b | ||
![]() |
958d6377e3 | ||
![]() |
9954154ca2 | ||
![]() |
4ecbf8c12c | ||
![]() |
fc8a3c5fb4 | ||
![]() |
01e7dff1a0 | ||
![]() |
018c0064cd | ||
![]() |
c2b016370b | ||
![]() |
fc791b4371 | ||
![]() |
f76bb009f4 | ||
![]() |
8a1292b295 | ||
![]() |
d7d80d3fc1 | ||
![]() |
41b01003fd | ||
![]() |
6557070ae1 | ||
![]() |
e7e580e177 | ||
![]() |
dd9ddd2019 | ||
![]() |
74aae523ba | ||
![]() |
48c40f9516 | ||
![]() |
e0e7674715 | ||
![]() |
e1a65276b9 | ||
![]() |
469adc85ad | ||
![]() |
e1b181ca4e | ||
![]() |
a4f0fbf8b7 | ||
![]() |
190cdaddf8 | ||
![]() |
5c4ba13839 | ||
![]() |
e62630cf3e | ||
![]() |
36fe7846c0 | ||
![]() |
8d150dd67a | ||
![]() |
506df00d81 | ||
![]() |
a9121fa28f | ||
![]() |
d5a56d9e85 | ||
![]() |
acf7c0c665 | ||
![]() |
619d48c97a | ||
![]() |
2cb198c38c | ||
![]() |
e8e39e0f3c | ||
![]() |
37860181d4 | ||
![]() |
d119dd9a0c | ||
![]() |
09ef19f7ec | ||
![]() |
6a06c92fa6 | ||
![]() |
58ae596b0f | ||
![]() |
f1ca21678d | ||
![]() |
d7eeef2c8a | ||
![]() |
4f626897f2 | ||
![]() |
b127e01845 | ||
![]() |
2118beeb23 | ||
![]() |
5020cd1bbf | ||
![]() |
cce636224c | ||
![]() |
60b3b8ddce | ||
![]() |
41446ec9ba | ||
![]() |
df8b047bca | ||
![]() |
12ced52012 | ||
![]() |
1d53335ae5 | ||
![]() |
971a50d290 | ||
![]() |
36dd9106a8 | ||
![]() |
0a4ee3ffc7 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,9 +3,7 @@ out
|
||||
*.jks
|
||||
*.apk
|
||||
config.prop
|
||||
|
||||
# Manually dumped jars
|
||||
snet/libs
|
||||
update.sh
|
||||
|
||||
# Built binaries
|
||||
native/out
|
||||
|
22
README.MD
22
README.MD
@@ -1,5 +1,13 @@
|
||||
# Magisk
|
||||
[XDA Announcement Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
|
||||
[Downloads](https://github.com/topjohnwu/Magisk/releases) | [Documentation](https://topjohnwu.github.io/Magisk/) | [XDA Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
|
||||
|
||||
## Introduction
|
||||
Magisk is a suite of open source tools for customizing Android, supporting devices higher than Android 5.0 (API 21). It covers the fundamental parts for Android customization: root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt removals etc.
|
||||
|
||||
Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact. With its systemless nature along with several other hacks, Magisk can hide modifications from nearly any system integrity verifications used in banking apps, corporation monitoring apps, game cheat detections, and most importantly [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html).
|
||||
|
||||
## Bug Reports
|
||||
**Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** **DO NOT** report bugs that is already fixed upstream. Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread.
|
||||
|
||||
## Building Environment Requirements
|
||||
1. Python 3.5+: run `build.py` script
|
||||
@@ -15,20 +23,12 @@
|
||||
4. Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
|
||||
5. By default, `build.py` build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (via the `-r, --release` flag), you need a Java Keystore file `release-key.jks` (only `JKS` format is supported) to sign APKs and zips. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
|
||||
|
||||
## Bug Reports
|
||||
**Make sure to install the latest [Canary Build](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337) before reporting any bugs!** Please **DO NOT** report bugs that is already fixed upstream.
|
||||
|
||||
Follow the instructions in the [Canary Channel XDA Thread](https://forum.xda-developers.com/apps/magisk/dev-magisk-canary-channel-bleeding-edge-t3839337), and report a bug either by opening an issue on GitHub or directly in the thread.
|
||||
|
||||
## Documentation
|
||||
[Link to Documentation](docs/README.MD)
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
Magisk, including all git submodules are free software:
|
||||
you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation,
|
||||
you can redistribute it and/or modify it under the terms of the
|
||||
GNU General Public License as published by the Free Software Foundation,
|
||||
either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
|
@@ -70,13 +70,23 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.core:core:1.0.1'
|
||||
fullImplementation project(':utils')
|
||||
implementation "androidx.core:core:${rootProject.ext.androidXVersion}"
|
||||
fullImplementation 'com.amitshekhar.android:android-networking:1.0.2'
|
||||
fullImplementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}"
|
||||
fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
|
||||
fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}"
|
||||
fullImplementation "com.google.android.material:material:${rootProject.ext.androidXVersion}"
|
||||
fullImplementation 'com.github.topjohnwu:libsu:2.0.2'
|
||||
fullImplementation 'com.github.topjohnwu:libsu:2.1.2'
|
||||
fullImplementation 'com.atlassian.commonmark:commonmark:0.11.0'
|
||||
fullImplementation 'org.kamranzafar:jtar:2.3'
|
||||
|
||||
def butterKnifeVersion = '9.0.0-rc2'
|
||||
if (properties.containsKey('android.injected.invoked.from.ide')) {
|
||||
fullImplementation "com.jakewharton:butterknife-reflect:${butterKnifeVersion}"
|
||||
} else {
|
||||
fullImplementation "com.jakewharton:butterknife-runtime:${butterKnifeVersion}"
|
||||
fullAnnotationProcessor "com.jakewharton:butterknife-compiler:${butterKnifeVersion}"
|
||||
}
|
||||
}
|
||||
|
10
app/proguard-rules.pro
vendored
10
app/proguard-rules.pro
vendored
@@ -17,14 +17,17 @@
|
||||
#}
|
||||
|
||||
# BouncyCastle
|
||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; }
|
||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; }
|
||||
-keep class org.bouncycastle.jcajce.provider.digest.SHA1** { *; }
|
||||
-keep,allowoptimization class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; }
|
||||
-keep,allowoptimization class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; }
|
||||
-keep,allowoptimization class org.bouncycastle.jcajce.provider.digest.SHA1** { *; }
|
||||
-dontwarn javax.naming.**
|
||||
|
||||
# Snet extention
|
||||
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
|
||||
|
||||
# Fast Android Networking Library
|
||||
-dontwarn okhttp3.**
|
||||
|
||||
# Strip logging
|
||||
-assumenosideeffects class com.topjohnwu.magisk.utils.Logger {
|
||||
public *** debug(...);
|
||||
@@ -33,3 +36,4 @@
|
||||
# Excessive obfuscation
|
||||
-repackageclasses 'a'
|
||||
-allowaccessmodification
|
||||
-optimizationpasses 6
|
||||
|
@@ -47,7 +47,7 @@
|
||||
<!-- Superuser -->
|
||||
|
||||
<activity
|
||||
android:name="a.p"
|
||||
android:name="a.m"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity="internal.superuser"
|
||||
@@ -68,17 +68,13 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="a.i">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<receiver android:name="a.j" />
|
||||
<receiver android:name="a.k" />
|
||||
<receiver android:name="a.l">
|
||||
<receiver android:name="a.i">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||
</intent-filter>
|
||||
@@ -87,11 +83,11 @@
|
||||
<!-- Service -->
|
||||
|
||||
<service
|
||||
android:name="a.m"
|
||||
android:name="a.j"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
<service
|
||||
android:name="a.n"
|
||||
android:name="a.k"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.receivers.BootReceiver;
|
||||
import com.topjohnwu.magisk.receivers.GeneralReceiver;
|
||||
|
||||
public class h extends BootReceiver {
|
||||
public class h extends GeneralReceiver {
|
||||
/* stub */
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.receivers.PackageReceiver;
|
||||
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||
|
||||
public class i extends PackageReceiver {
|
||||
public class i extends ShortcutReceiver {
|
||||
/* stub */
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||
import com.topjohnwu.magisk.services.OnBootService;
|
||||
|
||||
public class j extends ManagerUpdate {
|
||||
public class j extends OnBootService {
|
||||
/* stub */
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
|
||||
public class k extends RebootReceiver {
|
||||
public class k extends UpdateCheckService {
|
||||
/* stub */
|
||||
}
|
||||
|
@@ -1,7 +1,22 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
public class l extends ShortcutReceiver {
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
|
||||
public class l extends AboutCardRow {
|
||||
/* stub */
|
||||
|
||||
public l(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public l(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public l(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.services.OnBootService;
|
||||
import com.topjohnwu.magisk.SuRequestActivity;
|
||||
|
||||
public class m extends OnBootService {
|
||||
public class m extends SuRequestActivity {
|
||||
/* stub */
|
||||
}
|
||||
|
@@ -1,7 +0,0 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
|
||||
public class n extends UpdateCheckService {
|
||||
/* stub */
|
||||
}
|
@@ -1,22 +0,0 @@
|
||||
package a;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
|
||||
public class o extends AboutCardRow {
|
||||
/* stub */
|
||||
|
||||
public o(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public o(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public o(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package a;
|
||||
|
||||
import com.topjohnwu.magisk.SuRequestActivity;
|
||||
|
||||
public class p extends SuRequestActivity {
|
||||
/* stub */
|
||||
}
|
@@ -15,16 +15,17 @@ import java.util.Locale;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class AboutActivity extends BaseActivity {
|
||||
|
||||
Toolbar toolbar;
|
||||
AboutCardRow appVersionInfo;
|
||||
AboutCardRow appChangelog;
|
||||
AboutCardRow appTranslators;
|
||||
AboutCardRow appSourceCode;
|
||||
AboutCardRow supportThread;
|
||||
AboutCardRow twitter;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.app_version_info) AboutCardRow appVersionInfo;
|
||||
@BindView(R.id.app_changelog) AboutCardRow appChangelog;
|
||||
@BindView(R.id.app_translators) AboutCardRow appTranslators;
|
||||
@BindView(R.id.app_source_code) AboutCardRow appSourceCode;
|
||||
@BindView(R.id.support_thread) AboutCardRow supportThread;
|
||||
@BindView(R.id.follow_twitter) AboutCardRow twitter;
|
||||
|
||||
@Override
|
||||
public int getDarkTheme() {
|
||||
@@ -35,7 +36,7 @@ public class AboutActivity extends BaseActivity {
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_about);
|
||||
ViewBinder.bind(this);
|
||||
new AboutActivity_ViewBinding(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setNavigationOnClickListener(view -> finish());
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.os.Environment;
|
||||
import android.os.Process;
|
||||
|
||||
import java.io.File;
|
||||
@@ -9,7 +10,6 @@ import java.util.List;
|
||||
public class Const {
|
||||
|
||||
public static final String DEBUG_TAG = "MagiskManager";
|
||||
public static final String ORIG_PKG_NAME = BuildConfig.APPLICATION_ID;
|
||||
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
|
||||
|
||||
// APK content
|
||||
@@ -18,30 +18,28 @@ public class Const {
|
||||
public static final String SU_KEYSTORE_KEY = "su_key";
|
||||
|
||||
// Paths
|
||||
public static File MAGISK_PATH;
|
||||
public static final String MAGISK_PATH = "/sbin/.magisk/img";
|
||||
public static final File EXTERNAL_PATH;
|
||||
public static File MAGISK_DISABLE_FILE;
|
||||
public static File MAGISK_HOST_FILE;
|
||||
|
||||
static {
|
||||
/* Prevent crashing on unrooted devices */
|
||||
MAGISK_PATH = MAGISK_DISABLE_FILE = MAGISK_HOST_FILE = new File("xxx");
|
||||
MAGISK_DISABLE_FILE = new File("xxx");
|
||||
EXTERNAL_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
|
||||
EXTERNAL_PATH.mkdirs();
|
||||
}
|
||||
|
||||
public static final String BUSYBOX_PATH = "/sbin/.core/busybox";
|
||||
public static final String BUSYBOX_PATH = "/sbin/.magisk/busybox";
|
||||
public static final String TMP_FOLDER_PATH = "/dev/tmp";
|
||||
public static final String MAGISK_LOG = "/cache/magisk.log";
|
||||
public static final String MANAGER_CONFIGS = ".tmp.magisk.config";
|
||||
|
||||
// Versions
|
||||
public static final int UPDATE_SERVICE_VER = 1;
|
||||
|
||||
public static int MIN_MODULE_VER() {
|
||||
return Data.magiskVersionCode >= MAGISK_VER.REMOVE_LEGACY_LINK ? 1500 : 1400;
|
||||
}
|
||||
public static final int MIN_MODULE_VER = 1500;
|
||||
public static final int SNET_EXT_VER = 12;
|
||||
|
||||
/* A list of apps that should not be shown as hide-able */
|
||||
public static final List<String> HIDE_BLACKLIST = Arrays.asList(
|
||||
"android",
|
||||
Data.MM().getPackageName(),
|
||||
"com.google.android.gms"
|
||||
);
|
||||
@@ -49,15 +47,11 @@ public class Const {
|
||||
public static final int USER_ID = Process.myUid() / 100000;
|
||||
|
||||
public static final class MAGISK_VER {
|
||||
public static final int UNIFIED = 1300;
|
||||
public static final int FBE_AWARE = 1410;
|
||||
public static final int RESETPROP_PERSIST = 1436;
|
||||
public static final int MANAGER_HIDE = 1440;
|
||||
public static final int HIDDEN_PATH = 1460;
|
||||
public static final int REMOVE_LEGACY_LINK = 1630;
|
||||
public static final int SEPOL_REFACTOR = 1640;
|
||||
public static final int FIX_ENV = 1650;
|
||||
public static final int DBVER_SIX = 17000;
|
||||
public static final int CMDLINE_DB = 17305;
|
||||
public static final int HIDE_STATUS = 17315;
|
||||
}
|
||||
|
||||
public static class ID {
|
||||
@@ -70,20 +64,23 @@ public class Const {
|
||||
public static final int MAGISK_UPDATE_NOTIFICATION_ID = 4;
|
||||
public static final int APK_UPDATE_NOTIFICATION_ID = 5;
|
||||
public static final int DTBO_NOTIFICATION_ID = 7;
|
||||
public static final String NOTIFICATION_CHANNEL = "magisk_notification";
|
||||
public static final int HIDE_MANAGER_NOTIFICATION_ID = 8;
|
||||
public static final String UPDATE_NOTIFICATION_CHANNEL = "update";
|
||||
public static final String PROGRESS_NOTIFICATION_CHANNEL = "progress";
|
||||
}
|
||||
|
||||
public static class Url {
|
||||
public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/stable.json";
|
||||
public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/beta.json";
|
||||
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&sort=pushed&page=%d";
|
||||
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&sort=pushed";
|
||||
public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
|
||||
public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
|
||||
public static final String PAYPAL_URL = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=CC7FZ7526MNGG";
|
||||
public static final String PAYPAL_URL = "https://www.paypal.me/topjohnwu";
|
||||
public static final String PATREON_URL = "https://www.patreon.com/topjohnwu";
|
||||
public static final String TWITTER_URL = "https://twitter.com/topjohnwu";
|
||||
public static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
|
||||
public static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/Magisk";
|
||||
public static final String SNET_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/b66b1a914978e5f4c4bbfd74a59f4ad371bac107/snet.apk";
|
||||
}
|
||||
|
||||
|
||||
@@ -101,10 +98,12 @@ public class Const {
|
||||
|
||||
// intents
|
||||
public static final String OPEN_SECTION = "section";
|
||||
public static final String INTENT_SET_FILENAME = "filename";
|
||||
public static final String INTENT_SET_NAME = "filename";
|
||||
public static final String INTENT_SET_LINK = "link";
|
||||
public static final String FLASH_ACTION = "action";
|
||||
public static final String FLASH_SET_BOOT = "boot";
|
||||
public static final String BROADCAST_MANAGER_UPDATE = "manager_update";
|
||||
public static final String BROADCAST_REBOOT = "reboot";
|
||||
|
||||
// others
|
||||
public static final String CHECK_UPDATES = "check_update";
|
||||
|
@@ -6,14 +6,10 @@ import android.os.Looper;
|
||||
import android.util.Xml;
|
||||
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
import com.topjohnwu.magisk.receivers.BootReceiver;
|
||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||
import com.topjohnwu.magisk.receivers.PackageReceiver;
|
||||
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
||||
import com.topjohnwu.magisk.receivers.GeneralReceiver;
|
||||
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||
import com.topjohnwu.magisk.services.OnBootService;
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
@@ -51,8 +47,6 @@ public class Data {
|
||||
public static String managerLink;
|
||||
public static String managerNoteLink;
|
||||
public static String uninstallerLink;
|
||||
public static int snetVersionCode;
|
||||
public static String snetLink;
|
||||
|
||||
// Install flags
|
||||
public static boolean keepVerity = false;
|
||||
@@ -62,12 +56,9 @@ public class Data {
|
||||
public static boolean isDarkTheme;
|
||||
public static int suRequestTimeout;
|
||||
public static int suLogTimeout = 14;
|
||||
public static int suAccessState;
|
||||
public static boolean suFingerprint;
|
||||
public static int multiuserMode;
|
||||
public static int multiuserState = -1;
|
||||
public static int suResponseType;
|
||||
public static int suNotificationType;
|
||||
public static int suNamespaceMode;
|
||||
public static int updateChannel;
|
||||
public static int repoOrder;
|
||||
|
||||
@@ -79,15 +70,12 @@ public class Data {
|
||||
classMap.put(DonationActivity.class, a.e.class);
|
||||
classMap.put(FlashActivity.class, a.f.class);
|
||||
classMap.put(NoUIActivity.class, a.g.class);
|
||||
classMap.put(BootReceiver.class, a.h.class);
|
||||
classMap.put(PackageReceiver.class, a.i.class);
|
||||
classMap.put(ManagerUpdate.class, a.j.class);
|
||||
classMap.put(RebootReceiver.class, a.k.class);
|
||||
classMap.put(ShortcutReceiver.class, a.l.class);
|
||||
classMap.put(OnBootService.class, a.m.class);
|
||||
classMap.put(UpdateCheckService.class, a.n.class);
|
||||
classMap.put(AboutCardRow.class, a.o.class);
|
||||
classMap.put(SuRequestActivity.class, a.p.class);
|
||||
classMap.put(GeneralReceiver.class, a.h.class);
|
||||
classMap.put(ShortcutReceiver.class, a.i.class);
|
||||
classMap.put(OnBootService.class, a.j.class);
|
||||
classMap.put(UpdateCheckService.class, a.k.class);
|
||||
classMap.put(AboutCardRow.class, a.l.class);
|
||||
classMap.put(SuRequestActivity.class, a.m.class);
|
||||
|
||||
}
|
||||
|
||||
@@ -95,9 +83,12 @@ public class Data {
|
||||
try {
|
||||
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
||||
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
||||
String s = ShellUtils.fastCmd((magiskVersionCode >= Const.MAGISK_VER.RESETPROP_PERSIST ?
|
||||
"resetprop -p " : "getprop ") + Const.MAGISKHIDE_PROP);
|
||||
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
|
||||
if (magiskVersionCode >= Const.MAGISK_VER.HIDE_STATUS) {
|
||||
magiskHide = Shell.su("magiskhide --status").exec().isSuccess();
|
||||
} else {
|
||||
String s = ShellUtils.fastCmd(("resetprop -p ") + Const.MAGISKHIDE_PROP);
|
||||
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
|
||||
@@ -111,12 +102,12 @@ public class Data {
|
||||
mm.prefs.edit().commit();
|
||||
File xml = new File(mm.getFilesDir().getParent() + "/shared_prefs",
|
||||
mm.getPackageName() + "_preferences.xml");
|
||||
Shell.su(Utils.fmt("for usr in /data/user/*; do cat %s > ${usr}/%s; done", xml, Const.MANAGER_CONFIGS)).exec();
|
||||
Shell.su(Utils.fmt("cat %s > /data/user/0/%s", xml, Const.MANAGER_CONFIGS)).exec();
|
||||
}
|
||||
|
||||
public static void importPrefs() {
|
||||
MagiskManager mm = MM();
|
||||
SuFile config = new SuFile(Utils.fmt("/data/user/%d/%s", Const.USER_ID, Const.MANAGER_CONFIGS));
|
||||
SuFile config = new SuFile("/data/user/0/" + Const.MANAGER_CONFIGS);
|
||||
if (config.exists()) {
|
||||
SharedPreferences.Editor editor = mm.prefs.edit();
|
||||
try {
|
||||
@@ -181,15 +172,6 @@ public class Data {
|
||||
suRequestTimeout = Utils.getPrefsInt(mm.prefs, Const.Key.SU_REQUEST_TIMEOUT, Const.Value.timeoutList[2]);
|
||||
suResponseType = Utils.getPrefsInt(mm.prefs, Const.Key.SU_AUTO_RESPONSE, Const.Value.SU_PROMPT);
|
||||
suNotificationType = Utils.getPrefsInt(mm.prefs, Const.Key.SU_NOTIFICATION, Const.Value.NOTIFICATION_TOAST);
|
||||
suAccessState = mm.mDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
|
||||
multiuserMode = mm.mDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY);
|
||||
suNamespaceMode = mm.mDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
|
||||
suFingerprint = mm.mDB.getSettings(Const.Key.SU_FINGERPRINT, 0) != 0;
|
||||
if (suFingerprint && !FingerprintHelper.canUseFingerprint()) {
|
||||
// User revoked the fingerprint
|
||||
mm.mDB.setSettings(Const.Key.SU_FINGERPRINT, 0);
|
||||
suFingerprint = false;
|
||||
}
|
||||
|
||||
// config
|
||||
isDarkTheme = mm.prefs.getBoolean(Const.Key.DARK_THEME, false);
|
||||
@@ -201,15 +183,10 @@ public class Data {
|
||||
MM().prefs.edit()
|
||||
.putBoolean(Const.Key.DARK_THEME, isDarkTheme)
|
||||
.putBoolean(Const.Key.MAGISKHIDE, magiskHide)
|
||||
.putBoolean(Const.Key.HOSTS, Const.MAGISK_HOST_FILE.exists())
|
||||
.putBoolean(Const.Key.COREONLY, Const.MAGISK_DISABLE_FILE.exists())
|
||||
.putBoolean(Const.Key.SU_FINGERPRINT, suFingerprint)
|
||||
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(suRequestTimeout))
|
||||
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(suResponseType))
|
||||
.putString(Const.Key.SU_NOTIFICATION, String.valueOf(suNotificationType))
|
||||
.putString(Const.Key.ROOT_ACCESS, String.valueOf(suAccessState))
|
||||
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(multiuserMode))
|
||||
.putString(Const.Key.SU_MNT_NS, String.valueOf(suNamespaceMode))
|
||||
.putString(Const.Key.UPDATE_CHANNEL, String.valueOf(updateChannel))
|
||||
.putInt(Const.Key.UPDATE_SERVICE_VER, Const.UPDATE_SERVICE_VER)
|
||||
.putInt(Const.Key.REPO_ORDER, repoOrder)
|
||||
|
@@ -10,12 +10,13 @@ import com.topjohnwu.magisk.utils.Utils;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class DonationActivity extends BaseActivity {
|
||||
|
||||
Toolbar toolbar;
|
||||
AboutCardRow paypal;
|
||||
AboutCardRow patreon;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.paypal) AboutCardRow paypal;
|
||||
@BindView(R.id.patreon) AboutCardRow patreon;
|
||||
|
||||
@Override
|
||||
public int getDarkTheme() {
|
||||
@@ -26,7 +27,7 @@ public class DonationActivity extends BaseActivity {
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_donation);
|
||||
ViewBinder.bind(this);
|
||||
new DonationActivity_ViewBinding(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
toolbar.setNavigationOnClickListener(view -> finish());
|
||||
|
@@ -15,7 +15,6 @@ import android.widget.Toast;
|
||||
import com.topjohnwu.magisk.asyncs.FlashZip;
|
||||
import com.topjohnwu.magisk.asyncs.InstallMagisk;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.CallbackList;
|
||||
@@ -31,25 +30,25 @@ import java.util.Locale;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class FlashActivity extends BaseActivity {
|
||||
|
||||
Toolbar toolbar;
|
||||
TextView flashLogs;
|
||||
public LinearLayout buttonPanel;
|
||||
public Button reboot;
|
||||
ScrollView sv;
|
||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||
@BindView(R.id.txtLog) TextView flashLogs;
|
||||
@BindView(R.id.button_panel) public LinearLayout buttonPanel;
|
||||
@BindView(R.id.reboot) public Button reboot;
|
||||
@BindView(R.id.scrollView) ScrollView sv;
|
||||
|
||||
private List<String> logs;
|
||||
|
||||
void dismiss() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@OnClick(R.id.reboot)
|
||||
void reboot() {
|
||||
Shell.su("/system/bin/reboot").submit();
|
||||
}
|
||||
|
||||
@OnClick(R.id.save_logs)
|
||||
void saveLogs() {
|
||||
runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
|
||||
Calendar now = Calendar.getInstance();
|
||||
@@ -59,7 +58,7 @@ public class FlashActivity extends BaseActivity {
|
||||
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
|
||||
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
|
||||
|
||||
File logFile = new File(Download.EXTERNAL_PATH, filename);
|
||||
File logFile = new File(Const.EXTERNAL_PATH, filename);
|
||||
try (FileWriter writer = new FileWriter(logFile)) {
|
||||
for (String s : logs) {
|
||||
writer.write(s);
|
||||
@@ -82,7 +81,8 @@ public class FlashActivity extends BaseActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_flash);
|
||||
ViewBinder.bind(this);
|
||||
new FlashActivity_ViewBinding(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
ActionBar ab = getSupportActionBar();
|
||||
if (ab != null) {
|
||||
@@ -133,13 +133,18 @@ public class FlashActivity extends BaseActivity {
|
||||
new InstallMagisk(this, console, logs, InstallMagisk.SECOND_SLOT_MODE).exec();
|
||||
break;
|
||||
case Const.Value.PATCH_BOOT:
|
||||
runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||
() -> new InstallMagisk(this, console, logs,
|
||||
intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec());
|
||||
new InstallMagisk(this, console, logs,
|
||||
intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT)).exec();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.close)
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Prevent user accidentally press back button
|
||||
|
@@ -1,12 +1,10 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
|
||||
import com.topjohnwu.magisk.database.MagiskDB;
|
||||
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
@@ -22,7 +20,7 @@ public class MagiskManager extends ContainerApp {
|
||||
|
||||
// Global resources
|
||||
public SharedPreferences prefs;
|
||||
public MagiskDatabaseHelper mDB;
|
||||
public MagiskDB mDB;
|
||||
public RepoDatabaseHelper repoDB;
|
||||
|
||||
public MagiskManager() {
|
||||
@@ -36,22 +34,11 @@ public class MagiskManager extends ContainerApp {
|
||||
Shell.Config.setFlags(Shell.FLAG_MOUNT_MASTER);
|
||||
Shell.Config.verboseLogging(BuildConfig.DEBUG);
|
||||
Shell.Config.setInitializer(RootUtils.class);
|
||||
Shell.Config.setTimeout(2);
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
mDB = MagiskDatabaseHelper.getInstance(this);
|
||||
|
||||
String pkg = mDB.getStrings(Const.Key.SU_MANAGER, null);
|
||||
if (pkg != null && getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||
mDB.setStrings(Const.Key.SU_MANAGER, null);
|
||||
Shell.su("pm uninstall " + pkg).exec();
|
||||
}
|
||||
if (TextUtils.equals(pkg, getPackageName())) {
|
||||
try {
|
||||
// We are the manager, remove com.topjohnwu.magisk as it could be malware
|
||||
getPackageManager().getApplicationInfo(Const.ORIG_PKG_NAME, 0);
|
||||
RootUtils.uninstallPkg(Const.ORIG_PKG_NAME);
|
||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||
}
|
||||
mDB = MagiskDB.getInstance();
|
||||
repoDB = new RepoDatabaseHelper(this);
|
||||
|
||||
LocaleManager.setLocale(this);
|
||||
Data.loadConfig();
|
||||
|
@@ -18,6 +18,7 @@ import com.topjohnwu.magisk.fragments.SettingsFragment;
|
||||
import com.topjohnwu.magisk.fragments.SuperuserFragment;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -26,6 +27,7 @@ import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class MainActivity extends BaseActivity
|
||||
implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber {
|
||||
@@ -34,9 +36,9 @@ public class MainActivity extends BaseActivity
|
||||
private int mDrawerItem;
|
||||
private static boolean fromShortcut = false;
|
||||
|
||||
public Toolbar toolbar;
|
||||
DrawerLayout drawer;
|
||||
NavigationView navigationView;
|
||||
@BindView(R.id.toolbar) public Toolbar toolbar;
|
||||
@BindView(R.id.drawer_layout) DrawerLayout drawer;
|
||||
@BindView(R.id.nav_view) NavigationView navigationView;
|
||||
|
||||
private float toolbarElevation;
|
||||
|
||||
@@ -54,7 +56,7 @@ public class MainActivity extends BaseActivity
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
ViewBinder.bind(this);
|
||||
new MainActivity_ViewBinding(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
@@ -118,14 +120,12 @@ public class MainActivity extends BaseActivity
|
||||
public void checkHideSection() {
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.findItem(R.id.magiskhide).setVisible(Shell.rootAccess() &&
|
||||
Data.magiskVersionCode >= Const.MAGISK_VER.UNIFIED &&
|
||||
mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false));
|
||||
menu.findItem(R.id.modules).setVisible(Shell.rootAccess() && Data.magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.downloads).setVisible(Download.checkNetworkStatus(this)
|
||||
&& Shell.rootAccess() && Data.magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
|
||||
menu.findItem(R.id.superuser).setVisible(Shell.rootAccess() &&
|
||||
!(Const.USER_ID > 0 && Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED));
|
||||
menu.findItem(R.id.superuser).setVisible(Utils.showSuperUser());
|
||||
}
|
||||
|
||||
public void navigate(String item) {
|
||||
|
@@ -1,18 +1,18 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.UpdateRepos;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
|
||||
import com.topjohnwu.magisk.components.Notifications;
|
||||
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
@@ -22,6 +22,19 @@ public class SplashActivity extends BaseActivity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String pkg = mm.mDB.getStrings(Const.Key.SU_MANAGER, null);
|
||||
if (pkg != null && getPackageName().equals(BuildConfig.APPLICATION_ID)) {
|
||||
mm.mDB.setStrings(Const.Key.SU_MANAGER, null);
|
||||
Shell.su("pm uninstall " + pkg).exec();
|
||||
}
|
||||
if (TextUtils.equals(pkg, getPackageName())) {
|
||||
try {
|
||||
// We are the manager, remove com.topjohnwu.magisk as it could be malware
|
||||
getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
|
||||
RootUtils.uninstallPkg(BuildConfig.APPLICATION_ID);
|
||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||
}
|
||||
|
||||
// Magisk working as expected
|
||||
if (Shell.rootAccess() && Data.magiskVersionCode > 0) {
|
||||
// Update check service
|
||||
@@ -30,18 +43,13 @@ public class SplashActivity extends BaseActivity {
|
||||
Utils.loadModules();
|
||||
}
|
||||
|
||||
mm.repoDB = new RepoDatabaseHelper(this);
|
||||
Data.importPrefs();
|
||||
|
||||
// Dynamic detect all locales
|
||||
LocaleManager.loadAvailableLocales();
|
||||
|
||||
// Create notification channel on Android O
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(Const.ID.NOTIFICATION_CHANNEL,
|
||||
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
getSystemService(NotificationManager.class).createNotificationChannel(channel);
|
||||
}
|
||||
Notifications.setup(this);
|
||||
|
||||
// Setup shortcuts
|
||||
sendBroadcast(new Intent(this, Data.classMap.get(ShortcutReceiver.class)));
|
||||
|
@@ -22,22 +22,21 @@ import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||
import com.topjohnwu.magisk.utils.SuConnector;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SuRequestActivity extends BaseActivity {
|
||||
LinearLayout suPopup;
|
||||
Spinner timeout;
|
||||
ImageView appIcon;
|
||||
TextView appNameView;
|
||||
TextView packageNameView;
|
||||
Button grant_btn;
|
||||
Button deny_btn;
|
||||
ImageView fingerprintImg;
|
||||
TextView warning;
|
||||
@BindView(R.id.su_popup) LinearLayout suPopup;
|
||||
@BindView(R.id.timeout) Spinner timeout;
|
||||
@BindView(R.id.app_icon) ImageView appIcon;
|
||||
@BindView(R.id.app_name) TextView appNameView;
|
||||
@BindView(R.id.package_name) TextView packageNameView;
|
||||
@BindView(R.id.grant_btn) Button grant_btn;
|
||||
@BindView(R.id.deny_btn) Button deny_btn;
|
||||
@BindView(R.id.fingerprint) ImageView fingerprintImg;
|
||||
@BindView(R.id.warning) TextView warning;
|
||||
|
||||
private SuConnector connector;
|
||||
private Policy policy;
|
||||
@@ -47,6 +46,11 @@ public class SuRequestActivity extends BaseActivity {
|
||||
class SuConnectorV1 extends SuConnector {
|
||||
|
||||
SuConnectorV1(String name) throws IOException {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String name) throws IOException {
|
||||
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM));
|
||||
new FileObserver(name) {
|
||||
@Override
|
||||
@@ -59,28 +63,25 @@ public class SuRequestActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void response() {
|
||||
try (OutputStream out = getOutputStream()) {
|
||||
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void onResponse() throws IOException {
|
||||
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
class SuConnectorV2 extends SuConnector {
|
||||
|
||||
SuConnectorV2(String name) throws IOException {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String name) throws IOException {
|
||||
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.ABSTRACT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void response() {
|
||||
try (DataOutputStream out = getOutputStream()) {
|
||||
out.writeInt(policy.policy);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void onResponse() throws IOException {
|
||||
out.writeInt(policy.policy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,9 +119,9 @@ public class SuRequestActivity extends BaseActivity {
|
||||
// Get policy
|
||||
Intent intent = getIntent();
|
||||
try {
|
||||
String socketName = intent.getStringExtra("socket");
|
||||
connector = intent.getIntExtra("version", 1) == 1 ?
|
||||
new SuConnectorV1(intent.getStringExtra("socket")) :
|
||||
new SuConnectorV2(intent.getStringExtra("socket"));
|
||||
new SuConnectorV1(socketName) : new SuConnectorV2(socketName);
|
||||
Bundle bundle = connector.readSocketInput();
|
||||
int uid = Integer.parseInt(bundle.getString("uid"));
|
||||
policy = mm.mDB.getPolicy(uid);
|
||||
@@ -134,7 +135,7 @@ public class SuRequestActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
// Never allow com.topjohnwu.magisk (could be malware)
|
||||
if (TextUtils.equals(policy.packageName, Const.ORIG_PKG_NAME)) {
|
||||
if (TextUtils.equals(policy.packageName, BuildConfig.APPLICATION_ID)) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@@ -157,7 +158,7 @@ public class SuRequestActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_request);
|
||||
ViewBinder.bind(this);
|
||||
new SuRequestActivity_ViewBinding(this);
|
||||
|
||||
appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||
appNameView.setText(policy.appName);
|
||||
@@ -180,9 +181,9 @@ public class SuRequestActivity extends BaseActivity {
|
||||
}
|
||||
};
|
||||
|
||||
boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint();
|
||||
boolean useFP = FingerprintHelper.useFingerPrint();
|
||||
|
||||
if (useFingerprint) {
|
||||
if (useFP) {
|
||||
try {
|
||||
fingerprintHelper = new FingerprintHelper() {
|
||||
@Override
|
||||
@@ -208,11 +209,11 @@ public class SuRequestActivity extends BaseActivity {
|
||||
fingerprintHelper.authenticate();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
useFingerprint = false;
|
||||
useFP = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useFingerprint) {
|
||||
if (!useFP) {
|
||||
grant_btn.setOnClickListener(v -> {
|
||||
handleAction(Policy.ALLOW);
|
||||
timer.cancel();
|
||||
@@ -220,8 +221,8 @@ public class SuRequestActivity extends BaseActivity {
|
||||
grant_btn.requestFocus();
|
||||
}
|
||||
|
||||
grant_btn.setVisibility(useFingerprint ? View.GONE : View.VISIBLE);
|
||||
fingerprintImg.setVisibility(useFingerprint ? View.VISIBLE : View.GONE);
|
||||
grant_btn.setVisibility(useFP ? View.GONE : View.VISIBLE);
|
||||
fingerprintImg.setVisibility(useFP ? View.VISIBLE : View.GONE);
|
||||
|
||||
deny_btn.setOnClickListener(v -> {
|
||||
handleAction(Policy.DENY);
|
||||
@@ -251,7 +252,7 @@ public class SuRequestActivity extends BaseActivity {
|
||||
policy.policy = action;
|
||||
if (time >= 0) {
|
||||
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
||||
mm.mDB.addPolicy(policy);
|
||||
mm.mDB.updatePolicy(policy);
|
||||
}
|
||||
handleAction();
|
||||
}
|
||||
|
@@ -1,293 +0,0 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
|
||||
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
||||
import com.topjohnwu.magisk.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.adapters.ReposAdapter;
|
||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||
import com.topjohnwu.magisk.fragments.LogFragment;
|
||||
import com.topjohnwu.magisk.fragments.MagiskFragment;
|
||||
import com.topjohnwu.magisk.fragments.MagiskHideFragment;
|
||||
import com.topjohnwu.magisk.fragments.MagiskLogFragment;
|
||||
import com.topjohnwu.magisk.fragments.ModulesFragment;
|
||||
import com.topjohnwu.magisk.fragments.ReposFragment;
|
||||
import com.topjohnwu.magisk.fragments.SuLogFragment;
|
||||
import com.topjohnwu.magisk.fragments.SuperuserFragment;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public class ViewBinder {
|
||||
|
||||
public static void bind(MainActivity target) {
|
||||
target.drawer = target.findViewById(R.id.drawer_layout);
|
||||
target.toolbar = target.findViewById(R.id.toolbar);
|
||||
target.navigationView = target.findViewById(R.id.nav_view);
|
||||
}
|
||||
|
||||
public static void bind(AboutActivity target) {
|
||||
target.toolbar = target.findViewById(R.id.toolbar);
|
||||
target.appVersionInfo = target.findViewById(R.id.app_version_info);
|
||||
target.appChangelog = target.findViewById(R.id.app_changelog);
|
||||
target.appTranslators = target.findViewById(R.id.app_translators);
|
||||
target.appSourceCode = target.findViewById(R.id.app_source_code);
|
||||
target.supportThread = target.findViewById(R.id.support_thread);
|
||||
target.twitter = target.findViewById(R.id.follow_twitter);
|
||||
}
|
||||
|
||||
public static void bind(DonationActivity target) {
|
||||
target.toolbar = target.findViewById(R.id.toolbar);
|
||||
target.paypal = target.findViewById(R.id.paypal);
|
||||
target.patreon = target.findViewById(R.id.patreon);
|
||||
}
|
||||
|
||||
public static void bind(FlashActivity target) {
|
||||
target.toolbar = target.findViewById(R.id.toolbar);
|
||||
target.flashLogs = target.findViewById(R.id.txtLog);
|
||||
target.buttonPanel = target.findViewById(R.id.button_panel);
|
||||
target.sv = target.findViewById(R.id.scrollView);
|
||||
target.reboot = target.findViewById(R.id.reboot);
|
||||
target.reboot.setOnClickListener(v -> target.reboot());
|
||||
target.findViewById(R.id.no_thanks).setOnClickListener(v -> target.finish());
|
||||
target.findViewById(R.id.save_logs).setOnClickListener(v -> target.saveLogs());
|
||||
}
|
||||
|
||||
public static void bind(SuRequestActivity target) {
|
||||
target.suPopup = target.findViewById(R.id.su_popup);
|
||||
target.timeout = target.findViewById(R.id.timeout);
|
||||
target.appIcon = target.findViewById(R.id.app_icon);
|
||||
target.appNameView = target.findViewById(R.id.app_name);
|
||||
target.packageNameView = target.findViewById(R.id.package_name);
|
||||
target.grant_btn = target.findViewById(R.id.grant_btn);
|
||||
target.deny_btn = target.findViewById(R.id.deny_btn);
|
||||
target.fingerprintImg = target.findViewById(R.id.fingerprint);
|
||||
target.warning = target.findViewById(R.id.warning);
|
||||
}
|
||||
|
||||
public static void bind(LogFragment target, View v) {
|
||||
target.viewPager = v.findViewById(R.id.container);
|
||||
target.tab = v.findViewById(R.id.tab);
|
||||
}
|
||||
|
||||
public static void unbind(LogFragment target) {
|
||||
target.viewPager = null;
|
||||
target.tab = null;
|
||||
}
|
||||
|
||||
public static void bind(MagiskFragment target, View v) {
|
||||
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
|
||||
target.coreOnlyNotice = v.findViewById(R.id.core_only_notice);
|
||||
target.magiskUpdate = v.findViewById(R.id.magisk_update);
|
||||
target.magiskUpdateIcon = v.findViewById(R.id.magisk_update_icon);
|
||||
target.magiskUpdateText = v.findViewById(R.id.magisk_update_status);
|
||||
target.magiskUpdateProgress = v.findViewById(R.id.magisk_update_progress);
|
||||
target.magiskStatusIcon = v.findViewById(R.id.magisk_status_icon);
|
||||
target.magiskVersionText = v.findViewById(R.id.magisk_version);
|
||||
target.safetyNetCard = v.findViewById(R.id.safetyNet_card);
|
||||
target.safetyNetRefreshIcon = v.findViewById(R.id.safetyNet_refresh);
|
||||
target.safetyNetStatusText = v.findViewById(R.id.safetyNet_status);
|
||||
target.safetyNetProgress = v.findViewById(R.id.safetyNet_check_progress);
|
||||
target.expandLayout = v.findViewById(R.id.expand_layout);
|
||||
target.ctsStatusIcon = v.findViewById(R.id.cts_status_icon);
|
||||
target.ctsStatusText = v.findViewById(R.id.cts_status);
|
||||
target.basicStatusIcon = v.findViewById(R.id.basic_status_icon);
|
||||
target.basicStatusText = v.findViewById(R.id.basic_status);
|
||||
target.installOptionCard = v.findViewById(R.id.install_option_card);
|
||||
target.keepEncChkbox = v.findViewById(R.id.keep_force_enc);
|
||||
target.keepVerityChkbox = v.findViewById(R.id.keep_verity);
|
||||
target.installButton = v.findViewById(R.id.install_button);
|
||||
target.installText = v.findViewById(R.id.install_text);
|
||||
target.uninstallButton = v.findViewById(R.id.uninstall_button);
|
||||
|
||||
v.findViewById(R.id.safetyNet_title).setOnClickListener(v1 -> target.safetyNet());
|
||||
v.findViewById(R.id.install_button).setOnClickListener(v1 -> target.install());
|
||||
v.findViewById(R.id.uninstall_button).setOnClickListener(v1 -> target.uninstall());
|
||||
|
||||
Context ctx = target.getContext();
|
||||
target.colorBad = ContextCompat.getColor(ctx, R.color.red500);
|
||||
target.colorOK = ContextCompat.getColor(ctx, R.color.green500);
|
||||
target.colorWarn = ContextCompat.getColor(ctx, R.color.yellow500);
|
||||
target.colorNeutral = ContextCompat.getColor(ctx, R.color.grey500);
|
||||
target.colorInfo = ContextCompat.getColor(ctx, R.color.blue500);
|
||||
}
|
||||
|
||||
public static void unbind(MagiskFragment target) {
|
||||
target.mSwipeRefreshLayout = null;
|
||||
target.coreOnlyNotice = null;
|
||||
target.magiskUpdate = null;
|
||||
target.magiskUpdateIcon = null;
|
||||
target.magiskUpdateText = null;
|
||||
target.magiskUpdateProgress = null;
|
||||
target.magiskStatusIcon = null;
|
||||
target.magiskVersionText = null;
|
||||
target.safetyNetCard = null;
|
||||
target.safetyNetRefreshIcon = null;
|
||||
target.safetyNetStatusText = null;
|
||||
target.safetyNetProgress = null;
|
||||
target.expandLayout = null;
|
||||
target.ctsStatusIcon = null;
|
||||
target.ctsStatusText = null;
|
||||
target.basicStatusIcon = null;
|
||||
target.basicStatusText = null;
|
||||
target.installOptionCard = null;
|
||||
target.keepEncChkbox = null;
|
||||
target.keepVerityChkbox = null;
|
||||
target.installButton = null;
|
||||
target.installText = null;
|
||||
target.uninstallButton = null;
|
||||
|
||||
View v = target.getView();
|
||||
v.findViewById(R.id.safetyNet_title).setOnClickListener(null);
|
||||
v.findViewById(R.id.install_button).setOnClickListener(null);
|
||||
v.findViewById(R.id.uninstall_button).setOnClickListener(null);
|
||||
}
|
||||
|
||||
public static void bind(MagiskHideFragment target, View v) {
|
||||
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
|
||||
target.recyclerView = v.findViewById(R.id.recyclerView);
|
||||
}
|
||||
|
||||
public static void unbind(MagiskHideFragment target) {
|
||||
target.mSwipeRefreshLayout = null;
|
||||
target.recyclerView = null;
|
||||
}
|
||||
|
||||
public static void bind(MagiskLogFragment target, View v) {
|
||||
target.txtLog = v.findViewById(R.id.txtLog);
|
||||
target.svLog = v.findViewById(R.id.svLog);
|
||||
target.hsvLog = v.findViewById(R.id.hsvLog);
|
||||
target.progressBar = v.findViewById(R.id.progressBar);
|
||||
}
|
||||
|
||||
public static void unbind(MagiskLogFragment target) {
|
||||
target.txtLog = null;
|
||||
target.svLog = null;
|
||||
target.hsvLog = null;
|
||||
target.progressBar = null;
|
||||
}
|
||||
|
||||
public static void bind(ModulesFragment target, View v) {
|
||||
target.mSwipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout);
|
||||
target.recyclerView = v.findViewById(R.id.recyclerView);
|
||||
target.emptyRv = v.findViewById(R.id.empty_rv);
|
||||
v.findViewById(R.id.fab).setOnClickListener(v1 -> target.selectFile());
|
||||
}
|
||||
|
||||
public static void unbind(ModulesFragment target) {
|
||||
target.mSwipeRefreshLayout = null;
|
||||
target.recyclerView = null;
|
||||
target.emptyRv = null;
|
||||
View v = target.getView();
|
||||
v.findViewById(R.id.fab).setOnClickListener(null);
|
||||
}
|
||||
|
||||
public static void bind(ReposFragment target, View source) {
|
||||
target.recyclerView = source.findViewById(R.id.recyclerView);
|
||||
target.emptyRv = source.findViewById(R.id.empty_rv);
|
||||
target.mSwipeRefreshLayout = source.findViewById(R.id.swipeRefreshLayout);
|
||||
}
|
||||
|
||||
public static void unbind(ReposFragment target) {
|
||||
target.recyclerView = null;
|
||||
target.emptyRv = null;
|
||||
target.mSwipeRefreshLayout = null;
|
||||
}
|
||||
|
||||
public static void bind(SuLogFragment target, View source) {
|
||||
target.emptyRv = source.findViewById(R.id.empty_rv);
|
||||
target.recyclerView = source.findViewById(R.id.recyclerView);
|
||||
}
|
||||
|
||||
public static void unbind(SuLogFragment target) {
|
||||
target.emptyRv = null;
|
||||
target.recyclerView = null;
|
||||
}
|
||||
|
||||
public static void bind(SuperuserFragment target, View source) {
|
||||
target.recyclerView = source.findViewById(R.id.recyclerView);
|
||||
target.emptyRv = source.findViewById(R.id.empty_rv);
|
||||
}
|
||||
|
||||
public static void unbind(SuperuserFragment target) {
|
||||
target.emptyRv = null;
|
||||
target.recyclerView = null;
|
||||
}
|
||||
|
||||
public static void bind(CustomAlertDialog.ViewHolder target, View source) {
|
||||
target.dialogLayout = source.findViewById(R.id.dialog_layout);
|
||||
target.buttons = source.findViewById(R.id.button_panel);
|
||||
target.messageView = source.findViewById(R.id.message);
|
||||
target.negative = source.findViewById(R.id.negative);
|
||||
target.positive = source.findViewById(R.id.positive);
|
||||
target.neutral = source.findViewById(R.id.neutral);
|
||||
}
|
||||
|
||||
public static void bind(AboutCardRow target, View source) {
|
||||
target.mTitle = source.findViewById(android.R.id.title);
|
||||
target.mSummary = source.findViewById(android.R.id.summary);
|
||||
target.mIcon = source.findViewById(android.R.id.icon);
|
||||
target.mView = source.findViewById(R.id.container);
|
||||
}
|
||||
|
||||
public static void bind(ApplicationAdapter.ViewHolder target, View source) {
|
||||
target.appIcon = source.findViewById(R.id.app_icon);
|
||||
target.appName = source.findViewById(R.id.app_name);
|
||||
target.appPackage = source.findViewById(R.id.package_name);
|
||||
target.checkBox = source.findViewById(R.id.checkbox);
|
||||
}
|
||||
|
||||
public static void bind(ModulesAdapter.ViewHolder target, View source) {
|
||||
target.title = source.findViewById(R.id.title);
|
||||
target.versionName = source.findViewById(R.id.version_name);
|
||||
target.description = source.findViewById(R.id.description);
|
||||
target.notice = source.findViewById(R.id.notice);
|
||||
target.checkBox = source.findViewById(R.id.checkbox);
|
||||
target.author = source.findViewById(R.id.author);
|
||||
target.delete = source.findViewById(R.id.delete);
|
||||
}
|
||||
|
||||
public static void bind(PolicyAdapter.ViewHolder target, View source) {
|
||||
target.appName = source.findViewById(R.id.app_name);
|
||||
target.packageName = source.findViewById(R.id.package_name);
|
||||
target.appIcon = source.findViewById(R.id.app_icon);
|
||||
target.masterSwitch = source.findViewById(R.id.master_switch);
|
||||
target.notificationSwitch = source.findViewById(R.id.notification_switch);
|
||||
target.loggingSwitch = source.findViewById(R.id.logging_switch);
|
||||
target.expandLayout = source.findViewById(R.id.expand_layout);
|
||||
target.delete = source.findViewById(R.id.delete);
|
||||
target.moreInfo = source.findViewById(R.id.more_info);
|
||||
}
|
||||
|
||||
public static void bind(ReposAdapter.SectionHolder target, View source) {
|
||||
target.sectionText = source.findViewById(R.id.section_text);
|
||||
}
|
||||
|
||||
public static void bind(ReposAdapter.RepoHolder target, View source) {
|
||||
target.title = source.findViewById(R.id.title);
|
||||
target.versionName = source.findViewById(R.id.version_name);
|
||||
target.description = source.findViewById(R.id.description);
|
||||
target.author = source.findViewById(R.id.author);
|
||||
target.infoLayout = source.findViewById(R.id.info_layout);
|
||||
target.downloadImage = source.findViewById(R.id.download);
|
||||
target.updateTime = source.findViewById(R.id.update_time);
|
||||
}
|
||||
|
||||
public static void bind(SuLogAdapter.SectionHolder target, View source) {
|
||||
target.date = source.findViewById(R.id.date);
|
||||
target.arrow = source.findViewById(R.id.arrow);
|
||||
}
|
||||
|
||||
public static void bind(SuLogAdapter.LogViewHolder target, View source) {
|
||||
target.appName = source.findViewById(R.id.app_name);
|
||||
target.action = source.findViewById(R.id.action);
|
||||
target.time = source.findViewById(R.id.time);
|
||||
target.fromPid = source.findViewById(R.id.fromPid);
|
||||
target.toUid = source.findViewById(R.id.toUid);
|
||||
target.command = source.findViewById(R.id.command);
|
||||
target.expandLayout = source.findViewById(R.id.expand_layout);
|
||||
}
|
||||
}
|
@@ -3,8 +3,6 @@ package com.topjohnwu.magisk.adapters;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -17,9 +15,8 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -29,6 +26,7 @@ import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
|
||||
|
||||
@@ -52,25 +50,12 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
private String getLabel(ApplicationInfo info) {
|
||||
if (info.labelRes > 0) {
|
||||
try {
|
||||
Resources res = pm.getResourcesForApplication(info);
|
||||
Configuration config = new Configuration();
|
||||
config.setLocale(LocaleManager.locale);
|
||||
res.updateConfiguration(config, res.getDisplayMetrics());
|
||||
return res.getString(info.labelRes);
|
||||
} catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ }
|
||||
}
|
||||
return info.loadLabel(pm).toString();
|
||||
}
|
||||
|
||||
private void loadApps() {
|
||||
fullList = pm.getInstalledApplications(0);
|
||||
hideList = Shell.su("magiskhide --ls").exec().getOut();
|
||||
for (Iterator<ApplicationInfo> i = fullList.iterator(); i.hasNext(); ) {
|
||||
ApplicationInfo info = i.next();
|
||||
if (Const.HIDE_BLACKLIST.contains(info.packageName) || !info.enabled) {
|
||||
if (Const.HIDE_BLACKLIST.contains(info.packageName) || !info.enabled || info.uid == 1000) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
@@ -78,7 +63,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
boolean ah = hideList.contains(a.packageName);
|
||||
boolean bh = hideList.contains(b.packageName);
|
||||
if (ah == bh) {
|
||||
return getLabel(a).toLowerCase().compareTo(getLabel(b).toLowerCase());
|
||||
return Utils.getAppLabel(a, pm).toLowerCase()
|
||||
.compareTo(Utils.getAppLabel(b, pm).toLowerCase());
|
||||
} else if (ah) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -93,7 +79,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
ApplicationInfo info = showList.get(position);
|
||||
|
||||
holder.appIcon.setImageDrawable(info.loadIcon(pm));
|
||||
holder.appName.setText(getLabel(info));
|
||||
holder.appName.setText(Utils.getAppLabel(info, pm));
|
||||
holder.appPackage.setText(info.packageName);
|
||||
|
||||
holder.checkBox.setOnCheckedChangeListener(null);
|
||||
@@ -122,20 +108,20 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public ImageView appIcon;
|
||||
public TextView appName;
|
||||
public TextView appPackage;
|
||||
public CheckBox checkBox;
|
||||
@BindView(R.id.app_icon) ImageView appIcon;
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.package_name) TextView appPackage;
|
||||
@BindView(R.id.checkbox) CheckBox checkBox;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new ApplicationAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
private class ApplicationFilter extends Filter {
|
||||
class ApplicationFilter extends Filter {
|
||||
|
||||
private boolean lowercaseContains(String s, CharSequence filter) {
|
||||
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
||||
@@ -149,7 +135,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
||||
showList = new ArrayList<>();
|
||||
String filter = constraint.toString().toLowerCase();
|
||||
for (ApplicationInfo info : fullList) {
|
||||
if (lowercaseContains(getLabel(info), filter)
|
||||
if (lowercaseContains(Utils.getAppLabel(info, pm), filter)
|
||||
|| lowercaseContains(info.packageName, filter)) {
|
||||
showList.add(info);
|
||||
}
|
||||
|
@@ -11,14 +11,15 @@ import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.container.Module;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
|
||||
|
||||
@@ -28,6 +29,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
mList = list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module, parent, false);
|
||||
@@ -101,19 +103,19 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
return mList.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView title;
|
||||
public TextView versionName;
|
||||
public TextView description;
|
||||
public TextView notice;
|
||||
public CheckBox checkBox;
|
||||
public TextView author;
|
||||
public ImageView delete;
|
||||
@BindView(R.id.title) TextView title;
|
||||
@BindView(R.id.version_name) TextView versionName;
|
||||
@BindView(R.id.description) TextView description;
|
||||
@BindView(R.id.notice) TextView notice;
|
||||
@BindView(R.id.checkbox) CheckBox checkBox;
|
||||
@BindView(R.id.author) TextView author;
|
||||
@BindView(R.id.delete) ImageView delete;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new ModulesAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
checkBox.setEnabled(false);
|
||||
|
@@ -11,32 +11,35 @@ import android.widget.TextView;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||
import com.topjohnwu.magisk.components.ExpandableView;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
|
||||
import com.topjohnwu.magisk.database.MagiskDB;
|
||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> {
|
||||
|
||||
private List<Policy> policyList;
|
||||
private MagiskDatabaseHelper dbHelper;
|
||||
private MagiskDB dbHelper;
|
||||
private PackageManager pm;
|
||||
private Set<Policy> expandList = new HashSet<>();
|
||||
|
||||
public PolicyAdapter(List<Policy> list, MagiskDatabaseHelper db, PackageManager pm) {
|
||||
public PolicyAdapter(List<Policy> list, MagiskDB db, PackageManager pm) {
|
||||
policyList = list;
|
||||
dbHelper = db;
|
||||
this.pm = pm;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_policy, parent, false);
|
||||
@@ -62,14 +65,34 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
holder.appName.setText(policy.appName);
|
||||
holder.packageName.setText(policy.packageName);
|
||||
holder.appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && policy.policy == Policy.DENY) ||
|
||||
(!isChecked && policy.policy == Policy.ALLOW)) {
|
||||
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.updatePolicy(policy);
|
||||
|
||||
holder.notificationSwitch.setOnCheckedChangeListener(null);
|
||||
holder.loggingSwitch.setOnCheckedChangeListener(null);
|
||||
|
||||
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
||||
holder.notificationSwitch.setChecked(policy.notification);
|
||||
holder.loggingSwitch.setChecked(policy.logging);
|
||||
|
||||
holder.masterSwitch.setOnClickListener(v -> {
|
||||
boolean isChecked = holder.masterSwitch.isChecked();
|
||||
Runnable r = () -> {
|
||||
if ((isChecked && policy.policy == Policy.DENY) ||
|
||||
(!isChecked && policy.policy == Policy.ALLOW)) {
|
||||
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.updatePolicy(policy);
|
||||
}
|
||||
};
|
||||
if (FingerprintHelper.useFingerPrint()) {
|
||||
holder.masterSwitch.setChecked(!isChecked);
|
||||
FingerprintHelper.showAuthDialog((Activity) v.getContext(), () -> {
|
||||
holder.masterSwitch.setChecked(isChecked);
|
||||
r.run();
|
||||
});
|
||||
} else {
|
||||
r.run();
|
||||
}
|
||||
});
|
||||
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
@@ -106,9 +129,6 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setCancelable(true)
|
||||
.show());
|
||||
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
||||
holder.notificationSwitch.setChecked(policy.notification);
|
||||
holder.loggingSwitch.setChecked(policy.logging);
|
||||
|
||||
// Hide for now
|
||||
holder.moreInfo.setVisibility(View.GONE);
|
||||
@@ -119,24 +139,24 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
return policyList.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
|
||||
static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
|
||||
|
||||
public TextView appName;
|
||||
public TextView packageName;
|
||||
public ImageView appIcon;
|
||||
public Switch masterSwitch;
|
||||
public Switch notificationSwitch;
|
||||
public Switch loggingSwitch;
|
||||
public ViewGroup expandLayout;
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.package_name) TextView packageName;
|
||||
@BindView(R.id.app_icon) ImageView appIcon;
|
||||
@BindView(R.id.master_switch) Switch masterSwitch;
|
||||
@BindView(R.id.notification_switch) Switch notificationSwitch;
|
||||
@BindView(R.id.logging_switch) Switch loggingSwitch;
|
||||
@BindView(R.id.expand_layout) ViewGroup expandLayout;
|
||||
|
||||
public ImageView delete;
|
||||
public ImageView moreInfo;
|
||||
@BindView(R.id.delete) ImageView delete;
|
||||
@BindView(R.id.more_info) ImageView moreInfo;
|
||||
|
||||
private Container container = new Container();
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new PolicyAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||
container.expandLayout = expandLayout;
|
||||
setupExpandable();
|
||||
}
|
||||
|
@@ -12,9 +12,8 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.asyncs.DownloadModule;
|
||||
import com.topjohnwu.magisk.asyncs.MarkDownWindow;
|
||||
import com.topjohnwu.magisk.asyncs.ProcessRepoZip;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||
import com.topjohnwu.magisk.container.Module;
|
||||
@@ -26,6 +25,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
|
||||
|
||||
@@ -105,16 +105,15 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
|
||||
|
||||
holder.downloadImage.setOnClickListener(v -> {
|
||||
new CustomAlertDialog((BaseActivity) context)
|
||||
.setTitle(context.getString(R.string.repo_install_title, repo.getName()))
|
||||
.setMessage(context.getString(R.string.repo_install_msg, repo.getDownloadFilename()))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.install, (d, i) ->
|
||||
new ProcessRepoZip((BaseActivity) context, repo, true).exec()
|
||||
)
|
||||
.setNeutralButton(R.string.download, (d, i) ->
|
||||
new ProcessRepoZip((BaseActivity) context, repo, false).exec())
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
.setTitle(context.getString(R.string.repo_install_title, repo.getName()))
|
||||
.setMessage(context.getString(R.string.repo_install_msg, repo.getDownloadFilename()))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.install, (d, i) ->
|
||||
DownloadModule.exec((BaseActivity) context, repo, true))
|
||||
.setNeutralButton(R.string.download, (d, i) ->
|
||||
DownloadModule.exec((BaseActivity) context, repo, false))
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,29 +162,29 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public static class SectionHolder extends RecyclerView.ViewHolder {
|
||||
static class SectionHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView sectionText;
|
||||
@BindView(R.id.section_text) TextView sectionText;
|
||||
|
||||
SectionHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new ReposAdapter$SectionHolder_ViewBinding(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RepoHolder extends RecyclerView.ViewHolder {
|
||||
static class RepoHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView title;
|
||||
public TextView versionName;
|
||||
public TextView description;
|
||||
public TextView author;
|
||||
public LinearLayout infoLayout;
|
||||
public ImageView downloadImage;
|
||||
public TextView updateTime;
|
||||
@BindView(R.id.title) TextView title;
|
||||
@BindView(R.id.version_name) TextView versionName;
|
||||
@BindView(R.id.description) TextView description;
|
||||
@BindView(R.id.author) TextView author;
|
||||
@BindView(R.id.info_layout) LinearLayout infoLayout;
|
||||
@BindView(R.id.download) ImageView downloadImage;
|
||||
@BindView(R.id.update_time) TextView updateTime;
|
||||
|
||||
RepoHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new ReposAdapter$RepoHolder_ViewBinding(this, itemView);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C extends RecyclerView.ViewHolder>
|
||||
@@ -9,8 +10,9 @@ public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C exte
|
||||
|
||||
private static final int SECTION_TYPE = Integer.MIN_VALUE;
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
final public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
final public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
if (viewType == SECTION_TYPE)
|
||||
return onCreateSectionViewHolder(parent);
|
||||
return onCreateItemViewHolder(parent, viewType);
|
||||
@@ -18,7 +20,7 @@ public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C exte
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
final public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
final public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
|
||||
PositionInfo info = getPositionInfo(position);
|
||||
if (info.position == -1)
|
||||
onBindSectionViewHolder((S) holder, info.section);
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -10,10 +9,9 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.components.ExpandableView;
|
||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
|
||||
import com.topjohnwu.magisk.database.MagiskDB;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -21,29 +19,29 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> {
|
||||
|
||||
private List<List<Integer>> logEntryList;
|
||||
private List<List<SuLogEntry>> logEntries;
|
||||
private Set<Integer> itemExpanded, sectionExpanded;
|
||||
private MagiskDatabaseHelper suDB;
|
||||
private Cursor suLogCursor = null;
|
||||
private MagiskDB suDB;
|
||||
|
||||
public SuLogAdapter(MagiskDatabaseHelper db) {
|
||||
public SuLogAdapter(MagiskDB db) {
|
||||
suDB = db;
|
||||
logEntryList = Collections.emptyList();
|
||||
logEntries = Collections.emptyList();
|
||||
sectionExpanded = new HashSet<>();
|
||||
itemExpanded = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSectionCount() {
|
||||
return logEntryList.size();
|
||||
return logEntries.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(int section) {
|
||||
return sectionExpanded.contains(section) ? logEntryList.get(section).size() : 0;
|
||||
return sectionExpanded.contains(section) ? logEntries.get(section).size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,8 +58,7 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
||||
|
||||
@Override
|
||||
public void onBindSectionViewHolder(SectionHolder holder, int section) {
|
||||
suLogCursor.moveToPosition(logEntryList.get(section).get(0));
|
||||
SuLogEntry entry = new SuLogEntry(suLogCursor);
|
||||
SuLogEntry entry = logEntries.get(section).get(0);
|
||||
holder.arrow.setRotation(sectionExpanded.contains(section) ? 180 : 0);
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
RotateAnimation rotate;
|
||||
@@ -69,11 +66,11 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
||||
holder.arrow.setRotation(0);
|
||||
rotate = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
sectionExpanded.remove(section);
|
||||
notifyItemRangeRemoved(getItemPosition(section, 0), logEntryList.get(section).size());
|
||||
notifyItemRangeRemoved(getItemPosition(section, 0), logEntries.get(section).size());
|
||||
} else {
|
||||
rotate = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
sectionExpanded.add(section);
|
||||
notifyItemRangeInserted(getItemPosition(section, 0), logEntryList.get(section).size());
|
||||
notifyItemRangeInserted(getItemPosition(section, 0), logEntries.get(section).size());
|
||||
}
|
||||
rotate.setDuration(300);
|
||||
rotate.setFillAfter(true);
|
||||
@@ -84,17 +81,16 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
||||
|
||||
@Override
|
||||
public void onBindItemViewHolder(LogViewHolder holder, int section, int position) {
|
||||
int sqlPosition = logEntryList.get(section).get(position);
|
||||
suLogCursor.moveToPosition(sqlPosition);
|
||||
SuLogEntry entry = new SuLogEntry(suLogCursor);
|
||||
holder.setExpanded(itemExpanded.contains(sqlPosition));
|
||||
SuLogEntry entry = logEntries.get(section).get(position);
|
||||
int realIdx = getItemPosition(section, position);
|
||||
holder.setExpanded(itemExpanded.contains(realIdx));
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.isExpanded()) {
|
||||
holder.collapse();
|
||||
itemExpanded.remove(sqlPosition);
|
||||
itemExpanded.remove(realIdx);
|
||||
} else {
|
||||
holder.expand();
|
||||
itemExpanded.add(sqlPosition);
|
||||
itemExpanded.add(realIdx);
|
||||
}
|
||||
});
|
||||
holder.appName.setText(entry.appName);
|
||||
@@ -106,42 +102,39 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
||||
}
|
||||
|
||||
public void notifyDBChanged() {
|
||||
if (suLogCursor != null)
|
||||
suLogCursor.close();
|
||||
suLogCursor = suDB.getLogCursor();
|
||||
logEntryList = suDB.getLogStructure();
|
||||
logEntries = suDB.getLogs();
|
||||
itemExpanded.clear();
|
||||
sectionExpanded.clear();
|
||||
sectionExpanded.add(0);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public static class SectionHolder extends RecyclerView.ViewHolder {
|
||||
static class SectionHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public TextView date;
|
||||
public ImageView arrow;
|
||||
@BindView(R.id.date) TextView date;
|
||||
@BindView(R.id.arrow) ImageView arrow;
|
||||
|
||||
SectionHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new SuLogAdapter$SectionHolder_ViewBinding(this, itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
|
||||
static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
|
||||
|
||||
public TextView appName;
|
||||
public TextView action;
|
||||
public TextView time;
|
||||
public TextView fromPid;
|
||||
public TextView toUid;
|
||||
public TextView command;
|
||||
public ViewGroup expandLayout;
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.action) TextView action;
|
||||
@BindView(R.id.time) TextView time;
|
||||
@BindView(R.id.fromPid) TextView fromPid;
|
||||
@BindView(R.id.toUid) TextView toUid;
|
||||
@BindView(R.id.command) TextView command;
|
||||
@BindView(R.id.expand_layout) ViewGroup expandLayout;
|
||||
|
||||
private Container container = new Container();
|
||||
|
||||
LogViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ViewBinder.bind(this, itemView);
|
||||
new SuLogAdapter$LogViewHolder_ViewBinding(this, itemView);
|
||||
container.expandLayout = expandLayout;
|
||||
setupExpandable();
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.utils.ISafetyNetHelper;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
@@ -32,7 +33,7 @@ public class CheckSafetyNet extends ParallelTask<Void, Void, Void> {
|
||||
private void dlSnet() throws Exception {
|
||||
Shell.sh("rm -rf " + dexPath.getParent()).exec();
|
||||
dexPath.getParentFile().mkdir();
|
||||
HttpURLConnection conn = WebService.mustRequest(Data.snetLink, null);
|
||||
HttpURLConnection conn = WebService.mustRequest(Const.Url.SNET_URL);
|
||||
try (
|
||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(dexPath));
|
||||
InputStream in = new BufferedInputStream(conn.getInputStream())) {
|
||||
@@ -51,7 +52,7 @@ public class CheckSafetyNet extends ParallelTask<Void, Void, Void> {
|
||||
.invoke(null, ISafetyNetHelper.class, dexPath.getPath(), getActivity(),
|
||||
(ISafetyNetHelper.Callback) code ->
|
||||
Topic.publish(false, Topic.SNET_CHECK_DONE, code));
|
||||
if (helper.getVersion() < Data.snetVersionCode) {
|
||||
if (helper.getVersion() < Const.SNET_EXT_VER) {
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.androidnetworking.error.ANError;
|
||||
import com.androidnetworking.interfaces.JSONObjectRequestListener;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.utils.NotificationMgr;
|
||||
import com.topjohnwu.magisk.components.Notifications;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -42,64 +42,66 @@ public class CheckUpdates {
|
||||
}
|
||||
}
|
||||
|
||||
public static void fetchUpdates() {
|
||||
String jsonStr = "";
|
||||
public static void check(Runnable cb) {
|
||||
String url;
|
||||
switch (Data.updateChannel) {
|
||||
case Const.Value.STABLE_CHANNEL:
|
||||
jsonStr = WebService.getString(Const.Url.STABLE_URL);
|
||||
url = Const.Url.STABLE_URL;
|
||||
break;
|
||||
case Const.Value.BETA_CHANNEL:
|
||||
jsonStr = WebService.getString(Const.Url.BETA_URL);
|
||||
url = Const.Url.BETA_URL;
|
||||
break;
|
||||
case Const.Value.CUSTOM_CHANNEL:
|
||||
jsonStr = WebService.getString(Data.MM().prefs.getString(Const.Key.CUSTOM_CHANNEL, ""));
|
||||
url = Data.MM().prefs.getString(Const.Key.CUSTOM_CHANNEL, "");
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject json;
|
||||
try {
|
||||
json = new JSONObject(jsonStr);
|
||||
} catch (JSONException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
JSONObject magisk = getJson(json, "magisk");
|
||||
Data.remoteMagiskVersionString = getString(magisk, "version", null);
|
||||
Data.remoteMagiskVersionCode = getInt(magisk, "versionCode", -1);
|
||||
Data.magiskLink = getString(magisk, "link", null);
|
||||
Data.magiskNoteLink = getString(magisk, "note", null);
|
||||
Data.magiskMD5 = getString(magisk, "md5", null);
|
||||
|
||||
JSONObject manager = getJson(json, "app");
|
||||
Data.remoteManagerVersionString = getString(manager, "version", null);
|
||||
Data.remoteManagerVersionCode = getInt(manager, "versionCode", -1);
|
||||
Data.managerLink = getString(manager, "link", null);
|
||||
Data.managerNoteLink = getString(manager, "note", null);
|
||||
|
||||
JSONObject uninstaller = getJson(json, "uninstaller");
|
||||
Data.uninstallerLink = getString(uninstaller, "link", null);
|
||||
|
||||
JSONObject snet = getJson(json, "snet");
|
||||
Data.snetVersionCode = getInt(snet, "versionCode", -1);
|
||||
Data.snetLink = getString(snet, "link", null);
|
||||
}
|
||||
|
||||
public static void check(Runnable cb) {
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||
fetchUpdates();
|
||||
if (cb != null) {
|
||||
if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) {
|
||||
NotificationMgr.managerUpdate();
|
||||
} else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) {
|
||||
NotificationMgr.magiskUpdate();
|
||||
}
|
||||
cb.run();
|
||||
}
|
||||
Topic.publish(Topic.UPDATE_CHECK_DONE);
|
||||
});
|
||||
AndroidNetworking.get(url).build().getAsJSONObject(new UpdateListener(cb));
|
||||
}
|
||||
|
||||
public static void check() {
|
||||
check(null);
|
||||
}
|
||||
|
||||
private static class UpdateListener implements JSONObjectRequestListener {
|
||||
|
||||
private Runnable cb;
|
||||
|
||||
UpdateListener(Runnable callback) {
|
||||
cb = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(JSONObject json) {
|
||||
JSONObject magisk = getJson(json, "magisk");
|
||||
Data.remoteMagiskVersionString = getString(magisk, "version", null);
|
||||
Data.remoteMagiskVersionCode = getInt(magisk, "versionCode", -1);
|
||||
Data.magiskLink = getString(magisk, "link", null);
|
||||
Data.magiskNoteLink = getString(magisk, "note", null);
|
||||
Data.magiskMD5 = getString(magisk, "md5", null);
|
||||
|
||||
JSONObject manager = getJson(json, "app");
|
||||
Data.remoteManagerVersionString = getString(manager, "version", null);
|
||||
Data.remoteManagerVersionCode = getInt(manager, "versionCode", -1);
|
||||
Data.managerLink = getString(manager, "link", null);
|
||||
Data.managerNoteLink = getString(manager, "note", null);
|
||||
|
||||
JSONObject uninstaller = getJson(json, "uninstaller");
|
||||
Data.uninstallerLink = getString(uninstaller, "link", null);
|
||||
|
||||
if (cb != null) {
|
||||
if (BuildConfig.VERSION_CODE < Data.remoteManagerVersionCode) {
|
||||
Notifications.managerUpdate();
|
||||
} else if (Data.magiskVersionCode < Data.remoteMagiskVersionCode) {
|
||||
Notifications.magiskUpdate();
|
||||
}
|
||||
cb.run();
|
||||
}
|
||||
Topic.publish(Topic.UPDATE_CHECK_DONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ANError anError) {}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,125 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
import com.topjohnwu.magisk.components.ProgressNotification;
|
||||
import com.topjohnwu.magisk.container.Repo;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class DownloadModule {
|
||||
|
||||
public static void exec(BaseActivity activity, Repo repo, boolean install) {
|
||||
activity.runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
|
||||
() -> AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> dlProcessInstall(repo, install)));
|
||||
}
|
||||
|
||||
private static void dlProcessInstall(Repo repo, boolean install) {
|
||||
File output = new File(Const.EXTERNAL_PATH, repo.getDownloadFilename());
|
||||
ProgressNotification progress = new ProgressNotification(output.getName());
|
||||
try {
|
||||
MagiskManager mm = Data.MM();
|
||||
HttpURLConnection conn = WebService.mustRequest(repo.getZipUrl());
|
||||
ProgressInputStream pis = new ProgressInputStream(conn.getInputStream(),
|
||||
conn.getContentLength(), progress);
|
||||
removeTopFolder(new BufferedInputStream(pis),
|
||||
new BufferedOutputStream(new FileOutputStream(output)));
|
||||
conn.disconnect();
|
||||
if (install) {
|
||||
progress.dismiss();
|
||||
Intent intent = new Intent(mm, Data.classMap.get(FlashActivity.class));
|
||||
intent.setData(Uri.fromFile(output))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
||||
mm.startActivity(intent);
|
||||
} else {
|
||||
progress.getNotification().setContentTitle(output.getName());
|
||||
progress.dlDone();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
progress.dlFail();
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeTopFolder(InputStream in, OutputStream out) throws IOException {
|
||||
try (ZipInputStream zin = new ZipInputStream(in);
|
||||
ZipOutputStream zout = new ZipOutputStream(out)) {
|
||||
ZipEntry entry;
|
||||
int off = -1;
|
||||
while ((entry = zin.getNextEntry()) != null) {
|
||||
if (off < 0)
|
||||
off = entry.getName().indexOf('/') + 1;
|
||||
String path = entry.getName().substring(off);
|
||||
if (path.isEmpty())
|
||||
continue;
|
||||
zout.putNextEntry(new ZipEntry(path));
|
||||
if (!entry.isDirectory())
|
||||
ShellUtils.pump(zin, zout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProgressInputStream extends FilterInputStream {
|
||||
|
||||
private long totalBytes;
|
||||
private long bytesDownloaded;
|
||||
private ProgressNotification progress;
|
||||
|
||||
protected ProgressInputStream(InputStream in, long size, ProgressNotification p) {
|
||||
super(in);
|
||||
totalBytes = size;
|
||||
progress = p;
|
||||
}
|
||||
|
||||
private void updateProgress() {
|
||||
progress.onProgress(bytesDownloaded, totalBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
int b = super.read();
|
||||
if (b >= 0) {
|
||||
bytesDownloaded++;
|
||||
updateProgress();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
int sz = super.read(b, off, len);
|
||||
if (sz > 0) {
|
||||
bytesDownloaded += sz;
|
||||
updateProgress();
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,7 +14,6 @@ import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.container.TarEntry;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||
@@ -136,7 +135,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
if (!ShellUtils.checkSum("MD5", zip, Data.magiskMD5)) {
|
||||
console.add("- Downloading zip");
|
||||
HttpURLConnection conn = WebService.mustRequest(Data.magiskLink, null);
|
||||
HttpURLConnection conn = WebService.mustRequest(Data.magiskLink);
|
||||
buf = new BufferedInputStream(new ProgressStream(conn), conn.getContentLength());
|
||||
buf.mark(conn.getContentLength() + 1);
|
||||
try (OutputStream out = new FileOutputStream(zip)) {
|
||||
@@ -243,7 +242,7 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||
switch (mode) {
|
||||
case PATCH_MODE:
|
||||
String fmt = mm.prefs.getString(Const.Key.BOOT_FORMAT, ".img");
|
||||
File dest = new File(Download.EXTERNAL_PATH, "patched_boot" + fmt);
|
||||
File dest = new File(Const.EXTERNAL_PATH, "patched_boot" + fmt);
|
||||
dest.getParentFile().mkdirs();
|
||||
OutputStream out;
|
||||
switch (fmt) {
|
||||
|
@@ -6,7 +6,7 @@ import android.webkit.WebView;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
@@ -43,7 +43,7 @@ public class MarkDownWindow extends ParallelTask<Void, Void, String> {
|
||||
MagiskManager mm = Data.MM();
|
||||
String md;
|
||||
if (mUrl != null) {
|
||||
md = WebService.getString(mUrl);
|
||||
md = Utils.dlString(mUrl);
|
||||
} else {
|
||||
try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
|
||||
ShellUtils.pump(is, out);
|
||||
|
@@ -1,41 +1,53 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.AsyncTask;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.components.Notifications;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
import com.topjohnwu.superuser.io.SuFileOutputStream;
|
||||
import com.topjohnwu.utils.JarMap;
|
||||
import com.topjohnwu.utils.SignAPK;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
public class PatchAPK {
|
||||
|
||||
public static final String LOWERALPHA = "abcdefghijklmnopqrstuvwxyz";
|
||||
public static final String UPPERALPHA = LOWERALPHA.toUpperCase();
|
||||
public static final String ALPHA = LOWERALPHA + UPPERALPHA;
|
||||
public static final String DIGITS = "0123456789";
|
||||
public static final String ALPHANUM = ALPHA + DIGITS;
|
||||
public static final String ALPHANUMDOTS = ALPHANUM + "............";
|
||||
|
||||
private static String genPackageName(String prefix, int length) {
|
||||
StringBuilder builder = new StringBuilder(length);
|
||||
builder.append(prefix);
|
||||
length -= prefix.length();
|
||||
SecureRandom random = new SecureRandom();
|
||||
String base = "abcdefghijklmnopqrstuvwxyz";
|
||||
String alpha = base + base.toUpperCase();
|
||||
String full = alpha + "0123456789..........";
|
||||
char next, prev = '\0';
|
||||
char next, prev = '.';
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (prev == '.' || i == length - 1 || i == 0) {
|
||||
next = alpha.charAt(random.nextInt(alpha.length()));
|
||||
if (prev == '.' || i == length - 1) {
|
||||
next = ALPHA.charAt(random.nextInt(ALPHA.length()));
|
||||
} else {
|
||||
next = full.charAt(random.nextInt(full.length()));
|
||||
next = ALPHANUMDOTS.charAt(random.nextInt(ALPHANUMDOTS.length()));
|
||||
}
|
||||
builder.append(next);
|
||||
prev = next;
|
||||
@@ -43,88 +55,81 @@ public class PatchAPK {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private static int findOffset(byte buf[], byte pattern[]) {
|
||||
private static boolean findAndPatch(byte xml[], String a, String b) {
|
||||
if (a.length() != b.length())
|
||||
return false;
|
||||
char[] from = a.toCharArray(), to = b.toCharArray();
|
||||
CharBuffer buf = ByteBuffer.wrap(xml).order(ByteOrder.LITTLE_ENDIAN).asCharBuffer();
|
||||
int offset = -1;
|
||||
for (int i = 0; i < buf.length - pattern.length; ++i) {
|
||||
for (int i = 0; i < buf.length() - from.length; ++i) {
|
||||
boolean match = true;
|
||||
for (int j = 0; j < pattern.length; ++j) {
|
||||
if (buf[i + j] != pattern[j]) {
|
||||
for (int j = 0; j < from.length; ++j) {
|
||||
if (buf.get(i + j) != from[j]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
// Make sure it is null terminated
|
||||
if (match && buf.get(i + from.length) == '\0') {
|
||||
offset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* It seems that AAPT sometimes generate another type of string format */
|
||||
private static boolean fallbackPatch(byte xml[], String from, String to) {
|
||||
|
||||
byte[] target = new byte[from.length() * 2 + 2];
|
||||
for (int i = 0; i < from.length(); ++i) {
|
||||
target[i * 2] = (byte) from.charAt(i);
|
||||
}
|
||||
int offset = findOffset(xml, target);
|
||||
if (offset < 0)
|
||||
return false;
|
||||
byte[] dest = new byte[target.length - 2];
|
||||
for (int i = 0; i < to.length(); ++i) {
|
||||
dest[i * 2] = (byte) to.charAt(i);
|
||||
}
|
||||
System.arraycopy(dest, 0, xml, offset, dest.length);
|
||||
buf.position(offset);
|
||||
buf.put(to);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean findAndPatch(byte xml[], String from, String to) {
|
||||
byte target[] = (from + '\0').getBytes();
|
||||
int offset = findOffset(xml, target);
|
||||
if (offset < 0)
|
||||
return fallbackPatch(xml, from, to);
|
||||
System.arraycopy(to.getBytes(), 0, xml, offset, to.length());
|
||||
return true;
|
||||
private static boolean findAndPatch(byte xml[], int a, int b) {
|
||||
IntBuffer buf = ByteBuffer.wrap(xml).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer();
|
||||
int len = xml.length / 4;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
if (buf.get(i) == a) {
|
||||
buf.put(i, b);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean patchAndHide() {
|
||||
MagiskManager mm = Data.MM();
|
||||
|
||||
// Generate a new app with random package name
|
||||
SuFile repack = new SuFile("/data/local/tmp/repack.apk");
|
||||
String pkg = genPackageName("com.", Const.ORIG_PKG_NAME.length());
|
||||
File repack = new File(mm.getFilesDir(), "patched.apk");
|
||||
String pkg = genPackageName("com.", BuildConfig.APPLICATION_ID.length());
|
||||
|
||||
try {
|
||||
JarMap apk = new JarMap(mm.getPackageCodePath());
|
||||
if (!patchPackageID(apk, Const.ORIG_PKG_NAME, pkg))
|
||||
if (!patch(apk, pkg))
|
||||
return false;
|
||||
SignAPK.sign(apk, new SuFileOutputStream(repack));
|
||||
SignAPK.sign(apk, new BufferedOutputStream(new FileOutputStream(repack)));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Install the application
|
||||
repack.setReadable(true, false);
|
||||
if (!ShellUtils.fastCmdResult("pm install " + repack))
|
||||
return false;
|
||||
|
||||
repack.delete();
|
||||
return false;;
|
||||
|
||||
mm.mDB.setStrings(Const.Key.SU_MANAGER, pkg);
|
||||
Data.exportPrefs();
|
||||
RootUtils.uninstallPkg(Const.ORIG_PKG_NAME);
|
||||
RootUtils.rmAndLaunch(BuildConfig.APPLICATION_ID, pkg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean patchPackageID(JarMap apk, String from, String to) {
|
||||
public static boolean patch(JarMap apk, String pkg) {
|
||||
try {
|
||||
JarEntry je = apk.getJarEntry(Const.ANDROID_MANIFEST);
|
||||
byte xml[] = apk.getRawData(je);
|
||||
|
||||
if (!findAndPatch(xml, from, to))
|
||||
return false;
|
||||
if (!findAndPatch(xml, from + ".provider", to + ".provider"))
|
||||
if (!findAndPatch(xml, BuildConfig.APPLICATION_ID, pkg) ||
|
||||
!findAndPatch(xml, BuildConfig.APPLICATION_ID + ".provider", pkg + ".provider") ||
|
||||
!findAndPatch(xml, R.string.app_name, R.string.re_app_name))
|
||||
return false;
|
||||
|
||||
// Write in changes
|
||||
@@ -136,18 +141,16 @@ public class PatchAPK {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void hideManager(Activity activity) {
|
||||
ProgressDialog dialog = ProgressDialog.show(activity,
|
||||
activity.getString(R.string.hide_manager_toast),
|
||||
activity.getString(R.string.hide_manager_toast2));
|
||||
public static void hideManager() {
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||
MagiskManager mm = Data.MM();
|
||||
NotificationCompat.Builder progress =
|
||||
Notifications.progress(mm.getString(R.string.hide_manager_title));
|
||||
NotificationManagerCompat mgr = NotificationManagerCompat.from(mm);
|
||||
mgr.notify(Const.ID.HIDE_MANAGER_NOTIFICATION_ID, progress.build());
|
||||
boolean b = patchAndHide();
|
||||
Data.mainHandler.post(() -> {
|
||||
dialog.cancel();
|
||||
if (!b) {
|
||||
Utils.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
|
||||
}
|
||||
});
|
||||
mgr.cancel(Const.ID.HIDE_MANAGER_NOTIFICATION_ID);
|
||||
if (!b) Utils.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -1,197 +0,0 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.container.Repo;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
|
||||
|
||||
private ProgressDialog progressDialog;
|
||||
private boolean mInstall;
|
||||
private File mFile;
|
||||
private Repo mRepo;
|
||||
private int progress = 0, total = -1;
|
||||
|
||||
public ProcessRepoZip(BaseActivity context, Repo repo, boolean install) {
|
||||
super(context);
|
||||
mRepo = repo;
|
||||
mInstall = install && Shell.rootAccess();
|
||||
mFile = new File(Download.EXTERNAL_PATH, repo.getDownloadFilename());
|
||||
}
|
||||
|
||||
private void removeTopFolder(File input, File output) throws IOException {
|
||||
JarEntry entry;
|
||||
try (
|
||||
JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(input)));
|
||||
JarOutputStream out = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output)))
|
||||
) {
|
||||
String path;
|
||||
while ((entry = in.getNextJarEntry()) != null) {
|
||||
// Remove the top directory from the path
|
||||
path = entry.getName().substring(entry.getName().indexOf("/") + 1);
|
||||
// If it's the top folder, ignore it
|
||||
if (path.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// Don't include placeholder
|
||||
if (path.equals("system/placeholder")) {
|
||||
continue;
|
||||
}
|
||||
out.putNextEntry(new JarEntry(path));
|
||||
ShellUtils.pump(in, out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseActivity getActivity() {
|
||||
return (BaseActivity) super.getActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
BaseActivity activity = getActivity();
|
||||
mFile.getParentFile().mkdirs();
|
||||
progressDialog = ProgressDialog.show(activity, activity.getString(R.string.zip_download_title), activity.getString(R.string.zip_download_msg, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
BaseActivity activity = getActivity();
|
||||
if (activity == null) return null;
|
||||
try {
|
||||
// Request zip from Internet
|
||||
HttpURLConnection conn = WebService.mustRequest(mRepo.getZipUrl(), null);
|
||||
total = conn.getContentLength();
|
||||
|
||||
// Temp files
|
||||
File temp1 = new File(activity.getCacheDir(), "1.zip");
|
||||
File temp2 = new File(temp1.getParentFile(), "2.zip");
|
||||
temp1.getParentFile().mkdir();
|
||||
|
||||
// First download the zip, Web -> temp1
|
||||
try (
|
||||
InputStream in = new BufferedInputStream(new ProgressInputStream(conn.getInputStream()));
|
||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(temp1))
|
||||
) {
|
||||
ShellUtils.pump(in, out);
|
||||
in.close();
|
||||
}
|
||||
conn.disconnect();
|
||||
|
||||
Data.mainHandler.post(() -> {
|
||||
progressDialog.setTitle(R.string.zip_process_title);
|
||||
progressDialog.setMessage(getActivity().getString(R.string.zip_process_msg));
|
||||
});
|
||||
|
||||
// First remove top folder in Github source zip, temp1 -> temp2
|
||||
removeTopFolder(temp1, temp2);
|
||||
|
||||
// Then sign the zip
|
||||
ZipUtils.signZip(temp2, mFile);
|
||||
|
||||
// Delete temp files
|
||||
temp1.delete();
|
||||
temp2.delete();
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
BaseActivity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
progressDialog.dismiss();
|
||||
if (result) {
|
||||
Uri uri = Uri.fromFile(mFile);
|
||||
if (mInstall) {
|
||||
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class));
|
||||
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
||||
activity.startActivity(intent);
|
||||
} else {
|
||||
SnackbarMaker.showUri(activity, uri);
|
||||
}
|
||||
} else {
|
||||
Utils.toast(R.string.process_error, Toast.LENGTH_LONG);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exec(Void... voids) {
|
||||
getActivity().runWithPermission(
|
||||
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, super::exec);
|
||||
}
|
||||
|
||||
private class ProgressInputStream extends FilterInputStream {
|
||||
|
||||
ProgressInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
private void updateDlProgress(int step) {
|
||||
progress += step;
|
||||
progressDialog.setMessage(getActivity().getString(R.string.zip_download_msg,
|
||||
(int) (100 * (double) progress / total + 0.5)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read() throws IOException {
|
||||
int b = super.read();
|
||||
if (b > 0) {
|
||||
Data.mainHandler.post(() -> updateDlProgress(1));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(@NonNull byte[] b) throws IOException {
|
||||
return read(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int read(@NonNull byte[] b, int off, int len) throws IOException {
|
||||
int read = super.read(b, off, len);
|
||||
if (read > 0) {
|
||||
Data.mainHandler.post(() -> updateDlProgress(read));
|
||||
}
|
||||
return read;
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,14 +3,15 @@ package com.topjohnwu.magisk.asyncs;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.androidnetworking.common.ANRequest;
|
||||
import com.androidnetworking.common.ANResponse;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.container.Repo;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -22,9 +23,7 @@ import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -32,51 +31,45 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UpdateRepos {
|
||||
|
||||
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
|
||||
private static final int CORE_POOL_SIZE = Math.max(2, CPU_COUNT - 1);
|
||||
private static final DateFormat dateFormat;
|
||||
|
||||
private MagiskManager mm;
|
||||
private Set<String> cached;
|
||||
private ExecutorService threadPool;
|
||||
|
||||
static {
|
||||
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
|
||||
private MagiskManager mm;
|
||||
private Set<String> cached;
|
||||
private ExecutorService threadPool;
|
||||
|
||||
public UpdateRepos() {
|
||||
mm = Data.MM();
|
||||
}
|
||||
|
||||
private void waitTasks() {
|
||||
threadPool.shutdown();
|
||||
try {
|
||||
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
while (true) {
|
||||
try {
|
||||
if (threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
|
||||
break;
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadJSON(String jsonString) throws JSONException, ParseException {
|
||||
JSONArray jsonArray = new JSONArray(jsonString);
|
||||
|
||||
// Empty page, halt
|
||||
if (jsonArray.length() == 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < jsonArray.length(); i++) {
|
||||
JSONObject rawRepo = jsonArray.getJSONObject(i);
|
||||
String id = rawRepo.getString("description");
|
||||
String name = rawRepo.getString("name");
|
||||
private void loadJSON(JSONArray array) throws JSONException, ParseException {
|
||||
for (int i = 0; i < array.length(); i++) {
|
||||
JSONObject rawRepo = array.getJSONObject(i);
|
||||
String id = rawRepo.getString("name");
|
||||
Date date = dateFormat.parse(rawRepo.getString("pushed_at"));
|
||||
Set<String> set = Collections.synchronizedSet(cached);
|
||||
threadPool.execute(() -> {
|
||||
Repo repo = mm.repoDB.getRepo(id);
|
||||
try {
|
||||
if (repo == null)
|
||||
repo = new Repo(name);
|
||||
repo = new Repo(id);
|
||||
else
|
||||
set.remove(id);
|
||||
cached.remove(id);
|
||||
repo.update(date);
|
||||
mm.repoDB.addRepo(repo);
|
||||
} catch (Repo.IllegalRepoException e) {
|
||||
@@ -85,42 +78,50 @@ public class UpdateRepos {
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* We sort repos by last push, which means that we only need to check whether the
|
||||
* first page is updated to determine whether the online repo database is changed
|
||||
*/
|
||||
private boolean loadPage(int page) {
|
||||
Map<String, String> header = new HashMap<>();
|
||||
if (page == 0)
|
||||
header.put(Const.Key.IF_NONE_MATCH, mm.prefs.getString(Const.Key.ETAG_KEY, ""));
|
||||
String url = Utils.fmt(Const.Url.REPO_URL, page + 1);
|
||||
ANRequest.GetRequestBuilder req = AndroidNetworking.get(Const.Url.REPO_URL)
|
||||
.addQueryParameter("page", String.valueOf(page + 1));
|
||||
if (page == 0) {
|
||||
String etag = mm.prefs.getString(Const.Key.ETAG_KEY, null);
|
||||
if (etag != null)
|
||||
req.addHeaders(Const.Key.IF_NONE_MATCH, etag);
|
||||
}
|
||||
ANResponse<JSONArray> res = req.build().executeForJSONArray();
|
||||
if (res.getOkHttpResponse().code() == HttpURLConnection.HTTP_NOT_MODIFIED)
|
||||
return false;
|
||||
// Current page is the last page
|
||||
if (res.getResult() == null || res.getResult().length() == 0)
|
||||
return true;
|
||||
|
||||
try {
|
||||
HttpURLConnection conn = WebService.request(url, header);
|
||||
// No updates
|
||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED)
|
||||
return false;
|
||||
// Current page is the last page
|
||||
if (!loadJSON(WebService.getString(conn)))
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
loadJSON(res.getResult());
|
||||
} catch (JSONException | ParseException e) {
|
||||
// Should not happen, but if exception occurs, page load fails
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update ETAG
|
||||
if (page == 0) {
|
||||
String etag = header.get(Const.Key.ETAG_KEY);
|
||||
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
|
||||
mm.prefs.edit().putString(Const.Key.ETAG_KEY, etag).apply();
|
||||
String etag = res.getOkHttpResponse().header(Const.Key.ETAG_KEY);
|
||||
if (etag != null) {
|
||||
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
|
||||
mm.prefs.edit().putString(Const.Key.ETAG_KEY, etag).apply();
|
||||
}
|
||||
}
|
||||
|
||||
String links = header.get(Const.Key.LINK_KEY);
|
||||
String links = res.getOkHttpResponse().header(Const.Key.LINK_KEY);
|
||||
return links == null || !links.contains("next") || loadPage(page + 1);
|
||||
}
|
||||
|
||||
private boolean loadPages() {
|
||||
return loadPage(0);
|
||||
}
|
||||
|
||||
private void fullReload() {
|
||||
Cursor c = mm.repoDB.getRawCursor();
|
||||
while (c.moveToNext()) {
|
||||
@@ -141,10 +142,10 @@ public class UpdateRepos {
|
||||
public void exec(boolean force) {
|
||||
Topic.reset(Topic.REPO_LOAD_DONE);
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||
cached = mm.repoDB.getRepoIDSet();
|
||||
cached = Collections.synchronizedSet(mm.repoDB.getRepoIDSet());
|
||||
threadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE);
|
||||
|
||||
if (loadPage(0)) {
|
||||
if (loadPages()) {
|
||||
waitTasks();
|
||||
// The leftover cached means they are removed from online repo
|
||||
mm.repoDB.removeRepo(cached);
|
||||
|
@@ -27,17 +27,18 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* @author dvdandroid
|
||||
*/
|
||||
public class AboutCardRow extends LinearLayout {
|
||||
|
||||
public TextView mTitle;
|
||||
public TextView mSummary;
|
||||
public ImageView mIcon;
|
||||
public View mView;
|
||||
@BindView(android.R.id.title) TextView mTitle;
|
||||
@BindView(android.R.id.summary) TextView mSummary;
|
||||
@BindView(android.R.id.icon) ImageView mIcon;
|
||||
@BindView(R.id.container) View mView;
|
||||
|
||||
public AboutCardRow(Context context) {
|
||||
this(context, null);
|
||||
@@ -50,7 +51,7 @@ public class AboutCardRow extends LinearLayout {
|
||||
public AboutCardRow(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
LayoutInflater.from(context).inflate(R.layout.info_item_row, this);
|
||||
ViewBinder.bind(this, this);
|
||||
new AboutCardRow_ViewBinding(this, this);
|
||||
|
||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AboutCardRow, 0, 0);
|
||||
String title;
|
||||
|
@@ -2,35 +2,37 @@ package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.NoUIActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
public abstract class FlavorActivity extends AppCompatActivity implements Topic.AutoSubscriber {
|
||||
public abstract class BaseActivity extends AppCompatActivity implements Topic.AutoSubscriber {
|
||||
|
||||
public static final String INTENT_PERM = "perm_dialog";
|
||||
|
||||
protected static Runnable permissionGrantCallback;
|
||||
static int[] EMPTY_INT_ARRAY = new int[0];
|
||||
|
||||
private ActivityResultListener activityResultListener;
|
||||
static int[] EMPTY_INT_ARRAY = new int[0];
|
||||
public MagiskManager mm;
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
Configuration config = base.getResources().getConfiguration();
|
||||
config.setLocale(LocaleManager.locale);
|
||||
applyOverrideConfiguration(config);
|
||||
mm = Data.MM();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSubscribedTopics() {
|
||||
return EMPTY_INT_ARRAY;
|
||||
@@ -41,6 +43,15 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
Configuration config = base.getResources().getConfiguration();
|
||||
config.setLocale(LocaleManager.locale);
|
||||
applyOverrideConfiguration(config);
|
||||
mm = Data.MM();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
Topic.subscribe(this);
|
||||
@@ -48,6 +59,9 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
|
||||
setTheme(getDarkTheme());
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
String[] perms = getIntent().getStringArrayExtra(INTENT_PERM);
|
||||
if (perms != null)
|
||||
ActivityCompat.requestPermissions(this, perms, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,6 +84,34 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
|
||||
}
|
||||
}
|
||||
|
||||
public static void runWithPermission(Context context, String[] permissions, Runnable callback) {
|
||||
boolean granted = true;
|
||||
for (String perm : permissions) {
|
||||
if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED)
|
||||
granted = false;
|
||||
}
|
||||
if (granted) {
|
||||
Const.EXTERNAL_PATH.mkdirs();
|
||||
callback.run();
|
||||
} else {
|
||||
// Passed in context should be an activity if not granted, need to show dialog!
|
||||
permissionGrantCallback = callback;
|
||||
if (!(context instanceof BaseActivity)) {
|
||||
// Start NoUIActivity to show dialog
|
||||
Intent intent = new Intent(context, Data.classMap.get(NoUIActivity.class));
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(INTENT_PERM, permissions);
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
ActivityCompat.requestPermissions((BaseActivity) context, permissions, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void runWithPermission(String[] permissions, Runnable callback) {
|
||||
runWithPermission(this, permissions, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (activityResultListener != null)
|
||||
@@ -82,6 +124,23 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
|
||||
super.startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
boolean grant = true;
|
||||
for (int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED)
|
||||
grant = false;
|
||||
}
|
||||
if (grant) {
|
||||
if (permissionGrantCallback != null) {
|
||||
permissionGrantCallback.run();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, R.string.no_rw_storage, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
permissionGrantCallback = null;
|
||||
}
|
||||
|
||||
public interface ActivityResultListener {
|
||||
void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
}
|
@@ -7,10 +7,12 @@ import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
||||
|
||||
public MagiskManager mm;
|
||||
protected Unbinder unbinder = null;
|
||||
|
||||
public BaseFragment() {
|
||||
mm = Data.MM();
|
||||
@@ -28,6 +30,13 @@ public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (unbinder != null)
|
||||
unbinder.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivityForResult(Intent intent, int requestCode) {
|
||||
startActivityForResult(intent, requestCode, this::onActivityResult);
|
||||
@@ -43,6 +52,6 @@ public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
||||
|
||||
@Override
|
||||
public int[] getSubscribedTopics() {
|
||||
return FlavorActivity.EMPTY_INT_ARRAY;
|
||||
return BaseActivity.EMPTY_INT_ARRAY;
|
||||
}
|
||||
}
|
||||
|
@@ -9,13 +9,13 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class CustomAlertDialog extends AlertDialog.Builder {
|
||||
|
||||
@@ -27,16 +27,16 @@ public class CustomAlertDialog extends AlertDialog.Builder {
|
||||
private ViewHolder vh;
|
||||
|
||||
public class ViewHolder {
|
||||
public LinearLayout dialogLayout;
|
||||
public LinearLayout buttons;
|
||||
@BindView(R.id.dialog_layout) public LinearLayout dialogLayout;
|
||||
@BindView(R.id.button_panel) public LinearLayout buttons;
|
||||
|
||||
public TextView messageView;
|
||||
public Button negative;
|
||||
public Button positive;
|
||||
public Button neutral;
|
||||
@BindView(R.id.message) public TextView messageView;
|
||||
@BindView(R.id.negative) public Button negative;
|
||||
@BindView(R.id.positive) public Button positive;
|
||||
@BindView(R.id.neutral) public Button neutral;
|
||||
|
||||
ViewHolder(View v) {
|
||||
ViewBinder.bind(this, v);
|
||||
new CustomAlertDialog$ViewHolder_ViewBinding(this, v);
|
||||
messageView.setVisibility(View.GONE);
|
||||
negative.setVisibility(View.GONE);
|
||||
positive.setVisibility(View.GONE);
|
||||
|
@@ -1,17 +1,18 @@
|
||||
package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.androidnetworking.error.ANError;
|
||||
import com.androidnetworking.interfaces.DownloadListener;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.util.List;
|
||||
@@ -27,33 +28,10 @@ class InstallMethodDialog extends AlertDialog.Builder {
|
||||
Intent intent;
|
||||
switch (idx) {
|
||||
case 1:
|
||||
if (Data.remoteMagiskVersionCode < 1400) {
|
||||
SnackbarMaker.make(activity, R.string.no_boot_file_patch_support,
|
||||
Snackbar.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
Utils.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
|
||||
intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*");
|
||||
activity.startActivityForResult(intent, Const.ID.SELECT_BOOT,
|
||||
(requestCode, resultCode, data) -> {
|
||||
if (requestCode == Const.ID.SELECT_BOOT &&
|
||||
resultCode == BaseActivity.RESULT_OK && data != null) {
|
||||
Intent i = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
|
||||
activity.startActivity(i);
|
||||
}
|
||||
});
|
||||
patchBoot(activity);
|
||||
break;
|
||||
case 0:
|
||||
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
||||
Data.remoteMagiskVersionString, Data.remoteMagiskVersionCode);
|
||||
Download.receive(activity, new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Context context, Uri uri) {
|
||||
SnackbarMaker.showUri(activity, uri);
|
||||
}
|
||||
}, Data.magiskLink, filename);
|
||||
downloadOnly(activity);
|
||||
break;
|
||||
case 2:
|
||||
intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||
@@ -61,20 +39,67 @@ class InstallMethodDialog extends AlertDialog.Builder {
|
||||
activity.startActivity(intent);
|
||||
break;
|
||||
case 3:
|
||||
new CustomAlertDialog(activity)
|
||||
.setTitle(R.string.warning)
|
||||
.setMessage(R.string.install_inactive_slot_msg)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.yes, (d, i) -> {
|
||||
Intent it = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT);
|
||||
activity.startActivity(it);
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
installInactiveSlot(activity);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void patchBoot(BaseActivity a) {
|
||||
Utils.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*");
|
||||
a.runWithPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, () ->
|
||||
a.startActivityForResult(intent, Const.ID.SELECT_BOOT,
|
||||
(requestCode, resultCode, data) -> {
|
||||
if (requestCode == Const.ID.SELECT_BOOT &&
|
||||
resultCode == Activity.RESULT_OK && data != null) {
|
||||
Intent i = new Intent(a, Data.classMap.get(FlashActivity.class))
|
||||
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
|
||||
a.startActivity(i);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private void downloadOnly(BaseActivity a) {
|
||||
a.runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
|
||||
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
||||
Data.remoteMagiskVersionString, Data.remoteMagiskVersionCode);
|
||||
ProgressNotification progress = new ProgressNotification(filename);
|
||||
AndroidNetworking
|
||||
.download(Data.magiskLink, Const.EXTERNAL_PATH.getPath(), filename)
|
||||
.build()
|
||||
.setDownloadProgressListener(progress)
|
||||
.startDownload(new DownloadListener() {
|
||||
@Override
|
||||
public void onDownloadComplete() {
|
||||
progress.dlDone();
|
||||
SnackbarMaker.make(a,
|
||||
a.getString(R.string.internal_storage, "/Download/" + filename),
|
||||
Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ANError anError) {
|
||||
progress.dlFail();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void installInactiveSlot(BaseActivity activity) {
|
||||
new CustomAlertDialog(activity)
|
||||
.setTitle(R.string.warning)
|
||||
.setMessage(R.string.install_inactive_slot_msg)
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.yes, (d, i) -> {
|
||||
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT);
|
||||
activity.startActivity(intent);
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,12 @@
|
||||
package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.MarkDownWindow;
|
||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||
import com.topjohnwu.magisk.utils.DlInstallManager;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -19,19 +16,13 @@ public class ManagerInstallDialog extends CustomAlertDialog {
|
||||
public ManagerInstallDialog(@NonNull BaseActivity activity) {
|
||||
super(activity);
|
||||
MagiskManager mm = Data.MM();
|
||||
String filename = Utils.fmt("MagiskManager-v%s(%d).apk",
|
||||
String name = Utils.fmt("MagiskManager v%s(%d)",
|
||||
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
|
||||
setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.app_name)));
|
||||
setMessage(mm.getString(R.string.repo_install_msg, filename));
|
||||
setMessage(mm.getString(R.string.repo_install_msg, name));
|
||||
setCancelable(true);
|
||||
setPositiveButton(R.string.install, (d, i) -> activity.runWithPermission(
|
||||
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
||||
Intent intent = new Intent(mm, Data.classMap.get(ManagerUpdate.class));
|
||||
intent.putExtra(Const.Key.INTENT_SET_LINK, Data.managerLink);
|
||||
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
||||
mm.sendBroadcast(intent);
|
||||
}))
|
||||
.setNegativeButton(R.string.no_thanks, null);
|
||||
setPositiveButton(R.string.install, (d, i) -> DlInstallManager.upgrade(name));
|
||||
setNegativeButton(R.string.no_thanks, null);
|
||||
if (!TextUtils.isEmpty(Data.managerNoteLink)) {
|
||||
setNeutralButton(R.string.app_changelog, (d, i) ->
|
||||
new MarkDownWindow(activity, null, Data.managerNoteLink).exec());
|
||||
|
@@ -1,22 +1,39 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.SplashActivity;
|
||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
||||
import com.topjohnwu.magisk.receivers.GeneralReceiver;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.app.TaskStackBuilder;
|
||||
|
||||
public class NotificationMgr {
|
||||
public class Notifications {
|
||||
|
||||
public static void setup(Context c) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationManager mgr = c.getSystemService(NotificationManager.class);
|
||||
mgr.deleteNotificationChannel("magisk_notification");
|
||||
NotificationChannel channel =
|
||||
new NotificationChannel(Const.ID.UPDATE_NOTIFICATION_CHANNEL,
|
||||
c.getString(R.string.update_channel), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
mgr.createNotificationChannel(channel);
|
||||
channel = new NotificationChannel(Const.ID.PROGRESS_NOTIFICATION_CHANNEL,
|
||||
c.getString(R.string.progress_channel), NotificationManager.IMPORTANCE_LOW);
|
||||
mgr.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static void magiskUpdate() {
|
||||
MagiskManager mm = Data.MM();
|
||||
@@ -29,7 +46,7 @@ public class NotificationMgr {
|
||||
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(mm.getString(R.string.magisk_update_title))
|
||||
.setContentText(mm.getString(R.string.magisk_update_available, Data.remoteMagiskVersionString))
|
||||
@@ -37,23 +54,23 @@ public class NotificationMgr {
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
NotificationManagerCompat mgr = NotificationManagerCompat.from(mm);
|
||||
mgr.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
public static void managerUpdate() {
|
||||
MagiskManager mm = Data.MM();
|
||||
String filename = Utils.fmt("MagiskManager-v%s(%d).apk",
|
||||
String name = Utils.fmt("MagiskManager v%s(%d)",
|
||||
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
|
||||
|
||||
Intent intent = new Intent(mm, Data.classMap.get(ManagerUpdate.class));
|
||||
Intent intent = new Intent(mm, Data.classMap.get(GeneralReceiver.class));
|
||||
intent.setAction(Const.Key.BROADCAST_MANAGER_UPDATE);
|
||||
intent.putExtra(Const.Key.INTENT_SET_LINK, Data.managerLink);
|
||||
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
||||
intent.putExtra(Const.Key.INTENT_SET_NAME, name);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
||||
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(mm.getString(R.string.manager_update_title))
|
||||
.setContentText(mm.getString(R.string.manager_download_install))
|
||||
@@ -61,27 +78,37 @@ public class NotificationMgr {
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
NotificationManagerCompat mgr = NotificationManagerCompat.from(mm);
|
||||
mgr.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
public static void dtboPatched() {
|
||||
MagiskManager mm = Data.MM();
|
||||
|
||||
Intent intent = new Intent(mm, Data.classMap.get(RebootReceiver.class));
|
||||
Intent intent = new Intent(mm, Data.classMap.get(GeneralReceiver.class))
|
||||
.setAction(Const.Key.BROADCAST_REBOOT);
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
||||
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.UPDATE_NOTIFICATION_CHANNEL);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk_outline)
|
||||
.setContentTitle(mm.getString(R.string.dtbo_patched_title))
|
||||
.setContentText(mm.getString(R.string.dtbo_patched_reboot))
|
||||
.setVibrate(new long[]{0, 100, 100, 100})
|
||||
.addAction(R.drawable.ic_refresh, mm.getString(R.string.reboot), pendingIntent);
|
||||
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build());
|
||||
NotificationManagerCompat mgr = NotificationManagerCompat.from(mm);
|
||||
mgr.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
public static NotificationCompat.Builder progress(String title) {
|
||||
MagiskManager mm = Data.MM();
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.PROGRESS_NOTIFICATION_CHANNEL);
|
||||
builder.setPriority(NotificationCompat.PRIORITY_LOW)
|
||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||
.setContentTitle(title)
|
||||
.setProgress(0, 0, true)
|
||||
.setOngoing(true);
|
||||
return builder;
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.androidnetworking.interfaces.DownloadProgressListener;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
public class ProgressNotification implements DownloadProgressListener {
|
||||
|
||||
private NotificationManagerCompat mgr;
|
||||
private NotificationCompat.Builder builder;
|
||||
private long prevTime;
|
||||
|
||||
public ProgressNotification(String title) {
|
||||
MagiskManager mm = Data.MM();
|
||||
mgr = NotificationManagerCompat.from(mm);
|
||||
builder = Notifications.progress(title);
|
||||
prevTime = System.currentTimeMillis();
|
||||
update();
|
||||
Utils.toast(mm.getString(R.string.downloading_toast, title), Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgress(long bytesDownloaded, long totalBytes) {
|
||||
long cur = System.currentTimeMillis();
|
||||
if (cur - prevTime >= 1000) {
|
||||
prevTime = cur;
|
||||
int progress = (int) (bytesDownloaded * 100 / totalBytes);
|
||||
builder.setProgress(100, progress, false);
|
||||
builder.setContentText(progress + "%");
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public NotificationCompat.Builder getNotification() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
mgr.notify(hashCode(), builder.build());
|
||||
}
|
||||
|
||||
public void dlDone() {
|
||||
builder.setProgress(0, 0, false)
|
||||
.setContentText(Data.MM().getString(R.string.download_complete))
|
||||
.setSmallIcon(R.drawable.ic_check_circle)
|
||||
.setOngoing(false);
|
||||
update();
|
||||
}
|
||||
|
||||
public void dlFail() {
|
||||
builder.setProgress(0, 0, false)
|
||||
.setContentText(Data.MM().getString(R.string.download_file_error))
|
||||
.setSmallIcon(R.drawable.ic_cancel)
|
||||
.setOngoing(false);
|
||||
update();
|
||||
}
|
||||
|
||||
public void dismiss() {
|
||||
mgr.cancel(hashCode());
|
||||
}
|
||||
}
|
@@ -2,29 +2,29 @@ package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.androidnetworking.error.ANError;
|
||||
import com.androidnetworking.interfaces.DownloadListener;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class UninstallDialog extends CustomAlertDialog {
|
||||
|
||||
public UninstallDialog(@NonNull Activity activity) {
|
||||
super(activity);
|
||||
MagiskManager mm = Data.MM();
|
||||
setTitle(R.string.uninstall_magisk_title);
|
||||
setMessage(R.string.uninstall_magisk_msg);
|
||||
setNeutralButton(R.string.restore_img, (d, i) -> {
|
||||
@@ -41,17 +41,29 @@ public class UninstallDialog extends CustomAlertDialog {
|
||||
});
|
||||
});
|
||||
if (!TextUtils.isEmpty(Data.uninstallerLink)) {
|
||||
setPositiveButton(R.string.complete_uninstall, (d, i) ->
|
||||
Download.receive(activity, new DownloadReceiver() {
|
||||
setPositiveButton(R.string.complete_uninstall, (d, i) -> {
|
||||
File zip = new File(activity.getFilesDir(), "uninstaller.zip");
|
||||
ProgressNotification progress = new ProgressNotification(zip.getName());
|
||||
AndroidNetworking.download(Data.uninstallerLink, zip.getParent(), zip.getName())
|
||||
.build()
|
||||
.setDownloadProgressListener(progress)
|
||||
.startDownload(new DownloadListener() {
|
||||
@Override
|
||||
public void onDownloadDone(Context context, Uri uri) {
|
||||
Intent intent = new Intent(context, Data.classMap.get(FlashActivity.class))
|
||||
public void onDownloadComplete() {
|
||||
progress.dismiss();
|
||||
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
.setData(uri)
|
||||
.setData(Uri.fromFile(zip))
|
||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);
|
||||
context.startActivity(intent);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
}, Data.uninstallerLink, "magisk-uninstaller.zip"));
|
||||
|
||||
@Override
|
||||
public void onError(ANError anError) {
|
||||
progress.dlFail();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -11,19 +11,19 @@ public class Module extends BaseModule {
|
||||
public Module(String path) {
|
||||
|
||||
try {
|
||||
parseProps(Shell.Sync.su("dos2unix < " + path + "/module.prop"));
|
||||
parseProps(Shell.su("dos2unix < " + path + "/module.prop").exec().getOut());
|
||||
} catch (NumberFormatException ignored) {}
|
||||
|
||||
mRemoveFile = new SuFile(path, "remove");
|
||||
mDisableFile = new SuFile(path, "disable");
|
||||
mUpdateFile = new SuFile(path, "update");
|
||||
|
||||
if (getId() == null) {
|
||||
if (getId().isEmpty()) {
|
||||
int sep = path.lastIndexOf('/');
|
||||
setId(path.substring(sep + 1));
|
||||
}
|
||||
|
||||
if (getName() == null) {
|
||||
if (getName().isEmpty()) {
|
||||
setName(getId());
|
||||
}
|
||||
|
||||
@@ -33,13 +33,11 @@ public class Module extends BaseModule {
|
||||
}
|
||||
|
||||
public void createDisableFile() {
|
||||
mEnable = false;
|
||||
mDisableFile.createNewFile();
|
||||
mEnable = !mDisableFile.createNewFile();
|
||||
}
|
||||
|
||||
public void removeDisableFile() {
|
||||
mEnable = true;
|
||||
mDisableFile.delete();
|
||||
mEnable = mDisableFile.delete();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
@@ -47,13 +45,11 @@ public class Module extends BaseModule {
|
||||
}
|
||||
|
||||
public void createRemoveFile() {
|
||||
mRemove = true;
|
||||
mRemoveFile.createNewFile();
|
||||
mRemove = mRemoveFile.createNewFile();
|
||||
}
|
||||
|
||||
public void deleteRemoveFile() {
|
||||
mRemove = false;
|
||||
mRemoveFile.delete();
|
||||
mRemove = !mRemoveFile.delete();
|
||||
}
|
||||
|
||||
public boolean willBeRemoved() {
|
||||
|
@@ -3,7 +3,8 @@ package com.topjohnwu.magisk.container;
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
@@ -26,22 +27,22 @@ public class Policy implements Comparable<Policy>{
|
||||
this.uid = uid;
|
||||
packageName = pkgs[0];
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
appName = info.loadLabel(pm).toString();
|
||||
appName = Utils.getAppLabel(info, pm);
|
||||
}
|
||||
|
||||
public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
uid = c.getInt(c.getColumnIndex("uid"));
|
||||
packageName = c.getString(c.getColumnIndex("package_name"));
|
||||
policy = c.getInt(c.getColumnIndex("policy"));
|
||||
until = c.getLong(c.getColumnIndex("until"));
|
||||
logging = c.getInt(c.getColumnIndex("logging")) != 0;
|
||||
notification = c.getInt(c.getColumnIndex("notification")) != 0;
|
||||
public Policy(ContentValues values, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
uid = values.getAsInteger("uid");
|
||||
packageName = values.getAsString("package_name");
|
||||
policy = values.getAsInteger("policy");
|
||||
until = values.getAsInteger("until");
|
||||
logging = values.getAsInteger("logging") != 0;
|
||||
notification = values.getAsInteger("notification") != 0;
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
if (info.uid != uid)
|
||||
throw new PackageManager.NameNotFoundException();
|
||||
appName = info.loadLabel(pm).toString();
|
||||
}
|
||||
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("uid", uid);
|
||||
|
@@ -2,48 +2,41 @@ package com.topjohnwu.magisk.container;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class Repo extends BaseModule {
|
||||
|
||||
private String repoName;
|
||||
private Date mLastUpdate;
|
||||
|
||||
public Repo(String name) {
|
||||
repoName = name;
|
||||
public Repo(String id) {
|
||||
setId(id);
|
||||
}
|
||||
|
||||
public Repo(Cursor c) {
|
||||
super(c);
|
||||
repoName = c.getString(c.getColumnIndex("repo_name"));
|
||||
mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update")));
|
||||
}
|
||||
|
||||
public void update() throws IllegalRepoException {
|
||||
String props[] = Utils.dos2unix(WebService.getString(getManifestUrl())).split("\\n");
|
||||
String props[] = Utils.dlString(getPropUrl()).split("\\n");
|
||||
try {
|
||||
parseProps(props);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalRepoException("Repo [" + repoName + "] parse error: " + e.getMessage());
|
||||
throw new IllegalRepoException("Repo [" + getId() + "] parse error: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(getId())) {
|
||||
throw new IllegalRepoException("Repo [" + repoName + "] does not contain id");
|
||||
}
|
||||
if (getVersionCode() < 0) {
|
||||
throw new IllegalRepoException("Repo [" + repoName + "] does not contain versionCode");
|
||||
throw new IllegalRepoException("Repo [" + getId() + "] does not contain versionCode");
|
||||
}
|
||||
if (getMinMagiskVersion() < Const.MIN_MODULE_VER()) {
|
||||
Logger.debug("Repo [" + repoName + "] is outdated");
|
||||
if (getMinMagiskVersion() < Const.MIN_MODULE_VER) {
|
||||
Logger.debug("Repo [" + getId() + "] is outdated");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,25 +48,20 @@ public class Repo extends BaseModule {
|
||||
@Override
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = super.getContentValues();
|
||||
values.put("repo_name", repoName);
|
||||
values.put("last_update", mLastUpdate.getTime());
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getRepoName() {
|
||||
return repoName;
|
||||
}
|
||||
|
||||
public String getZipUrl() {
|
||||
return String.format(Const.Url.ZIP_URL, repoName);
|
||||
return String.format(Const.Url.ZIP_URL, getId());
|
||||
}
|
||||
|
||||
public String getManifestUrl() {
|
||||
return String.format(Const.Url.FILE_URL, repoName, "module.prop");
|
||||
public String getPropUrl() {
|
||||
return String.format(Const.Url.FILE_URL, getId(), "module.prop");
|
||||
}
|
||||
|
||||
public String getDetailUrl() {
|
||||
return String.format(Const.Url.FILE_URL, repoName, "README.md");
|
||||
return String.format(Const.Url.FILE_URL, getId(), "README.md");
|
||||
}
|
||||
|
||||
public String getLastUpdateString() {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package com.topjohnwu.magisk.container;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
|
||||
@@ -20,17 +19,18 @@ public class SuLogEntry {
|
||||
fromUid = policy.uid;
|
||||
packageName = policy.packageName;
|
||||
appName = policy.appName;
|
||||
action = policy.policy == Policy.ALLOW;
|
||||
}
|
||||
|
||||
public SuLogEntry(Cursor c) {
|
||||
fromUid = c.getInt(c.getColumnIndex("from_uid"));
|
||||
fromPid = c.getInt(c.getColumnIndex("from_pid"));
|
||||
toUid = c.getInt(c.getColumnIndex("to_uid"));
|
||||
packageName = c.getString(c.getColumnIndex("package_name"));
|
||||
appName = c.getString(c.getColumnIndex("app_name"));
|
||||
command = c.getString(c.getColumnIndex("command"));
|
||||
action = c.getInt(c.getColumnIndex("action")) != 0;
|
||||
date = new Date(c.getLong(c.getColumnIndex("time")));
|
||||
public SuLogEntry(ContentValues values) {
|
||||
fromUid = values.getAsInteger("from_uid");
|
||||
packageName = values.getAsString("package_name");
|
||||
appName = values.getAsString("app_name");
|
||||
fromPid = values.getAsInteger("from_pid");
|
||||
command = values.getAsString("command");
|
||||
toUid = values.getAsInteger("to_uid");
|
||||
action = values.getAsInteger("action") != 0;
|
||||
date = new Date(values.getAsLong("time"));
|
||||
}
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
|
@@ -0,0 +1,66 @@
|
||||
package com.topjohnwu.magisk.database;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class MagiskDB {
|
||||
|
||||
static final String POLICY_TABLE = "policies";
|
||||
static final String LOG_TABLE = "logs";
|
||||
static final String SETTINGS_TABLE = "settings";
|
||||
static final String STRINGS_TABLE = "strings";
|
||||
static final File LEGACY_MANAGER_DB =
|
||||
new File(Utils.fmt("/sbin/.magisk/db-%d/magisk.db", Const.USER_ID));
|
||||
|
||||
@NonNull
|
||||
public static MagiskDB getInstance() {
|
||||
if (LEGACY_MANAGER_DB.canWrite()) {
|
||||
return MagiskDBLegacy.newInstance();
|
||||
} else if (Shell.rootAccess()) {
|
||||
return Data.magiskVersionCode >= Const.MAGISK_VER.CMDLINE_DB ?
|
||||
new MagiskDBCmdline() : MagiskDBLegacy.newInstance();
|
||||
} else {
|
||||
return new MagiskDB();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearOutdated() {}
|
||||
|
||||
public void deletePolicy(Policy policy) {
|
||||
deletePolicy(policy.uid);
|
||||
}
|
||||
|
||||
public void deletePolicy(String pkg) {}
|
||||
|
||||
public void deletePolicy(int uid) {}
|
||||
|
||||
public Policy getPolicy(int uid) { return null; }
|
||||
|
||||
public void updatePolicy(Policy policy) {}
|
||||
|
||||
public List<Policy> getPolicyList() { return Collections.emptyList(); }
|
||||
|
||||
public List<List<SuLogEntry>> getLogs() { return Collections.emptyList(); }
|
||||
|
||||
public void addLog(SuLogEntry log) {}
|
||||
|
||||
public void clearLogs() {}
|
||||
|
||||
public void setSettings(String key, int value) {}
|
||||
|
||||
public int getSettings(String key, int defaultValue) { return defaultValue; }
|
||||
|
||||
public void setStrings(String key, String value) {}
|
||||
|
||||
public String getStrings(String key, String defaultValue) { return defaultValue; }
|
||||
}
|
@@ -0,0 +1,189 @@
|
||||
package com.topjohnwu.magisk.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MagiskDBCmdline extends MagiskDB {
|
||||
|
||||
private PackageManager pm;
|
||||
|
||||
public MagiskDBCmdline() {
|
||||
pm = Data.MM().getPackageManager();
|
||||
}
|
||||
|
||||
private List<String> rawSQL(String fmt, Object... args) {
|
||||
return Shell.su("magisk --sqlite '" + Utils.fmt(fmt, args) + "'").exec().getOut();
|
||||
}
|
||||
|
||||
private List<ContentValues> SQL(String fmt, Object... args) {
|
||||
List<ContentValues> list = new ArrayList<>();
|
||||
for (String raw : rawSQL(fmt, args)) {
|
||||
ContentValues values = new ContentValues();
|
||||
String[] cols = raw.split("\\|");
|
||||
for (String col : cols) {
|
||||
String[] pair = col.split("=", 2);
|
||||
if (pair.length != 2)
|
||||
continue;
|
||||
values.put(pair[0], pair[1]);
|
||||
}
|
||||
list.add(values);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private String toSQL(ContentValues values) {
|
||||
StringBuilder keys = new StringBuilder(), vals = new StringBuilder();
|
||||
keys.append('(');
|
||||
vals.append("VALUES(");
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, Object> entry : values.valueSet()) {
|
||||
if (!first) {
|
||||
keys.append(',');
|
||||
vals.append(',');
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
keys.append(entry.getKey());
|
||||
vals.append('"');
|
||||
vals.append(entry.getValue());
|
||||
vals.append('"');
|
||||
}
|
||||
keys.append(')');
|
||||
vals.append(')');
|
||||
keys.append(vals);
|
||||
return keys.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOutdated() {
|
||||
rawSQL(
|
||||
"DELETE FROM %s WHERE until > 0 AND until < %d;" +
|
||||
"DELETE FROM %s WHERE time < %d",
|
||||
POLICY_TABLE, System.currentTimeMillis() / 1000,
|
||||
LOG_TABLE, System.currentTimeMillis() - Data.suLogTimeout * 86400000
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePolicy(String pkg) {
|
||||
rawSQL("DELETE FROM %s WHERE package_name=\"%s\"", POLICY_TABLE, pkg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePolicy(int uid) {
|
||||
rawSQL("DELETE FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Policy getPolicy(int uid) {
|
||||
List<ContentValues> res =
|
||||
SQL("SELECT * FROM %s WHERE uid=%d", POLICY_TABLE, uid);
|
||||
if (!res.isEmpty()) {
|
||||
try {
|
||||
return new Policy(res.get(0), pm);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(uid);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePolicy(Policy policy) {
|
||||
rawSQL("REPLACE INTO %s %s", POLICY_TABLE, toSQL(policy.getContentValues()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Policy> getPolicyList() {
|
||||
List<Policy> list = new ArrayList<>();
|
||||
for (ContentValues values : SQL("SELECT * FROM %s WHERE uid/100000=%d", POLICY_TABLE, Const.USER_ID)) {
|
||||
try {
|
||||
list.add(new Policy(values, pm));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(values.getAsInteger("uid"));
|
||||
}
|
||||
}
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<SuLogEntry>> getLogs() {
|
||||
List<List<SuLogEntry>> ret = new ArrayList<>();
|
||||
List<SuLogEntry> list = null;
|
||||
String dateString = null, newString;
|
||||
for (ContentValues values : SQL("SELECT * FROM %s ORDER BY time DESC", LOG_TABLE)) {
|
||||
Date date = new Date(values.getAsLong("time"));
|
||||
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, LocaleManager.locale).format(date);
|
||||
if (!TextUtils.equals(dateString, newString)) {
|
||||
dateString = newString;
|
||||
list = new ArrayList<>();
|
||||
ret.add(list);
|
||||
}
|
||||
list.add(new SuLogEntry(values));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLog(SuLogEntry log) {
|
||||
rawSQL("INSERT INTO %s %s", LOG_TABLE, toSQL(log.getContentValues()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLogs() {
|
||||
rawSQL("DELETE FROM %s", LOG_TABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(String key, int value) {
|
||||
ContentValues data = new ContentValues();
|
||||
data.put("key", key);
|
||||
data.put("value", value);
|
||||
rawSQL("REPLACE INTO %s %s", SETTINGS_TABLE, toSQL(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSettings(String key, int defaultValue) {
|
||||
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", SETTINGS_TABLE, key);
|
||||
if (res.isEmpty())
|
||||
return defaultValue;
|
||||
return res.get(0).getAsInteger("value");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrings(String key, String value) {
|
||||
if (value == null) {
|
||||
rawSQL("DELETE FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
||||
return;
|
||||
}
|
||||
ContentValues data = new ContentValues();
|
||||
data.put("key", key);
|
||||
data.put("value", value);
|
||||
rawSQL("REPLACE INTO %s %s", STRINGS_TABLE, toSQL(data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStrings(String key, String defaultValue) {
|
||||
List<ContentValues> res = SQL("SELECT value FROM %s WHERE key=\"%s\"", STRINGS_TABLE, key);
|
||||
if (res.isEmpty())
|
||||
return defaultValue;
|
||||
return res.get(0).getAsString("value");
|
||||
}
|
||||
}
|
@@ -4,6 +4,7 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
@@ -21,43 +22,33 @@ import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class MagiskDatabaseHelper {
|
||||
public class MagiskDBLegacy extends MagiskDB {
|
||||
|
||||
private static final int DATABASE_VER = 6;
|
||||
private static final int OLD_DATABASE_VER = 5;
|
||||
private static final String POLICY_TABLE = "policies";
|
||||
private static final String LOG_TABLE = "logs";
|
||||
private static final String SETTINGS_TABLE = "settings";
|
||||
private static final String STRINGS_TABLE = "strings";
|
||||
|
||||
private PackageManager pm;
|
||||
private SQLiteDatabase db;
|
||||
private MagiskManager mm;
|
||||
|
||||
@NonNull
|
||||
public static MagiskDatabaseHelper getInstance(MagiskManager mm) {
|
||||
static MagiskDBLegacy newInstance() {
|
||||
try {
|
||||
return new MagiskDatabaseHelper(mm);
|
||||
return new MagiskDBLegacy();
|
||||
} catch (Exception e) {
|
||||
// Let's cleanup everything and try again
|
||||
Shell.su("db_clean '*'").exec();
|
||||
return new MagiskDatabaseHelper(mm);
|
||||
return new MagiskDBLegacy();
|
||||
}
|
||||
}
|
||||
|
||||
private MagiskDatabaseHelper(MagiskManager context) {
|
||||
mm = context;
|
||||
pm = mm.getPackageManager();
|
||||
db = openDatabase(mm);
|
||||
private MagiskDBLegacy() {
|
||||
pm = Data.MM().getPackageManager();
|
||||
db = openDatabase();
|
||||
db.disableWriteAheadLogging();
|
||||
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
|
||||
int curVersion = db.getVersion();
|
||||
@@ -71,48 +62,37 @@ public class MagiskDatabaseHelper {
|
||||
clearOutdated();
|
||||
}
|
||||
|
||||
private SQLiteDatabase openDatabase(MagiskManager mm) {
|
||||
final File DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
|
||||
private SQLiteDatabase openDatabase() {
|
||||
MagiskManager mm = Data.MM();
|
||||
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||
? mm.createDeviceProtectedStorageContext() : mm;
|
||||
if (!DB_FILE.canWrite()) {
|
||||
if (!Shell.rootAccess()) {
|
||||
if (!LEGACY_MANAGER_DB.canWrite()) {
|
||||
if (!Shell.rootAccess() || Data.magiskVersionCode < 0) {
|
||||
// We don't want the app to crash, create a db and return
|
||||
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
||||
}
|
||||
// Cleanup
|
||||
Shell.su("db_clean " + Const.USER_ID).exec();
|
||||
if (Data.magiskVersionCode < Const.MAGISK_VER.FBE_AWARE) {
|
||||
// Super old legacy mode
|
||||
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
||||
} else if (Data.magiskVersionCode < Const.MAGISK_VER.HIDDEN_PATH) {
|
||||
// Legacy mode with FBE aware
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
de.moveDatabaseFrom(mm, "su.db");
|
||||
}
|
||||
return de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
||||
} else {
|
||||
// Global database
|
||||
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
|
||||
mm.deleteDatabase("su.db");
|
||||
de.deleteDatabase("su.db");
|
||||
if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) {
|
||||
// We need some additional policies on old versions
|
||||
Shell.su("db_sepatch").exec();
|
||||
}
|
||||
if (!GLOBAL_DB.exists()) {
|
||||
Shell.su("db_init").exec();
|
||||
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
|
||||
Shell.su("db_restore").exec();
|
||||
}
|
||||
// Global database
|
||||
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
|
||||
mm.deleteDatabase("su.db");
|
||||
de.deleteDatabase("su.db");
|
||||
if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) {
|
||||
// We need some additional policies on old versions
|
||||
Shell.su("db_sepatch").exec();
|
||||
}
|
||||
if (!GLOBAL_DB.exists()) {
|
||||
Shell.su("db_init").exec();
|
||||
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
|
||||
Shell.su("db_restore").exec();
|
||||
}
|
||||
Shell.su("db_setup " + Process.myUid()).exec();
|
||||
}
|
||||
// Not using legacy mode, open the mounted global DB
|
||||
return SQLiteDatabase.openOrCreateDatabase(DB_FILE, null);
|
||||
return SQLiteDatabase.openOrCreateDatabase(LEGACY_MANAGER_DB, null);
|
||||
}
|
||||
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion) {
|
||||
private void onUpgrade(SQLiteDatabase db, int oldVersion) {
|
||||
if (oldVersion == 0) {
|
||||
createTables(db);
|
||||
oldVersion = 3;
|
||||
@@ -147,13 +127,13 @@ public class MagiskDatabaseHelper {
|
||||
}
|
||||
if (oldVersion == 5) {
|
||||
setSettings(Const.Key.SU_FINGERPRINT,
|
||||
mm.prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0);
|
||||
Data.MM().prefs.getBoolean(Const.Key.SU_FINGERPRINT, false) ? 1 : 0);
|
||||
++oldVersion;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove everything, we do not support downgrade
|
||||
public void onDowngrade(SQLiteDatabase db) {
|
||||
private void onDowngrade(SQLiteDatabase db) {
|
||||
Utils.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE);
|
||||
@@ -166,22 +146,23 @@ public class MagiskDatabaseHelper {
|
||||
// Policies
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + POLICY_TABLE + " " +
|
||||
"(uid INT, package_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
"(uid INT, package_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
|
||||
// Logs
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + LOG_TABLE + " " +
|
||||
"(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
"(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
|
||||
// Settings
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + SETTINGS_TABLE + " " +
|
||||
"(key TEXT, value INT, PRIMARY KEY(key))");
|
||||
"(key TEXT, value INT, PRIMARY KEY(key))");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearOutdated() {
|
||||
// Clear outdated policies
|
||||
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
|
||||
@@ -189,23 +170,24 @@ public class MagiskDatabaseHelper {
|
||||
db.delete(LOG_TABLE, Utils.fmt("time < %d", System.currentTimeMillis() - Data.suLogTimeout * 86400000), null);
|
||||
}
|
||||
|
||||
public void deletePolicy(Policy policy) {
|
||||
deletePolicy(policy.uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePolicy(String pkg) {
|
||||
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePolicy(int uid) {
|
||||
db.delete(POLICY_TABLE, Utils.fmt("uid=%d", uid), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Policy getPolicy(int uid) {
|
||||
Policy policy = null;
|
||||
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid=%d", uid), null, null, null, null)) {
|
||||
if (c.moveToNext()) {
|
||||
policy = new Policy(c, pm);
|
||||
ContentValues values = new ContentValues();
|
||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
||||
policy = new Policy(values, pm);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(uid);
|
||||
@@ -214,21 +196,21 @@ public class MagiskDatabaseHelper {
|
||||
return policy;
|
||||
}
|
||||
|
||||
public void addPolicy(Policy policy) {
|
||||
@Override
|
||||
public void updatePolicy(Policy policy) {
|
||||
db.replace(POLICY_TABLE, null, policy.getContentValues());
|
||||
}
|
||||
|
||||
public void updatePolicy(Policy policy) {
|
||||
db.update(POLICY_TABLE, policy.getContentValues(), Utils.fmt("uid=%d", policy.uid), null);
|
||||
}
|
||||
|
||||
public List<Policy> getPolicyList(PackageManager pm) {
|
||||
@Override
|
||||
public List<Policy> getPolicyList() {
|
||||
try (Cursor c = db.query(POLICY_TABLE, null, Utils.fmt("uid/100000=%d", Const.USER_ID),
|
||||
null, null, null, null)) {
|
||||
List<Policy> ret = new ArrayList<>(c.getCount());
|
||||
while (c.moveToNext()) {
|
||||
try {
|
||||
Policy policy = new Policy(c, pm);
|
||||
ContentValues values = new ContentValues();
|
||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
||||
Policy policy = new Policy(values, pm);
|
||||
ret.add(policy);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// The app no longer exist, remove from DB
|
||||
@@ -240,11 +222,12 @@ public class MagiskDatabaseHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<Integer>> getLogStructure() {
|
||||
try (Cursor c = db.query(LOG_TABLE, new String[] { "time" }, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
|
||||
@Override
|
||||
public List<List<SuLogEntry>> getLogs() {
|
||||
try (Cursor c = db.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
|
||||
null, null, null, "time DESC")) {
|
||||
List<List<Integer>> ret = new ArrayList<>();
|
||||
List<Integer> list = null;
|
||||
List<List<SuLogEntry>> ret = new ArrayList<>();
|
||||
List<SuLogEntry> list = null;
|
||||
String dateString = null, newString;
|
||||
while (c.moveToNext()) {
|
||||
Date date = new Date(c.getLong(c.getColumnIndex("time")));
|
||||
@@ -254,25 +237,25 @@ public class MagiskDatabaseHelper {
|
||||
list = new ArrayList<>();
|
||||
ret.add(list);
|
||||
}
|
||||
list.add(c.getPosition());
|
||||
ContentValues values = new ContentValues();
|
||||
DatabaseUtils.cursorRowToContentValues(c, values);
|
||||
list.add(new SuLogEntry(values));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor getLogCursor() {
|
||||
return db.query(LOG_TABLE, null, Utils.fmt("from_uid/100000=%d", Const.USER_ID),
|
||||
null, null, null, "time DESC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLog(SuLogEntry log) {
|
||||
db.insert(LOG_TABLE, null, log.getContentValues());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearLogs() {
|
||||
db.delete(LOG_TABLE, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(String key, int value) {
|
||||
ContentValues data = new ContentValues();
|
||||
data.put("key", key);
|
||||
@@ -280,6 +263,7 @@ public class MagiskDatabaseHelper {
|
||||
db.replace(SETTINGS_TABLE, null, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSettings(String key, int defaultValue) {
|
||||
int value = defaultValue;
|
||||
try (Cursor c = db.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
|
||||
@@ -290,6 +274,7 @@ public class MagiskDatabaseHelper {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrings(String key, String value) {
|
||||
if (value == null) {
|
||||
db.delete(STRINGS_TABLE, "key=?", new String[] { key });
|
||||
@@ -301,6 +286,7 @@ public class MagiskDatabaseHelper {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStrings(String key, String defaultValue) {
|
||||
String value = defaultValue;
|
||||
try (Cursor c = db.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
|
@@ -16,7 +16,7 @@ import java.util.Set;
|
||||
|
||||
public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final int DATABASE_VER = 3;
|
||||
private static final int DATABASE_VER = 4;
|
||||
private static final String TABLE_NAME = "repos";
|
||||
|
||||
private SQLiteDatabase mDb;
|
||||
@@ -29,8 +29,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
mDb = getWritableDatabase();
|
||||
|
||||
// Remove outdated repos
|
||||
mDb.delete(TABLE_NAME, "minMagisk<?",
|
||||
new String[] { String.valueOf(Const.MIN_MODULE_VER()) });
|
||||
mDb.delete(TABLE_NAME, "minMagisk<?", new String[] { String.valueOf(Const.MIN_MODULE_VER) });
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -40,21 +39,14 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
try {
|
||||
if (oldVersion < 3) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " +
|
||||
"author TEXT, description TEXT, repo_name TEXT, last_update INT, " +
|
||||
"PRIMARY KEY(id))");
|
||||
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
||||
oldVersion = 3;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// Reset database
|
||||
onDowngrade(db, DATABASE_VER, 0);
|
||||
if (oldVersion != newVersion) {
|
||||
// Nuke old DB and create new table
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " +
|
||||
"author TEXT, description TEXT, last_update INT, PRIMARY KEY(id))");
|
||||
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +67,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
public void removeRepo(Repo repo) {
|
||||
mDb.delete(TABLE_NAME, "repo_name=?", new String[] { repo.getRepoName() });
|
||||
notifyAdapter();
|
||||
removeRepo(repo.getId());
|
||||
}
|
||||
|
||||
public void removeRepo(Iterable<String> list) {
|
||||
@@ -115,7 +106,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
orderBy = "last_update DESC";
|
||||
}
|
||||
return mDb.query(TABLE_NAME, null, "minMagisk<=? AND minMagisk>=?",
|
||||
new String[] { String.valueOf(Data.magiskVersionCode), String.valueOf(Const.MIN_MODULE_VER()) },
|
||||
new String[] { String.valueOf(Data.magiskVersionCode), String.valueOf(Const.MIN_MODULE_VER) },
|
||||
null, null, orderBy);
|
||||
}
|
||||
|
||||
|
@@ -7,35 +7,31 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MainActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.TabFragmentAdapter;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class LogFragment extends BaseFragment {
|
||||
|
||||
public ViewPager viewPager;
|
||||
public TabLayout tab;
|
||||
@BindView(R.id.container) ViewPager viewPager;
|
||||
@BindView(R.id.tab) TabLayout tab;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_log, container, false);
|
||||
ViewBinder.bind(this, v);
|
||||
unbinder = new LogFragment_ViewBinding(this, v);
|
||||
|
||||
((MainActivity) requireActivity()).toolbar.setElevation(0);
|
||||
|
||||
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
|
||||
|
||||
if (!(Const.USER_ID > 0 && Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
||||
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
|
||||
}
|
||||
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
|
||||
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
|
||||
tab.setupWithViewPager(viewPager);
|
||||
tab.setVisibility(View.VISIBLE);
|
||||
@@ -44,10 +40,4 @@ public class LogFragment extends BaseFragment {
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,6 @@ import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MainActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.asyncs.CheckSafetyNet;
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.components.BaseActivity;
|
||||
@@ -42,6 +41,9 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class MagiskFragment extends BaseFragment
|
||||
implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber {
|
||||
@@ -49,41 +51,42 @@ public class MagiskFragment extends BaseFragment
|
||||
private Container expandableContainer = new Container();
|
||||
private static boolean shownDialog = false;
|
||||
|
||||
public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.swipeRefreshLayout) public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
public CardView coreOnlyNotice;
|
||||
@BindView(R.id.core_only_notice) CardView coreOnlyNotice;
|
||||
|
||||
public RelativeLayout magiskUpdate;
|
||||
public ImageView magiskUpdateIcon;
|
||||
public TextView magiskUpdateText;
|
||||
public ProgressBar magiskUpdateProgress;
|
||||
public ImageView magiskStatusIcon;
|
||||
public TextView magiskVersionText;
|
||||
@BindView(R.id.magisk_update) RelativeLayout magiskUpdate;
|
||||
@BindView(R.id.magisk_update_icon) ImageView magiskUpdateIcon;
|
||||
@BindView(R.id.magisk_update_status) TextView magiskUpdateText;
|
||||
@BindView(R.id.magisk_update_progress) ProgressBar magiskUpdateProgress;
|
||||
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
|
||||
@BindView(R.id.magisk_version) TextView magiskVersionText;
|
||||
|
||||
public CardView safetyNetCard;
|
||||
public ImageView safetyNetRefreshIcon;
|
||||
public TextView safetyNetStatusText;
|
||||
public ProgressBar safetyNetProgress;
|
||||
public LinearLayout expandLayout;
|
||||
public ImageView ctsStatusIcon;
|
||||
public TextView ctsStatusText;
|
||||
public ImageView basicStatusIcon;
|
||||
public TextView basicStatusText;
|
||||
@BindView(R.id.safetyNet_card) CardView safetyNetCard;
|
||||
@BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon;
|
||||
@BindView(R.id.safetyNet_status) TextView safetyNetStatusText;
|
||||
@BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress;
|
||||
@BindView(R.id.expand_layout) LinearLayout expandLayout;
|
||||
@BindView(R.id.cts_status_icon) ImageView ctsStatusIcon;
|
||||
@BindView(R.id.cts_status) TextView ctsStatusText;
|
||||
@BindView(R.id.basic_status_icon) ImageView basicStatusIcon;
|
||||
@BindView(R.id.basic_status) TextView basicStatusText;
|
||||
|
||||
public CardView installOptionCard;
|
||||
public CheckBox keepEncChkbox;
|
||||
public CheckBox keepVerityChkbox;
|
||||
public CardView installButton;
|
||||
public TextView installText;
|
||||
public CardView uninstallButton;
|
||||
@BindView(R.id.install_option_card) CardView installOptionCard;
|
||||
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
|
||||
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
|
||||
@BindView(R.id.install_button) CardView installButton;
|
||||
@BindView(R.id.install_text) TextView installText;
|
||||
@BindView(R.id.uninstall_button) CardView uninstallButton;
|
||||
|
||||
public int colorBad;
|
||||
public int colorOK;
|
||||
public int colorWarn;
|
||||
public int colorNeutral;
|
||||
public int colorInfo;
|
||||
@BindColor(R.color.red500) int colorBad;
|
||||
@BindColor(R.color.green500) int colorOK;
|
||||
@BindColor(R.color.yellow500) int colorWarn;
|
||||
@BindColor(R.color.green500) int colorNeutral;
|
||||
@BindColor(R.color.blue500) int colorInfo;
|
||||
|
||||
public void safetyNet() {
|
||||
@OnClick(R.id.safetyNet_title)
|
||||
void safetyNet() {
|
||||
Runnable task = () -> {
|
||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||
safetyNetRefreshIcon.setVisibility(View.GONE);
|
||||
@@ -106,7 +109,8 @@ public class MagiskFragment extends BaseFragment
|
||||
|
||||
}
|
||||
|
||||
public void install() {
|
||||
@OnClick(R.id.install_button)
|
||||
void install() {
|
||||
shownDialog = true;
|
||||
|
||||
// Show Manager update first
|
||||
@@ -119,7 +123,8 @@ public class MagiskFragment extends BaseFragment
|
||||
new MagiskInstallDialog((BaseActivity) getActivity()).show();
|
||||
}
|
||||
|
||||
public void uninstall() {
|
||||
@OnClick(R.id.uninstall_button)
|
||||
void uninstall() {
|
||||
new UninstallDialog(requireActivity()).show();
|
||||
}
|
||||
|
||||
@@ -128,7 +133,7 @@ public class MagiskFragment extends BaseFragment
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_magisk, container, false);
|
||||
ViewBinder.bind(this, v);
|
||||
unbinder = new MagiskFragment_ViewBinding(this, v);
|
||||
requireActivity().setTitle(R.string.magisk);
|
||||
|
||||
expandableContainer.expandLayout = expandLayout;
|
||||
@@ -145,12 +150,6 @@ public class MagiskFragment extends BaseFragment
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
Data.loadMagiskInfo();
|
||||
@@ -215,11 +214,10 @@ public class MagiskFragment extends BaseFragment
|
||||
|
||||
boolean hasNetwork = Download.checkNetworkStatus(mm);
|
||||
boolean hasRoot = Shell.rootAccess();
|
||||
boolean isUpToDate = Data.magiskVersionCode > Const.MAGISK_VER.UNIFIED;
|
||||
|
||||
magiskUpdate.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
|
||||
installOptionCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
|
||||
uninstallButton.setVisibility(isUpToDate && hasRoot ? View.VISIBLE : View.GONE);
|
||||
uninstallButton.setVisibility(hasRoot ? View.VISIBLE : View.GONE);
|
||||
coreOnlyNotice.setVisibility(mm.prefs.getBoolean(Const.Key.COREONLY, false) ? View.VISIBLE : View.GONE);
|
||||
|
||||
int image, color;
|
||||
|
@@ -9,7 +9,6 @@ import android.view.ViewGroup;
|
||||
import android.widget.SearchView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
@@ -18,11 +17,12 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber {
|
||||
|
||||
public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
public RecyclerView recyclerView;
|
||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
SearchView search;
|
||||
|
||||
private ApplicationAdapter appAdapter;
|
||||
@@ -39,7 +39,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
|
||||
ViewBinder.bind(this, view);
|
||||
unbinder = new MagiskHideFragment_ViewBinding(this, view);
|
||||
|
||||
appAdapter = new ApplicationAdapter(requireActivity());
|
||||
recyclerView.setAdapter(appAdapter);
|
||||
@@ -73,12 +73,6 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
||||
search.setOnQueryTextListener(searchListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getSubscribedTopics() {
|
||||
return new int[] {Topic.MAGISK_HIDE_DONE};
|
||||
|
@@ -17,10 +17,8 @@ import android.widget.TextView;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
@@ -29,19 +27,20 @@ import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class MagiskLogFragment extends BaseFragment {
|
||||
|
||||
public TextView txtLog;
|
||||
public ScrollView svLog;
|
||||
public HorizontalScrollView hsvLog;
|
||||
public ProgressBar progressBar;
|
||||
@BindView(R.id.txtLog) TextView txtLog;
|
||||
@BindView(R.id.svLog) ScrollView svLog;
|
||||
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
|
||||
@BindView(R.id.progressBar) ProgressBar progressBar;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_magisk_log, container, false);
|
||||
ViewBinder.bind(this, view);
|
||||
unbinder = new MagiskLogFragment_ViewBinding(this, view);
|
||||
setHasOptionsMenu(true);
|
||||
txtLog.setTextIsSelectable(true);
|
||||
return view;
|
||||
@@ -59,12 +58,6 @@ public class MagiskLogFragment extends BaseFragment {
|
||||
readLogs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_log, menu);
|
||||
@@ -87,7 +80,7 @@ public class MagiskLogFragment extends BaseFragment {
|
||||
}
|
||||
}
|
||||
|
||||
public void readLogs() {
|
||||
private void readLogs() {
|
||||
Shell.su("cat " + Const.MAGISK_LOG + " | tail -n 5000").submit(result -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
if (result.getOut().isEmpty())
|
||||
@@ -99,14 +92,14 @@ public class MagiskLogFragment extends BaseFragment {
|
||||
});
|
||||
}
|
||||
|
||||
public void saveLogs() {
|
||||
private void saveLogs() {
|
||||
Calendar now = Calendar.getInstance();
|
||||
String filename = Utils.fmt("magisk_log_%04d%02d%02d_%02d%02d%02d.log",
|
||||
now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1,
|
||||
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
|
||||
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
|
||||
|
||||
File logFile = new File(Download.EXTERNAL_PATH, filename);
|
||||
File logFile = new File(Const.EXTERNAL_PATH, filename);
|
||||
try {
|
||||
logFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
@@ -117,7 +110,7 @@ public class MagiskLogFragment extends BaseFragment {
|
||||
SnackbarMaker.make(txtLog, logFile.getPath(), Snackbar.LENGTH_SHORT).show());
|
||||
}
|
||||
|
||||
public void clearLogs() {
|
||||
private void clearLogs() {
|
||||
Shell.su("echo -n > " + Const.MAGISK_LOG).submit();
|
||||
txtLog.setText(R.string.log_is_empty);
|
||||
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||
|
@@ -16,7 +16,6 @@ import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.FlashActivity;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
import com.topjohnwu.magisk.container.Module;
|
||||
@@ -32,14 +31,17 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
||||
|
||||
public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
public RecyclerView recyclerView;
|
||||
public TextView emptyRv;
|
||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||
|
||||
public void selectFile() {
|
||||
@OnClick(R.id.fab)
|
||||
void selectFile() {
|
||||
runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("application/zip");
|
||||
@@ -53,7 +55,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_modules, container, false);
|
||||
ViewBinder.bind(this, view);
|
||||
unbinder = new ModulesFragment_ViewBinding(this, view);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
mSwipeRefreshLayout.setOnRefreshListener(() -> {
|
||||
@@ -98,12 +100,6 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_reboot, menu);
|
||||
@@ -122,7 +118,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
||||
Shell.su("/system/bin/reboot bootloader").submit();
|
||||
return true;
|
||||
case R.id.reboot_download:
|
||||
Shell.su("/system/bin/reboot download").submit();
|
||||
Shell.su("/system/bin/reboot upgrade").submit();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@@ -14,7 +14,6 @@ import android.widget.TextView;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.ReposAdapter;
|
||||
import com.topjohnwu.magisk.asyncs.UpdateRepos;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
@@ -27,12 +26,13 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
||||
|
||||
public RecyclerView recyclerView;
|
||||
public TextView emptyRv;
|
||||
public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
private ReposAdapter adapter;
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_repos, container, false);
|
||||
ViewBinder.bind(this, view);
|
||||
unbinder = new ReposFragment_ViewBinding(this, view);
|
||||
|
||||
mSwipeRefreshLayout.setRefreshing(true);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
@@ -120,6 +120,5 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mm.repoDB.unregisterAdapter();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
}
|
||||
|
@@ -1,39 +1,29 @@
|
||||
package com.topjohnwu.magisk.fragments;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.DlInstallManager;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||
import com.topjohnwu.magisk.utils.RootUtils;
|
||||
import com.topjohnwu.magisk.utils.Topic;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
@@ -53,38 +43,68 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
||||
Topic.Subscriber, Topic.AutoSubscriber {
|
||||
|
||||
private PreferenceScreen prefScreen;
|
||||
|
||||
private ListPreference updateChannel, suAccess, autoRes, suNotification,
|
||||
requestTimeout, multiuserMode, namespaceMode;
|
||||
private MagiskManager mm;
|
||||
private PreferenceCategory generalCatagory;
|
||||
|
||||
private ListPreference updateChannel, autoRes, suNotification,
|
||||
requestTimeout, rootConfig, multiuserConfig, nsConfig;
|
||||
|
||||
private int rootState, namespaceState;
|
||||
private boolean showSuperuser;
|
||||
|
||||
private void prefsSync() {
|
||||
rootState = mm.mDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
|
||||
namespaceState = mm.mDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
|
||||
showSuperuser = Utils.showSuperUser();
|
||||
mm.prefs.edit()
|
||||
.putString(Const.Key.ROOT_ACCESS, String.valueOf(rootState))
|
||||
.putString(Const.Key.SU_MNT_NS, String.valueOf(namespaceState))
|
||||
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(Data.multiuserState))
|
||||
.putBoolean(Const.Key.SU_FINGERPRINT, FingerprintHelper.useFingerPrint())
|
||||
.apply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.app_settings, rootKey);
|
||||
mm = Data.MM();
|
||||
prefScreen = getPreferenceScreen();
|
||||
prefsSync();
|
||||
|
||||
generalCatagory = (PreferenceCategory) findPreference("general");
|
||||
setPreferencesFromResource(R.xml.app_settings, rootKey);
|
||||
|
||||
PreferenceScreen prefScreen = getPreferenceScreen();
|
||||
|
||||
PreferenceCategory generalCatagory = (PreferenceCategory) findPreference("general");
|
||||
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
|
||||
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
|
||||
Preference hideManager = findPreference("hide");
|
||||
hideManager.setOnPreferenceClickListener(pref -> {
|
||||
PatchAPK.hideManager();
|
||||
return true;
|
||||
});
|
||||
Preference restoreManager = findPreference("restore");
|
||||
findPreference("clear").setOnPreferenceClickListener((pref) -> {
|
||||
restoreManager.setOnPreferenceClickListener(pref -> {
|
||||
DlInstallManager.restore();
|
||||
return true;
|
||||
});
|
||||
findPreference("clear").setOnPreferenceClickListener(pref -> {
|
||||
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
||||
mm.repoDB.clearRepo();
|
||||
Utils.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
|
||||
return true;
|
||||
});
|
||||
findPreference("hosts").setOnPreferenceClickListener(pref -> {
|
||||
Shell.su("add_hosts_module").exec();
|
||||
Utils.loadModules();
|
||||
Utils.toast(R.string.settings_hosts_toast, Toast.LENGTH_SHORT);
|
||||
return true;
|
||||
});
|
||||
|
||||
updateChannel = (ListPreference) findPreference(Const.Key.UPDATE_CHANNEL);
|
||||
suAccess = (ListPreference) findPreference(Const.Key.ROOT_ACCESS);
|
||||
rootConfig = (ListPreference) findPreference(Const.Key.ROOT_ACCESS);
|
||||
autoRes = (ListPreference) findPreference(Const.Key.SU_AUTO_RESPONSE);
|
||||
requestTimeout = (ListPreference) findPreference(Const.Key.SU_REQUEST_TIMEOUT);
|
||||
suNotification = (ListPreference) findPreference(Const.Key.SU_NOTIFICATION);
|
||||
multiuserMode = (ListPreference) findPreference(Const.Key.SU_MULTIUSER_MODE);
|
||||
namespaceMode = (ListPreference) findPreference(Const.Key.SU_MNT_NS);
|
||||
multiuserConfig = (ListPreference) findPreference(Const.Key.SU_MULTIUSER_MODE);
|
||||
nsConfig = (ListPreference) findPreference(Const.Key.SU_MNT_NS);
|
||||
SwitchPreference reauth = (SwitchPreference) findPreference(Const.Key.SU_REAUTH);
|
||||
SwitchPreference fingerprint = (SwitchPreference) findPreference(Const.Key.SU_FINGERPRINT);
|
||||
|
||||
@@ -114,7 +134,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
|
||||
// Disable dangerous settings in secondary user
|
||||
if (Const.USER_ID > 0) {
|
||||
suCategory.removePreference(multiuserMode);
|
||||
suCategory.removePreference(multiuserConfig);
|
||||
}
|
||||
|
||||
// Disable re-authentication option on Android O, it will not work
|
||||
@@ -131,38 +151,12 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
fingerprint.setSummary(R.string.disable_fingerprint);
|
||||
}
|
||||
|
||||
if (Data.magiskVersionCode >= Const.MAGISK_VER.MANAGER_HIDE) {
|
||||
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||
hideManager.setOnPreferenceClickListener((pref) -> {
|
||||
PatchAPK.hideManager(requireActivity());
|
||||
return true;
|
||||
});
|
||||
if (Shell.rootAccess() && Const.USER_ID == 0) {
|
||||
if (mm.getPackageName().equals(BuildConfig.APPLICATION_ID)) {
|
||||
generalCatagory.removePreference(restoreManager);
|
||||
} else {
|
||||
if (Download.checkNetworkStatus(mm)) {
|
||||
restoreManager.setOnPreferenceClickListener((pref) -> {
|
||||
Download.receive(
|
||||
requireActivity(), new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Context context, Uri uri) {
|
||||
Data.exportPrefs();
|
||||
Shell.su("cp " + uri.getPath() + " /data/local/tmp/manager.apk").exec();
|
||||
if (ShellUtils.fastCmdResult("pm install /data/local/tmp/manager.apk")) {
|
||||
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
||||
RootUtils.uninstallPkg(context.getPackageName());
|
||||
return;
|
||||
}
|
||||
Shell.su("rm -f /data/local/tmp/manager.apk").exec();
|
||||
}
|
||||
},
|
||||
Data.managerLink,
|
||||
Utils.fmt("MagiskManager-v%s.apk", Data.remoteManagerVersionString)
|
||||
);
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
if (!Download.checkNetworkStatus(mm))
|
||||
generalCatagory.removePreference(restoreManager);
|
||||
}
|
||||
generalCatagory.removePreference(hideManager);
|
||||
}
|
||||
} else {
|
||||
@@ -170,16 +164,13 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
generalCatagory.removePreference(hideManager);
|
||||
}
|
||||
|
||||
if (!Shell.rootAccess() || (Const.USER_ID > 0 &&
|
||||
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
||||
if (!showSuperuser) {
|
||||
prefScreen.removePreference(suCategory);
|
||||
}
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
generalCatagory.removePreference(hideManager);
|
||||
} else if (Data.magiskVersionCode < Const.MAGISK_VER.UNIFIED) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,9 +213,16 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
mm.mDB.setSettings(key, Utils.getPrefsInt(prefs, key));
|
||||
break;
|
||||
}
|
||||
Data.loadConfig();
|
||||
setSummary();
|
||||
switch (key) {
|
||||
case Const.Key.ROOT_ACCESS:
|
||||
rootState = Utils.getPrefsInt(prefs, key);
|
||||
break;
|
||||
case Const.Key.SU_MULTIUSER_MODE:
|
||||
Data.multiuserState = Utils.getPrefsInt(prefs, key);
|
||||
break;
|
||||
case Const.Key.SU_MNT_NS:
|
||||
namespaceState = Utils.getPrefsInt(prefs, key);
|
||||
break;
|
||||
case Const.Key.DARK_THEME:
|
||||
requireActivity().recreate();
|
||||
break;
|
||||
@@ -245,17 +243,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
Shell.su("magiskhide --disable").submit();
|
||||
}
|
||||
break;
|
||||
case Const.Key.HOSTS:
|
||||
if (prefs.getBoolean(key, false)) {
|
||||
Shell.su("cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE,
|
||||
"mount -o bind " + Const.MAGISK_HOST_FILE + " /system/etc/hosts")
|
||||
.submit();
|
||||
} else {
|
||||
Shell.su("umount -l /system/etc/hosts",
|
||||
"rm -f " + Const.MAGISK_HOST_FILE)
|
||||
.submit();
|
||||
}
|
||||
break;
|
||||
case Const.Key.LOCALE:
|
||||
LocaleManager.setLocale(mm);
|
||||
requireActivity().recreate();
|
||||
@@ -268,6 +255,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
Utils.setupUpdateCheck();
|
||||
break;
|
||||
}
|
||||
Data.loadConfig();
|
||||
setSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -277,54 +266,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
case Const.Key.SU_FINGERPRINT:
|
||||
boolean checked = ((SwitchPreference) preference).isChecked();
|
||||
((SwitchPreference) preference).setChecked(!checked);
|
||||
CustomAlertDialog dialog = new CustomAlertDialog(requireActivity());
|
||||
CustomAlertDialog.ViewHolder vh = dialog.getViewHolder();
|
||||
Drawable fingerprint = getResources().getDrawable(R.drawable.ic_fingerprint);
|
||||
fingerprint.setBounds(0, 0, Utils.dpInPx(50), Utils.dpInPx(50));
|
||||
Resources.Theme theme = requireActivity().getTheme();
|
||||
TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint});
|
||||
fingerprint.setTint(ta.getColor(0, Color.GRAY));
|
||||
ta.recycle();
|
||||
vh.messageView.setCompoundDrawables(null, null, null, fingerprint);
|
||||
vh.messageView.setCompoundDrawablePadding(Utils.dpInPx(20));
|
||||
vh.messageView.setGravity(Gravity.CENTER);
|
||||
try {
|
||||
FingerprintHelper helper = new FingerprintHelper() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(errString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(helpString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(R.string.auth_fail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||
dialog.dismiss();
|
||||
((SwitchPreference) preference).setChecked(checked);
|
||||
mm.mDB.setSettings(key, checked ? 1 : 0);
|
||||
|
||||
}
|
||||
};
|
||||
dialog.setMessage(R.string.auth_fingerprint)
|
||||
.setNegativeButton(R.string.close, (d, w) -> helper.cancel())
|
||||
.setOnCancelListener(d -> helper.cancel())
|
||||
.show();
|
||||
helper.authenticate();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utils.toast(R.string.auth_fail, Toast.LENGTH_SHORT);
|
||||
}
|
||||
FingerprintHelper.showAuthDialog(requireActivity(), () -> {
|
||||
((SwitchPreference) preference).setChecked(checked);
|
||||
mm.mDB.setSettings(key, checked ? 1 : 0);
|
||||
});
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@@ -333,8 +278,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
private void setSummary() {
|
||||
updateChannel.setSummary(getResources()
|
||||
.getStringArray(R.array.update_channel)[Data.updateChannel]);
|
||||
suAccess.setSummary(getResources()
|
||||
.getStringArray(R.array.su_access)[Data.suAccessState]);
|
||||
rootConfig.setSummary(getResources()
|
||||
.getStringArray(R.array.su_access)[rootState]);
|
||||
autoRes.setSummary(getResources()
|
||||
.getStringArray(R.array.auto_response)[Data.suResponseType]);
|
||||
suNotification.setSummary(getResources()
|
||||
@@ -342,10 +287,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
||||
requestTimeout.setSummary(
|
||||
getString(R.string.request_timeout_summary,
|
||||
mm.prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10")));
|
||||
multiuserMode.setSummary(getResources()
|
||||
.getStringArray(R.array.multiuser_summary)[Data.multiuserMode]);
|
||||
namespaceMode.setSummary(getResources()
|
||||
.getStringArray(R.array.namespace_summary)[Data.suNamespaceMode]);
|
||||
multiuserConfig.setSummary(getResources()
|
||||
.getStringArray(R.array.multiuser_summary)[Data.multiuserState]);
|
||||
nsConfig.setSummary(getResources()
|
||||
.getStringArray(R.array.namespace_summary)[namespaceState]);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -10,17 +10,17 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SuLogFragment extends BaseFragment {
|
||||
|
||||
public TextView emptyRv;
|
||||
public RecyclerView recyclerView;
|
||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
|
||||
private SuLogAdapter adapter;
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SuLogFragment extends BaseFragment {
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
||||
ViewBinder.bind(this, v);
|
||||
unbinder = new SuLogFragment_ViewBinding(this, v);
|
||||
adapter = new SuLogAdapter(mm.mDB);
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
@@ -76,10 +76,4 @@ public class SuLogFragment extends BaseFragment {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.ViewBinder;
|
||||
import com.topjohnwu.magisk.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.components.BaseFragment;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
@@ -17,11 +16,12 @@ import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SuperuserFragment extends BaseFragment {
|
||||
|
||||
public RecyclerView recyclerView;
|
||||
public TextView emptyRv;
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||
|
||||
private PackageManager pm;
|
||||
|
||||
@@ -29,9 +29,9 @@ public class SuperuserFragment extends BaseFragment {
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_superuser, container, false);
|
||||
ViewBinder.bind(this, view);
|
||||
unbinder = new SuperuserFragment_ViewBinding(this, view);
|
||||
|
||||
pm = getActivity().getPackageManager();
|
||||
pm = requireActivity().getPackageManager();
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -47,14 +47,8 @@ public class SuperuserFragment extends BaseFragment {
|
||||
displayPolicyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
ViewBinder.unbind(this);
|
||||
}
|
||||
|
||||
private void displayPolicyList() {
|
||||
List<Policy> policyList = mm.mDB.getPolicyList(pm);
|
||||
List<Policy> policyList = mm.mDB.getPolicyList();
|
||||
|
||||
if (policyList.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
|
@@ -1,35 +0,0 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.SuRequestActivity;
|
||||
import com.topjohnwu.magisk.services.OnBootService;
|
||||
import com.topjohnwu.magisk.utils.SuConnector;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) {
|
||||
switch (intent.getExtras().getString("action", "boot")) {
|
||||
case "request":
|
||||
Intent i = new Intent(context, Data.classMap.get(SuRequestActivity.class))
|
||||
.putExtra("socket", intent.getStringExtra("socket"))
|
||||
.putExtra("version", 2)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
break;
|
||||
case "log":
|
||||
SuConnector.handleLogs(intent, 2);
|
||||
break;
|
||||
case "boot":
|
||||
OnBootService.enqueueWork(context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.SuRequestActivity;
|
||||
import com.topjohnwu.magisk.services.OnBootService;
|
||||
import com.topjohnwu.magisk.utils.DlInstallManager;
|
||||
import com.topjohnwu.magisk.utils.SuConnector;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
public class GeneralReceiver extends BroadcastReceiver {
|
||||
|
||||
private String getPkg(Intent i) {
|
||||
return i.getData() == null ? "" : i.getData().getEncodedSchemeSpecificPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
MagiskManager mm = Data.MM();
|
||||
if (intent == null)
|
||||
return;
|
||||
String action = intent.getAction();
|
||||
if (action == null)
|
||||
return;
|
||||
switch (action) {
|
||||
case Intent.ACTION_BOOT_COMPLETED:
|
||||
String bootAction = intent.getStringExtra("action");
|
||||
if (bootAction == null)
|
||||
bootAction = "boot";
|
||||
switch (bootAction) {
|
||||
case "request":
|
||||
Intent i = new Intent(mm, Data.classMap.get(SuRequestActivity.class))
|
||||
.putExtra("socket", intent.getStringExtra("socket"))
|
||||
.putExtra("version", 2)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mm.startActivity(i);
|
||||
break;
|
||||
case "log":
|
||||
SuConnector.handleLogs(intent, 2);
|
||||
break;
|
||||
case "notify":
|
||||
SuConnector.handleNotify(intent);
|
||||
break;
|
||||
case "boot":
|
||||
default:
|
||||
/* The actual on-boot trigger */
|
||||
OnBootService.enqueueWork(mm);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_REPLACED:
|
||||
// This will only work pre-O
|
||||
if (mm.prefs.getBoolean(Const.Key.SU_REAUTH, false)) {
|
||||
mm.mDB.deletePolicy(getPkg(intent));
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
|
||||
String pkg = getPkg(intent);
|
||||
mm.mDB.deletePolicy(pkg);
|
||||
Shell.su("magiskhide --rm " + pkg).submit();
|
||||
break;
|
||||
case Const.Key.BROADCAST_MANAGER_UPDATE:
|
||||
Data.managerLink = intent.getStringExtra(Const.Key.INTENT_SET_LINK);
|
||||
DlInstallManager.upgrade(intent.getStringExtra(Const.Key.INTENT_SET_NAME));
|
||||
break;
|
||||
case Const.Key.BROADCAST_REBOOT:
|
||||
Shell.su("/system/bin/reboot").submit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||
import com.topjohnwu.magisk.utils.Download;
|
||||
import com.topjohnwu.utils.JarMap;
|
||||
import com.topjohnwu.utils.SignAPK;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
public class ManagerUpdate extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Download.receive(
|
||||
context, new PatchedInstall(),
|
||||
intent.getStringExtra(Const.Key.INTENT_SET_LINK),
|
||||
intent.getStringExtra(Const.Key.INTENT_SET_FILENAME)
|
||||
);
|
||||
}
|
||||
|
||||
private static class PatchedInstall extends ManagerInstall {
|
||||
@Override
|
||||
public void onDownloadDone(Context context, Uri uri) {
|
||||
if (!context.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||
String orig = uri.getPath();
|
||||
String patch = orig.substring(0, orig.lastIndexOf('.')) + "-patched.apk";
|
||||
try {
|
||||
JarMap apk = new JarMap(orig);
|
||||
PatchAPK.patchPackageID(apk, Const.ORIG_PKG_NAME, context.getPackageName());
|
||||
SignAPK.sign(apk, new BufferedOutputStream(new FileOutputStream(patch)));
|
||||
super.onDownloadDone(context, Uri.fromFile(new File(patch)));
|
||||
} catch (Exception ignored) { }
|
||||
});
|
||||
} else {
|
||||
super.onDownloadDone(context, uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
public class PackageReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
MagiskManager mm = Data.MM();
|
||||
|
||||
String pkg = intent.getData().getEncodedSchemeSpecificPart();
|
||||
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_PACKAGE_REPLACED:
|
||||
// This will only work pre-O
|
||||
if (mm.prefs.getBoolean(Const.Key.SU_REAUTH, false)) {
|
||||
mm.mDB.deletePolicy(pkg);
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
|
||||
mm.mDB.deletePolicy(pkg);
|
||||
Shell.su("magiskhide --rm " + pkg).submit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
public class RebootReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Shell.su("/system/bin/reboot").submit();
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.SplashActivity;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -33,8 +34,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
||||
private ArrayList<ShortcutInfo> getShortCuts(MagiskManager mm) {
|
||||
ArrayList<ShortcutInfo> shortCuts = new ArrayList<>();
|
||||
boolean root = Shell.rootAccess();
|
||||
if (root && !(Const.USER_ID > 0 &&
|
||||
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
||||
if (Utils.showSuperUser()) {
|
||||
shortCuts.add(new ShortcutInfo.Builder(mm, "superuser")
|
||||
.setShortLabel(mm.getString(R.string.superuser))
|
||||
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||
@@ -45,8 +45,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
||||
.setRank(0)
|
||||
.build());
|
||||
}
|
||||
if (root && Data.magiskVersionCode >= Const.MAGISK_VER.UNIFIED
|
||||
&& mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false)) {
|
||||
if (root && mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false)) {
|
||||
shortCuts.add(new ShortcutInfo.Builder(mm, "magiskhide")
|
||||
.setShortLabel(mm.getString(R.string.magiskhide))
|
||||
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||
@@ -68,7 +67,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
||||
.setRank(3)
|
||||
.build());
|
||||
shortCuts.add(new ShortcutInfo.Builder(mm, "downloads")
|
||||
.setShortLabel(mm.getString(R.string.download))
|
||||
.setShortLabel(mm.getString(R.string.downloads))
|
||||
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||
.putExtra(Const.Key.OPEN_SECTION, "downloads")
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
|
@@ -5,7 +5,7 @@ import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.utils.NotificationMgr;
|
||||
import com.topjohnwu.magisk.components.Notifications;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
|
||||
@@ -28,6 +28,6 @@ public class OnBootService extends JobIntentService {
|
||||
* to reboot if dtbo wasn't patched and patched by Magisk Manager.
|
||||
* */
|
||||
if (Shell.rootAccess() && ShellUtils.fastCmdResult("mm_patch_dtbo"))
|
||||
NotificationMgr.dtboPatched();
|
||||
Notifications.dtboPatched();
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
SuConnector.handleLogs(intent, 1);
|
||||
if (intent != null)
|
||||
SuConnector.handleLogs(intent, 1);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,113 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.androidnetworking.error.ANError;
|
||||
import com.androidnetworking.interfaces.DownloadListener;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||
import com.topjohnwu.magisk.components.ProgressNotification;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
import com.topjohnwu.utils.JarMap;
|
||||
import com.topjohnwu.utils.SignAPK;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
public class DlInstallManager {
|
||||
|
||||
public static void upgrade(String name) {
|
||||
dlInstall(name, new PatchPackageName());
|
||||
}
|
||||
|
||||
public static void restore() {
|
||||
String name = Utils.fmt("MagiskManager v%s(%d)",
|
||||
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
|
||||
dlInstall(name, new RestoreManager());
|
||||
}
|
||||
|
||||
public static void dlInstall(String name, ManagerDownloadListener listener) {
|
||||
MagiskManager mm = Data.MM();
|
||||
File apk = new File(mm.getFilesDir(), "manager.apk");
|
||||
ProgressNotification progress = new ProgressNotification(name);
|
||||
listener.setInstances(apk, progress);
|
||||
AndroidNetworking
|
||||
.download(Data.managerLink, apk.getParent(), apk.getName())
|
||||
.setExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||
.build()
|
||||
.setDownloadProgressListener(progress)
|
||||
.startDownload(listener);
|
||||
}
|
||||
|
||||
public abstract static class ManagerDownloadListener implements DownloadListener {
|
||||
private File apk;
|
||||
private ProgressNotification progress;
|
||||
|
||||
private void setInstances(File apk, ProgressNotification progress) {
|
||||
this.apk = apk;
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public abstract void onDownloadComplete(File apk, ProgressNotification progress);
|
||||
|
||||
@Override
|
||||
public final void onDownloadComplete() {
|
||||
onDownloadComplete(apk, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ANError anError) {
|
||||
progress.dlFail();
|
||||
}
|
||||
}
|
||||
|
||||
private static class PatchPackageName extends ManagerDownloadListener {
|
||||
|
||||
@Override
|
||||
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
||||
File patched = apk;
|
||||
MagiskManager mm = Data.MM();
|
||||
if (!mm.getPackageName().equals(BuildConfig.APPLICATION_ID)) {
|
||||
progress.getNotification()
|
||||
.setProgress(0, 0, true)
|
||||
.setContentTitle(mm.getString(R.string.hide_manager_title))
|
||||
.setContentText("");
|
||||
progress.update();
|
||||
patched = new File(apk.getParent(), "patched.apk");
|
||||
try {
|
||||
JarMap jarMap = new JarMap(apk);
|
||||
PatchAPK.patch(jarMap, mm.getPackageName());
|
||||
SignAPK.sign(jarMap, new BufferedOutputStream(new FileOutputStream(patched)));
|
||||
} catch (Exception e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
APKInstall.install(mm, patched);
|
||||
progress.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private static class RestoreManager extends ManagerDownloadListener {
|
||||
|
||||
@Override
|
||||
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
||||
MagiskManager mm = Data.MM();
|
||||
progress.getNotification()
|
||||
.setProgress(0, 0, true)
|
||||
.setContentTitle(mm.getString(R.string.restore_img_msg))
|
||||
.setContentText("");
|
||||
progress.update();
|
||||
Data.exportPrefs();
|
||||
// Make it world readable
|
||||
apk.setReadable(true, false);
|
||||
if (ShellUtils.fastCmdResult("pm install " + apk))
|
||||
RootUtils.rmAndLaunch(mm.getPackageName(), BuildConfig.APPLICATION_ID);
|
||||
progress.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,17 +1,26 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.security.keystore.KeyGenParameterSpec;
|
||||
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||
import android.security.keystore.KeyProperties;
|
||||
import android.view.Gravity;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||
|
||||
import java.security.KeyStore;
|
||||
|
||||
@@ -26,6 +35,16 @@ public abstract class FingerprintHelper {
|
||||
private Cipher cipher;
|
||||
private CancellationSignal cancel;
|
||||
|
||||
public static boolean useFingerPrint() {
|
||||
MagiskManager mm = Data.MM();
|
||||
boolean fp = mm.mDB.getSettings(Const.Key.SU_FINGERPRINT, 0) != 0;
|
||||
if (fp && !canUseFingerprint()) {
|
||||
mm.mDB.setSettings(Const.Key.SU_FINGERPRINT, 0);
|
||||
fp = false;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
public static boolean canUseFingerprint() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
||||
return false;
|
||||
@@ -35,6 +54,56 @@ public abstract class FingerprintHelper {
|
||||
return km.isKeyguardSecure() && fm != null && fm.isHardwareDetected() && fm.hasEnrolledFingerprints();
|
||||
}
|
||||
|
||||
public static void showAuthDialog(Activity activity, Runnable onSuccess) {
|
||||
CustomAlertDialog dialog = new CustomAlertDialog(activity);
|
||||
CustomAlertDialog.ViewHolder vh = dialog.getViewHolder();
|
||||
try {
|
||||
FingerprintHelper helper = new FingerprintHelper() {
|
||||
@Override
|
||||
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(errString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(helpString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationFailed() {
|
||||
vh.messageView.setTextColor(Color.RED);
|
||||
vh.messageView.setText(R.string.auth_fail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||
dialog.dismiss();
|
||||
onSuccess.run();
|
||||
}
|
||||
};
|
||||
Drawable fingerprint = activity.getResources().getDrawable(R.drawable.ic_fingerprint);
|
||||
fingerprint.setBounds(0, 0, Utils.dpInPx(50), Utils.dpInPx(50));
|
||||
Resources.Theme theme = activity.getTheme();
|
||||
TypedArray ta = theme.obtainStyledAttributes(new int[] {R.attr.imageColorTint});
|
||||
fingerprint.setTint(ta.getColor(0, Color.GRAY));
|
||||
ta.recycle();
|
||||
vh.messageView.setCompoundDrawables(null, null, null, fingerprint);
|
||||
vh.messageView.setCompoundDrawablePadding(Utils.dpInPx(20));
|
||||
vh.messageView.setGravity(Gravity.CENTER);
|
||||
dialog.setMessage(R.string.auth_fingerprint)
|
||||
.setNegativeButton(R.string.close, (d, w) -> helper.cancel())
|
||||
.setOnCancelListener(d -> helper.cancel())
|
||||
.show();
|
||||
helper.authenticate();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Utils.toast(R.string.auth_fail, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected FingerprintHelper() throws Exception {
|
||||
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||
manager = Data.MM().getSystemService(FingerprintManager.class);
|
||||
|
@@ -25,25 +25,20 @@ public class RootUtils extends Shell.Initializer {
|
||||
Shell.su("db_clean " + Const.USER_ID, "pm uninstall " + pkg).exec();
|
||||
}
|
||||
|
||||
public static void rmAndLaunch(String rm, String launch) {
|
||||
Shell.su(Utils.fmt("(rm_launch %d %s %s)&", Const.USER_ID, rm, launch)).exec();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInit(Context context, @NonNull Shell shell) {
|
||||
Shell.Job job = shell.newJob();
|
||||
if (shell.isRoot()) {
|
||||
InputStream magiskUtils = context.getResources().openRawResource(R.raw.util_functions);
|
||||
InputStream managerUtils = context.getResources().openRawResource(R.raw.utils);
|
||||
job.add(magiskUtils).add(managerUtils);
|
||||
if (!new SuFile("/sbin/.magisk").exists())
|
||||
job.add("ln -s /sbin/.core /sbin/.magisk");
|
||||
|
||||
job.add(context.getResources().openRawResource(R.raw.util_functions))
|
||||
.add(context.getResources().openRawResource(R.raw.utils));
|
||||
Const.MAGISK_DISABLE_FILE = new SuFile("/cache/.disable_magisk");
|
||||
SuFile file = new SuFile("/sbin/.core/img");
|
||||
if (file.exists()) {
|
||||
Const.MAGISK_PATH = file;
|
||||
} else if ((file = new SuFile("/dev/magisk/img")).exists()) {
|
||||
Const.MAGISK_PATH = file;
|
||||
} else {
|
||||
Const.MAGISK_PATH = new SuFile("/magisk");
|
||||
}
|
||||
Const.MAGISK_HOST_FILE = new SuFile(Const.MAGISK_PATH + "/.core/hosts");
|
||||
|
||||
Data.loadMagiskInfo();
|
||||
} else {
|
||||
InputStream nonroot = context.getResources().openRawResource(R.raw.nonroot_utils);
|
||||
|
@@ -15,6 +15,8 @@ import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.container.Policy;
|
||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -23,96 +25,133 @@ import java.util.Date;
|
||||
public abstract class SuConnector {
|
||||
|
||||
protected LocalSocket socket = new LocalSocket();
|
||||
protected DataOutputStream out;
|
||||
protected DataInputStream in;
|
||||
|
||||
private String readString(DataInputStream is) throws IOException {
|
||||
int len = is.readInt();
|
||||
public SuConnector(String name) throws IOException {
|
||||
connect(name);
|
||||
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
|
||||
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
|
||||
}
|
||||
|
||||
private String readString() throws IOException {
|
||||
int len = in.readInt();
|
||||
byte[] buf = new byte[len];
|
||||
is.readFully(buf);
|
||||
return new String(buf);
|
||||
in.readFully(buf);
|
||||
return new String(buf, "UTF-8");
|
||||
}
|
||||
|
||||
public Bundle readSocketInput() throws IOException {
|
||||
Bundle bundle = new Bundle();
|
||||
DataInputStream is = new DataInputStream(socket.getInputStream());
|
||||
while (true) {
|
||||
String name = readString(is);
|
||||
String name = readString();
|
||||
if (TextUtils.equals(name, "eof"))
|
||||
break;
|
||||
bundle.putString(name, readString(is));
|
||||
bundle.putString(name, readString());
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
protected DataOutputStream getOutputStream() throws IOException {
|
||||
return new DataOutputStream(socket.getOutputStream());
|
||||
public void response() {
|
||||
try {
|
||||
onResponse();
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
out.close();
|
||||
socket.close();
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
public abstract void response();
|
||||
public abstract void connect(String name) throws IOException;
|
||||
|
||||
protected abstract void onResponse() throws IOException;
|
||||
|
||||
public static void handleLogs(Intent intent, int version) {
|
||||
MagiskManager mm = Data.MM();
|
||||
|
||||
if (intent == null) return;
|
||||
|
||||
int fromUid = intent.getIntExtra("from.uid", -1);
|
||||
if (fromUid < 0) return;
|
||||
if (fromUid == Process.myUid()) return;
|
||||
|
||||
Policy policy = mm.mDB.getPolicy(fromUid);
|
||||
if (policy == null) {
|
||||
MagiskManager mm = Data.MM();
|
||||
PackageManager pm = mm.getPackageManager();
|
||||
Policy policy;
|
||||
|
||||
boolean notify;
|
||||
Bundle data = intent.getExtras();
|
||||
if (data.containsKey("notify")) {
|
||||
notify = data.getBoolean("notify");
|
||||
try {
|
||||
policy = new Policy(fromUid, mm.getPackageManager());
|
||||
policy = new Policy(fromUid, pm);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Doesn't report whether notify or not, check database ourselves
|
||||
policy = mm.mDB.getPolicy(fromUid);
|
||||
if (policy == null)
|
||||
return;
|
||||
notify = policy.notification;
|
||||
}
|
||||
|
||||
SuLogEntry log = new SuLogEntry(policy);
|
||||
if (version == 1) {
|
||||
String action = intent.getStringExtra("action");
|
||||
if (action == null) return;
|
||||
switch (action) {
|
||||
case "allow":
|
||||
log.action = true;
|
||||
policy.policy = Policy.ALLOW;
|
||||
break;
|
||||
case "deny":
|
||||
log.action = false;
|
||||
policy.policy = Policy.DENY;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
switch (intent.getIntExtra("policy", -1)) {
|
||||
case Policy.ALLOW:
|
||||
log.action = true;
|
||||
break;
|
||||
case Policy.DENY:
|
||||
log.action = false;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
policy.policy = data.getInt("policy", -1);
|
||||
if (policy.policy < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
String message = mm.getString(log.action ?
|
||||
R.string.su_allow_toast : R.string.su_deny_toast, policy.appName);
|
||||
if (notify)
|
||||
handleNotify(policy);
|
||||
|
||||
SuLogEntry log = new SuLogEntry(policy);
|
||||
|
||||
int toUid = intent.getIntExtra("to.uid", -1);
|
||||
if (toUid < 0) return;
|
||||
int pid = intent.getIntExtra("pid", -1);
|
||||
if (pid < 0) return;
|
||||
String command = intent.getStringExtra("command");
|
||||
if (command == null) return;
|
||||
log.toUid = toUid;
|
||||
log.fromPid = pid;
|
||||
log.command = command;
|
||||
log.date = new Date();
|
||||
mm.mDB.addLog(log);
|
||||
}
|
||||
|
||||
private static void handleNotify(Policy policy) {
|
||||
MagiskManager mm = Data.MM();
|
||||
String message = mm.getString(policy.policy == Policy.ALLOW ?
|
||||
R.string.su_allow_toast : R.string.su_deny_toast, policy.appName);
|
||||
if (policy.notification && Data.suNotificationType == Const.Value.NOTIFICATION_TOAST)
|
||||
Utils.toast(message, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
if (policy.logging) {
|
||||
int toUid = intent.getIntExtra("to.uid", -1);
|
||||
if (toUid < 0) return;
|
||||
int pid = intent.getIntExtra("pid", -1);
|
||||
if (pid < 0) return;
|
||||
String command = intent.getStringExtra("command");
|
||||
if (command == null) return;
|
||||
log.toUid = toUid;
|
||||
log.fromPid = pid;
|
||||
log.command = command;
|
||||
log.date = new Date();
|
||||
mm.mDB.addLog(log);
|
||||
}
|
||||
public static void handleNotify(Intent intent) {
|
||||
MagiskManager mm = Data.MM();
|
||||
int fromUid = intent.getIntExtra("from.uid", -1);
|
||||
if (fromUid < 0) return;
|
||||
if (fromUid == Process.myUid()) return;
|
||||
try {
|
||||
Policy policy = new Policy(fromUid, mm.getPackageManager());
|
||||
policy.policy = intent.getIntExtra("policy", -1);
|
||||
if (policy.policy >= 0)
|
||||
handleNotify(policy);
|
||||
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||
}
|
||||
}
|
||||
|
@@ -6,25 +6,30 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.androidnetworking.AndroidNetworking;
|
||||
import com.topjohnwu.magisk.Const;
|
||||
import com.topjohnwu.magisk.Data;
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.container.Module;
|
||||
import com.topjohnwu.magisk.container.ValueSortedMap;
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import a.n;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static int getPrefsInt(SharedPreferences prefs, String key, int def) {
|
||||
@@ -78,7 +83,7 @@ public class Utils {
|
||||
if (mm.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) {
|
||||
if (scheduler.getAllPendingJobs().isEmpty() ||
|
||||
Const.UPDATE_SERVICE_VER > mm.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) {
|
||||
ComponentName service = new ComponentName(mm, n.class);
|
||||
ComponentName service = new ComponentName(mm, Data.classMap.get(UpdateCheckService.class));
|
||||
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
|
||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
.setPersisted(true)
|
||||
@@ -114,13 +119,40 @@ public class Utils {
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||
Map<String, Module> moduleMap = new ValueSortedMap<>();
|
||||
SuFile path = new SuFile(Const.MAGISK_PATH);
|
||||
String[] modules = path.list(
|
||||
SuFile[] modules = path.listFiles(
|
||||
(file, name) -> !name.equals("lost+found") && !name.equals(".core"));
|
||||
for (String name : modules) {
|
||||
Module module = new Module(Const.MAGISK_PATH + "/" + name);
|
||||
for (SuFile file : modules) {
|
||||
if (file.isFile()) continue;
|
||||
Module module = new Module(Const.MAGISK_PATH + "/" + file.getName());
|
||||
moduleMap.put(module.getId(), module);
|
||||
}
|
||||
Topic.publish(Topic.MODULE_LOAD_DONE, moduleMap);
|
||||
});
|
||||
}
|
||||
|
||||
public static String getAppLabel(ApplicationInfo info, PackageManager pm) {
|
||||
try {
|
||||
if (info.labelRes > 0) {
|
||||
Resources res = pm.getResourcesForApplication(info);
|
||||
Configuration config = new Configuration();
|
||||
config.setLocale(LocaleManager.locale);
|
||||
res.updateConfiguration(config, res.getDisplayMetrics());
|
||||
return res.getString(info.labelRes);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
return info.loadLabel(pm).toString();
|
||||
}
|
||||
|
||||
public static boolean showSuperUser() {
|
||||
if (Data.multiuserState < 0)
|
||||
Data.multiuserState = Data.MM().mDB.getSettings(Const.Key.SU_MULTIUSER_MODE,
|
||||
Const.Value.MULTIUSER_MODE_OWNER_ONLY);
|
||||
return Shell.rootAccess() && (Const.USER_ID == 0 ||
|
||||
Data.multiuserState != Const.Value.MULTIUSER_MODE_OWNER_MANAGED);
|
||||
}
|
||||
|
||||
public static String dlString(String url) {
|
||||
String s = (String) AndroidNetworking.get(url).build().executeForString().getResult();
|
||||
return s == null ? "" : s;
|
||||
}
|
||||
}
|
@@ -54,42 +54,42 @@
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
||||
</LinearLayout>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/app_version_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_info_outline"
|
||||
app:text="@string/app_version"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/app_changelog"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_history"
|
||||
app:text="@string/app_changelog"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/app_translators"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_language"
|
||||
app:text="@string/app_translators"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/follow_twitter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_twitter"
|
||||
app:text="@string/follow_twitter"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/app_source_code"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_github"
|
||||
app:text="@string/app_source_code"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/support_thread"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@@ -40,14 +40,14 @@
|
||||
android:text="@string/donation"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/paypal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_paypal"
|
||||
app:text="PayPal"/>
|
||||
|
||||
<a.o
|
||||
<a.l
|
||||
android:id="@+id/patreon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@@ -42,7 +42,7 @@
|
||||
android:visibility="gone">
|
||||
|
||||
<Button
|
||||
android:id="@+id/no_thanks"
|
||||
android:id="@+id/close"
|
||||
style="?android:borderlessButtonStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
|
@@ -1,7 +1,8 @@
|
||||
### 6.0.0
|
||||
- Update to latest AndroidX support library
|
||||
- Fix crashes when online repos contain incomplete metadata
|
||||
- Optimize BootSigner to use as little memory as possible, prevent OutOfMemoryError
|
||||
- Support new communication scheme between Magisk v17.2 and Magisk Manager
|
||||
- Enable excessive obfuscation to prevent APK analysis root detections (still not 100% obfuscated due to backwards compatibility with stable channel)
|
||||
|
||||
## v6.1.0
|
||||
- Introduce new downloading methods: no longer uses buggy system Download Manager
|
||||
- Introduce many new notifications for better user experience
|
||||
- Add support for Magisk v18.0
|
||||
- Change application name to "Manager" after hiding(repackaging) to prevent app name detection
|
||||
- Add built-in systemless hosts module (access in settings)
|
||||
- Auto launch the newly installed app after hiding(repackaging) and restoring Magisk Manager
|
||||
- Fix bug causing incomplete module.prop in modules to have improper UI
|
@@ -6,7 +6,7 @@ db_sepatch() {
|
||||
|
||||
db_clean() {
|
||||
local USERID=$1
|
||||
local DIR="/sbin/.core/db-${USERID}"
|
||||
local DIR="/sbin/.magisk/db-${USERID}"
|
||||
umount -l /data/user*/*/*/databases/su.db $DIR $DIR/*
|
||||
rm -rf $DIR
|
||||
[ "$USERID" = "*" ] && rm -fv /data/adb/magisk.db*
|
||||
@@ -26,7 +26,7 @@ db_restore() {
|
||||
db_setup() {
|
||||
local USER=$1
|
||||
local USERID=$(($USER / 100000))
|
||||
local DIR=/sbin/.core/db-${USERID}
|
||||
local DIR=/sbin/.magisk/db-${USERID}
|
||||
mkdir -p $DIR
|
||||
touch $DIR/magisk.db
|
||||
mount -o bind /data/adb/magisk.db $DIR/magisk.db
|
||||
@@ -49,8 +49,8 @@ fix_env() {
|
||||
sh update-binary extract
|
||||
rm -f update-binary magisk.apk
|
||||
cd /
|
||||
rm -rf /sbin/.core/busybox/*
|
||||
/sbin/.core/mirror/bin/busybox --install -s /sbin/.core/busybox
|
||||
rm -rf /sbin/.magisk/busybox/*
|
||||
/sbin/.magisk/mirror/bin/busybox --install -s /sbin/.magisk/busybox
|
||||
}
|
||||
|
||||
direct_install() {
|
||||
@@ -79,8 +79,8 @@ mm_patch_dtbo() {
|
||||
}
|
||||
|
||||
restore_imgs() {
|
||||
local SHA1=`cat /.backup/.sha1`
|
||||
[ -z $SHA1 ] && local SHA1=`grep_prop #STOCKSHA1`
|
||||
local SHA1=`grep_prop SHA1 /sbin/.magisk/config`
|
||||
[ -z $SHA1 ] && local SHA1=`cat /.backup/.sha1`
|
||||
[ -z $SHA1 ] && return 1
|
||||
local STOCKBOOT=/data/stock_boot_${SHA1}.img.gz
|
||||
local STOCKDTBO=/data/stock_dtbo.img.gz
|
||||
@@ -109,3 +109,36 @@ post_ota() {
|
||||
chmod 755 post-fs-data.d/post_ota.sh
|
||||
cd /
|
||||
}
|
||||
|
||||
add_hosts_module() {
|
||||
# Do not touch existing hosts module
|
||||
[ -d /sbin/.magisk/img/hosts ] && return
|
||||
cd /sbin/.magisk/img
|
||||
mkdir -p hosts/system/etc
|
||||
cat << EOF > hosts/module.prop
|
||||
id=hosts
|
||||
name=Systemless Hosts
|
||||
version=1.0
|
||||
versionCode=1
|
||||
author=Magisk Manager
|
||||
description=Magisk Manager built-in systemless hosts module
|
||||
minMagisk=17000
|
||||
EOF
|
||||
if [ -f .core/hosts ]; then
|
||||
# Migrate old hosts file to new module
|
||||
mv -f .core/hosts hosts/system/etc/hosts
|
||||
else
|
||||
cp -f /system/etc/hosts hosts/system/etc/hosts
|
||||
fi
|
||||
magisk --clone-attr /system/etc/hosts hosts/system/etc/hosts
|
||||
touch hosts/update
|
||||
touch hosts/auto_mount
|
||||
cd /
|
||||
}
|
||||
|
||||
rm_launch() {
|
||||
db_clean $1
|
||||
pm uninstall $2
|
||||
monkey -p $3 1
|
||||
exit
|
||||
}
|
||||
|
@@ -1,146 +1,208 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<resources>
|
||||
<!--Universal-->
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">الإضافات</string>
|
||||
<string name="downloads">التنزيلات</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="log">السجل</string>
|
||||
<string name="settings">الإعدادات</string>
|
||||
<string name="install">التثبيت</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk غير مثبت</string>
|
||||
|
||||
<string name="checking_for_updates">البحث عن تحديثات…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$s متاح!</string>
|
||||
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">الاستجابة غير صالحه</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="advanced_settings_title">إعدادات متقدمة</string>
|
||||
<string name="keep_force_encryption">الحفاظ علي قوه التشفير</string>
|
||||
<string name="keep_dm_verity">إبقاء AVB 2.0/dm-verity</string>
|
||||
<string name="current_magisk_title">نسخة Magisk المثبته: %1$s</string>
|
||||
<string name="install_magisk_title">آخر نسخة Magisk: %1$s</string>
|
||||
<string name="uninstall">إلغاء التثبيت</string>
|
||||
<string name="uninstall_magisk_title">إلغاء تثبيت Magisk</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
|
||||
<string name="no_modules_found">لم يعثر على الإضافات</string>
|
||||
<string name="update_file_created">سيتم تحديث الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_created">سيتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_deleted">لن يتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_created">سيتم تعطيل الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_removed">سيتم تمكين الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="author">انشئ بواسطة %1$s</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">يتوفر تحديث</string>
|
||||
<string name="installed">مثبت</string>
|
||||
<string name="not_installed">غير مثبت</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuReload">إعادة تحميل</string>
|
||||
<string name="menuClearLog">حذف السجل الآن</string>
|
||||
<string name="logs_cleared">تم حذف السجل بنجاح</string>
|
||||
<string name="log_is_empty">السجل فارغ</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">حول</string>
|
||||
<string name="app_changelog">تغييرات التطبيق</string>
|
||||
<string name="translators">xx6600xx ,silent_6600</string>
|
||||
<string name="app_version">إصدار التطبيق</string>
|
||||
<string name="app_source_code">الشفرة المصدرية</string>
|
||||
<string name="donation">التبرع</string>
|
||||
<string name="app_translators">مترجم التطبيق</string>
|
||||
<string name="support_thread">منتدى الدعم</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">إغلاق</string>
|
||||
<string name="repo_install_title">تثبيت %1$s</string>
|
||||
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
|
||||
<string name="download">التنزيل</string>
|
||||
<string name="reboot">إعادة التشغيل</string>
|
||||
<string name="zip_process_msg">معالجة الملف المضغوط …</string>
|
||||
<string name="magisk_update_title">تحديث Magisk جديد متوفر!</string>
|
||||
<string name="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
|
||||
<string name="release_notes">ملاحظات الإصدار</string>
|
||||
<string name="repo_cache_cleared">تم مسح الذاكرة المؤقته للمستودع</string>
|
||||
<string name="process_error">خطأ في العملية</string>
|
||||
<string name="internal_storage">يتم تخزين الملف المضغوط في:\n[التخزين الداخلي]%1$s</string>
|
||||
<string name="zip_process_title">معالجة</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">عام</string>
|
||||
<string name="settings_dark_theme_title">السمة الغامقة</string>
|
||||
<string name="settings_dark_theme_summary">تفعيل السمة الغامقة</string>
|
||||
<string name="settings_clear_cache_title">حذف الذاكرة المؤقتة للمستودع</string>
|
||||
<string name="settings_clear_cache_summary">حذف المعلومات المخزنة مؤقتا للمستودع على الانترنت، يجبر التطبيق لتحديث عبر الانترنت</string>
|
||||
|
||||
<string name="settings_core_only_title">Magisk الوضع الأساسي فقط</string>
|
||||
<string name="settings_core_only_summary">تمكين الميزات الأساسية فقط، لن يتم تحميل جميع الإضافات. MagiskSU، MagiskHide، systemless hosts، و لا يزال ممكنا</string>
|
||||
<string name="settings_magiskhide_summary">إخفاء Magisk من مختلف الاكتشافات</string>
|
||||
<string name="settings_hosts_title">تمكين المضيفين(الهوست) لـ systemless</string>
|
||||
<string name="settings_hosts_summary">Systemless يدعم تطبيقات حجب الإعلانات</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_20">20 ثانية</string>
|
||||
<string name="settings_su_request_30">30 ثانية</string>
|
||||
<string name="settings_su_request_60">60 ثانية</string>
|
||||
<string name="superuser_access">Superuser صلاحيات</string>
|
||||
<string name="auto_response">استجابة تلقائية</string>
|
||||
<string name="request_timeout">مهلة الطلب</string>
|
||||
<string name="superuser_notification">Superuser إشعارات</string>
|
||||
<string name="request_timeout_summary">%1$s ثانية</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="multiuser_hint_owner_request">تم إرسال طلب إلى مالك الجهاز. يرجى التبديل إلى المالك ومنح الإذن</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser طلبات</string>
|
||||
<string name="deny_with_str">رفض%1$s</string>
|
||||
<string name="deny">رفض</string>
|
||||
<string name="prompt">طلب</string>
|
||||
<string name="grant">سماح</string>
|
||||
<string name="su_warning">منح حق الوصول الكامل إلى جهازك.\nرفض إذا كنت غير متأكد!</string>
|
||||
<string name="forever">للابد</string>
|
||||
<string name="once">مره</string>
|
||||
<string name="tenmin">10 دقائق</string>
|
||||
<string name="twentymin">20 دقائق</string>
|
||||
<string name="thirtymin">30 دقائق</string>
|
||||
<string name="sixtymin">60 دقائق</string>
|
||||
<string name="su_allow_toast">%1$s يتم منح صلاحيات Superuser</string>
|
||||
<string name="su_deny_toast">%1$s يتم رفض صلاحيات Superuser</string>
|
||||
<string name="no_apps_found">لا توجد تطبيقات</string>
|
||||
<string name="su_snack_grant">Superuser الصلاحيات لـ %1$s تم منحها</string>
|
||||
<string name="su_snack_deny">Superuser الصلاحيات لـ %1$s تم رفضها</string>
|
||||
<string name="su_snack_notif_on">الإشعارات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_snack_notif_off">الإشعارات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_log_on">السجلات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_snack_log_off">السجلات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_revoke">%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="pid">PID:\u0020</string>
|
||||
<string name="target_uid">الهدف UID:\u0020</string>
|
||||
<string name="command">الأمر:\u0020</string>
|
||||
<string name="about">حول</string>
|
||||
<string name="advanced_settings_title">إعدادات متقدمة</string>
|
||||
<string name="app_changelog">تغييرات التطبيق</string>
|
||||
<string name="app_source_code">الشفرة المصدرية</string>
|
||||
<string name="app_translators">مترجم التطبيق</string>
|
||||
<string name="app_version">إصدار التطبيق</string>
|
||||
<string name="author">انشئ بواسطة %1$s</string>
|
||||
<string name="auto_response">استجابة تلقائية</string>
|
||||
<string name="checking_for_updates">البحث عن تحديثات…</string>
|
||||
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
|
||||
<string name="close">إغلاق</string>
|
||||
<string name="command">"الأمر: "</string>
|
||||
<string name="current_magisk_title">نسخة Magisk المثبته: %1$s</string>
|
||||
<string name="deny">رفض</string>
|
||||
<string name="deny_with_str">رفض%1$s</string>
|
||||
<string name="disable_file_created">سيتم تعطيل الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="disable_file_removed">سيتم تمكين الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="donation">التبرع</string>
|
||||
<string name="download">التنزيل</string>
|
||||
<string name="downloads">التنزيلات</string>
|
||||
<string name="forever">للابد</string>
|
||||
<string name="grant">سماح</string>
|
||||
<string name="install">التثبيت</string>
|
||||
<string name="install_magisk_title">آخر نسخة Magisk: %1$s</string>
|
||||
<string name="installed">مثبت</string>
|
||||
<string name="internal_storage">"يتم تخزين الملف المضغوط في:
|
||||
[التخزين الداخلي]%1$s"</string>
|
||||
<string name="keep_dm_verity">إبقاء AVB 2.0/dm-verity</string>
|
||||
<string name="keep_force_encryption">الحفاظ علي قوه التشفير</string>
|
||||
<string name="log">السجل</string>
|
||||
<string name="log_is_empty">السجل فارغ</string>
|
||||
<string name="logs_cleared">تم حذف السجل بنجاح</string>
|
||||
<string name="magisk_update_available">Magisk v%1$s متاح!</string>
|
||||
<string name="magisk_update_title">تحديث Magisk جديد متوفر!</string>
|
||||
<string name="magisk_version_error">Magisk غير مثبت</string>
|
||||
<string name="menuClearLog">حذف السجل الآن</string>
|
||||
<string name="menuReload">إعادة تحميل</string>
|
||||
<string name="modules">الإضافات</string>
|
||||
<string name="multiuser_hint_owner_request">تم إرسال طلب إلى مالك الجهاز. يرجى التبديل إلى المالك ومنح الإذن</string>
|
||||
<string name="multiuser_mode">وضع تعدد المستخدمين</string>
|
||||
<string name="no_apps_found">لا توجد تطبيقات</string>
|
||||
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
|
||||
<string name="no_modules_found">لم يعثر على الإضافات</string>
|
||||
<string name="none">بدون</string>
|
||||
<string name="not_installed">غير مثبت</string>
|
||||
<string name="once">مرة</string>
|
||||
<string name="owner_manage_summary">يمكن للمالك فقط إدارة صلاحيات الروت وتلقي مطالبات الطلب</string>
|
||||
<string name="owner_only_summary">المالك فقط لديه صلاحيات الروت</string>
|
||||
<string name="pid">"PID: "</string>
|
||||
<string name="process_error">خطأ في العملية</string>
|
||||
<string name="prompt">طلب</string>
|
||||
<string name="reboot">إعادة التشغيل</string>
|
||||
<string name="release_notes">ملاحظات الإصدار</string>
|
||||
<string name="remove_file_created">سيتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="remove_file_deleted">لن يتم حذف الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="repo_cache_cleared">تم مسح الذاكرة المؤقته للمستودع</string>
|
||||
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
|
||||
<string name="repo_install_title">تثبيت %1$s</string>
|
||||
<string name="request_timeout">مهلة الطلب</string>
|
||||
<string name="request_timeout_summary">%1$s ثانية</string>
|
||||
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
|
||||
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">الاستجابة غير صالحه</string>
|
||||
<string name="settings">الإعدادات</string>
|
||||
<string name="settings_clear_cache_summary">حذف المعلومات المخزنة مؤقتا للمستودع على الانترنت، يجبر التطبيق لتحديث عبر الانترنت</string>
|
||||
<string name="settings_clear_cache_title">حذف الذاكرة المؤقتة للمستودع</string>
|
||||
<string name="settings_core_only_summary">تمكين الميزات الأساسية فقط، لن يتم تحميل جميع الإضافات. MagiskSU، MagiskHide، systemless hosts، و لا يزال ممكنا</string>
|
||||
<string name="settings_core_only_title">Magisk الوضع الأساسي فقط</string>
|
||||
<string name="settings_dark_theme_summary">تفعيل السمة الغامقة</string>
|
||||
<string name="settings_dark_theme_title">السمة الغامقة</string>
|
||||
<string name="settings_general_category">عام</string>
|
||||
<string name="settings_hosts_summary">Systemless يدعم تطبيقات حجب الإعلانات</string>
|
||||
<string name="settings_hosts_title">تمكين المضيفين(الهوست) لـ systemless</string>
|
||||
<string name="settings_magiskhide_summary">إخفاء Magisk من مختلف الاكتشافات</string>
|
||||
<string name="settings_owner_manage">إدارة مالك الجهاز</string>
|
||||
<string name="settings_owner_only">مالك الجهاز فقط</string>
|
||||
<string name="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
|
||||
<string name="settings_su_adb">ADB فقط</string>
|
||||
<string name="settings_su_app">التطبيقات فقط</string>
|
||||
<string name="settings_su_app_adb">التطبيقات و ADB</string>
|
||||
<string name="settings_su_disable">معطل</string>
|
||||
<string name="settings_su_request_10">10 ثواني</string>
|
||||
<string name="settings_su_request_20">20 ثانية</string>
|
||||
<string name="settings_su_request_30">30 ثانية</string>
|
||||
<string name="settings_su_request_60">60 ثانية</string>
|
||||
<string name="settings_user_independent">مستخدم مستقل</string>
|
||||
<string name="sixtymin">60 دقائق</string>
|
||||
<string name="su_allow_toast">%1$s يتم منح صلاحيات Superuser</string>
|
||||
<string name="su_deny_toast">%1$s يتم رفض صلاحيات Superuser</string>
|
||||
<string name="su_request_title">Superuser طلبات</string>
|
||||
<string name="su_revoke_msg">تأكيد لسحب صلاحيات %1$s ?</string>
|
||||
<string name="su_revoke_title">سحب؟</string>
|
||||
<string name="su_snack_deny">Superuser الصلاحيات لـ %1$s تم رفضها</string>
|
||||
<string name="su_snack_grant">Superuser الصلاحيات لـ %1$s تم منحها</string>
|
||||
<string name="su_snack_log_off">السجلات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_log_on">السجلات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_snack_notif_off">الإشعارات لـ %1$s تم تعطيلها</string>
|
||||
<string name="su_snack_notif_on">الإشعارات لـ %1$s تم تفعيلها</string>
|
||||
<string name="su_snack_revoke">%1$s الصلاحيات سحبت</string>
|
||||
<string name="su_warning">"منح حق الوصول الكامل إلى جهازك.
|
||||
رفض إذا كنت غير متأكد!"</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="superuser_access">Superuser صلاحيات</string>
|
||||
<string name="superuser_notification">Superuser إشعارات</string>
|
||||
<string name="support_thread">منتدى الدعم</string>
|
||||
<string name="target_uid">"الهدف UID: "</string>
|
||||
<string name="tenmin">10 دقائق</string>
|
||||
<string name="thirtymin">30 دقائق</string>
|
||||
<string name="toast">ملاحظة منبثقة</string>
|
||||
<string name="translators">xx6600xx ,silent_6600</string>
|
||||
<string name="twentymin">20 دقائق</string>
|
||||
<string name="uninstall">إلغاء التثبيت</string>
|
||||
<string name="uninstall_magisk_title">إلغاء تثبيت Magisk</string>
|
||||
<string name="update_available">يتوفر تحديث</string>
|
||||
<string name="update_file_created">سيتم تحديث الإضافة في إعادة التشغيل التالي</string>
|
||||
<string name="user_indepenent_summary">كل مستخدم لديه قواعد روت منفصلة خاصة به</string>
|
||||
<string name="zip_process_msg">معالجة الملف المضغوط …</string>
|
||||
<string name="zip_process_title">معالجة</string>
|
||||
<string name="android_o_not_support">لا يدعم إصدار الأندرويد +8.0</string>
|
||||
<string name="auth_fail">فشل المصادقة</string>
|
||||
<string name="auth_fingerprint">مصادقة البصمة</string>
|
||||
<string name="boot_file_patch_msg">حدد الذاكرة المؤقتة لنسخة boot الأصلية بتنسيق img. أو .img.tar</string>
|
||||
<string name="complete_uninstall">إلغاء التثبيت بالكامل</string>
|
||||
<string name="direct_install">تثبيت مباشر (موصى به)</string>
|
||||
<string name="disable_fingerprint">لم يتم تعيين بصمات الأصابع أو لا يوجد جهاز مدعوم</string>
|
||||
<string name="download_zip_only">تحميل ملف zip فقط</string>
|
||||
<string name="dtbo_patched_reboot">قام مدير Magisk بتصحيح dtbo.img ، يرجى إعادة التشغيل</string>
|
||||
<string name="dtbo_patched_title">تم تصحيح DTBO!</string>
|
||||
<string name="env_fix_msg">يحتاج جهازك إلى إعداد إضافي لـ Magisk للعمل بشكل صحيح. سيتم تنزيل ملف zip لتثبيت Magisk ، هل تريد المتابعة الآن؟</string>
|
||||
<string name="env_fix_title">يتطلب إعداد إضافي</string>
|
||||
<string name="flashing">التثبيت</string>
|
||||
<string name="follow_twitter">تابعني على تويتر</string>
|
||||
<string name="global_summary">تستخدم كافة جلسات الجذر مساحة الأسم ذات التركيب العالمي</string>
|
||||
<string name="hide_manager_fail_toast">فشل إخفاء مدير Magisk …</string>
|
||||
<string name="hide_manager_title">إخفاء مدير Magisk…</string>
|
||||
<string name="hide_manager_msg">هذا قد يستغرق بعض الوقت…</string>
|
||||
<string name="install_inactive_slot">التثبيت على فتحة غير نشطة (بعد OTA)</string>
|
||||
<string name="install_inactive_slot_msg">"سيتم إجبار جهازك للتمهيد على الفتحة غير النشطة الحالية بعد إعادة التشغيل!
|
||||
فقط استخدام هذا الخيار بعد الانتهاء من OTA.
|
||||
استمرار؟"</string>
|
||||
<string name="invalid_update_channel">قناة تحديث غير صالحة</string>
|
||||
<string name="isolate_summary">سيكون لكل جلسة جذر مساحة الاسم الخاصة بها معزولة</string>
|
||||
<string name="language">اللغة</string>
|
||||
<string name="update_channel">تحديثات Magisk</string>
|
||||
<string name="manager_download_install">اضغط للتنزيل والتثبيت</string>
|
||||
<string name="manager_update_title">تحديث مدير Magisk الجديد متوفر!</string>
|
||||
<string name="menuSaveLog">حفظ السجل</string>
|
||||
<string name="mount_namespace_mode">وضع تركيب مساحة الأسم</string>
|
||||
<string name="no_boot_file_patch_support">"لا يدعم إصدار Magisk المستهدف تصحيح ملفات صور boot"</string>
|
||||
<string name="open_link_failed_toast">لم يتم العثور على تطبيق لفتح الرابط …</string>
|
||||
<string name="patch_boot_file">تصحيح ملف صورة boot</string>
|
||||
<string name="proprietary_notice">مدير Magisk هو FOSS ، والذي لا يحتوي على شفرة API الخاصة بشركة SafetyNet الخاصة بشركة Google.
|
||||
|
||||
هل تسمح لـ Magisk Manager بتنزيل ملحق (يحتوي على GoogleApiClient) لعمليات التحقق من SafetyNet؟ "</string>
|
||||
<string name="proprietary_title">تحميل رمز الملكية</string>
|
||||
<string name="reboot_bootloader">إعادة تمهيد إلى وضع Bootloader</string>
|
||||
<string name="reboot_download">إعادة تمهيد إلى وضع التحميل</string>
|
||||
<string name="reboot_recovery">إعادة تمهيد إلى وضع الإسترداد</string>
|
||||
<string name="requester_summary">"سترث جلسات الجذر مساحة الأسماء المطلوبة الخاصة بها"</string>
|
||||
<string name="restore_done">تمت الأستعادة!</string>
|
||||
<string name="restore_fail">النسخ الاحتياطي الأصلي غير موجود!</string>
|
||||
<string name="restore_img">استعادة الصور</string>
|
||||
<string name="restore_img_msg">الأستعادة …</string>
|
||||
<string name="safetyNet_api_error">خطأ SafetyNet API</string>
|
||||
<string name="select_method">حدد الطريقة</string>
|
||||
<string name="settings_boot_format_summary">"حدد تنسيق ملف boot المصحح للإخراج.
|
||||
اختر img. للتثبيت من خلال وضع fastboot/ التحميل ؛ اختر img.tar. للتثبيت مع ODIN. "</string>
|
||||
<string name="settings_boot_format_title">تنسيق إخراج ملف Boot المصحح</string>
|
||||
<string name="settings_check_update_summary">التحقق من التحديثات في الخلفية بشكل دوري</string>
|
||||
<string name="settings_check_update_title">تفقد التحديث</string>
|
||||
<string name="settings_hide_manager_summary">أعد حزم مدير Magisk مع اسم حزمة عشوائية</string>
|
||||
<string name="settings_hide_manager_title">إخفاء مدير Magisk</string>
|
||||
<string name="settings_ns_global">مساحة الاسم العالمية</string>
|
||||
<string name="settings_ns_isolate">مساحة الاسم المعزولة</string>
|
||||
<string name="settings_ns_requester">وراثة مساحة الاسم</string>
|
||||
<string name="settings_restore_manager_summary">استعادة مدير Magisk مع الحزمة الأصلية</string>
|
||||
<string name="settings_restore_manager_title">استعادة مدير Magisk</string>
|
||||
<string name="settings_su_fingerprint_summary">أستخدام ماسح بصمات الأصابع للسماح بطلبات المستخدم المتميز</string>
|
||||
<string name="settings_su_fingerprint_title">تمكين مصادقة البصمة</string>
|
||||
<string name="settings_su_reauth_summary">أعد المصادقة على صلاحيات المستخدم المتميز بعد إجراء ترقيات للتطبيق</string>
|
||||
<string name="settings_su_reauth_title">إعادة المصادقة بعد الترقية</string>
|
||||
<string name="settings_update">تحديث الاعدادات</string>
|
||||
<string name="settings_update_beta">بيتا</string>
|
||||
<string name="settings_update_channel_title">قناة التحديث</string>
|
||||
<string name="settings_update_custom">مخصص</string>
|
||||
<string name="settings_update_custom_msg">أدخل عنوان URL مخصص</string>
|
||||
<string name="settings_update_stable">مستقر</string>
|
||||
<string name="setup_done">تم الإعداد</string>
|
||||
<string name="setup_fail">فشل الإعداد</string>
|
||||
<string name="setup_msg">تشغيل إعداد البيئة…</string>
|
||||
<string name="setup_title">إعداد إضافي</string>
|
||||
<string name="sort_by_name">الترتيب حسب الاسم</string>
|
||||
<string name="sort_by_update">فرز حسب آخر تحديث</string>
|
||||
<string name="sorting_order">ترتيب الفرز</string>
|
||||
<string name="su_db_corrupt">قاعدة بيانات SU معطوبة ، سوف يتم إنشاء قاعدة بيانات جديدة</string>
|
||||
<string name="system_default">(أفتراضي النظام)</string>
|
||||
<string name="uninstall_magisk_msg">سيتم تعطيل/إزالة جميع الوحدات. ستتم إزالة الجذر ، وربما تشفير بياناتك إذا كانت بياناتك غير مشفرة حالياً</string>
|
||||
<string name="update">تحديث %1$s</string>
|
||||
<string name="updated_on">تم التحديث في: %1$s</string>
|
||||
<string name="warning">تحذير</string>
|
||||
<string name="zip_download_msg">تحميل ملف zip (%1$d%%)…</string>
|
||||
<string name="zip_download_title">يتم التحميل</string>
|
||||
<string name="downloading_toast">جاري التنزيل %1$s</string>
|
||||
<string name="download_file_error">خطأ تنزيل الملف</string>
|
||||
<string name="no_rw_storage">أن هذه الميزة لا تعمل دون الحصول على إذن الكتابة على التخزين الخارجي.</string>
|
||||
</resources>
|
||||
|
@@ -9,13 +9,13 @@
|
||||
<string name="install">Инсталиране</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk не е инсталиран</string>
|
||||
<string name="magisk_version_error">Magisk не е инсталиран.</string>
|
||||
<string name="checking_for_updates">Проверяваме за актуализации…</string>
|
||||
<string name="magisk_update_available">Magisk версия %1$s е налице!</string>
|
||||
<string name="magisk_update_available">Magisk версия %1$s е налице.</string>
|
||||
<string name="invalid_update_channel">Невалиден канал за актуализации</string>
|
||||
<string name="safetyNet_check_text">Докоснете за стартиране на SafetyNet проверката</string>
|
||||
<string name="checking_safetyNet_status">Проверяване статуса на SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">SafetyNet проверката е успешна</string>
|
||||
<string name="safetyNet_check_text">Докоснете за стартиране на SafetyNet проверката.</string>
|
||||
<string name="checking_safetyNet_status">Проверка статуса на SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">SafetyNet проверката е успешна.</string>
|
||||
<string name="safetyNet_api_error">Грешка в SafetyNet ППИ</string>
|
||||
<string name="safetyNet_res_invalid">Невалиден отговор</string>
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
<string name="install_magisk_title">Най-нова версия: %1$s</string>
|
||||
<string name="uninstall">Деинсталиране</string>
|
||||
<string name="uninstall_magisk_title">Деинсталиране на Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Всички модули ще бъдат изключени/премахнати. Руут достъпът ще бъде премахнат и е възможно криптиране на данните Ви</string>
|
||||
<string name="uninstall_magisk_msg">Всички модули ще бъдат изключени/премахнати. Руут достъпът ще бъде премахнат и е възможно криптиране на данните Ви.</string>
|
||||
<string name="update">Актуализация %1$s</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Не е представена информация)</string>
|
||||
<string name="no_modules_found">Няма намерени модули</string>
|
||||
<string name="update_file_created">Модулът ще бъде обновен при следващото рестартиране</string>
|
||||
<string name="remove_file_created">Модулът ще бъде премахнат при следващото рестартиране</string>
|
||||
<string name="remove_file_deleted">Модулът няма да бъде премахнат при следващото рестартиране</string>
|
||||
<string name="disable_file_created">Модулът ще бъде изключен при следващото рестартиране</string>
|
||||
<string name="disable_file_removed">Модулът ще бъде активиран при следващото рестартиране</string>
|
||||
<string name="no_modules_found">Няма намерени модули.</string>
|
||||
<string name="update_file_created">Модулът ще бъде обновен при следващото рестартиране.</string>
|
||||
<string name="remove_file_created">Модулът ще бъде премахнат при следващото рестартиране.</string>
|
||||
<string name="remove_file_deleted">Модулът няма да бъде премахнат при следващото рестартиране.</string>
|
||||
<string name="disable_file_created">Модулът ще бъде изключен при следващото рестартиране.</string>
|
||||
<string name="disable_file_removed">Модулът ще бъде активиран при следващото рестартиране.</string>
|
||||
<string name="author">Създаден от %1$s</string>
|
||||
<string name="reboot_recovery">Рестартиране в режима за възстановяване</string>
|
||||
<string name="reboot_bootloader">Рестартиране в буутлоудъра</string>
|
||||
<string name="reboot_download">Рестартиране в даунлоуд режима</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Налице е актуализация</string>
|
||||
<string name="installed">Инсталиран</string>
|
||||
<string name="not_installed">Не е инсталиран</string>
|
||||
<string name="update_available">Налице е актуализация.</string>
|
||||
<string name="installed">Инсталирани</string>
|
||||
<string name="not_installed">Не са инсталирани</string>
|
||||
<string name="updated_on">Актуализиран на: %1$s</string>
|
||||
<string name="sorting_order">Сортиране</string>
|
||||
<string name="sort_by_name">Сортиране по наименование</string>
|
||||
@@ -56,8 +56,8 @@
|
||||
<string name="menuSaveLog">Запазване на доклад</string>
|
||||
<string name="menuReload">Презареждане</string>
|
||||
<string name="menuClearLog">Изчистване на дневника</string>
|
||||
<string name="logs_cleared">Успешно изчистване на дневника</string>
|
||||
<string name="log_is_empty">Дневникът е празен</string>
|
||||
<string name="logs_cleared">Успешно изчистване на дневника.</string>
|
||||
<string name="log_is_empty">Дневникът е празен.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Относно</string>
|
||||
@@ -76,115 +76,121 @@
|
||||
<string name="repo_install_msg">Желаете ли да инсталирате %1$s сега?</string>
|
||||
<string name="download">Изтегляне</string>
|
||||
<string name="reboot">Рестартиране</string>
|
||||
<string name="magisk_update_title">Налице е нова версия на Magisk!</string>
|
||||
<string name="settings_reboot_toast">Трябва да рестартирате за прилагане на настройките</string>
|
||||
<string name="magisk_update_title">Налице е нова версия на Magisk.</string>
|
||||
<string name="settings_reboot_toast">Трябва да рестартирате устройството, за да бъдат приложени настройките.</string>
|
||||
<string name="release_notes">Бележки</string>
|
||||
<string name="repo_cache_cleared">Кешът на хранилището е изчистен</string>
|
||||
<string name="repo_cache_cleared">Кешът на хранилището е изчистен.</string>
|
||||
<string name="process_error">Грешка при процеса</string>
|
||||
<string name="internal_storage">Архивът е записан във:\n[Вътрешната памет]%1$s</string>
|
||||
<string name="internal_storage">Архивът е записан във:\n[Вътрешната памет]%1$s.</string>
|
||||
<string name="zip_download_title">Изтегляне</string>
|
||||
<string name="zip_download_msg">Изтегляне на архив (%1$d%%)…</string>
|
||||
<string name="zip_process_title">Обработване</string>
|
||||
<string name="zip_process_msg">Обработване на архива…</string>
|
||||
<string name="manager_update_title">Налице е нова версия на Magisk Manager!</string>
|
||||
<string name="manager_download_install">Докоснете за изтегляне и инсталиране</string>
|
||||
<string name="manager_update_title">Налице е нова версия на Magisk Manager.</string>
|
||||
<string name="manager_download_install">Докоснете за изтегляне и инсталиране.</string>
|
||||
<string name="dtbo_patched_title">DTBO беше модифициран!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager модифицира dtbo.img, моля да рестартирате</string>
|
||||
<string name="magisk_updates">Актуализации на Magisk</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager модифицира dtbo.img, моля да рестартирате устройството.</string>
|
||||
<string name="update_channel">Актуализации на Magisk</string>
|
||||
<string name="flashing">Инсталиране</string>
|
||||
<string name="hide_manager_toast">Скриване на Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Може да отнеме време…</string>
|
||||
<string name="hide_manager_fail_toast">Скриването на Magisk Manager е неуспешно…</string>
|
||||
<string name="open_link_failed_toast">Не бе намерено приложение за отваряне на линка…</string>
|
||||
<string name="hide_manager_title">Скриване на Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Може да отнеме известно време.</string>
|
||||
<string name="hide_manager_fail_toast">Скриването на Magisk Manager бе неуспешно.</string>
|
||||
<string name="open_link_failed_toast">Не бе намерено приложение за отваряне на линка.</string>
|
||||
<string name="download_zip_only">Изтегляне само на архив</string>
|
||||
<string name="patch_boot_file">Модифициране на Boot образа</string>
|
||||
<string name="direct_install">Директно инсталиране (Препоръчва се)</string>
|
||||
<string name="direct_install">Директно инсталиране (Препоръчва се.)</string>
|
||||
<string name="install_inactive_slot">Инсталиране на неактивен слот (След OTA)</string>
|
||||
<string name="warning">Внимание</string>
|
||||
<string name="install_inactive_slot_msg">Вашето устройство НАЛОЖИТЕЛНО ще стартира текущия неактивен слот при следващото рестартиране!\nИзползвайте тази опция само след приключване на OTA актуализация.\nПродължаване?</string>
|
||||
<string name="install_inactive_slot_msg">Вашето устройство НАЛОЖИТЕЛНО ще стартира текущия неактивен слот при следващото рестартиране.\nИзползвайте тази опция само след като приключи инсталирането на OTA.\nПродължаване?</string>
|
||||
. <string name="select_method">Избор на метод</string>
|
||||
<string name="no_boot_file_patch_support">Избраната версия на Magisk не поддържа модифициране на Boot образи</string>
|
||||
<string name="boot_file_patch_msg">Изберете стоков Boot образ с формат .img или .img.tar</string>
|
||||
<string name="no_boot_file_patch_support">Текущата версия на Magisk не поддържа модифициране на boot образи.</string>
|
||||
<string name="boot_file_patch_msg">Изберете стоков boot образ с формат .img или .img.tar.</string>
|
||||
<string name="complete_uninstall">Пълно деинсталиране</string>
|
||||
<string name="restore_img">Възстановяване на образи</string>
|
||||
<string name="restore_img_msg">Възстановяване…</string>
|
||||
<string name="restore_done">Възстановяването е успешно!</string>
|
||||
<string name="restore_fail">Не е налице архив на стоковия образ!</string>
|
||||
<string name="proprietary_title">Изтегляне на патентования код</string>
|
||||
<string name="proprietary_notice">Magisk Manager е FOSS и затова не включва частния код за SafetyNet ППИ на Google.\n\nПозволявате ли на Magisk Manager да изтегли добавката (включва GoogleApiClient) за SafetyNet проверки?</string>
|
||||
<string name="su_db_corrupt">Базата данни за SU е повредена, ще създадем нов db файл</string>
|
||||
<string name="setup_done">Първоначалната настройка е готова</string>
|
||||
<string name="setup_fail">Първоначалната настройка е неуспешна</string>
|
||||
<string name="proprietary_notice">Magisk Manager е FOSS и затова не включва патентования код за SafetyNet ППИ на Google.\n\nПозволявате ли на Magisk Manager да изтегли добавката (включва GoogleApiClient) за SafetyNet проверки?</string>
|
||||
<string name="su_db_corrupt">Базата данни за SU е повредена. Ще създадем нов db файл.</string>
|
||||
<string name="setup_done">Първоначалната настройка е готова.</string>
|
||||
<string name="setup_fail">Първоначалната настройка е неуспешна.</string>
|
||||
<string name="env_fix_title">Изисква допълнително настройване</string>
|
||||
<string name="env_fix_msg">Вашето устройство се нуждае от допълнителни настройки за Magisk, за да работи перфектно. Ще бъде изтеглен архивът за настройка на Magisk. Желаете ли да продължите?</string>
|
||||
<string name="setup_title">Допълнителни настройване</string>
|
||||
<string name="setup_msg">Настройването на средата е в ход…</string>
|
||||
|
||||
<string name="env_fix_msg">Вашето устройство се нуждае от допълнително надстройване на Magisk, за да работи нормално. Ще бъде изтеглен архивът за надстройка на Magisk. Желаете ли да продължите?</string>
|
||||
<string name="setup_title">Допълнително надстройване</string>
|
||||
<string name="setup_msg">Надстройването на средата е в ход…</string>
|
||||
<string name="download_file_error">Грешка при изтеглянето на файла.</string>
|
||||
<string name="downloading_toast">Изтегляне на %1$s</string>
|
||||
<string name="no_rw_storage">Тази функция няма да работи без разрешение за запис във външната памет.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Общи</string>
|
||||
<string name="settings_dark_theme_title">Тъмна тема</string>
|
||||
<string name="settings_dark_theme_summary">Включване на тъмната тема</string>
|
||||
<string name="settings_clear_cache_title">Изчистване кеша на хранилището</string>
|
||||
<string name="settings_clear_cache_summary"> Изчистване на кешираната информация на онлайн хранилището за принудително обновяване</string>
|
||||
<string name="settings_clear_cache_summary">Изчистване на кешираната информация на онлайн хранилището за принудителното му обновяване.</string>
|
||||
<string name="settings_hide_manager_title">Скриване на Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Смяна пакетното наименование на Magisk Manager със случайно наименование</string>
|
||||
<string name="settings_hide_manager_summary">Смяна пакетното наименование на Magisk Manager със случайно наименование.</string>
|
||||
<string name="settings_restore_manager_title">Възстановяване на Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Възстановяване на оригиналното пакетно наименование на Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Възстановяване на оригиналното пакетно наименование на Magisk Manager.</string>
|
||||
<string name="language">Език</string>
|
||||
<string name="system_default">(Системен)</string>
|
||||
<string name="settings_update">Настройки за актуализиране</string>
|
||||
<string name="settings_check_update_title">Проверка за актуализации</string>
|
||||
<string name="settings_check_update_summary">Периодично проверяване за актуализации във фонов режим</string>
|
||||
<string name="settings_check_update_summary">Периодично проверяване за актуализации във фонов режим.</string>
|
||||
<string name="settings_update_channel_title">Канал за актуализации</string>
|
||||
<string name="settings_update_stable">Стабилен</string>
|
||||
<string name="settings_update_beta">Бета</string>
|
||||
<string name="settings_update_custom">Потребителски</string>
|
||||
<string name="settings_update_custom_msg">Въведете потребителски URL</string>
|
||||
<string name="settings_boot_format_title">Изходен формат за модифициран Boot образ</string>
|
||||
<string name="settings_boot_format_summary">Избор на изходен формат за модифициран Boot образ.\nИзберете .img, за инсталиране чрез fastboot/download режим; изберете .img.tar за инсталиране чрез ODIN.</string>
|
||||
<string name="settings_boot_format_title">Изходен формат за модифициран boot образ</string>
|
||||
<string name="settings_boot_format_summary">Избор на изходен формат за модифициран boot образ.\nИзберете .img за инсталиране чрез fastboot/даунлоуд режима; изберете .img.tar за инсталиране чрез ODIN.</string>
|
||||
<string name="settings_core_only_title">Режим Magisk Core Only</string>
|
||||
<string name="settings_core_only_summary">Работят само основни функции, като MagiskSU, MagiskHide и несистемни хостове, без модули.</string>
|
||||
<string name="settings_magiskhide_summary">Скриване на Magisk от различни детектори</string>
|
||||
<string name="settings_core_only_summary">Работят само основни функции, като MagiskSU и MagiskHide, без всякакви модули.</string>
|
||||
<string name="settings_magiskhide_summary">Скриване на Magisk от различни детектори.</string>
|
||||
<string name="settings_hosts_title">Несистемни хостове</string>
|
||||
<string name="settings_hosts_summary">Поддръжка на несистемни хостове за използване на приложения, блокиращи реклами</string>
|
||||
<string name="settings_hosts_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">Superuser достъп</string>
|
||||
<string name="auto_response">Автоматичен отговор</string>
|
||||
<string name="request_timeout">Време за запитване</string>
|
||||
<string name="superuser_notification">Superuser известие</string>
|
||||
<string name="request_timeout_summary">%1$s секунди</string>
|
||||
<string name="settings_su_reauth_title">Повторно запитване след ъпгрейд</string>
|
||||
<string name="settings_su_reauth_summary">Повторно запитване за Superuser достъп след ъпгрейд на приложение</string>
|
||||
<string name="settings_su_fingerprint_title"> Superuser права само с пръстов отпечатък</string>
|
||||
<string name="settings_su_fingerprint_summary">Използване на сензора за пръстови отпечатъци за разрешаване на Superuser досъп</string>
|
||||
<string name="auth_fingerprint">Удостоверете с пръстов отпечатък</string>
|
||||
<string name="settings_su_reauth_title">Повторно запитване след актуализация</string>
|
||||
<string name="settings_su_reauth_summary">Повторно запитване за Superuser достъп след актуализация на приложенията.</string>
|
||||
<string name="settings_su_fingerprint_title">Superuser права само с пръстов отпечатък</string>
|
||||
<string name="settings_su_fingerprint_summary">Използване на сензора за пръстови отпечатъци за разрешаване на Superuser достъп.</string>
|
||||
<string name="auth_fingerprint">Удостоверете с пръстов отпечатък.</string>
|
||||
|
||||
<string name="multiuser_mode">Потребителски достъп</string>
|
||||
<string name="settings_owner_only">Само собственик</string>
|
||||
<string name="settings_owner_manage">Управление от страна на собственика</string>
|
||||
<string name="settings_user_independent">Независими потребители</string>
|
||||
<string name="owner_only_summary">Само собственикът има руут достъп</string>
|
||||
<string name="owner_manage_summary">Само собственикът може да управлява руут достъпа и да получава запитвания за достъп</string>
|
||||
<string name="user_indepenent_summary">Всеки потребител има собствени правила за руут достъп</string>
|
||||
<string name="multiuser_hint_owner_request">Направено е запитване до собственика на устройството. Моля да преминете в режим на собственик и да дадете разрешение</string>
|
||||
<string name="owner_only_summary">Само собственикът има руут достъп.</string>
|
||||
<string name="owner_manage_summary">Само собственикът може да управлява руут достъпа и да получава запитвания за достъп.</string>
|
||||
<string name="user_indepenent_summary">Всеки потребител има собствени правила за руут достъп.</string>
|
||||
<string name="multiuser_hint_owner_request">Направено е запитване до собственика на устройството. Моля да преминете в режим на собственик и да дадете разрешение.</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="android_o_not_support">Не поддържа Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Не са добавени пръстови отпечатъци или устройството не поддържа тази функция</string>
|
||||
<string name="global_summary">Всички сесии с руут достъп използват глобалното именно пространство.</string>
|
||||
<string name="requester_summary">Всички сесии с руут достъп наследяват именното пространство на запитващото приложение.</string>
|
||||
<string name="isolate_summary">Всички сесии с руут достъп имат собствени именни пространства.</string>
|
||||
<string name="android_o_not_support">Не поддържа Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Не са добавени пръстови отпечатъци или устройството не поддържа тази функция.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Запитване за Superuser достъп</string>
|
||||
@@ -192,28 +198,28 @@
|
||||
<string name="deny">Отказ</string>
|
||||
<string name="prompt">Запитване</string>
|
||||
<string name="grant">Разрешаване</string>
|
||||
<string name="su_warning">Дава пълен достъп до устройството Ви.\Откажете, ако не Сте сигурен/на!</string>
|
||||
<string name="su_warning">Дава пълен достъп до устройството Ви.\Откажете, ако не сте сигурен/на.</string>
|
||||
<string name="forever">Завинаги</string>
|
||||
<string name="once">Веднъж</string>
|
||||
<string name="tenmin">10 мин</string>
|
||||
<string name="twentymin">20 мин</string>
|
||||
<string name="thirtymin">30 мин</string>
|
||||
<string name="sixtymin">60 мин</string>
|
||||
<string name="su_allow_toast">На %1$s бе разрешен Superuser достъп</string>
|
||||
<string name="su_deny_toast">На %1$s бе отказан Superuser достъп</string>
|
||||
<string name="no_apps_found">Няма намерени приложения</string>
|
||||
<string name="su_snack_grant">На %1$s е предоставен Superuser достъп</string>
|
||||
<string name="su_snack_deny">На %1$s е отказан Superuser достъп</string>
|
||||
<string name="su_snack_notif_on">Извесията за %1$s са включени</string>
|
||||
<string name="su_snack_notif_off">Извесията за %1$s са изключени</string>
|
||||
<string name="su_snack_log_on">Записването в дневника за %1$s е включено</string>
|
||||
<string name="su_snack_log_off">Записването в дневника за %1$s е изключено</string>
|
||||
<string name="su_snack_revoke">Настройките за достъп на %1$s са анулирани</string>
|
||||
<string name="su_allow_toast">На %1$s бе разрешен Superuser достъп.</string>
|
||||
<string name="su_deny_toast">На %1$s бе отказан Superuser достъп.</string>
|
||||
<string name="no_apps_found">Няма намерени приложения.</string>
|
||||
<string name="su_snack_grant">На %1$s е предоставен Superuser достъп.</string>
|
||||
<string name="su_snack_deny">На %1$s е отказан Superuser достъп.</string>
|
||||
<string name="su_snack_notif_on">Известията за %1$s са включени.</string>
|
||||
<string name="su_snack_notif_off">Известията за %1$s са изключени.</string>
|
||||
<string name="su_snack_log_on">Записването в дневника за %1$s е включено.</string>
|
||||
<string name="su_snack_log_off">Записването в дневника за %1$s е изключено.</string>
|
||||
<string name="su_snack_revoke">Настройките за достъп на %1$s са анулирани.</string>
|
||||
<string name="su_revoke_title">Анулиране?</string>
|
||||
<string name="su_revoke_msg">Потвърждавате ли анулирането на настройките за достъп на %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Без</string>
|
||||
<string name="auth_fail">Неуспешна заверка</string>
|
||||
<string name="auth_fail">Неуспешна заверка.</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<string name="uninstall_magisk_msg">Tots els mòduls seran desactivats / eliminats. L\'accés Root s\'eliminarà i, possiblement, xifrarà totes les dades si no estan ja xifrades.</string>
|
||||
<string name="uninstall_magisk_title">Desinstal·lar Magisk</string>
|
||||
<string name="update">Actualització %1$s</string>
|
||||
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(No hi ha informació)</string>
|
||||
<string name="no_modules_found">No s’han trobat mòduls</string>
|
||||
@@ -90,10 +90,10 @@
|
||||
<string name="manager_download_install">Premi per a descarregar i instal·lar</string>
|
||||
<string name="dtbo_patched_title">DTBO ha estat arranjat</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ha arranjat dtbo.img, per favor reinicia el dispositiu</string>
|
||||
<string name="magisk_updates">Actualització de Magisk</string>
|
||||
<string name="flashing">Flashejat</string>
|
||||
<string name="hide_manager_toast">Amagant Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Això pot tardar un temps…</string>
|
||||
<string name="update_channel">Actualització de Magisk</string>
|
||||
<string name="flashing">Instal·lant</string>
|
||||
<string name="hide_manager_title">Amagant Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Això pot tardar un temps…</string>
|
||||
<string name="hide_manager_fail_toast">L’amagament de Magisk Manager ha fallat…</string>
|
||||
<string name="open_link_failed_toast">No s’ha trobat cap aplicació per obrir l’enllaç…</string>
|
||||
<string name="download_zip_only">Descarregar només l’arxiu ZIP</string>
|
||||
@@ -117,7 +117,7 @@
|
||||
<string name="env_fix_msg">El seu dispositiu requereix d’una instal·lació addicional per tal de que Magisk funcioni correctament. Es descarregarà el zip d’instalació de Magisk, desitja continuar ara?</string>
|
||||
<string name="setup_title">Configuració Addicional</string>
|
||||
<string name="setup_msg">Executant Configuració d\'Entorn</string>
|
||||
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
<string name="settings_dark_theme_title">Tema obscur</string>
|
||||
@@ -140,8 +140,8 @@
|
||||
<string name="settings_update_custom_msg">Inserta una URL personalitzada</string>
|
||||
<string name="settings_boot_format_title">Arranja la imatge d’arrancada segons el tipus de format</string>
|
||||
<string name="settings_boot_format_summary">Seleccionar el format de sortida per arranjar la imatge d’arrancada.\nTriï .img per flashejar mitcançant fastboot/download; triï .img.tar per flashejar amb ODIN.</string>
|
||||
|
||||
<string name="settings_core_only_summary">Habilitar només les funcions principals, no es carregaran tots els mòduls. MagiskSU, MagiskHide, y Systemless Hosts seguirán habilitats</string>
|
||||
|
||||
<string name="settings_core_only_summary">Habilitar només les funcions principals, no es carregaran tots els mòduls. MagiskSU y MagiskHide seguirán habilitats</string>
|
||||
<string name="settings_magiskhide_summary">Amagar Magisk de varies deteccions</string>
|
||||
<string name="settings_hosts_title">Systemless Hosts</string>
|
||||
<string name="settings_hosts_summary">Suport per aplicacions tipus Adblock fora de la partició del sistema</string>
|
||||
@@ -151,8 +151,10 @@
|
||||
<string name="settings_su_adb">Només ADB</string>
|
||||
<string name="settings_su_disable">Deshabilitat</string>
|
||||
<string name="settings_su_request_10">10 segons</string>
|
||||
<string name="settings_su_request_15">15 segons</string>
|
||||
<string name="settings_su_request_20">20 segons</string>
|
||||
<string name="settings_su_request_30">30 segons</string>
|
||||
<string name="settings_su_request_45">45 segons</string>
|
||||
<string name="settings_su_request_60">60 segons</string>
|
||||
<string name="superuser_access">Accés de superusuari</string>
|
||||
<string name="auto_response">Resposta automàtica</string>
|
||||
@@ -164,9 +166,9 @@
|
||||
<string name="settings_su_fingerprint_title">Autenticació per Empremta Dactilar</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilitza el sensor d’Empremta Dactilar per permetre les sol·licituds de superusuari</string>
|
||||
<string name="auth_fingerprint">Autenticar Emprempta Digital</string>
|
||||
|
||||
|
||||
<string name="multiuser_mode">Mode Multiusuari</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>
|
||||
<string name="settings_user_independent">Usuari Independent</string>
|
||||
@@ -174,7 +176,7 @@
|
||||
<string name="owner_manage_summary"> Només l’administrador pot supervisar l’acces root y rebre sol·licituds d’altres usuaris</string>
|
||||
<string name="user_indepenent_summary">Tots els usuaris tenen separades les seves pròpies regles de root </string>
|
||||
<string name="multiuser_hint_owner_request">S’ha enviat una sol·licitud a l’administrador del dispositiu. Per favor, canviï a la conta de l’administrador y concedeixi el permís</string>
|
||||
|
||||
|
||||
<string name="mount_namespace_mode">Muntar Namespace </string>
|
||||
<string name="settings_ns_global">Namespace Global</string>
|
||||
<string name="settings_ns_requester">Heretar Namespace</string>
|
||||
|
@@ -73,6 +73,9 @@
|
||||
<string name="process_error">Chyba při Zpracování</string>
|
||||
<string name="internal_storage">Zip je uchován v:\n[Interním Úložišti]%1$s</string>
|
||||
<string name="zip_process_title">Zpracování</string>
|
||||
<string name="download_file_error">Chyba při Stahování souboru</string>
|
||||
<string name="downloading_toast">Stahování %1$s</string>
|
||||
<string name="no_rw_storage">Tato funkce nebude fungovat bez povolení k zápisu na externí úložiště.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Obecné</string>
|
||||
@@ -90,8 +93,10 @@
|
||||
<string name="settings_su_adb">Pouze ADB</string>
|
||||
<string name="settings_su_disable">Zakázáno</string>
|
||||
<string name="settings_su_request_10">10 sekund</string>
|
||||
<string name="settings_su_request_15">15 sekund</string>
|
||||
<string name="settings_su_request_20">20 sekund</string>
|
||||
<string name="settings_su_request_30">30 sekund</string>
|
||||
<string name="settings_su_request_45">45 sekund</string>
|
||||
<string name="settings_su_request_60">60 sekund</string>
|
||||
<string name="superuser_access">Přístup Superuser</string>
|
||||
<string name="auto_response">Automatická Reakce</string>
|
||||
|
@@ -90,10 +90,10 @@
|
||||
<string name="manager_download_install">Herunterladen und installieren</string>
|
||||
<string name="dtbo_patched_title">DTBO wurde gepatched!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager hat dtbo.img gepatched, bitte neustarten</string>
|
||||
<string name="magisk_updates">Magisk Update</string>
|
||||
<string name="update_channel">Magisk Update</string>
|
||||
<string name="flashing">Flashing</string>
|
||||
<string name="hide_manager_toast">Verberge Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Das könnte einige Zeit dauern...</string>
|
||||
<string name="hide_manager_title">Verberge Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Das könnte einige Zeit dauern...</string>
|
||||
<string name="hide_manager_fail_toast">Verbergen von Magisk Manager fehlgeschlagen…</string>
|
||||
<string name="open_link_failed_toast">Es wurde keine Anwendung gefunden, um diesen Link zu öffnen...</string>
|
||||
<string name="download_zip_only">Nur Zip-Datei herunterladen</string>
|
||||
@@ -119,6 +119,9 @@
|
||||
<string name="env_fix_msg">Ihr Gerät benötigt zusätzliche Einrichtung, damit Magisk ordnungsgemäß funktioniert. Es wird eine Magisk-Installations-Zip wird heruntergeladen, fortfahren?</string>
|
||||
<string name="setup_title">Zusätzliche Einrichtung</string>
|
||||
<string name="setup_msg">Umgebungseinrichtung läuft…</string>
|
||||
<string name="download_file_error">Fehler beim Herunterladen der Datei</string>
|
||||
<string name="downloading_toast">Herunterladen von %1$s</string>
|
||||
<string name="no_rw_storage">Dieses Feature funktioniert nicht, ohne die Berechtigung den externen Speicher zu beschreiben.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Allgemein</string>
|
||||
@@ -143,7 +146,7 @@
|
||||
<string name="settings_boot_format_title">Ausgabeformat des gepatchten Boot-Images</string>
|
||||
<string name="settings_boot_format_summary">Wähle das Ausgabeformat des gepatchten Boot-Images.\nWähle .img, um mit \"fastboot/download mode\" zu flashen; wähle .img.tar zum Flashen mit ODIN.</string>
|
||||
<string name="settings_core_only_title">Nur Kernfunktionen</string>
|
||||
<string name="settings_core_only_summary">Aktiviert lediglich die Kernfunktionen, Module werden nicht geladen. MagiskSU, Magisk Hide und Systemless hosts bleiben weiterhin aktiv</string>
|
||||
<string name="settings_core_only_summary">Aktiviert lediglich die Kernfunktionen, Module werden nicht geladen. MagiskSU und Magisk Hide bleiben weiterhin aktiv</string>
|
||||
<string name="settings_magiskhide_summary">Versteckt Magisk vor diversen Entdeckungsmethoden</string>
|
||||
<string name="settings_hosts_title">Systemlose Hosts-Datei</string>
|
||||
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>
|
||||
@@ -153,8 +156,10 @@
|
||||
<string name="settings_su_adb">Nur ADB</string>
|
||||
<string name="settings_su_disable">Deaktiviert</string>
|
||||
<string name="settings_su_request_10">10 Sekunden</string>
|
||||
<string name="settings_su_request_15">15 Sekunden</string>
|
||||
<string name="settings_su_request_20">20 Sekunden</string>
|
||||
<string name="settings_su_request_30">30 Sekunden</string>
|
||||
<string name="settings_su_request_45">45 Sekunden</string>
|
||||
<string name="settings_su_request_60">60 Sekunden</string>
|
||||
<string name="superuser_access">Superuser-Zugriff</string>
|
||||
<string name="auto_response">Automatisch beantworten</string>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<resources>
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Modules</string>
|
||||
|
||||
|
||||
<string name="downloads">Λήψεις</string>
|
||||
<string name="superuser">Υπερχρήστης</string>
|
||||
<string name="log">Αρχείο Καταγραφής</string>
|
||||
@@ -51,7 +51,7 @@
|
||||
<string name="updated_on">Αναβαθμίστηκε στις: %1$s</string>
|
||||
<string name="sorting_order">Ταξινόμηση κατά</string>
|
||||
<string name="sort_by_name">Ταξινόμηση κατά όνομα</string>
|
||||
<string name="sort_by_update">Ταξινόμηση κατά τελευταία αναβάθμιση</string>
|
||||
<string name="sort_by_update">Ταξινόμηση κατά τελευταία αναβάθμιση</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">"Αποθήκευση καταγραφής "</string>
|
||||
@@ -90,10 +90,10 @@
|
||||
<string name="manager_download_install">Πιέστε για λήψη και εγκατάσταση</string>
|
||||
<string name="dtbo_patched_title">Έγινε patch στο DTBO!</string>
|
||||
<string name="dtbo_patched_reboot">Το Magisk Manager έκανε patch το dtbo.img, παρακαλώ κάντε επανεκκίνηση</string>
|
||||
<string name="magisk_updates">Ενημερώσεις Magisk</string>
|
||||
<string name="update_channel">Ενημερώσεις Magisk</string>
|
||||
<string name="flashing">Γίνεται flash</string>
|
||||
<string name="hide_manager_toast">Κρύβοντας το Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Αυτό μπορεί να πάρει λίγη ώρα…</string>
|
||||
<string name="hide_manager_title">Κρύβοντας το Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Αυτό μπορεί να πάρει λίγη ώρα…</string>
|
||||
<string name="hide_manager_fail_toast">Η απόκρυψη του Magisk Manager απέτυχε…</string>
|
||||
<string name="download_zip_only">Λήψη Zip Μόνο</string>
|
||||
<string name="patch_boot_file">Εφαρμογή Patch στο Αρχείο Εικόνας Boot</string>
|
||||
@@ -107,7 +107,10 @@
|
||||
<string name="proprietary_title">Λήψη Ιδιόκτητου Κώδικα</string>
|
||||
<string name="proprietary_notice">Το Magisk Manager είναι FOSS οπότε δεν περιέχει της Google τον ιδιόκτητο κώδικα του SafetyNet API.\n\nΕπιτρέπετε στο Magisk Manager να κατεβάσει μια επέκταση (περιέχει το GoogleApiClient) για ελέγχους του SafetyNet?</string>
|
||||
<string name="su_db_corrupt">Η βάση δεδομένων SU είναι κατεστραμμένη, θα αναδημιουργηθεί νέα</string>
|
||||
|
||||
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
|
||||
<string name="downloading_toast">Κατέβασμα %1$s</string>
|
||||
<string name="no_rw_storage">Η λειτουργία αυτή δεν θα δουλέψει χωρίς την άδεια εγγραφής στον εξωτερικό χώρο αποθηκεύσης.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Γενικά</string>
|
||||
<string name="settings_dark_theme_title">Σκούρο θέμα</string>
|
||||
@@ -127,7 +130,7 @@
|
||||
<string name="settings_boot_format_title">Μορφή Τροποποιημένης Εικόνας Boot</string>
|
||||
<string name="settings_boot_format_summary">Επιλέξτε τη μορφή της εξαγόμενης εικόνας boot μετά το patch.\nΕπιλέξτε .img για flash μέσω λειτουργίας fastboot/download· επιλέξτε .img.tar για flash μέσω ODIN.</string>
|
||||
<string name="settings_core_only_title">Magisk Λειτουργία Πυρήνα Μόνο</string>
|
||||
<string name="settings_core_only_summary">Ενεργοποίηση μόνο των λειτουργιών πυρήνα, καμία από τις ενότητες δεν θα ενεργοποιηθεί. Τα MagiskSU, MagiskHide, και systemless hosts θα παραμείνουν ενεργά</string>
|
||||
<string name="settings_core_only_summary">Ενεργοποίηση μόνο των λειτουργιών πυρήνα, καμία από τις ενότητες δεν θα ενεργοποιηθεί. Τα MagiskSU και MagiskHide θα παραμείνουν ενεργά</string>
|
||||
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
|
||||
@@ -137,8 +140,10 @@
|
||||
<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>
|
||||
@@ -165,7 +170,7 @@
|
||||
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
|
||||
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
|
||||
<string name="android_o_not_support">Δεν υποστηρίζεται Android 8.0+</string>
|
||||
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Αίτημα υπερχρήστη</string>
|
||||
<string name="deny_with_str">Άρνηση%1$s</string>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<string name="uninstall_magisk_msg">Todos los módulos serán desactivados / eliminados. El acceso Root se eliminará y, posiblemente, cifrará los datos si los datos no están cifrados actualmente.</string>
|
||||
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
|
||||
<string name="update">Actualización %1$s</string>
|
||||
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(No hay información)</string>
|
||||
<string name="no_modules_found">No se encontraron módulos</string>
|
||||
@@ -70,6 +70,14 @@
|
||||
<string name="app_translators">Traductores</string>
|
||||
<string name="support_thread">Hilo de soporte</string>
|
||||
<string name="follow_twitter">Sigueme en Twitter</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Actualización de Magisk</string>
|
||||
<string name="progress_channel">Notificaciones de progreso</string>
|
||||
<string name="download_complete">Descarga Completa</string>
|
||||
<string name="download_file_error">Error descargando archivo</string>
|
||||
<string name="magisk_update_title">¡Nueva actualización de Magisk disponible!</string>
|
||||
<string name="manager_update_title">Nueva actualización de Magisk Manager disponible!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Cerrar</string>
|
||||
@@ -78,7 +86,6 @@
|
||||
<string name="download">Descargar</string>
|
||||
<string name="reboot">Reiniciar</string>
|
||||
<string name="zip_process_msg">Procesando archivo zip…</string>
|
||||
<string name="magisk_update_title">¡Nueva actualización de Magisk disponible!</string>
|
||||
<string name="settings_reboot_toast">Reinicia para aplicar los ajustes</string>
|
||||
<string name="release_notes">Notas de lanzamiento</string>
|
||||
<string name="repo_cache_cleared">Caché del repositorio limpiada</string>
|
||||
@@ -87,14 +94,12 @@
|
||||
<string name="zip_download_title">Descargando</string>
|
||||
<string name="zip_download_msg">Descargando el archivo zip (%1$d%%)…</string>
|
||||
<string name="zip_process_title">Procesando</string>
|
||||
<string name="manager_update_title">Nueva actualización de Magisk Manager disponible!</string>
|
||||
<string name="manager_download_install">Pulse para descargar e instalar</string>
|
||||
<string name="dtbo_patched_title">DTBO fue parchado!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ha parcheado dtbo.img, por favor reinicia</string>
|
||||
<string name="magisk_updates">Actualización de Magisk</string>
|
||||
<string name="flashing">Flasheando</string>
|
||||
<string name="hide_manager_toast">Ocultando Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Esto podría tomar un tiempo…</string>
|
||||
<string name="hide_manager_title">Ocultando Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Esto podría tomar un tiempo…</string>
|
||||
<string name="hide_manager_fail_toast">La Ocultación de Magisk Manager ha fallado…</string>
|
||||
<string name="open_link_failed_toast">No se encontró ninguna aplicación para abrir el enlace…</string>
|
||||
<string name="download_zip_only">Descargar sólo el archivo ZIP</string>
|
||||
@@ -119,6 +124,10 @@
|
||||
<string name="setup_title">Configuración Adicional</string>
|
||||
<string name="setup_msg">Ejecutando Configuración de Entorno</string>
|
||||
|
||||
<string name="downloading_toast">Descargando %1$s</string>
|
||||
<string name="no_rw_storage">Esta opción no funcionará sin permiso de escritura en la memoria externa.</string>
|
||||
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
<string name="settings_dark_theme_title">Tema oscuro</string>
|
||||
@@ -141,19 +150,22 @@
|
||||
<string name="settings_update_custom_msg">Insertar una URL personalizada</string>
|
||||
<string name="settings_boot_format_title">Parchear imagen boot por tipo de formato</string>
|
||||
<string name="settings_boot_format_summary">Seleccionar el formato de salida para parchear la imagen boot.\nEscoja .img para flashear mediante fastboot/download mode; escoja .img.tar para flashear con ODIN.</string>
|
||||
|
||||
<string name="settings_core_only_summary">Habilitar sólo funciones principales, no se cargarán todos los módulos. MagiskSU, MagiskHide, y Systemless Hosts seguirán habilitados</string>
|
||||
|
||||
<string name="settings_core_only_summary">Habilitar sólo funciones principales, no se cargarán todos los módulos. MagiskSU y MagiskHide seguirán habilitados</string>
|
||||
<string name="settings_magiskhide_summary">Ocultar Magisk de varias detecciones</string>
|
||||
<string name="settings_hosts_title">Systemless Hosts</string>
|
||||
<string name="settings_hosts_summary">Soporte para aplicaciones Adblock fuera de la partición system</string>
|
||||
<string name="settings_hosts_toast">Módulo systemless hosts agregado</string>
|
||||
|
||||
<string name="settings_su_app_adb">Aplicaciones y ADB</string>
|
||||
<string name="settings_su_app">Sólo aplicaciones</string>
|
||||
<string name="settings_su_adb">Sólo ADB</string>
|
||||
<string name="settings_su_disable">Deshabilitado</string>
|
||||
<string name="settings_su_request_10">10 segundos</string>
|
||||
<string name="settings_su_request_15">15 segundos</string>
|
||||
<string name="settings_su_request_20">20 segundos</string>
|
||||
<string name="settings_su_request_30">30 segundos</string>
|
||||
<string name="settings_su_request_45">45 segundos</string>
|
||||
<string name="settings_su_request_60">60 segundos</string>
|
||||
<string name="superuser_access">Acceso de superusuario</string>
|
||||
<string name="auto_response">Respuesta automática</string>
|
||||
@@ -165,8 +177,8 @@
|
||||
<string name="settings_su_fingerprint_title">Autenticación por Huella Dactilar</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilizar el sensor de Huella Dactilar para permitir las solicitudes de superusuario</string>
|
||||
<string name="auth_fingerprint">Autenticar Huella Dactilar</string>
|
||||
|
||||
<string name="multiuser_mode">Modo MultiUsuario</string>
|
||||
|
||||
<string name="multiuser_mode">Modo MultiUsuario</string>
|
||||
<string name="settings_owner_only">Sólo Administrador del Dispositivo</string>
|
||||
<string name="settings_owner_manage">Administrador del Dispositivo</string>
|
||||
<string name="settings_user_independent">Usuario Independiente</string>
|
||||
@@ -174,7 +186,7 @@
|
||||
<string name="owner_manage_summary">Sólo el administrador puede supervisar el acceso root y recibir solicitudes de otros usuarios</string>
|
||||
<string name="user_indepenent_summary">Cada usuario tiene separadas sus propias reglas de root </string>
|
||||
<string name="multiuser_hint_owner_request">Se ha enviado una solicitud al administrador del dispositivo. Por favor, cambie a la cuenta del administrador y conceda el permiso</string>
|
||||
|
||||
|
||||
<string name="mount_namespace_mode">Montar Namespace </string>
|
||||
<string name="settings_ns_global">Global Namespace</string>
|
||||
<string name="settings_ns_requester">Heredar Namespace</string>
|
||||
|
@@ -89,10 +89,10 @@
|
||||
<string name="manager_download_install">Vajuta allalaadimiseks ja installimiseks</string>
|
||||
<string name="dtbo_patched_title">DTBO sai paigatud!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager on paiganud dtbo.img, palun taaskäivita</string>
|
||||
<string name="magisk_updates">Magisk\'i uuendused</string>
|
||||
<string name="update_channel">Magisk\'i uuendused</string>
|
||||
<string name="flashing">Välgutamine</string>
|
||||
<string name="hide_manager_toast">Peidan Magisk Manager\'i…</string>
|
||||
<string name="hide_manager_toast2">See võib aega võtta…</string>
|
||||
<string name="hide_manager_title">Peidan Magisk Manager\'i…</string>
|
||||
<string name="hide_manager_msg">See võib aega võtta…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager\'i peitmine ebaõnnestus…</string>
|
||||
<string name="download_zip_only">Laadi ainult ZIP alla</string>
|
||||
<string name="patch_boot_file">Paika käivituspildi fail</string>
|
||||
@@ -115,6 +115,9 @@
|
||||
<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_title">Lisaseadistus</string>
|
||||
<string name="setup_msg">Käivitan keskkonnaseadistust…</string>
|
||||
<string name="download_file_error">Faili allalaadimisel esines viga</string>
|
||||
<string name="downloading_toast">Laadin %1$s alla</string>
|
||||
<string name="no_rw_storage">See funktsioon ei tööta ilma välismälule kirjutamise õiguseta.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Üldine</string>
|
||||
@@ -139,7 +142,7 @@
|
||||
<string name="settings_boot_format_title">Paigatud käivitusväljundi vorming</string>
|
||||
<string name="settings_boot_format_summary">Vali väljutatava paigatud käivituspildi vorming.\nVali .img, mida välgutada fastboot/allalaadimisrežiimi kaudu; vali .img.tar, mida välgutada ODIN\'i kaudu.</string>
|
||||
<string name="settings_core_only_title">Magisk\'i ainult tuuma režiim</string>
|
||||
<string name="settings_core_only_summary">Luba ainult põhifunktsioonid. MagiskSU, MagiskHide ja süsteemivaba hosts siiski lubatakse, ent mooduleid ei laadita.</string>
|
||||
<string name="settings_core_only_summary">Luba ainult põhifunktsioonid. MagiskSU ja MagiskHide siiski lubatakse, ent mooduleid ei laadita.</string>
|
||||
<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>
|
||||
@@ -149,8 +152,10 @@
|
||||
<string name="settings_su_adb">Ainult ADB</string>
|
||||
<string name="settings_su_disable">Keelatud</string>
|
||||
<string name="settings_su_request_10">10 sekundit</string>
|
||||
<string name="settings_su_request_15">15 sekundit</string>
|
||||
<string name="settings_su_request_20">20 sekundit</string>
|
||||
<string name="settings_su_request_30">30 sekundit</string>
|
||||
<string name="settings_su_request_45">45 sekundit</string>
|
||||
<string name="settings_su_request_60">60 sekundit</string>
|
||||
<string name="superuser_access">Superkasutaja ligipääs</string>
|
||||
<string name="auto_response">Automaatne vastus</string>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Modules</string>
|
||||
<string name="downloads">Téléchargements</string>
|
||||
@@ -9,15 +9,15 @@
|
||||
<string name="install">Installer</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk n\'est pas installé</string>
|
||||
<string name="magisk_version_error">Magisk n\'est pas installé.</string>
|
||||
<string name="checking_for_updates">Vérification des mises à jours…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$s disponible !</string>
|
||||
<string name="invalid_update_channel">Canal de mise à jour invalide</string>
|
||||
<string name="safetyNet_check_text">Appuyer pour lancer le contrôle SafetyNet</string>
|
||||
<string name="safetyNet_check_text">Appuyer pour lancer le contrôle SafetyNet.</string>
|
||||
<string name="checking_safetyNet_status">Vérification de l\'état SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Contrôle SafetyNet passé avec succès</string>
|
||||
<string name="safetyNet_api_error">Erreur d\'API SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">La réponse est invalide</string>
|
||||
<string name="safetyNet_res_invalid">La réponse est invalide.</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="advanced_settings_title">Paramètres avancés</string>
|
||||
@@ -27,17 +27,17 @@
|
||||
<string name="install_magisk_title">Dernière Version : %1$s</string>
|
||||
<string name="uninstall">Désinstaller</string>
|
||||
<string name="uninstall_magisk_title">Désinstaller Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Tous les modules seront désactivés/effacés. Le root sera enlevé et vos données seront potentiellement chiffrées si elles ne le sont pas actuellement</string>
|
||||
<string name="uninstall_magisk_msg">Tous les modules seront désactivés/effacés. Le root sera enlevé et vos données seront potentiellement chiffrées si elles ne le sont pas actuellement.</string>
|
||||
<string name="update">Mise à jour %1$s</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Aucune information transmise)</string>
|
||||
<string name="no_modules_found">Aucun module trouvé</string>
|
||||
<string name="update_file_created">Le module va être mis à jour au prochain redémarrage</string>
|
||||
<string name="remove_file_created">Le module va être supprimé au prochain redémarrage</string>
|
||||
<string name="remove_file_deleted">Le module ne sera pas supprimé au prochain redémarrage</string>
|
||||
<string name="disable_file_created">Le module va être désactivé au prochain redémarrage</string>
|
||||
<string name="disable_file_removed">Le module va être activé au prochain redémarrage</string>
|
||||
<string name="no_modules_found">Aucun module trouvé.</string>
|
||||
<string name="update_file_created">Le module va être mis à jour au prochain redémarrage.</string>
|
||||
<string name="remove_file_created">Le module va être supprimé au prochain redémarrage.</string>
|
||||
<string name="remove_file_deleted">Le module ne sera pas supprimé au prochain redémarrage.</string>
|
||||
<string name="disable_file_created">Le module va être désactivé au prochain redémarrage.</string>
|
||||
<string name="disable_file_removed">Le module va être activé au prochain redémarrage.</string>
|
||||
<string name="author">Créé par %1$s</string>
|
||||
<string name="reboot_recovery">Redémarrer en récupération</string>
|
||||
<string name="reboot_bootloader">Redémarrer en chargement démarrage</string>
|
||||
@@ -56,8 +56,8 @@
|
||||
<string name="menuSaveLog">Enregistrer journal</string>
|
||||
<string name="menuReload">Actualiser</string>
|
||||
<string name="menuClearLog">Effacer le journal maintenant</string>
|
||||
<string name="logs_cleared">Journal effacé avec succès</string>
|
||||
<string name="log_is_empty">Journal vide</string>
|
||||
<string name="logs_cleared">Journal effacé avec succès.</string>
|
||||
<string name="log_is_empty">Journal vide.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">À propos</string>
|
||||
@@ -69,6 +69,14 @@
|
||||
<string name="app_translators">Traducteurs de l\'application</string>
|
||||
<string name="support_thread">Fil d\'assistance</string>
|
||||
<string name="follow_twitter">Me suivre sur Twitter</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Mises à jours Magisk</string>
|
||||
<string name="progress_channel">Progression des notifications</string>
|
||||
<string name="download_complete">Téléchargement terminé</string>
|
||||
<string name="download_file_error">Érreure de téléchargement du fichier</string>
|
||||
<string name="magisk_update_title">Nouvelle MàJ Magisk disponible!</string>
|
||||
<string name="manager_update_title">Nouvelle MàJ du Gestionnaire Magisk Disponible!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Fermer</string>
|
||||
@@ -76,8 +84,7 @@
|
||||
<string name="repo_install_msg">Voulez-vous installer %1$s maintenant ?</string>
|
||||
<string name="download">Télécharger</string>
|
||||
<string name="reboot">Redémarrer</string>
|
||||
<string name="magisk_update_title">Nouvelle mis à jour Magisk disponible!</string>
|
||||
<string name="settings_reboot_toast">Redémarrer afin d\'appliquer les réglages</string>
|
||||
<string name="settings_reboot_toast">Redémarrer afin d\'appliquer les réglages.</string>
|
||||
<string name="release_notes">Notes de version</string>
|
||||
<string name="repo_cache_cleared">Cache du dépôt éffacé</string>
|
||||
<string name="process_error">Erreur du processus</string>
|
||||
@@ -86,16 +93,14 @@
|
||||
<string name="zip_download_msg">Téléchargement du fichier zip (%1$d%%) …</string>
|
||||
<string name="zip_process_title">Traitement en cours</string>
|
||||
<string name="zip_process_msg">Traitement du fichier zip…</string>
|
||||
<string name="manager_update_title">Nouvelle mise à jour du Gestionnaire Magisk disponible!</string>
|
||||
<string name="manager_download_install">Appuyer pour télécharger et installer</string>
|
||||
<string name="manager_download_install">Appuyer pour télécharger et installer.</string>
|
||||
<string name="dtbo_patched_title">DTBO a été patché!</string>
|
||||
<string name="dtbo_patched_reboot">Le Gestionnaire Magisk a vient de patcher dtbo.img, merci de redémarrer</string>
|
||||
<string name="magisk_updates">Mises à jours Magisk</string>
|
||||
<string name="dtbo_patched_reboot">Le Gestionnaire Magisk a vient de patcher dtbo.img, merci de redémarrer.</string>
|
||||
<string name="flashing">Installation</string>
|
||||
<string name="hide_manager_toast">Masquer le Gestionnaire Magisk…</string>
|
||||
<string name="hide_manager_toast2">Cela pourrait prendre un certain temps …</string>
|
||||
<string name="hide_manager_fail_toast">Masquage du Gestionnaire Magisk échoué…</string>
|
||||
<string name="open_link_failed_toast">Aucune application trouvée pour ouvrir le lien…</string>
|
||||
<string name="hide_manager_title">Masquer le Gestionnaire Magisk…</string>
|
||||
<string name="hide_manager_msg">Cela pourrait prendre un certain temps.</string>
|
||||
<string name="hide_manager_fail_toast">Masquage du Gestionnaire Magisk échoué.</string>
|
||||
<string name="open_link_failed_toast">Aucune application trouvée pour ouvrir le lien.</string>
|
||||
<string name="download_zip_only">Uniquement télécharger le zip</string>
|
||||
<string name="patch_boot_file">Patch Fichier Image Démarrage</string>
|
||||
<string name="direct_install">Installation directe (Recommendée)</string>
|
||||
@@ -104,37 +109,39 @@
|
||||
<string name="install_inactive_slot_msg">Votre téléphone sera FORÇÉ de démarrer dans le slot actuellement inactif après un redémarrage!\nUtiliser cette option uniquement après que la mise à jour OTA ai été éffectuée.\nContinuer?</string>
|
||||
<string name="select_method">Sélectionner le méthode</string>
|
||||
<string name="no_boot_file_patch_support">La version cible de Magisk ne prend pas en charge la correction de fichier image de démarrage</string>
|
||||
<string name="boot_file_patch_msg">Sélectionnez l\'image par défaut de démarrage stockée au format .img ou .img.tar</string>
|
||||
<string name="boot_file_patch_msg">Sélectionnez l\'image par défaut de démarrage stockée au format .img ou .img.tar.</string>
|
||||
<string name="complete_uninstall">Désinstallation terminée</string>
|
||||
<string name="restore_img">Restauration des images</string>
|
||||
<string name="restore_img_msg">Restauration…</string>
|
||||
<string name="restore_done">Restauration terminée!</string>
|
||||
<string name="restore_fail">Le sauvegarde par défaut n\'existe pas!</string>
|
||||
<string name="proprietary_title">Télécharger Code Propriétaire</string>
|
||||
<string name="proprietary_notice">Magisk Manager est Libre, il ne contient pas le code API SafetyNet propriétaire de Google. \ N \ nAutorisez vous le Gestionnaire Magisk à télécharger une extension (contenant GoogleApiClient) pour les contrôles SafetyNet? </string>
|
||||
<string name = "su_db_corrupt"> La base de données SU est corrompue, une nouvelle base de donnée va être re-créée</string>
|
||||
<string name="proprietary_notice">Magisk Manager est Libre et ne contient pas le code API SafetyNet propriétaire de Google. \n\nAutoriseriez vous le Gestionnaire Magisk à télécharger une extension (contenant GoogleApiClient) pour les contrôles SafetyNet? </string>
|
||||
<string name="su_db_corrupt"> La base de données SU est corrompue. Une nouvelle base de donnée va être à nouveau créée.</string>
|
||||
<string name="setup_done">Installation terminée</string>
|
||||
<string name="setup_fail">Échec de l\'installation</string>
|
||||
<string name="env_fix_title">Installation additionnelle requise</string>
|
||||
<string name="env_fix_msg">Votre appareil a besoin d\'une configuration supplémentaire pour que Magisk fonctionne correctement. Il téléchargera le zip d\'installation de Magisk, voulez-vous procéder maintenant ?</string>
|
||||
<string name="setup_title">Installation Additionnel</string>
|
||||
<string name="setup_msg">Démarrer l\'installation de l\'environnement…</string>
|
||||
|
||||
<string name="downloading_toast">Téléchargement à %1$s</string>
|
||||
<string name="no_rw_storage">Cette fonctionnalité ne marchera pas sans la permission d\'écriture sur le stockage externe.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Général</string>
|
||||
<string name="settings_dark_theme_title">Thème sombre</string>
|
||||
<string name="settings_dark_theme_summary">Activer le thème sombre</string>
|
||||
<string name="settings_dark_theme_summary">Activer le thème sombre.</string>
|
||||
<string name="settings_clear_cache_title">Éffacer le cache du dépot</string>
|
||||
<string name="settings_clear_cache_summary">Effacer les informations de cache pour les dépots en ligne, Forcer l\'appli à se rafraichir en ligne</string>
|
||||
<string name="settings_clear_cache_summary">Éffacer les informations de cache pour les dépots en ligne. Celà forcera l\'appli à se rafraichir en ligne.</string>
|
||||
<string name="settings_hide_manager_title">Masquer le Gestionnaire Magisk</string>
|
||||
<string name="settings_hide_manager_summary">Reconstruire le Gestionnaire Magisk avec un nom de paquet aléatoire</string>
|
||||
<string name="settings_hide_manager_summary">Reconstruire le Gestionnaire Magisk avec un nom de paquet aléatoire.</string>
|
||||
<string name="settings_restore_manager_title">Restaurer le Gestionnaire Magisk</string>
|
||||
<string name="settings_restore_manager_summary">Restaurer le Gestionnaire Magisk avec le paquet originel</string>
|
||||
<string name="language">Language</string>
|
||||
<string name="language">Langage</string>
|
||||
<string name="system_default">(Système par Défaut)</string>
|
||||
<string name="settings_update">Mis à jour des réglages</string>
|
||||
<string name="settings_check_update_title">Vérification des mises à jours</string>
|
||||
<string name="settings_check_update_summary">Vérifier l\'éxistance de mise à jour en tâche de fond de façon périodique</string>
|
||||
<string name="settings_check_update_summary">Vérifier de façon périodique l\'éxistance de mise à jour en tâche de fond de façon périodique.</string>
|
||||
<string name="settings_update_channel_title">Canal de mise à jour</string>
|
||||
<string name="settings_update_stable">Stable</string>
|
||||
<string name="settings_update_beta">Béta</string>
|
||||
@@ -143,18 +150,21 @@
|
||||
<string name="settings_boot_format_title">Patcher Format Fichier Démarrage</string>
|
||||
<string name="settings_boot_format_summary">Sélectioner le format de sortie de l\'image de boot.\nChoisir .img pour flasher à traver le mode démarrage rapide/téléchargement; choisir .img.tar pour flasher via ODIN.</string>
|
||||
<string name="settings_core_only_title">Mode Magisk Core uniquement</string>
|
||||
<string name="settings_core_only_summary">Activer uniquement les fonctionnalités de base, tous les modules ne seront pas chargés. MagiskSU, MagiskHide et les hosts systemless restent activés</string>
|
||||
<string name="settings_magiskhide_summary">Masquer Magisk de diverses détections</string>
|
||||
<string name="settings_core_only_summary">Activer uniquement les fonctionnalités de base, tous les modules ne seront pas chargés. MagiskSU et MagiskHide restent activés</string>
|
||||
<string name="settings_magiskhide_summary">Masquer Magisk de diverses formes de détections.</string>
|
||||
<string name="settings_hosts_title">Hôtes systemless</string>
|
||||
<string name="settings_hosts_summary">Support d\'hôtes systemless pour les applications type Adblock</string>
|
||||
<string name="settings_hosts_summary">Support d\'hôtes systemless pour les applications type Adblock.</string>
|
||||
<string name="settings_hosts_toast">Ajout d\'un module d\'hôtes sans système</string>
|
||||
|
||||
<string name="settings_su_app_adb">Applis et ADB</string>
|
||||
<string name="settings_su_app">Applications uniquement</string>
|
||||
<string name="settings_su_adb">ADB uniquement</string>
|
||||
<string name="settings_su_disable">Désactivé</string>
|
||||
<string name="settings_su_request_10">10 secondes</string>
|
||||
<string name="settings_su_request_15">15 secondes</string>
|
||||
<string name="settings_su_request_20">20 secondes</string>
|
||||
<string name="settings_su_request_30">30 secondes</string>
|
||||
<string name="settings_su_request_45">45 secondes</string>
|
||||
<string name="settings_su_request_60">60 secondes</string>
|
||||
<string name="superuser_access">Accès Superuser</string>
|
||||
<string name="auto_response">Réponse automatique</string>
|
||||
@@ -170,21 +180,21 @@
|
||||
<string name="multiuser_mode">Mode Multi-utilisateurs</string>
|
||||
<string name="settings_owner_only">Propriétaire de l\'appareil uniquement</string>
|
||||
<string name="settings_owner_manage">Propriétaire de l\'appareil géré</string>
|
||||
<string name="settings_user_independent">Utilisateur indépendant</string>
|
||||
<string name="owner_only_summary">Seul le propriétaire a un accès root</string>
|
||||
<string name="owner_manage_summary">Seul le propriétaire peut gérer l\'accès root et recevoir des demandes de requêtes</string>
|
||||
<string name="user_indepenent_summary">Chaque utilisateur a ses propres règles de root séparées</string>
|
||||
<string name="multiuser_hint_owner_request">Une requête a été envoyée au propriétaire du périphérique. Merci de basculer en propriétaire et d\'accepter les permissions requises</string>
|
||||
<string name="settings_user_independent">Utilisateur-Indépendant</string>
|
||||
<string name="owner_only_summary">Seul le propriétaire a un accès root.</string>
|
||||
<string name="owner_manage_summary">Seul le propriétaire peut gérer l\'accès root et recevoir des demandes de requêtes.</string>
|
||||
<string name="user_indepenent_summary">Chaque utilisateur a ses propres règles de root séparées.</string>
|
||||
<string name="multiuser_hint_owner_request">Une requête a été envoyée au propriétaire du périphérique. Merci de basculer en propriétaire et d\'accepter les permissions requises.</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mode Montage Espace de Noms</string>
|
||||
<string name="settings_ns_global">Espace de Nom Global</string>
|
||||
<string name="settings_ns_requester">Hériter de l\'espace de noms</string>
|
||||
<string name="settings_ns_isolate">Espace de noms isolé</string>
|
||||
<string name="global_summary">Toutes les sessions racines utilisent l\'espace de noms de montage global</string>
|
||||
<string name="requester_summary">Les sessions racines hériteront de l\'espace de noms de son demandeur</string>
|
||||
<string name="isolate_summary">Chaque session racine aura son propre espace de noms isolé</string>
|
||||
<string name="android_o_not_support">Android 8.0+ non supporté</string>
|
||||
<string name="disable_fingerprint">Aucune empreinte digitale n\'a été définie ou aucun support de périphérique</string>
|
||||
<string name="global_summary">Toutes les sessions racines utilisent l\'espace de noms de montage global.</string>
|
||||
<string name="requester_summary">Les sessions racine hériteront de l\'espace nom de leur demandeur.</string>
|
||||
<string name="isolate_summary">Chaque session racine aura son propre espace de noms isolé.</string>
|
||||
<string name="android_o_not_support">Android 8.0+ non supporté.</string>
|
||||
<string name="disable_fingerprint">Aucune empreinte digitale n\'a été définie ou aucun support de périphérique.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Requête Superuser</string>
|
||||
@@ -195,10 +205,10 @@
|
||||
<string name="su_warning">Accepter un accès complet à votre appareil.\nRefuser si vous n\'êtes pas sûr !</string>
|
||||
<string name="forever">Toujours</string>
|
||||
<string name="once">Une fois</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="tenmin">10 mins</string>
|
||||
<string name="twentymin">20 mins</string>
|
||||
<string name="thirtymin">30 mins</string>
|
||||
<string name="sixtymin">60 mins</string>
|
||||
<string name="su_allow_toast">%1$s a obtenu les droits Superuser</string>
|
||||
<string name="su_deny_toast">%1$s n\'a pas obtenu les droits Superuser</string>
|
||||
<string name="no_apps_found">Aucune application trouvée</string>
|
||||
|
@@ -81,9 +81,9 @@
|
||||
<string name="zip_process_msg">Obrada zip datoteke …</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="magisk_updates">Magisk ažuriranja</string>
|
||||
<string name="update_channel">Magisk ažuriranja</string>
|
||||
<string name="flashing">Apliciranje</string>
|
||||
<string name="hide_manager_toast">Skrivanje Magisk Manager aplikacije…</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="download_zip_only">Preuzmi samo zip</string>
|
||||
<string name="patch_boot_file">Zakrpa datoteke za podizanje sustava</string>
|
||||
@@ -96,6 +96,9 @@
|
||||
<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>
|
||||
<string name="downloading_toast">Preuzimanje %1$s</string>
|
||||
<string name="no_rw_storage">Ova značajka neće raditi bez dopuštenja za korištenje vanjske pohrane.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Općenito</string>
|
||||
@@ -115,7 +118,7 @@
|
||||
<string name="settings_boot_format_summary">Odaberite izlazni format datoteke za podizanje sustava nakon zakrpe.\nOdaberite .img da biste aplicirali putem brzog pokretanja(fastboota)/preuzimanja(downloada); odaberite .img.tar da biste aplicirali putem ODIN-a.</string>
|
||||
|
||||
<string name="settings_core_only_title">Samo Magisk Core način rada</string>
|
||||
<string name="settings_core_only_summary">Omogućite samo osnovne značajke, svi se moduli neće učitati. MagiskSU, MagiskHide i systemless hostovi će i dalje biti omogućeni</string>
|
||||
<string name="settings_core_only_summary">Omogućite samo osnovne značajke, svi se moduli neće učitati. MagiskSU i MagiskHide će i dalje biti omogućeni</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>
|
||||
@@ -125,8 +128,10 @@
|
||||
<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>
|
||||
|
@@ -8,15 +8,15 @@
|
||||
<string name="install">Pasang</string>
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk tidak terpasang</string>
|
||||
<string name="magisk_version_error">Magisk tidak terpasang.</string>
|
||||
<string name="checking_for_updates">Memeriksa pembaruan…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$s tersedia!</string>
|
||||
<string name="invalid_update_channel">Kanal Pembaruan tidak valid!</string>
|
||||
<string name="safetyNet_check_text">Ketuk untuk memulai pemeriksaan SafetyNet</string>
|
||||
<string name="safetyNet_check_text">Ketuk untuk memulai pemeriksaan SafetyNet.</string>
|
||||
<string name="checking_safetyNet_status">Memeriksa status SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Pemeriksaan SafetyNet Berhasil</string>
|
||||
<string name="safetyNet_api_error">Kesalahan pada API SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">Tanggapan tidak valid</string>
|
||||
<string name="safetyNet_res_invalid">Tanggapan tidak valid.</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="advanced_settings_title">Pengaturan Lanjutan</string>
|
||||
@@ -26,17 +26,17 @@
|
||||
<string name="install_magisk_title">Versi Terbaru: %1$s</string>
|
||||
<string name="uninstall">Copot</string>
|
||||
<string name="uninstall_magisk_title">Copot Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Semua modul akan dinonaktifkan/dihapus. Root akan dihapus, dan berpotensi mengenkripsi data Anda jika tidak terenkripsi saat ini.</string>
|
||||
<string name="uninstall_magisk_msg">Semua modul akan dinonaktifkan/dihapus. Root akan dihapus, dan berpotensi mengenkripsi data Anda jika belum.</string>
|
||||
<string name="update">Perbarui %1$s</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Tidak ada info tersedia)</string>
|
||||
<string name="no_modules_found">Tidak ada modul ditemukan</string>
|
||||
<string name="update_file_created">Modul akan diperbarui pada reboot berikutnya</string>
|
||||
<string name="remove_file_created">Modul akan dihapus pada reboot berikutnya</string>
|
||||
<string name="remove_file_deleted">Modul tidak akan dihapus pada reboot berikutnya</string>
|
||||
<string name="disable_file_created">Modul akan dinonaktifkan pada reboot berikutnya</string>
|
||||
<string name="disable_file_removed">Modul akan diaktifkan pada reboot berikutnya</string>
|
||||
<string name="no_modules_found">Tidak ada modul ditemukan.</string>
|
||||
<string name="update_file_created">Modul akan diperbarui pada reboot berikutnya.</string>
|
||||
<string name="remove_file_created">Modul akan dihapus pada reboot berikutnya.</string>
|
||||
<string name="remove_file_deleted">Modul tidak akan dihapus pada reboot berikutnya.</string>
|
||||
<string name="disable_file_created">Modul akan dinonaktifkan pada reboot berikutnya.</string>
|
||||
<string name="disable_file_removed">Modul akan diaktifkan pada reboot berikutnya.</string>
|
||||
<string name="author">Dibuat oleh %1$s</string>
|
||||
<string name="reboot_recovery">Reboot ke Recovery</string>
|
||||
<string name="reboot_bootloader">Reboot ke Bootloader</string>
|
||||
@@ -55,8 +55,8 @@
|
||||
<string name="menuSaveLog">Simpan log</string>
|
||||
<string name="menuReload">Muat ulang</string>
|
||||
<string name="menuClearLog">Bersihkan log sekarang</string>
|
||||
<string name="logs_cleared">Log berhasil dibersihkan</string>
|
||||
<string name="log_is_empty">Log kosong</string>
|
||||
<string name="logs_cleared">Log berhasil dibersihkan.</string>
|
||||
<string name="log_is_empty">Log kosong.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Tentang</string>
|
||||
@@ -69,14 +69,21 @@
|
||||
<string name="support_thread">Thread dukungan</string>
|
||||
<string name="follow_twitter">Ikuti saya di Twitter</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Pembaruan Magisk</string>
|
||||
<string name="progress_channel">Notifikasi Kemajuan</string>
|
||||
<string name="download_complete">Unduhan selesai</string>
|
||||
<string name="download_file_error">Kesalahan mengunduh file</string>
|
||||
<string name="magisk_update_title">Pembaruan Magisk Baru Tersedia!</string>
|
||||
<string name="manager_update_title">Pembaruan Magisk Manager Baru Tersedia!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Tutup</string>
|
||||
<string name="repo_install_title">Pasang %1$s</string>
|
||||
<string name="repo_install_msg">Apakah Anda ingin memasang %1$s sekarang?</string>
|
||||
<string name="download">Unduh</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
<string name="magisk_update_title">Pembaruan Magisk Tersedia!</string>
|
||||
<string name="settings_reboot_toast">Reboot untuk menerapkan pengaturan</string>
|
||||
<string name="settings_reboot_toast">Reboot untuk menerapkan pengaturan.</string>
|
||||
<string name="release_notes">Catatan rilis</string>
|
||||
<string name="repo_cache_cleared">Cache repo dibersihkan</string>
|
||||
<string name="process_error">Kesalahan proses</string>
|
||||
@@ -84,17 +91,15 @@
|
||||
<string name="zip_download_title">Mengunduh</string>
|
||||
<string name="zip_download_msg">Mengunduh file zip (%1$d%%) …</string>
|
||||
<string name="zip_process_title">Memproses</string>
|
||||
<string name="zip_process_msg">Memproses file zip …</string>
|
||||
<string name="manager_update_title">Pembaruan Magisk Manager Tersedia!</string>
|
||||
<string name="manager_download_install">Tekan untuk unduh dan pasang</string>
|
||||
<string name="zip_process_msg">Memproses file zip…</string>
|
||||
<string name="manager_download_install">Tekan untuk unduh dan pasang.</string>
|
||||
<string name="dtbo_patched_title">DTBO telah ditambal!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager telah menambal dtbo.img, silahkan reboot</string>
|
||||
<string name="magisk_updates">Pembaruan Magisk</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager telah menambal dtbo.img. Silahkan reboot.</string>
|
||||
<string name="flashing">Flashing</string>
|
||||
<string name="hide_manager_toast">Menyembunyikan Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Ini mungkin membutuhkan beberapa saat…</string>
|
||||
<string name="hide_manager_fail_toast">Kesalahan menyembunyikan Magisk Manager…</string>
|
||||
<string name="open_link_failed_toast">Tidak ada aplikasi ditemukan untuk membuka tautan…</string>
|
||||
<string name="hide_manager_title">Menyembunyikan Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Ini mungkin membutuhkan waktu beberapa saat.</string>
|
||||
<string name="hide_manager_fail_toast">Kesalahan menyembunyikan Magisk Manager.</string>
|
||||
<string name="open_link_failed_toast">Tidak ada aplikasi ditemukan untuk membuka tautan.</string>
|
||||
<string name="download_zip_only">Unduh Zip Saja</string>
|
||||
<string name="patch_boot_file">Tambal File Boot Image</string>
|
||||
<string name="direct_install">Pasang Langsung (Direkomendasikan)</string>
|
||||
@@ -103,55 +108,62 @@
|
||||
<string name="install_inactive_slot_msg">Perangkat Anda akan DIPAKSA untuk boot ke slot nonaktif saat ini setelah sebuah reboot!\nHanya gunakan opsi ini setelah OTA selesai.\nLanjutkan?</string>
|
||||
<string name="select_method">Pilih Metode</string>
|
||||
<string name="no_boot_file_patch_support">Versi target Magisk tidak mendukung penambalan file boot image</string>
|
||||
<string name="boot_file_patch_msg">Pilih stock boot image dump dalam format .img atau .img.tar</string>
|
||||
<string name="restore_img">Pulihkan Image</string>
|
||||
<string name="boot_file_patch_msg">Pilih stock boot image dump dalam format .img atau .img.tar.</string>
|
||||
<string name="complete_uninstall">Copot Total</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">Unduh Kode Proprieter</string>
|
||||
<string name="proprietary_notice">Magisk Manager adalah aplikasi FOSS, yang tidak menyertakan kode API proprieter Google SafetyNet.\n\nApakah Anda mengizinkan Magisk Manager untuk mengunduh sebuah ekstensi (berisi GoogleApiClient) untuk pemeriksaan SafetyNet?</string>
|
||||
<string name="su_db_corrupt">Database SU rusak, akan membuat db baru</string>
|
||||
<string name="setup_done">Penyiapan selesai</string>
|
||||
<string name="setup_fail">Penyiapan gagal</string>
|
||||
<string name="proprietary_notice">Magisk Manager adalah aplikasi FOSS dan tidak menyertakan kode API proprieter Google SafetyNet.\n\nAkankah Anda mengizinkan Magisk Manager untuk mengunduh sebuah ekstensi (berisi GoogleApiClient) untuk pemeriksaan SafetyNet?</string>
|
||||
<string name="su_db_corrupt">Database SU rusak. Akan membuat db yang baru</string>
|
||||
<string name="setup_done">Penyiapan selesai.</string>
|
||||
<string name="setup_fail">Penyiapan gagal.</string>
|
||||
<string name="env_fix_title">Memerlukan Penyiapan Tambahan</string>
|
||||
<string name="env_fix_msg">Perangkat Anda memerlukan penyiapan tambahan untuk Magisk dapat bekerja dengan baik. Ia akan mengunduh zip penyiapan Magisk, apakah Anda ingin melanjutkan sekarang?</string>
|
||||
<string name="setup_title">Penyiapan Tambahan</string>
|
||||
<string name="setup_msg">Menjalankan penyiapan lingkungan…</string>
|
||||
<string name="downloading_toast">Mengunduh %1$s</string>
|
||||
<string name="no_rw_storage">Fitur ini tidak akan bekerja tanpa izin untuk menulis ke penyimpanan eksternal.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Umum</string>
|
||||
<string name="settings_dark_theme_title">Tema Gelap</string>
|
||||
<string name="settings_dark_theme_summary">Aktifkan tema gelap</string>
|
||||
<string name="settings_dark_theme_summary">Aktifkan tema gelap.</string>
|
||||
<string name="settings_clear_cache_title">Bersihkan Cache Repo</string>
|
||||
<string name="settings_clear_cache_summary">Bersihkan informasi ter-cache untuk repo online, memaksa apl untuk menyegarkan online</string>
|
||||
<string name="settings_clear_cache_summary">Bersihkan informasi ter-cache untuk repo online. Ini memaksa apl untuk menyegarkan secara online.</string>
|
||||
<string name="settings_hide_manager_title">Sembunyikan Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Pak ulang Magisk Manager dengan nama paket acak</string>
|
||||
<string name="settings_hide_manager_summary">Pak ulang Magisk Manager dengan nama paket acak.</string>
|
||||
<string name="settings_restore_manager_title">Pulihkan Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Pulihkan Magisk Manager dengan paket asli</string>
|
||||
<string name="language">Bahasa</string>
|
||||
<string name="system_default">(Default Sistem)</string>
|
||||
<string name="settings_update">Pengaturan Pembaruan</string>
|
||||
<string name="settings_check_update_title">Periksa Pembaruan</string>
|
||||
<string name="settings_check_update_summary">Secara periodik memeriksa pembaruan di latar belakang.</string>
|
||||
<string name="settings_update_channel_title">Kanal Pembaruan</string>
|
||||
<string name="settings_update_stable">Stabil</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Kustom</string>
|
||||
<string name="settings_update_custom_msg">Masukkan sebuah URL kustom</string>
|
||||
<string name="settings_boot_format_title">Format Keluaran Boot yang Ditambal</string>
|
||||
<string name="settings_boot_format_summary">Pilih format keluaran boot image yang ditambal.\nPilih .img untuk flash melalui mode recovery/download; pilih .img.tar untuk flash melalui ODIN.</string>
|
||||
<string name="settings_boot_format_summary">Pilih format untuk keluaran boot image yang ditambal.\nPilih .img untuk flash melalui mode recovery/download; pilih .img.tar untuk flash melalui ODIN.</string>
|
||||
<string name="settings_core_only_title">Magisk Mode Inti Saja</string>
|
||||
<string name="settings_core_only_summary">Aktifkan fitur inti saja. MagiskSU, MagiskHide, dan host tanpa sistem akan tetap diaktifkan</string>
|
||||
<string name="settings_magiskhide_summary">Sembunyikan Magisk dari berbagai pendeteksian</string>
|
||||
<string name="settings_core_only_summary">Aktifkan fitur inti saja. MagiskSU dan MagiskHide akan tetap diaktifkan</string>
|
||||
<string name="settings_magiskhide_summary">Sembunyikan Magisk dari berbagai bentuk pendeteksian.</string>
|
||||
<string name="settings_hosts_title">Host tanpa sistem</string>
|
||||
<string name="settings_hosts_summary">Dukungan host tanpa sistem untuk apl pemblokir iklan</string>
|
||||
<string name="settings_hosts_summary">Dukungan host tanpa sistem untuk apl pemblokir iklan.</string>
|
||||
<string name="settings_hosts_toast">Ditambahkan modul host tanpa sistem</string>
|
||||
|
||||
<string name="settings_su_app_adb">Apl dan ADB</string>
|
||||
<string name="settings_su_app">Apl saja</string>
|
||||
<string name="settings_su_adb">ADB saja</string>
|
||||
<string name="settings_su_disable">Nonaktif</string>
|
||||
<string name="settings_su_request_10">10 detik</string>
|
||||
<string name="settings_su_request_15">15 detik</string>
|
||||
<string name="settings_su_request_20">20 detik</string>
|
||||
<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">Tanggapan Otomatis</string>
|
||||
@@ -167,21 +179,21 @@
|
||||
<string name="multiuser_mode">Mode Multipengguna</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 permintaan</string>
|
||||
<string name="user_indepenent_summary">Setiap pengguna memiliki aturan root tersendiri</string>
|
||||
<string name="multiuser_hint_owner_request">Permintaan telah dikirim kepada pemilik perangkat. Silakan beralih ke pemilik dan berikan izin yang diperlukan</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 permintaan.</string>
|
||||
<string name="user_indepenent_summary">Setiap pengguna memiliki aturan root-nya sendiri.</string>
|
||||
<string name="multiuser_hint_owner_request">Permintaan telah dikirim kepada pemilik perangkat. Silakan beralih ke pemilik dan berikan izin yang diperlukan.</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mode Mount Ruang Nama</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 Terisolasi</string>
|
||||
<string name="global_summary">Semua sesi root menggunakan mount ruang nama global</string>
|
||||
<string name="requester_summary">Sesi root akan mewarisi ruang nama pemintanya</string>
|
||||
<string name="isolate_summary">Setiap sesi root akan memiliki ruang nama tersendiri</string>
|
||||
<string name="android_o_not_support">Tidak mendukung Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Tidak ada sidik jari diatur atau tidak ada dukungan perangkat</string>
|
||||
<string name="global_summary">Semua sesi root menggunakan mount ruang nama global.</string>
|
||||
<string name="requester_summary">Sesi root akan mewarisi ruang nama peminta mereka.</string>
|
||||
<string name="isolate_summary">Setiap sesi root akan memiliki ruang nama tersendiri.</string>
|
||||
<string name="android_o_not_support">Tidak mendukung Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Tidak ada sidik jari diatur atau tidak ada dukungan perangkat.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Permintaan Superuser</string>
|
||||
@@ -216,5 +228,4 @@
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">UID target:\u0020</string>
|
||||
<string name="command">Perintah:\u0020</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<resources>
|
||||
<!--Universal-->
|
||||
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="downloads">Download</string>
|
||||
@@ -8,18 +8,18 @@
|
||||
<string name="log">Registro eventi</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<string name="install">Installa</string>
|
||||
|
||||
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version_error">Magisk non è installato</string>
|
||||
<string name="magisk_version_error">Magisk non è installato.</string>
|
||||
<string name="checking_for_updates">Controllo aggiornamenti…</string>
|
||||
<string name="magisk_update_available">È disponibile Magisk v%1$s!</string>
|
||||
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
|
||||
<string name="safetyNet_check_text">Tocca per controllare SafetyNet</string>
|
||||
<string name="safetyNet_check_text">Tocca per controllare SafetyNet.</string>
|
||||
<string name="checking_safetyNet_status">Controllo stato SafetyNet…</string>
|
||||
<string name="safetyNet_check_success">Controllo SafetyNet OK</string>
|
||||
<string name="safetyNet_api_error">Errore API SafetyNet</string>
|
||||
<string name="safetyNet_res_invalid">La risposta non è valida</string>
|
||||
|
||||
<string name="safetyNet_res_invalid">La risposta non è valida.</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="advanced_settings_title">Impostazioni avanzate</string>
|
||||
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
|
||||
@@ -28,22 +28,22 @@
|
||||
<string name="install_magisk_title">Ultima versione disponibile: %1$s</string>
|
||||
<string name="uninstall">Disinstalla</string>
|
||||
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi. Il root verrà rimosso e se il dispositivo non è crittografato è possibile che tutti i dati vengano crittografati</string>
|
||||
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi. Il root verrà rimosso e i tuoi dati potrebbero venire criptati, nel caso non lo siano già.</string>
|
||||
<string name="update">Aggiorna %1$s</string>
|
||||
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nessuna informazione)</string>
|
||||
<string name="no_modules_found">Nessun modulo trovato</string>
|
||||
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio</string>
|
||||
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio</string>
|
||||
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio</string>
|
||||
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio</string>
|
||||
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio</string>
|
||||
<string name="no_modules_found">Nessun modulo trovato.</string>
|
||||
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio.</string>
|
||||
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio.</string>
|
||||
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio.</string>
|
||||
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio.</string>
|
||||
<string name="author">Creato da: %1$s</string>
|
||||
<string name="reboot_recovery">Riavvia in Recovery</string>
|
||||
<string name="reboot_bootloader">Riavvia in Bootloader</string>
|
||||
<string name="reboot_download">Riavvia in Download Mode</string>
|
||||
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Aggiornamento disponibile</string>
|
||||
<string name="installed">Installato</string>
|
||||
@@ -52,13 +52,13 @@
|
||||
<string name="sorting_order">Ordinamento</string>
|
||||
<string name="sort_by_name">Ordina per nome</string>
|
||||
<string name="sort_by_update">Ordina per ultimo aggiornamento</string>
|
||||
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">Salva registro eventi</string>
|
||||
<string name="menuReload">Ricarica</string>
|
||||
<string name="menuClearLog">Svuota il registro eventi</string>
|
||||
<string name="logs_cleared">Registro eventi svuotato correttamente</string>
|
||||
<string name="log_is_empty">Il registro eventi è vuoto</string>
|
||||
<string name="logs_cleared">Registro eventi svuotato correttamente.</string>
|
||||
<string name="log_is_empty">Il registro eventi è vuoto.</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Informazioni</string>
|
||||
@@ -70,6 +70,14 @@
|
||||
<string name="app_translators">Traduttori</string>
|
||||
<string name="support_thread">Thread di supporto</string>
|
||||
<string name="follow_twitter">Seguimi su Twitter</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Aggiornamenti Magisk</string>
|
||||
<string name="progress_channel">Notifiche di avanzamento</string>
|
||||
<string name="download_complete">Download completato</string>
|
||||
<string name="download_file_error">Errore nel download del file</string>
|
||||
<string name="magisk_update_title">È disponibile un nuovo aggiornamento di Magisk!</string>
|
||||
<string name="manager_update_title">È disponibile un nuovo aggiornamento di Magisk Manager!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Chiudi</string>
|
||||
@@ -77,117 +85,118 @@
|
||||
<string name="repo_install_msg">Vuoi installare %1$s?</string>
|
||||
<string name="download">Download</string>
|
||||
<string name="reboot">Riavvia</string>
|
||||
<string name="magisk_update_title">È disponibile un nuovo aggiornamento di Magisk!</string>
|
||||
<string name="settings_reboot_toast">Riavvia per applicare</string>
|
||||
<string name="settings_reboot_toast">Riavvia per applicare i cambiamenti.</string>
|
||||
<string name="release_notes">Note di rilascio</string>
|
||||
<string name="repo_cache_cleared">La cache delle repository è stata svuotata</string>
|
||||
<string name="process_error">Errore di elaborazione</string>
|
||||
<string name="process_error">Errore di elaborazione</string>
|
||||
<string name="internal_storage">Il file zip si trova in:\n[Memoria Interna]%1$s</string>
|
||||
<string name="zip_download_title">Download in corso</string>
|
||||
<string name="zip_download_msg">Download del file zip (%1$d%%) …</string>
|
||||
<string name="zip_process_title">Elaborazione</string>
|
||||
<string name="zip_process_msg">Elaborazione del file zip…</string>
|
||||
<string name="manager_update_title">È disponibile un nuovo aggiornamento di Magisk Manager!</string>
|
||||
<string name="manager_download_install">Premere per scaricare e installare</string>
|
||||
<string name="manager_download_install">Premere per scaricare e installare.</string>
|
||||
<string name="dtbo_patched_title">DTBO è stato aggiornato!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img, riavvia per completare</string>
|
||||
<string name="magisk_updates">Aggiornamenti di Magisk</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img. Riavvia per completare.</string>
|
||||
<string name="flashing">Flash in corso…</string>
|
||||
<string name="hide_manager_toast">Nascondendo Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">Potrebbe volerci un po\'…</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="hide_manager_title">Nascondendo Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">Potrebbe volerci un po\'.</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="download_zip_only">Scarica solo il file zip</string>
|
||||
<string name="patch_boot_file">Aggiorna l\'immagine di boot</string>
|
||||
<string name="direct_install">Installazione diretta (raccomandata)</string>
|
||||
<string name="install_inactive_slot">Installa nello slot inattivo (dopo un OTA)</string>
|
||||
<string name="warning">Attenzione</string>
|
||||
<string name="install_inactive_slot_msg">Questo dispositivo verrà FORZATO ad avviarsi usando lo slot inattivo!\nUsa questo metodo solo dopo che un OTA è stato installato.\nVuoi continuare?</string>
|
||||
<string name="select_method">Seleziona un metodo</string>
|
||||
<string name="select_method">Seleziona un metodo</string>
|
||||
<string name="no_boot_file_patch_support">La versione Magisk di destinazione non supporta l\'aggiornamento dell\'immagine di boot</string>
|
||||
<string name="boot_file_patch_msg">Seleziona l\'immagine originale di boot in formato .img o img.tar</string>
|
||||
<string name="boot_file_patch_msg">Seleziona l\'immagine originale di boot in formato .img o img.tar.</string>
|
||||
<string name="complete_uninstall">Disinstallazione completa</string>
|
||||
<string name="restore_img">Ripristina Immagini</string>
|
||||
<string name="restore_img_msg">Ripristino…</string>
|
||||
<string name="restore_done">Ripristino completato!</string>
|
||||
<string name="restore_img_msg">Ripristino…</string>
|
||||
<string name="restore_done">Ripristino completato!</string>
|
||||
<string name="restore_fail">Non esiste un\'immagine originale di boot!</string>
|
||||
<string name="proprietary_title">Scarica codice proprietario</string>
|
||||
<string name="proprietary_notice">Magisk Manager è FOSS, quindi non contiene codice proprietario delle API Google SafetyNet.\n\nVuoi permettere il download di un\'estensione (che contiene GoogleApiClient) per controllare lo stato di SafetyNet?</string>
|
||||
<string name="su_db_corrupt">Il database SU è corrotto, un nuovo DB verrà ricreato</string>
|
||||
<string name="setup_done">Configurazione completata</string>
|
||||
<string name="setup_fail">Configurazione fallita</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="su_db_corrupt">Il database SU è corrotto. Vuoi ricrearne uno nuovo?</string>
|
||||
<string name="setup_done">Configurazione completata.</string>
|
||||
<string name="setup_fail">Configurazione fallita.</string>
|
||||
<string name="env_fix_title">Richiedi configurazione aggiuntiva</string>
|
||||
<string name="env_fix_msg">Il tuo dispositivo necessita di una configurazione aggiuntiva per far funzionare Magisk correttamente. Verrà scaricato il file zip di Magisk, vuoi procedere ora?</string>
|
||||
<string name="setup_title">Configurazione aggiuntiva</string>
|
||||
<string name="setup_msg">Configurazione dell\'ambiente in corso…</string>
|
||||
|
||||
|
||||
<string name="downloading_toast">Download di %1$s</string>
|
||||
<string name="no_rw_storage">Questa funzione non sarà attiva senza l\'autorizzazione di scrittura nella memoria di archiviazione esterna</string>
|
||||
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Generale</string>
|
||||
<string name="settings_dark_theme_title">Tema scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita il tema scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita il tema scuro.</string>
|
||||
<string name="settings_clear_cache_title">Svuota cache repository</string>
|
||||
<string name="settings_clear_cache_summary">Svuota la cache delle repository e forza l\'aggiornamento online dell\'app</string>
|
||||
<string name="settings_clear_cache_summary">Svuota la cache delle repository. Questa opzione forza l\'aggiornamento online dell\'app.</string>
|
||||
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
|
||||
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome pacchetto casuale</string>
|
||||
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome pacchetto casuale.</string>
|
||||
<string name="settings_restore_manager_title">Ripristina Magisk Manager</string>
|
||||
<string name="settings_restore_manager_summary">Ripristina Magisk Manager con il nome pacchetto originale</string>
|
||||
<string name="language">Lingua</string>
|
||||
<string name="system_default">(Sistema)</string>
|
||||
<string name="settings_update">Impostazioni aggiornamento</string>
|
||||
<string name="settings_check_update_title">Controlla aggiornamenti</string>
|
||||
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti in background</string>
|
||||
<string name="settings_check_update_summary">Controlla automaticamente gli aggiornamenti in background.</string>
|
||||
<string name="settings_update_channel_title">Canale di aggiornamento</string>
|
||||
<string name="settings_update_stable">Stabile</string>
|
||||
<string name="settings_update_beta">Beta</string>
|
||||
<string name="settings_update_custom">Personalizzato</string>
|
||||
<string name="settings_update_custom_msg">Inserisci un URL personalizzato</string>
|
||||
<string name="settings_boot_format_title">Formato dell\'immagine di boot aggiornata</string>
|
||||
<string name="settings_boot_format_summary">Seleziona il formato nel quale l\'immagine di boot verrà salvata.\nSeleziona .img per il flash in Fastboot/Download Mode; Seleziona .img.tar per il flash con Odin.</string>
|
||||
<string name="settings_boot_format_summary">Seleziona il formato nel quale la nuova immagine di boot verrà salvata.\nSeleziona .img per il flash in Fastboot/Download Mode; Seleziona .img.tar per il flash con Odin.</string>
|
||||
<string name="settings_core_only_title">Modalità Magisk Core</string>
|
||||
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU, MagiskHide e host systemless rimarranno abilitati</string>
|
||||
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
|
||||
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU e MagiskHide rimarranno abilitati</string>
|
||||
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni.</string>
|
||||
<string name="settings_hosts_title">Host systemless</string>
|
||||
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità</string>
|
||||
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità.</string>
|
||||
|
||||
<string name="settings_su_app_adb">App e ADB</string>
|
||||
<string name="settings_su_app">Solo app</string>
|
||||
<string name="settings_su_adb">Solo ADB</string>
|
||||
<string name="settings_su_disable">Disabilitato</string>
|
||||
<string name="settings_su_request_10">10 secondi</string>
|
||||
<string name="settings_su_request_15">15 secondi</string>
|
||||
<string name="settings_su_request_20">20 secondi</string>
|
||||
<string name="settings_su_request_30">30 secondi</string>
|
||||
<string name="settings_su_request_45">45 secondi</string>
|
||||
<string name="settings_su_request_60">60 secondi</string>
|
||||
<string name="superuser_access">Accesso Superuser</string>
|
||||
<string name="auto_response">Accesso predefinito</string>
|
||||
<string name="request_timeout">Timeout richiesta</string>
|
||||
<string name="superuser_notification">Notifica Superuser</string>
|
||||
<string name="request_timeout_summary">%1$s secondi</string>
|
||||
<string name="settings_su_reauth_title">Ri-autentica dopo aggiornamento</string>
|
||||
<string name="settings_su_reauth_summary">Ri-autentica i permessi Superuser dopo un aggiornamento dell\'app</string>
|
||||
<string name="settings_su_reauth_title">Riautentica dopo aggiornamento</string>
|
||||
<string name="settings_su_reauth_summary">Riautentica i permessi Superuser dopo un aggiornamento dell\'app</string>
|
||||
<string name="settings_su_fingerprint_title">Abilita autenticazione impronta</string>
|
||||
<string name="settings_su_fingerprint_summary">Utilizza il sensore di impronte per accettare le richieste Superuser</string>
|
||||
<string name="auth_fingerprint">Conferma Impronta</string>
|
||||
|
||||
<string name="multiuser_mode">Modalità multiutente</string>
|
||||
<string name="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">Utente indipendente</string>
|
||||
<string name="owner_only_summary">Solo il proprietario ha i permessi di root</string>
|
||||
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root separate</string>
|
||||
<string name="settings_user_independent">Idipendente dall\'utente</string>
|
||||
<string name="owner_only_summary">Solo il proprietario ha i permessi di root.</string>
|
||||
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste.</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root indpendenti.</string>
|
||||
<string name="multiuser_hint_owner_request">Una richiesta è stata inviata al proprietario del dispositivo. Accedi come proprietario dispositivo e concedi i permessi.</string>
|
||||
|
||||
|
||||
<string name="mount_namespace_mode">Modalità mount namespace</string>
|
||||
<string name="settings_ns_global">Namespace globale</string>
|
||||
<string name="settings_ns_requester">Namespace ereditato</string>
|
||||
<string name="settings_ns_isolate">Namespace isolato</string>
|
||||
<string name="global_summary">Tutte le sessioni di root erediteranno il namespace globale</string>
|
||||
<string name="requester_summary">Le sessioni di root erediteranno il namespace del loro richiedente</string>
|
||||
<string name="isolate_summary">Ogni sessione di root avrà il suo namespace isolato</string>
|
||||
<string name="android_o_not_support">Non è supportato da Android 8.0+</string>
|
||||
<string name="disable_fingerprint">Non è presente alcuna impronta o il dispositivo non è supportato</string>
|
||||
|
||||
<string name="global_summary">Tutte le sessioni di root erediteranno il namespace globale.</string>
|
||||
<string name="requester_summary">Le sessioni di root erediteranno il namespace del loro richiedente.</string>
|
||||
<string name="isolate_summary">Ogni sessione di root avrà il suo namespace isolato.</string>
|
||||
<string name="android_o_not_support">Non è supportato da Android 8.0+.</string>
|
||||
<string name="disable_fingerprint">Non è presente alcuna impronta o il dispositivo non è supportato.</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Richiesta Superuser</string>
|
||||
<string name="deny_with_str">Nega %1$s</string>
|
||||
@@ -216,10 +225,10 @@
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Nessuno</string>
|
||||
<string name="auth_fail">Autenticatione fallita</string>
|
||||
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">UID destinazione:\u0020</string>
|
||||
<string name="command">Comando:\u0020</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
@@ -90,10 +90,10 @@
|
||||
<string name="manager_download_install">タップでダウンロードしてインストールします</string>
|
||||
<string name="dtbo_patched_title">DTBOをパッチしました!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Managerはdtbo.imgをパッチしました。再起動してください</string>
|
||||
<string name="magisk_updates">Magiskの更新</string>
|
||||
<string name="update_channel">Magiskの更新</string>
|
||||
<string name="flashing">書き込み中</string>
|
||||
<string name="hide_manager_toast">Magisk Managerを隠しています…</string>
|
||||
<string name="hide_manager_toast2">しばらくお待ちください…</string>
|
||||
<string name="hide_manager_title">Magisk Managerを隠しています…</string>
|
||||
<string name="hide_manager_msg">しばらくお待ちください…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Managerを隠せませんでした…</string>
|
||||
<string name="download_zip_only">ZIPのみダウンロード</string>
|
||||
<string name="patch_boot_file">Bootイメージのパッチ</string>
|
||||
@@ -108,6 +108,9 @@
|
||||
<string name="proprietary_title">プロプライエタリコードのダウンロード</string>
|
||||
<string name="proprietary_notice">Magisk ManagerはFOSSのため、GoogleのプロプライエタリなSafetyNet APIコードを含んでいません。\n\nMagisk ManagerがSafetyNetチェックのための拡張機能 (GoogleApiClientを含む) をダウンロードすることを許可しますか?</string>
|
||||
<string name="su_db_corrupt">SUデータベースが壊れています。DBを再生成します</string>
|
||||
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
|
||||
<string name="downloading_toast">%1$s をダウンロード中</string>
|
||||
<string name="no_rw_storage">この機能は外部ストレージへの書き込み権限がないと動作しません</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">一般</string>
|
||||
@@ -128,7 +131,7 @@
|
||||
<string name="settings_boot_format_title">パッチしたBootの出力形式</string>
|
||||
<string name="settings_boot_format_summary">パッチしたBootイメージの出力形式を選択してください。\nfastboot/download modeでインストールするには .img を、ODINでインストールするには .img.tar を選択してください</string>
|
||||
<string name="settings_core_only_title">Magisk コアモード</string>
|
||||
<string name="settings_core_only_summary">コア機能のみを有効にします。すべてのモジュールが読み込まれなくなります。 MagiskSU、MagiskHide、systemless hostsは引き続き有効になります</string>
|
||||
<string name="settings_core_only_summary">コア機能のみを有効にします。すべてのモジュールが読み込まれなくなります。 MagiskSU、MagiskHide は引き続き有効になります</string>
|
||||
<string name="settings_magiskhide_summary">さまざまな検出からMagiskを隠します</string>
|
||||
<string name="settings_hosts_title">Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">広告ブロックアプリのためのSystemless hostsサポートを有効化します</string>
|
||||
|
@@ -71,6 +71,9 @@
|
||||
<string name="process_error">처리 오류</string>
|
||||
<string name="internal_storage">zip 파일이 다음 위치에 저장됨:\n[내부 저장소]%1$s</string>
|
||||
<string name="zip_process_title">처리 중</string>
|
||||
<string name="download_file_error">파일 다운로드 오류</string>
|
||||
<string name="downloading_toast">%1$s 다운로드 중</string>
|
||||
<string name="no_rw_storage">이 기능은 외부 저장소 쓰기 권한 없이는 작동하지 않습니다.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">일반</string>
|
||||
@@ -80,7 +83,7 @@
|
||||
<string name="settings_clear_cache_summary">온라인 저장소에 대해 캐시된 정보를 지우고, 온라인에서 정보를 강제로 새로 고칩니다.</string>
|
||||
|
||||
<string name="settings_core_only_title">Magisk 핵심 기능 모드</string>
|
||||
<string name="settings_core_only_summary">핵심 기능만 사용합니다. 모든 모듈은 로드하지 않습니다. MagiskSU, MagiskHide 및 systemless hosts 는 계속 사용할 수 있습니다.</string>
|
||||
<string name="settings_core_only_summary">핵심 기능만 사용합니다. 모든 모듈은 로드하지 않습니다. MagiskSU 및 MagiskHide 는 계속 사용할 수 있습니다.</string>
|
||||
<string name="settings_magiskhide_summary">다양한 감지로부터 Magisk를 숨깁니다.</string>
|
||||
<string name="settings_hosts_title">systemless hosts</string>
|
||||
<string name="settings_hosts_summary">광고 차단 앱에서 사용하는 systemless hosts를 지원합니다.</string>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Papildiniai</string>
|
||||
<string name="downloads">Papildinių parduotuvė</string>
|
||||
@@ -51,7 +51,7 @@
|
||||
<string name="sorting_order">Išdėliojimo tvarka</string>
|
||||
<string name="sort_by_name">Išdėlioti pagal pavadinimą (A-Z)</string>
|
||||
<string name="sort_by_update">Išdėlioti pagal atnaujinimo datą (Naujausi-Seniausi)</string>
|
||||
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveLog">Išsaugoti įvykių sąrašą</string>
|
||||
<string name="menuReload">Įvykių sąrašo atnaujinmas</string>
|
||||
@@ -89,16 +89,16 @@
|
||||
<string name="manager_download_install">Paspauskite, kad atsisiųstumėte ir instaliuotumėte</string>
|
||||
<string name="dtbo_patched_title">DTBO buvo ištaisytas!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager ištaisė dtbo.img, prašome perkrauti telefoną</string>
|
||||
<string name="magisk_updates">Magisk Atnaujinimai</string>
|
||||
<string name="update_channel">Magisk Atnaujinimai</string>
|
||||
<string name="flashing">Instaliuojama</string>
|
||||
<string name="hide_manager_toast">Magisk Manager paslėpiamas…</string>
|
||||
<string name="hide_manager_toast2">Tai užtruks sekundėlę…</string>
|
||||
<string name="hide_manager_title">Magisk Manager paslėpiamas…</string>
|
||||
<string name="hide_manager_msg">Tai užtruks sekundėlę…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager paslėpimas žlugo…</string>
|
||||
<string name="download_zip_only">Atsisiųsti zip failą</string>
|
||||
<string name="patch_boot_file">Ištaisyti boot failą</string>
|
||||
<string name="direct_install">Tiesioginis instaliavimas (Rekomenduojamas)</string>
|
||||
<string name="select_method">Pasirinkite metodą</string>
|
||||
<string name="no_boot_file_patch_support">Pasirinkta Magisk versija nepalaiko pakeitimų boot faile</string>
|
||||
<string name="no_boot_file_patch_support">Pasirinkta Magisk versija nepalaiko pakeitimų boot faile</string>
|
||||
<string name="boot_file_patch_msg">Pasirinkti boot failą .img ar .img.tar formate</string>
|
||||
<string name="complete_uninstall">Pilnas pašalinimas</string>
|
||||
<string name="restore_img">Atstatyti boot failą</string>
|
||||
@@ -112,8 +112,11 @@
|
||||
<string name="setup_fail">Pasiruošimas nesėkmingas</string>
|
||||
<string name="env_fix_title">Reikalingas papildomas pasiruošimas</string>
|
||||
<string name="env_fix_msg">Kad Magisk veiktų tinkamai, jūsų įrenginiui reikia papildomo paruošimo. Tai atsisiųs papildomą Magisk zip failą, ar norite tęsti?</string>
|
||||
<string name="setup_title">Papildomas pasiruošimas</string>
|
||||
<string name="setup_title">Papildomas pasiruošimas</string>
|
||||
<string name="setup_msg">Paruošiama aplinka…</string>
|
||||
<string name="download_file_error">Atsisiunčiant failą įvyko klaida</string>
|
||||
<string name="downloading_toast">Atsisiunčiamas %1$s</string>
|
||||
<string name="no_rw_storage">Ši funkija neveiks be prieigos prie saugyklos</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Pagrininiai</string>
|
||||
@@ -138,7 +141,7 @@
|
||||
<string name="settings_boot_format_title">Boot failo formatas</string>
|
||||
<string name="settings_boot_format_summary">Pasirinkti boot failo formatą.\n.img naudojamas įdiegimui per fastboot/download; .img.tar naudojamas įdiegimui per ODIN</string>
|
||||
<string name="settings_core_only_title">Pagrindinis Magisk režimas</string>
|
||||
<string name="settings_core_only_summary">Įgalinti tik pagrindines funkcijas, išjungti visus papildinius. MagiskSU, Magisk Hide ir Sistemos pedejėjai liks įgalinti</string>
|
||||
<string name="settings_core_only_summary">Įgalinti tik pagrindines funkcijas, išjungti visus papildinius. MagiskSU ir Magisk Hide liks įgalinti</string>
|
||||
<string name="settings_magiskhide_summary">Paslėpti Magisk nuo įvairių susekimų</string>
|
||||
<string name="settings_hosts_title">Sistemos padejėjai</string>
|
||||
<string name="settings_hosts_summary">Įgalinti sistemos padejėjus Adblock programėlėms</string>
|
||||
@@ -148,8 +151,10 @@
|
||||
<string name="settings_su_adb">Tik ADB</string>
|
||||
<string name="settings_su_disable">Išjungta</string>
|
||||
<string name="settings_su_request_10">10 sekundžių</string>
|
||||
<string name="settings_su_request_15">15 sekundžių</string>
|
||||
<string name="settings_su_request_20">20 sekundžių</string>
|
||||
<string name="settings_su_request_30">30 sekundžių</string>
|
||||
<string name="settings_su_request_45">45 sekundžių</string>
|
||||
<string name="settings_su_request_60">60 sekundžių</string>
|
||||
<string name="superuser_access">Supervartotojo prieiga</string>
|
||||
<string name="auto_response">Automatinis atsakymas</string>
|
||||
@@ -160,7 +165,7 @@
|
||||
<string name="settings_su_reauth_summary">Pakartotinai patvirtinti supervartotojo leidimus po programėlės atnaujinimo</string>
|
||||
<string name="settings_su_fingerprint_title">Įgalinti patvirtinimą piršto antspaudu</string>
|
||||
<string name="settings_su_fingerprint_summary">Naudoti piršto antspaudą supervartotojo leidimo prašymų atsakymui</string>
|
||||
|
||||
|
||||
<string name="multiuser_mode">Daugialypio vartotojo režimas</string>
|
||||
<string name="settings_owner_only">Tik įrenginio savininkas</string>
|
||||
<string name="settings_owner_manage">Įrenginio savininko valdomas</string>
|
||||
@@ -179,7 +184,7 @@
|
||||
<string name="isolate_summary">Kiekviena root sesija turi savo izoliuotą vardų sritį</string>
|
||||
<string name="android_o_not_support">Įrenginiai su Android 8.0+ nepalaiko šio nustatymo</string>
|
||||
<string name="disable_fingerprint">Jūsų įrenginyje nebuvo surasta pirštų antspaudų arba jūsų įrenginys neturi pirštų antspaudų skaitytuvo</string>
|
||||
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Supervartotojo prašymas</string>
|
||||
<string name="deny_with_str">Atmesti%1$s</string>
|
||||
@@ -208,7 +213,7 @@
|
||||
<string name="toast">Išmesti</string>
|
||||
<string name="none">Nėra</string>
|
||||
<string name="auth_fail">Patvirtinimas žlugo</string>
|
||||
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">Target UID:\u0020</string>
|
||||
|
@@ -90,10 +90,10 @@
|
||||
<string name="manager_download_install">Tik om te downloaden en installeren</string>
|
||||
<string name="dtbo_patched_title">DTBO is gepatched!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager heeft dtbo.img gepatched, herstarten a.u.b.</string>
|
||||
<string name="magisk_updates">Magisk updates</string>
|
||||
<string name="update_channel">Magisk updates</string>
|
||||
<string name="flashing">Flashen</string>
|
||||
<string name="hide_manager_toast">Magisk Manager verbergen…</string>
|
||||
<string name="hide_manager_toast2">Dit kan even duren…</string>
|
||||
<string name="hide_manager_title">Magisk Manager verbergen…</string>
|
||||
<string name="hide_manager_msg">Dit kan even duren…</string>
|
||||
<string name="hide_manager_fail_toast">Magisk Manager verbergen mislukt…</string>
|
||||
<string name="download_zip_only">Alleen zip downloaden</string>
|
||||
<string name="patch_boot_file">Boot image-bestand patchen</string>
|
||||
@@ -108,6 +108,9 @@
|
||||
<string name="proprietary_title">Google\'s code downloaden</string>
|
||||
<string name="proprietary_notice">Magisk Manager is FOSS, dus bevat geen SafetyNet API code van Google.\n\nSta je Magisk Manager toe om een extensie te downloaden (bevat GoogleApiClient) voor SafetyNet controles?</string>
|
||||
<string name="su_db_corrupt">SU database is corrupt, nieuwe db maken…</string>
|
||||
<string name="download_file_error">Fout tijdens downloaden</string>
|
||||
<string name="downloading_toast">%1$s downloaden</string>
|
||||
<string name="no_rw_storage">Deze functie werkt niet zonder schrijfpermissie voor externe opslag.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Algemeen</string>
|
||||
@@ -132,7 +135,7 @@
|
||||
<string name="settings_boot_format_title">Gepatchte boot uitvoerformaat</string>
|
||||
<string name="settings_boot_format_summary">Kies het formaat van de boot image uitvoer.\nKies .img om via fastboot/downloadmodus te flashen; kies .img.tar om via ODIN te flashen.</string>
|
||||
<string name="settings_core_only_title">Magisk basismodus</string>
|
||||
<string name="settings_core_only_summary">Alleen kernfuncties inschakelen. Alle modules worden niet geladen. MagiskSU, MagiskHide, en systeemloze hosts blijven ingeschakeld</string>
|
||||
<string name="settings_core_only_summary">Alleen kernfuncties inschakelen. Alle modules worden niet geladen. MagiskSU en MagiskHide blijven ingeschakeld</string>
|
||||
<string name="settings_magiskhide_summary">Magisk van verschillende detecties verbergen</string>
|
||||
<string name="settings_hosts_title">Systeemloze hosts</string>
|
||||
<string name="settings_hosts_summary">Systemloze hosts ondersteuning voor Adblock apps</string>
|
||||
@@ -142,8 +145,10 @@
|
||||
<string name="settings_su_adb">Alleen ADB</string>
|
||||
<string name="settings_su_disable">Uitgeschakeld</string>
|
||||
<string name="settings_su_request_10">10 seconden</string>
|
||||
<string name="settings_su_request_15">15 seconden</string>
|
||||
<string name="settings_su_request_20">20 seconden</string>
|
||||
<string name="settings_su_request_30">30 seconden</string>
|
||||
<string name="settings_su_request_45">45 seconden</string>
|
||||
<string name="settings_su_request_60">60 seconden</string>
|
||||
<string name="superuser_access">Superuser toegang</string>
|
||||
<string name="auto_response">Automatisch antwoord</string>
|
||||
@@ -154,7 +159,7 @@
|
||||
<string name="settings_su_reauth_summary">Superuser rechten opnieuw opvragen na bijwerken applicatie</string>
|
||||
<string name="settings_su_fingerprint_title">Vingerafdruk authenticatie inschakelen</string>
|
||||
<string name="settings_su_fingerprint_summary">Vingerafdruk gebruiken om superuser verzoeken toe te staan</string>
|
||||
|
||||
|
||||
<string name="multiuser_mode">Multi-gebruiker modus</string>
|
||||
<string name="settings_owner_only">Alleen apparaateigenaar</string>
|
||||
<string name="settings_owner_manage">Beheerd door apparaateigenaar</string>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<resources>
|
||||
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="modules">Moduły</string>
|
||||
<string name="downloads">Pobieranie</string>
|
||||
@@ -29,7 +29,7 @@
|
||||
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
|
||||
<string name="uninstall_magisk_msg">Wszystkie moduły będą wyłączone/usunięte. Root zostanie usunięty i przywrócone szyfrowanie danych, jeśli nie są te dane obecnie szyfrowane</string>
|
||||
<string name="update">Aktualizacja %1$s</string>
|
||||
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nie umieszczono informacji)</string>
|
||||
<string name="no_modules_found">Nie znaleziono modułów</string>
|
||||
@@ -42,7 +42,7 @@
|
||||
<string name="reboot_recovery">Restart do Recovery</string>
|
||||
<string name="reboot_bootloader">Restart do Bootloadera</string>
|
||||
<string name="reboot_download">Restart do Download</string>
|
||||
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Aktualizacja jest dostępna</string>
|
||||
<string name="installed">Zainstalowany</string>
|
||||
@@ -68,6 +68,15 @@
|
||||
<string name="donation">Dotacja</string>
|
||||
<string name="app_translators">Tłumacze Aplikacji</string>
|
||||
<string name="support_thread">Strona Wsparcia</string>
|
||||
<string name="follow_twitter">Polub mnie na Twitterze</string>
|
||||
|
||||
<!-- System Components, Notifications -->
|
||||
<string name="update_channel">Aktualizacja Magisk</string>
|
||||
<string name="progress_channel">Powiadomienia o Postępie</string>
|
||||
<string name="download_complete">Pobieranie zakończone</string>
|
||||
<string name="download_file_error">Błąd pobierania pliku</string>
|
||||
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
|
||||
<string name="manager_update_title">Nowa Wersja Magisk Manager Jest Dostępna!</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="close">Zamknij</string>
|
||||
@@ -75,7 +84,6 @@
|
||||
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
|
||||
<string name="download">Pobierz</string>
|
||||
<string name="reboot">Restart</string>
|
||||
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
|
||||
<string name="settings_reboot_toast">Uruchom ponownie, aby zastosować ustawienia</string>
|
||||
<string name="release_notes">Zmiany</string>
|
||||
<string name="repo_cache_cleared">Cache repozytorium wyczyszczone</string>
|
||||
@@ -85,23 +93,26 @@
|
||||
<string name="zip_download_msg">Pobieranie pliku zip (%1$d%%) …</string>
|
||||
<string name="zip_process_title">Przetwarzanie</string>
|
||||
<string name="zip_process_msg">Przetwarzanie pliku zip …</string>
|
||||
<string name="manager_update_title">Nowa Wersja Magisk Manager Jest Dostępna!</string>
|
||||
<string name="manager_download_install">Naciśnij aby pobrać i zainstalować</string>
|
||||
<string name="dtbo_patched_title">DTBO został wgrany!</string>
|
||||
<string name="dtbo_patched_reboot">Magisk Manager wgrał dtbo.img, uruchom ponownie</string>
|
||||
<string name="magisk_updates">Aktualizacja Magisk</string>
|
||||
<string name="flashing">Flashowanie</string>
|
||||
<string name="hide_manager_toast">Ukryj Magisk Manager…</string>
|
||||
<string name="hide_manager_toast2">To może chwilę potrwać…</string>
|
||||
<string name="hide_manager_title">Ukryj Magisk Manager…</string>
|
||||
<string name="hide_manager_msg">To może chwilę potrwać…</string>
|
||||
<string name="hide_manager_fail_toast">Błąd Ukrycia Magisk Managera</string>
|
||||
<string name="open_link_failed_toast">Nie znaleziono aplikacji pod linkiem.</string>
|
||||
<string name="download_zip_only">Pobierz Tylko Zip</string>
|
||||
<string name="patch_boot_file">Patchowanie Pliku Boot Image</string>
|
||||
<string name="direct_install">Bezpośrednia instalacja (Zalecane)</string>
|
||||
<string name="select_method">Wybierz Metodę</string>
|
||||
<string name="install_inactive_slot">Zainstaluj do nieaktywnego Slotu (po OTA)</string>
|
||||
<string name="warning">Uwaga</string>
|
||||
<string name="install_inactive_slot_msg">Urządzenie będzie MUSIAŁO uruchomić się z bieżącego nieaktywnego slotu po restarcie! /\nUżyj tylko tej opcji po zakończeniu OTA.\nKontynuować?</string>
|
||||
<string name="select_method">Wybierz Metodę</string>
|
||||
<string name="no_boot_file_patch_support">Wersja docelowa programu Magisk nie obsługuje ładowania pliku boot image</string>
|
||||
<string name="boot_file_patch_msg">Wybierz stock boot image w formacie .img lub .img.tar</string>
|
||||
<string name="complete_uninstall">Odinstalowywanie Zakończone</string>
|
||||
<string name="restore_img">Przywróć Obraz</string>
|
||||
<string name="restore_img_msg">Przywracanie…</string>
|
||||
<string name="restore_done">Przywracanie zakończone!</string>
|
||||
<string name="restore_fail">Stock backup nie istnieje!</string>
|
||||
<string name="proprietary_title">Pobierz Kod</string>
|
||||
@@ -111,7 +122,11 @@
|
||||
<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 pliku instalacyjnego Magisk, czy chcesz kontynuować?</string>
|
||||
|
||||
<string name="setup_title">Dodatkowa konfiguracja</string>
|
||||
<string name="setup_msg">Uruchamianie konfiguracji środowiska…</string>
|
||||
<string name="downloading_toast">Pobieranie %1$s</string>
|
||||
<string name="no_rw_storage">Ta funkcja nie będzie działać bez uprawnień do zapisu na pamięci zewnętrznej.</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Ogólne</string>
|
||||
<string name="settings_dark_theme_title">Ciemny Motyw</string>
|
||||
@@ -124,7 +139,7 @@
|
||||
<string name="settings_restore_manager_summary">Przywróć oryginalną paczkę Magisk Manager</string>
|
||||
<string name="language">Język</string>
|
||||
<string name="system_default">(Domyślny Systemu)</string>
|
||||
<string name="settings_update">Aktualizacja Ustawień</string>
|
||||
<string name="settings_update">Ustawienia Aktualizacji</string>
|
||||
<string name="settings_check_update_title">Sprawdź Aktualizację</string>
|
||||
<string name="settings_check_update_summary">Regularnie sprawdzaj aktualizacje w tle</string>
|
||||
<string name="settings_update_channel_title">Kanał Aktualizacji</string>
|
||||
@@ -135,18 +150,21 @@
|
||||
<string name="settings_boot_format_title">Poprawny format pliku rozruchowego</string>
|
||||
<string name="settings_boot_format_summary">Wybierz format pliku boot image.\nWybierz .img dla wgrywania poprzez Fastboot/Download Mode. Wybierz .img.tar dla ODINA.</string>
|
||||
<string name="settings_core_only_title">Tylko Podstawowy Tryb Magisk</string>
|
||||
<string name="settings_core_only_summary">Włącz tylko podstawowe funkcje, wszystkie moduły nie zostaną załadowane. MagiskSU, MagiskHide i systemless hosts nadal będą włączone</string>
|
||||
<string name="settings_core_only_summary">Włącz tylko podstawowe funkcje, wszystkie moduły nie zostaną załadowane. MagiskSU i MagiskHide nadal będą włączone</string>
|
||||
<string name="settings_magiskhide_summary">Włącz Magisk Hide dla wykrytych aplikacji</string>
|
||||
<string name="settings_hosts_title">Włącz systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Wsparcie systemless dla aplikacji Adblock</string>
|
||||
|
||||
<string name="settings_su_app_adb">Aplikacje i ADB</string>
|
||||
<string name="settings_hosts_toast">Dodano systemowy host moduł</string>
|
||||
|
||||
<string name="settings_su_app_adb">Aplikacje i ADB</string>
|
||||
<string name="settings_su_app">Tylko Aplikacje</string>
|
||||
<string name="settings_su_adb">Tylko ADB</string>
|
||||
<string name="settings_su_disable">Wyłączone</string>
|
||||
<string name="settings_su_request_10">10 sekund</string>
|
||||
<string name="settings_su_request_15">15 sekund</string>
|
||||
<string name="settings_su_request_20">20 sekund</string>
|
||||
<string name="settings_su_request_30">30 sekund</string>
|
||||
<string name="settings_su_request_45">45 sekund</string>
|
||||
<string name="settings_su_request_60">60 sekund</string>
|
||||
<string name="superuser_access">Dostęp Superuser</string>
|
||||
<string name="auto_response">Automatyczna Odpowiedź</string>
|
||||
@@ -157,8 +175,9 @@
|
||||
<string name="settings_su_reauth_summary">Ponowne uwierzytelnianie uprawnienia superużytkownika po aktualizacji aplikacji</string>
|
||||
<string name="settings_su_fingerprint_title">Włącz Uwierzytelnienie Odciskiem Palca</string>
|
||||
<string name="settings_su_fingerprint_summary">Użyj skanera linii papilarnych, aby zezwolić na żądania supersu</string>
|
||||
<string name="auth_fingerprint">Uwierzytelnianie Odciskiem Palców</string>
|
||||
|
||||
<string name="multiuser_mode">Tryb Multiusera</string>
|
||||
<string name="multiuser_mode">Tryb Multiusera</string>
|
||||
<string name="settings_owner_only">Tylko Właściciel Urządzenia</string>
|
||||
<string name="settings_owner_manage">Zarządzanie Właścicielami Urządzenia</string>
|
||||
<string name="settings_user_independent">Niezależny Użytkownik</string>
|
||||
@@ -176,7 +195,7 @@
|
||||
<string name="isolate_summary">W każdej sesji root będzie miał własną odosobnioną nazwę</string>
|
||||
<string name="android_o_not_support">Brak wsparcia dla Androida 8.0+</string>
|
||||
<string name="disable_fingerprint">Nie ustawiono żadnych odcisków palców lub brak obsługi urządzenia</string>
|
||||
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Prośba o dostęp Superusera</string>
|
||||
<string name="deny_with_str">Odmów%1$s</string>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user