1
mirror of https://github.com/topjohnwu/Magisk synced 2025-10-30 09:00:52 +01:00

Compare commits

..

180 Commits

Author SHA1 Message Date
topjohnwu
55ecc41d06 Bump version 2017-07-20 03:20:17 +08:00
#DarkBasic - BasicHD
28fcdf2cbb Update strings.xml
Delele Translate "Magisk Modo Sólo Núcleo". (After several hours (Days :v ). I thought it was best left in its original form .Magisk Hide, should also be translated if it were the case, it was better to leave it that way so as not to confuse the users.)
Fix translation error
Translations Updates and added new line
2017-07-20 03:19:58 +08:00
topjohnwu
24087679a8 Update uninstaller 2017-07-20 02:56:36 +08:00
topjohnwu
5ac6a8cb4a Small minor updates 2017-07-20 02:54:34 +08:00
topjohnwu
668d85d14e Improve notification support 2017-07-20 01:44:32 +08:00
topjohnwu
c11a3dc95c Fix Magisk Manager freezing issue 2017-07-20 00:51:30 +08:00
topjohnwu
56f57c20a2 Update AsyncTasks to prevent memory leak 2017-07-19 18:01:22 +08:00
topjohnwu
240d14779a Minor cleanup in check updates 2017-07-19 16:10:17 +08:00
topjohnwu
3550d1e61c Bump version 2017-07-19 00:38:25 +08:00
topjohnwu
6513ad249c Fix string.xml 2017-07-19 00:36:54 +08:00
killer7mod
50297b1880 update strings.xml portuguese brazil 2017-07-19 00:25:36 +08:00
#DarkBasic - BasicHD
f189b78b9e #DBC01 - Translation update 2017-07-19 00:25:23 +08:00
zertyuiop
5c0250f495 Fix too long string
checking_safetyNet_status string is too long.
2017-07-19 00:24:47 +08:00
pavlaras
2093f726e9 Update strings.xml
corrected Greek translation
2017-07-19 00:24:36 +08:00
topjohnwu
10efe3859d Update repo fragment and adapter 2017-07-18 23:18:57 +08:00
topjohnwu
6933bcf7bb Merge shells 2017-07-18 17:14:42 +08:00
topjohnwu
2ea046cd80 Add flashing screen 2017-07-18 17:14:42 +08:00
topjohnwu
f4097a372b Root shell with no outputs 2017-07-18 01:06:05 +08:00
topjohnwu
87ea2a2bef Rewrite root shell 2017-07-16 03:00:01 +08:00
JpegXguy
cc14a1c361 Fix untranslated strings 2017-07-15 01:23:59 +08:00
topjohnwu
bcdface60d Fix crashing when installing modules 2017-07-15 01:22:00 +08:00
topjohnwu
4dc9419d2e Bump version 2017-07-14 02:31:29 +08:00
topjohnwu
d2bcac813e Fix update notifications on Android O 2017-07-14 02:27:02 +08:00
topjohnwu
080c37a7f6 Remove busybox from strings 2017-07-14 01:18:20 +08:00
topjohnwu
f9a3838db6 Fix strings 2017-07-13 15:37:00 +08:00
JpegXguy
1e61db104b Added Greek Language 2017-07-13 15:22:53 +08:00
Generator
30a9c7718d Added (European) Portuguese
Split Portuguese into pt_BR and pt_PT
2017-07-13 15:22:40 +08:00
Dmitry Val'd
34b052b5d3 Update strings.xml
Full and correct translation to russian language
2017-07-13 15:21:27 +08:00
topjohnwu
aaa12853ad Prevent crashing when requesting SN check while checking
Fixed #208, fixed #212
2017-07-13 15:12:43 +08:00
topjohnwu
b0ab55b0bf Only show one notification at a time 2017-07-13 14:51:12 +08:00
topjohnwu
d2f8496f4e Update dependency 2017-07-13 14:47:47 +08:00
topjohnwu
1a69b16d36 Bump version 2017-07-11 01:11:10 +08:00
topjohnwu
b5e8673e62 Fix small UI bug 2017-07-11 01:09:40 +08:00
topjohnwu
264c6a50b6 Update uninstallation 2017-07-11 00:55:53 +08:00
topjohnwu
493642eb38 Minor translation update 2017-07-11 00:55:44 +08:00
gh2923
28d42b9164 fix some expressions 2017-07-08 11:17:41 -05:00
Jens Lody
42f29062ca Fix timeout of temporary granted su-rights. 2017-07-08 11:17:07 -05:00
topjohnwu
c4377ed6c2 Bump version 2017-07-03 01:08:54 +08:00
topjohnwu
7d283ed65f Optimize imports 2017-07-01 18:09:34 +08:00
topjohnwu
bf1f941e50 Adapt to Android O new broadcast limitations 2017-07-01 18:09:34 +08:00
topjohnwu
789fef34ba Fix crash on Android O 2017-07-01 18:09:34 +08:00
topjohnwu
1daf5a611c MagiskHide now defaults to enabled 2017-07-01 17:38:33 +08:00
topjohnwu
6aed1db67e Update Android Studio 2017-07-01 15:57:49 +08:00
gh2923
cf68854770 Update Simplified Chinese Translation 2017-06-20 21:46:36 +08:00
linar10
711392c73b Update Strings PL 2017-06-20 21:45:46 +08:00
c727
9573c32481 update strings.de 2017-06-20 21:45:38 +08:00
RoySchutte
a15f80f79d Create strings.xml 2017-06-20 21:45:28 +08:00
Igor Sorocean
23e7475f06 update romanian translation 2017-06-20 21:45:11 +08:00
topjohnwu
1eb571b787 Proper handle policy changes 2017-06-20 18:33:50 +08:00
topjohnwu
dd3b716d85 Extract expandable viewholder 2017-06-20 17:57:17 +08:00
topjohnwu
28649c07e3 SU policy DB bug fix 2017-06-20 17:57:17 +08:00
topjohnwu
961e02be0d Update Android Studio 2017-06-20 17:54:40 +08:00
topjohnwu
a161491bfd Disable shrinkResources due to buildtool bug 2017-06-16 15:25:22 +08:00
topjohnwu
e0b4d1c1e4 Bump version 2017-06-16 04:07:10 +08:00
topjohnwu
fd4aaab137 Rewrite zip signing 2017-06-16 03:12:57 +08:00
topjohnwu
42d14d5ca2 Update to new build tools, target API 26 2017-06-16 03:06:22 +08:00
topjohnwu
d3ff482c9b Bump version 2017-06-08 22:55:48 +08:00
topjohnwu
f682368eeb Update strings 2017-06-08 22:49:26 +08:00
topjohnwu
4a5d033efb Store data in intent for OTA 2017-06-08 22:35:30 +08:00
topjohnwu
343161b195 Add mount namespace options 2017-06-08 22:27:24 +08:00
topjohnwu
bc576a9659 Update uninstall script 2017-06-08 04:28:55 +08:00
topjohnwu
19e407fcc4 Update translations 2017-06-08 04:23:17 +08:00
RoySchutte
bc7327d004 Update strings.xml 2017-06-08 04:14:12 +08:00
ROBERTO
666fa1c797 Update Italian translation 2017-06-08 04:14:01 +08:00
Igor Sorocean
0eda4a7821 Update romanian translation 2017-06-08 04:13:44 +08:00
topjohnwu
862058fd2b Bump version 2017-06-08 03:20:04 +08:00
topjohnwu
69e5bcd57d Simple OTA implementation 2017-06-07 02:21:58 +08:00
topjohnwu
efeddda328 Use Java synchronize instead serial tasks 2017-06-06 03:21:52 +08:00
topjohnwu
ff6938280e Switch to DB based su configs 2017-06-01 03:18:41 +08:00
RoySchutte
1e4425b30f Update strings-nl.xml 2017-05-31 11:45:02 -05:00
Igor Sorocean
b5d1d8cdad Update romanian translation 2017-05-31 11:44:37 -05:00
gh2923
029be5ccca Update Simplified Chinese Translation 2017-05-31 11:44:17 -05:00
gh2923
29c2d785b5 Update Simplified Chinese Translation 2017-05-31 11:44:04 -05:00
Exalm
abda8cfa32 Updated russian translation 2017-05-31 11:43:48 -05:00
topjohnwu
44e7d79d4c Add Arabic translation
Credits to @xx6600xx
2017-06-01 00:41:36 +08:00
topjohnwu
9a1dc8ee0e Refactor su database 2017-06-01 00:26:36 +08:00
topjohnwu
27879c3f01 Improve Logger 2017-05-31 17:43:55 +08:00
topjohnwu
29096eb5d7 Monitor package (un)install events 2017-05-31 16:31:33 +08:00
topjohnwu
a573baea03 Simplify SU requests, binary should be much superior now 2017-05-30 01:27:10 +08:00
topjohnwu
5af07c4531 Update Traditional Chinese translate 2017-05-28 01:44:29 +08:00
topjohnwu
44e36feb09 Improve multiuser settings and notification 2017-05-28 01:31:19 +08:00
topjohnwu
2a7d996881 Add multiuser support 2017-05-27 02:41:24 +08:00
topjohnwu
738f943a68 Several UI tweaks 2017-05-26 18:20:53 +08:00
dvdandroid
47e62a5681 Small code cleanup 2017-05-24 21:21:15 +02:00
dvdandroid
1ecbfd7590 Adjust theme in about and settings activities 2017-05-24 20:55:47 +02:00
topjohnwu
67c139a04b Fix theme changing glitch 2017-05-24 00:37:15 +08:00
RoySchutte
31cc008249 Update strings.xml
2 small changes to make strings more similar.
2017-05-23 19:47:38 +08:00
topjohnwu
9cb026439d Update translations 2017-05-23 17:02:05 +08:00
topjohnwu
e6f10176c6 Network check 2017-05-23 17:01:38 +08:00
RoySchutte
0917c79470 Update strings.xml
Added and translated new strings.
2017-05-22 23:53:59 +08:00
ROBERTO
597baa986d Updated Italian language 2017-05-22 23:53:43 +08:00
topjohnwu
75cc4b4843 Merge install and status 2017-05-21 12:16:38 +08:00
topjohnwu
aac088d496 Update strings.xml 2017-05-20 03:17:37 +08:00
RoySchutte
a822e5bbc5 Update strings.xml
Fixed many Dutch translations which were gramatically incorrect. Added translations (up-to-date).
Hopefully these translations will make it to the next release, because the current translations aren't pretty *_*.
2017-05-20 03:08:22 +08:00
Igor Sorocean
c527249c21 Add romanian translation 2017-05-20 03:08:14 +08:00
topjohnwu
9ef798f534 Update SafetyNet check UI 2017-05-20 03:04:14 +08:00
topjohnwu
e69b99f089 Update status UI 2017-05-19 08:37:57 -07:00
topjohnwu
55b8079e86 Update MagiskHide method 2017-05-12 23:11:28 +08:00
topjohnwu
e272dbe9af Include busybox binary and remove busybox toggle 2017-05-12 04:05:21 +08:00
topjohnwu
962f8354ac Use new version detection method 2017-05-12 02:25:07 +08:00
topjohnwu
20e4a960f7 Fix strings 2017-05-10 22:54:17 +08:00
ROBERTO
82249cb50a Italian language update 2017-04-28 23:45:41 +08:00
gh2923
fad417e553 Update Simplified Chinese Translation 2017-04-28 15:41:59 +08:00
lindwurm
5ba692f50c l10n: Update Japanese Translations
* Fixed more strings!

Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-04-28 15:41:50 +08:00
topjohnwu
907e01e524 Use stable build tools + retrolambda 2017-04-26 19:04:06 +08:00
lindwurm
b8ed23efa7 l10n: Update Japanese Translations
Signed-off-by: lindwurm <lindwurm.q@gmail.com>
2017-04-26 19:03:14 +08:00
topjohnwu
2b3bbf7e67 Bump version 2017-04-26 00:59:56 +08:00
topjohnwu
464fe627a3 Swap tabs 2017-04-26 00:27:55 +08:00
topjohnwu
6a9e39c470 Support unlimited amount of repos 2017-04-26 00:15:53 +08:00
topjohnwu
7fec9a3cc6 Fix string.xml errors 2017-04-24 22:26:40 +08:00
Primokorn
008f6ef462 Update french strings.xml
Better translation.
2017-04-24 21:54:34 +08:00
lilymaniac
2440c108ca Update values-ko/strings.xml 2017-04-24 21:54:22 +08:00
linar10
430baad8a4 Update strings pl 2017-04-24 21:54:05 +08:00
Nosi
51132e74b4 Changes Spanish 2017-04-24 21:53:48 +08:00
killer7Mod
a4f33e106a Update Portuguese translation 2017-04-24 21:53:21 +08:00
SakuraSa233
baba3190e0 Add Japanese Translation 2017-04-24 21:53:05 +08:00
topjohnwu
47b13aa5ea Use stock FAB; Log monospace; Fixes 2017-04-24 21:52:23 +08:00
topjohnwu
ae88d3054d Finally, official Java 8 support 2017-04-05 17:02:18 +08:00
topjohnwu
411b600e14 Screw that Jack compiler, use retrolambda 2017-03-31 16:04:12 +08:00
topjohnwu
0a0ad9a184 Bump to 4.3.1 2017-03-31 13:17:58 +08:00
topjohnwu
234bead59e Bump version 2017-03-31 06:58:47 +08:00
Primokorn
76de310986 Create french strings.xml
Hope it's not too late for the update :)
2017-03-31 03:23:23 +08:00
topjohnwu
817f050bcd Say goodbye to old modules 2017-03-30 06:52:18 +08:00
topjohnwu
60ae685d1e Change disable to Core Only Mode 2017-03-30 05:16:50 +08:00
Wang Han
4c7bdbb284 Fix crashing when selecting release notes on some devices 2017-03-26 23:55:11 +08:00
topjohnwu
435251ca41 Bump version 2017-03-20 06:24:59 +08:00
topjohnwu
324a0dd38f Update uninstall script 2017-03-20 04:17:04 +08:00
topjohnwu
cc77d93918 Fix string.xml(vi) 2017-03-20 03:38:24 +08:00
Nguyễn Thanh Tài
0ea7d8bd8c Added Vietnamese translation 2017-03-20 03:12:03 +08:00
topjohnwu
849b217143 Fix build issues 2017-03-16 14:08:40 +08:00
Fabio
9af6efba59 Update Italian Translation [2/2] 2017-03-16 13:40:52 +08:00
Fatih Fırıncı
079d6f06ef Added turkish language
Please merge it
2017-03-16 13:40:43 +08:00
gargamelek
9cf0757689 Added czech translation 2017-03-16 13:40:30 +08:00
c727
b54c438948 update strings-de 2017-03-16 13:40:10 +08:00
linar10
c3ff4bfdad Update strings pl 2017-03-16 13:39:49 +08:00
topjohnwu
5d62e066e2 Bump version 2017-02-22 05:06:19 +08:00
topjohnwu
e94219c5a3 Add notification settings 2017-02-22 04:58:03 +08:00
topjohnwu
8ed9634adf Fix Samsung crash 2017-02-22 04:13:21 +08:00
topjohnwu
0aefa9599f Version bump 2017-02-21 03:52:35 +08:00
c727
e279cf0575 update strings-de 2017-02-20 13:40:01 -06:00
topjohnwu
a3f0ef8e77 Many improvements and bug fixes
Close #114
2017-02-21 03:38:37 +08:00
topjohnwu
8eba05ed4a Potentially fix Samsung crash and change colors 2017-02-20 20:11:07 +08:00
topjohnwu
2f78155723 Bump version 2017-02-19 10:49:47 +08:00
topjohnwu
6785221479 Small refinements and bugfixes
Close #109
2017-02-19 10:14:29 +08:00
topjohnwu
9bc410dd3d Add MarkDown styles 2017-02-18 04:35:51 +08:00
gh2923
2491ab6bf9 Update Simplified Chinese Translation 2017-02-17 10:56:44 -06:00
topjohnwu
f615ed40cd Several refinements 2017-02-17 14:07:15 +08:00
linar10
430f2cafc1 Update strings.xml 2017-02-16 23:27:51 -06:00
Deiki-kun
0ad049da88 Updated and corrected Spanish strings.xml 2017-02-16 23:27:39 -06:00
c727
2c7691567b Update strings-de 2017-02-16 23:27:22 -06:00
topjohnwu
1d70d0fe94 Don't show notification again if coming from notification 2017-02-17 09:26:27 +08:00
topjohnwu
ac44f05811 Resource cleanup 2017-02-17 09:03:40 +08:00
topjohnwu
d99252f394 Add update notification 2017-02-17 08:51:51 +08:00
topjohnwu
b58c7ba7c5 Add download button to repo, close #99 2017-02-16 17:50:36 +08:00
topjohnwu
8c5acd1a0a Add traditional Chinese 2017-02-16 17:09:11 +08:00
linar10
b9b1ebf18c Update strings.xml 2017-02-16 01:44:37 -06:00
lilymaniac
8ca132cef0 Add Korean translation
Change-Id: Ie5b9ee02dc179c99b1ff5c50e5ce046cc2f2522e
Signed-off-by: lilymaniac <lilymaniac@outlook.com>
2017-02-16 01:43:46 -06:00
topjohnwu
a03bb90754 Use README.md in details for repo 2017-02-16 05:48:26 +08:00
topjohnwu
d1c939f48a Use temporary files to process zips
Fix #96
2017-02-15 23:46:50 +08:00
gh2923
21b11f1b48 Update Simplified Chinese Translation 2017-02-15 08:44:45 +08:00
topjohnwu
23c84a7803 Massive Zip flashing refactoring 2017-02-15 05:25:24 +08:00
topjohnwu
f9ab060403 Fix su request crashing 2017-02-15 05:07:14 +08:00
topjohnwu
df7a5bf149 Redo styling 2017-02-14 16:35:03 +08:00
topjohnwu
c4afa069df Add custom AlertDialog 2017-02-13 23:11:50 +08:00
topjohnwu
1bfafdb44f Don't reload ApplicationInfo list
Fix #94
2017-02-13 04:00:45 +08:00
topjohnwu
1ef5bd7076 Remove URL in resources 2017-02-13 03:16:39 +08:00
linar10
29176fa4f4 Update strings-pl 2017-02-13 03:14:24 +08:00
topjohnwu
958c95732b Move AboutCardRow to components package 2017-02-13 03:13:24 +08:00
topjohnwu
44b0d4127c Remove GSON and switch to database 2017-02-12 23:27:20 +08:00
topjohnwu
1418ec2416 Remove module helper 2017-02-12 20:53:41 +08:00
topjohnwu
b51978f51c Move asynctasks to seperate package 2017-02-12 19:49:46 +08:00
topjohnwu
b07361580a Contexts are different: Make context clearer 2017-02-12 05:02:18 +08:00
topjohnwu
d1b5ebad7d Several fixes 2017-02-07 07:32:40 +08:00
Exalm
f4ce813de9 Better icon 2017-02-07 06:17:54 +08:00
drbeat
b44ac994d8 fix typos and translate new strings 2017-02-07 06:16:53 +08:00
Exalm
333948814c Russian translation 2017-02-07 06:16:14 +08:00
linar10
1a51ad6e01 Update strings - pl 2017-02-07 06:15:52 +08:00
topjohnwu
22a5c11f0d Fix MagiskHide startup issue 2017-02-07 06:02:06 +08:00
topjohnwu
51b22d1ad4 Make callback events non-static 2017-02-07 04:09:49 +08:00
topjohnwu
bef5969580 No more static crap :) 2017-02-07 02:01:32 +08:00
137 changed files with 9027 additions and 4920 deletions

