1
mirror of https://github.com/topjohnwu/Magisk synced 2025-10-26 02:22:14 +01:00

Compare commits

..

172 Commits

Author SHA1 Message Date
topjohnwu
ea6552615d Bump version 2017-08-13 01:50:20 +08:00
Generator
4bf3287fce update pt_PT 2017-08-13 01:20:04 +08:00
Mevlüt TOPÇU
832c2034c2 Update
Hi,

Update, translations and typo fix

Merge please

Thank you
2017-08-13 01:19:48 +08:00
RJ Trujillo
b0aa26e1f1 More string updates
* A few grammatical corrections were made
* Everything looks cleaner now
2017-08-13 01:19:27 +08:00
dark-basic #DarkBasic BasicHD
e52baeb967 Update Strings.xml 2017-08-13 01:19:15 +08:00
Leonidas P
8268eb9a83 Update strings.xml 2017-08-13 01:18:55 +08:00
topjohnwu
3cc458abd9 Always use global mount namespace 2017-08-12 17:07:28 +08:00
topjohnwu
337b4c4268 Upgrade Android Studio 2017-08-12 15:54:14 +08:00
topjohnwu
001f8657f6 Use global Magisk native busybox for Magisk Manager 2017-08-12 02:25:55 +08:00
topjohnwu
ea884e7fa1 Re-organize application startup 2017-08-12 01:31:34 +08:00
topjohnwu
1b1394cf5d Improve Markdown support
Close #259
2017-08-08 16:12:49 +08:00
topjohnwu
1eef930dbb Move OnClickListener to Butterknife 2017-08-08 16:09:45 +08:00
topjohnwu
1e175e74ed Prevent crashes 2017-08-07 00:15:46 +08:00
John Wu
75a46c365e Update README.md 2017-08-04 00:23:14 +08:00
topjohnwu
8e7b8825f5 Rename callbackevents to topic/subscribers 2017-08-04 00:17:31 +08:00
topjohnwu
2ecbca303b Update Shell 2017-08-03 23:33:08 +08:00
topjohnwu
8195a4d616 Don't ignore libbusybox.so, we want it removed 2017-08-01 23:54:45 +08:00
topjohnwu
7ba40f925f Remove busybox in APK, download from internet 2017-08-01 23:52:39 +08:00
topjohnwu
345cd1795f Update WebService 2017-08-01 23:08:34 +08:00
topjohnwu
959aaee045 Fix FlashZip crash when fails 2017-07-31 01:19:43 +08:00
topjohnwu
53477f0f59 Improve locale settings 2017-07-31 00:44:38 +08:00
topjohnwu
5716218f41 Update busybox version and bug fixes 2017-07-31 00:21:18 +08:00
topjohnwu
9df6b9d5c0 Remove external files from git
These files should be copied to the correct place by Magisk's build script
2017-07-30 23:17:39 +08:00
topjohnwu
ec46031d36 Update Android Studio 2017-07-30 14:41:22 +08:00
RJ Trujillo
55b84d166a Improve dialog strings
* A space should never follow a question mark or any form of punctuation
* Multiple exclamation marks are not needed
2017-07-30 01:36:25 -05:00
Silvered99
34ae8bacec Update strings.xml 2017-07-30 01:36:16 -05:00
RoySchutte
cb4e5ca0f7 Update strings.xml 2017-07-30 01:36:07 -05:00
Leonidas P
0ba45468c4 Fix typos
these pesky little buggers, you never find them...
2017-07-30 01:35:57 -05:00
Frieder Bluemle
710502784e Update Gradle wrapper to 4.1-rc-1 2017-07-30 01:35:46 -05:00
topjohnwu
0275a8558d Fix locale settings duplicate 2017-07-24 18:37:13 +08:00
topjohnwu
58acc75cf6 Fix SuLog UI 2017-07-24 13:15:05 +08:00
topjohnwu
874ababb9f Fix strings.xml 2017-07-24 02:08:58 +08:00
gh2923
3771e6b0cd Update Simplified Chinese Translation 2017-07-24 01:38:55 +08:00
Sopor
33eaefa966 Add Swedish translation 2017-07-24 01:38:43 +08:00
RoySchutte
cd7e236d57 Update strings.xml 2017-07-24 01:38:18 +08:00
Andrei Conache
54c0b7c7d5 update italian translation 2017-07-24 01:38:02 +08:00
zertyuiop
a2177daec2 Update strings.xml 2017-07-24 01:37:42 +08:00
dark-basic #DarkBasic BasicHD
628386b453 Update Spanish strings.xml 2017-07-24 01:37:23 +08:00
Leonidas P
b222bfb3e0 Update Greek translation 2017-07-24 01:36:09 +08:00
topjohnwu
ab199d883d Change su logs time granularity 2017-07-24 01:26:56 +08:00
topjohnwu
356065d1ee Rewrite SuLogAdapter 2017-07-24 01:26:56 +08:00
topjohnwu
76e7c5623d Simplify ApplicationAdapter filter 2017-07-24 01:26:56 +08:00
topjohnwu
085fba050a Introduce self-written SectionedAdapter 2017-07-24 01:26:45 +08:00
topjohnwu
295334d3ac Preserve toolbar elevation when restart activity 2017-07-23 00:47:54 +08:00
topjohnwu
36124ddca4 Update CallbackEvents 2017-07-23 00:39:38 +08:00
topjohnwu
bd6585765e Add locale settings 2017-07-23 00:33:24 +08:00
topjohnwu
c325deb4ed Random changes 2017-07-22 17:39:34 +08:00
topjohnwu
73bb0b10ee Prevent memory leak in CallbackEvent 2017-07-21 05:18:24 +08:00
topjohnwu
72820b162c Code cleanups 2017-07-21 05:08:39 +08:00
topjohnwu
89e5b8d057 Switch to official BouncyCastle 2017-07-21 03:56:48 +08:00
topjohnwu
da4f53ebbb Don't store multiple repo copies in memory 2017-07-21 02:46:19 +08:00
topjohnwu
8458553b74 Update database helper 2017-07-21 02:10:00 +08:00
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
126 changed files with 6592 additions and 5406 deletions

