mirror of
https://github.com/topjohnwu/Magisk
synced 2025-10-27 04:02:14 +01:00
Compare commits
546 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d5cf8a6fe | ||
|
|
290959f74c | ||
|
|
4d9f58ee72 | ||
|
|
9241246de6 | ||
|
|
58a5d52b78 | ||
|
|
2906178ac3 | ||
|
|
e0afbb647b | ||
|
|
50be50cf6a | ||
|
|
77a9d3a5bc | ||
|
|
f9c7a4c933 | ||
|
|
2b759b84b0 | ||
|
|
1e45c63ea5 | ||
|
|
b14a260827 | ||
|
|
ade1597e03 | ||
|
|
2739d3cb67 | ||
|
|
dc5e78e142 | ||
|
|
e9759a5868 | ||
|
|
e7ab802498 | ||
|
|
42672c2e27 | ||
|
|
e65d61d313 | ||
|
|
076da5c7c4 | ||
|
|
9deaf2507c | ||
|
|
5c114c67de | ||
|
|
d904cb0441 | ||
|
|
bd1dd9d863 | ||
|
|
afebe734b8 | ||
|
|
e21a78164e | ||
|
|
1e0f96d0fd | ||
|
|
bf650332d8 | ||
|
|
f32e0af830 | ||
|
|
4c94f90e5d | ||
|
|
ffb4224640 | ||
|
|
89fff4830b | ||
|
|
16e4c67992 | ||
|
|
cf47214ee4 | ||
|
|
0feab753fb | ||
|
|
d0b6318b90 | ||
|
|
966e23b846 | ||
|
|
5b8a1fc2a7 | ||
|
|
02ea3ca525 | ||
|
|
0632b146b8 | ||
|
|
1b0b180761 | ||
|
|
0d11f73a1d | ||
|
|
533cb8eb58 | ||
|
|
8ac1181e9a | ||
|
|
5ca1892eb0 | ||
|
|
e32db6a0e8 | ||
|
|
82fff615d6 | ||
|
|
24a8f0808d | ||
|
|
4a7c3c06bc | ||
|
|
da93bbc1fe | ||
|
|
fa2dbe981e | ||
|
|
ce6cceae8b | ||
|
|
7b26e8b818 | ||
|
|
2da5fcb00b | ||
|
|
a079966f97 | ||
|
|
468796c23d | ||
|
|
5833aadef5 | ||
|
|
eb261c8026 | ||
|
|
a4c48847d1 | ||
|
|
43288be091 | ||
|
|
1ad7a6fe93 | ||
|
|
4e0a3f5e72 | ||
|
|
d7c33f647d | ||
|
|
9087207dc0 | ||
|
|
2760f37e6b | ||
|
|
3fa3426032 | ||
|
|
2e4dc91b96 | ||
|
|
aaaaa3d044 | ||
|
|
1edc4449d5 | ||
|
|
f3cd4da026 | ||
|
|
872c55207c | ||
|
|
339ca6d666 | ||
|
|
4aeac3b8f4 | ||
|
|
d625beb7f3 | ||
|
|
735b65c50c | ||
|
|
efb1eab327 | ||
|
|
49d4785da0 | ||
|
|
28e65ce383 | ||
|
|
c3b6a48373 | ||
|
|
a42ebd429b | ||
|
|
8f89010752 | ||
|
|
105a18f719 | ||
|
|
eb04ca4c4a | ||
|
|
6092d7ca88 | ||
|
|
66cad101c0 | ||
|
|
0a14f43f9c | ||
|
|
311c1f0dfd | ||
|
|
0499588107 | ||
|
|
d4d837a562 | ||
|
|
fbcbb20178 | ||
|
|
0914700fc6 | ||
|
|
eeced2fb5b | ||
|
|
6509e3d4f5 | ||
|
|
317052604b | ||
|
|
5538f7168c | ||
|
|
dcb9e4cd93 | ||
|
|
d9382f59bf | ||
|
|
403a0c770a | ||
|
|
f0f1cdc501 | ||
|
|
4e272b70ef | ||
|
|
8dc62a0232 | ||
|
|
9225b47568 | ||
|
|
d462873e74 | ||
|
|
fc19b50290 | ||
|
|
333fe6da0e | ||
|
|
75fcda9f81 | ||
|
|
44ba2a9903 | ||
|
|
2fceb1ad96 | ||
|
|
bacb5fa462 | ||
|
|
67f8dc494e | ||
|
|
3e4caabecb | ||
|
|
dcd5183b24 | ||
|
|
d80c6b42a6 | ||
|
|
64effe9385 | ||
|
|
96dd24e91d | ||
|
|
fbb4f85ef0 | ||
|
|
716f06846b | ||
|
|
241f2656fa | ||
|
|
e973d49517 | ||
|
|
c3bf9a095b | ||
|
|
abfc28db32 | ||
|
|
8b5652ced5 | ||
|
|
d6dbab53cd | ||
|
|
46de1ed968 | ||
|
|
9bebe07d5a | ||
|
|
ee4db43136 | ||
|
|
efac220998 | ||
|
|
31026b43f4 | ||
|
|
bc3fbe09f5 | ||
|
|
7ac55068db | ||
|
|
6abd9aa8a4 | ||
|
|
c91ebfbcc1 | ||
|
|
2f232fc670 | ||
|
|
41f5c8d96c | ||
|
|
4fd04e62af | ||
|
|
63a9a7d643 | ||
|
|
a63d6c03fd | ||
|
|
fd552e68a9 | ||
|
|
de4e26b488 | ||
|
|
fa3865e962 | ||
|
|
a6950b8aca | ||
|
|
8df96ff664 | ||
|
|
8b29267ad6 | ||
|
|
0ef92a4866 | ||
|
|
85bef8fa96 | ||
|
|
ca9f9fee9a | ||
|
|
b59e05c63e | ||
|
|
3c0630bfc0 | ||
|
|
bf84dd6518 | ||
|
|
f575155a41 | ||
|
|
bd240ba48c | ||
|
|
106a2bb7df | ||
|
|
82bbbe05b2 | ||
|
|
9956dc0995 | ||
|
|
fc76673802 | ||
|
|
17b5291bbb | ||
|
|
9908dfd79a | ||
|
|
2dbaf9595c | ||
|
|
9a16ab1bd7 | ||
|
|
9e5cb6cb91 | ||
|
|
8c19654d20 | ||
|
|
d5a7a75d9d | ||
|
|
851b676077 | ||
|
|
765b51285a | ||
|
|
8a338de696 | ||
|
|
8a61ae621d | ||
|
|
60e1e07e87 | ||
|
|
e51a3dacb9 | ||
|
|
9a8a27dbb9 | ||
|
|
2eb001876a | ||
|
|
b510dc51ac | ||
|
|
d7f7508fa2 | ||
|
|
e66b0bf3b2 | ||
|
|
0555b73a19 | ||
|
|
877a297de4 | ||
|
|
49559ec0ec | ||
|
|
30e45f863d | ||
|
|
434efec860 | ||
|
|
5022f00a55 | ||
|
|
8aac373ca3 | ||
|
|
c3586fe0a5 | ||
|
|
11f254e5e5 | ||
|
|
c61ec2465f | ||
|
|
fd5ad91d26 | ||
|
|
5c4c391f94 | ||
|
|
4dacffd7a1 | ||
|
|
61599059d5 | ||
|
|
f32a29911b | ||
|
|
b73d5753f2 | ||
|
|
2eee335b5f | ||
|
|
013a2e1336 | ||
|
|
fbaf2bded6 | ||
|
|
38a34a7eeb | ||
|
|
70174e093b | ||
|
|
0333e82e86 | ||
|
|
36a8839cf8 | ||
|
|
d0ed6e7fe3 | ||
|
|
72dfbf5e44 | ||
|
|
114a3c037f | ||
|
|
782adc9a9f | ||
|
|
e0642b018d | ||
|
|
6bd4006652 | ||
|
|
01efe7a4ea | ||
|
|
7e133b0cf4 | ||
|
|
fd808bd51e | ||
|
|
b4e8860ee4 | ||
|
|
fb3f8605fd | ||
|
|
e394445f1b | ||
|
|
ca1b0bf1ce | ||
|
|
bf5798190d | ||
|
|
ca5030a646 | ||
|
|
e22324e434 | ||
|
|
e46d4ecd3e | ||
|
|
84f92bd661 | ||
|
|
b44dcc2da0 | ||
|
|
d6062944f1 | ||
|
|
79f549795b | ||
|
|
eaf7c3c486 | ||
|
|
1ac379c17a | ||
|
|
51a4dbf263 | ||
|
|
2d91bfd9e6 | ||
|
|
e437ffdbae | ||
|
|
ccde8b73a2 | ||
|
|
65f88e4ae2 | ||
|
|
354440ee8a | ||
|
|
59106e4f52 | ||
|
|
d76c266fbc | ||
|
|
31681c9c5f | ||
|
|
0e5a32b476 | ||
|
|
a22a1dd284 | ||
|
|
27c59dbb65 | ||
|
|
fb04e32480 | ||
|
|
14a2f63b8b | ||
|
|
9e81db8692 | ||
|
|
1ed67eed35 | ||
|
|
abc5457136 | ||
|
|
4b238a9cd0 | ||
|
|
f200d472ef | ||
|
|
105b2fc114 | ||
|
|
5ed4071f74 | ||
|
|
551a478fdc | ||
|
|
7c319f5fc3 | ||
|
|
1fcf35ebeb | ||
|
|
6d749a58c6 | ||
|
|
34450cdddd | ||
|
|
846bbb4da1 | ||
|
|
d7a26dbf27 | ||
|
|
a86d5b3e61 | ||
|
|
b2bece9ef6 | ||
|
|
f9cbf883ac | ||
|
|
7f225b3973 | ||
|
|
72e7605fce | ||
|
|
a4c1ddd9f2 | ||
|
|
ddd513110f | ||
|
|
e33d623d40 | ||
|
|
eec19ba9af | ||
|
|
413b3f394b | ||
|
|
88cee1212b | ||
|
|
cf25fa8ed8 | ||
|
|
3f053b8547 | ||
|
|
79aa261ca2 | ||
|
|
ac2a9da4c4 | ||
|
|
d8b1d79879 | ||
|
|
feb0f4b7b5 | ||
|
|
6c8fe46590 | ||
|
|
5e3c9e5022 | ||
|
|
f7f821b93c | ||
|
|
36a70e995f | ||
|
|
537ae1a315 | ||
|
|
87b6bf2c26 | ||
|
|
9df6b0618a | ||
|
|
c7e30ac63e | ||
|
|
f5e547944a | ||
|
|
d10680187d | ||
|
|
f5aa6a3cf8 | ||
|
|
c944277e78 | ||
|
|
2e5402d741 | ||
|
|
24f6024383 | ||
|
|
15b1215972 | ||
|
|
11222c89d4 | ||
|
|
893a8ec8d9 | ||
|
|
da2b00de59 | ||
|
|
1276c28e03 | ||
|
|
e458215f27 | ||
|
|
fee4031d0f | ||
|
|
0835ff88b2 | ||
|
|
2e95d9f07e | ||
|
|
fe2388394d | ||
|
|
7fc9b908d4 | ||
|
|
0ed524f173 | ||
|
|
aed3ab994e | ||
|
|
5347cedfa6 | ||
|
|
5b28a713e0 | ||
|
|
f1fb7404c2 | ||
|
|
fc67c0195f | ||
|
|
2f02f9a580 | ||
|
|
07f712a1ce | ||
|
|
c7044b0d20 | ||
|
|
15866cfba9 | ||
|
|
4c2570628d | ||
|
|
113eec59f9 | ||
|
|
f7abc03dac | ||
|
|
ef3f188a2c | ||
|
|
dd62fe89f7 | ||
|
|
ec2d7d77eb | ||
|
|
6c6368fd81 | ||
|
|
ba31c6b625 | ||
|
|
cad189d2dc | ||
|
|
7cf3da1b3b | ||
|
|
45fabf8e03 | ||
|
|
2c12fe6eb2 | ||
|
|
b41b2283f4 | ||
|
|
e8e7cd5008 | ||
|
|
7873433977 | ||
|
|
52d19d3ea2 | ||
|
|
6348d0a6fb | ||
|
|
f7a650b9a4 | ||
|
|
a97d278bcd | ||
|
|
8647ba4729 | ||
|
|
4631077c49 | ||
|
|
18dab28c32 | ||
|
|
8ffbffddb3 | ||
|
|
f191db2fe0 | ||
|
|
dc8f0f6feb | ||
|
|
01a43b03bd | ||
|
|
86db0cd2cd | ||
|
|
ae6dd50ccd | ||
|
|
77032eced1 | ||
|
|
820427e93b | ||
|
|
89e11c9cc8 | ||
|
|
05cf53fe6f | ||
|
|
97b72a5941 | ||
|
|
7922f65243 | ||
|
|
67f7935421 | ||
|
|
9348c5bad9 | ||
|
|
0f7caa66fb | ||
|
|
bd14994eb9 | ||
|
|
08818e8542 | ||
|
|
706eba329d | ||
|
|
f6a2b1c882 | ||
|
|
c2e6622016 | ||
|
|
53904b0627 | ||
|
|
cef14d4576 | ||
|
|
73203a55ca | ||
|
|
397f7326a3 | ||
|
|
4bbd7989dd | ||
|
|
a0b47f3ca3 | ||
|
|
89e9e7c176 | ||
|
|
ddc2f317ab | ||
|
|
867bab8513 | ||
|
|
b1e0c5ff38 | ||
|
|
6dbd9bfb12 | ||
|
|
3c78344812 | ||
|
|
594f268885 | ||
|
|
93d5716414 | ||
|
|
4b8e92f00a | ||
|
|
fc6ef7dd57 | ||
|
|
c881fd4964 | ||
|
|
4bcc2b2f03 | ||
|
|
6150055a05 | ||
|
|
23a33b4351 | ||
|
|
e02386a6ac | ||
|
|
099e703834 | ||
|
|
1ededc637e | ||
|
|
0850bca9d3 | ||
|
|
6d2fd480bf | ||
|
|
ddf0c379be | ||
|
|
45b5e89912 | ||
|
|
a748d5291a | ||
|
|
f5131fae56 | ||
|
|
f79a40a67a | ||
|
|
43146b8316 | ||
|
|
b71b4bd4e5 | ||
|
|
44895a86b8 | ||
|
|
eecb66f4f1 | ||
|
|
e7f1c03151 | ||
|
|
56602cb9a3 | ||
|
|
1e2f776b83 | ||
|
|
ec3705f2ed | ||
|
|
ae0dcabf43 | ||
|
|
6030b00ee2 | ||
|
|
a17908f6e1 | ||
|
|
cb7148a24c | ||
|
|
2f824f59dc | ||
|
|
ad94f10205 | ||
|
|
02b2290b16 | ||
|
|
f8a814a588 | ||
|
|
4c4338cc02 | ||
|
|
5675a1ae7d | ||
|
|
0952224c3d | ||
|
|
4e26c10287 | ||
|
|
f3e82b9ef1 | ||
|
|
e50295d337 | ||
|
|
fde78be2b4 | ||
|
|
c071ac8973 | ||
|
|
599ee57d39 | ||
|
|
4499cebcd9 | ||
|
|
cd6eca1dc2 | ||
|
|
951273f8ef | ||
|
|
51eeb89f67 | ||
|
|
0efa73d96c | ||
|
|
63512b39b2 | ||
|
|
f392ade78d | ||
|
|
0236ab887e | ||
|
|
d4baae411b | ||
|
|
e02e46d0fc | ||
|
|
3c04dab472 | ||
|
|
fc1844b4df | ||
|
|
99ef20627a | ||
|
|
4497e0aaca | ||
|
|
c3e045e367 | ||
|
|
501d3e6c32 | ||
|
|
b27b9c1d18 | ||
|
|
f7d3d1eeaf | ||
|
|
0d72a4c8ba | ||
|
|
dbdb0a2560 | ||
|
|
18a09703de | ||
|
|
bc6a14d30f | ||
|
|
97db49a57b | ||
|
|
eca2168685 | ||
|
|
1bcef38739 | ||
|
|
aac6ad73da | ||
|
|
122b4d66b6 | ||
|
|
0f8f4e361b | ||
|
|
3733b589ac | ||
|
|
6a2e781db2 | ||
|
|
c6569ce022 | ||
|
|
a62bdc58cb | ||
|
|
912009494d | ||
|
|
a5d7c41d20 | ||
|
|
232ae2a189 | ||
|
|
aa8b23105f | ||
|
|
c113f854a2 | ||
|
|
87de0e7a0e | ||
|
|
85755e3022 | ||
|
|
02dc1172be | ||
|
|
dbf8c41209 | ||
|
|
8c4fd759c6 | ||
|
|
23dc19ad94 | ||
|
|
0c99c4d93f | ||
|
|
8ab045331b | ||
|
|
a8d0936e04 | ||
|
|
4e349acb50 | ||
|
|
947e3b06b4 | ||
|
|
5fd574a14f | ||
|
|
03c1053871 | ||
|
|
c7ed0ef5eb | ||
|
|
2aede97754 | ||
|
|
9b8a5e9bf3 | ||
|
|
0f910f2d40 | ||
|
|
15f155100c | ||
|
|
2468f5a6c4 | ||
|
|
945a52a99f | ||
|
|
486b2c82a7 | ||
|
|
800b7f4370 | ||
|
|
8ca5a048d6 | ||
|
|
44b7a3c3f1 | ||
|
|
554ebe7206 | ||
|
|
d7b87fcb8e | ||
|
|
c94f9e1cc9 | ||
|
|
68532fade3 | ||
|
|
e219867cdf | ||
|
|
765d5d9729 | ||
|
|
43029f37b1 | ||
|
|
7188462c55 | ||
|
|
f9ff814955 | ||
|
|
dfbd1305b3 | ||
|
|
c9255ab31b | ||
|
|
1e714af3cf | ||
|
|
4c959cd983 | ||
|
|
d959c35723 | ||
|
|
69a9d7485b | ||
|
|
dcf07ad8c7 | ||
|
|
ed6cdb2eb4 | ||
|
|
a73e7e9f99 | ||
|
|
ab853e1fcf | ||
|
|
37d38b62b1 | ||
|
|
f9bb517142 | ||
|
|
efe9b867d5 | ||
|
|
d9cf33d1ba | ||
|
|
ee3028e67d | ||
|
|
d810e6c82d | ||
|
|
e0a281583d | ||
|
|
d739dcac2b | ||
|
|
cdd4cb8ec2 | ||
|
|
93ef90cd24 | ||
|
|
e165a1e65c | ||
|
|
4066e5bf14 | ||
|
|
4729514a22 | ||
|
|
93aedcfeb7 | ||
|
|
47d18bb896 | ||
|
|
61dafbe06e | ||
|
|
474325da68 | ||
|
|
9317401d57 | ||
|
|
67d746a62c | ||
|
|
2f1f68f12f | ||
|
|
2742edd73f | ||
|
|
834561a5de | ||
|
|
11102b4dd6 | ||
|
|
fef2da3c0b | ||
|
|
9820296e92 | ||
|
|
dbfde74c1e | ||
|
|
b28668e18d | ||
|
|
5f1174de27 | ||
|
|
543ce937ec | ||
|
|
5537b083a8 | ||
|
|
6b0854749f | ||
|
|
09ba4772b8 | ||
|
|
06a1d08465 | ||
|
|
d510ead877 | ||
|
|
2968a1559e | ||
|
|
cba26eedb5 | ||
|
|
23e74b2781 | ||
|
|
ef0277d10e | ||
|
|
a623a5b7cc | ||
|
|
be8479fdba | ||
|
|
e97e6d467c | ||
|
|
75ec890d46 | ||
|
|
871a9c29c8 | ||
|
|
a4f903d947 | ||
|
|
1920a52829 | ||
|
|
6e14a727b1 | ||
|
|
ea855837df | ||
|
|
d05ed0e59c | ||
|
|
a9eb443072 | ||
|
|
d382b00efd | ||
|
|
ef9d077c7f | ||
|
|
e4b20abf8e | ||
|
|
e9f0a10175 | ||
|
|
c3968a26cf | ||
|
|
9371515ecc | ||
|
|
a83e055b19 | ||
|
|
6907651756 | ||
|
|
fc2d0246e6 | ||
|
|
bb9c362bab | ||
|
|
51402e68d2 | ||
|
|
1b8813228b | ||
|
|
922e36cfb0 | ||
|
|
edff094626 | ||
|
|
aa72a080b0 | ||
|
|
2a93d1c652 | ||
|
|
6b2f23712c | ||
|
|
375ab93ee3 | ||
|
|
d5962e9d71 | ||
|
|
ffaa264bd3 |
79
README.MD
79
README.MD
@@ -1,41 +1,70 @@
|
||||
# Magisk
|
||||