2
.gitignore vendored
View File

@@ -3,6 +3,6 @@
/local.properties
.idea/
/build
app/app-release.apk
app/release
*.hprof
app/.externalNativeBuild/

View File

@@ -1,4 +1,6 @@
# Magisk Manager
The project should be built with Android Studio version 2.2.0+
I use Java 8 features, which requires Jack compiler and it's only available in 2.2.0+
Also, you need to install CMake and NDK to build the zipadjust library for zip preprocessing
# Magisk Manager
You need to install CMake and NDK to build the zipadjust library for zip preprocessing
## Pre-built Binaries
Busybox (arm and x86) compiled by osm0sis (`libbusybox.so` under `app\src\main\jniLibs`)
Source and more info: [osm0sis' Odds and Ends](https://forum.xda-developers.com/showthread.php?t=2239421)

View File

@@ -1,28 +1,25 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 25
versionCode 20
versionName "4.0"
jackOptions {
enabled true
jackInProcess true
}
targetSdkVersion 26
versionCode 51
versionName "5.1.1"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
abiFilters 'x86', 'armeabi-v7a'
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
@@ -31,35 +28,36 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
dexOptions {
preDexLibraries = true
preDexLibraries true
javaMaxHeapSize "2g"
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
}
lintOptions {
disable 'MissingTranslation'
}
}
repositories {
jcenter()
maven { url "https://jitpack.io" }
maven { url "https://maven.google.com" }
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:recyclerview-v7:25.1.1'
compile 'com.android.support:cardview-v7:25.1.1'
compile 'com.android.support:design:25.1.1'
compile 'com.android.support:support-v4:25.1.1'
compile 'com.android.support:support-v13:25.1.1'
compile 'com.jakewharton:butterknife:8.5.1'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.github.clans:fab:1.6.4'
compile 'com.thoughtbot:expandablerecyclerview:1.4'
compile 'com.madgag.spongycastle:core:1.54.0.0'
compile 'com.madgag.spongycastle:prov:1.54.0.0'
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
compile 'com.madgag.spongycastle:pg:1.54.0.0'
compile 'com.google.android.gms:play-services-safetynet:9.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
implementation 'com.android.support:design:26.0.0-beta2'
implementation 'com.android.support:support-v4:26.0.0-beta2'
implementation 'com.jakewharton:butterknife:8.7.0'
implementation 'com.thoughtbot:expandablerecyclerview:1.4'
implementation 'us.feras.mdv:markdownview:1.1.0'
implementation 'com.madgag.spongycastle:core:1.54.0.0'
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
implementation 'com.madgag.spongycastle:pkix:1.54.0.0'
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
}

