mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-15 00:37:26 +00:00
Compare commits
84 Commits
v17.1
...
manager-v6
Author | SHA1 | Date | |
---|---|---|---|
![]() |
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 | ||
![]() |
cfe32f1a70 | ||
![]() |
d877f5d5c6 | ||
![]() |
0ab6ffefb4 | ||
![]() |
a292a1d23a | ||
![]() |
3f87f6aee3 | ||
![]() |
04bcd145d3 | ||
![]() |
244e811291 | ||
![]() |
ac7467fb59 | ||
![]() |
2c0436216f | ||
![]() |
017fbf267b | ||
![]() |
e6afbf2ec0 | ||
![]() |
906b4aad9e | ||
![]() |
4cf8d41f6a | ||
![]() |
47c860142e | ||
![]() |
2fba3f213b | ||
![]() |
af7c6f9fce | ||
![]() |
78534deab6 | ||
![]() |
6710314832 | ||
![]() |
0cd4fa6fa0 | ||
![]() |
065949496e | ||
![]() |
39c82576ae | ||
![]() |
37221a508d | ||
![]() |
6b43a32a10 | ||
![]() |
d7cd1ff142 | ||
![]() |
659d947863 | ||
![]() |
39be7a6288 | ||
![]() |
8ac976c579 | ||
![]() |
70fd432c57 | ||
![]() |
00135f2f49 | ||
![]() |
9b944bc29c | ||
![]() |
d520b3d2a0 | ||
![]() |
6f41d9855b | ||
![]() |
2d7c1da741 | ||
![]() |
c0f45b6b1e | ||
![]() |
7a0025673c | ||
![]() |
ad7ec79903 |
22
README.MD
22
README.MD
@@ -1,7 +1,15 @@
|
|||||||
# Magisk
|
# Magisk
|
||||||
|
[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
|
## Building Environment Requirements
|
||||||
|
|
||||||
1. Python 3.5+: run `build.py` script
|
1. Python 3.5+: run `build.py` script
|
||||||
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
|
2. Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
|
||||||
3. Latest Android SDK: set `ANDROID_HOME` environment variable to the path to Android SDK
|
3. Latest Android SDK: set `ANDROID_HOME` environment variable to the path to Android SDK
|
||||||
@@ -9,13 +17,11 @@
|
|||||||
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
|
5. (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
|
||||||
|
|
||||||
## Building Notes and Instructions
|
## Building Notes and Instructions
|
||||||
1. Building is supported on macOS, Linux, and Windows using the custom NDK: [FrankeNDK](https://github.com/topjohnwu/FrankeNDK).
|
1. Clone sources with submodules: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
|
||||||
2. Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
|
2. Building is supported on macOS, Linux, and Windows. Official releases are built and tested with [FrankeNDK](https://github.com/topjohnwu/FrankeNDK); point `ANDROID_NDK_HOME` to FrankeNDK if you want to use it for compiling.
|
||||||
3. 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`
|
3. Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
|
||||||
4. 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).
|
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).
|
||||||
## Documentation
|
|
||||||
[Link to Documentation](docs/README.MD)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
def configProps = new Properties()
|
def configProps = new Properties()
|
||||||
configProps.load(new FileInputStream(rootProject.file('config.prop')))
|
def configPath = project.hasProperty('configPath') ? project.configPath : rootProject.file('config.prop')
|
||||||
|
configProps.load(new FileInputStream(configPath))
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
@@ -70,14 +71,20 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
fullImplementation project(':utils')
|
fullImplementation project(':utils')
|
||||||
implementation "com.android.support:support-core-utils:${rootProject.ext.supportLibVersion}"
|
implementation "androidx.core:core:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation "com.android.support:preference-v7:${rootProject.ext.supportLibVersion}"
|
fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation "com.android.support:recyclerview-v7:${rootProject.ext.supportLibVersion}"
|
fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation "com.android.support:cardview-v7:${rootProject.ext.supportLibVersion}"
|
fullImplementation "androidx.cardview:cardview:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation "com.android.support:design:${rootProject.ext.supportLibVersion}"
|
fullImplementation "com.google.android.material:material:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation 'com.github.topjohnwu:libsu:2.0.1'
|
fullImplementation 'com.github.topjohnwu:libsu:2.0.2'
|
||||||
fullImplementation 'com.atlassian.commonmark:commonmark:0.11.0'
|
fullImplementation 'com.atlassian.commonmark:commonmark:0.11.0'
|
||||||
fullImplementation 'org.kamranzafar:jtar:2.3'
|
fullImplementation 'org.kamranzafar:jtar:2.3'
|
||||||
fullImplementation 'com.jakewharton:butterknife:8.8.1'
|
|
||||||
fullAnnotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
|
def butterKnifeVersion = '9.0.0-rc1'
|
||||||
|
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}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
11
app/proguard-rules.pro
vendored
11
app/proguard-rules.pro
vendored
@@ -16,19 +16,20 @@
|
|||||||
# public *;
|
# public *;
|
||||||
#}
|
#}
|
||||||
|
|
||||||
# Don't obfuscate, we are open source anyway :)
|
|
||||||
-dontobfuscate
|
|
||||||
|
|
||||||
# BouncyCastle
|
# BouncyCastle
|
||||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; }
|
-keep class org.bouncycastle.jcajce.provider.asymmetric.rsa.**SHA1** { *; }
|
||||||
-keep class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; }
|
-keep class org.bouncycastle.jcajce.provider.asymmetric.RSA** { *; }
|
||||||
-keep class org.bouncycastle.jcajce.provider.digest.SHA1** { *; }
|
-keep class org.bouncycastle.jcajce.provider.digest.SHA1** { *; }
|
||||||
-dontwarn javax.naming.**
|
-dontwarn javax.naming.**
|
||||||
|
|
||||||
# Gson
|
# Snet extention
|
||||||
-keepattributes Signature
|
-keepclassmembers class com.topjohnwu.magisk.utils.ISafetyNetHelper { *; }
|
||||||
|
|
||||||
# Strip logging
|
# Strip logging
|
||||||
-assumenosideeffects class com.topjohnwu.magisk.utils.Logger {
|
-assumenosideeffects class com.topjohnwu.magisk.utils.Logger {
|
||||||
public *** debug(...);
|
public *** debug(...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Excessive obfuscation
|
||||||
|
-repackageclasses 'a'
|
||||||
|
-allowaccessmodification
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.topjohnwu.magisk">
|
package="com.topjohnwu.magisk">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
@@ -8,15 +9,18 @@
|
|||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MagiskManager"
|
android:name="a.q"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/AppTheme"
|
||||||
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
|
|
||||||
|
<!-- Activities -->
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name="a.b"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SplashActivity"
|
android:name="a.c"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@style/SplashTheme">
|
android:theme="@style/SplashTheme">
|
||||||
@@ -26,53 +30,68 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".AboutActivity"
|
android:name="a.d"
|
||||||
android:theme="@style/AppTheme.StatusBar" />
|
android:theme="@style/AppTheme.StatusBar" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".DonationActivity"
|
android:name="a.e"
|
||||||
android:theme="@style/AppTheme.StatusBar"/>
|
android:theme="@style/AppTheme.StatusBar"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".FlashActivity"
|
android:name="a.f"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
android:screenOrientation="nosensor"
|
android:screenOrientation="nosensor"
|
||||||
android:theme="@style/AppTheme.StatusBar" />
|
android:theme="@style/AppTheme.StatusBar" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".NoUIActivity"
|
android:name="a.g"
|
||||||
android:theme="@style/AppTheme.Translucent" />
|
android:theme="@style/AppTheme.Translucent" />
|
||||||
|
|
||||||
|
<!-- Superuser -->
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".superuser.RequestActivity"
|
android:name="a.p"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:taskAffinity="internal.superuser"
|
android:taskAffinity="internal.superuser"
|
||||||
android:theme="@style/SuRequest" />
|
android:theme="@style/SuRequest" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".superuser.RequestActivity"
|
||||||
|
android:excludeFromRecents="true"
|
||||||
|
android:launchMode="singleTask"
|
||||||
|
android:taskAffinity="internal.superuser"
|
||||||
|
android:theme="@style/AppTheme.Translucent" />
|
||||||
|
|
||||||
<receiver android:name=".superuser.SuReceiver" />
|
<receiver android:name=".superuser.SuReceiver" />
|
||||||
<receiver android:name=".receivers.BootReceiver">
|
|
||||||
|
<!-- Receiver -->
|
||||||
|
|
||||||
|
<receiver android:name="a.h">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receivers.PackageReceiver">
|
<receiver android:name="a.i">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||||
<data android:scheme="package" />
|
<data android:scheme="package" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver android:name=".receivers.ManagerUpdate" />
|
<receiver android:name="a.j" />
|
||||||
<receiver android:name=".receivers.RebootReceiver" />
|
<receiver android:name="a.k" />
|
||||||
<receiver android:name=".receivers.ShortcutReceiver">
|
<receiver android:name="a.l">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<!-- Service -->
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.OnBootService"
|
android:name="a.m"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
<service
|
<service
|
||||||
android:name=".services.UpdateCheckService"
|
android:name="a.n"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
10
app/src/full/java/a/a.java
Normal file
10
app/src/full/java/a/a.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.utils.BootSigner;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
public class a extends BootSigner {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/b.java
Normal file
7
app/src/full/java/a/b.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.MainActivity;
|
||||||
|
|
||||||
|
public class b extends MainActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/c.java
Normal file
7
app/src/full/java/a/c.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.SplashActivity;
|
||||||
|
|
||||||
|
public class c extends SplashActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/d.java
Normal file
7
app/src/full/java/a/d.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.AboutActivity;
|
||||||
|
|
||||||
|
public class d extends AboutActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/e.java
Normal file
7
app/src/full/java/a/e.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.DonationActivity;
|
||||||
|
|
||||||
|
public class e extends DonationActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/f.java
Normal file
7
app/src/full/java/a/f.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.FlashActivity;
|
||||||
|
|
||||||
|
public class f extends FlashActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/h.java
Normal file
7
app/src/full/java/a/h.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.receivers.BootReceiver;
|
||||||
|
|
||||||
|
public class h extends BootReceiver {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/i.java
Normal file
7
app/src/full/java/a/i.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.receivers.PackageReceiver;
|
||||||
|
|
||||||
|
public class i extends PackageReceiver {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/j.java
Normal file
7
app/src/full/java/a/j.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||||
|
|
||||||
|
public class j extends ManagerUpdate {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/k.java
Normal file
7
app/src/full/java/a/k.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
||||||
|
|
||||||
|
public class k extends RebootReceiver {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/l.java
Normal file
7
app/src/full/java/a/l.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.receivers.ShortcutReceiver;
|
||||||
|
|
||||||
|
public class l extends ShortcutReceiver {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/m.java
Normal file
7
app/src/full/java/a/m.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.services.OnBootService;
|
||||||
|
|
||||||
|
public class m extends OnBootService {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/n.java
Normal file
7
app/src/full/java/a/n.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||||
|
|
||||||
|
public class n extends UpdateCheckService {
|
||||||
|
/* stub */
|
||||||
|
}
|
22
app/src/full/java/a/o.java
Normal file
22
app/src/full/java/a/o.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
7
app/src/full/java/a/p.java
Normal file
7
app/src/full/java/a/p.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.SuRequestActivity;
|
||||||
|
|
||||||
|
public class p extends SuRequestActivity {
|
||||||
|
/* stub */
|
||||||
|
}
|
7
app/src/full/java/a/q.java
Normal file
7
app/src/full/java/a/q.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package a;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
|
|
||||||
|
public class q extends MagiskManager {
|
||||||
|
/* stub */
|
||||||
|
}
|
@@ -2,9 +2,6 @@ package com.topjohnwu.magisk;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
@@ -15,8 +12,10 @@ import com.topjohnwu.magisk.utils.Utils;
|
|||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class AboutActivity extends BaseActivity {
|
public class AboutActivity extends BaseActivity {
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ public class AboutActivity extends BaseActivity {
|
|||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_about);
|
setContentView(R.layout.activity_about);
|
||||||
ButterKnife.bind(this);
|
new AboutActivity_ViewBinding(this);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
toolbar.setNavigationOnClickListener(view -> finish());
|
toolbar.setNavigationOnClickListener(view -> finish());
|
||||||
|
@@ -41,7 +41,6 @@ public class Const {
|
|||||||
|
|
||||||
/* A list of apps that should not be shown as hide-able */
|
/* A list of apps that should not be shown as hide-able */
|
||||||
public static final List<String> HIDE_BLACKLIST = Arrays.asList(
|
public static final List<String> HIDE_BLACKLIST = Arrays.asList(
|
||||||
"android",
|
|
||||||
Data.MM().getPackageName(),
|
Data.MM().getPackageName(),
|
||||||
"com.google.android.gms"
|
"com.google.android.gms"
|
||||||
);
|
);
|
||||||
@@ -49,11 +48,6 @@ public class Const {
|
|||||||
public static final int USER_ID = Process.myUid() / 100000;
|
public static final int USER_ID = Process.myUid() / 100000;
|
||||||
|
|
||||||
public static final class MAGISK_VER {
|
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 REMOVE_LEGACY_LINK = 1630;
|
||||||
public static final int SEPOL_REFACTOR = 1640;
|
public static final int SEPOL_REFACTOR = 1640;
|
||||||
public static final int FIX_ENV = 1650;
|
public static final int FIX_ENV = 1650;
|
||||||
@@ -141,9 +135,6 @@ public class Const {
|
|||||||
public static final int NAMESPACE_MODE_ISOLATE = 2;
|
public static final int NAMESPACE_MODE_ISOLATE = 2;
|
||||||
public static final int NO_NOTIFICATION = 0;
|
public static final int NO_NOTIFICATION = 0;
|
||||||
public static final int NOTIFICATION_TOAST = 1;
|
public static final int NOTIFICATION_TOAST = 1;
|
||||||
public static final int NOTIFY_NORMAL_LOG = 0;
|
|
||||||
public static final int NOTIFY_USER_TOASTS = 1;
|
|
||||||
public static final int NOTIFY_USER_TO_OWNER = 2;
|
|
||||||
public static final int SU_PROMPT = 0;
|
public static final int SU_PROMPT = 0;
|
||||||
public static final int SU_AUTO_DENY = 1;
|
public static final int SU_AUTO_DENY = 1;
|
||||||
public static final int SU_AUTO_ALLOW = 2;
|
public static final int SU_AUTO_ALLOW = 2;
|
||||||
|
@@ -5,6 +5,14 @@ import android.os.Handler;
|
|||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.util.Xml;
|
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.ShortcutReceiver;
|
||||||
|
import com.topjohnwu.magisk.services.OnBootService;
|
||||||
|
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
@@ -18,11 +26,14 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class Data {
|
public class Data {
|
||||||
// Global app instance
|
// Global app instance
|
||||||
public static WeakReference<MagiskManager> weakApp;
|
public static WeakReference<MagiskManager> weakApp;
|
||||||
public static Handler mainHandler = new Handler(Looper.getMainLooper());
|
public static Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
public static Map<Class, Class> classMap = new HashMap<>();
|
||||||
|
|
||||||
// Current status
|
// Current status
|
||||||
public static String magiskVersionString;
|
public static String magiskVersionString;
|
||||||
@@ -60,12 +71,31 @@ public class Data {
|
|||||||
public static int updateChannel;
|
public static int updateChannel;
|
||||||
public static int repoOrder;
|
public static int repoOrder;
|
||||||
|
|
||||||
|
static {
|
||||||
|
classMap.put(MagiskManager.class, a.q.class);
|
||||||
|
classMap.put(MainActivity.class, a.b.class);
|
||||||
|
classMap.put(SplashActivity.class, a.c.class);
|
||||||
|
classMap.put(AboutActivity.class, a.d.class);
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static void loadMagiskInfo() {
|
public static void loadMagiskInfo() {
|
||||||
try {
|
try {
|
||||||
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
magiskVersionString = ShellUtils.fastCmd("magisk -v").split(":")[0];
|
||||||
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
magiskVersionCode = Integer.parseInt(ShellUtils.fastCmd("magisk -V"));
|
||||||
String s = ShellUtils.fastCmd((magiskVersionCode >= Const.MAGISK_VER.RESETPROP_PERSIST ?
|
String s = ShellUtils.fastCmd(("resetprop -p ") + Const.MAGISKHIDE_PROP);
|
||||||
"resetprop -p " : "getprop ") + Const.MAGISKHIDE_PROP);
|
|
||||||
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
|
magiskHide = s.isEmpty() || Integer.parseInt(s) != 0;
|
||||||
} catch (NumberFormatException ignored) {}
|
} catch (NumberFormatException ignored) {}
|
||||||
}
|
}
|
||||||
|
@@ -2,16 +2,15 @@ package com.topjohnwu.magisk;
|
|||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class DonationActivity extends BaseActivity {
|
public class DonationActivity extends BaseActivity {
|
||||||
|
|
||||||
@@ -28,7 +27,7 @@ public class DonationActivity extends BaseActivity {
|
|||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_donation);
|
setContentView(R.layout.activity_donation);
|
||||||
ButterKnife.bind(this);
|
new DonationActivity_ViewBinding(this);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
toolbar.setNavigationOnClickListener(view -> finish());
|
toolbar.setNavigationOnClickListener(view -> finish());
|
||||||
|
@@ -4,8 +4,6 @@ import android.Manifest;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -31,8 +29,9 @@ import java.util.Calendar;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.ActionBar;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
|
|
||||||
public class FlashActivity extends BaseActivity {
|
public class FlashActivity extends BaseActivity {
|
||||||
@@ -45,11 +44,6 @@ public class FlashActivity extends BaseActivity {
|
|||||||
|
|
||||||
private List<String> logs;
|
private List<String> logs;
|
||||||
|
|
||||||
@OnClick(R.id.no_thanks)
|
|
||||||
void dismiss() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.reboot)
|
@OnClick(R.id.reboot)
|
||||||
void reboot() {
|
void reboot() {
|
||||||
Shell.su("/system/bin/reboot").submit();
|
Shell.su("/system/bin/reboot").submit();
|
||||||
@@ -88,7 +82,8 @@ public class FlashActivity extends BaseActivity {
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_flash);
|
setContentView(R.layout.activity_flash);
|
||||||
ButterKnife.bind(this);
|
new FlashActivity_ViewBinding(this);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
ActionBar ab = getSupportActionBar();
|
ActionBar ab = getSupportActionBar();
|
||||||
if (ab != null) {
|
if (ab != null) {
|
||||||
@@ -145,6 +140,12 @@ public class FlashActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.close)
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
super.finish();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
// Prevent user accidentally press back button
|
// Prevent user accidentally press back button
|
||||||
|
@@ -38,7 +38,7 @@ public class MagiskManager extends ContainerApp {
|
|||||||
Shell.Config.setInitializer(RootUtils.class);
|
Shell.Config.setInitializer(RootUtils.class);
|
||||||
|
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
mDB = MagiskDatabaseHelper.getInstance(this);
|
mDB = MagiskDatabaseHelper.getInstance();
|
||||||
|
|
||||||
String pkg = mDB.getStrings(Const.Key.SU_MANAGER, null);
|
String pkg = mDB.getStrings(Const.Key.SU_MANAGER, null);
|
||||||
if (pkg != null && getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
if (pkg != null && getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||||
|
@@ -3,17 +3,11 @@ package com.topjohnwu.magisk;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.design.widget.NavigationView;
|
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.app.FragmentTransaction;
|
|
||||||
import android.support.v4.widget.DrawerLayout;
|
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
|
||||||
import android.support.v7.widget.Toolbar;
|
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.google.android.material.navigation.NavigationView;
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.fragments.LogFragment;
|
import com.topjohnwu.magisk.fragments.LogFragment;
|
||||||
import com.topjohnwu.magisk.fragments.MagiskFragment;
|
import com.topjohnwu.magisk.fragments.MagiskFragment;
|
||||||
@@ -26,8 +20,13 @@ import com.topjohnwu.magisk.utils.Download;
|
|||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.ActionBarDrawerToggle;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class MainActivity extends BaseActivity
|
public class MainActivity extends BaseActivity
|
||||||
implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber {
|
implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber {
|
||||||
@@ -36,9 +35,9 @@ public class MainActivity extends BaseActivity
|
|||||||
private int mDrawerItem;
|
private int mDrawerItem;
|
||||||
private static boolean fromShortcut = false;
|
private static boolean fromShortcut = false;
|
||||||
|
|
||||||
@BindView(R.id.drawer_layout) DrawerLayout drawer;
|
|
||||||
@BindView(R.id.toolbar) public Toolbar toolbar;
|
@BindView(R.id.toolbar) public Toolbar toolbar;
|
||||||
@BindView(R.id.nav_view) public NavigationView navigationView;
|
@BindView(R.id.drawer_layout) DrawerLayout drawer;
|
||||||
|
@BindView(R.id.nav_view) NavigationView navigationView;
|
||||||
|
|
||||||
private float toolbarElevation;
|
private float toolbarElevation;
|
||||||
|
|
||||||
@@ -50,13 +49,13 @@ public class MainActivity extends BaseActivity
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
if (!mm.hasInit) {
|
if (!mm.hasInit) {
|
||||||
startActivity(new Intent(this, SplashActivity.class));
|
startActivity(new Intent(this, Data.classMap.get(SplashActivity.class)));
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
ButterKnife.bind(this);
|
new MainActivity_ViewBinding(this);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
@@ -112,11 +111,6 @@ public class MainActivity extends BaseActivity
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getSubscribedTopics() {
|
|
||||||
return new int[] {Topic.RELOAD_ACTIVITY};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPublish(int topic, Object[] result) {
|
public void onPublish(int topic, Object[] result) {
|
||||||
recreate();
|
recreate();
|
||||||
@@ -125,7 +119,6 @@ public class MainActivity extends BaseActivity
|
|||||||
public void checkHideSection() {
|
public void checkHideSection() {
|
||||||
Menu menu = navigationView.getMenu();
|
Menu menu = navigationView.getMenu();
|
||||||
menu.findItem(R.id.magiskhide).setVisible(Shell.rootAccess() &&
|
menu.findItem(R.id.magiskhide).setVisible(Shell.rootAccess() &&
|
||||||
Data.magiskVersionCode >= Const.MAGISK_VER.UNIFIED &&
|
|
||||||
mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false));
|
mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false));
|
||||||
menu.findItem(R.id.modules).setVisible(Shell.rootAccess() && Data.magiskVersionCode >= 0);
|
menu.findItem(R.id.modules).setVisible(Shell.rootAccess() && Data.magiskVersionCode >= 0);
|
||||||
menu.findItem(R.id.downloads).setVisible(Download.checkNetworkStatus(this)
|
menu.findItem(R.id.downloads).setVisible(Download.checkNetworkStatus(this)
|
||||||
@@ -196,11 +189,11 @@ public class MainActivity extends BaseActivity
|
|||||||
displayFragment(new SettingsFragment(), true);
|
displayFragment(new SettingsFragment(), true);
|
||||||
break;
|
break;
|
||||||
case R.id.app_about:
|
case R.id.app_about:
|
||||||
startActivity(new Intent(this, AboutActivity.class));
|
startActivity(new Intent(this, Data.classMap.get(AboutActivity.class)));
|
||||||
mDrawerItem = bak;
|
mDrawerItem = bak;
|
||||||
break;
|
break;
|
||||||
case R.id.donation:
|
case R.id.donation:
|
||||||
startActivity(new Intent(this, DonationActivity.class));
|
startActivity(new Intent(this, Data.classMap.get(DonationActivity.class)));
|
||||||
mDrawerItem = bak;
|
mDrawerItem = bak;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
package com.topjohnwu.magisk;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class NoUIActivity extends BaseActivity {
|
public class NoUIActivity extends BaseActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
|
@@ -44,7 +44,7 @@ public class SplashActivity extends BaseActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup shortcuts
|
// Setup shortcuts
|
||||||
sendBroadcast(new Intent(this, ShortcutReceiver.class));
|
sendBroadcast(new Intent(this, Data.classMap.get(ShortcutReceiver.class)));
|
||||||
|
|
||||||
if (Download.checkNetworkStatus(this)) {
|
if (Download.checkNetworkStatus(this)) {
|
||||||
// Fire update check
|
// Fire update check
|
||||||
@@ -58,7 +58,7 @@ public class SplashActivity extends BaseActivity {
|
|||||||
|
|
||||||
mm.hasInit = true;
|
mm.hasInit = true;
|
||||||
|
|
||||||
Intent intent = new Intent(this, MainActivity.class);
|
Intent intent = new Intent(this, Data.classMap.get(MainActivity.class));
|
||||||
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION));
|
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION));
|
||||||
intent.putExtra(BaseActivity.INTENT_PERM, getIntent().getStringExtra(BaseActivity.INTENT_PERM));
|
intent.putExtra(BaseActivity.INTENT_PERM, getIntent().getStringExtra(BaseActivity.INTENT_PERM));
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
|
259
app/src/full/java/com/topjohnwu/magisk/SuRequestActivity.java
Normal file
259
app/src/full/java/com/topjohnwu/magisk/SuRequestActivity.java
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
|
import android.net.LocalSocketAddress;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.CountDownTimer;
|
||||||
|
import android.os.FileObserver;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
|
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 {
|
||||||
|
@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;
|
||||||
|
private CountDownTimer timer;
|
||||||
|
private FingerprintHelper fingerprintHelper;
|
||||||
|
|
||||||
|
class SuConnectorV1 extends SuConnector {
|
||||||
|
|
||||||
|
SuConnectorV1(String name) throws IOException {
|
||||||
|
socket.connect(new LocalSocketAddress(name, LocalSocketAddress.Namespace.FILESYSTEM));
|
||||||
|
new FileObserver(name) {
|
||||||
|
@Override
|
||||||
|
public void onEvent(int fileEvent, String path) {
|
||||||
|
if (fileEvent == FileObserver.DELETE_SELF) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.startWatching();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void response() {
|
||||||
|
try (OutputStream out = getOutputStream()) {
|
||||||
|
out.write((policy.policy == Policy.ALLOW ? "socket:ALLOW" : "socket:DENY").getBytes());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SuConnectorV2 extends SuConnector {
|
||||||
|
|
||||||
|
SuConnectorV2(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getDarkTheme() {
|
||||||
|
return R.style.SuRequest_Dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish() {
|
||||||
|
if (timer != null)
|
||||||
|
timer.cancel();
|
||||||
|
if (fingerprintHelper != null)
|
||||||
|
fingerprintHelper.cancel();
|
||||||
|
super.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (policy != null) {
|
||||||
|
handleAction(Policy.DENY);
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
|
||||||
|
PackageManager pm = getPackageManager();
|
||||||
|
mm.mDB.clearOutdated();
|
||||||
|
|
||||||
|
// Get policy
|
||||||
|
Intent intent = getIntent();
|
||||||
|
try {
|
||||||
|
connector = intent.getIntExtra("version", 1) == 1 ?
|
||||||
|
new SuConnectorV1(intent.getStringExtra("socket")) :
|
||||||
|
new SuConnectorV2(intent.getStringExtra("socket"));
|
||||||
|
Bundle bundle = connector.readSocketInput();
|
||||||
|
int uid = Integer.parseInt(bundle.getString("uid"));
|
||||||
|
policy = mm.mDB.getPolicy(uid);
|
||||||
|
if (policy == null) {
|
||||||
|
policy = new Policy(uid, pm);
|
||||||
|
}
|
||||||
|
} catch (IOException | PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Never allow com.topjohnwu.magisk (could be malware)
|
||||||
|
if (TextUtils.equals(policy.packageName, Const.ORIG_PKG_NAME)) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (Data.suResponseType) {
|
||||||
|
case Const.Value.SU_AUTO_DENY:
|
||||||
|
handleAction(Policy.DENY, 0);
|
||||||
|
return;
|
||||||
|
case Const.Value.SU_AUTO_ALLOW:
|
||||||
|
handleAction(Policy.ALLOW, 0);
|
||||||
|
return;
|
||||||
|
case Const.Value.SU_PROMPT:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not interactive, response directly
|
||||||
|
if (policy.policy != Policy.INTERACTIVE) {
|
||||||
|
handleAction();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_request);
|
||||||
|
new SuRequestActivity_ViewBinding(this);
|
||||||
|
|
||||||
|
appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||||
|
appNameView.setText(policy.appName);
|
||||||
|
packageNameView.setText(policy.packageName);
|
||||||
|
|
||||||
|
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
|
||||||
|
R.array.allow_timeout, android.R.layout.simple_spinner_item);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
timeout.setAdapter(adapter);
|
||||||
|
|
||||||
|
timer = new CountDownTimer(Data.suRequestTimeout * 1000, 1000) {
|
||||||
|
@Override
|
||||||
|
public void onTick(long millisUntilFinished) {
|
||||||
|
deny_btn.setText(getString(R.string.deny_with_str, "(" + millisUntilFinished / 1000 + ")"));
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
|
||||||
|
handleAction(Policy.DENY);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint();
|
||||||
|
|
||||||
|
if (useFingerprint) {
|
||||||
|
try {
|
||||||
|
fingerprintHelper = new FingerprintHelper() {
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
||||||
|
warning.setText(errString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
||||||
|
warning.setText(helpString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
||||||
|
handleAction(Policy.ALLOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAuthenticationFailed() {
|
||||||
|
warning.setText(R.string.auth_fail);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fingerprintHelper.authenticate();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
useFingerprint = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!useFingerprint) {
|
||||||
|
grant_btn.setOnClickListener(v -> {
|
||||||
|
handleAction(Policy.ALLOW);
|
||||||
|
timer.cancel();
|
||||||
|
});
|
||||||
|
grant_btn.requestFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
grant_btn.setVisibility(useFingerprint ? View.GONE : View.VISIBLE);
|
||||||
|
fingerprintImg.setVisibility(useFingerprint ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
deny_btn.setOnClickListener(v -> {
|
||||||
|
handleAction(Policy.DENY);
|
||||||
|
timer.cancel();
|
||||||
|
});
|
||||||
|
suPopup.setOnClickListener(v -> cancelTimeout());
|
||||||
|
timeout.setOnTouchListener((v, event) -> cancelTimeout());
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean cancelTimeout() {
|
||||||
|
timer.cancel();
|
||||||
|
deny_btn.setText(getString(R.string.deny));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAction() {
|
||||||
|
connector.response();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAction(int action) {
|
||||||
|
handleAction(action, Const.Value.timeoutList[timeout.getSelectedItemPosition()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleAction(int action, int time) {
|
||||||
|
policy.policy = action;
|
||||||
|
if (time >= 0) {
|
||||||
|
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
||||||
|
mm.mDB.addPolicy(policy);
|
||||||
|
}
|
||||||
|
handleAction();
|
||||||
|
}
|
||||||
|
}
|
@@ -3,11 +3,7 @@ package com.topjohnwu.magisk.adapters;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -19,8 +15,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -28,8 +24,9 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
|
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
|
||||||
|
|
||||||
@@ -53,25 +50,12 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
return new ViewHolder(v);
|
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() {
|
private void loadApps() {
|
||||||
fullList = pm.getInstalledApplications(0);
|
fullList = pm.getInstalledApplications(0);
|
||||||
hideList = Shell.su("magiskhide --ls").exec().getOut();
|
hideList = Shell.su("magiskhide --ls").exec().getOut();
|
||||||
for (Iterator<ApplicationInfo> i = fullList.iterator(); i.hasNext(); ) {
|
for (Iterator<ApplicationInfo> i = fullList.iterator(); i.hasNext(); ) {
|
||||||
ApplicationInfo info = i.next();
|
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();
|
i.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +63,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
boolean ah = hideList.contains(a.packageName);
|
boolean ah = hideList.contains(a.packageName);
|
||||||
boolean bh = hideList.contains(b.packageName);
|
boolean bh = hideList.contains(b.packageName);
|
||||||
if (ah == bh) {
|
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) {
|
} else if (ah) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
@@ -94,7 +79,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
ApplicationInfo info = showList.get(position);
|
ApplicationInfo info = showList.get(position);
|
||||||
|
|
||||||
holder.appIcon.setImageDrawable(info.loadIcon(pm));
|
holder.appIcon.setImageDrawable(info.loadIcon(pm));
|
||||||
holder.appName.setText(getLabel(info));
|
holder.appName.setText(Utils.getAppLabel(info, pm));
|
||||||
holder.appPackage.setText(info.packageName);
|
holder.appPackage.setText(info.packageName);
|
||||||
|
|
||||||
holder.checkBox.setOnCheckedChangeListener(null);
|
holder.checkBox.setOnCheckedChangeListener(null);
|
||||||
@@ -132,11 +117,11 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
|
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.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) {
|
private boolean lowercaseContains(String s, CharSequence filter) {
|
||||||
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
||||||
@@ -150,7 +135,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
showList = new ArrayList<>();
|
showList = new ArrayList<>();
|
||||||
String filter = constraint.toString().toLowerCase();
|
String filter = constraint.toString().toLowerCase();
|
||||||
for (ApplicationInfo info : fullList) {
|
for (ApplicationInfo info : fullList) {
|
||||||
if (lowercaseContains(getLabel(info), filter)
|
if (lowercaseContains(Utils.getAppLabel(info, pm), filter)
|
||||||
|| lowercaseContains(info.packageName, filter)) {
|
|| lowercaseContains(info.packageName, filter)) {
|
||||||
showList.add(info);
|
showList.add(info);
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.adapters;
|
package com.topjohnwu.magisk.adapters;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -11,6 +9,7 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||||
import com.topjohnwu.magisk.container.Module;
|
import com.topjohnwu.magisk.container.Module;
|
||||||
@@ -18,8 +17,9 @@ import com.topjohnwu.superuser.Shell;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
|
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
mList = list;
|
mList = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module, parent, false);
|
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module, parent, false);
|
||||||
@@ -46,9 +47,9 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
String noInfo = context.getString(R.string.no_info_provided);
|
String noInfo = context.getString(R.string.no_info_provided);
|
||||||
|
|
||||||
holder.title.setText(module.getName());
|
holder.title.setText(module.getName());
|
||||||
holder.versionName.setText( TextUtils.isEmpty(version) ? noInfo : version);
|
holder.versionName.setText(TextUtils.isEmpty(version) ? noInfo : version);
|
||||||
holder.author.setText( TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
|
holder.author.setText(TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
|
||||||
holder.description.setText( TextUtils.isEmpty(description) ? noInfo : description);
|
holder.description.setText(TextUtils.isEmpty(description) ? noInfo : description);
|
||||||
|
|
||||||
holder.checkBox.setOnCheckedChangeListener(null);
|
holder.checkBox.setOnCheckedChangeListener(null);
|
||||||
holder.checkBox.setChecked(module.isEnabled());
|
holder.checkBox.setChecked(module.isEnabled());
|
||||||
@@ -114,7 +115,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
|
|
||||||
ViewHolder(View itemView) {
|
ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new ModulesAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||||
|
|
||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
checkBox.setEnabled(false);
|
checkBox.setEnabled(false);
|
||||||
|
@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.adapters;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -11,19 +9,23 @@ import android.widget.ImageView;
|
|||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||||
import com.topjohnwu.magisk.components.ExpandableView;
|
import com.topjohnwu.magisk.components.ExpandableView;
|
||||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
import com.topjohnwu.magisk.container.Policy;
|
||||||
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
|
import com.topjohnwu.magisk.database.MagiskDatabaseHelper;
|
||||||
|
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> {
|
public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder> {
|
||||||
|
|
||||||
@@ -38,6 +40,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
|||||||
this.pm = pm;
|
this.pm = pm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_policy, parent, false);
|
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_policy, parent, false);
|
||||||
@@ -63,14 +66,34 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
|||||||
holder.appName.setText(policy.appName);
|
holder.appName.setText(policy.appName);
|
||||||
holder.packageName.setText(policy.packageName);
|
holder.packageName.setText(policy.packageName);
|
||||||
holder.appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
holder.appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||||
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
|
||||||
if ((isChecked && policy.policy == Policy.DENY) ||
|
holder.notificationSwitch.setOnCheckedChangeListener(null);
|
||||||
(!isChecked && policy.policy == Policy.ALLOW)) {
|
holder.loggingSwitch.setOnCheckedChangeListener(null);
|
||||||
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
|
|
||||||
String message = v.getContext().getString(
|
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
||||||
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
|
holder.notificationSwitch.setChecked(policy.notification);
|
||||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
holder.loggingSwitch.setChecked(policy.logging);
|
||||||
dbHelper.updatePolicy(policy);
|
|
||||||
|
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 (Data.suFingerprint) {
|
||||||
|
holder.masterSwitch.setChecked(!isChecked);
|
||||||
|
FingerprintHelper.showAuthDialog((Activity) v.getContext(), () -> {
|
||||||
|
holder.masterSwitch.setChecked(isChecked);
|
||||||
|
r.run();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
r.run();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||||
@@ -107,9 +130,6 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
|||||||
.setNegativeButton(R.string.no_thanks, null)
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.show());
|
.show());
|
||||||
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
|
||||||
holder.notificationSwitch.setChecked(policy.notification);
|
|
||||||
holder.loggingSwitch.setChecked(policy.logging);
|
|
||||||
|
|
||||||
// Hide for now
|
// Hide for now
|
||||||
holder.moreInfo.setVisibility(View.GONE);
|
holder.moreInfo.setVisibility(View.GONE);
|
||||||
@@ -137,7 +157,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
|||||||
|
|
||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new PolicyAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||||
container.expandLayout = expandLayout;
|
container.expandLayout = expandLayout;
|
||||||
setupExpandable();
|
setupExpandable();
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.adapters;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@@ -25,8 +24,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
|
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
|
||||||
|
|
||||||
@@ -89,11 +88,16 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
|
|||||||
Repo repo = repoPairs.get(section).second.get(position);
|
Repo repo = repoPairs.get(section).second.get(position);
|
||||||
Context context = holder.itemView.getContext();
|
Context context = holder.itemView.getContext();
|
||||||
|
|
||||||
holder.title.setText(repo.getName());
|
String name = repo.getName();
|
||||||
holder.versionName.setText(repo.getVersion());
|
String version = repo.getVersion();
|
||||||
String author = repo.getAuthor();
|
String author = repo.getAuthor();
|
||||||
holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
|
String description = repo.getDescription();
|
||||||
holder.description.setText(repo.getDescription());
|
String noInfo = context.getString(R.string.no_info_provided);
|
||||||
|
|
||||||
|
holder.title.setText(TextUtils.isEmpty(name) ? noInfo : name);
|
||||||
|
holder.versionName.setText(TextUtils.isEmpty(version) ? noInfo : version);
|
||||||
|
holder.author.setText(TextUtils.isEmpty(author) ? noInfo : context.getString(R.string.author, author));
|
||||||
|
holder.description.setText(TextUtils.isEmpty(description) ? noInfo : description);
|
||||||
holder.updateTime.setText(context.getString(R.string.updated_on, repo.getLastUpdateString()));
|
holder.updateTime.setText(context.getString(R.string.updated_on, repo.getLastUpdateString()));
|
||||||
|
|
||||||
holder.infoLayout.setOnClickListener(v ->
|
holder.infoLayout.setOnClickListener(v ->
|
||||||
@@ -165,7 +169,7 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
|
|||||||
|
|
||||||
SectionHolder(View itemView) {
|
SectionHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new ReposAdapter$SectionHolder_ViewBinding(this, itemView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +185,7 @@ public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, R
|
|||||||
|
|
||||||
RepoHolder(View itemView) {
|
RepoHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new ReposAdapter$RepoHolder_ViewBinding(this, itemView);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
package com.topjohnwu.magisk.adapters;
|
package com.topjohnwu.magisk.adapters;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C extends RecyclerView.ViewHolder>
|
public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C extends RecyclerView.ViewHolder>
|
||||||
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.adapters;
|
package com.topjohnwu.magisk.adapters;
|
||||||
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -20,8 +19,8 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> {
|
public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> {
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
|||||||
|
|
||||||
SectionHolder(View itemView) {
|
SectionHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new SuLogAdapter$SectionHolder_ViewBinding(this, itemView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +141,7 @@ public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, S
|
|||||||
|
|
||||||
LogViewHolder(View itemView) {
|
LogViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
ButterKnife.bind(this, itemView);
|
new SuLogAdapter$LogViewHolder_ViewBinding(this, itemView);
|
||||||
container.expandLayout = expandLayout;
|
container.expandLayout = expandLayout;
|
||||||
setupExpandable();
|
setupExpandable();
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
package com.topjohnwu.magisk.adapters;
|
package com.topjohnwu.magisk.adapters;
|
||||||
|
|
||||||
|
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
import android.support.v4.app.FragmentManager;
|
|
||||||
import android.support.v4.app.FragmentPagerAdapter;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
|
|
||||||
public class TabFragmentAdapter extends FragmentPagerAdapter {
|
public class TabFragmentAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
private List<Fragment> fragmentList;
|
private List<Fragment> fragmentList;
|
||||||
|
@@ -4,7 +4,6 @@ import android.app.Activity;
|
|||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
@@ -44,6 +43,8 @@ import java.net.HttpURLConnection;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
private static final int PATCH_MODE = 0;
|
private static final int PATCH_MODE = 0;
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -18,6 +17,8 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
|
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
|
||||||
|
|
||||||
private String mTitle;
|
private String mTitle;
|
||||||
|
@@ -111,6 +111,7 @@ public class PatchAPK {
|
|||||||
repack.delete();
|
repack.delete();
|
||||||
|
|
||||||
mm.mDB.setStrings(Const.Key.SU_MANAGER, pkg);
|
mm.mDB.setStrings(Const.Key.SU_MANAGER, pkg);
|
||||||
|
mm.mDB.flush();
|
||||||
Data.exportPrefs();
|
Data.exportPrefs();
|
||||||
RootUtils.uninstallPkg(Const.ORIG_PKG_NAME);
|
RootUtils.uninstallPkg(Const.ORIG_PKG_NAME);
|
||||||
|
|
||||||
|
@@ -4,7 +4,6 @@ import android.Manifest;
|
|||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
@@ -35,6 +34,8 @@ import java.util.jar.JarEntry;
|
|||||||
import java.util.jar.JarInputStream;
|
import java.util.jar.JarInputStream;
|
||||||
import java.util.jar.JarOutputStream;
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
|
public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
|
||||||
|
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
@@ -140,7 +141,7 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
|
|||||||
if (result) {
|
if (result) {
|
||||||
Uri uri = Uri.fromFile(mFile);
|
Uri uri = Uri.fromFile(mFile);
|
||||||
if (mInstall) {
|
if (mInstall) {
|
||||||
Intent intent = new Intent(activity, FlashActivity.class);
|
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class));
|
||||||
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -66,17 +66,15 @@ public class UpdateRepos {
|
|||||||
|
|
||||||
for (int i = 0; i < jsonArray.length(); i++) {
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
JSONObject rawRepo = jsonArray.getJSONObject(i);
|
JSONObject rawRepo = jsonArray.getJSONObject(i);
|
||||||
String id = rawRepo.getString("description");
|
String id = rawRepo.getString("name");
|
||||||
String name = rawRepo.getString("name");
|
|
||||||
Date date = dateFormat.parse(rawRepo.getString("pushed_at"));
|
Date date = dateFormat.parse(rawRepo.getString("pushed_at"));
|
||||||
Set<String> set = Collections.synchronizedSet(cached);
|
|
||||||
threadPool.execute(() -> {
|
threadPool.execute(() -> {
|
||||||
Repo repo = mm.repoDB.getRepo(id);
|
Repo repo = mm.repoDB.getRepo(id);
|
||||||
try {
|
try {
|
||||||
if (repo == null)
|
if (repo == null)
|
||||||
repo = new Repo(name);
|
repo = new Repo(id);
|
||||||
else
|
else
|
||||||
set.remove(id);
|
cached.remove(id);
|
||||||
repo.update(date);
|
repo.update(date);
|
||||||
mm.repoDB.addRepo(repo);
|
mm.repoDB.addRepo(repo);
|
||||||
} catch (Repo.IllegalRepoException e) {
|
} catch (Repo.IllegalRepoException e) {
|
||||||
@@ -141,7 +139,7 @@ public class UpdateRepos {
|
|||||||
public void exec(boolean force) {
|
public void exec(boolean force) {
|
||||||
Topic.reset(Topic.REPO_LOAD_DONE);
|
Topic.reset(Topic.REPO_LOAD_DONE);
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||||
cached = mm.repoDB.getRepoIDSet();
|
cached = Collections.synchronizedSet(mm.repoDB.getRepoIDSet());
|
||||||
threadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE);
|
threadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE);
|
||||||
|
|
||||||
if (loadPage(0)) {
|
if (loadPage(0)) {
|
||||||
|
@@ -29,7 +29,6 @@ import android.widget.TextView;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author dvdandroid
|
* @author dvdandroid
|
||||||
@@ -52,7 +51,7 @@ public class AboutCardRow extends LinearLayout {
|
|||||||
public AboutCardRow(Context context, AttributeSet attrs, int defStyleAttr) {
|
public AboutCardRow(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
LayoutInflater.from(context).inflate(R.layout.info_item_row, this);
|
LayoutInflater.from(context).inflate(R.layout.info_item_row, this);
|
||||||
ButterKnife.bind(this, this);
|
new AboutCardRow_ViewBinding(this, this);
|
||||||
|
|
||||||
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AboutCardRow, 0, 0);
|
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.AboutCardRow, 0, 0);
|
||||||
String title;
|
String title;
|
||||||
@@ -69,8 +68,6 @@ public class AboutCardRow extends LinearLayout {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOnClickListener(OnClickListener l) {
|
public void setOnClickListener(OnClickListener l) {
|
||||||
super.setOnClickListener(l);
|
|
||||||
|
|
||||||
mView.setOnClickListener(l);
|
mView.setOnClickListener(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,15 +1,18 @@
|
|||||||
package com.topjohnwu.magisk.components;
|
package com.topjohnwu.magisk.components;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v4.app.Fragment;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import butterknife.Unbinder;
|
||||||
|
|
||||||
public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
||||||
|
|
||||||
public MagiskManager mm;
|
public MagiskManager mm;
|
||||||
|
protected Unbinder unbinder = null;
|
||||||
|
|
||||||
public BaseFragment() {
|
public BaseFragment() {
|
||||||
mm = Data.MM();
|
mm = Data.MM();
|
||||||
@@ -27,6 +30,13 @@ public class BaseFragment extends Fragment implements Topic.AutoSubscriber {
|
|||||||
super.onPause();
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (unbinder != null)
|
||||||
|
unbinder.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startActivityForResult(Intent intent, int requestCode) {
|
public void startActivityForResult(Intent intent, int requestCode) {
|
||||||
startActivityForResult(intent, requestCode, this::onActivityResult);
|
startActivityForResult(intent, requestCode, this::onActivityResult);
|
||||||
|
@@ -2,11 +2,6 @@ package com.topjohnwu.magisk.components;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.annotation.StyleRes;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -15,8 +10,12 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.annotation.StyleRes;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class CustomAlertDialog extends AlertDialog.Builder {
|
public class CustomAlertDialog extends AlertDialog.Builder {
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ public class CustomAlertDialog extends AlertDialog.Builder {
|
|||||||
@BindView(R.id.neutral) public Button neutral;
|
@BindView(R.id.neutral) public Button neutral;
|
||||||
|
|
||||||
ViewHolder(View v) {
|
ViewHolder(View v) {
|
||||||
ButterKnife.bind(this, v);
|
new CustomAlertDialog$ViewHolder_ViewBinding(this, v);
|
||||||
messageView.setVisibility(View.GONE);
|
messageView.setVisibility(View.GONE);
|
||||||
negative.setVisibility(View.GONE);
|
negative.setVisibility(View.GONE);
|
||||||
positive.setVisibility(View.GONE);
|
positive.setVisibility(View.GONE);
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.components;
|
package com.topjohnwu.magisk.components;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.asyncs.InstallMagisk;
|
import com.topjohnwu.magisk.asyncs.InstallMagisk;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class EnvFixDialog extends CustomAlertDialog {
|
public class EnvFixDialog extends CustomAlertDialog {
|
||||||
|
|
||||||
public EnvFixDialog(@NonNull Activity activity) {
|
public EnvFixDialog(@NonNull Activity activity) {
|
||||||
|
@@ -4,9 +4,6 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.StyleRes;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -15,6 +12,10 @@ import com.topjohnwu.magisk.R;
|
|||||||
import com.topjohnwu.magisk.utils.LocaleManager;
|
import com.topjohnwu.magisk.utils.LocaleManager;
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StyleRes;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
public abstract class FlavorActivity extends AppCompatActivity implements Topic.AutoSubscriber {
|
public abstract class FlavorActivity extends AppCompatActivity implements Topic.AutoSubscriber {
|
||||||
|
|
||||||
private ActivityResultListener activityResultListener;
|
private ActivityResultListener activityResultListener;
|
||||||
@@ -42,11 +43,11 @@ public abstract class FlavorActivity extends AppCompatActivity implements Topic.
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
Topic.subscribe(this);
|
Topic.subscribe(this);
|
||||||
if (Data.isDarkTheme && getDarkTheme() != -1) {
|
if (Data.isDarkTheme && getDarkTheme() != -1) {
|
||||||
setTheme(getDarkTheme());
|
setTheme(getDarkTheme());
|
||||||
}
|
}
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
package com.topjohnwu.magisk.components;
|
package com.topjohnwu.magisk.components;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
@@ -17,6 +17,8 @@ import com.topjohnwu.magisk.utils.Utils;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
class InstallMethodDialog extends AlertDialog.Builder {
|
class InstallMethodDialog extends AlertDialog.Builder {
|
||||||
|
|
||||||
InstallMethodDialog(BaseActivity activity, List<String> options) {
|
InstallMethodDialog(BaseActivity activity, List<String> options) {
|
||||||
@@ -26,23 +28,21 @@ class InstallMethodDialog extends AlertDialog.Builder {
|
|||||||
Intent intent;
|
Intent intent;
|
||||||
switch (idx) {
|
switch (idx) {
|
||||||
case 1:
|
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);
|
Utils.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
|
||||||
intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*");
|
intent = new Intent(Intent.ACTION_GET_CONTENT).setType("*/*");
|
||||||
activity.startActivityForResult(intent, Const.ID.SELECT_BOOT,
|
activity.runWithPermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, () ->
|
||||||
(requestCode, resultCode, data) -> {
|
activity.startActivityForResult(intent, Const.ID.SELECT_BOOT,
|
||||||
if (requestCode == Const.ID.SELECT_BOOT &&
|
(requestCode, resultCode, data) -> {
|
||||||
resultCode == BaseActivity.RESULT_OK && data != null) {
|
if (requestCode == Const.ID.SELECT_BOOT &&
|
||||||
Intent i = new Intent(activity, FlashActivity.class)
|
resultCode == Activity.RESULT_OK && data != null) {
|
||||||
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
|
Intent i = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
|
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
|
||||||
activity.startActivity(i);
|
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
|
||||||
}
|
activity.startActivity(i);
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
||||||
@@ -55,22 +55,22 @@ class InstallMethodDialog extends AlertDialog.Builder {
|
|||||||
}, Data.magiskLink, filename);
|
}, Data.magiskLink, filename);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
intent = new Intent(activity, FlashActivity.class)
|
intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_MAGISK);
|
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_MAGISK);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
new CustomAlertDialog(activity)
|
new CustomAlertDialog(activity)
|
||||||
.setTitle(R.string.warning)
|
.setTitle(R.string.warning)
|
||||||
.setMessage(R.string.install_inactive_slot_msg)
|
.setMessage(R.string.install_inactive_slot_msg)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setPositiveButton(R.string.yes, (d, i) -> {
|
.setPositiveButton(R.string.yes, (d, i) -> {
|
||||||
Intent it = new Intent(activity, FlashActivity.class)
|
Intent it = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT);
|
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_INACTIVE_SLOT);
|
||||||
activity.startActivity(it);
|
activity.startActivity(it);
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
.show();
|
.show();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ package com.topjohnwu.magisk.components;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
@@ -13,6 +12,8 @@ import com.topjohnwu.magisk.asyncs.MarkDownWindow;
|
|||||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class ManagerInstallDialog extends CustomAlertDialog {
|
public class ManagerInstallDialog extends CustomAlertDialog {
|
||||||
|
|
||||||
public ManagerInstallDialog(@NonNull BaseActivity activity) {
|
public ManagerInstallDialog(@NonNull BaseActivity activity) {
|
||||||
@@ -25,7 +26,7 @@ public class ManagerInstallDialog extends CustomAlertDialog {
|
|||||||
setCancelable(true);
|
setCancelable(true);
|
||||||
setPositiveButton(R.string.install, (d, i) -> activity.runWithPermission(
|
setPositiveButton(R.string.install, (d, i) -> activity.runWithPermission(
|
||||||
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
||||||
Intent intent = new Intent(mm, ManagerUpdate.class);
|
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_LINK, Data.managerLink);
|
||||||
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
||||||
mm.sendBroadcast(intent);
|
mm.sendBroadcast(intent);
|
||||||
|
@@ -2,14 +2,15 @@ package com.topjohnwu.magisk.components;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
public class SnackbarMaker {
|
public class SnackbarMaker {
|
||||||
|
|
||||||
public static Snackbar make(Activity activity, CharSequence text, int duration) {
|
public static Snackbar make(Activity activity, CharSequence text, int duration) {
|
||||||
@@ -34,7 +35,7 @@ public class SnackbarMaker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setup(Snackbar snack) {
|
private static void setup(Snackbar snack) {
|
||||||
TextView text = snack.getView().findViewById(android.support.design.R.id.snackbar_text);
|
TextView text = snack.getView().findViewById(com.google.android.material.R.id.snackbar_text);
|
||||||
text.setMaxLines(Integer.MAX_VALUE);
|
text.setMaxLines(Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,7 +5,6 @@ import android.app.ProgressDialog;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@@ -19,6 +18,8 @@ import com.topjohnwu.magisk.utils.Download;
|
|||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class UninstallDialog extends CustomAlertDialog {
|
public class UninstallDialog extends CustomAlertDialog {
|
||||||
|
|
||||||
public UninstallDialog(@NonNull Activity activity) {
|
public UninstallDialog(@NonNull Activity activity) {
|
||||||
@@ -44,7 +45,7 @@ public class UninstallDialog extends CustomAlertDialog {
|
|||||||
Download.receive(activity, new DownloadReceiver() {
|
Download.receive(activity, new DownloadReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadDone(Context context, Uri uri) {
|
public void onDownloadDone(Context context, Uri uri) {
|
||||||
Intent intent = new Intent(context, FlashActivity.class)
|
Intent intent = new Intent(context, Data.classMap.get(FlashActivity.class))
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.setData(uri)
|
.setData(uri)
|
||||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);
|
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);
|
||||||
|
@@ -1,29 +1,35 @@
|
|||||||
package com.topjohnwu.magisk.container;
|
package com.topjohnwu.magisk.container;
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public abstract class BaseModule implements Comparable<BaseModule> {
|
public abstract class BaseModule implements Comparable<BaseModule> {
|
||||||
|
|
||||||
private String mId = null, mName, mVersion, mAuthor, mDescription;
|
private String mId, mName, mVersion, mAuthor, mDescription;
|
||||||
private int mVersionCode = -1, minMagiskVersion = -1;
|
private int mVersionCode = -1, minMagiskVersion = -1;
|
||||||
|
|
||||||
protected BaseModule() {}
|
protected BaseModule() {
|
||||||
|
mId = mName = mVersion = mAuthor = mDescription = "";
|
||||||
|
}
|
||||||
|
|
||||||
protected BaseModule(Cursor c) {
|
protected BaseModule(Cursor c) {
|
||||||
mId = c.getString(c.getColumnIndex("id"));
|
mId = nonNull(c.getString(c.getColumnIndex("id")));
|
||||||
mName = c.getString(c.getColumnIndex("name"));
|
mName = nonNull(c.getString(c.getColumnIndex("name")));
|
||||||
mVersion = c.getString(c.getColumnIndex("version"));
|
mVersion = nonNull(c.getString(c.getColumnIndex("version")));
|
||||||
mVersionCode = c.getInt(c.getColumnIndex("versionCode"));
|
mVersionCode = c.getInt(c.getColumnIndex("versionCode"));
|
||||||
mAuthor = c.getString(c.getColumnIndex("author"));
|
mAuthor = nonNull(c.getString(c.getColumnIndex("author")));
|
||||||
mDescription = c.getString(c.getColumnIndex("description"));
|
mDescription = nonNull(c.getString(c.getColumnIndex("description")));
|
||||||
minMagiskVersion = c.getInt(c.getColumnIndex("minMagisk"));
|
minMagiskVersion = c.getInt(c.getColumnIndex("minMagisk"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String nonNull(String s) {
|
||||||
|
return s == null ? "" : s;
|
||||||
|
}
|
||||||
|
|
||||||
public ContentValues getContentValues() {
|
public ContentValues getContentValues() {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put("id", mId);
|
values.put("id", mId);
|
||||||
|
@@ -4,7 +4,10 @@ import android.content.ContentValues;
|
|||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
|
||||||
public class Policy implements Comparable<Policy>{
|
public class Policy implements Comparable<Policy>{
|
||||||
@@ -25,7 +28,7 @@ public class Policy implements Comparable<Policy>{
|
|||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
packageName = pkgs[0];
|
packageName = pkgs[0];
|
||||||
info = pm.getApplicationInfo(packageName, 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 {
|
public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||||
|
@@ -14,16 +14,14 @@ import java.util.Date;
|
|||||||
|
|
||||||
public class Repo extends BaseModule {
|
public class Repo extends BaseModule {
|
||||||
|
|
||||||
private String repoName;
|
|
||||||
private Date mLastUpdate;
|
private Date mLastUpdate;
|
||||||
|
|
||||||
public Repo(String name) {
|
public Repo(String id) {
|
||||||
repoName = name;
|
setId(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Repo(Cursor c) {
|
public Repo(Cursor c) {
|
||||||
super(c);
|
super(c);
|
||||||
repoName = c.getString(c.getColumnIndex("repo_name"));
|
|
||||||
mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update")));
|
mLastUpdate = new Date(c.getLong(c.getColumnIndex("last_update")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,17 +30,14 @@ public class Repo extends BaseModule {
|
|||||||
try {
|
try {
|
||||||
parseProps(props);
|
parseProps(props);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new IllegalRepoException("Repo [" + repoName + "] parse error: " + e.getMessage());
|
throw new IllegalRepoException("Repo [" + getId() + "] parse error: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getId() == null) {
|
|
||||||
throw new IllegalRepoException("Repo [" + repoName + "] does not contain id");
|
|
||||||
}
|
|
||||||
if (getVersionCode() < 0) {
|
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()) {
|
if (getMinMagiskVersion() < Const.MIN_MODULE_VER()) {
|
||||||
Logger.debug("Repo [" + repoName + "] is outdated");
|
Logger.debug("Repo [" + getId() + "] is outdated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,25 +49,20 @@ public class Repo extends BaseModule {
|
|||||||
@Override
|
@Override
|
||||||
public ContentValues getContentValues() {
|
public ContentValues getContentValues() {
|
||||||
ContentValues values = super.getContentValues();
|
ContentValues values = super.getContentValues();
|
||||||
values.put("repo_name", repoName);
|
|
||||||
values.put("last_update", mLastUpdate.getTime());
|
values.put("last_update", mLastUpdate.getTime());
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRepoName() {
|
|
||||||
return repoName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getZipUrl() {
|
public String getZipUrl() {
|
||||||
return String.format(Const.Url.ZIP_URL, repoName);
|
return String.format(Const.Url.ZIP_URL, getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getManifestUrl() {
|
public String getManifestUrl() {
|
||||||
return String.format(Const.Url.FILE_URL, repoName, "module.prop");
|
return String.format(Const.Url.FILE_URL, getId(), "module.prop");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDetailUrl() {
|
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() {
|
public String getLastUpdateString() {
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.container;
|
package com.topjohnwu.magisk.container;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -9,6 +7,8 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class ValueSortedMap<K, V extends Comparable<? super V>> extends HashMap<K, V> {
|
public class ValueSortedMap<K, V extends Comparable<? super V>> extends HashMap<K, V> {
|
||||||
|
|
||||||
private List<V> sorted = new ArrayList<>();
|
private List<V> sorted = new ArrayList<>();
|
||||||
|
@@ -7,7 +7,6 @@ import android.database.Cursor;
|
|||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@@ -29,6 +28,8 @@ import java.util.Collections;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class MagiskDatabaseHelper {
|
public class MagiskDatabaseHelper {
|
||||||
|
|
||||||
private static final int DATABASE_VER = 6;
|
private static final int DATABASE_VER = 6;
|
||||||
@@ -37,26 +38,30 @@ public class MagiskDatabaseHelper {
|
|||||||
private static final String LOG_TABLE = "logs";
|
private static final String LOG_TABLE = "logs";
|
||||||
private static final String SETTINGS_TABLE = "settings";
|
private static final String SETTINGS_TABLE = "settings";
|
||||||
private static final String STRINGS_TABLE = "strings";
|
private static final String STRINGS_TABLE = "strings";
|
||||||
|
private static final File MANAGER_DB =
|
||||||
|
new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
|
||||||
|
|
||||||
private PackageManager pm;
|
private PackageManager pm;
|
||||||
private SQLiteDatabase db;
|
private SQLiteDatabase db;
|
||||||
private MagiskManager mm;
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static MagiskDatabaseHelper getInstance(MagiskManager mm) {
|
public static MagiskDatabaseHelper getInstance() {
|
||||||
try {
|
try {
|
||||||
return new MagiskDatabaseHelper(mm);
|
return new MagiskDatabaseHelper();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Let's cleanup everything and try again
|
// Let's cleanup everything and try again
|
||||||
Shell.su("db_clean '*'").exec();
|
Shell.su("db_clean '*'").exec();
|
||||||
return new MagiskDatabaseHelper(mm);
|
return new MagiskDatabaseHelper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MagiskDatabaseHelper(MagiskManager context) {
|
private MagiskDatabaseHelper() {
|
||||||
mm = context;
|
pm = Data.MM().getPackageManager();
|
||||||
pm = mm.getPackageManager();
|
init();
|
||||||
db = openDatabase(mm);
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
db = openDatabase();
|
||||||
db.disableWriteAheadLogging();
|
db.disableWriteAheadLogging();
|
||||||
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
|
int version = Data.magiskVersionCode >= Const.MAGISK_VER.DBVER_SIX ? DATABASE_VER : OLD_DATABASE_VER;
|
||||||
int curVersion = db.getVersion();
|
int curVersion = db.getVersion();
|
||||||
@@ -70,48 +75,37 @@ public class MagiskDatabaseHelper {
|
|||||||
clearOutdated();
|
clearOutdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SQLiteDatabase openDatabase(MagiskManager mm) {
|
private SQLiteDatabase openDatabase() {
|
||||||
final File DB_FILE = new File(Utils.fmt("/sbin/.core/db-%d/magisk.db", Const.USER_ID));
|
MagiskManager mm = Data.MM();
|
||||||
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
Context de = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||||
? mm.createDeviceProtectedStorageContext() : mm;
|
? mm.createDeviceProtectedStorageContext() : mm;
|
||||||
if (!DB_FILE.canWrite()) {
|
if (!MANAGER_DB.canWrite()) {
|
||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
// We don't want the app to crash, create a db and return
|
// We don't want the app to crash, create a db and return
|
||||||
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
||||||
}
|
}
|
||||||
// Cleanup
|
// Cleanup
|
||||||
Shell.su("db_clean " + Const.USER_ID).exec();
|
Shell.su("db_clean " + Const.USER_ID).exec();
|
||||||
if (Data.magiskVersionCode < Const.MAGISK_VER.FBE_AWARE) {
|
// Global database
|
||||||
// Super old legacy mode
|
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
|
||||||
return mm.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
mm.deleteDatabase("su.db");
|
||||||
} else if (Data.magiskVersionCode < Const.MAGISK_VER.HIDDEN_PATH) {
|
de.deleteDatabase("su.db");
|
||||||
// Legacy mode with FBE aware
|
if (Data.magiskVersionCode < Const.MAGISK_VER.SEPOL_REFACTOR) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
// We need some additional policies on old versions
|
||||||
de.moveDatabaseFrom(mm, "su.db");
|
Shell.su("db_sepatch").exec();
|
||||||
}
|
}
|
||||||
return de.openOrCreateDatabase("su.db", Context.MODE_PRIVATE, null);
|
if (!GLOBAL_DB.exists()) {
|
||||||
} else {
|
Shell.su("db_init").exec();
|
||||||
// Global database
|
SQLiteDatabase.openOrCreateDatabase(GLOBAL_DB, null).close();
|
||||||
final SuFile GLOBAL_DB = new SuFile("/data/adb/magisk.db");
|
Shell.su("db_restore").exec();
|
||||||
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();
|
Shell.su("db_setup " + Process.myUid()).exec();
|
||||||
}
|
}
|
||||||
// Not using legacy mode, open the mounted global DB
|
// Not using legacy mode, open the mounted global DB
|
||||||
return SQLiteDatabase.openOrCreateDatabase(DB_FILE, null);
|
return SQLiteDatabase.openOrCreateDatabase(MANAGER_DB, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion) {
|
private void onUpgrade(SQLiteDatabase db, int oldVersion) {
|
||||||
if (oldVersion == 0) {
|
if (oldVersion == 0) {
|
||||||
createTables(db);
|
createTables(db);
|
||||||
oldVersion = 3;
|
oldVersion = 3;
|
||||||
@@ -146,13 +140,13 @@ public class MagiskDatabaseHelper {
|
|||||||
}
|
}
|
||||||
if (oldVersion == 5) {
|
if (oldVersion == 5) {
|
||||||
setSettings(Const.Key.SU_FINGERPRINT,
|
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;
|
++oldVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove everything, we do not support downgrade
|
// 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);
|
Utils.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG);
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE);
|
db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE);
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE);
|
db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE);
|
||||||
@@ -181,6 +175,11 @@ public class MagiskDatabaseHelper {
|
|||||||
"(key TEXT, value INT, PRIMARY KEY(key))");
|
"(key TEXT, value INT, PRIMARY KEY(key))");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
db.close();
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
public void clearOutdated() {
|
public void clearOutdated() {
|
||||||
// Clear outdated policies
|
// Clear outdated policies
|
||||||
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
|
db.delete(POLICY_TABLE, Utils.fmt("until > 0 AND until < %d", System.currentTimeMillis() / 1000), null);
|
||||||
|
@@ -16,7 +16,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
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 static final String TABLE_NAME = "repos";
|
||||||
|
|
||||||
private SQLiteDatabase mDb;
|
private SQLiteDatabase mDb;
|
||||||
@@ -40,21 +40,14 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
try {
|
if (oldVersion != newVersion) {
|
||||||
if (oldVersion < 3) {
|
// Nuke old DB and create new table
|
||||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
|
||||||
db.execSQL(
|
db.execSQL(
|
||||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||||
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " +
|
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " +
|
||||||
"author TEXT, description TEXT, repo_name TEXT, last_update INT, " +
|
"author TEXT, description TEXT, last_update INT, PRIMARY KEY(id))");
|
||||||
"PRIMARY KEY(id))");
|
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
||||||
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
|
|
||||||
oldVersion = 3;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
// Reset database
|
|
||||||
onDowngrade(db, DATABASE_VER, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +68,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeRepo(Repo repo) {
|
public void removeRepo(Repo repo) {
|
||||||
mDb.delete(TABLE_NAME, "repo_name=?", new String[] { repo.getRepoName() });
|
removeRepo(repo.getId());
|
||||||
notifyAdapter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeRepo(Iterable<String> list) {
|
public void removeRepo(Iterable<String> list) {
|
||||||
|
@@ -2,12 +2,11 @@ package com.topjohnwu.magisk.fragments;
|
|||||||
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.design.widget.TabLayout;
|
|
||||||
import android.support.v4.view.ViewPager;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MainActivity;
|
import com.topjohnwu.magisk.MainActivity;
|
||||||
@@ -15,14 +14,11 @@ import com.topjohnwu.magisk.R;
|
|||||||
import com.topjohnwu.magisk.adapters.TabFragmentAdapter;
|
import com.topjohnwu.magisk.adapters.TabFragmentAdapter;
|
||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
|
|
||||||
|
import androidx.viewpager.widget.ViewPager;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class LogFragment extends BaseFragment {
|
public class LogFragment extends BaseFragment {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
|
|
||||||
@BindView(R.id.container) ViewPager viewPager;
|
@BindView(R.id.container) ViewPager viewPager;
|
||||||
@BindView(R.id.tab) TabLayout tab;
|
@BindView(R.id.tab) TabLayout tab;
|
||||||
|
|
||||||
@@ -31,7 +27,7 @@ public class LogFragment extends BaseFragment {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
// Inflate the layout for this fragment
|
// Inflate the layout for this fragment
|
||||||
View v = inflater.inflate(R.layout.fragment_log, container, false);
|
View v = inflater.inflate(R.layout.fragment_log, container, false);
|
||||||
unbinder = ButterKnife.bind(this, v);
|
unbinder = new LogFragment_ViewBinding(this, v);
|
||||||
|
|
||||||
((MainActivity) requireActivity()).toolbar.setElevation(0);
|
((MainActivity) requireActivity()).toolbar.setElevation(0);
|
||||||
|
|
||||||
@@ -48,11 +44,4 @@ public class LogFragment extends BaseFragment {
|
|||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,6 @@ import android.content.Context;
|
|||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.CardView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -41,20 +36,22 @@ import com.topjohnwu.magisk.utils.Topic;
|
|||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.cardview.widget.CardView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import butterknife.BindColor;
|
import butterknife.BindColor;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class MagiskFragment extends BaseFragment
|
public class MagiskFragment extends BaseFragment
|
||||||
implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber {
|
implements SwipeRefreshLayout.OnRefreshListener, ExpandableView, Topic.Subscriber {
|
||||||
|
|
||||||
private Container expandableContainer = new Container();
|
private Container expandableContainer = new Container();
|
||||||
private Unbinder unbinder;
|
|
||||||
private static boolean shownDialog = false;
|
private static boolean shownDialog = false;
|
||||||
|
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) public SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
|
|
||||||
@BindView(R.id.core_only_notice) CardView coreOnlyNotice;
|
@BindView(R.id.core_only_notice) CardView coreOnlyNotice;
|
||||||
|
|
||||||
@@ -85,7 +82,7 @@ public class MagiskFragment extends BaseFragment
|
|||||||
@BindColor(R.color.red500) int colorBad;
|
@BindColor(R.color.red500) int colorBad;
|
||||||
@BindColor(R.color.green500) int colorOK;
|
@BindColor(R.color.green500) int colorOK;
|
||||||
@BindColor(R.color.yellow500) int colorWarn;
|
@BindColor(R.color.yellow500) int colorWarn;
|
||||||
@BindColor(R.color.grey500) int colorNeutral;
|
@BindColor(R.color.green500) int colorNeutral;
|
||||||
@BindColor(R.color.blue500) int colorInfo;
|
@BindColor(R.color.blue500) int colorInfo;
|
||||||
|
|
||||||
@OnClick(R.id.safetyNet_title)
|
@OnClick(R.id.safetyNet_title)
|
||||||
@@ -136,7 +133,7 @@ public class MagiskFragment extends BaseFragment
|
|||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
View v = inflater.inflate(R.layout.fragment_magisk, container, false);
|
View v = inflater.inflate(R.layout.fragment_magisk, container, false);
|
||||||
unbinder = ButterKnife.bind(this, v);
|
unbinder = new MagiskFragment_ViewBinding(this, v);
|
||||||
requireActivity().setTitle(R.string.magisk);
|
requireActivity().setTitle(R.string.magisk);
|
||||||
|
|
||||||
expandableContainer.expandLayout = expandLayout;
|
expandableContainer.expandLayout = expandLayout;
|
||||||
@@ -196,12 +193,6 @@ public class MagiskFragment extends BaseFragment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Container getContainer() {
|
public Container getContainer() {
|
||||||
return expandableContainer;
|
return expandableContainer;
|
||||||
@@ -223,11 +214,10 @@ public class MagiskFragment extends BaseFragment
|
|||||||
|
|
||||||
boolean hasNetwork = Download.checkNetworkStatus(mm);
|
boolean hasNetwork = Download.checkNetworkStatus(mm);
|
||||||
boolean hasRoot = Shell.rootAccess();
|
boolean hasRoot = Shell.rootAccess();
|
||||||
boolean isUpToDate = Data.magiskVersionCode > Const.MAGISK_VER.UNIFIED;
|
|
||||||
|
|
||||||
magiskUpdate.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
|
magiskUpdate.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
|
||||||
installOptionCard.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);
|
coreOnlyNotice.setVisibility(mm.prefs.getBoolean(Const.Key.COREONLY, false) ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
int image, color;
|
int image, color;
|
||||||
|
@@ -1,10 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.fragments;
|
package com.topjohnwu.magisk.fragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -17,13 +13,14 @@ import com.topjohnwu.magisk.adapters.ApplicationAdapter;
|
|||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber {
|
public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
SearchView search;
|
SearchView search;
|
||||||
@@ -42,7 +39,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
|
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
|
||||||
unbinder = ButterKnife.bind(this, view);
|
unbinder = new MagiskHideFragment_ViewBinding(this, view);
|
||||||
|
|
||||||
appAdapter = new ApplicationAdapter(requireActivity());
|
appAdapter = new ApplicationAdapter(requireActivity());
|
||||||
recyclerView.setAdapter(appAdapter);
|
recyclerView.setAdapter(appAdapter);
|
||||||
@@ -76,12 +73,6 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
search.setOnQueryTextListener(searchListener);
|
search.setOnQueryTextListener(searchListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getSubscribedTopics() {
|
public int[] getSubscribedTopics() {
|
||||||
return new int[] {Topic.MAGISK_HIDE_DONE};
|
return new int[] {Topic.MAGISK_HIDE_DONE};
|
||||||
|
@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.fragments;
|
|||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
@@ -16,6 +14,7 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
@@ -28,14 +27,11 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class MagiskLogFragment extends BaseFragment {
|
public class MagiskLogFragment extends BaseFragment {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
|
|
||||||
@BindView(R.id.txtLog) TextView txtLog;
|
@BindView(R.id.txtLog) TextView txtLog;
|
||||||
@BindView(R.id.svLog) ScrollView svLog;
|
@BindView(R.id.svLog) ScrollView svLog;
|
||||||
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
|
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
|
||||||
@@ -45,7 +41,7 @@ public class MagiskLogFragment extends BaseFragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_magisk_log, container, false);
|
View view = inflater.inflate(R.layout.fragment_magisk_log, container, false);
|
||||||
unbinder = ButterKnife.bind(this, view);
|
unbinder = new MagiskLogFragment_ViewBinding(this, view);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
txtLog.setTextIsSelectable(true);
|
txtLog.setTextIsSelectable(true);
|
||||||
return view;
|
return view;
|
||||||
@@ -63,12 +59,6 @@ public class MagiskLogFragment extends BaseFragment {
|
|||||||
readLogs();
|
readLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.menu_log, menu);
|
inflater.inflate(R.menu.menu_log, menu);
|
||||||
@@ -91,7 +81,7 @@ public class MagiskLogFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readLogs() {
|
private void readLogs() {
|
||||||
Shell.su("cat " + Const.MAGISK_LOG + " | tail -n 5000").submit(result -> {
|
Shell.su("cat " + Const.MAGISK_LOG + " | tail -n 5000").submit(result -> {
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
if (result.getOut().isEmpty())
|
if (result.getOut().isEmpty())
|
||||||
@@ -103,7 +93,7 @@ public class MagiskLogFragment extends BaseFragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveLogs() {
|
private void saveLogs() {
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
String filename = Utils.fmt("magisk_log_%04d%02d%02d_%02d%02d%02d.log",
|
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.YEAR), now.get(Calendar.MONTH) + 1,
|
||||||
@@ -121,7 +111,7 @@ public class MagiskLogFragment extends BaseFragment {
|
|||||||
SnackbarMaker.make(txtLog, logFile.getPath(), Snackbar.LENGTH_SHORT).show());
|
SnackbarMaker.make(txtLog, logFile.getPath(), Snackbar.LENGTH_SHORT).show());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearLogs() {
|
private void clearLogs() {
|
||||||
Shell.su("echo -n > " + Const.MAGISK_LOG).submit();
|
Shell.su("echo -n > " + Const.MAGISK_LOG).submit();
|
||||||
txtLog.setText(R.string.log_is_empty);
|
txtLog.setText(R.string.log_is_empty);
|
||||||
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
|
||||||
|
@@ -4,10 +4,6 @@ import android.Manifest;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -17,6 +13,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.FlashActivity;
|
import com.topjohnwu.magisk.FlashActivity;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
||||||
@@ -30,19 +27,21 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||||
|
|
||||||
@OnClick(R.id.fab)
|
@OnClick(R.id.fab)
|
||||||
public void selectFile() {
|
void selectFile() {
|
||||||
runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
runWithPermission(new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, () -> {
|
||||||
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
intent.setType("application/zip");
|
intent.setType("application/zip");
|
||||||
@@ -56,7 +55,7 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_modules, container, false);
|
View view = inflater.inflate(R.layout.fragment_modules, container, false);
|
||||||
unbinder = ButterKnife.bind(this, view);
|
unbinder = new ModulesFragment_ViewBinding(this, view);
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
mSwipeRefreshLayout.setOnRefreshListener(() -> {
|
mSwipeRefreshLayout.setOnRefreshListener(() -> {
|
||||||
@@ -95,18 +94,12 @@ public class ModulesFragment extends BaseFragment implements Topic.Subscriber {
|
|||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
|
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
|
||||||
// Get the URI of the selected file
|
// Get the URI of the selected file
|
||||||
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
Intent intent = new Intent(getActivity(), Data.classMap.get(FlashActivity.class));
|
||||||
intent.setData(data.getData()).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
intent.setData(data.getData()).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
inflater.inflate(R.menu.menu_reboot, menu);
|
inflater.inflate(R.menu.menu_reboot, menu);
|
||||||
|
@@ -2,10 +2,6 @@ package com.topjohnwu.magisk.fragments;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -26,13 +22,14 @@ import com.topjohnwu.magisk.utils.Topic;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
@@ -49,7 +46,7 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_repos, container, false);
|
View view = inflater.inflate(R.layout.fragment_repos, container, false);
|
||||||
unbinder = ButterKnife.bind(this, view);
|
unbinder = new ReposFragment_ViewBinding(this, view);
|
||||||
|
|
||||||
mSwipeRefreshLayout.setRefreshing(true);
|
mSwipeRefreshLayout.setRefreshing(true);
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
@@ -123,6 +120,5 @@ public class ReposFragment extends BaseFragment implements Topic.Subscriber {
|
|||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
mm.repoDB.unregisterAdapter();
|
mm.repoDB.unregisterAdapter();
|
||||||
unbinder.unbind();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,23 +1,11 @@
|
|||||||
package com.topjohnwu.magisk.fragments;
|
package com.topjohnwu.magisk.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
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.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v14.preference.SwitchPreference;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
import android.support.v7.preference.ListPreference;
|
|
||||||
import android.support.v7.preference.Preference;
|
|
||||||
import android.support.v7.preference.PreferenceCategory;
|
|
||||||
import android.support.v7.preference.PreferenceFragmentCompat;
|
|
||||||
import android.support.v7.preference.PreferenceScreen;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -30,7 +18,6 @@ import com.topjohnwu.magisk.MagiskManager;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
|
||||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||||
import com.topjohnwu.magisk.utils.Download;
|
import com.topjohnwu.magisk.utils.Download;
|
||||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
||||||
@@ -44,6 +31,17 @@ import com.topjohnwu.superuser.ShellUtils;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.preference.ListPreference;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceCategory;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.PreferenceGroupAdapter;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
import androidx.preference.SwitchPreference;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat
|
public class SettingsFragment extends PreferenceFragmentCompat
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
implements SharedPreferences.OnSharedPreferenceChangeListener,
|
||||||
Topic.Subscriber, Topic.AutoSubscriber {
|
Topic.Subscriber, Topic.AutoSubscriber {
|
||||||
@@ -126,7 +124,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
fingerprint.setSummary(R.string.disable_fingerprint);
|
fingerprint.setSummary(R.string.disable_fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Data.magiskVersionCode >= Const.MAGISK_VER.MANAGER_HIDE) {
|
if (Shell.rootAccess()) {
|
||||||
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME)) {
|
||||||
hideManager.setOnPreferenceClickListener((pref) -> {
|
hideManager.setOnPreferenceClickListener((pref) -> {
|
||||||
PatchAPK.hideManager(requireActivity());
|
PatchAPK.hideManager(requireActivity());
|
||||||
@@ -173,8 +171,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
prefScreen.removePreference(magiskCategory);
|
prefScreen.removePreference(magiskCategory);
|
||||||
generalCatagory.removePreference(hideManager);
|
generalCatagory.removePreference(hideManager);
|
||||||
} else if (Data.magiskVersionCode < Const.MAGISK_VER.UNIFIED) {
|
|
||||||
prefScreen.removePreference(magiskCategory);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +217,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
setSummary();
|
setSummary();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case Const.Key.DARK_THEME:
|
case Const.Key.DARK_THEME:
|
||||||
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
requireActivity().recreate();
|
||||||
break;
|
break;
|
||||||
case Const.Key.COREONLY:
|
case Const.Key.COREONLY:
|
||||||
if (prefs.getBoolean(key, false)) {
|
if (prefs.getBoolean(key, false)) {
|
||||||
@@ -253,7 +249,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
break;
|
break;
|
||||||
case Const.Key.LOCALE:
|
case Const.Key.LOCALE:
|
||||||
LocaleManager.setLocale(mm);
|
LocaleManager.setLocale(mm);
|
||||||
Topic.publish(false, Topic.RELOAD_ACTIVITY);
|
requireActivity().recreate();
|
||||||
break;
|
break;
|
||||||
case Const.Key.UPDATE_CHANNEL:
|
case Const.Key.UPDATE_CHANNEL:
|
||||||
case Const.Key.CUSTOM_CHANNEL:
|
case Const.Key.CUSTOM_CHANNEL:
|
||||||
@@ -272,54 +268,11 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
case Const.Key.SU_FINGERPRINT:
|
case Const.Key.SU_FINGERPRINT:
|
||||||
boolean checked = ((SwitchPreference) preference).isChecked();
|
boolean checked = ((SwitchPreference) preference).isChecked();
|
||||||
((SwitchPreference) preference).setChecked(!checked);
|
((SwitchPreference) preference).setChecked(!checked);
|
||||||
CustomAlertDialog dialog = new CustomAlertDialog(requireActivity());
|
FingerprintHelper.showAuthDialog(requireActivity(), () -> {
|
||||||
CustomAlertDialog.ViewHolder vh = dialog.getViewHolder();
|
((SwitchPreference) preference).setChecked(checked);
|
||||||
Drawable fingerprint = getResources().getDrawable(R.drawable.ic_fingerprint);
|
Data.suFingerprint = checked;
|
||||||
fingerprint.setBounds(0, 0, Utils.dpInPx(50), Utils.dpInPx(50));
|
mm.mDB.setSettings(key, checked ? 1 : 0);
|
||||||
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);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -352,4 +305,38 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
public int[] getSubscribedTopics() {
|
public int[] getSubscribedTopics() {
|
||||||
return new int[] {Topic.LOCALE_FETCH_DONE};
|
return new int[] {Topic.LOCALE_FETCH_DONE};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||||
|
return new PreferenceGroupAdapter(preferenceScreen) {
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
|
||||||
|
super.onBindViewHolder(holder, position);
|
||||||
|
Preference preference = getItem(position);
|
||||||
|
if (preference instanceof PreferenceCategory)
|
||||||
|
setZeroPaddingToLayoutChildren(holder.itemView);
|
||||||
|
else {
|
||||||
|
View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
|
||||||
|
if (iconFrame != null) {
|
||||||
|
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setZeroPaddingToLayoutChildren(View view) {
|
||||||
|
if (!(view instanceof ViewGroup))
|
||||||
|
return;
|
||||||
|
ViewGroup viewGroup = (ViewGroup) view;
|
||||||
|
int childCount = viewGroup.getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
setZeroPaddingToLayoutChildren(viewGroup.getChildAt(i));
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||||
|
viewGroup.setPaddingRelative(0, viewGroup.getPaddingTop(), viewGroup.getPaddingEnd(), viewGroup.getPaddingBottom());
|
||||||
|
else
|
||||||
|
viewGroup.setPadding(0, viewGroup.getPaddingTop(), viewGroup.getPaddingRight(), viewGroup.getPaddingBottom());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.fragments;
|
package com.topjohnwu.magisk.fragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -15,16 +13,15 @@ import com.topjohnwu.magisk.R;
|
|||||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class SuLogFragment extends BaseFragment {
|
public class SuLogFragment extends BaseFragment {
|
||||||
|
|
||||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
private SuLogAdapter adapter;
|
private SuLogAdapter adapter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -44,7 +41,7 @@ public class SuLogFragment extends BaseFragment {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
// Inflate the layout for this fragment
|
// Inflate the layout for this fragment
|
||||||
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
||||||
unbinder = ButterKnife.bind(this, v);
|
unbinder = new SuLogFragment_ViewBinding(this, v);
|
||||||
adapter = new SuLogAdapter(mm.mDB);
|
adapter = new SuLogAdapter(mm.mDB);
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
@@ -79,10 +76,4 @@ public class SuLogFragment extends BaseFragment {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.fragments;
|
|||||||
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -16,24 +14,24 @@ import com.topjohnwu.magisk.container.Policy;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import butterknife.Unbinder;
|
|
||||||
|
|
||||||
public class SuperuserFragment extends BaseFragment {
|
public class SuperuserFragment extends BaseFragment {
|
||||||
|
|
||||||
private Unbinder unbinder;
|
|
||||||
private PackageManager pm;
|
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||||
|
|
||||||
|
private PackageManager pm;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_superuser, container, false);
|
View view = inflater.inflate(R.layout.fragment_superuser, container, false);
|
||||||
unbinder = ButterKnife.bind(this, view);
|
unbinder = new SuperuserFragment_ViewBinding(this, view);
|
||||||
|
|
||||||
pm = getActivity().getPackageManager();
|
pm = requireActivity().getPackageManager();
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,12 +47,6 @@ public class SuperuserFragment extends BaseFragment {
|
|||||||
displayPolicyList();
|
displayPolicyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyView() {
|
|
||||||
super.onDestroyView();
|
|
||||||
unbinder.unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayPolicyList() {
|
private void displayPolicyList() {
|
||||||
List<Policy> policyList = mm.mDB.getPolicyList(pm);
|
List<Policy> policyList = mm.mDB.getPolicyList(pm);
|
||||||
|
|
||||||
|
@@ -5,14 +5,31 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.Data;
|
||||||
|
import com.topjohnwu.magisk.SuRequestActivity;
|
||||||
import com.topjohnwu.magisk.services.OnBootService;
|
import com.topjohnwu.magisk.services.OnBootService;
|
||||||
|
import com.topjohnwu.magisk.utils.SuConnector;
|
||||||
|
|
||||||
public class BootReceiver extends BroadcastReceiver {
|
public class BootReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED))
|
if (TextUtils.equals(intent.getAction(), Intent.ACTION_BOOT_COMPLETED)) {
|
||||||
OnBootService.enqueueWork(context);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,6 @@ import android.content.pm.ShortcutInfo;
|
|||||||
import android.content.pm.ShortcutManager;
|
import android.content.pm.ShortcutManager;
|
||||||
import android.graphics.drawable.Icon;
|
import android.graphics.drawable.Icon;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.support.annotation.RequiresApi;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -18,6 +17,8 @@ import com.topjohnwu.superuser.Shell;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
public class ShortcutReceiver extends BroadcastReceiver {
|
public class ShortcutReceiver extends BroadcastReceiver {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
@@ -36,7 +37,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
|||||||
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
Data.multiuserMode == Const.Value.MULTIUSER_MODE_OWNER_MANAGED)) {
|
||||||
shortCuts.add(new ShortcutInfo.Builder(mm, "superuser")
|
shortCuts.add(new ShortcutInfo.Builder(mm, "superuser")
|
||||||
.setShortLabel(mm.getString(R.string.superuser))
|
.setShortLabel(mm.getString(R.string.superuser))
|
||||||
.setIntent(new Intent(mm, SplashActivity.class)
|
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||||
.putExtra(Const.Key.OPEN_SECTION, "superuser")
|
.putExtra(Const.Key.OPEN_SECTION, "superuser")
|
||||||
.setAction(Intent.ACTION_VIEW)
|
.setAction(Intent.ACTION_VIEW)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||||
@@ -44,11 +45,10 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
|||||||
.setRank(0)
|
.setRank(0)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
if (root && Data.magiskVersionCode >= Const.MAGISK_VER.UNIFIED
|
if (root && mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false)) {
|
||||||
&& mm.prefs.getBoolean(Const.Key.MAGISKHIDE, false)) {
|
|
||||||
shortCuts.add(new ShortcutInfo.Builder(mm, "magiskhide")
|
shortCuts.add(new ShortcutInfo.Builder(mm, "magiskhide")
|
||||||
.setShortLabel(mm.getString(R.string.magiskhide))
|
.setShortLabel(mm.getString(R.string.magiskhide))
|
||||||
.setIntent(new Intent(mm, SplashActivity.class)
|
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||||
.putExtra(Const.Key.OPEN_SECTION, "magiskhide")
|
.putExtra(Const.Key.OPEN_SECTION, "magiskhide")
|
||||||
.setAction(Intent.ACTION_VIEW)
|
.setAction(Intent.ACTION_VIEW)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||||
@@ -59,7 +59,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
|||||||
if (!mm.prefs.getBoolean(Const.Key.COREONLY, false) && root && Data.magiskVersionCode >= 0) {
|
if (!mm.prefs.getBoolean(Const.Key.COREONLY, false) && root && Data.magiskVersionCode >= 0) {
|
||||||
shortCuts.add(new ShortcutInfo.Builder(mm, "modules")
|
shortCuts.add(new ShortcutInfo.Builder(mm, "modules")
|
||||||
.setShortLabel(mm.getString(R.string.modules))
|
.setShortLabel(mm.getString(R.string.modules))
|
||||||
.setIntent(new Intent(mm, SplashActivity.class)
|
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||||
.putExtra(Const.Key.OPEN_SECTION, "modules")
|
.putExtra(Const.Key.OPEN_SECTION, "modules")
|
||||||
.setAction(Intent.ACTION_VIEW)
|
.setAction(Intent.ACTION_VIEW)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||||
@@ -68,7 +68,7 @@ public class ShortcutReceiver extends BroadcastReceiver {
|
|||||||
.build());
|
.build());
|
||||||
shortCuts.add(new ShortcutInfo.Builder(mm, "downloads")
|
shortCuts.add(new ShortcutInfo.Builder(mm, "downloads")
|
||||||
.setShortLabel(mm.getString(R.string.download))
|
.setShortLabel(mm.getString(R.string.download))
|
||||||
.setIntent(new Intent(mm, SplashActivity.class)
|
.setIntent(new Intent(mm, Data.classMap.get(SplashActivity.class))
|
||||||
.putExtra(Const.Key.OPEN_SECTION, "downloads")
|
.putExtra(Const.Key.OPEN_SECTION, "downloads")
|
||||||
.setAction(Intent.ACTION_VIEW)
|
.setAction(Intent.ACTION_VIEW)
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK))
|
||||||
|
@@ -2,18 +2,20 @@ package com.topjohnwu.magisk.services;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.v4.app.JobIntentService;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.utils.NotificationMgr;
|
import com.topjohnwu.magisk.utils.NotificationMgr;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.app.JobIntentService;
|
||||||
|
|
||||||
public class OnBootService extends JobIntentService {
|
public class OnBootService extends JobIntentService {
|
||||||
|
|
||||||
public static void enqueueWork(Context context) {
|
public static void enqueueWork(Context context) {
|
||||||
enqueueWork(context, OnBootService.class, Const.ID.ONBOOT_SERVICE_ID, new Intent());
|
enqueueWork(context, Data.classMap.get(OnBootService.class), Const.ID.ONBOOT_SERVICE_ID, new Intent());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,297 +1,21 @@
|
|||||||
package com.topjohnwu.magisk.superuser;
|
package com.topjohnwu.magisk.superuser;
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
|
||||||
import android.net.LocalSocket;
|
|
||||||
import android.net.LocalSocketAddress;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.CountDownTimer;
|
|
||||||
import android.os.FileObserver;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.SuRequestActivity;
|
||||||
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
|
||||||
import com.topjohnwu.magisk.utils.FingerprintHelper;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
|
|
||||||
public class RequestActivity extends BaseActivity {
|
public class RequestActivity extends BaseActivity {
|
||||||
|
|
||||||
@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 String socketPath;
|
|
||||||
private LocalSocket socket;
|
|
||||||
private PackageManager pm;
|
|
||||||
|
|
||||||
private boolean hasTimeout;
|
|
||||||
private Policy policy;
|
|
||||||
private CountDownTimer timer;
|
|
||||||
private FingerprintHelper fingerprintHelper;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getDarkTheme() {
|
|
||||||
return R.style.SuRequest_Dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
|
Intent intent = new Intent(this, Data.classMap.get(SuRequestActivity.class))
|
||||||
|
.putExtra("socket", getIntent().getStringExtra("socket"))
|
||||||
pm = getPackageManager();
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
mm.mDB.clearOutdated();
|
startActivity(intent);
|
||||||
|
|
||||||
Intent intent = getIntent();
|
|
||||||
socketPath = intent.getStringExtra("socket");
|
|
||||||
hasTimeout = intent.getBooleanExtra("timeout", true);
|
|
||||||
|
|
||||||
new FileObserver(socketPath) {
|
|
||||||
@Override
|
|
||||||
public void onEvent(int fileEvent, String path) {
|
|
||||||
if (fileEvent == FileObserver.DELETE_SELF) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.startWatching();
|
|
||||||
|
|
||||||
new SocketManager(this).exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish() {
|
|
||||||
if (timer != null)
|
|
||||||
timer.cancel();
|
|
||||||
if (fingerprintHelper != null)
|
|
||||||
fingerprintHelper.cancel();
|
|
||||||
super.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean cancelTimeout() {
|
|
||||||
timer.cancel();
|
|
||||||
deny_btn.setText(getString(R.string.deny));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showRequest() {
|
|
||||||
switch (Data.suResponseType) {
|
|
||||||
case Const.Value.SU_AUTO_DENY:
|
|
||||||
handleAction(Policy.DENY, 0);
|
|
||||||
return;
|
|
||||||
case Const.Value.SU_AUTO_ALLOW:
|
|
||||||
handleAction(Policy.ALLOW, 0);
|
|
||||||
return;
|
|
||||||
case Const.Value.SU_PROMPT:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not interactive, response directly
|
|
||||||
if (policy.policy != Policy.INTERACTIVE) {
|
|
||||||
handleAction();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_request);
|
|
||||||
ButterKnife.bind(this);
|
|
||||||
|
|
||||||
appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
|
||||||
appNameView.setText(policy.appName);
|
|
||||||
packageNameView.setText(policy.packageName);
|
|
||||||
|
|
||||||
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
|
|
||||||
R.array.allow_timeout, android.R.layout.simple_spinner_item);
|
|
||||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
|
||||||
timeout.setAdapter(adapter);
|
|
||||||
|
|
||||||
timer = new CountDownTimer(Data.suRequestTimeout * 1000, 1000) {
|
|
||||||
@Override
|
|
||||||
public void onTick(long millisUntilFinished) {
|
|
||||||
deny_btn.setText(getString(R.string.deny_with_str, "(" + millisUntilFinished / 1000 + ")"));
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onFinish() {
|
|
||||||
deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
|
|
||||||
handleAction(Policy.DENY);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
boolean useFingerprint = Data.suFingerprint && FingerprintHelper.canUseFingerprint();
|
|
||||||
|
|
||||||
if (useFingerprint) {
|
|
||||||
try {
|
|
||||||
fingerprintHelper = new FingerprintHelper() {
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationError(int errorCode, CharSequence errString) {
|
|
||||||
warning.setText(errString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
|
|
||||||
warning.setText(helpString);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
|
|
||||||
handleAction(Policy.ALLOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAuthenticationFailed() {
|
|
||||||
warning.setText(R.string.auth_fail);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fingerprintHelper.authenticate();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
useFingerprint = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!useFingerprint) {
|
|
||||||
grant_btn.setOnClickListener(v -> {
|
|
||||||
handleAction(Policy.ALLOW);
|
|
||||||
timer.cancel();
|
|
||||||
});
|
|
||||||
grant_btn.requestFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
grant_btn.setVisibility(useFingerprint ? View.GONE : View.VISIBLE);
|
|
||||||
fingerprintImg.setVisibility(useFingerprint ? View.VISIBLE : View.GONE);
|
|
||||||
|
|
||||||
deny_btn.setOnClickListener(v -> {
|
|
||||||
handleAction(Policy.DENY);
|
|
||||||
timer.cancel();
|
|
||||||
});
|
|
||||||
suPopup.setOnClickListener(v -> cancelTimeout());
|
|
||||||
timeout.setOnTouchListener((v, event) -> cancelTimeout());
|
|
||||||
|
|
||||||
if (hasTimeout) {
|
|
||||||
timer.start();
|
|
||||||
} else {
|
|
||||||
cancelTimeout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed() {
|
|
||||||
if (policy != null) {
|
|
||||||
handleAction(Policy.DENY);
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleAction() {
|
|
||||||
String response;
|
|
||||||
if (policy.policy == Policy.ALLOW) {
|
|
||||||
response = "socket:ALLOW";
|
|
||||||
} else {
|
|
||||||
response = "socket:DENY";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
socket.getOutputStream().write((response).getBytes());
|
|
||||||
socket.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleAction(int action) {
|
|
||||||
handleAction(action, Const.Value.timeoutList[timeout.getSelectedItemPosition()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleAction(int action, int time) {
|
|
||||||
policy.policy = action;
|
|
||||||
if (time >= 0) {
|
|
||||||
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
|
||||||
mm.mDB.addPolicy(policy);
|
|
||||||
}
|
|
||||||
handleAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SocketManager extends ParallelTask<Void, Void, Boolean> {
|
|
||||||
|
|
||||||
SocketManager(BaseActivity context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
try {
|
|
||||||
socket = new LocalSocket();
|
|
||||||
socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM));
|
|
||||||
|
|
||||||
DataInputStream is = new DataInputStream(socket.getInputStream());
|
|
||||||
ContentValues payload = new ContentValues();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
int nameLen = is.readInt();
|
|
||||||
byte[] nameBytes = new byte[nameLen];
|
|
||||||
is.readFully(nameBytes);
|
|
||||||
String name = new String(nameBytes);
|
|
||||||
if (TextUtils.equals(name, "eof"))
|
|
||||||
break;
|
|
||||||
|
|
||||||
int dataLen = is.readInt();
|
|
||||||
byte[] dataBytes = new byte[dataLen];
|
|
||||||
is.readFully(dataBytes);
|
|
||||||
String data = new String(dataBytes);
|
|
||||||
payload.put(name, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.getAsInteger("uid") == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int uid = payload.getAsInteger("uid");
|
|
||||||
policy = mm.mDB.getPolicy(uid);
|
|
||||||
if (policy == null) {
|
|
||||||
policy = new Policy(uid, pm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Never allow com.topjohnwu.magisk (could be malware) */
|
|
||||||
if (TextUtils.equals(policy.packageName, Const.ORIG_PKG_NAME))
|
|
||||||
return false;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
if (result) {
|
|
||||||
showRequest();
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -3,88 +3,13 @@ package com.topjohnwu.magisk.superuser;
|
|||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.utils.SuConnector;
|
||||||
import com.topjohnwu.magisk.Data;
|
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
import com.topjohnwu.magisk.container.Policy;
|
|
||||||
import com.topjohnwu.magisk.container.SuLogEntry;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
public class SuReceiver extends BroadcastReceiver {
|
public class SuReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
int fromUid, toUid, pid, mode;
|
SuConnector.handleLogs(intent, 1);
|
||||||
String command, action;
|
|
||||||
Policy policy;
|
|
||||||
|
|
||||||
MagiskManager mm = Data.MM();
|
|
||||||
|
|
||||||
if (intent == null) return;
|
|
||||||
|
|
||||||
mode = intent.getIntExtra("mode", -1);
|
|
||||||
if (mode < 0) return;
|
|
||||||
|
|
||||||
if (mode == Const.Value.NOTIFY_USER_TO_OWNER) {
|
|
||||||
Utils.toast(R.string.multiuser_hint_owner_request, Toast.LENGTH_LONG);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fromUid = intent.getIntExtra("from.uid", -1);
|
|
||||||
if (fromUid < 0) return;
|
|
||||||
if (fromUid == Process.myUid()) return; // Don't show anything if it's Magisk Manager
|
|
||||||
|
|
||||||
action = intent.getStringExtra("action");
|
|
||||||
if (action == null) return;
|
|
||||||
|
|
||||||
policy = mm.mDB.getPolicy(fromUid);
|
|
||||||
if (policy == null) {
|
|
||||||
try {
|
|
||||||
policy = new Policy(fromUid, mm.getPackageManager());
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SuLogEntry log = new SuLogEntry(policy);
|
|
||||||
|
|
||||||
String message;
|
|
||||||
switch (action) {
|
|
||||||
case "allow":
|
|
||||||
message = mm.getString(R.string.su_allow_toast, policy.appName);
|
|
||||||
log.action = true;
|
|
||||||
break;
|
|
||||||
case "deny":
|
|
||||||
message = mm.getString(R.string.su_deny_toast, policy.appName);
|
|
||||||
log.action = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (policy.notification && Data.suNotificationType == Const.Value.NOTIFICATION_TOAST)
|
|
||||||
Utils.toast(message, Toast.LENGTH_SHORT);
|
|
||||||
|
|
||||||
if (mode == Const.Value.NOTIFY_NORMAL_LOG && policy.logging) {
|
|
||||||
toUid = intent.getIntExtra("to.uid", -1);
|
|
||||||
if (toUid < 0) return;
|
|
||||||
pid = intent.getIntExtra("pid", -1);
|
|
||||||
if (pid < 0) return;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.support.annotation.Keep;
|
|
||||||
|
|
||||||
import com.topjohnwu.utils.SignBoot;
|
import com.topjohnwu.utils.SignBoot;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
|
||||||
public class BootSigner {
|
public class BootSigner {
|
||||||
|
|
||||||
@Keep
|
@Keep
|
||||||
|
@@ -1,17 +1,26 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
|
import android.app.Activity;
|
||||||
import android.app.KeyguardManager;
|
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.hardware.fingerprint.FingerprintManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.CancellationSignal;
|
import android.os.CancellationSignal;
|
||||||
import android.security.keystore.KeyGenParameterSpec;
|
import android.security.keystore.KeyGenParameterSpec;
|
||||||
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
import android.security.keystore.KeyPermanentlyInvalidatedException;
|
||||||
import android.security.keystore.KeyProperties;
|
import android.security.keystore.KeyProperties;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
|
import com.topjohnwu.magisk.R;
|
||||||
|
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||||
|
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
|
||||||
@@ -35,6 +44,56 @@ public abstract class FingerprintHelper {
|
|||||||
return km.isKeyguardSecure() && fm != null && fm.isHardwareDetected() && fm.hasEnrolledFingerprints();
|
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 {
|
protected FingerprintHelper() throws Exception {
|
||||||
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
manager = Data.MM().getSystemService(FingerprintManager.class);
|
manager = Data.MM().getSystemService(FingerprintManager.class);
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.support.annotation.Keep;
|
|
||||||
|
|
||||||
public interface ISafetyNetHelper {
|
public interface ISafetyNetHelper {
|
||||||
|
|
||||||
int RESPONSE_ERR = 0x01;
|
int RESPONSE_ERR = 0x01;
|
||||||
@@ -10,14 +8,11 @@ public interface ISafetyNetHelper {
|
|||||||
int BASIC_PASS = 0x10;
|
int BASIC_PASS = 0x10;
|
||||||
int CTS_PASS = 0x20;
|
int CTS_PASS = 0x20;
|
||||||
|
|
||||||
@Keep
|
|
||||||
void attest();
|
void attest();
|
||||||
|
|
||||||
@Keep
|
|
||||||
int getVersion();
|
int getVersion();
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
@Keep
|
|
||||||
void onResponse(int responseCode);
|
void onResponse(int responseCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.utils;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -16,6 +15,8 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
|
||||||
public class LocaleManager {
|
public class LocaleManager {
|
||||||
public static Locale locale = Locale.getDefault();
|
public static Locale locale = Locale.getDefault();
|
||||||
public final static Locale defaultLocale = Locale.getDefault();
|
public final static Locale defaultLocale = Locale.getDefault();
|
||||||
|
@@ -4,8 +4,6 @@ import android.app.NotificationManager;
|
|||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -15,15 +13,18 @@ import com.topjohnwu.magisk.SplashActivity;
|
|||||||
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
import com.topjohnwu.magisk.receivers.ManagerUpdate;
|
||||||
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
import com.topjohnwu.magisk.receivers.RebootReceiver;
|
||||||
|
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.TaskStackBuilder;
|
||||||
|
|
||||||
public class NotificationMgr {
|
public class NotificationMgr {
|
||||||
|
|
||||||
public static void magiskUpdate() {
|
public static void magiskUpdate() {
|
||||||
MagiskManager mm = Data.MM();
|
MagiskManager mm = Data.MM();
|
||||||
|
|
||||||
Intent intent = new Intent(mm, SplashActivity.class);
|
Intent intent = new Intent(mm, Data.classMap.get(SplashActivity.class));
|
||||||
intent.putExtra(Const.Key.OPEN_SECTION, "magisk");
|
intent.putExtra(Const.Key.OPEN_SECTION, "magisk");
|
||||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
|
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
|
||||||
stackBuilder.addParentStack(SplashActivity.class);
|
stackBuilder.addParentStack(Data.classMap.get(SplashActivity.class));
|
||||||
stackBuilder.addNextIntent(intent);
|
stackBuilder.addNextIntent(intent);
|
||||||
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
|
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
@@ -46,7 +47,7 @@ public class NotificationMgr {
|
|||||||
String filename = Utils.fmt("MagiskManager-v%s(%d).apk",
|
String filename = Utils.fmt("MagiskManager-v%s(%d).apk",
|
||||||
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
|
Data.remoteManagerVersionString, Data.remoteManagerVersionCode);
|
||||||
|
|
||||||
Intent intent = new Intent(mm, ManagerUpdate.class);
|
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_LINK, Data.managerLink);
|
||||||
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
intent.putExtra(Const.Key.INTENT_SET_FILENAME, filename);
|
||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
||||||
@@ -68,7 +69,7 @@ public class NotificationMgr {
|
|||||||
public static void dtboPatched() {
|
public static void dtboPatched() {
|
||||||
MagiskManager mm = Data.MM();
|
MagiskManager mm = Data.MM();
|
||||||
|
|
||||||
Intent intent = new Intent(mm, RebootReceiver.class);
|
Intent intent = new Intent(mm, Data.classMap.get(RebootReceiver.class));
|
||||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
|
||||||
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
@@ -14,6 +13,8 @@ import com.topjohnwu.superuser.io.SuFile;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
public class RootUtils extends Shell.Initializer {
|
public class RootUtils extends Shell.Initializer {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -49,7 +50,7 @@ public class RootUtils extends Shell.Initializer {
|
|||||||
job.add(nonroot);
|
job.add(nonroot);
|
||||||
}
|
}
|
||||||
|
|
||||||
job.add("mount_partitions", "get_flags", "run_migrations").exec();
|
job.add("mount_partitions", "get_flags", "run_migrations", "export BOOTMODE=true").exec();
|
||||||
|
|
||||||
Data.keepVerity = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPVERITY"));
|
Data.keepVerity = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPVERITY"));
|
||||||
Data.keepEnc = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPFORCEENCRYPT"));
|
Data.keepEnc = Boolean.parseBoolean(ShellUtils.fastCmd("echo $KEEPFORCEENCRYPT"));
|
||||||
|
118
app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java
Normal file
118
app/src/full/java/com/topjohnwu/magisk/utils/SuConnector.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.LocalSocket;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
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.container.Policy;
|
||||||
|
import com.topjohnwu.magisk.container.SuLogEntry;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public abstract class SuConnector {
|
||||||
|
|
||||||
|
protected LocalSocket socket = new LocalSocket();
|
||||||
|
|
||||||
|
private String readString(DataInputStream is) throws IOException {
|
||||||
|
int len = is.readInt();
|
||||||
|
byte[] buf = new byte[len];
|
||||||
|
is.readFully(buf);
|
||||||
|
return new String(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Bundle readSocketInput() throws IOException {
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
DataInputStream is = new DataInputStream(socket.getInputStream());
|
||||||
|
while (true) {
|
||||||
|
String name = readString(is);
|
||||||
|
if (TextUtils.equals(name, "eof"))
|
||||||
|
break;
|
||||||
|
bundle.putString(name, readString(is));
|
||||||
|
}
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DataOutputStream getOutputStream() throws IOException {
|
||||||
|
return new DataOutputStream(socket.getOutputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void response();
|
||||||
|
|
||||||
|
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) {
|
||||||
|
try {
|
||||||
|
policy = new Policy(fromUid, mm.getPackageManager());
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SuLogEntry log = new SuLogEntry(policy);
|
||||||
|
if (version == 1) {
|
||||||
|
String action = intent.getStringExtra("action");
|
||||||
|
if (action == null) return;
|
||||||
|
switch (action) {
|
||||||
|
case "allow":
|
||||||
|
log.action = true;
|
||||||
|
break;
|
||||||
|
case "deny":
|
||||||
|
log.action = false;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = mm.getString(log.action ?
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
import android.support.annotation.IntDef;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
@@ -9,23 +7,24 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import androidx.annotation.IntDef;
|
||||||
|
|
||||||
public class Topic {
|
public class Topic {
|
||||||
|
|
||||||
public static final int MAGISK_HIDE_DONE = 0;
|
public static final int MAGISK_HIDE_DONE = 0;
|
||||||
public static final int RELOAD_ACTIVITY = 1;
|
public static final int MODULE_LOAD_DONE = 1;
|
||||||
public static final int MODULE_LOAD_DONE = 2;
|
public static final int REPO_LOAD_DONE = 2;
|
||||||
public static final int REPO_LOAD_DONE = 3;
|
public static final int UPDATE_CHECK_DONE = 3;
|
||||||
public static final int UPDATE_CHECK_DONE = 4;
|
public static final int SNET_CHECK_DONE = 4;
|
||||||
public static final int SNET_CHECK_DONE = 5;
|
public static final int LOCALE_FETCH_DONE = 5;
|
||||||
public static final int LOCALE_FETCH_DONE = 6;
|
|
||||||
|
|
||||||
@IntDef({MAGISK_HIDE_DONE, RELOAD_ACTIVITY, MODULE_LOAD_DONE, REPO_LOAD_DONE,
|
@IntDef({MAGISK_HIDE_DONE, MODULE_LOAD_DONE, REPO_LOAD_DONE,
|
||||||
UPDATE_CHECK_DONE, SNET_CHECK_DONE, LOCALE_FETCH_DONE})
|
UPDATE_CHECK_DONE, SNET_CHECK_DONE, LOCALE_FETCH_DONE})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface TopicID {}
|
public @interface TopicID {}
|
||||||
|
|
||||||
// We will not dynamically add topics, so use arrays instead of hash tables
|
// We will not dynamically add topics, so use arrays instead of hash tables
|
||||||
private static Store[] topicList = new Store[7];
|
private static Store[] topicList = new Store[6];
|
||||||
|
|
||||||
public static void subscribe(Subscriber sub, @TopicID int... topics) {
|
public static void subscribe(Subscriber sub, @TopicID int... topics) {
|
||||||
for (int topic : topics) {
|
for (int topic : topics) {
|
||||||
|
@@ -6,6 +6,10 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
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.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
@@ -18,12 +22,13 @@ import com.topjohnwu.magisk.MagiskManager;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.container.Module;
|
import com.topjohnwu.magisk.container.Module;
|
||||||
import com.topjohnwu.magisk.container.ValueSortedMap;
|
import com.topjohnwu.magisk.container.ValueSortedMap;
|
||||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
|
||||||
import com.topjohnwu.superuser.io.SuFile;
|
import com.topjohnwu.superuser.io.SuFile;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import a.n;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
public static int getPrefsInt(SharedPreferences prefs, String key, int def) {
|
public static int getPrefsInt(SharedPreferences prefs, String key, int def) {
|
||||||
@@ -77,7 +82,7 @@ public class Utils {
|
|||||||
if (mm.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) {
|
if (mm.prefs.getBoolean(Const.Key.CHECK_UPDATES, true)) {
|
||||||
if (scheduler.getAllPendingJobs().isEmpty() ||
|
if (scheduler.getAllPendingJobs().isEmpty() ||
|
||||||
Const.UPDATE_SERVICE_VER > mm.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) {
|
Const.UPDATE_SERVICE_VER > mm.prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1)) {
|
||||||
ComponentName service = new ComponentName(mm, UpdateCheckService.class);
|
ComponentName service = new ComponentName(mm, n.class);
|
||||||
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
|
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
|
||||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||||
.setPersisted(true)
|
.setPersisted(true)
|
||||||
@@ -122,4 +127,17 @@ public class Utils {
|
|||||||
Topic.publish(Topic.MODULE_LOAD_DONE, moduleMap);
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
@@ -20,7 +20,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -54,42 +54,42 @@
|
|||||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/app_version_info"
|
android:id="@+id/app_version_info"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_info_outline"
|
app:icon="@drawable/ic_info_outline"
|
||||||
app:text="@string/app_version"/>
|
app:text="@string/app_version"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/app_changelog"
|
android:id="@+id/app_changelog"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_history"
|
app:icon="@drawable/ic_history"
|
||||||
app:text="@string/app_changelog"/>
|
app:text="@string/app_changelog"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/app_translators"
|
android:id="@+id/app_translators"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_language"
|
app:icon="@drawable/ic_language"
|
||||||
app:text="@string/app_translators"/>
|
app:text="@string/app_translators"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/follow_twitter"
|
android:id="@+id/follow_twitter"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_twitter"
|
app:icon="@drawable/ic_twitter"
|
||||||
app:text="@string/follow_twitter"/>
|
app:text="@string/follow_twitter"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/app_source_code"
|
android:id="@+id/app_source_code"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_github"
|
app:icon="@drawable/ic_github"
|
||||||
app:text="@string/app_source_code"/>
|
app:text="@string/app_source_code"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/support_thread"
|
android:id="@+id/support_thread"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
@@ -40,14 +40,14 @@
|
|||||||
android:text="@string/donation"
|
android:text="@string/donation"
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
android:textAppearance="@style/TextAppearance.AppCompat.Headline"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/paypal"
|
android:id="@+id/paypal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:icon="@drawable/ic_paypal"
|
app:icon="@drawable/ic_paypal"
|
||||||
app:text="PayPal"/>
|
app:text="PayPal"/>
|
||||||
|
|
||||||
<com.topjohnwu.magisk.components.AboutCardRow
|
<a.o
|
||||||
android:id="@+id/patreon"
|
android:id="@+id/patreon"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@@ -42,7 +42,7 @@
|
|||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/no_thanks"
|
android:id="@+id/close"
|
||||||
style="?android:borderlessButtonStyle"
|
style="?android:borderlessButtonStyle"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/drawer_layout"
|
android:id="@+id/drawer_layout"
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<android.support.design.widget.NavigationView
|
<com.google.android.material.navigation.NavigationView
|
||||||
android:id="@+id/nav_view"
|
android:id="@+id/nav_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@@ -32,4 +32,4 @@
|
|||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
app:menu="@menu/drawer" />
|
app:menu="@menu/drawer" />
|
||||||
|
|
||||||
</android.support.v4.widget.DrawerLayout>
|
</androidx.drawerlayout.widget.DrawerLayout>
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/su_popup"
|
android:id="@+id/su_popup"
|
||||||
tools:context=".superuser.RequestActivity"
|
tools:context=".SuRequestActivity"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:minWidth="350dp"
|
android:minWidth="350dp"
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
tools:context="com.topjohnwu.magisk.fragments.LogFragment">
|
tools:context="com.topjohnwu.magisk.fragments.LogFragment">
|
||||||
|
|
||||||
<android.support.design.widget.TabLayout
|
<com.google.android.material.tabs.TabLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorPrimary"
|
android:background="?attr/colorPrimary"
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
android:elevation="4dp"
|
android:elevation="4dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
</android.support.design.widget.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
|
|
||||||
|
|
||||||
<android.support.v4.view.ViewPager
|
<androidx.viewpager.widget.ViewPager
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/container"/>
|
android:id="@+id/container"/>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/core_only_notice"
|
android:id="@+id/core_only_notice"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -55,9 +55,9 @@
|
|||||||
android:text="@string/settings_core_only_title"
|
android:text="@string/settings_core_only_title"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -141,9 +141,9 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/safetyNet_card"
|
android:id="@+id/safetyNet_card"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -259,9 +259,9 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/install_option_card"
|
android:id="@+id/install_option_card"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -308,9 +308,9 @@
|
|||||||
android:text="@string/keep_dm_verity" />
|
android:text="@string/keep_dm_verity" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/install_button"
|
android:id="@+id/install_button"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -361,9 +361,9 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/uninstall_button"
|
android:id="@+id/uninstall_button"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -392,10 +392,10 @@
|
|||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/swipeRefreshLayout"
|
android:id="@+id/swipeRefreshLayout"
|
||||||
@@ -12,15 +12,15 @@ android:orientation="vertical">
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:dividerHeight="@dimen/card_divider_space"
|
android:dividerHeight="@dimen/card_divider_space"
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
@@ -9,20 +9,20 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
<android.support.design.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:id="@+id/coordinator"
|
android:id="@+id/coordinator"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:dividerHeight="@dimen/card_divider_space"
|
android:dividerHeight="@dimen/card_divider_space"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/empty_rv"
|
android:id="@+id/empty_rv"
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/fab"
|
android:id="@+id/fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@@ -47,6 +47,6 @@
|
|||||||
tools:fabSize="normal"
|
tools:fabSize="normal"
|
||||||
tools:pressedTranslationZ="12dp" />
|
tools:pressedTranslationZ="12dp" />
|
||||||
|
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout"
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="fill_parent"
|
android:layout_height="fill_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -23,13 +23,13 @@
|
|||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:dividerHeight="@dimen/card_divider_space"
|
android:dividerHeight="@dimen/card_divider_space"
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v4.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
@@ -18,11 +18,11 @@
|
|||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:dividerHeight="@dimen/card_divider_space"
|
android:dividerHeight="@dimen/card_divider_space"
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -17,11 +17,11 @@
|
|||||||
android:textStyle="italic"
|
android:textStyle="italic"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/recyclerView"
|
android:id="@+id/recyclerView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:dividerHeight="@dimen/card_divider_space"
|
android:dividerHeight="@dimen/card_divider_space"
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
@@ -73,6 +73,6 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
@@ -110,4 +110,4 @@
|
|||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
@@ -167,6 +167,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
@@ -93,6 +93,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v7.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
||||||
style="?attr/cardStyle"
|
style="?attr/cardStyle"
|
||||||
@@ -140,6 +140,6 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</android.support.v7.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<android.support.v7.widget.Toolbar android:id="@+id/toolbar"
|
<androidx.appcompat.widget.Toolbar android:id="@+id/toolbar"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
@@ -1,12 +1,7 @@
|
|||||||
### 5.9.1
|
### 6.0.1
|
||||||
- Prevent upgrading database before upgrading to v17.0
|
- Update to use new online module's organizing method
|
||||||
|
- When fingerprint authentication is enabled, toggling root permissions in "Superuser" section now requires fingerprint beforehand
|
||||||
### v5.9.0
|
- Fix crashes when entering MagiskHide section on some devices
|
||||||
- No more on boot notifications
|
- Remove support to Magisk version lower than v15.0
|
||||||
- Support new mechanism for installing to inactive slot for OTAs on A/B devices
|
- Ask storage permissions before patching stock boot image
|
||||||
- Fix restore Magisk Manager settings on Android P
|
- Update dark theme CardView color
|
||||||
- Verify existing file checksums to prevent unnecessary re-downloads
|
|
||||||
- Update SNET extension to use new Google API, fix "Invalid Response" errors
|
|
||||||
- Move fingerprint settings to magisk database to prevent the settings to be easily removed
|
|
||||||
- Fingerprint settings are now guarded with fingerprint authentications before it can get changed
|
|
||||||
- Prevent any files to be downloaded to `/sdcard/MagiskManager`
|
|
||||||
|
@@ -10,11 +10,11 @@
|
|||||||
|
|
||||||
<!--Status Fragment-->
|
<!--Status Fragment-->
|
||||||
<string name="magisk_version_error">Magisk ist nicht installiert</string>
|
<string name="magisk_version_error">Magisk ist nicht installiert</string>
|
||||||
<string name="checking_for_updates">Suche nach Aktualisierungen…</string>
|
<string name="checking_for_updates">Suche nach Aktualisierungen...</string>
|
||||||
<string name="magisk_update_available">Magisk %1$s ist verfügbar!</string>
|
<string name="magisk_update_available">Magisk %1$s ist verfügbar!</string>
|
||||||
<string name="invalid_update_channel">Nicht valider Aktualisierungskanal</string>
|
<string name="invalid_update_channel">Ungültiger Aktualisierungskanal</string>
|
||||||
<string name="safetyNet_check_text">SafetyNet-Status abfragen</string>
|
<string name="safetyNet_check_text">SafetyNet-Status abfragen</string>
|
||||||
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status…</string>
|
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status...</string>
|
||||||
<string name="safetyNet_check_success">SafetyNet-Test erfolgreich</string>
|
<string name="safetyNet_check_success">SafetyNet-Test erfolgreich</string>
|
||||||
<string name="safetyNet_api_error">SafetyNet API Fehler</string>
|
<string name="safetyNet_api_error">SafetyNet API Fehler</string>
|
||||||
<string name="safetyNet_res_invalid">Die Antwort ist ungültig</string>
|
<string name="safetyNet_res_invalid">Die Antwort ist ungültig</string>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<string name="install_magisk_title">Neueste Version: %1$s</string>
|
<string name="install_magisk_title">Neueste Version: %1$s</string>
|
||||||
<string name="uninstall">Deinstallieren</string>
|
<string name="uninstall">Deinstallieren</string>
|
||||||
<string name="uninstall_magisk_title">Magisk deinstallieren</string>
|
<string name="uninstall_magisk_title">Magisk deinstallieren</string>
|
||||||
<string name="uninstall_magisk_msg">Alle Module werden deaktiviert/entfernt. Root wird entfernt und wenn die Daten nicht verschlüsselt sind, werden sie möglicherweise verschlüsselt.</string>
|
<string name="uninstall_magisk_msg">Alle Module werden deaktiviert/entfernt. Root wird entfernt und möglicherweise werden Ihre Daten verschlüsseln, falls Ihre Daten derzeit nicht verschlüsselt sind.</string>
|
||||||
<string name="update">Aktualisierung %1$s</string>
|
<string name="update">Aktualisierung %1$s</string>
|
||||||
|
|
||||||
<!--Module Fragment-->
|
<!--Module Fragment-->
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
<string name="disable_file_created">Modul wird beim nächsten Neustart deaktiviert</string>
|
<string name="disable_file_created">Modul wird beim nächsten Neustart deaktiviert</string>
|
||||||
<string name="disable_file_removed">Modul wird beim nächsten Neustart aktiviert</string>
|
<string name="disable_file_removed">Modul wird beim nächsten Neustart aktiviert</string>
|
||||||
<string name="author">Erstellt von %1$s</string>
|
<string name="author">Erstellt von %1$s</string>
|
||||||
<string name="reboot_recovery">Neustart in die Recovery</string>
|
<string name="reboot_recovery">Neustart in das Recovery</string>
|
||||||
<string name="reboot_bootloader">Neustart in den Bootloader</string>
|
<string name="reboot_bootloader">Neustart in den Bootloader</string>
|
||||||
<string name="reboot_download">Neustart in den Download-Modus</string>
|
<string name="reboot_download">Neustart in den Download-Modus</string>
|
||||||
|
|
||||||
@@ -50,24 +50,25 @@
|
|||||||
<string name="updated_on">Zuletzt aktualisiert: %1$s</string>
|
<string name="updated_on">Zuletzt aktualisiert: %1$s</string>
|
||||||
<string name="sorting_order">Sortierung</string>
|
<string name="sorting_order">Sortierung</string>
|
||||||
<string name="sort_by_name">Nach Namen sortiert</string>
|
<string name="sort_by_name">Nach Namen sortiert</string>
|
||||||
<string name="sort_by_update">Nach Aktualisierung sortiert</string>
|
<string name="sort_by_update">Nach Aktualisierungsdatum sortiert</string>
|
||||||
|
|
||||||
<!--Log Fragment-->
|
<!--Log Fragment-->
|
||||||
<string name="menuSaveLog">Protokoll speichern</string>
|
<string name="menuSaveLog">Log speichern</string>
|
||||||
<string name="menuReload">Log erneut laden</string>
|
<string name="menuReload">Log erneut laden</string>
|
||||||
<string name="menuClearLog">Log löschen</string>
|
<string name="menuClearLog">Log löschen</string>
|
||||||
<string name="logs_cleared">Log gelöscht</string>
|
<string name="logs_cleared">Log gelöscht</string>
|
||||||
<string name="log_is_empty">Log ist leer</string>
|
<string name="log_is_empty">Log ist leer</string>
|
||||||
|
|
||||||
<!--About Activity-->
|
<!--About Activity-->
|
||||||
<string name="about">Über</string>
|
<string name="about">Info</string>
|
||||||
<string name="app_changelog">Änderungen</string>
|
<string name="app_changelog">Änderungsprotokoll</string>
|
||||||
<string name="translators">skalnet, c727, jenslody</string>
|
<string name="translators">skalnet, c727, jenslody, SuperSandro2000</string>
|
||||||
<string name="app_version">Version</string>
|
<string name="app_version">Version</string>
|
||||||
<string name="app_source_code">Quelltext</string>
|
<string name="app_source_code">Quelltext</string>
|
||||||
<string name="donation">Spende</string>
|
<string name="donation">Spenden</string>
|
||||||
<string name="app_translators">Übersetzer</string>
|
<string name="app_translators">Übersetzer</string>
|
||||||
<string name="support_thread">Hilfeforum</string>
|
<string name="support_thread">Hilfeforum</string>
|
||||||
|
<string name="follow_twitter">Folge mir auf Twitter</string>
|
||||||
|
|
||||||
<!--Toasts, Dialogs-->
|
<!--Toasts, Dialogs-->
|
||||||
<string name="close">Schließen</string>
|
<string name="close">Schließen</string>
|
||||||
@@ -75,12 +76,12 @@
|
|||||||
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
|
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
|
||||||
<string name="download">Herunterladen</string>
|
<string name="download">Herunterladen</string>
|
||||||
<string name="reboot">Neustart</string>
|
<string name="reboot">Neustart</string>
|
||||||
<string name="magisk_update_title">Neue Magisk-Aktualisierung verfügbar!</string>
|
<string name="magisk_update_title">Neue Magisk Update verfügbar!</string>
|
||||||
<string name="settings_reboot_toast">Neustarten, um die Änderungen anzuwenden</string>
|
<string name="settings_reboot_toast">Neustarten, um die Änderungen zu übernehmen</string>
|
||||||
<string name="release_notes">Änderungen</string>
|
<string name="release_notes">Versionshinweise</string>
|
||||||
<string name="repo_cache_cleared">Repo-Cache gelöscht</string>
|
<string name="repo_cache_cleared">Repo-Cache geleert</string>
|
||||||
<string name="process_error">Prozessfehler</string>
|
<string name="process_error">Prozessfehler</string>
|
||||||
<string name="internal_storage">Die zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
|
<string name="internal_storage">Die Zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
|
||||||
<string name="zip_download_title">Herunterladen</string>
|
<string name="zip_download_title">Herunterladen</string>
|
||||||
<string name="zip_download_msg">Lade Zip-Datei herunter (%1$d%%) …</string>
|
<string name="zip_download_msg">Lade Zip-Datei herunter (%1$d%%) …</string>
|
||||||
<string name="zip_process_title">Verarbeite</string>
|
<string name="zip_process_title">Verarbeite</string>
|
||||||
@@ -88,30 +89,34 @@
|
|||||||
<string name="manager_update_title">Aktualisierung für Magisk Manager verfügbar!</string>
|
<string name="manager_update_title">Aktualisierung für Magisk Manager verfügbar!</string>
|
||||||
<string name="manager_download_install">Herunterladen und installieren</string>
|
<string name="manager_download_install">Herunterladen und installieren</string>
|
||||||
<string name="dtbo_patched_title">DTBO wurde gepatched!</string>
|
<string name="dtbo_patched_title">DTBO wurde gepatched!</string>
|
||||||
<string name="dtbo_patched_reboot">Magisk Manager hat dtbo.img gepatched, bitte Neustart durchführen</string>
|
<string name="dtbo_patched_reboot">Magisk Manager hat dtbo.img gepatched, bitte neustarten</string>
|
||||||
<string name="magisk_updates">Magisk Aktualisierungen</string>
|
<string name="magisk_updates">Magisk Update</string>
|
||||||
<string name="flashing">Flashing</string>
|
<string name="flashing">Flashing</string>
|
||||||
<string name="hide_manager_toast">Verberge Magisk Manager…</string>
|
<string name="hide_manager_toast">Verberge Magisk Manager…</string>
|
||||||
<string name="hide_manager_toast2">Dies könnte einige Zeit in Anspruch nehmen…</string>
|
<string name="hide_manager_toast2">Das könnte einige Zeit dauern...</string>
|
||||||
<string name="hide_manager_fail_toast">Verbergen von Magisk Manager fehlgeschlagen…</string>
|
<string name="hide_manager_fail_toast">Verbergen von Magisk Manager fehlgeschlagen…</string>
|
||||||
<string name="download_zip_only">Zip-Datei nur herunterladen</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>
|
||||||
<string name="patch_boot_file">Boot-Image-Datei patchen</string>
|
<string name="patch_boot_file">Boot-Image-Datei patchen</string>
|
||||||
<string name="direct_install">Direkt installieren (empfohlen)</string>
|
<string name="direct_install">Direkt installieren (empfohlen)</string>
|
||||||
|
<string name="install_inactive_slot">Installiere auf inaktiven Slot (Nach OTA)</string>
|
||||||
|
<string name="warning">Warnung</string>
|
||||||
|
<string name="install_inactive_slot_msg">Dein Gerät wird GEZWUNGEN in den aktuell inaktiven Slot zu starten, nachdem nach dem ein Neustart durchgeführt wurde!\nBenutze diese Option nur, nachdem das OTA beendet wurde.\nFortsetzen?</string>
|
||||||
<string name="select_method">Methode auswählen</string>
|
<string name="select_method">Methode auswählen</string>
|
||||||
<string name="no_boot_file_patch_support">Magisk Zielversion unterstützt das Patchen des Boot-Images nicht</string>
|
<string name="no_boot_file_patch_support">Magisk Zielversion unterstützt das Patchen von Boot-Images nicht</string>
|
||||||
<string name="boot_file_patch_msg">Selektiere das originale Boot image dump im Format .img oder .img.tar</string>
|
<string name="boot_file_patch_msg">Wähle das original Boot-Image-Dump im Format .img oder .img.tar</string>
|
||||||
<string name="complete_uninstall">Komplette Deinstallation</string>
|
<string name="complete_uninstall">Komplette Deinstallation</string>
|
||||||
<string name="restore_img">Images wiederherstellen</string>
|
<string name="restore_img">Images wiederherstellen</string>
|
||||||
<string name="restore_img_msg">Wiederherstellen...</string>
|
<string name="restore_img_msg">Wiederherstellen...</string>
|
||||||
<string name="restore_done">Wiederherstellung durchgeführt!</string>
|
<string name="restore_done">Wiederherstellung erfolgreich!</string>
|
||||||
<string name="restore_fail">Kein Original Backup vorhanden!</string>
|
<string name="restore_fail">Kein Original Backup vorhanden!</string>
|
||||||
<string name="proprietary_title">Lade proprietären Code herunter</string>
|
<string name="proprietary_title">Lade proprietären Code herunter</string>
|
||||||
<string name="proprietary_notice">Magisk Manager ist FOSS und enthält keinen proprietären SafetyNet API Code von Google. Magisk Manager erlauben eine Erweiterung (enthält GoogleApiClient) für SafetyNet-Checks herunterzuladen?</string>
|
<string name="proprietary_notice">Magisk Manager ist FOSS und enthält keinen proprietären SafetyNet API Code von Google. Magisk Manager erlauben eine Erweiterung (enthält GoogleApiClient) für SafetyNet-Checks herunterzuladen?</string>
|
||||||
<string name="su_db_corrupt">Datenbank für SU ist fehlerhaft, es wird eine neue erstellt</string>
|
<string name="su_db_corrupt">SU-Datenbank ist fehlerhaft, es wird eine neue erstellt</string>
|
||||||
<string name="setup_done">Einrichtung abgeschlossen</string>
|
<string name="setup_done">Einrichtung abgeschlossen</string>
|
||||||
<string name="setup_fail">Einrichtung fehlgeschlagen</string>
|
<string name="setup_fail">Einrichtung fehlgeschlagen</string>
|
||||||
<string name="env_fix_title">Zusätzliche Einrichtung erforderlich</string>
|
<string name="env_fix_title">Zusätzliche Einrichtung erforderlich</string>
|
||||||
<string name="env_fix_msg">Um Magisk ordnungsgemäß zu nutzen, benötigt das Geräte eine zusätzliche Einrichtung. Magisk Einrichtungs-zip wird heruntergeladen, fortsetzen?</string>
|
<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_title">Zusätzliche Einrichtung</string>
|
||||||
<string name="setup_msg">Umgebungseinrichtung läuft…</string>
|
<string name="setup_msg">Umgebungseinrichtung läuft…</string>
|
||||||
|
|
||||||
@@ -119,12 +124,12 @@
|
|||||||
<string name="settings_general_category">Allgemein</string>
|
<string name="settings_general_category">Allgemein</string>
|
||||||
<string name="settings_dark_theme_title">Dunkles Theme</string>
|
<string name="settings_dark_theme_title">Dunkles Theme</string>
|
||||||
<string name="settings_dark_theme_summary">Dunkles Theme aktivieren</string>
|
<string name="settings_dark_theme_summary">Dunkles Theme aktivieren</string>
|
||||||
<string name="settings_clear_cache_title">Repo-Cache löschen</string>
|
<string name="settings_clear_cache_title">Repo-Cache leeren</string>
|
||||||
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen der Online-Repos. Erzwingt eine Online-Aktualisierung</string>
|
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen des Online-Repos. Erzwingt eine Aktualisierung</string>
|
||||||
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
|
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
|
||||||
<string name="settings_hide_manager_summary">Magisk Manager mit zufälligem Paketnamen neu packen</string>
|
<string name="settings_hide_manager_summary">Magisk Manager mit zufälligem Paketnamen neu packen</string>
|
||||||
<string name="settings_restore_manager_title">Stelle Magisk Manager wieder her</string>
|
<string name="settings_restore_manager_title">Magisk Manager wiederherstellen</string>
|
||||||
<string name="settings_restore_manager_summary">Stelle Magisk Manager mit ursprünglichem Paket wieder her</string>
|
<string name="settings_restore_manager_summary">Stellt Magisk Manager mit ursprünglichem Paketnamen wieder her</string>
|
||||||
<string name="language">Sprache</string>
|
<string name="language">Sprache</string>
|
||||||
<string name="system_default">(Systemstandard)</string>
|
<string name="system_default">(Systemstandard)</string>
|
||||||
<string name="settings_update">Aktualisierungs-Einstellungen</string>
|
<string name="settings_update">Aktualisierungs-Einstellungen</string>
|
||||||
@@ -134,13 +139,13 @@
|
|||||||
<string name="settings_update_stable">Stabil</string>
|
<string name="settings_update_stable">Stabil</string>
|
||||||
<string name="settings_update_beta">Beta</string>
|
<string name="settings_update_beta">Beta</string>
|
||||||
<string name="settings_update_custom">Benutzerdefiniert</string>
|
<string name="settings_update_custom">Benutzerdefiniert</string>
|
||||||
<string name="settings_update_custom_msg">Gebe eine benutzerdefinierte URL ein</string>
|
<string name="settings_update_custom_msg">Gib eine benutzerdefinierte URL ein</string>
|
||||||
<string name="settings_boot_format_title">Ausgabeformat des gepatchten Boot-Images</string>
|
<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_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_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, Magisk Hide und Systemless hosts bleiben weiterhin aktiv</string>
|
||||||
<string name="settings_magiskhide_summary">Versteckt Magisk vor diversen Entdeckungsmethoden</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_title">Systemlose Hosts-Datei</string>
|
||||||
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>
|
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>
|
||||||
|
|
||||||
<string name="settings_su_app_adb">Apps und ADB</string>
|
<string name="settings_su_app_adb">Apps und ADB</string>
|
||||||
@@ -160,6 +165,7 @@
|
|||||||
<string name="settings_su_reauth_summary">Superuser-Zugriff nach App-Aktualisierung erneut abfragen</string>
|
<string name="settings_su_reauth_summary">Superuser-Zugriff nach App-Aktualisierung erneut abfragen</string>
|
||||||
<string name="settings_su_fingerprint_title">Aktiviere Authentifizierung durch Fingerabdruck</string>
|
<string name="settings_su_fingerprint_title">Aktiviere Authentifizierung durch Fingerabdruck</string>
|
||||||
<string name="settings_su_fingerprint_summary">Fingerabdrucksensor benutzen um Superuser-Anfragen zu erlauben</string>
|
<string name="settings_su_fingerprint_summary">Fingerabdrucksensor benutzen um Superuser-Anfragen zu erlauben</string>
|
||||||
|
<string name="auth_fingerprint">Authentifiziere Fingerabdruck</string>
|
||||||
|
|
||||||
<string name="multiuser_mode">Mehrbenutzermodus</string>
|
<string name="multiuser_mode">Mehrbenutzermodus</string>
|
||||||
<string name="settings_owner_only">Nur der Gerätebesitzer</string>
|
<string name="settings_owner_only">Nur der Gerätebesitzer</string>
|
||||||
@@ -168,15 +174,15 @@
|
|||||||
<string name="owner_only_summary">Nur der Besitzer hat Root-Zugriff</string>
|
<string name="owner_only_summary">Nur der Besitzer hat Root-Zugriff</string>
|
||||||
<string name="owner_manage_summary">Nur der Besitzer verwaltet den Root-Zugriff und erhält Zugriffs-Anfragen</string>
|
<string name="owner_manage_summary">Nur der Besitzer verwaltet den Root-Zugriff und erhält Zugriffs-Anfragen</string>
|
||||||
<string name="user_indepenent_summary">Jeder Nutzer hat seine eingenen Root-Regeln</string>
|
<string name="user_indepenent_summary">Jeder Nutzer hat seine eingenen Root-Regeln</string>
|
||||||
<string name="multiuser_hint_owner_request">Eine Anfrage wurde an den Gerätebesitzer gesendet. Bitte wechsle zum Bersitzerkonto und gewähre die Rechte</string>
|
<string name="multiuser_hint_owner_request">Eine Anfrage wurde an den Gerätebesitzer gesendet. Bitte wechsel zum Bersitzerkonto und gewähre die Rechte.</string>
|
||||||
|
|
||||||
<string name="mount_namespace_mode">Namensraum-Modus</string>
|
<string name="mount_namespace_mode">Mount-Namespace-Modus</string>
|
||||||
<string name="settings_ns_global">Globaler Namensraum</string>
|
<string name="settings_ns_global">Globaler Namespace</string>
|
||||||
<string name="settings_ns_requester">Geerbter Namensraum</string>
|
<string name="settings_ns_requester">Geerbter Namespace</string>
|
||||||
<string name="settings_ns_isolate">Isolierter Namensraum</string>
|
<string name="settings_ns_isolate">Isolierter Namespace</string>
|
||||||
<string name="global_summary">Alle Root-Sitzungen benutzen den global angelegten Namensraum</string>
|
<string name="global_summary">Alle Root-Sitzungen benutzen den global angelegten Namespace</string>
|
||||||
<string name="requester_summary">Root-Sitzungen erben den Namensraum des Abfragenden</string>
|
<string name="requester_summary">Root-Sitzungen erben den Namespace des Abfragenden</string>
|
||||||
<string name="isolate_summary">Jede Root-Sitzung hat ihren isolierten Namensraum</string>
|
<string name="isolate_summary">Jede Root-Sitzung hat ihren isolierten Namespace</string>
|
||||||
<string name="android_o_not_support">Android 8.0+ wird nicht unterstützt</string>
|
<string name="android_o_not_support">Android 8.0+ wird nicht unterstützt</string>
|
||||||
<string name="disable_fingerprint">Keine Fingerabdrücke gespeichert oder keine Geräteunterstützung</string>
|
<string name="disable_fingerprint">Keine Fingerabdrücke gespeichert oder keine Geräteunterstützung</string>
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user