|
||||
|
||||
[Downloads](https://github.com/topjohnwu/Magisk/releases) \| [Documentation](https://topjohnwu.github.io/Magisk/) \| [XDA Thread](https://forum.xda-developers.com/apps/magisk/official-magisk-v7-universal-systemless-t3473445)
|
||||

|
||||

|
||||
|
||||
## Introduction
|
||||
|
||||
Magisk is a suite of open source tools for customizing Android, supporting devices higher than Android 4.2 (API 17). It covers the fundamental parts for Android customization: root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt removals etc.
|
||||
Magisk is a suite of open source tools for customizing Android, supporting devices higher than Android 4.2. It covers fundamental parts of Android customization: root, boot scripts, SELinux patches, AVB2.0 / dm-verity / forceencrypt removals etc.
|
||||
|
||||
Furthermore, Magisk provides a **Systemless Interface** to alter the system (or vendor) arbitrarily while the actual partitions stay completely intact. With its systemless nature along with several other hacks, Magisk can almost perfectly hide modifications within userspace. Note that since 2020.3, the CTS check of [Google's SafetyNet API](https://developer.android.com/training/safetynet/index.html) will **NOT** pass.
|
||||
Here are some feature highlights:
|
||||
|
||||
- **MagiskSU**: Provide root access to your device
|
||||
- **Magisk Modules**: Modify read-only partitions by installing modules
|
||||
- **MagiskHide**: Hide Magisk from root detections / system integrity checks
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.2/MagiskManager-v8.0.2.apk)
|
||||
[](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-debug.apk)
|
||||
<br>
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v20.4)
|
||||
[](https://github.com/topjohnwu/Magisk/releases/tag/v21.0)
|
||||
|
||||
## Useful Links
|
||||
|
||||
- [Installation Instruction](https://topjohnwu.github.io/Magisk/install.html)
|
||||
- [Frequently Asked Questions](https://topjohnwu.github.io/Magisk/faq.html)
|
||||
- [Magisk Documentation](https://topjohnwu.github.io/Magisk/)
|
||||
- [Magisk Troubleshoot Wiki](https://www.didgeridoohan.com/magisk/HomePage) (by [@Didgeridoohan](https://github.com/Didgeridoohan))
|
||||
|
||||
## Android Version Support
|
||||
|
||||
- Android 4.2+: MagiskSU and Magisk Modules Only
|
||||
- Android 4.4+: All core features available
|
||||
- Android 6.0+: Guaranteed MagiskHide support
|
||||
- Android 7.0+: Full MagiskHide protection
|
||||
- Android 9.0+: Magisk Manager stealth mode
|
||||
|
||||
## Bug Reports
|
||||
|
||||
**Only reports using debug canary builds will be accepted.** \
|
||||
Access canary builds by upgrading to either canary Magisk Manager:
|
||||
- [Canary Manager (Release)](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-release.apk)
|
||||
- [Canary Manager (Debug)](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-debug.apk)
|
||||
Canary Channels are cutting edge builds for those adventurous. To access canary builds, install the Canary Magisk Manager, switch to the Canary Channel in settings and upgrade.
|
||||
|
||||
For installation issues, upload both boot image and install logs. \
|
||||
For Magisk issues, upload boot logcat or dmesg. \
|
||||
**Only bug reports from Canary builds will be accepted.**
|
||||
|
||||
For installation issues, upload both boot image and install logs.<br>
|
||||
For Magisk issues, upload boot logcat or dmesg.<br>
|
||||
For Magisk Manager crashes, record and upload the logcat when the crash occurs.
|
||||
|
||||
## Building Environment Requirements
|
||||
## Building and Development
|
||||
|
||||
- Python 3: run `build.py` script
|
||||
- Java Development Kit (JDK) 8: Compile Magisk Manager and sign zips
|
||||
- Latest Android SDK: set `ANDROID_HOME` environment variable to the path to Android SDK
|
||||
- Android NDK: Install NDK along with SDK (`$ANDROID_HOME/ndk-bundle`), or optionally specify a custom path `ANDROID_NDK_HOME`
|
||||
- (Windows Only) Python package Colorama: Install with `pip install colorama`, used for ANSI color codes
|
||||
- Magisk builds on any OS Android Studio supports. Install Android Studio and do the initial setups.
|
||||
- Clone sources: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
|
||||
- Install Python 3.6+ \
|
||||
(Windows only: select **'Add Python to PATH'** in installer, and run `pip install colorama` after install)
|
||||
- Configure to use the JDK bundled in Android Studio:
|
||||
- macOS: `export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home"`
|
||||
- Linux: `export PATH="/path/to/androidstudio/jre/bin:$PATH"`
|
||||
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
|
||||
- Set environment variable `ANDROID_SDK_ROOT` to the Android SDK folder (can be found in Android Studio settings)
|
||||
- Run `./build.py ndk` to let the script download and install NDK for you
|
||||
- Set configurations in `config.prop`. A sample `config.prop.sample` is provided.
|
||||
- To start building, run `build.py` to see your options. \
|
||||
For each action, use `-h` to access help (e.g. `./build.py all -h`)
|
||||
- To start development, open the project in Android Studio. Both app (Kotlin/Java) and native (C++/C) source code can be properly developed using the IDE, but *always* use `build.py` for building.
|
||||
- `build.py` builds in debug mode by default. If you want release builds (with `-r, --release`), you need a Java Keystore to sign APKs and zips. For more information, check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key).
|
||||
|
||||
## Building Notes and Instructions
|
||||
|
||||
- Clone sources with submodules: `git clone --recurse-submodules https://github.com/topjohnwu/Magisk.git`
|
||||
- Building is supported on macOS, Linux, and Windows. Official releases are built and tested with [FrankeNDK](https://github.com/topjohnwu/FrankeNDK); point `ANDROID_NDK_HOME` to FrankeNDK if you want to use it for compiling.
|
||||
- Set configurations in `config.prop`. A sample file `config.prop.sample` is provided as an example.
|
||||
- Run `build.py` with argument `-h` to see the built-in help message. The `-h` option also works for each supported actions, e.g. `./build.py binary -h`
|
||||
- By default, `build.py` build binaries and Magisk Manager in debug mode. If you want to build Magisk Manager in release mode (via the `-r, --release` flag), you need a Java Keystore file `release-key.jks` (only `JKS` format is supported) to sign APKs and zips. For more information, check out [Google's Official Documentation](https://developer.android.com/studio/publish/app-signing.html#signing-manually).
|
||||
|
||||
## Translations
|
||||
## Translation Contributions
|
||||
|
||||
Default string resources for Magisk Manager and its stub APK are located here:
|
||||
|
||||
|
||||
135
app/build.gradle
135
app/build.gradle
@@ -1,135 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
kapt {
|
||||
correctErrorTypes = true
|
||||
useBuildCache = true
|
||||
mapDiagnosticLocations = true
|
||||
javacOptions {
|
||||
option("-Xmaxerrs", 1000)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
applicationId 'com.topjohnwu.magisk'
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled true
|
||||
versionName props['appVersion']
|
||||
versionCode props['appVersionCode'] as Integer
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = ["room.incremental":"true"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
|
||||
'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude '/META-INF/**'
|
||||
exclude '/androidsupportmultidexversion.txt'
|
||||
exclude '/org/bouncycastle/**'
|
||||
exclude '/kotlin/**'
|
||||
exclude '/kotlinx/**'
|
||||
exclude '/okhttp3/**'
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
}
|
||||
|
||||
androidExtensions {
|
||||
experimental = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation project(':shared')
|
||||
implementation project(':signing')
|
||||
|
||||
implementation 'com.github.topjohnwu:jtar:1.0.0'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
implementation 'com.ncapdevi:frag-nav:3.2.0'
|
||||
implementation 'com.github.pwittchen:reactivenetwork-rx2:3.0.6'
|
||||
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.18'
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${vKotlin}"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${vKotlin}"
|
||||
|
||||
def vBAdapt = '3.1.1'
|
||||
def bindingAdapter = 'me.tatarka.bindingcollectionadapter2:bindingcollectionadapter'
|
||||
implementation "${bindingAdapter}:${vBAdapt}"
|
||||
implementation "${bindingAdapter}-recyclerview:${vBAdapt}"
|
||||
|
||||
def vMarkwon = '4.2.1'
|
||||
implementation "io.noties.markwon:core:${vMarkwon}"
|
||||
implementation "io.noties.markwon:html:${vMarkwon}"
|
||||
implementation "io.noties.markwon:image:${vMarkwon}"
|
||||
implementation 'com.caverock:androidsvg:1.4'
|
||||
|
||||
def vLibsu = '2.5.1'
|
||||
implementation "com.github.topjohnwu.libsu:core:${vLibsu}"
|
||||
implementation "com.github.topjohnwu.libsu:io:${vLibsu}"
|
||||
|
||||
def vKoin = '2.0.1'
|
||||
implementation "org.koin:koin-core:${vKoin}"
|
||||
implementation "org.koin:koin-android:${vKoin}"
|
||||
implementation "org.koin:koin-androidx-viewmodel:${vKoin}"
|
||||
|
||||
def vRetrofit = '2.7.1'
|
||||
implementation "com.squareup.retrofit2:retrofit:${vRetrofit}"
|
||||
implementation "com.squareup.retrofit2:converter-moshi:${vRetrofit}"
|
||||
implementation "com.squareup.retrofit2:converter-scalars:${vRetrofit}"
|
||||
implementation "com.squareup.retrofit2:adapter-rxjava2:${vRetrofit}"
|
||||
|
||||
def vOkHttp = '3.12.10'
|
||||
implementation("com.squareup.okhttp3:okhttp:${vOkHttp}") {
|
||||
force = true
|
||||
}
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:${vOkHttp}"
|
||||
|
||||
def vMoshi = '1.10.0-SNAPSHOT'
|
||||
implementation "com.squareup.moshi:moshi:${vMoshi}"
|
||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}"
|
||||
|
||||
def vRoom = '2.2.4'
|
||||
implementation "androidx.room:room-runtime:${vRoom}"
|
||||
implementation "androidx.room:room-rxjava2:${vRoom}"
|
||||
kapt "androidx.room:room-compiler:${vRoom}"
|
||||
|
||||
def vNav = '2.2.1'
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:${vNav}"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:${vNav}"
|
||||
|
||||
implementation 'androidx.biometric:biometric:1.0.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-beta01'
|
||||
implementation 'androidx.browser:browser:1.2.0'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.2.2'
|
||||
implementation 'androidx.work:work-runtime:2.3.3'
|
||||
implementation 'androidx.transition:transition:1.3.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.core:core-ktx:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha03'
|
||||
}
|
||||
149
app/build.gradle.kts
Normal file
149
app/build.gradle.kts
Normal file
@@ -0,0 +1,149 @@
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
kotlin("android")
|
||||
kotlin("android.extensions")
|
||||
kotlin("kapt")
|
||||
id("androidx.navigation.safeargs.kotlin")
|
||||
}
|
||||
|
||||
kapt {
|
||||
correctErrorTypes = true
|
||||
useBuildCache = true
|
||||
mapDiagnosticLocations = true
|
||||
javacOptions {
|
||||
option("-Xmaxerrs", 1000)
|
||||
}
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
applicationId = "com.topjohnwu.magisk"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled = true
|
||||
versionName = Config["appVersion"]
|
||||
versionCode = Config["appVersionCode"]?.toInt()
|
||||
buildConfigField("int", "LATEST_MAGISK", Config["versionCode"] ?: "Integer.MAX_VALUE")
|
||||
|
||||
javaCompileOptions.annotationProcessorOptions.arguments(
|
||||
mapOf("room.incremental" to "true")
|
||||
)
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
isMinifyEnabled = true
|
||||
isShrinkResources = true
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
dataBinding = true
|
||||
}
|
||||
|
||||
dependenciesInfo {
|
||||
includeInApk = false
|
||||
includeInBundle = false
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
exclude("/META-INF/**")
|
||||
exclude("/org/bouncycastle/**")
|
||||
exclude("/kotlin/**")
|
||||
exclude("/kotlinx/**")
|
||||
exclude("/okhttp3/**")
|
||||
exclude("/*.txt")
|
||||
exclude("/*.bin")
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
androidExtensions {
|
||||
isExperimental = true
|
||||
}
|
||||
|
||||
val copyUtils = tasks.register("copyUtils", Copy::class) {
|
||||
from(rootProject.file("scripts/util_functions.sh"))
|
||||
into("src/main/res/raw")
|
||||
}
|
||||
|
||||
tasks["preBuild"]?.dependsOn(copyUtils)
|
||||
|
||||
dependencies {
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
implementation(kotlin("stdlib"))
|
||||
implementation(project(":app:shared"))
|
||||
implementation(project(":app:signing"))
|
||||
|
||||
implementation("com.github.topjohnwu:jtar:1.0.0")
|
||||
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
|
||||
implementation("com.github.topjohnwu:lz4-java:1.7.1")
|
||||
implementation("com.jakewharton.timber:timber:4.7.1")
|
||||
|
||||
val vBAdapt = "4.0.0"
|
||||
val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter"
|
||||
implementation("${bindingAdapter}:${vBAdapt}")
|
||||
implementation("${bindingAdapter}-recyclerview:${vBAdapt}")
|
||||
|
||||
val vMarkwon = "4.6.0"
|
||||
implementation("io.noties.markwon:core:${vMarkwon}")
|
||||
implementation("io.noties.markwon:html:${vMarkwon}")
|
||||
implementation("io.noties.markwon:image:${vMarkwon}")
|
||||
implementation("com.caverock:androidsvg:1.4")
|
||||
|
||||
val vLibsu = "3.0.2"
|
||||
implementation("com.github.topjohnwu.libsu:core:${vLibsu}")
|
||||
implementation("com.github.topjohnwu.libsu:io:${vLibsu}")
|
||||
|
||||
val vKoin = "2.1.6"
|
||||
implementation("org.koin:koin-core:${vKoin}")
|
||||
implementation("org.koin:koin-android:${vKoin}")
|
||||
implementation("org.koin:koin-androidx-viewmodel:${vKoin}")
|
||||
|
||||
val vRetrofit = "2.9.0"
|
||||
implementation("com.squareup.retrofit2:retrofit:${vRetrofit}")
|
||||
implementation("com.squareup.retrofit2:converter-moshi:${vRetrofit}")
|
||||
implementation("com.squareup.retrofit2:converter-scalars:${vRetrofit}")
|
||||
|
||||
val vOkHttp = "3.12.12"
|
||||
implementation("com.squareup.okhttp3:okhttp") {
|
||||
version {
|
||||
strictly(vOkHttp)
|
||||
}
|
||||
}
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:${vOkHttp}")
|
||||
implementation("com.squareup.okhttp3:okhttp-dnsoverhttps:${vOkHttp}")
|
||||
|
||||
val vMoshi = "1.11.0"
|
||||
implementation("com.squareup.moshi:moshi:${vMoshi}")
|
||||
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
|
||||
|
||||
val vRoom = "2.3.0-alpha03"
|
||||
implementation("androidx.room:room-runtime:${vRoom}")
|
||||
implementation("androidx.room:room-ktx:${vRoom}")
|
||||
kapt("androidx.room:room-compiler:${vRoom}")
|
||||
|
||||
val vNav: String by rootProject.extra
|
||||
implementation("androidx.navigation:navigation-fragment-ktx:${vNav}")
|
||||
implementation("androidx.navigation:navigation-ui-ktx:${vNav}")
|
||||
|
||||
implementation("androidx.biometric:biometric:1.0.1")
|
||||
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
|
||||
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
|
||||
implementation("androidx.browser:browser:1.2.0")
|
||||
implementation("androidx.preference:preference:1.1.1")
|
||||
implementation("androidx.recyclerview:recyclerview:1.1.0")
|
||||
implementation("androidx.fragment:fragment-ktx:1.2.5")
|
||||
implementation("androidx.work:work-runtime-ktx:2.4.0")
|
||||
implementation("androidx.transition:transition:1.3.1")
|
||||
implementation("androidx.multidex:multidex:2.0.1")
|
||||
implementation("androidx.core:core-ktx:1.3.2")
|
||||
implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.0.0")
|
||||
implementation("com.google.android.material:material:1.2.1")
|
||||
}
|
||||
11
app/proguard-rules.pro
vendored
11
app/proguard-rules.pro
vendored
@@ -29,15 +29,12 @@
|
||||
-keep class a.* { *; }
|
||||
|
||||
# Snet
|
||||
-keepclassmembers class com.topjohnwu.magisk.core.utils.SafetyNetHelper { *; }
|
||||
-keep,allowobfuscation interface com.topjohnwu.magisk.core.utils.SafetyNetHelper$Callback
|
||||
-keepclassmembers class * implements com.topjohnwu.magisk.core.utils.SafetyNetHelper$Callback {
|
||||
void onResponse(int);
|
||||
-keepclassmembers class com.topjohnwu.magisk.ui.safetynet.SafetyNetHelper { *; }
|
||||
-keep,allowobfuscation interface com.topjohnwu.magisk.ui.safetynet.SafetyNetHelper$Callback
|
||||
-keepclassmembers class * implements com.topjohnwu.magisk.ui.safetynet.SafetyNetHelper$Callback {
|
||||
void onResponse(org.json.JSONObject);
|
||||
}
|
||||
|
||||
# Fragments
|
||||
-keep,allowobfuscation class * extends androidx.fragment.app.Fragment
|
||||
|
||||
# Strip Timber verbose and debug logging
|
||||
-assumenosideeffects class timber.log.Timber.Tree {
|
||||
public void v(**);
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
com.topjohnwu.magisk:color/xxxxxxxx = 0x7f010000
|
||||
com.topjohnwu.magisk:drawable/xxxxxxxx = 0x7f020000
|
||||
com.topjohnwu.magisk:string/xxxxxxxx = 0x7f030000
|
||||
com.topjohnwu.magisk:style/xxxxxxxx = 0x7f040000
|
||||
com.topjohnwu.magisk:xml/xxxxxxxx = 0x7f050000
|
||||
14
app/shared/build.gradle.kts
Normal file
14
app/shared/build.gradle.kts
Normal file
@@ -0,0 +1,14 @@
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
}
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
consumerProguardFiles("proguard-rules.pro")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
}
|
||||
@@ -4,26 +4,14 @@
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="Magisk Manager"
|
||||
android:installLocation="internalOnly"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<activity
|
||||
android:name="a.r"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:process=":remote" />
|
||||
|
||||
<provider
|
||||
android:name="a.p"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -4,31 +4,22 @@ import android.content.ContentProvider;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.text.TextUtils;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.topjohnwu.shared.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
|
||||
import static org.xmlpull.v1.XmlPullParser.START_TAG;
|
||||
|
||||
/**
|
||||
* Modified from androidx.core.content.FileProvider
|
||||
*/
|
||||
@@ -36,25 +27,12 @@ public class FileProvider extends ContentProvider {
|
||||
private static final String[] COLUMNS = {
|
||||
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE };
|
||||
|
||||
private static final String TAG_ROOT_PATH = "root-path";
|
||||
private static final String TAG_FILES_PATH = "files-path";
|
||||
private static final String TAG_CACHE_PATH = "cache-path";
|
||||
private static final String TAG_EXTERNAL = "external-path";
|
||||
private static final String TAG_EXTERNAL_FILES = "external-files-path";
|
||||
private static final String TAG_EXTERNAL_CACHE = "external-cache-path";
|
||||
private static final String TAG_EXTERNAL_MEDIA = "external-media-path";
|
||||
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_PATH = "path";
|
||||
|
||||
private static final File DEVICE_ROOT = new File("/");
|
||||
|
||||
private static HashMap<String, PathStrategy> sCache = new HashMap<>();
|
||||
|
||||
private PathStrategy mStrategy;
|
||||
|
||||
public static ProviderCallHandler callHandler;
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
@@ -150,13 +128,6 @@ public class FileProvider extends ContentProvider {
|
||||
return file.delete() ? 1 : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String method, String arg, Bundle extras) {
|
||||
if (callHandler != null)
|
||||
return callHandler.call(getContext(), method, arg, extras);
|
||||
return Bundle.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(Uri uri, String mode)
|
||||
throws FileNotFoundException {
|
||||
@@ -171,63 +142,36 @@ public class FileProvider extends ContentProvider {
|
||||
synchronized (sCache) {
|
||||
strat = sCache.get(authority);
|
||||
if (strat == null) {
|
||||
try {
|
||||
strat = parsePathStrategy(context, authority);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("Failed to parse xml", e);
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new IllegalArgumentException("Failed to parse xml", e);
|
||||
}
|
||||
strat = createPathStrategy(context, authority);
|
||||
sCache.put(authority, strat);
|
||||
}
|
||||
}
|
||||
return strat;
|
||||
}
|
||||
|
||||
private static PathStrategy parsePathStrategy(Context context, String authority)
|
||||
throws IOException, XmlPullParserException {
|
||||
private static PathStrategy createPathStrategy(Context context, String authority) {
|
||||
final SimplePathStrategy strat = new SimplePathStrategy(authority);
|
||||
|
||||
final XmlResourceParser in = context.getResources().getXml(R.xml.file_paths);
|
||||
|
||||
int type;
|
||||
while ((type = in.next()) != END_DOCUMENT) {
|
||||
if (type == START_TAG) {
|
||||
final String tag = in.getName();
|
||||
|
||||
final String name = in.getAttributeValue(null, ATTR_NAME);
|
||||
String path = in.getAttributeValue(null, ATTR_PATH);
|
||||
|
||||
File target = null;
|
||||
if (TAG_ROOT_PATH.equals(tag)) {
|
||||
target = DEVICE_ROOT;
|
||||
} else if (TAG_FILES_PATH.equals(tag)) {
|
||||
target = context.getFilesDir();
|
||||
} else if (TAG_CACHE_PATH.equals(tag)) {
|
||||
target = context.getCacheDir();
|
||||
} else if (TAG_EXTERNAL.equals(tag)) {
|
||||
target = Environment.getExternalStorageDirectory();
|
||||
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
|
||||
File[] externalFilesDirs = getExternalFilesDirs(context, null);
|
||||
if (externalFilesDirs.length > 0) {
|
||||
target = externalFilesDirs[0];
|
||||
}
|
||||
} else if (TAG_EXTERNAL_CACHE.equals(tag)) {
|
||||
File[] externalCacheDirs = getExternalCacheDirs(context);
|
||||
if (externalCacheDirs.length > 0) {
|
||||
target = externalCacheDirs[0];
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||
&& TAG_EXTERNAL_MEDIA.equals(tag)) {
|
||||
File[] externalMediaDirs = context.getExternalMediaDirs();
|
||||
if (externalMediaDirs.length > 0) {
|
||||
target = externalMediaDirs[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (target != null) {
|
||||
strat.addRoot(name, buildPath(target, path));
|
||||
}
|
||||
strat.addRoot("root_files", buildPath(DEVICE_ROOT, "."));
|
||||
strat.addRoot("internal_files", buildPath(context.getFilesDir(), "."));
|
||||
strat.addRoot("cache_files", buildPath(context.getCacheDir(), "."));
|
||||
strat.addRoot("external_files", buildPath(Environment.getExternalStorageDirectory(), "."));
|
||||
{
|
||||
File[] externalFilesDirs = getExternalFilesDirs(context, null);
|
||||
if (externalFilesDirs.length > 0) {
|
||||
strat.addRoot("external_file_files", buildPath(externalFilesDirs[0], "."));
|
||||
}
|
||||
}
|
||||
{
|
||||
File[] externalCacheDirs = getExternalCacheDirs(context);
|
||||
if (externalCacheDirs.length > 0) {
|
||||
strat.addRoot("external_cache_files", buildPath(externalCacheDirs[0], "."));
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
File[] externalMediaDirs = context.getExternalMediaDirs();
|
||||
if (externalMediaDirs.length > 0) {
|
||||
strat.addRoot("external_media_files", buildPath(externalMediaDirs[0], "."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,10 +47,9 @@ public class Networking {
|
||||
} catch (Exception e) {
|
||||
if (Build.VERSION.SDK_INT < 21) {
|
||||
// Failed to update SSL provider, use NoSSLv3SocketFactory on SDK < 21
|
||||
// and return false to notify potential issues
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(new NoSSLv3SocketFactory());
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
35
app/signing/build.gradle.kts
Normal file
35
app/signing/build.gradle.kts
Normal file
@@ -0,0 +1,35 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
|
||||
plugins {
|
||||
id("java-library")
|
||||
id("java")
|
||||
id("com.github.johnrengelman.shadow") version "6.0.0"
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
val jar by tasks.getting(Jar::class) {
|
||||
manifest {
|
||||
attributes["Main-Class"] = "com.topjohnwu.signing.ZipSigner"
|
||||
}
|
||||
}
|
||||
|
||||
val shadowJar by tasks.getting(ShadowJar::class) {
|
||||
archiveBaseName.set("zipsigner")
|
||||
archiveClassifier.set(null as String?)
|
||||
archiveVersion.set("4.0")
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
|
||||
|
||||
api("org.bouncycastle:bcprov-jdk15on:1.67")
|
||||
api("org.bouncycastle:bcpkix-jdk15on:1.67")
|
||||
}
|
||||
772
app/signing/src/main/java/com/topjohnwu/signing/ApkSignerV2.java
Normal file
772
app/signing/src/main/java/com/topjohnwu/signing/ApkSignerV2.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -28,20 +27,20 @@ public class ZipSigner {
|
||||
System.exit(2);
|
||||
}
|
||||
|
||||
private static void sign(JarMap input, OutputStream output) throws Exception {
|
||||
sign(SignAPK.class.getResourceAsStream("/keys/testkey.x509.pem"),
|
||||
SignAPK.class.getResourceAsStream("/keys/testkey.pk8"), input, output);
|
||||
private static void sign(JarMap input, FileOutputStream output) throws Exception {
|
||||
sign(SignApk.class.getResourceAsStream("/keys/testkey.x509.pem"),
|
||||
SignApk.class.getResourceAsStream("/keys/testkey.pk8"), input, output);
|
||||
}
|
||||
|
||||
private static void sign(InputStream certIs, InputStream keyIs,
|
||||
JarMap input, OutputStream output) throws Exception {
|
||||
JarMap input, FileOutputStream output) throws Exception {
|
||||
X509Certificate cert = CryptoUtils.readCertificate(certIs);
|
||||
PrivateKey key = CryptoUtils.readPrivateKey(keyIs);
|
||||
SignAPK.signAndAdjust(cert, key, input, output);
|
||||
SignApk.sign(cert, key, input, output);
|
||||
}
|
||||
|
||||
private static void sign(String keyStore, String keyStorePass, String alias, String keyPass,
|
||||
JarMap in, OutputStream out) throws Exception {
|
||||
JarMap in, FileOutputStream out) throws Exception {
|
||||
KeyStore ks;
|
||||
try {
|
||||
ks = KeyStore.getInstance("JKS");
|
||||
@@ -56,7 +55,7 @@ public class ZipSigner {
|
||||
}
|
||||
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
|
||||
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
|
||||
SignAPK.signAndAdjust(cert, key, in, out);
|
||||
SignApk.sign(cert, key, in, out);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@@ -66,7 +65,7 @@ public class ZipSigner {
|
||||
Security.insertProviderAt(new BouncyCastleProvider(), 1);
|
||||
|
||||
try (JarMap in = JarMap.open(args[args.length - 2], false);
|
||||
OutputStream out = new FileOutputStream(args[args.length - 1])) {
|
||||
FileOutputStream out = new FileOutputStream(args[args.length - 1])) {
|
||||
if (args.length == 2) {
|
||||
sign(in, out);
|
||||
} else if (args.length == 4) {
|
||||
136
app/signing/src/main/java/com/topjohnwu/signing/ZipUtils.java
Normal file
136
app/signing/src/main/java/com/topjohnwu/signing/ZipUtils.java
Normal file
@@ -0,0 +1,136 @@
|
||||
package com.topjohnwu.signing;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* Assorted ZIP format helpers.
|
||||
*
|
||||
* <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
|
||||
* order of these buffers is little-endian.
|
||||
*/
|
||||
public abstract class ZipUtils {
|
||||
|
||||
private static final int ZIP_EOCD_REC_MIN_SIZE = 22;
|
||||
private static final int ZIP_EOCD_REC_SIG = 0x06054b50;
|
||||
private static final int ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET = 12;
|
||||
private static final int ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET = 16;
|
||||
private static final int ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET = 20;
|
||||
|
||||
private static final int ZIP64_EOCD_LOCATOR_SIZE = 20;
|
||||
private static final int ZIP64_EOCD_LOCATOR_SIG = 0x07064b50;
|
||||
|
||||
private static final int UINT16_MAX_VALUE = 0xffff;
|
||||
|
||||
private ZipUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position at which ZIP End of Central Directory record starts in the provided
|
||||
* buffer or {@code -1} if the record is not present.
|
||||
*
|
||||
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
|
||||
*/
|
||||
public static int findZipEndOfCentralDirectoryRecord(ByteBuffer zipContents) {
|
||||
assertByteOrderLittleEndian(zipContents);
|
||||
|
||||
// ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
|
||||
// The record can be identified by its 4-byte signature/magic which is located at the very
|
||||
// beginning of the record. A complication is that the record is variable-length because of
|
||||
// the comment field.
|
||||
// The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
|
||||
// end of the buffer for the EOCD record signature. Whenever we find a signature, we check
|
||||
// the candidate record's comment length is such that the remainder of the record takes up
|
||||
// exactly the remaining bytes in the buffer. The search is bounded because the maximum
|
||||
// size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
|
||||
|
||||
int archiveSize = zipContents.capacity();
|
||||
if (archiveSize < ZIP_EOCD_REC_MIN_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
int maxCommentLength = Math.min(archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT16_MAX_VALUE);
|
||||
int eocdWithEmptyCommentStartPosition = archiveSize - ZIP_EOCD_REC_MIN_SIZE;
|
||||
for (int expectedCommentLength = 0; expectedCommentLength < maxCommentLength; expectedCommentLength++) {
|
||||
int eocdStartPos = eocdWithEmptyCommentStartPosition - expectedCommentLength;
|
||||
if (zipContents.getInt(eocdStartPos) == ZIP_EOCD_REC_SIG) {
|
||||
int actualCommentLength = getUnsignedInt16(zipContents, eocdStartPos + ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET);
|
||||
if (actualCommentLength == expectedCommentLength) {
|
||||
return eocdStartPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided buffer contains a ZIP64 End of Central Directory
|
||||
* Locator.
|
||||
*
|
||||
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
|
||||
*/
|
||||
public static boolean isZip64EndOfCentralDirectoryLocatorPresent(ByteBuffer zipContents, int zipEndOfCentralDirectoryPosition) {
|
||||
assertByteOrderLittleEndian(zipContents);
|
||||
|
||||
// ZIP64 End of Central Directory Locator immediately precedes the ZIP End of Central
|
||||
// Directory Record.
|
||||
|
||||
int locatorPosition = zipEndOfCentralDirectoryPosition - ZIP64_EOCD_LOCATOR_SIZE;
|
||||
if (locatorPosition < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return zipContents.getInt(locatorPosition) == ZIP64_EOCD_LOCATOR_SIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset of the start of the ZIP Central Directory in the archive.
|
||||
*
|
||||
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
|
||||
*/
|
||||
public static long getZipEocdCentralDirectoryOffset(ByteBuffer zipEndOfCentralDirectory) {
|
||||
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
|
||||
return getUnsignedInt32(zipEndOfCentralDirectory, zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the offset of the start of the ZIP Central Directory in the archive.
|
||||
*
|
||||
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
|
||||
*/
|
||||
public static void setZipEocdCentralDirectoryOffset(ByteBuffer zipEndOfCentralDirectory, long offset) {
|
||||
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
|
||||
setUnsignedInt32(zipEndOfCentralDirectory, zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_OFFSET, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size (in bytes) of the ZIP Central Directory.
|
||||
*
|
||||
* <p>NOTE: Byte order of {@code zipEndOfCentralDirectory} must be little-endian.
|
||||
*/
|
||||
public static long getZipEocdCentralDirectorySizeBytes(ByteBuffer zipEndOfCentralDirectory) {
|
||||
assertByteOrderLittleEndian(zipEndOfCentralDirectory);
|
||||
return getUnsignedInt32(zipEndOfCentralDirectory, zipEndOfCentralDirectory.position() + ZIP_EOCD_CENTRAL_DIR_SIZE_FIELD_OFFSET);
|
||||
}
|
||||
|
||||
private static void assertByteOrderLittleEndian(ByteBuffer buffer) {
|
||||
if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
|
||||
throw new IllegalArgumentException("ByteBuffer byte order must be little endian");
|
||||
}
|
||||
}
|
||||
|
||||
private static int getUnsignedInt16(ByteBuffer buffer, int offset) {
|
||||
return buffer.getShort(offset) & 0xffff;
|
||||
}
|
||||
|
||||
private static long getUnsignedInt32(ByteBuffer buffer, int offset) {
|
||||
return buffer.getInt(offset) & 0xffffffffL;
|
||||
}
|
||||
|
||||
private static void setUnsignedInt32(ByteBuffer buffer, int offset, long value) {
|
||||
if ((value < 0) || (value > 0xffffffffL)) {
|
||||
throw new IllegalArgumentException("uint32 value of out range: " + value);
|
||||
}
|
||||
buffer.putInt(buffer.position() + offset, (int) value);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user