View File

@@ -16,31 +16,10 @@
# public *;
#}
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.topjohnwu.magisk.module.** { *; }
-keep class com.topjohnwu.magisk.module.ModuleHelper$ValueSortedMap { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keep class android.support.v7.internal.** { *; }
-keep interface android.support.v7.internal.** { *; }
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
# SpongyCastle
-keep class org.spongycastle.** {*;}
-keep class org.spongycastle.** { *; }
-dontwarn javax.naming.**
-dontwarn android.content.**
-dontwarn android.animation.**

View File

@@ -1,15 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.topjohnwu.magisk"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.topjohnwu.magisk">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:name=".MagiskManager"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
@@ -19,8 +21,7 @@
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:exported="true"/>
android:exported="true" />
<activity
android:name=".SplashActivity"
android:configChanges="orientation|screenSize"
@@ -28,16 +29,22 @@
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".AboutActivity"
android:theme="@style/AppTheme.Transparent"/>
android:theme="@style/AppTheme.Transparent" />
<activity
android:name=".SettingsActivity"
android:theme="@style/AppTheme.Transparent" />
<activity
android:name=".FlashActivity"
android:screenOrientation="nosensor"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@style/AppTheme.Transparent" />
<activity
android:name=".superuser.RequestActivity"
android:excludeFromRecents="true"
@@ -50,14 +57,27 @@
android:taskAffinity="internal.superuser"
android:theme="@style/SuRequest" />
<receiver
android:name=".superuser.SuReceiver" />
<receiver android:name=".superuser.SuReceiver" />
<receiver android:name=".receivers.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.PackageReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.ManagerUpdate" />
<service android:name=".services.OnBootIntentService" />
<service
android:name=".services.UpdateCheckService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<provider
android:name="android.support.v4.content.FileProvider"
@@ -75,4 +95,4 @@
</application>
</manifest>
</manifest>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,192 @@
##########################################################################################
#
# Magisk General Utility Functions
# by topjohnwu
#
# Used in flash_script.sh, addon.d.sh, magisk module installers, and uninstaller
#
##########################################################################################
get_outfd() {
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=0
for FD in `ls /proc/$$/fd`; do
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null
if [ "$?" -eq "0" ]; then
ps | grep " 3 $FD " | grep -v grep >/dev/null
if [ "$?" -eq "0" ]; then
OUTFD=$FD
break
fi
fi
done
fi
}
ui_print() {
if $BOOTMODE; then
echo "$1"
else
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
fi
}
getvar() {
local VARNAME=$1
local VALUE=$(eval echo \$"$VARNAME");
for FILE in /dev/.magisk /data/.magisk /cache/.magisk /system/.magisk; do
if [ -z "$VALUE" ]; then
LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
if [ ! -z "$LINE" ]; then
VALUE=${LINE#*=}
fi
fi
done
eval $VARNAME=\$VALUE
}
find_boot_image() {
if [ -z "$BOOTIMAGE" ]; then
for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null
[ ! -z $BOOTIMAGE ] && break
done
fi
# Recovery fallback
if [ -z "$BOOTIMAGE" ]; then
for FSTAB in /etc/*fstab*; do
BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -v "#" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
[ ! -z $BOOTIMAGE ] && break
done
fi
[ -L "$BOOTIMAGE" ] && BOOTIMAGE=`readlink $BOOTIMAGE`
}
is_mounted() {
if [ ! -z "$2" ]; then
cat /proc/mounts | grep $1 | grep $2, >/dev/null
else
cat /proc/mounts | grep $1 >/dev/null
fi
return $?
}
grep_prop() {
REGEX="s/^$1=//p"
shift
FILES=$@
if [ -z "$FILES" ]; then
FILES='/system/build.prop'
fi
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
}
remove_system_su() {
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
ui_print "! System installed root detected, mount rw :("
mount -o rw,remount /system
# SuperSU
if [ -e /system/bin/.ext/.su ]; then
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
cd /system/bin
if [ -e app_process64 ]; then
ln -sf app_process64 app_process
else
ln -sf app_process32 app_process
fi
fi
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
/system/.supersu /cache/.supersu /data/.supersu \
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk 2>/dev/null
fi
}
api_level_arch_detect() {
API=`grep_prop ro.build.version.sdk`
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
ABILONG=`grep_prop ro.product.cpu.abi`
ARCH=arm
IS64BIT=false
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
}
recovery_actions() {
# TWRP bug fix
mount -o bind /dev/urandom /dev/random
# Temporarily block out all custom recovery binaries/libs
mv /sbin /sbin_tmp
# Add all possible library paths
OLD_LD_PATH=$LD_LIBRARY_PATH
$IS64BIT && export LD_LIBRARY_PATH=/system/lib64:/system/vendor/lib64 || export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib
}
recovery_cleanup() {
mv /sbin_tmp /sbin
# Clear LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$OLD_LD_PATH
ui_print "- Unmounting partitions"
umount -l /system
umount -l /vendor 2>/dev/null
umount -l /dev/random
}
abort() {
ui_print "$1"
mv /sbin_tmp /sbin 2>/dev/null
exit 1
}
set_perm() {
chown $2:$3 $1 || exit 1
chmod $4 $1 || exit 1
if [ ! -z $5 ]; then
chcon $5 $1 2>/dev/null
else
chcon 'u:object_r:system_file:s0' $1 2>/dev/null
fi
}
set_perm_recursive() {
find $1 -type d 2>/dev/null | while read dir; do
set_perm $dir $2 $3 $4 $6
done
find $1 -type f 2>/dev/null | while read file; do
set_perm $file $2 $3 $5 $6
done
}
mktouch() {
mkdir -p ${1%/*}
if [ -z "$2" ]; then
touch $1
else
echo $2 > $1
fi
chmod 644 $1
}
request_size_check() {
reqSizeM=`du -s $1 | cut -f1`
reqSizeM=$((reqSizeM / 1024 + 1))
}
image_size_check() {
SIZE="`$MAGISKBIN/magisk --imgsize $IMG`"
curUsedM=`echo "$SIZE" | cut -d" " -f1`
curSizeM=`echo "$SIZE" | cut -d" " -f2`
curFreeM=$((curSizeM - curUsedM))
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -1,24 +1,22 @@
package com.topjohnwu.magisk;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import java.io.IOException;
import java.io.InputStream;
@@ -26,9 +24,9 @@ import java.io.InputStream;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AboutActivity extends AppCompatActivity {
public class AboutActivity extends Activity {
private static final String DONATION_URL = "http://topjohnwu.github.io/donate";
private static final String DONATION_URL = "https://www.paypal.me/topjohnwu";
private static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
private static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/MagiskManager";
@@ -44,10 +42,8 @@ public class AboutActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String theme = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("theme", "");
Logger.dev("AboutActivity: Theme is " + theme);
if (Global.Configs.isDarkTheme) {
setTheme(R.style.AppTheme_dh);
if (getApplicationContext().isDarkTheme) {
setTheme(R.style.AppTheme_Transparent_Dark);
}
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
@@ -85,7 +81,7 @@ public class AboutActivity extends AppCompatActivity {
result = Html.fromHtml(changes);
}
appChangelog.setOnClickListener(v -> {
AlertDialog d = Utils.getAlertDialogBuilder(this)
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_changelog)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
@@ -104,7 +100,7 @@ public class AboutActivity extends AppCompatActivity {
} else {
result = Html.fromHtml(getString(R.string.app_developers_));
}
AlertDialog d = Utils.getAlertDialogBuilder(this)
AlertDialog d = new AlertDialogBuilder(this)
.setTitle(R.string.app_developers)
.setMessage(result)
.setPositiveButton(android.R.string.ok, null)
@@ -134,18 +130,4 @@ public class AboutActivity extends AppCompatActivity {
setFloating();
}
public void setFloating() {
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
if (isTablet) {
WindowManager.LayoutParams params = getWindow().getAttributes();
params.height = getResources().getDimensionPixelSize(R.dimen.floating_height);
params.width = getResources().getDimensionPixelSize(R.dimen.floating_width);
params.alpha = 1.0f;
params.dimAmount = 0.6f;
params.flags |= 2;
getWindow().setAttributes(params);
setFinishOnTouchOutside(true);
}
}
}

View File

@@ -0,0 +1,98 @@
package com.topjohnwu.magisk;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.asyncs.FlashZip;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Shell;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class FlashActivity extends Activity {
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.flash_logs) RecyclerView flashLogs;
@BindView(R.id.button_panel) LinearLayout buttonPanel;
private AdaptiveList<String> rootShellOutput;
@OnClick(R.id.no_thanks)
public void dismiss() {
finish();
}
@OnClick(R.id.reboot)
public void reboot() {
Shell.getShell(this).su_raw("reboot");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
ButterKnife.bind(this);
rootShellOutput = new AdaptiveList<>(flashLogs);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.flashing);
}
setFloating();
flashLogs.setAdapter(new FlashLogAdapter());
// We must receive a Uri of the target zip
Uri uri = getIntent().getData();
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
}
@Override
public void onBackPressed() {
// Prevent user accidentally press back button
}
private class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_flashlog, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(rootShellOutput.get(position));
}
@Override
public int getItemCount() {
return rootShellOutput.size();
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.textView) TextView text;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

View File

@@ -1,133 +0,0 @@
package com.topjohnwu.magisk;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.preference.PreferenceManager;
import android.util.SparseArray;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import java.io.File;
import java.util.List;
public class Global {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static class Info {
public static double magiskVersion;
public static String magiskVersionString = "(none)";
public static double remoteMagiskVersion = -1;
public static String magiskLink;
public static String releaseNoteLink;
public static int SNCheckResult = -1;
public static String bootBlock = null;
public static boolean isSuClient = false;
public static String suVersion = null;
public static boolean disabled = false;
}
public static class Data {
public static ValueSortedMap<String, Repo> repoMap;
public static ValueSortedMap<String, Module> moduleMap;
public static List<String> blockList;
public static List<ApplicationInfo> appList;
public static List<String> magiskHideList;
}
public static class Events {
public static final CallbackHandler.Event blockDetectionDone = new CallbackHandler.Event();
public static final CallbackHandler.Event packageLoadDone = new CallbackHandler.Event();
public static final CallbackHandler.Event reloadMainActivity = new CallbackHandler.Event();
public static final CallbackHandler.Event moduleLoadDone = new CallbackHandler.Event();
public static final CallbackHandler.Event repoLoadDone = new CallbackHandler.Event();
public static final CallbackHandler.Event updateCheckDone = new CallbackHandler.Event();
public static final CallbackHandler.Event safetyNetDone = new CallbackHandler.Event();
public static SparseArray<CallbackHandler.Event> uidMap = new SparseArray<>();
}
public static class Configs {
public static boolean isDarkTheme;
public static boolean shellLogging;
public static boolean devLogging;
public static boolean magiskHide;
public static int suRequestTimeout;
public static int suLogTimeout = 14;
public static int suAccessState;
public static int suResponseType;
public static int suNotificationType;
}
public static void init(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Configs.isDarkTheme = prefs.getBoolean("dark_theme", false);
Configs.devLogging = prefs.getBoolean("developer_logging", false);
Configs.shellLogging = prefs.getBoolean("shell_logging", false);
Configs.magiskHide = prefs.getBoolean("magiskhide", false);
updateMagiskInfo();
initSuAccess();
initSuConfigs(context);
// Initialize prefs
prefs.edit()
.putBoolean("dark_theme", Configs.isDarkTheme)
.putBoolean("magiskhide", Configs.magiskHide)
.putBoolean("busybox", Utils.commandExists("busybox"))
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
.putString("su_request_timeout", String.valueOf(Configs.suRequestTimeout))
.putString("su_auto_response", String.valueOf(Configs.suResponseType))
.putString("su_notification", String.valueOf(Configs.suNotificationType))
.putString("su_access", String.valueOf(Configs.suAccessState))
.apply();
}
public static void initSuConfigs(Context context) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
Configs.suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
Configs.suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
Configs.suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
}
public static void initSuAccess() {
List<String> ret = Shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) {
Info.suVersion = ret.get(0);
Info.isSuClient = Info.suVersion.toUpperCase().contains("MAGISK");
}
if (Info.isSuClient) {
ret = Shell.sh("getprop persist.sys.root_access");
if (Utils.isValidShellResponse(ret))
Configs.suAccessState = Integer.parseInt(ret.get(0));
else {
Shell.su(true, "setprop persist.sys.root_access 3");
Configs.suAccessState = 3;
}
}
}
public static void updateMagiskInfo() {
List<String> ret = Shell.sh("getprop magisk.version");
if (!Utils.isValidShellResponse(ret)) {
Info.magiskVersion = -1;
} else {
try {
Info.magiskVersionString = ret.get(0);
Info.magiskVersion = Double.parseDouble(ret.get(0));
} catch (NumberFormatException e) {
// Custom version don't need to receive updates
Info.magiskVersion = Double.POSITIVE_INFINITY;
}
}
ret = Shell.sh("getprop ro.magisk.disable");
try {
Info.disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
Info.disabled = false;
}
}
}

View File

@@ -1,174 +0,0 @@
package com.topjohnwu.magisk;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Spinner;
import android.widget.TextView;
import com.topjohnwu.magisk.receivers.MagiskDlReceiver;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class InstallFragment extends Fragment implements CallbackHandler.EventListener {
private static final String UNINSTALLER = "magisk_uninstaller.sh";
private Unbinder unbinder;
@BindView(R.id.current_version_title) TextView currentVersionTitle;
@BindView(R.id.install_title) TextView installTitle;
@BindView(R.id.block_spinner) Spinner spinner;
@BindView(R.id.detect_bootimage) Button detectButton;
@BindView(R.id.flash_button) CardView flashButton;
@BindView(R.id.uninstall_button) CardView uninstallButton;
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_install, container, false);
unbinder = ButterKnife.bind(this, v);
detectButton.setOnClickListener(v1 -> toAutoDetect());
currentVersionTitle.setText(getString(R.string.current_magisk_title, Global.Info.magiskVersionString));
installTitle.setText(getString(R.string.install_magisk_title, Global.Info.remoteMagiskVersion));
flashButton.setOnClickListener(v1 -> {
String bootImage;
if (Global.Info.bootBlock != null) {
if (spinner.getSelectedItemPosition() > 0)
bootImage = Global.Data.blockList.get(spinner.getSelectedItemPosition() - 1);
else
bootImage = Global.Info.bootBlock;
} else {
bootImage = Global.Data.blockList.get(spinner.getSelectedItemPosition());
}
String filename = "Magisk-v" + Global.Info.remoteMagiskVersion + ".zip";
Utils.getAlertDialogBuilder(getActivity())
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
.setMessage(getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.dlAndReceive(
getActivity(),
new MagiskDlReceiver(bootImage, keepEncChkbox.isChecked(), keepVerityChkbox.isChecked()),
Global.Info.magiskLink,
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.check_release_notes, (dialog, which) -> {
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Global.Info.releaseNoteLink)));
})
.setNegativeButton(R.string.no_thanks, null)
.show();
});
if (Global.Info.magiskVersion < 10.3) {
uninstallButton.setVisibility(View.GONE);
} else {
uninstallButton.setOnClickListener(vi -> {
Utils.getAlertDialogBuilder(getActivity())
.setTitle("Uninstall Magisk")
.setMessage("This will remove all modules, MagiskSU, and potentially re-encrypt your device\nAre you sure to process?")
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
try {
InputStream in = getActivity().getAssets().open(UNINSTALLER);
File uninstaller = new File(getActivity().getCacheDir().getAbsolutePath() + "/" + UNINSTALLER);
FileOutputStream out = new FileOutputStream(uninstaller);
byte[] bytes = new byte[1024];
int read;
while ((read = in.read(bytes)) != -1)
out.write(bytes, 0, read);
in.close();
out.close();
ProgressDialog progress = new ProgressDialog(getActivity());
progress.setTitle(R.string.reboot);
progress.show();
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
progress.setMessage(getString(R.string.reboot_countdown, millisUntilFinished / 1000));
}
@Override
public void onFinish() {
progress.setMessage(getString(R.string.reboot_countdown, 0));
Shell.su(true, "cp -af " + uninstaller + " /cache/" + UNINSTALLER,
"reboot");
}
}.start();
} catch (IOException e) {
e.printStackTrace();
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
});
}
if (Global.Events.blockDetectionDone.isTriggered) {
updateUI();
}
return v;
}
@Override
public void onTrigger(CallbackHandler.Event event) {
updateUI();
}
private void updateUI() {
List<String> items = new ArrayList<>(Global.Data.blockList);
if (Global.Info.bootBlock != null)
items.add(0, getString(R.string.auto_detect, Global.Info.bootBlock));
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
toAutoDetect();
}
private void toAutoDetect() {
if (Global.Info.bootBlock != null) {
spinner.setSelection(0);
}
}
@Override
public void onStart() {
super.onStart();
getActivity().setTitle(R.string.install);
CallbackHandler.register(Global.Events.blockDetectionDone, this);
}
@Override
public void onStop() {
CallbackHandler.unRegister(Global.Events.blockDetectionDone, this);
super.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}

View File

@@ -3,13 +3,13 @@ package com.topjohnwu.magisk;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.topjohnwu.magisk.adapters.TabFragmentAdapter;
import com.topjohnwu.magisk.components.Fragment;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -31,14 +31,14 @@ public class LogFragment extends Fragment {
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
if (Global.Info.isSuClient) {
if (getApplication().isSuClient) {
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
tab.setupWithViewPager(viewPager);
tab.setVisibility(View.VISIBLE);
}
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
viewPager.setAdapter(adapter);
return v;

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
@@ -16,15 +15,16 @@ import android.view.ViewGroup;
import android.widget.SearchView;
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class MagiskHideFragment extends Fragment implements CallbackHandler.EventListener {
public class MagiskHideFragment extends Fragment implements CallbackEvent.Listener<Void> {
private Unbinder unbinder;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@@ -50,7 +50,7 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even
PackageManager packageManager = getActivity().getPackageManager();
mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.setOnRefreshListener(() -> new Async.LoadApps(packageManager).exec());
mSwipeRefreshLayout.setOnRefreshListener(() -> new MagiskHide(getActivity()).list());
appAdapter = new ApplicationAdapter(packageManager);
recyclerView.setAdapter(appAdapter);
@@ -71,6 +71,10 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even
}
};
if (getApplication().magiskHideDone.isTriggered) {
onTrigger(getApplication().magiskHideDone);
}
return view;
}
@@ -85,15 +89,12 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even
public void onStart() {
super.onStart();
getActivity().setTitle(R.string.magiskhide);
CallbackHandler.register(Global.Events.packageLoadDone, this);
if (Global.Events.packageLoadDone.isTriggered) {
onTrigger(Global.Events.packageLoadDone);
}
getApplication().magiskHideDone.register(this);
}
@Override
public void onStop() {
CallbackHandler.unRegister(Global.Events.packageLoadDone, this);
getApplication().magiskHideDone.unRegister(this);
super.onStop();
}
@@ -104,9 +105,9 @@ public class MagiskHideFragment extends Fragment implements CallbackHandler.Even
}
@Override
public void onTrigger(CallbackHandler.Event event) {
public void onTrigger(CallbackEvent<Void> event) {
Logger.dev("MagiskHideFragment: UI refresh");
appAdapter.setLists(Global.Data.appList, Global.Data.magiskHideList);
appAdapter.setLists(getApplication().appList, getApplication().magiskHideList);
mSwipeRefreshLayout.setRefreshing(false);
if (!TextUtils.isEmpty(lastFilter)) {
appAdapter.filter(lastFilter);

View File

@@ -1,17 +1,13 @@
package com.topjohnwu.magisk;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -25,15 +21,15 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -121,49 +117,33 @@ public class MagiskLogFragment extends Fragment {
new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500);
}
} else {
Snackbar.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
SnackbarMaker.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
}
}
}
public class LogManager extends Async.RootTask<Object, Void, Object> {
private class LogManager extends ParallelTask<Object, Void, Object> {
int mode;
File targetFile;
private int mode;
private File targetFile;
@SuppressLint("DefaultLocale")
@Override
protected Object doInBackground(Object... params) {
MagiskManager magiskManager = MagiskLogFragment.this.getApplication();
mode = (int) params[0];
switch (mode) {
case 0:
List<String> logList = Utils.readFile(MAGISK_LOG);
if (Utils.isValidShellResponse(logList)) {
StringBuilder llog = new StringBuilder(15 * 10 * 1024);
for (String s : logList) {
llog.append(s).append("\n");
}
return llog.toString();
}
return "";
StringBuildingList logList = new StringBuildingList();
magiskManager.shell.su(logList, "cat " + MAGISK_LOG);
return logList.toString();
case 1:
Shell.su("echo > " + MAGISK_LOG);
Snackbar.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
magiskManager.shell.su_raw("echo > " + MAGISK_LOG);
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
return "";
case 2:
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
return false;
}
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
return false;
Calendar now = Calendar.getInstance();
String filename = String.format(
"magisk_%s_%04d%02d%02d_%02d%02d%02d.log", "error",
@@ -174,22 +154,18 @@ public class MagiskLogFragment extends Fragment {
targetFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MagiskManager/" + filename);
if ((!targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs())
|| (targetFile.exists() && !targetFile.delete()))
|| (targetFile.exists() && !targetFile.delete())) {
return false;
List<String> in = Utils.readFile(MAGISK_LOG);
if (Utils.isValidShellResponse(in)) {
try (FileWriter out = new FileWriter(targetFile)) {
for (String line : in)
out.write(line + "\n");
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return false;
try (FileWriter out = new FileWriter(targetFile)) {
FileWritingList fileWritingList = new FileWritingList(out);
magiskManager.shell.su(fileWritingList, "cat " + MAGISK_LOG);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
return null;
}
@@ -197,12 +173,10 @@ public class MagiskLogFragment extends Fragment {
@Override
protected void onPostExecute(Object o) {
if (o == null) return;
boolean bool;
String llog;
switch (mode) {
case 0:
case 1:
llog = (String) o;
String llog = (String) o;
progressBar.setVisibility(View.GONE);
if (TextUtils.isEmpty(llog))
txtLog.setText(R.string.log_is_empty);
@@ -212,26 +186,64 @@ public class MagiskLogFragment extends Fragment {
hsvLog.post(() -> hsvLog.scrollTo(0, 0));
break;
case 2:
bool = (boolean) o;
if (bool)
Toast.makeText(getActivity(), targetFile.toString(), Toast.LENGTH_LONG).show();
else
Toast.makeText(getActivity(), getString(R.string.logs_save_failed), Toast.LENGTH_LONG).show();
boolean bool = (boolean) o;
if (bool) {
MagiskLogFragment.this.getApplication().toast(targetFile.toString(), Toast.LENGTH_LONG);
} else {
MagiskLogFragment.this.getApplication().toast(R.string.logs_save_failed, Toast.LENGTH_LONG);
}
break;
}
}
public void read() {
void read() {
exec(0);
}
public void clear() {
void clear() {
exec(1);
}
public void save() {
void save() {
exec(2);
}
}
private static class StringBuildingList extends Shell.AbstractList<String> {
StringBuilder builder;
StringBuildingList() {
builder = new StringBuilder();
}
@Override
public boolean add(String s) {
builder.append(s).append("\n");
return true;
}
@Override
public String toString() {
return builder.toString();
}
}
private static class FileWritingList extends Shell.AbstractList<String> {
private FileWriter writer;
FileWritingList(FileWriter out) {
writer = out;
}
@Override
public boolean add(String s) {
try {
writer.write(s + "\n");
} catch (IOException ignored) {}
return true;
}
}
}

View File

@@ -0,0 +1,235 @@
package com.topjohnwu.magisk;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.SafetyNetHelper;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import java.io.File;
import java.util.List;
public class MagiskManager extends Application {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_PATH = "/magisk";
public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String UTIL_FUNCTIONS= "util_functions.sh";
public static final String INTENT_SECTION = "section";
public static final String INTENT_VERSION = "version";
public static final String INTENT_LINK = "link";
public static final String BUSYBOX_VERSION = "1.26.2";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
public static final String NOTIFICATION_CHANNEL = "magisk_update_notice";
// Events
public final CallbackEvent<Void> magiskHideDone = new CallbackEvent<>();
public final CallbackEvent<Void> reloadMainActivity = new CallbackEvent<>();
public final CallbackEvent<Void> moduleLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
// Info
public String magiskVersionString;
public int magiskVersionCode = -1;
public String remoteMagiskVersionString;
public int remoteMagiskVersionCode = -1;
public String magiskLink;
public String releaseNoteLink;
public String remoteManagerVersionString;
public int remoteManagerVersionCode = -1;
public String managerLink;
public SafetyNetHelper.Result SNCheckResult;
public String bootBlock = null;
public boolean isSuClient = false;
public String suVersion = null;
public boolean disabled;
// Data
public ValueSortedMap<String, Repo> repoMap;
public ValueSortedMap<String, Module> moduleMap;
public List<String> blockList;
public List<ApplicationInfo> appList;
public List<String> magiskHideList;
// Configurations
public static boolean shellLogging;
public static boolean devLogging;
public boolean magiskHide;
public boolean isDarkTheme;
public boolean updateNotification;
public boolean suReauth;
public int suRequestTimeout;
public int suLogTimeout = 14;
public int suAccessState;
public int multiuserMode;
public int suResponseType;
public int suNotificationType;
public int suNamespaceMode;
// Global resources
public SharedPreferences prefs;
public SuDatabaseHelper suDB;
public Shell shell;
private static Handler mHandler = new Handler();
@Override
public void onCreate() {
super.onCreate();
new File(getApplicationInfo().dataDir).mkdirs(); /* Create the app data directory */
prefs = PreferenceManager.getDefaultSharedPreferences(this);
shell = Shell.getShell();
}
public void toast(String msg, int duration) {
mHandler.post(() -> Toast.makeText(this, msg, duration).show());
}
public void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(this, resId, duration).show());
}
public void init() {
isDarkTheme = prefs.getBoolean("dark_theme", false);
if (BuildConfig.DEBUG) {
devLogging = prefs.getBoolean("developer_logging", false);
shellLogging = prefs.getBoolean("shell_logging", false);
} else {
devLogging = false;
shellLogging = false;
}
magiskHide = prefs.getBoolean("magiskhide", true);
initSU();
updateMagiskInfo();
updateBlockInfo();
// Initialize busybox
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
busybox.getParentFile().mkdirs();
shell.su_raw(
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
"chmod -R 755 " + busybox.getParent(),
busybox + " --install -s " + busybox.getParent()
);
}
// Initialize prefs
prefs.edit()
.putBoolean("dark_theme", isDarkTheme)
.putBoolean("magiskhide", magiskHide)
.putBoolean("notification", updateNotification)
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
.putBoolean("disable", Utils.itemExist(shell, MAGISK_DISABLE_FILE))
.putBoolean("su_reauth", suReauth)
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
.putString("su_auto_response", String.valueOf(suResponseType))
.putString("su_notification", String.valueOf(suNotificationType))
.putString("su_access", String.valueOf(suAccessState))
.putString("multiuser_mode", String.valueOf(multiuserMode))
.putString("mnt_ns", String.valueOf(suNamespaceMode))
.putString("busybox_version", BUSYBOX_VERSION)
.apply();
// Add busybox to PATH
shell.su_raw("PATH=$PATH:" + busybox.getParent());
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
}
}
public void initSUConfig() {
suDB = new SuDatabaseHelper(this);
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
suReauth = prefs.getBoolean("su_reauth", false);
}
public void initSU() {
initSUConfig();
List<String> ret = shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) {
suVersion = ret.get(0);
isSuClient = suVersion.toUpperCase().contains("MAGISK");
}
if (isSuClient) {
suAccessState = suDB.getSettings(SuDatabaseHelper.ROOT_ACCESS, 3);
multiuserMode = suDB.getSettings(SuDatabaseHelper.MULTIUSER_MODE, 0);
suNamespaceMode = suDB.getSettings(SuDatabaseHelper.MNT_NS, 1);
}
}
public void updateMagiskInfo() {
updateNotification = prefs.getBoolean("notification", true);
List<String> ret;
ret = shell.sh("magisk -v");
if (!Utils.isValidShellResponse(ret)) {
ret = shell.sh("getprop magisk.version");
if (Utils.isValidShellResponse(ret)) {
try {
magiskVersionString = ret.get(0);
magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10;
} catch (NumberFormatException ignored) {}
}
} else {
magiskVersionString = ret.get(0).split(":")[0];
ret = shell.sh("magisk -V");
try {
magiskVersionCode = Integer.parseInt(ret.get(0));
} catch (NumberFormatException ignored) {}
}
ret = shell.sh("getprop " + DISABLE_INDICATION_PROP);
try {
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
disabled = false;
}
ret = shell.sh("getprop " + MAGISKHIDE_PROP);
try {
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
magiskHide = true;
}
}
public void updateBlockInfo() {
List<String> res = shell.su(
"for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do",
"BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null",
"[ ! -z \"$BOOTIMAGE\" ] && break",
"done",
"[ ! -z \"$BOOTIMAGE\" -a -L \"$BOOTIMAGE\" ] && BOOTIMAGE=`readlink $BOOTIMAGE`",
"echo \"$BOOTIMAGE\""
);
if (Utils.isValidShellResponse(res)) {
bootBlock = res.get(0);
} else {
blockList = shell.su("ls -d /dev/block/mmc* /dev/block/sd* 2>/dev/null");
}
}
}