5
.gitignore vendored
View File

@@ -3,6 +3,9 @@
/local.properties
.idea/
/build
app/app-release.apk
app/release
*.hprof
app/.externalNativeBuild/
*.sh
public.certificate.x509.pem
private.key.pk8

View File

@@ -1,4 +1,7 @@
# 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
This is one of the submodules used in Magisk. The project is licensed under GPL v3 (or newer).
More info are written in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk)
## Building Notes
You need to install CMake and NDK to build the zipadjust library.
There are several files required to let Magisk Manager work properly, and they can be copied by using the build script in the [Magisk Main Repo](https://github.com/topjohnwu/Magisk). These files are: `magisk_uninstaller.sh`, `util_functions.sh`, `public.certificate.x509.pem`, and `private.key.pk8` under the `app/src/main/assets` folder.

View File

@@ -1,28 +1,30 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
compileSdkVersion 26
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 25
versionCode 27
versionName "4.3.0"
jackOptions {
enabled true
jackInProcess true
}
targetSdkVersion 26
versionCode 52
versionName "5.2.0"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
javaCompileOptions {
annotationProcessorOptions {
argument('butterknife.debuggable', 'false')
}
}
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
@@ -31,34 +33,34 @@ 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.3.1'
compile 'com.android.support:cardview-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
compile 'com.android.support:support-v4:25.3.1'
compile 'com.jakewharton:butterknife:8.5.1'
compile 'com.github.clans:fab:1.6.4'
compile 'com.thoughtbot:expandablerecyclerview:1.4'
compile 'us.feras.mdv:markdownview:1.1.0'
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'
implementation 'com.android.support:cardview-v7:26.0.0'
implementation 'com.android.support:design:26.0.0'
implementation 'com.android.support:support-v4:26.0.0'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.9.0'
implementation 'org.bouncycastle:bcprov-jdk15on:1.57'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.57'
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

View File

@@ -16,10 +16,10 @@
# public *;
#}
-keep class android.support.v7.internal.** { *; }
-keep interface android.support.v7.internal.** { *; }
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
# BouncyCastle
-keep class org.bouncycastle.** { *; }
-dontwarn javax.naming.**
-dontwarn android.content.**
-dontwarn android.animation.**
# SpongyCastle
-keep class org.spongycastle.** {*;}

View File

@@ -1,14 +1,14 @@
<?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"
@@ -21,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"
@@ -30,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"
@@ -52,21 +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" />
<service android:name=".services.BootupIntentService" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.ManagerUpdate" />
<service android:name=".services.OnBootIntentService" />
<service
android:name=".services.UpdateCheckService"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true" />
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE" />
<provider
android:name="android.support.v4.content.FileProvider"
@@ -84,4 +95,4 @@
</application>
</manifest>
</manifest>

View File

@@ -1,133 +0,0 @@
[ -z $BOOTMODE ] && BOOTMODE=false
# This path should work in any cases
TMPDIR=/dev/tmp
BOOTTMP=$TMPDIR/boottmp
MAGISKBIN=/data/magisk
CHROMEDIR=$MAGISKBIN/chromeos
SYSTEMLIB=/system/lib
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64
# Default permissions
umask 022
ui_print_wrapper() {
type ui_print >/dev/null && ui_print "$1" || echo "$1"
}
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
}
find_boot_image() {
if [ -z "$BOOTIMAGE" ]; then
for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`
if [ ! -z "$BOOTIMAGE" ]; then break; fi
done
fi
if [ -z "$BOOTIMAGE" ]; then
FSTAB="/etc/recovery.fstab"
[ ! -f "$FSTAB" ] && FSTAB="/etc/recovery.fstab.bak"
[ -f "$FSTAB" ] && BOOTIMAGE=`grep -E '\b/boot\b' "$FSTAB" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
fi
}
# Environments
# Set permissions
chmod -R 755 $CHROMEDIR/futility $MAGISKBIN 2>/dev/null
# Temporary busybox for installation
mkdir -p $TMPDIR/busybox
$MAGISKBIN/busybox --install -s $TMPDIR/busybox
rm -f $TMPDIR/busybox/su $TMPDIR/busybox/sh $TMPDIR/busybox/reboot
PATH=$TMPDIR/busybox:$PATH
# Find the boot image
find_boot_image
if [ -z "$BOOTIMAGE" ]; then
ui_print_wrapper "! Unable to detect boot image"
exit 1
fi
ui_print_wrapper "- Found Boot Image: $BOOTIMAGE"
rm -rf $BOOTTMP 2>/dev/null
mkdir -p $BOOTTMP
cd $BOOTTMP
ui_print_wrapper "- Unpacking boot image"
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --unpack $BOOTIMAGE
if [ $? -ne 0 ]; then
ui_print_wrapper "! Unable to unpack boot image"
exit 1
fi
# Update our previous backup to new format if exists
if [ -f /data/stock_boot.img ]; then
SHA1=`LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --sha1 /data/stock_boot.img | tail -n 1`
STOCKDUMP=/data/stock_boot_${SHA1}.img
mv /data/stock_boot.img $STOCKDUMP
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --compress $STOCKDUMP
fi
# Detect boot image state
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-test ramdisk.cpio
case $? in
0 )
ui_print_wrapper "! Magisk is not installed!"
ui_print_wrapper "! Nothing to uninstall"
exit
;;
1 )
# Find SHA1 of stock boot image
if [ -z $SHA1 ]; then
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc`
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
rm -f init.magisk.rc
fi
if [ -f ${STOCKDUMP}.gz ]; then
ui_print_wrapper "- Boot image backup found!"
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
else
ui_print_wrapper "! Boot image backup unavailable"
ui_print_wrapper "- Restoring ramdisk with backup"
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
fi
;;
2 )
ui_print_wrapper "- SuperSU patched image detected"
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
;;
esac
# Sign chromeos boot
if [ -f chromeos ]; then
echo > config
echo > bootloader
LD_LIBRARY_PATH=$SYSTEMLIB $CHROMEDIR/futility vbutil_kernel --pack stock_boot.img.signed --keyblock $CHROMEDIR/kernel.keyblock --signprivate $CHROMEDIR/kernel_data_key.vbprivk --version 1 --vmlinuz stock_boot.img --config config --arch arm --bootloader bootloader --flags 0x1
rm -f stock_boot.img
mv stock_boot.img.signed stock_boot.img
fi
ui_print_wrapper "- Flashing stock/reverted image"
[ ! -L "$BOOTIMAGE" ] && dd if=/dev/zero of=$BOOTIMAGE bs=4096 2>/dev/null
dd if=stock_boot.img of=$BOOTIMAGE bs=4096
ui_print_wrapper "- Removing Magisk files"
rm -rf /cache/magisk.log /cache/last_magisk.log /cache/magiskhide.log /cache/.disable_magisk \
/cache/magisk /cache/magisk_merge /cache/magisk_mount /cache/unblock /cache/magisk_uninstaller.sh \
/data/Magisk.apk /data/magisk.apk /data/magisk.img /data/magisk_merge.img \
/data/busybox /data/magisk /data/custom_ramdisk_patch.sh 2>/dev/null
$BOOTMODE && reboot

Binary file not shown.

View File

@@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIEqDCCA5CgAwIBAgIJAJNurL4H8gHfMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
Fw0wODAyMjkwMTMzNDZaFw0zNTA3MTcwMTMzNDZaMIGUMQswCQYDVQQGEwJVUzET
MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
hvcNAQEBBQADggENADCCAQgCggEBANaTGQTexgskse3HYuDZ2CU+Ps1s6x3i/waM
qOi8qM1r03hupwqnbOYOuw+ZNVn/2T53qUPn6D1LZLjk/qLT5lbx4meoG7+yMLV4
wgRDvkxyGLhG9SEVhvA4oU6Jwr44f46+z4/Kw9oe4zDJ6pPQp8PcSvNQIg1QCAcy
4ICXF+5qBTNZ5qaU7Cyz8oSgpGbIepTYOzEJOmc3Li9kEsBubULxWBjf/gOBzAzU
RNps3cO4JFgZSAGzJWQTT7/emMkod0jb9WdqVA2BVMi7yge54kdVMxHEa5r3b97s
zI5p58ii0I54JiCUP5lyfTwE/nKZHZnfm644oLIXf6MdW2r+6R8CAQOjgfwwgfkw
HQYDVR0OBBYEFEhZAFY9JyxGrhGGBaR0GawJyowRMIHJBgNVHSMEgcEwgb6AFEhZ
AFY9JyxGrhGGBaR0GawJyowRoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAJNurL4H8gHfMAwGA1Ud
EwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHqvlozrUMRBBVEY0NqrrwFbinZa
J6cVosK0TyIUFf/azgMJWr+kLfcHCHJsIGnlw27drgQAvilFLAhLwn62oX6snb4Y
LCBOsVMR9FXYJLZW2+TcIkCRLXWG/oiVHQGo/rWuWkJgU134NDEFJCJGjDbiLCpe
+ZTWHdcwauTJ9pUbo8EvHRkU3cYfGmLaLfgn9gP+pWA7LFQNvXwBnDa6sppCccEX
31I828XzgXpJ4O+mDL1/dBd+ek8ZPUP0IgdyZm5MTYPhvVqGCHzzTy3sIeJFymwr
sBbmg2OAUNLEMO6nwmocSdN2ClirfxqCzJOLSDE4QyS9BAH6EhY6UFcOaE0=
-----END CERTIFICATE-----

View File

@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
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.AlertDialog;
@@ -13,13 +12,11 @@ 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.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.utils.Logger;
import java.io.IOException;
import java.io.InputStream;
@@ -29,7 +26,7 @@ import butterknife.ButterKnife;
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";
@@ -45,10 +42,8 @@ public class AboutActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String theme = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("theme", "");
Logger.dev("AboutActivity: Theme is " + theme);
if (getApplicationContext().isDarkTheme) {
setTheme(R.style.AppTheme_Dark);
setTheme(R.style.AppTheme_Transparent_Dark);
}
setContentView(R.layout.activity_about);
ButterKnife.bind(this);
@@ -135,18 +130,4 @@ public class AboutActivity extends Activity {
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,228 +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.design.widget.Snackbar;
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.asyncs.ProcessMagiskZip;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.utils.CallbackEvent;
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 java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
public class InstallFragment extends Fragment implements CallbackEvent.Listener<Void> {
private static final String UNINSTALLER = "magisk_uninstaller.sh";
@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.install_button) CardView installButton;
@BindView(R.id.install_text) TextView installText;
@BindView(R.id.uninstall_button) CardView uninstallButton;
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
@OnClick(R.id.detect_bootimage)
public void toAutoDetect() {
if (magiskManager.bootBlock != null) {
spinner.setSelection(0);
}
}
@OnClick(R.id.install_button)
public void install() {
String bootImage = null;
if (magiskManager.blockList != null) {
int idx = spinner.getSelectedItemPosition();
if (magiskManager.bootBlock != null) {
if (idx > 0) {
bootImage = magiskManager.blockList.get(idx - 1);
}
} else {
if (idx > 0) {
bootImage = magiskManager.blockList.get(idx - 1);
} else {
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
}
}
}
final String finalBootImage = bootImage;
String filename = "Magisk-v" + magiskManager.remoteMagiskVersion + ".zip";
new AlertDialogBuilder(getActivity())
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
.setMessage(getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
(dialogInterface, i) -> Utils.dlAndReceive(
getActivity(),
new DownloadReceiver() {
private String boot = finalBootImage;
private boolean enc = keepEncChkbox.isChecked();
private boolean verity = keepVerityChkbox.isChecked();
@Override
public void onDownloadDone(Uri uri) {
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
}
},
magiskManager.magiskLink,
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
if (magiskManager.releaseNoteLink != null) {
Intent openReleaseNoteLink = new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink));
openReleaseNoteLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
magiskManager.startActivity(openReleaseNoteLink);
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
@OnClick(R.id.uninstall_button)
public void uninstall() {
new AlertDialogBuilder(getActivity())
.setTitle(R.string.uninstall_magisk_title)
.setMessage(R.string.uninstall_magisk_msg)
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
try {
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
File uninstaller = new File(magiskManager.getCacheDir(), 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, "mv -f " + uninstaller + " /cache/" + UNINSTALLER,
"reboot");
}
}.start();
} catch (IOException e) {
e.printStackTrace();
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
private Unbinder unbinder;
private MagiskManager magiskManager;
@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);
magiskManager = getApplication();
if (magiskManager.magiskVersion < 0) {
currentVersionTitle.setText(getString(R.string.current_magisk_title, getString(R.string.version_none)));
} else {
currentVersionTitle.setText(getString(R.string.current_magisk_title, "v" + magiskManager.magiskVersionString));
}
installTitle.setText(getString(R.string.install_magisk_title, "v" + String.format(Locale.US, "%.1f", magiskManager.remoteMagiskVersion)));
updateUI();
return v;
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
updateUI();
}
private void updateUI() {
if (magiskManager.blockList == null || !Shell.rootAccess()) {
uninstallButton.setVisibility(View.GONE);
installText.setText(R.string.download);
detectButton.setEnabled(false);
keepEncChkbox.setEnabled(false);
keepVerityChkbox.setEnabled(false);
spinner.setEnabled(false);
} else {
uninstallButton.setVisibility(magiskManager.magiskVersion > 10.3 ? View.VISIBLE : View.GONE);
installText.setText(R.string.download_install);
detectButton.setEnabled(true);
keepEncChkbox.setEnabled(true);
keepVerityChkbox.setEnabled(true);
spinner.setEnabled(true);
List<String> items = new ArrayList<>();
if (magiskManager.bootBlock != null) {
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
} else {
items.add(getString(R.string.cannot_auto_detect));
}
items.addAll(magiskManager.blockList);
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();
}
}
@Override
public void onStart() {
super.onStart();
getActivity().setTitle(R.string.install);
magiskManager.blockDetectionDone.register(this);
}
@Override
public void onStop() {
magiskManager.blockDetectionDone.unRegister(this);
super.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
}

View File

@@ -29,9 +29,9 @@ public class LogFragment extends Fragment {
View v = inflater.inflate(R.layout.fragment_log, container, false);
unbinder = ButterKnife.bind(this, v);
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
((MainActivity) getActivity()).toolbar.setElevation(0);
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
if (getApplication().isSuClient) {
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
@@ -39,6 +39,8 @@ public class LogFragment extends Fragment {
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

@@ -1,12 +1,9 @@
package com.topjohnwu.magisk;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -15,16 +12,14 @@ import android.view.ViewGroup;
import android.widget.SearchView;
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
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 com.topjohnwu.magisk.utils.Topic;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class MagiskHideFragment extends Fragment implements CallbackEvent.Listener<Void> {
public class MagiskHideFragment extends Fragment implements Topic.Subscriber {
private Unbinder unbinder;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@@ -46,13 +41,12 @@ public class MagiskHideFragment extends Fragment implements CallbackEvent.Listen
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
unbinder = ButterKnife.bind(this, view);
PackageManager packageManager = getActivity().getPackageManager();
lastFilter = "";
mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.setOnRefreshListener(() -> new MagiskHide(getActivity()).list());
mSwipeRefreshLayout.setOnRefreshListener(() -> appAdapter.refresh());
appAdapter = new ApplicationAdapter(packageManager);
appAdapter = new ApplicationAdapter(getActivity());
recyclerView.setAdapter(appAdapter);
searchListener = new SearchView.OnQueryTextListener() {
@@ -71,9 +65,7 @@ public class MagiskHideFragment extends Fragment implements CallbackEvent.Listen
}
};
if (getApplication().magiskHideDone.isTriggered) {
onTrigger(getApplication().magiskHideDone);
}
getActivity().setTitle(R.string.magiskhide);
return view;
}
@@ -81,23 +73,10 @@ public class MagiskHideFragment extends Fragment implements CallbackEvent.Listen
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_magiskhide, menu);
SearchView search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.app_search));
SearchView search = (SearchView) menu.findItem(R.id.app_search).getActionView();
search.setOnQueryTextListener(searchListener);
}
@Override
public void onStart() {
super.onStart();
getActivity().setTitle(R.string.magiskhide);
getApplication().magiskHideDone.register(this);
}
@Override
public void onStop() {
getApplication().magiskHideDone.unRegister(this);
super.onStop();
}
@Override
public void onDestroyView() {
super.onDestroyView();
@@ -105,12 +84,13 @@ public class MagiskHideFragment extends Fragment implements CallbackEvent.Listen
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
Logger.dev("MagiskHideFragment: UI refresh");
appAdapter.setLists(getApplication().appList, getApplication().magiskHideList);
public void onTopicPublished(Topic topic) {
mSwipeRefreshLayout.setRefreshing(false);
if (!TextUtils.isEmpty(lastFilter)) {
appAdapter.filter(lastFilter);
}
appAdapter.filter(lastFilter);
}
@Override
public Topic[] getSubscription() {
return new Topic[] { getApplication().magiskHideDone };
}
}

View File

@@ -1,16 +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.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -24,17 +21,15 @@ import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.SerialTask;
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;
@@ -127,45 +122,28 @@ public class MagiskLogFragment extends Fragment {
}
}
public class LogManager extends SerialTask<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();
Shell.getShell(magiskManager).su(logList, "cat " + MAGISK_LOG);
return logList.toString();
case 1:
Shell.su("echo > " + MAGISK_LOG);
Shell.getShell(magiskManager).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",
@@ -180,19 +158,14 @@ public class MagiskLogFragment extends Fragment {
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;
}
try (FileWriter out = new FileWriter(targetFile)) {
FileWritingList fileWritingList = new FileWritingList(out);
Shell.getShell(magiskManager).su(fileWritingList, "cat " + MAGISK_LOG);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;
return true;
}
return null;
}
@@ -200,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);
@@ -215,27 +186,64 @@ public class MagiskLogFragment extends Fragment {
hsvLog.post(() -> hsvLog.scrollTo(0, 0));
break;
case 2:
bool = (boolean) o;
boolean bool = (boolean) o;
if (bool) {
Toast.makeText(getActivity(), targetFile.toString(), Toast.LENGTH_LONG).show();
MagiskLogFragment.this.getApplication().toast(targetFile.toString(), Toast.LENGTH_LONG);
} else {
Toast.makeText(getActivity(), getString(R.string.logs_save_failed), Toast.LENGTH_LONG).show();
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;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,14 +20,15 @@ import android.view.MenuItem;
import android.view.View;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends Activity
implements NavigationView.OnNavigationItemSelectedListener, CallbackEvent.Listener<Void> {
implements NavigationView.OnNavigationItemSelectedListener, Topic.Subscriber {
private final Handler mDrawerHandler = new Handler();
private SharedPreferences prefs;
@@ -80,8 +81,6 @@ public class MainActivity extends Activity
navigate(getIntent().getStringExtra(MagiskManager.INTENT_SECTION));
navigationView.setNavigationItemSelectedListener(this);
getApplicationContext().reloadMainActivity.register(this);
getApplicationContext().updateCheckDone.register(this);
}
@@ -91,31 +90,15 @@ public class MainActivity extends Activity
checkHideSection();
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
navigate(savedInstanceState.getInt(MagiskManager.INTENT_SECTION, R.id.status));
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(MagiskManager.INTENT_SECTION, mDrawerItem);
}
@Override
protected void onDestroy() {
getApplicationContext().reloadMainActivity.unRegister(this);
getApplicationContext().updateCheckDone.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
@@ -127,38 +110,38 @@ public class MainActivity extends Activity
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
if (event == getApplicationContext().reloadMainActivity) {
recreate();
} else if (event == getApplicationContext().updateCheckDone) {
checkHideSection();
}
public void onTopicPublished(Topic topic) {
recreate();
}
private void checkHideSection() {
@Override
public Topic[] getSubscription() {
return new Topic[] { getApplicationContext().reloadActivity };
}
public void checkHideSection() {
Menu menu = navigationView.getMenu();
menu.findItem(R.id.magiskhide).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersion >= 8
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 1300
&& prefs.getBoolean("magiskhide", false));
menu.findItem(R.id.modules).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
menu.findItem(R.id.downloads).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
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);
menu.findItem(R.id.install).setVisible(getApplicationContext().remoteMagiskVersion > 0);
}
public void navigate(String item) {
int itemId = R.id.status;
int itemId = R.id.magisk;
if (item != null) {
switch (item) {
case "status":
itemId = R.id.status;
case "magisk":
itemId = R.id.magisk;
break;
case "install":
itemId = R.id.install;
itemId = -1;
break;
case "superuser":
itemId = R.id.superuser;
@@ -191,11 +174,15 @@ public class MainActivity extends Activity
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);

View File

@@ -2,7 +2,6 @@ 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.widget.SwipeRefreshLayout;
@@ -12,23 +11,22 @@ 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.FlashZip;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Topic;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.Unbinder;
public class ModulesFragment extends Fragment implements CallbackEvent.Listener<Void> {
public class ModulesFragment extends Fragment implements Topic.Subscriber {
private static final int FETCH_ZIP_CODE = 2;
@@ -36,7 +34,12 @@ public class ModulesFragment extends Fragment implements CallbackEvent.Listener<
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.empty_rv) TextView emptyRv;
@BindView(R.id.fab) FloatingActionButton fabio;
@OnClick(R.id.fab)
public void selectFile() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/zip");
startActivityForResult(intent, FETCH_ZIP_CODE);
}
private List<Module> listModules = new ArrayList<>();
@@ -46,12 +49,6 @@ public class ModulesFragment extends Fragment implements CallbackEvent.Listener<
View view = inflater.inflate(R.layout.fragment_modules, container, false);
unbinder = ButterKnife.bind(this, view);
fabio.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/zip");
startActivityForResult(intent, FETCH_ZIP_CODE);
});
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.GONE);
new LoadModules(getActivity()).exec();
@@ -69,40 +66,30 @@ public class ModulesFragment extends Fragment implements CallbackEvent.Listener<
}
});
if (getApplication().moduleLoadDone.isTriggered) {
updateUI();
}
getActivity().setTitle(R.string.modules);
return view;
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
public void onTopicPublished(Topic topic) {
Logger.dev("ModulesFragment: UI refresh triggered");
updateUI();
}
@Override
public Topic[] getSubscription() {
return new Topic[] { getApplication().moduleLoadDone };
}
@Override
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 FlashZip(getActivity(), uri).exec();
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(data.getData()).putExtra("ACTION", "flash");
startActivity(intent);
}
}
@Override
public void onStart() {
super.onStart();
getApplication().moduleLoadDone.register(this);
getActivity().setTitle(R.string.modules);
}
@Override
public void onStop() {
getApplication().moduleLoadDone.unRegister(this);
super.onStop();
}
@Override

View File

@@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -14,39 +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.asyncs.LoadRepos;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger;
import java.util.ArrayList;
import java.util.List;
import com.topjohnwu.magisk.utils.Topic;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
public class ReposFragment extends Fragment implements CallbackEvent.Listener<Void> {
public class ReposFragment extends Fragment implements Topic.Subscriber {
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) {
@@ -60,24 +43,40 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
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));
recyclerView.setAdapter(mSectionedAdapter);
adapter = new ReposAdapter(getApplication().repoDB, getApplication().moduleMap);
recyclerView.setAdapter(adapter);
mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.GONE);
new LoadRepos(getActivity()).exec();
new UpdateRepos(getActivity()).exec();
});
if (getApplication().repoLoadDone.isTriggered) {
reloadRepos();
updateUI();
}
getActivity().setTitle(R.string.downloads);
searchListener = new SearchView.OnQueryTextListener() {
return view;
}
@Override
public void onTopicPublished(Topic topic) {
Logger.dev("ReposFragment: UI refresh triggered");
mSwipeRefreshLayout.setRefreshing(false);
adapter.notifyDBChanged();
recyclerView.setVisibility(adapter.getItemCount() == 0 ? View.GONE : View.VISIBLE);
emptyRv.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
@Override
public Topic[] getSubscription() {
return new Topic[] { getApplication().repoLoadDone };
}
@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;
@@ -85,39 +84,10 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
@Override
public boolean onQueryTextChange(String newText) {
new FilterApps().exec(newText);
adapter.filter(newText);
return false;
}
};
return view;
}
@Override
public void onTrigger(CallbackEvent<Void> 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();
getApplication().repoLoadDone.register(this);
getActivity().setTitle(R.string.downloads);
}
@Override
public void onStop() {
getApplication().repoLoadDone.unRegister(this);
super.onStop();
});
}
@Override
@@ -125,92 +95,4 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
super.onDestroyView();
unbinder.unbind();
}
private void reloadRepos() {
mUpdateRepos.clear();
mInstalledRepos.clear();
mOthersRepos.clear();
for (Repo repo : getApplication().repoMap.values()) {
Module module = getApplication().moduleMap.get(repo.getId());
if (module != null) {
if (repo.getVersionCode() > module.getVersionCode()) {
mUpdateRepos.add(repo);
} else {
mInstalledRepos.add(repo);
}
} else {
mOthersRepos.add(repo);
}
}
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 ParallelTask<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

@@ -6,15 +6,13 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.GetBootBlocks;
import com.topjohnwu.magisk.asyncs.LoadApps;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Utils;
public class SplashActivity extends Activity{
@@ -27,47 +25,37 @@ public class SplashActivity extends Activity{
MagiskManager magiskManager = getApplicationContext();
// Init the info and configs and root shell
// Init the info and configs and root sh
magiskManager.init();
// Initialize the update check service, notify every 3 hours
if (!"install".equals(getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
ComponentName service = new ComponentName(magiskManager, UpdateCheckService.class);
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(3 * 60 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
// 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) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
}
loadModuleTask.setCallBack(() -> new UpdateRepos(getApplication()).exec());
}
// Now fire all async tasks
new GetBootBlocks(this).exec();
if (magiskManager.magiskHide && magiskManager.magiskVersion > 11 &&
!magiskManager.magiskHideStarted) {
new MagiskHide().enable();
loadModuleTask.exec();
Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section);
}
new LoadModules(this) {
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
new LoadRepos(activity).exec();
}
}.exec();
new LoadApps(this).exec();
new CheckUpdates(this, false){
@Override
protected void onPostExecute(Void v) {
super.onPostExecute(v);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
Intent intent = new Intent(magiskManager, MainActivity.class);
if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section);
}
startActivity(intent);
finish();
}
}.exec();
startActivity(intent);
finish();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -13,10 +13,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -28,7 +24,8 @@ public class SuLogFragment extends Fragment {
@BindView(R.id.recyclerView) RecyclerView recyclerView;
private Unbinder unbinder;
private SuLogDatabaseHelper dbHelper;
private MagiskManager magiskManager;
private SuLogAdapter adapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -48,8 +45,9 @@ 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();
adapter = new SuLogAdapter(magiskManager.suDB);
recyclerView.setAdapter(adapter);
updateList();
@@ -57,13 +55,12 @@ public class SuLogFragment extends Fragment {
}
private void updateList() {
List<SuLogEntry> logs = dbHelper.getLogList();
adapter.notifyDBChanged();
if (logs.size() == 0) {
if (adapter.getSectionCount() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
recyclerView.setAdapter(new SuLogAdapter(logs).getAdapter());
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
@@ -76,7 +73,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

@@ -11,7 +11,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.adapters.PolicyAdapter;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.superuser.Policy;
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.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
@@ -13,13 +14,16 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import butterknife.BindView;
@@ -40,20 +44,19 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
private List<ApplicationInfo> mOriginalList, mList;
private List<String> mHideList;
private PackageManager packageManager;
private PackageManager pm;
private ApplicationFilter filter;
private Topic magiskHideDone;
private Shell shell;
public ApplicationAdapter(PackageManager packageManager) {
public ApplicationAdapter(Context context) {
mOriginalList = mList = Collections.emptyList();
mHideList = Collections.emptyList();
this.packageManager = packageManager;
filter = new ApplicationFilter();
}
public void setLists(List<ApplicationInfo> listApps, List<String> hideList) {
mOriginalList = mList = listApps;
mHideList = hideList;
notifyDataSetChanged();
pm = context.getPackageManager();
magiskHideDone = Utils.getMagiskManager(context).magiskHideDone;
shell = Shell.getShell(context);
new LoadApps().exec();
}
@Override
@@ -66,8 +69,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
public void onBindViewHolder(final ViewHolder holder, int position) {
ApplicationInfo info = mList.get(position);
holder.appIcon.setImageDrawable(info.loadIcon(packageManager));
holder.appName.setText(info.loadLabel(packageManager));
holder.appIcon.setImageDrawable(info.loadIcon(pm));
holder.appName.setText(info.loadLabel(pm));
holder.appPackage.setText(info.packageName);
// Remove all listeners
@@ -86,10 +89,10 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
holder.checkBox.setChecked(mHideList.contains(info.packageName));
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
if (isChecked) {
new MagiskHide().add(info.packageName);
Utils.addMagiskHide(shell, info.packageName);
mHideList.add(info.packageName);
} else {
new MagiskHide().rm(info.packageName);
Utils.rmMagiskHide(shell, info.packageName);
mHideList.remove(info.packageName);
}
});
@@ -105,6 +108,10 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
filter.filter(constraint);
}
public void refresh() {
new LoadApps().exec();
}
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_icon) ImageView appIcon;
@@ -122,31 +129,47 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<ApplicationInfo> filteredApps;
if (constraint == null || constraint.length() == 0) {
filteredApps = mOriginalList;
mList = mOriginalList;
} else {
filteredApps = new ArrayList<>();
mList = new ArrayList<>();
String filter = constraint.toString().toLowerCase();
for (ApplicationInfo info : mOriginalList) {
if (Utils.lowercaseContains(info.loadLabel(packageManager), filter)
if (Utils.lowercaseContains(info.loadLabel(pm), filter)
|| Utils.lowercaseContains(info.packageName, filter)) {
filteredApps.add(info);
mList.add(info);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredApps;
results.count = filteredApps.size();
return results;
return null;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mList = (List<ApplicationInfo>) results.values;
notifyDataSetChanged();
}
}
private class LoadApps extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
mOriginalList = pm.getInstalledApplications(0);
for (Iterator<ApplicationInfo> i = mOriginalList.iterator(); i.hasNext(); ) {
ApplicationInfo info = i.next();
if (ApplicationAdapter.BLACKLIST.contains(info.packageName) || !info.enabled) {
i.remove();
}
}
Collections.sort(mOriginalList, (a, b) -> a.loadLabel(pm).toString().toLowerCase()
.compareTo(b.loadLabel(pm).toString().toLowerCase()));
mHideList = Utils.listMagiskHide(shell);
return null;
}
@Override
protected void onPostExecute(Void v) {
magiskHideDone.publish(false);
}
}
}

View File

@@ -12,7 +12,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.SerialTask;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.utils.Shell;
@@ -39,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();
@@ -53,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 SerialTask<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;
SnackbarMaker.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 SerialTask<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;
SnackbarMaker.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,9 +1,12 @@
package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -12,70 +15,113 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.MarkDownWindow;
import com.topjohnwu.magisk.asyncs.ProcessRepoZip;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.MarkDownWindow;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder> {
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
private List<Repo> mUpdateRepos, mInstalledRepos, mOthersRepos;
private Context mContext;
private static final int UPDATES = 0;
private static final int INSTALLED = 1;
private static final int OTHERS = 2;
public ReposAdapter(List<Repo> update, List<Repo> installed, List<Repo> others) {
mUpdateRepos = update;
mInstalledRepos = installed;
mOthersRepos = others;
private Cursor repoCursor = null;
private Map<String, Module> moduleMap;
private RepoDatabaseHelper repoDB;
private List<Pair<Integer, List<Repo>>> repoPairs;
public ReposAdapter(RepoDatabaseHelper db, Map<String, Module> map) {
repoDB = db;
moduleMap = map;
repoPairs = new ArrayList<>();
}
@Override
public int getSectionCount() {
return repoPairs.size();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
mContext = parent.getContext();
View v = LayoutInflater.from(mContext).inflate(R.layout.list_item_repo, parent, false);
return new ViewHolder(v);
public int getItemCount(int section) {
return repoPairs.get(section).second.size();
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Repo repo = getItem(position);
public SectionHolder onCreateSectionViewHolder(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.section, parent, false);
return new SectionHolder(v);
}
@Override
public RepoHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false);
return new RepoHolder(v);
}
@Override
public void onBindSectionViewHolder(SectionHolder holder, int section) {
switch (repoPairs.get(section).first) {
case UPDATES:
holder.sectionText.setText(R.string.update_available);
break;
case INSTALLED:
holder.sectionText.setText(R.string.installed);
break;
case OTHERS:
holder.sectionText.setText(R.string.not_installed);
break;
}
}
@Override
public void onBindItemViewHolder(RepoHolder holder, int section, int position) {
Repo repo = repoPairs.get(section).second.get(position);
Context context = holder.itemView.getContext();
holder.title.setText(repo.getName());
holder.versionName.setText(repo.getVersion());
String author = repo.getAuthor();
holder.author.setText(TextUtils.isEmpty(author) ? null : mContext.getString(R.string.author, author));
holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
holder.description.setText(repo.getDescription());
holder.infoLayout.setOnClickListener(v -> new MarkDownWindow(null, repo.getDetailUrl(), mContext));
holder.infoLayout.setOnClickListener(v ->
new MarkDownWindow((Activity) context, null, repo.getDetailUrl()).exec());
holder.downloadImage.setOnClickListener(v -> {
String filename = repo.getName() + "-" + repo.getVersion() + ".zip";
new AlertDialogBuilder(mContext)
.setTitle(mContext.getString(R.string.repo_install_title, repo.getName()))
.setMessage(mContext.getString(R.string.repo_install_msg, filename))
new AlertDialogBuilder(context)
.setTitle(context.getString(R.string.repo_install_title, repo.getName()))
.setMessage(context.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> Utils.dlAndReceive(
mContext,
context,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
new ProcessRepoZip(activity, uri, true).exec();
new ProcessRepoZip((Activity) context, uri, true).exec();
}
},
repo.getZipUrl(),
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.download, (d, i) -> Utils.dlAndReceive(
mContext,
context,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
new ProcessRepoZip(activity, uri, false).exec();
new ProcessRepoZip((Activity) context, uri, false).exec();
}
},
repo.getZipUrl(),
@@ -85,26 +131,62 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
});
}
@Override
public int getItemCount() {
return mUpdateRepos.size() + mInstalledRepos.size() + mOthersRepos.size();
public void notifyDBChanged() {
if (repoCursor != null)
repoCursor.close();
repoCursor = repoDB.getRepoCursor();
filter("");
}
private Repo getItem(int position) {
if (position >= mUpdateRepos.size()) {
position -= mUpdateRepos.size();
if (position >= mInstalledRepos.size()) {
position -= mInstalledRepos.size();
return mOthersRepos.get(position);
} else {
return mInstalledRepos.get(position);
public void filter(String s) {
List<Repo> updates = new ArrayList<>();
List<Repo> installed = new ArrayList<>();
List<Repo> others = new ArrayList<>();
repoPairs.clear();
while (repoCursor.moveToNext()) {
Repo repo = new Repo(repoCursor);
if (repo.getName().toLowerCase().contains(s.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(s.toLowerCase())
|| repo.getDescription().toLowerCase().contains(s.toLowerCase())
) {
// Passed the repoFilter
Module module = moduleMap.get(repo.getId());
if (module != null) {
if (repo.getVersionCode() > module.getVersionCode()) {
// Updates
updates.add(repo);
} else {
installed.add(repo);
}
} else {
others.add(repo);
}
}
} else {
return mUpdateRepos.get(position);
}
repoCursor.moveToFirst();
if (!updates.isEmpty())
repoPairs.add(new Pair<>(UPDATES, updates));
if (!installed.isEmpty())
repoPairs.add(new Pair<>(INSTALLED, installed));
if (!others.isEmpty())
repoPairs.add(new Pair<>(OTHERS, others));
notifyDataSetChanged();
}
static class SectionHolder extends RecyclerView.ViewHolder {
@BindView(R.id.section_text) TextView sectionText;
SectionHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
static class RepoHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title) TextView title;
@BindView(R.id.version_name) TextView versionName;
@@ -113,7 +195,7 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
@BindView(R.id.info_layout) LinearLayout infoLayout;
@BindView(R.id.download) ImageView downloadImage;
ViewHolder(View itemView) {
RepoHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}

View File

@@ -0,0 +1,93 @@
package com.topjohnwu.magisk.adapters;
import android.support.v7.widget.RecyclerView;
import android.view.ViewGroup;
public abstract class SectionedAdapter<S extends RecyclerView.ViewHolder, C extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int SECTION_TYPE = Integer.MIN_VALUE;
@Override
final public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == SECTION_TYPE)
return onCreateSectionViewHolder(parent);
return onCreateItemViewHolder(parent, viewType);
}
@Override
@SuppressWarnings("unchecked")
final public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
PositionInfo info = getPositionInfo(position);
if (info.position == -1)
onBindSectionViewHolder((S) holder, info.section);
else
onBindItemViewHolder((C) holder, info.section, info.position);
}
@Override
final public int getItemCount() {
int size, sec;
size = sec = getSectionCount();
for (int i = 0; i < sec; ++i){
size += getItemCount(i);
}
return size;
}
@Override
final public int getItemViewType(int position) {
PositionInfo info = getPositionInfo(position);
if (info.position == -1)
return SECTION_TYPE;
else
return getItemViewType(info.section, info.position);
}
public int getItemViewType(int section, int position) {
return 0;
}
protected int getSectionPosition(int section) {
return getItemPosition(section, -1);
}
protected int getItemPosition(int section, int position) {
int realPosition = 0;
// Previous sections
for (int i = 0; i < section; ++i) {
realPosition += getItemCount(i) + 1;
}
// Current section
realPosition += position + 1;
return realPosition;
}
private PositionInfo getPositionInfo(int position) {
int section = 0;
while (true) {
if (position == 0)
return new PositionInfo(section, -1);
position -= 1;
if (position < getItemCount(section))
return new PositionInfo(section, position);
position -= getItemCount(section++);
}
}
private static class PositionInfo {
int section;
int position;
PositionInfo(int section, int position) {
this.section = section;
this.position = position;
}
}
public abstract int getSectionCount();
public abstract int getItemCount(int section);
public abstract S onCreateSectionViewHolder(ViewGroup parent);
public abstract C onCreateItemViewHolder(ViewGroup parent, int viewType);
public abstract void onBindSectionViewHolder(S holder, int section);
public abstract void onBindItemViewHolder(C holder, int section, int position);
}

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);
}
}

View File

@@ -1,15 +1,9 @@
package com.topjohnwu.magisk.asyncs;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.NotificationCompat;
import com.topjohnwu.magisk.BuildConfig;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
@@ -18,55 +12,51 @@ import org.json.JSONObject;
public class CheckUpdates extends ParallelTask<Void, Void, Void> {
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json";
private static final int NOTIFICATION_ID = 1;
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/magisk_update.json";
private boolean showNotification = false;
public CheckUpdates(Context context, boolean b) {
this(context);
showNotification = b;
public CheckUpdates(Context context) {
super(context);
}
public CheckUpdates(Context context) {
magiskManager = Utils.getMagiskManager(context);
public CheckUpdates(Context context, boolean b) {
super(context);
showNotification = b;
}
@Override
protected Void doInBackground(Void... voids) {
String jsonStr = WebService.request(UPDATE_JSON, WebService.GET);
MagiskManager magiskManager = getMagiskManager();
if (magiskManager == null) return null;
String jsonStr = WebService.getString(UPDATE_JSON);
try {
JSONObject json = new JSONObject(jsonStr);
JSONObject magisk = json.getJSONObject("magisk");
magiskManager.remoteMagiskVersion = magisk.getDouble("versionCode");
magiskManager.remoteMagiskVersionString = magisk.getString("version");
magiskManager.remoteMagiskVersionCode = magisk.getInt("versionCode");
magiskManager.magiskLink = magisk.getString("link");
magiskManager.releaseNoteLink = magisk.getString("note");
} catch (JSONException ignored) {
}
JSONObject manager = json.getJSONObject("app");
magiskManager.remoteManagerVersionString = manager.getString("version");
magiskManager.remoteManagerVersionCode = manager.getInt("versionCode");
magiskManager.managerLink = manager.getString("link");
} catch (JSONException ignored) {}
return null;
}
@Override
protected void onPostExecute(Void v) {
if (magiskManager.magiskVersion < magiskManager.remoteMagiskVersion
&& showNotification && magiskManager.updateNotification) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(magiskManager.getString(R.string.magisk_update_title))
.setContentText(magiskManager.getString(R.string.magisk_update_available, magiskManager.remoteMagiskVersion))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true);
Intent intent = new Intent(magiskManager, SplashActivity.class);
intent.putExtra(MagiskManager.INTENT_SECTION, "install");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, builder.build());
MagiskManager magiskManager = getMagiskManager();
if (magiskManager == null) return;
if (showNotification && magiskManager.updateNotification) {
if (BuildConfig.VERSION_CODE < magiskManager.remoteManagerVersionCode) {
Utils.showManagerUpdate(magiskManager);
} else if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode) {
Utils.showMagiskUpdate(magiskManager);
}
}
magiskManager.updateCheckDone.trigger();
magiskManager.updateCheckDone.publish();
super.onPostExecute(v);
}
}

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