View File

@@ -7,7 +7,6 @@ import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
@@ -15,23 +14,25 @@ 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.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, CallbackHandler.EventListener {
public class MainActivity extends Activity
implements NavigationView.OnNavigationItemSelectedListener, CallbackEvent.Listener<Void> {
private final Handler mDrawerHandler = new Handler();
private SharedPreferences prefs;
private int mDrawerItem;
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.drawer_layout) DrawerLayout drawer;
@@ -42,10 +43,10 @@ public class MainActivity extends AppCompatActivity
@Override
protected void onCreate(final Bundle savedInstanceState) {
prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefs = getApplicationContext().prefs;
if (Global.Configs.isDarkTheme) {
setTheme(R.style.AppTheme_dh);
if (getApplicationContext().isDarkTheme) {
setTheme(R.style.AppTheme_Dark);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@@ -76,40 +77,35 @@ public class MainActivity extends AppCompatActivity
drawer.addDrawerListener(toggle);
toggle.syncState();
navigate(R.id.status);
if (savedInstanceState == null)
navigate(getIntent().getStringExtra(MagiskManager.INTENT_SECTION));
navigationView.setNavigationItemSelectedListener(this);
CallbackHandler.register(Global.Events.reloadMainActivity, this);
getApplicationContext().reloadMainActivity.register(this);
}
@Override
protected void onResume() {
super.onResume();
CallbackHandler.register(Global.Events.updateCheckDone, this);
if (Global.Events.updateCheckDone.isTriggered)
onTrigger(Global.Events.updateCheckDone);
checkHideSection();
}
@Override
protected void onPause() {
CallbackHandler.unRegister(Global.Events.updateCheckDone, this);
super.onPause();
}
@Override
protected void onDestroy() {
CallbackHandler.unRegister(Global.Events.reloadMainActivity, this);
getApplicationContext().reloadMainActivity.unRegister(this);
super.onDestroy();
}
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(navigationView))
if (drawer.isDrawerOpen(navigationView)) {
drawer.closeDrawer(navigationView);
else
} else if (mDrawerItem != R.id.magisk) {
navigate(R.id.magisk);
} else {
finish();
}
}
@Override
@@ -121,35 +117,74 @@ public class MainActivity extends AppCompatActivity
}
@Override
public void onTrigger(CallbackHandler.Event event) {
if (event == Global.Events.updateCheckDone) {
Menu menu = navigationView.getMenu();
menu.findItem(R.id.install).setVisible(Global.Info.remoteMagiskVersion > 0 &&
Shell.rootAccess());
} else if (event == Global.Events.reloadMainActivity) {
recreate();
}
public void onTrigger(CallbackEvent<Void> event) {
recreate();
}
private void checkHideSection() {
public void checkHideSection() {
Menu menu = navigationView.getMenu();
if (Shell.rootAccess()) {
menu.findItem(R.id.magiskhide).setVisible(
Global.Info.magiskVersion >= 8 && prefs.getBoolean("magiskhide", false));
menu.findItem(R.id.modules).setVisible(Global.Info.magiskVersion >= 4);
menu.findItem(R.id.downloads).setVisible(Global.Info.magiskVersion >= 4);
menu.findItem(R.id.log).setVisible(true);
menu.findItem(R.id.superuser).setVisible(Global.Info.isSuClient);
menu.findItem(R.id.magiskhide).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 1300
&& prefs.getBoolean("magiskhide", false));
menu.findItem(R.id.modules).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus(this) &&
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
menu.findItem(R.id.superuser).setVisible(
Shell.rootAccess() && getApplicationContext().isSuClient);
}
public void navigate(String item) {
int itemId = R.id.magisk;
if (item != null) {
switch (item) {
case "magisk":
itemId = R.id.magisk;
break;
case "install":
itemId = -1;
break;
case "superuser":
itemId = R.id.superuser;
break;
case "modules":
itemId = R.id.modules;
break;
case "downloads":
itemId = R.id.downloads;
break;
case "magiskhide":
itemId = R.id.magiskhide;
break;
case "log":
itemId = R.id.log;
break;
case "settings":
itemId = R.id.settings;
break;
case "about":
itemId = R.id.app_about;
break;
}
}
navigate(itemId);
}
public void navigate(int itemId) {
int bak = mDrawerItem;
mDrawerItem = itemId;
navigationView.setCheckedItem(itemId);
switch (itemId) {
case R.id.status:
displayFragment(new StatusFragment(), "status", true);
case -1:
Bundle args = new Bundle();
args.putBoolean(MagiskFragment.SHOW_DIALOG, true);
Fragment frag = new MagiskFragment();
frag.setArguments(args);
displayFragment(frag, "magisk", true);
break;
case R.id.install:
displayFragment(new InstallFragment(), "install", true);
case R.id.magisk:
displayFragment(new MagiskFragment(), "magisk", true);
break;
case R.id.superuser:
displayFragment(new SuperuserFragment(), "superuser", true);
@@ -165,13 +200,14 @@ public class MainActivity extends AppCompatActivity
break;
case R.id.log:
displayFragment(new LogFragment(), "log", false);
toolbar.setElevation(0);
break;
case R.id.settings:
startActivity(new Intent(this, SettingsActivity.class));
mDrawerItem = bak;
break;
case R.id.app_about:
startActivity(new Intent(this, AboutActivity.class));
mDrawerItem = bak;
break;
}
}
@@ -182,5 +218,6 @@ public class MainActivity extends AppCompatActivity
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
transaction.replace(R.id.content_frame, navFragment, tag).commitNow();
if (setElevation) toolbar.setElevation(toolbarElevation);
else toolbar.setElevation(0);
}
}

View File

@@ -2,10 +2,9 @@ package com.topjohnwu.magisk;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -13,12 +12,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.github.clans.fab.FloatingActionButton;
import com.topjohnwu.magisk.adapters.ModulesAdapter;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.ModuleHelper;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import java.util.ArrayList;
@@ -28,7 +26,7 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class ModulesFragment extends Fragment implements CallbackHandler.EventListener {
public class ModulesFragment extends Fragment implements CallbackEvent.Listener<Void> {
private static final int FETCH_ZIP_CODE = 2;
@@ -54,7 +52,7 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.GONE);
new Async.LoadModules().exec();
new LoadModules(getActivity()).exec();
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@@ -69,7 +67,7 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
}
});
if (Global.Events.moduleLoadDone.isTriggered) {
if (getApplication().moduleLoadDone.isTriggered) {
updateUI();
}
@@ -77,7 +75,7 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
}
@Override
public void onTrigger(CallbackHandler.Event event) {
public void onTrigger(CallbackEvent<Void> event) {
Logger.dev("ModulesFragment: UI refresh triggered");
updateUI();
}
@@ -86,8 +84,9 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FETCH_ZIP_CODE && resultCode == Activity.RESULT_OK && data != null) {
// Get the URI of the selected file
final Uri uri = data.getData();
new Async.FlashZIP(getActivity(), uri).exec();
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(data.getData()).putExtra("ACTION", "flash");
startActivity(intent);
}
}
@@ -95,13 +94,13 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
@Override
public void onStart() {
super.onStart();
CallbackHandler.register(Global.Events.moduleLoadDone, this);
getApplication().moduleLoadDone.register(this);
getActivity().setTitle(R.string.modules);
}
@Override
public void onStop() {
CallbackHandler.unRegister(Global.Events.moduleLoadDone, this);
getApplication().moduleLoadDone.unRegister(this);
super.onStop();
}
@@ -112,7 +111,8 @@ public class ModulesFragment extends Fragment implements CallbackHandler.EventLi
}
private void updateUI() {
ModuleHelper.getModuleList(listModules);
listModules.clear();
listModules.addAll(getApplication().moduleMap.values());
if (listModules.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);

View File

@@ -2,8 +2,6 @@ package com.topjohnwu.magisk;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -15,37 +13,23 @@ import android.widget.SearchView;
import android.widget.TextView;
import com.topjohnwu.magisk.adapters.ReposAdapter;
import com.topjohnwu.magisk.adapters.SimpleSectionedRecyclerViewAdapter;
import com.topjohnwu.magisk.module.ModuleHelper;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.utils.CallbackHandler;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class ReposFragment extends Fragment implements CallbackHandler.EventListener {
public class ReposFragment extends Fragment implements CallbackEvent.Listener<Void> {
private Unbinder unbinder;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.empty_rv) TextView emptyRv;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
private List<Repo> mUpdateRepos = new ArrayList<>();
private List<Repo> mInstalledRepos = new ArrayList<>();
private List<Repo> mOthersRepos = new ArrayList<>();
private List<Repo> fUpdateRepos = new ArrayList<>();
private List<Repo> fInstalledRepos = new ArrayList<>();
private List<Repo> fOthersRepos = new ArrayList<>();
private SimpleSectionedRecyclerViewAdapter mSectionedAdapter;
private SearchView.OnQueryTextListener searchListener;
private ReposAdapter adapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -59,24 +43,43 @@ public class ReposFragment extends Fragment implements CallbackHandler.EventList
View view = inflater.inflate(R.layout.fragment_repos, container, false);
unbinder = ButterKnife.bind(this, view);
mSectionedAdapter = new SimpleSectionedRecyclerViewAdapter(R.layout.section,
R.id.section_text, new ReposAdapter(fUpdateRepos, fInstalledRepos, fOthersRepos));
adapter = new ReposAdapter(getApplication().repoMap);
recyclerView.setAdapter(mSectionedAdapter);
recyclerView.setAdapter(adapter);
mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.GONE);
new Async.LoadRepos(getActivity()).exec();
new LoadRepos(getActivity()).exec();
});
if (Global.Events.repoLoadDone.isTriggered) {
reloadRepos();
updateUI();
if (getApplication().repoLoadDone.isTriggered) {
onTrigger(null);
}
searchListener = new SearchView.OnQueryTextListener() {
return view;
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
Logger.dev("ReposFragment: UI refresh triggered");
if (getApplication().repoMap.isEmpty()) {
recyclerView.setVisibility(View.GONE);
emptyRv.setVisibility(View.VISIBLE);
} else {
adapter.filter(getApplication().moduleMap, "");
recyclerView.setVisibility(View.VISIBLE);
emptyRv.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_repo, menu);
SearchView search = (SearchView) menu.findItem(R.id.repo_search).getActionView();
search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
@@ -84,38 +87,22 @@ public class ReposFragment extends Fragment implements CallbackHandler.EventList
@Override
public boolean onQueryTextChange(String newText) {
new FilterApps().exec(newText);
adapter.filter(getApplication().moduleMap, newText);
return false;
}
};
return view;
}
@Override
public void onTrigger(CallbackHandler.Event event) {
Logger.dev("ReposFragment: UI refresh triggered");
reloadRepos();
updateUI();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_repo, menu);
SearchView search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.repo_search));
search.setOnQueryTextListener(searchListener);
});
}
@Override
public void onStart() {
super.onStart();
CallbackHandler.register(Global.Events.repoLoadDone, this);
getApplication().repoLoadDone.register(this);
getActivity().setTitle(R.string.downloads);
}
@Override
public void onStop() {
CallbackHandler.unRegister(Global.Events.repoLoadDone, this);
getApplication().repoLoadDone.unRegister(this);
super.onStop();
}
@@ -124,78 +111,4 @@ public class ReposFragment extends Fragment implements CallbackHandler.EventList
super.onDestroyView();
unbinder.unbind();
}
private void reloadRepos() {
ModuleHelper.getRepoLists(mUpdateRepos, mInstalledRepos, mOthersRepos);
fUpdateRepos.clear();
fInstalledRepos.clear();
fOthersRepos.clear();
fUpdateRepos.addAll(mUpdateRepos);
fInstalledRepos.addAll(mInstalledRepos);
fOthersRepos.addAll(mOthersRepos);
}
private void updateUI() {
if (fUpdateRepos.size() + fInstalledRepos.size() + fOthersRepos.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
List<SimpleSectionedRecyclerViewAdapter.Section> sections = new ArrayList<>();
if (!fUpdateRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(0, getString(R.string.update_available)));
}
if (!fInstalledRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(fUpdateRepos.size(), getString(R.string.installed)));
}
if (!fOthersRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(fUpdateRepos.size() + fInstalledRepos.size(), getString(R.string.not_installed)));
}
SimpleSectionedRecyclerViewAdapter.Section[] array = sections.toArray(new SimpleSectionedRecyclerViewAdapter.Section[sections.size()]);
mSectionedAdapter.setSections(array);
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
mSwipeRefreshLayout.setRefreshing(false);
}
private class FilterApps extends Async.NormalTask<String, Void, Void> {
@Override
protected Void doInBackground(String... strings) {
String newText = strings[0];
fUpdateRepos.clear();
fInstalledRepos.clear();
fOthersRepos.clear();
for (Repo repo: mUpdateRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fUpdateRepos.add(repo);
}
}
for (Repo repo: mInstalledRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fInstalledRepos.add(repo);
}
}
for (Repo repo: mOthersRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fOthersRepos.add(repo);
}
}
return null;
}
@Override
protected void onPostExecute(Void v) {
updateUI();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +1,65 @@
package com.topjohnwu.magisk;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.asyncs.LoadApps;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Utils;
public class SplashActivity extends AppCompatActivity {
public class SplashActivity extends Activity{
private static final int UPDATE_SERVICE_ID = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Init the info and configs and root shell
Global.init(getApplicationContext());
MagiskManager magiskManager = getApplicationContext();
// Init the info and configs and root sh
magiskManager.init();
// Get possible additional info from intent
magiskManager.remoteMagiskVersionString = getIntent().getStringExtra(MagiskManager.INTENT_VERSION);
magiskManager.magiskLink = getIntent().getStringExtra(MagiskManager.INTENT_LINK);
LoadModules loadModuleTask = new LoadModules(this);
if (Utils.checkNetworkStatus(this)) {
// Initialize the update check service, notify every 8 hours
if (!TextUtils.equals("install", getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
}
loadModuleTask.setCallBack(() -> new LoadRepos(this).exec());
}
// Now fire all async tasks
new Async.CheckUpdates().exec();
new Async.GetBootBlocks().exec();
new Async.LoadModules() {
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
new Async.LoadRepos(getApplicationContext()).exec();
}
}.exec();
new Async.LoadApps(getPackageManager()).exec();
loadModuleTask.exec();
new LoadApps(this).exec();
// Preparation done, now start main activity
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section);
}
startActivity(intent);
finish();
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -13,7 +12,7 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.superuser.SuLogDatabaseHelper;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.List;
@@ -28,7 +27,7 @@ public class SuLogFragment extends Fragment {
@BindView(R.id.recyclerView) RecyclerView recyclerView;
private Unbinder unbinder;
private SuLogDatabaseHelper dbHelper;
private MagiskManager magiskManager;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -48,8 +47,7 @@ public class SuLogFragment extends Fragment {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
unbinder = ButterKnife.bind(this, v);
dbHelper = new SuLogDatabaseHelper(getActivity());
magiskManager = getApplication();
updateList();
@@ -57,7 +55,7 @@ public class SuLogFragment extends Fragment {
}
private void updateList() {
List<SuLogEntry> logs = dbHelper.getLogList();
List<SuLogEntry> logs = magiskManager.suDB.getLogList();
if (logs.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
@@ -76,7 +74,7 @@ public class SuLogFragment extends Fragment {
updateList();
return true;
case R.id.menu_clear:
dbHelper.clearLogs();
magiskManager.suDB.clearLogs();
updateList();
return true;
default:

View File

@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -11,8 +10,8 @@ import android.view.ViewGroup;
import android.widget.TextView;
import com.topjohnwu.magisk.adapters.PolicyAdapter;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.superuser.SuDatabaseHelper;
import java.util.List;
@@ -33,15 +32,15 @@ public class SuperuserFragment extends Fragment {
unbinder = ButterKnife.bind(this, view);
PackageManager pm = getActivity().getPackageManager();
MagiskManager magiskManager = getApplication();
SuDatabaseHelper dbHelper = new SuDatabaseHelper(getActivity());
List<Policy> policyList = dbHelper.getPolicyList(pm);
List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
if (policyList.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
recyclerView.setAdapter(new PolicyAdapter(policyList, dbHelper, pm));
recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}

View File

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
@@ -13,7 +14,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Utils;
import java.util.ArrayList;
@@ -50,8 +52,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
}
public void setLists(List<ApplicationInfo> listApps, List<String> hideList) {
mOriginalList = mList = Collections.unmodifiableList(listApps);
mHideList = new ArrayList<>(hideList);
mOriginalList = mList = listApps;
mHideList = hideList;
notifyDataSetChanged();
}
@@ -76,20 +78,19 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
if (SNLIST.contains(info.packageName)) {
holder.checkBox.setChecked(true);
holder.checkBox.setEnabled(false);
holder.itemView.setOnClickListener(v -> {
Snackbar snackbar = Snackbar.make(holder.itemView, R.string.safetyNet_hide_notice, Snackbar.LENGTH_LONG);
((TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text)).setMaxLines(2);
snackbar.show();
});
holder.itemView.setOnClickListener(v ->
SnackbarMaker.make(holder.itemView,
R.string.safetyNet_hide_notice, Snackbar.LENGTH_LONG).show()
);
} else {
holder.checkBox.setEnabled(true);
holder.checkBox.setChecked(mHideList.contains(info.packageName));
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
if (isChecked) {
new Async.MagiskHide().add(info.packageName);
new MagiskHide((Activity) holder.itemView.getContext()).add(info.packageName);
mHideList.add(info.packageName);
} else {
new Async.MagiskHide().rm(info.packageName);
new MagiskHide((Activity) holder.itemView.getContext()).rm(info.packageName);
mHideList.remove(info.packageName);
}
});

View File

@@ -12,8 +12,8 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.utils.Async;
import com.topjohnwu.magisk.utils.Shell;
import java.util.List;
@@ -38,6 +38,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Context context = holder.itemView.getContext();
Shell rootShell = Shell.getShell(context);
final Module module = mList.get(position);
String version = module.getVersion();
@@ -52,44 +53,31 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(module.isEnabled());
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> new Async.RootTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
if (isChecked) {
module.removeDisableFile();
} else {
module.createDisableFile();
}
return null;
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
int snack;
if (isChecked) {
module.removeDisableFile(rootShell);
snack = R.string.disable_file_removed;
} else {
module.createDisableFile(rootShell);
snack = R.string.disable_file_created;
}
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
});
@Override
protected void onPostExecute(Void v) {
int snack = isChecked ? R.string.disable_file_removed : R.string.disable_file_created;
Snackbar.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
holder.delete.setOnClickListener(v -> {
boolean removed = module.willBeRemoved();
int snack;
if (removed) {
module.deleteRemoveFile(rootShell);
snack = R.string.remove_file_deleted;
} else {
module.createRemoveFile(rootShell);
snack = R.string.remove_file_created;
}
}.exec());
holder.delete.setOnClickListener(v -> new Async.RootTask<Void, Void, Void>() {
private final boolean removed = module.willBeRemoved();
@Override
protected Void doInBackground(Void... voids) {
if (removed) {
module.deleteRemoveFile();
} else {
module.createRemoveFile();
}
return null;
}
@Override
protected void onPostExecute(Void v) {
int snack = removed ? R.string.remove_file_deleted : R.string.remove_file_created;
Snackbar.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
updateDeleteButton(holder, module);
}
}.exec());
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
updateDeleteButton(holder, module);
});
if (module.isUpdated()) {
holder.notice.setVisibility(View.VISIBLE);

View File

@@ -1,178 +0,0 @@
package com.topjohnwu.magisk.adapters;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Arrays;
import java.util.Comparator;
public class SimpleSectionedRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int SECTION_TYPE = 0;
private boolean mValid = true;
private int mSectionResourceId;
private int mTextResourceId;
private RecyclerView.Adapter mBaseAdapter;
private SparseArray<Section> mSections = new SparseArray<Section>();
public SimpleSectionedRecyclerViewAdapter(int sectionResourceId, int textResourceId,
RecyclerView.Adapter baseAdapter) {
mSectionResourceId = sectionResourceId;
mTextResourceId = textResourceId;
mBaseAdapter = baseAdapter;
mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
mValid = mBaseAdapter.getItemCount()>0;
notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeChanged(positionStart, itemCount);
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeInserted(positionStart, itemCount);
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
mValid = mBaseAdapter.getItemCount()>0;
notifyItemRangeRemoved(positionStart, itemCount);
}
});
}
public static class SectionViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public SectionViewHolder(View view, int mTextResourceid) {
super(view);
title = (TextView) view.findViewById(mTextResourceid);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) {
if (typeView == SECTION_TYPE) {
View view = LayoutInflater.from(parent.getContext()).inflate(mSectionResourceId, parent, false);
return new SectionViewHolder(view,mTextResourceId);
}else{
return mBaseAdapter.onCreateViewHolder(parent, typeView -1);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) {
if (isSectionHeaderPosition(position)) {
((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title);
}else{
mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position));
}
}
@Override
public int getItemViewType(int position) {
return isSectionHeaderPosition(position)
? SECTION_TYPE
: mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ;
}
public static class Section {
int firstPosition;
int sectionedPosition;
CharSequence title;
public Section(int firstPosition, CharSequence title) {
this.firstPosition = firstPosition;
this.title = title;
}
public CharSequence getTitle() {
return title;
}
}
public void setSections(Section[] sections) {
mSections.clear();
Arrays.sort(sections, new Comparator<Section>() {
@Override
public int compare(Section o, Section o1) {
return (o.firstPosition == o1.firstPosition)
? 0
: ((o.firstPosition < o1.firstPosition) ? -1 : 1);
}
});
int offset = 0; // offset positions for the headers we're adding
for (Section section : sections) {
section.sectionedPosition = section.firstPosition + offset;
mSections.append(section.sectionedPosition, section);
++offset;
}
notifyDataSetChanged();
}
public int positionToSectionedPosition(int position) {
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).firstPosition > position) {
break;
}
++offset;
}
return position + offset;
}
public int sectionedPositionToPosition(int sectionedPosition) {
if (isSectionHeaderPosition(sectionedPosition)) {
return RecyclerView.NO_POSITION;
}
int offset = 0;
for (int i = 0; i < mSections.size(); i++) {
if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
break;
}
--offset;
}
return sectionedPosition + offset;
}
public boolean isSectionHeaderPosition(int position) {
return mSections.get(position) != null;
}
@Override
public long getItemId(int position) {
return isSectionHeaderPosition(position)
? Integer.MAX_VALUE - mSections.indexOfKey(position)
: mBaseAdapter.getItemId(sectionedPositionToPosition(position));
}
@Override
public int getItemCount() {
return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0);
}
}

Some files were not shown because too many files have changed in this diff Show More