Compare commits

...

141 Commits

Author SHA1 Message Date
topjohnwu
773c24b7fc Bump version 2017-09-28 03:55:53 +08:00
topjohnwu
8f926c7ca9 Load scripts in memory 2017-09-28 03:33:56 +08:00
topjohnwu
c562cbc2bb Update zip and magisk installation 2017-09-26 20:46:58 +08:00
topjohnwu
3fbbb0865a Update trad. Chinese 2017-09-26 02:13:39 +08:00
Naboleo
7d5f612a48 Update strings.xml 2017-09-26 03:07:55 +09:00
linar10
4a5a36440b Update strings.xml 2017-09-26 03:07:41 +09:00
Dmitry Val'd
43dd5cfea1 Update RU translation
Added new or missing lines
2017-09-26 03:07:33 +09:00
dark-basic #DarkBasic BasicHD
7b5fec1842 Update strings.xml 2017-09-26 03:07:20 +09:00
topjohnwu
5762ded601 Properly detect hosts file 2017-09-25 17:55:40 +08:00
topjohnwu
a3abb86daa Only place files in de on FDE enabled devices 2017-09-24 21:29:01 +08:00
topjohnwu
4f5c656b05 Update uninstall method 2017-09-16 03:53:13 +08:00
topjohnwu
a31cddbe7b Prevent NPE 2017-09-16 02:41:24 +08:00
topjohnwu
b4ecd93f1c Proper FBE support: place files in DE 2017-09-15 18:03:25 +08:00
topjohnwu
0acc23e058 Allow dialog to popup 2017-09-15 13:55:36 +08:00
topjohnwu
cdd5f9b628 Fix busybox installation 2017-09-15 13:34:53 +08:00
topjohnwu
4c9f5f4655 Support patching second slot 2017-09-15 13:03:10 +08:00
topjohnwu
b80ba13cb4 Fix strings 2017-09-15 03:47:18 +08:00
Santiago Pintos
8260bdc09c Update translations into spanish
Add two strings: "zip_download_title" and "zip_download_msg"
2017-09-13 10:12:13 -05:00
RoySchutte
24f856e02b Update strings.xml 2017-09-13 10:12:03 -05:00
Mevlüt TOPÇU
3aa619b928 Update
Merge please

Thank you
2017-09-13 10:11:53 -05:00
Taras Korzhak
4cb5e98d94 Update Ukrainian translation 2017-09-13 10:11:25 -05:00
Primokorn
272910575e Update FR strings.xml
Stupid typo
Unhide Magisk Manager should not be translated
2017-09-13 10:09:37 -05:00
topjohnwu
a15a62f4bc Move logic to external script file 2017-09-13 23:07:59 +08:00
topjohnwu
53cf11db8c Fix failure if MagiskManager folder doesn't exist 2017-09-13 23:07:59 +08:00
Dmitry Val'd
01052fbe47 Update strings.xml 2017-09-07 10:45:27 +08:00
dark-basic #DarkBasic BasicHD
a5e1e075c7 Update Strings (6-9-17)
Small Update
New Line Added.
2017-09-07 10:45:12 +08:00
c727
6be32ac688 update german strings
small improvements for new strings
also unified some strings

@topjohnwu:
what do you thing about calling the hidden Magsik Manager also "Magisk Manager" instead of "Unhide Magisk Manager"
The hidden status could be symbolized by an incognito style version of the app icon
advantages:
-same position in app drawer
-no need to translate it
2017-09-07 10:45:02 +08:00
topjohnwu
b362c0ef38 Bump version 2017-09-06 23:06:18 +08:00
topjohnwu
bba9969e31 Fix install button hiding 2017-09-06 23:05:51 +08:00
Primokorn
007ba24809 Update FR strings.xml 2017-09-06 22:33:04 +08:00
topjohnwu
df21539311 Some versioning fixes 2017-09-06 22:32:40 +08:00
topjohnwu
2592cb6019 Show Install button after update check done 2017-09-06 16:28:24 +08:00
topjohnwu
f7df17a7ed Small fix 2017-09-06 15:42:45 +08:00
dark-basic #DarkBasic BasicHD
62f42b72f8 Update Strings.xml (05-09-17)
New lines added.
2017-09-06 14:42:22 +08:00
topjohnwu
a1ba4fda6f Improve install Magisk 2017-09-06 14:41:59 +08:00
topjohnwu
1c06b04c45 Use GNU tar format 2017-09-06 13:39:29 +08:00
topjohnwu
2ee22fd374 Add restore stock image feature 2017-09-05 17:43:13 +08:00
topjohnwu
4c230d9e61 Root shell workaround 2017-09-05 13:46:54 +08:00
topjohnwu
727294fbbe Disable D8, dex not compatible with Android 5.0 2017-09-05 02:57:30 +08:00
Dmitry Val'd
478c43969b Update strings.xml
Added missing/new lines
2017-09-05 02:50:36 +08:00
Jens Lody
79b5303350 Update german translation 2017-09-05 02:50:20 +08:00
topjohnwu
ce4b742b25 Support .img.tar as input 2017-09-04 01:57:45 +08:00
topjohnwu
a9dc15bda5 Update TW translations 2017-09-04 01:14:38 +08:00
topjohnwu
ba6387ff5c Resource cleanup! 2017-09-04 00:58:39 +08:00
linar10
8fa98508b7 Update strings.xml 2017-09-03 23:18:12 +08:00
Dmitry Val'd
decdbaecf9 Update strings.xml
Added missing lines
2017-09-03 23:18:02 +08:00
gh2923
6d87cf9be0 Update Simplified Chinese Translation 2017-09-03 23:17:53 +08:00
Leonidas P
94f434c4a6 Translate Update Channel Strings 2017-09-03 23:17:36 +08:00
dark-basic #DarkBasic BasicHD
7ba867c30b Update Strings - (New Update 03-09-17) 2017-09-03 23:17:18 +08:00
topjohnwu
3424395e10 Calculate offset for unhide 2017-09-03 23:00:54 +08:00
topjohnwu
926c7359a2 Merge download and process repo modules 2017-09-03 22:10:54 +08:00
topjohnwu
ec0af99a2e Fix locale settings 2017-09-03 21:12:09 +08:00
topjohnwu
b4d948886c Fix unzip issues 2017-09-03 21:05:57 +08:00
topjohnwu
4d8d79372a Update strings 2017-09-03 18:28:46 +08:00
topjohnwu
04a589722c Support .img.tar format for ODIN 2017-09-03 17:46:00 +08:00
topjohnwu
d4a10e2873 Various adjustments 2017-09-03 17:46:00 +08:00
topjohnwu
4998ad6c7e Show Manager updates in dialogs 2017-09-03 14:58:21 +08:00
topjohnwu
a07ca5ff50 Slightly change busybox handling 2017-09-03 03:26:01 +08:00
topjohnwu
f07e7571ab Change block detection method 2017-09-03 02:45:43 +08:00
topjohnwu
834c16485c Reduce unnecessary code 2017-09-03 02:34:23 +08:00
topjohnwu
04a4265ef3 Show correct message 2017-09-03 00:17:42 +08:00
topjohnwu
0ec473195d Update install Magisk method 2017-09-03 00:10:14 +08:00
topjohnwu
0bf09256b0 Update Android Studio and Gradle 2017-09-02 19:12:03 +08:00
topjohnwu
db8fd2c913 Add boot image file patch 2017-08-31 03:07:33 +08:00
topjohnwu
dbe6e5b3d7 Simplify app startup 2017-08-30 02:28:24 +08:00
topjohnwu
cc81cd446b Extract ExpandableView code into interface 2017-08-29 04:10:04 +08:00
topjohnwu
439c7118f1 Proper runtime permission implementation 2017-08-29 03:08:09 +08:00
topjohnwu
d8154a5815 Update deprecate code 2017-08-29 01:56:43 +08:00
topjohnwu
4e3787bc0d Add beta update channel 2017-08-29 01:34:42 +08:00
topjohnwu
02e0955924 Fix settings crash 2017-08-29 00:37:52 +08:00
topjohnwu
a78950e822 Reduce boilerplate 2017-08-28 00:27:10 +08:00
topjohnwu
1ce1a94a35 Update translations 2017-08-27 01:38:05 +08:00
gh2923
977b6d9f67 Update Simplified Chinese Translation 2017-08-27 01:09:49 +08:00
Igor Sorocean
b5e6dbd797 update romanian translation 2017-08-27 01:09:41 +08:00
Taras
833e6688f1 Added Ukrainian translation 2017-08-27 01:09:33 +08:00
Dmitry Val'd
bc22c9f84f Update strings.xml
Added missing strings
2017-08-27 01:08:25 +08:00
Mevlüt TOPÇU
2149a7d116 Update
Merge please
2017-08-27 01:08:14 +08:00
dark-basic #DarkBasic BasicHD
29175d2c17 Update Strings.xml 2017-08-27 01:07:45 +08:00
Leonidas P
803454d5c8 Update Greek Strings 2017-08-27 01:07:26 +08:00
topjohnwu
36cf32dc42 Change unhide app temp location 2017-08-27 01:04:55 +08:00
topjohnwu
657f4ab303 Add hide Magisk Manager feature 2017-08-22 03:01:54 +08:00
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
117 changed files with 4032 additions and 3107 deletions

4
.gitignore vendored
View File

@@ -6,3 +6,7 @@
app/release
*.hprof
app/.externalNativeBuild/
*.sh
public.certificate.x509.pem
private.key.pk8
*.apk

View File

@@ -1,6 +1,7 @@
# Magisk Manager
You need to install CMake and NDK to build the zipadjust library for zip preprocessing
# Magisk Manager
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)
## Pre-built Binaries
Busybox (arm and x86) compiled by osm0sis (`libbusybox.so` under `app\src\main\jniLibs`)
Source and more info: [osm0sis' Odds and Ends](https://forum.xda-developers.com/showthread.php?t=2239421)
## 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

@@ -2,17 +2,22 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 26
versionCode 50
versionName "5.1.0"
versionCode 55
versionName "5.3.5"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'armeabi-v7a'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
javaCompileOptions {
annotationProcessorOptions {
argument('butterknife.debuggable', 'false')
}
}
}
@@ -48,16 +53,16 @@ repositories {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
implementation 'com.android.support:design:26.0.0-beta2'
implementation 'com.android.support:support-v4:26.0.0-beta2'
implementation 'com.jakewharton:butterknife:8.7.0'
implementation 'com.thoughtbot:expandablerecyclerview:1.4'
implementation 'us.feras.mdv:markdownview:1.1.0'
implementation 'com.madgag.spongycastle:core:1.54.0.0'
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
implementation 'com.madgag.spongycastle:pkix:1.54.0.0'
implementation project(':resource')
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:cardview-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:support-v4:26.1.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 'org.kamranzafar:jtar:2.3'
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
}

View File

@@ -16,8 +16,8 @@
# public *;
#}
# SpongyCastle
-keep class org.spongycastle.** { *; }
# BouncyCastle
-keep class org.bouncycastle.** { *; }
-dontwarn javax.naming.**
-dontwarn android.content.**

View File

@@ -17,7 +17,8 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
android:directBootAware="true"
tools:ignore="UnusedAttribute">
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"

View File

@@ -1,137 +0,0 @@
#!/system/bin/sh
##########################################################################################
#
# Magisk Uninstaller
# by topjohnwu
#
# This script can be placed in /cache/magisk_uninstaller.sh
# The Magisk main binary will pick up the script, and uninstall itself, following a reboot
# This script can also be used in flashable zip with the uninstaller_loader.sh
#
# This script will try to do restoration with the following:
# 1-1. Find and restore the original stock boot image dump (OTA proof)
# 1-2. If 1-1 fails, restore ramdisk from the internal backup
# (ramdisk fully restored, not OTA friendly)
# 1-3. If 1-2 fails, it will remove added files in ramdisk, however modified files
# are remained modified, because we have no backups. By doing so, Magisk will
# not be started at boot, but this isn't actually 100% cleaned up
# 2. Remove all Magisk related files
# (The list is LARGE, most likely due to bad decision in early versions
# the latest versions has much less bloat to cleanup)
#
##########################################################################################
# Call ui_print_wrap if exists, or else simply use echo
# Useful when wrapped in flashable zip
ui_print_wrap() {
type ui_print >/dev/null 2>&1 && ui_print "$1" || echo "$1"
}
# Call abort if exists, or else show error message and exit
# Essential when wrapped in flashable zip
abort_wrap() {
type abort >/dev/null 2>&1
if [ $? -ne 0 ]; then
ui_print_wrap "$1"
exit 1
else
abort "$1"
fi
}
if [ ! -d $MAGISKBIN -o ! -f $MAGISKBIN/magiskboot -o ! -f $MAGISKBIN/util_functions.sh ]; then
ui_print_wrap "! Cannot find $MAGISKBIN"
exit 1
fi
[ -z $BOOTMODE ] && BOOTMODE=false
MAGISKBIN=/data/magisk
CHROMEDIR=$MAGISKBIN/chromeos
# Default permissions
umask 022
# Load utility functions
. $MAGISKBIN/util_functions.sh
# Find the boot image
find_boot_image
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
ui_print_wrap "- Found Boot Image: $BOOTIMAGE"
cd $MAGISKBIN
ui_print_wrap "- Unpacking boot image"
./magiskboot --unpack "$BOOTIMAGE"
[ $? -ne 0 ] && abort_wrap "! Unable to unpack boot image"
# Update our previous backup to new format if exists
if [ -f /data/stock_boot.img ]; then
SHA1=`./magiskboot --sha1 /data/stock_boot.img | tail -n 1`
STOCKDUMP=/data/stock_boot_${SHA1}.img
mv /data/stock_boot.img $STOCKDUMP
./magiskboot --compress $STOCKDUMP
fi
# Detect boot image state
./magiskboot --cpio-test ramdisk.cpio
case $? in
0 ) # Stock boot
ui_print_wrap "- Stock boot image detected!"
ui_print_wrap "! Magisk is not installed!"
exit
;;
1 ) # Magisk patched
ui_print_wrap "- Magisk patched image detected!"
# Find SHA1 of stock boot image
if [ -z $SHA1 ]; then
./magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc.old
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc.old`
rm -f init.magisk.rc.old
fi
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
if [ -f ${STOCKDUMP}.gz ]; then
ui_print_wrap "- Boot image backup found!"
./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
else
ui_print_wrap "! Boot image backup unavailable"
ui_print_wrap "- Restoring ramdisk with backup"
./magiskboot --cpio-restore ramdisk.cpio
./magiskboot --repack $BOOTIMAGE stock_boot.img
fi
;;
2 ) # Other patched
ui_print_wrap "! Boot image patched by other programs!"
abort_wrap "! Cannot uninstall with this uninstaller"
;;
esac
# Sign chromeos boot
if [ -f chromeos ]; then
echo > empty
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 empty --arch arm --bootloader empty --flags 0x1
rm -f empty stock_boot.img
mv stock_boot.img.signed stock_boot.img
fi
ui_print_wrap "- Flashing stock/reverted image"
if [ -L "$BOOTIMAGE" ]; then
dd if=stock_boot.img of="$BOOTIMAGE" bs=4096
else
cat stock_boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1
fi
rm -f stock_boot.img
ui_print_wrap "- 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/magisk_debug.log \
/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

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

View File

@@ -42,7 +42,7 @@ public class AboutActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getApplicationContext().isDarkTheme) {
if (getMagiskManager().isDarkTheme) {
setTheme(R.style.AppTheme_Transparent_Dark);
}
setContentView(R.layout.activity_about);

View File

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
@@ -8,25 +9,37 @@ import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.asyncs.FlashZip;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Shell;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class FlashActivity extends Activity {
public static final String SET_ACTION = "action";
public static final String SET_BOOT = "boot";
public static final String SET_ENC = "enc";
public static final String SET_VERITY = "verity";
public static final String FLASH_ZIP = "flash";
public static final String PATCH_BOOT = "patch";
public static final String FLASH_MAGISK = "magisk";
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.flash_logs) RecyclerView flashLogs;
@BindView(R.id.button_panel) LinearLayout buttonPanel;
private AdaptiveList<String> rootShellOutput;
@BindView(R.id.reboot) Button reboot;
@OnClick(R.id.no_thanks)
public void dismiss() {
@@ -35,7 +48,7 @@ public class FlashActivity extends Activity {
@OnClick(R.id.reboot)
public void reboot() {
Shell.getShell(this).su_raw("reboot");
getShell().su_raw("reboot");
}
@Override
@@ -43,22 +56,56 @@ public class FlashActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
ButterKnife.bind(this);
rootShellOutput = new AdaptiveList<>(flashLogs);
AdaptiveList<String> rootShellOutput = new AdaptiveList<>(flashLogs);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.flashing);
}
setFloating();
if (!Shell.rootAccess())
reboot.setVisibility(View.GONE);
flashLogs.setAdapter(new FlashLogAdapter());
flashLogs.setAdapter(new FlashLogAdapter(rootShellOutput));
// We must receive a Uri of the target zip
Uri uri = getIntent().getData();
Intent intent = getIntent();
Uri uri = intent.getData();
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
boolean keepEnc = intent.getBooleanExtra(SET_ENC, false);
boolean keepVerity = intent.getBooleanExtra(SET_VERITY, false);
switch (getIntent().getStringExtra(SET_ACTION)) {
case FLASH_ZIP:
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
break;
case PATCH_BOOT:
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, (Uri) intent.getParcelableExtra(SET_BOOT))
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
break;
case FLASH_MAGISK:
String boot = intent.getStringExtra(SET_BOOT);
if (getMagiskManager().remoteMagiskVersionCode < 1370) {
// Use legacy installation method
getShell().su_raw(
"echo \"BOOTIMAGE=" + boot + "\" > /dev/.magisk",
"echo \"KEEPFORCEENCRYPT=" + keepEnc + "\" >> /dev/.magisk",
"echo \"KEEPVERITY=" + keepVerity + "\" >> /dev/.magisk"
);
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
} else {
// Use new installation method
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, boot)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
}
break;
}
}
@Override
@@ -66,7 +113,13 @@ public class FlashActivity extends Activity {
// Prevent user accidentally press back button
}
private class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
private static class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
private List<String> mList;
FlashLogAdapter(List<String> list) {
mList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
@@ -77,16 +130,16 @@ public class FlashActivity extends Activity {
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(rootShellOutput.get(position));
holder.text.setText(mList.get(position));
}
@Override
public int getItemCount() {
return rootShellOutput.size();
return mList.size();
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
public static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.textView) TextView text;

View File

@@ -29,6 +29,8 @@ public class LogFragment extends Fragment {
View v = inflater.inflate(R.layout.fragment_log, container, false);
unbinder = ButterKnife.bind(this, v);
((MainActivity) getActivity()).toolbar.setElevation(0);
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
if (getApplication().isSuClient) {

View File

@@ -1,12 +1,8 @@
package com.topjohnwu.magisk;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
@@ -14,7 +10,6 @@ import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
@@ -25,18 +20,13 @@ import android.widget.Spinner;
import android.widget.TextView;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.ExpandableView;
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.Topic;
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;
@@ -47,14 +37,13 @@ import butterknife.OnClick;
import butterknife.Unbinder;
public class MagiskFragment extends Fragment
implements CallbackEvent.Listener<Void>, SwipeRefreshLayout.OnRefreshListener {
implements Topic.Subscriber, SwipeRefreshLayout.OnRefreshListener, ExpandableView {
private static boolean noDialog = false;
private static int expandHeight = 0;
private static boolean mExpanded = false;
private Container expandableContainer = new Container();
private MagiskManager magiskManager;
private MagiskManager mm;
private Unbinder unbinder;
private static boolean shownDialog = false;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@@ -95,7 +84,7 @@ public class MagiskFragment extends Fragment
@BindColor(R.color.blue500) int colorInfo;
@OnClick(R.id.safetyNet_title)
public void safetyNet() {
void safetyNet() {
safetyNetProgress.setVisibility(View.VISIBLE);
safetyNetRefreshIcon.setVisibility(View.GONE);
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
@@ -104,114 +93,23 @@ public class MagiskFragment extends Fragment
}
@OnClick(R.id.install_button)
public void install() {
String bootImage = null;
if (Shell.rootAccess()) {
if (magiskManager.bootBlock != null) {
bootImage = magiskManager.bootBlock;
} else {
int idx = spinner.getSelectedItemPosition();
if (idx > 0) {
bootImage = magiskManager.blockList.get(idx - 1);
} else {
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
return;
}
}
}
final String finalBootImage = bootImage;
String filename = "Magisk-v" + magiskManager.remoteMagiskVersionString + ".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,
(d, i) ->
Utils.dlAndReceive(
getActivity(),
new DownloadReceiver() {
private String boot = finalBootImage;
private boolean enc = keepEncChkbox.isChecked();
private boolean verity = keepVerityChkbox.isChecked();
void install() {
shownDialog = true;
@Override
public void onDownloadDone(Uri uri) {
if (Shell.rootAccess()) {
magiskManager.shell.su_raw(
"rm -f /dev/.magisk",
"echo \"BOOTIMAGE=" + boot + "\" >> /dev/.magisk",
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
);
startActivity(new Intent(getActivity(), FlashActivity.class).setData(uri));
} else {
Utils.showUriSnack(getActivity(), uri);
}
}
},
magiskManager.magiskLink,
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.release_notes, (d, i) -> {
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();
// Show Manager update first
if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
Utils.showManagerInstallDialog(getActivity());
return;
}
((NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
Utils.showMagiskInstallDialog(this,
keepEncChkbox.isChecked(), keepVerityChkbox.isChecked());
}
@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(MagiskManager.UNINSTALLER);
File uninstaller = new File(magiskManager.getCacheDir(), MagiskManager.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();
in = magiskManager.getAssets().open(MagiskManager.UTIL_FUNCTIONS);
File utils = new File(magiskManager.getCacheDir(), MagiskManager.UTIL_FUNCTIONS);
out = new FileOutputStream(utils);
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));
magiskManager.shell.su_raw(
"mv -f " + uninstaller + " /cache/" + MagiskManager.UNINSTALLER,
"mv -f " + utils + " /data/magisk/" + MagiskManager.UTIL_FUNCTIONS,
"reboot"
);
}
}.start();
} catch (IOException e) {
e.printStackTrace();
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
void uninstall() {
Utils.showUninstallDialog(this);
}
@Nullable
@@ -219,39 +117,14 @@ public class MagiskFragment extends Fragment
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_magisk, container, false);
unbinder = ButterKnife.bind(this, v);
magiskManager = getApplication();
getActivity().setTitle(R.string.magisk);
expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (expandHeight == 0) {
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
expandLayout.measure(widthSpec, heightSpec);
expandHeight = expandLayout.getMeasuredHeight();
}
mm = getApplication();
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
setExpanded();
return true;
}
});
expandableContainer.expandLayout = expandLayout;
setupExpandable();
mSwipeRefreshLayout.setOnRefreshListener(this);
if (magiskManager.magiskVersionCode < 0 && Shell.rootAccess() && !noDialog) {
noDialog = true;
new AlertDialogBuilder(getActivity())
.setTitle(R.string.no_magisk_title)
.setMessage(R.string.no_magisk_msg)
.setCancelable(true)
.setPositiveButton(R.string.goto_install, (d, i) -> {})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
updateUI();
return v;
@@ -259,6 +132,7 @@ public class MagiskFragment extends Fragment
@Override
public void onRefresh() {
mm.getMagiskInfo();
updateUI();
magiskUpdateText.setText(R.string.checking_for_updates);
@@ -267,15 +141,16 @@ public class MagiskFragment extends Fragment
safetyNetStatusText.setText(R.string.safetyNet_check_text);
magiskManager.safetyNetDone.isTriggered = false;
magiskManager.updateCheckDone.isTriggered = false;
magiskManager.remoteMagiskVersionString = null;
magiskManager.remoteMagiskVersionCode = -1;
mm.safetyNetDone.hasPublished = false;
mm.updateCheckDone.hasPublished = false;
mm.remoteMagiskVersionString = null;
mm.remoteMagiskVersionCode = -1;
collapse();
noDialog = false;
shownDialog = false;
// Trigger state check
if (Utils.checkNetworkStatus(magiskManager)) {
if (Utils.checkNetworkStatus(mm)) {
new CheckUpdates(getActivity()).exec();
} else {
mSwipeRefreshLayout.setRefreshing(false);
@@ -283,32 +158,17 @@ public class MagiskFragment extends Fragment
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
if (event == magiskManager.updateCheckDone) {
public void onTopicPublished(Topic topic) {
if (topic == mm.updateCheckDone) {
updateCheckUI();
} else if (event == magiskManager.safetyNetDone) {
} else if (topic == mm.safetyNetDone) {
updateSafetyNetUI();
}
}
@Override
public void onStart() {
super.onStart();
// Manual trigger if already done
if (magiskManager.updateCheckDone.isTriggered)
updateCheckUI();
if (magiskManager.safetyNetDone.isTriggered)
updateSafetyNetUI();
magiskManager.updateCheckDone.register(this);
magiskManager.safetyNetDone.register(this);
getActivity().setTitle(R.string.magisk);
}
@Override
public void onStop() {
magiskManager.updateCheckDone.unRegister(this);
magiskManager.safetyNetDone.unRegister(this);
super.onStop();
public Topic[] getSubscription() {
return new Topic[] { mm.updateCheckDone, mm.safetyNetDone };
}
@Override
@@ -317,32 +177,53 @@ public class MagiskFragment extends Fragment
unbinder.unbind();
}
@Override
public Container getContainer() {
return expandableContainer;
}
public String getSelectedBootImage() {
if (Shell.rootAccess()) {
if (mm.bootBlock != null) {
return mm.bootBlock;
} else {
int idx = spinner.getSelectedItemPosition();
if (idx > 0) {
return mm.blockList.get(idx - 1);
} else {
SnackbarMaker.make(getActivity(),
R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
return null;
}
}
} else {
return null;
}
}
private void updateUI() {
((MainActivity) getActivity()).checkHideSection();
magiskManager.updateMagiskInfo();
final int ROOT = 0x1, NETWORK = 0x2, UPTODATE = 0x4;
int status = 0;
status |= Shell.rootAccess() ? ROOT : 0;
status |= Utils.checkNetworkStatus(magiskManager) ? NETWORK : 0;
status |= magiskManager.magiskVersionCode >= 130 ? UPTODATE : 0;
magiskUpdateCard.setVisibility(Utils.checkBits(status, NETWORK) ? View.VISIBLE : View.GONE);
safetyNetCard.setVisibility(Utils.checkBits(status, NETWORK) ? View.VISIBLE : View.GONE);
bootImageCard.setVisibility(Utils.checkBits(status, NETWORK, ROOT) ? View.VISIBLE : View.GONE);
installOptionCard.setVisibility(Utils.checkBits(status, NETWORK, ROOT) ? View.VISIBLE : View.GONE);
installButton.setVisibility(Utils.checkBits(status, NETWORK) ? View.VISIBLE : View.GONE);
uninstallButton.setVisibility(Utils.checkBits(status, UPTODATE, ROOT) ? View.VISIBLE : View.GONE);
boolean hasNetwork = Utils.checkNetworkStatus(getActivity());
boolean hasRoot = Shell.rootAccess();
boolean isUpToDate = mm.magiskVersionCode > 1300;
magiskUpdateCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
safetyNetCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
bootImageCard.setVisibility(hasNetwork && hasRoot ? View.VISIBLE : View.GONE);
installOptionCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
uninstallButton.setVisibility(isUpToDate && hasRoot ? View.VISIBLE : View.GONE);
int image, color;
if (magiskManager.magiskVersionCode < 0) {
if (mm.magiskVersionCode < 0) {
color = colorBad;
image = R.drawable.ic_cancel;
magiskVersionText.setText(R.string.magisk_version_error);
} else {
color = colorOK;
image = R.drawable.ic_check_circle;
magiskVersionText.setText(getString(R.string.current_magisk_title, "v" + magiskManager.magiskVersionString));
magiskVersionText.setText(getString(R.string.current_magisk_title, "v" + mm.magiskVersionString));
}
magiskStatusIcon.setImageResource(image);
@@ -355,10 +236,10 @@ public class MagiskFragment extends Fragment
rootStatusText.setText(R.string.not_rooted);
break;
case 1:
if (magiskManager.suVersion != null) {
if (mm.suVersion != null) {
color = colorOK;
image = R.drawable.ic_check_circle;
rootStatusText.setText(magiskManager.suVersion);
rootStatusText.setText(mm.suVersion);
break;
}
case -1:
@@ -371,37 +252,46 @@ public class MagiskFragment extends Fragment
rootStatusIcon.setImageResource(image);
rootStatusIcon.setColorFilter(color);
if (!Shell.rootAccess()) {
installText.setText(R.string.download);
List<String> items = new ArrayList<>();
if (mm.bootBlock != null) {
items.add(getString(R.string.auto_detect, mm.bootBlock));
spinner.setEnabled(false);
} else {
installText.setText(R.string.download_install);
List<String> items = new ArrayList<>();
if (magiskManager.bootBlock != null) {
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
spinner.setEnabled(false);
} 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);
items.add(getString(R.string.cannot_auto_detect));
if (mm.blockList != null)
items.addAll(mm.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);
}
private void updateCheckUI() {
int image, color;
if (magiskManager.remoteMagiskVersionCode < 0) {
if (mm.remoteMagiskVersionCode < 0) {
color = colorNeutral;
image = R.drawable.ic_help;
magiskUpdateText.setText(R.string.cannot_check_updates);
} else {
color = colorOK;
image = R.drawable.ic_check_circle;
magiskUpdateText.setText(getString(R.string.install_magisk_title, "v" + magiskManager.remoteMagiskVersionString));
magiskUpdateText.setText(getString(R.string.install_magisk_title, "v" + mm.remoteMagiskVersionString));
}
installButton.setVisibility(View.VISIBLE);
if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
installText.setText(getString(R.string.update, getString(R.string.app_name)));
} else if (mm.magiskVersionCode > 0 && mm.remoteMagiskVersionCode > mm.magiskVersionCode) {
installText.setText(getString(R.string.update, getString(R.string.magisk)));
} else {
installText.setText(R.string.install);
}
if (!shownDialog && (mm.remoteMagiskVersionCode > mm.magiskVersionCode
|| mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE)) {
install();
}
magiskUpdateIcon.setImageResource(image);
@@ -416,85 +306,34 @@ public class MagiskFragment extends Fragment
int image, color;
safetyNetProgress.setVisibility(View.GONE);
safetyNetRefreshIcon.setVisibility(View.VISIBLE);
if (magiskManager.SNCheckResult.failed) {
safetyNetStatusText.setText(magiskManager.SNCheckResult.errmsg);
if (mm.SNCheckResult.failed) {
safetyNetStatusText.setText(mm.SNCheckResult.errmsg);
collapse();
} else {
safetyNetStatusText.setText(R.string.safetyNet_check_success);
if (magiskManager.SNCheckResult.ctsProfile) {
if (mm.SNCheckResult.ctsProfile) {
color = colorOK;
image = R.drawable.ic_check_circle;
} else {
color = colorBad;
image = R.drawable.ic_cancel;
}
ctsStatusText.setText("ctsProfile: " + magiskManager.SNCheckResult.ctsProfile);
ctsStatusText.setText("ctsProfile: " + mm.SNCheckResult.ctsProfile);
ctsStatusIcon.setImageResource(image);
ctsStatusIcon.setColorFilter(color);
if (magiskManager.SNCheckResult.basicIntegrity) {
if (mm.SNCheckResult.basicIntegrity) {
color = colorOK;
image = R.drawable.ic_check_circle;
} else {
color = colorBad;
image = R.drawable.ic_cancel;
}
basicStatusText.setText("basicIntegrity: " + magiskManager.SNCheckResult.basicIntegrity);
basicStatusText.setText("basicIntegrity: " + mm.SNCheckResult.basicIntegrity);
basicStatusIcon.setImageResource(image);
basicStatusIcon.setColorFilter(color);
expand();
}
}
private void setExpanded() {
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = mExpanded ? expandHeight : 0;
expandLayout.setLayoutParams(layoutParams);
expandLayout.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
}
private void expand() {
if (mExpanded) return;
expandLayout.setVisibility(View.VISIBLE);
ValueAnimator mAnimator = slideAnimator(0, expandHeight);
mAnimator.start();
mExpanded = true;
}
private void collapse() {
if (!mExpanded) return;
int finalHeight = expandLayout.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
expandLayout.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
});
mAnimator.start();
mExpanded = false;
}
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = value;
expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

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

@@ -2,16 +2,10 @@ package com.topjohnwu.magisk;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
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;
@@ -28,13 +22,13 @@ import android.widget.Toast;
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;
@@ -45,29 +39,22 @@ public class MagiskLogFragment extends Fragment {
private static final String MAGISK_LOG = "/cache/magisk.log";
private Unbinder unbinder;
@BindView(R.id.txtLog) TextView txtLog;
@BindView(R.id.svLog) ScrollView svLog;
@BindView(R.id.hsvLog) HorizontalScrollView hsvLog;
@BindView(R.id.progressBar) ProgressBar progressBar;
private MenuItem mClickedMenuItem;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_magisk_log, container, false);
unbinder = ButterKnife.bind(this, view);
setHasOptionsMenu(true);
txtLog.setTextIsSelectable(true);
new LogManager(getActivity()).read();
new LogManager().read();
return view;
}
@@ -81,7 +68,7 @@ public class MagiskLogFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
new LogManager(getActivity()).read();
new LogManager().read();
}
@Override
@@ -97,43 +84,30 @@ public class MagiskLogFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
mClickedMenuItem = item;
switch (item.getItemId()) {
case R.id.menu_refresh:
new LogManager(getActivity()).read();
new LogManager().read();
return true;
case R.id.menu_save:
new LogManager(getActivity()).save();
Utils.runWithPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
() -> new LogManager().save());
return true;
case R.id.menu_clear:
new LogManager(getActivity()).clear();
new LogManager().clear();
return true;
default:
return true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 0) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (mClickedMenuItem != null) {
new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500);
}
} else {
SnackbarMaker.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
}
}
}
private class LogManager extends ParallelTask<Object, Void, Object> {
int mode;
File targetFile;
private int mode;
private File targetFile;
LogManager(Activity activity) {
super(activity);
LogManager() {
super(MagiskLogFragment.this.getActivity());
}
@SuppressLint("DefaultLocale")
@@ -142,34 +116,16 @@ public class MagiskLogFragment extends Fragment {
mode = (int) params[0];
switch (mode) {
case 0:
List<String> logList = Utils.readFile(magiskManager.shell, 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();
getShell().su(logList, "cat " + MAGISK_LOG);
return logList.toString();
case 1:
magiskManager.shell.su_raw("echo > " + MAGISK_LOG);
getShell().su_raw("echo -n > " + 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",
@@ -177,26 +133,21 @@ public class MagiskLogFragment extends Fragment {
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
targetFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MagiskManager/" + filename);
targetFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
if ((!targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs())
|| (targetFile.exists() && !targetFile.delete())) {
return false;
}
List<String> in = Utils.readFile(magiskManager.shell, 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);
getShell().su(fileWritingList, "cat " + MAGISK_LOG);
} catch (IOException e) {
e.printStackTrace();
return false;
}
return false;
return true;
}
return null;
}
@@ -204,12 +155,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);
@@ -219,27 +168,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();
getMagiskManager().toast(targetFile.toString(), Toast.LENGTH_LONG);
} else {
Toast.makeText(getActivity(), getString(R.string.logs_save_failed), Toast.LENGTH_LONG).show();
getMagiskManager().toast(R.string.logs_save_failed, Toast.LENGTH_LONG);
}
break;
}
}
public void read() {
void read() {
exec(0);
}
public void clear() {
void clear() {
exec(1);
}
public void save() {
void save() {
exec(2);
}
}
private static class StringBuildingList extends Shell.AbstractList<String> {
StringBuilder builder;
StringBuildingList() {
builder = new StringBuilder();
}
@Override
public boolean add(String s) {
builder.append(s).append("\n");
return true;
}
@Override
public String toString() {
return builder.toString();
}
}
private static class FileWritingList extends Shell.AbstractList<String> {
private FileWriter writer;
FileWritingList(FileWriter out) {
writer = out;
}
@Override
public boolean add(String s) {
try {
writer.write(s + "\n");
} catch (IOException ignored) {}
return true;
}
}
}

View File

@@ -3,47 +3,64 @@ package com.topjohnwu.magisk;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.DownloadBusybox;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.superuser.SuReceiver;
import com.topjohnwu.magisk.superuser.SuRequestActivity;
import com.topjohnwu.magisk.utils.SafetyNetHelper;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;
public class MagiskManager extends Application {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static final String MAGISK_HOST_FILE = "/magisk/.core/hosts";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_PATH = "/magisk";
public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String UTIL_FUNCTIONS= "util_functions.sh";
public static final String INTENT_SECTION = "section";
public static final String BUSYBOX_VERSION = "1.26.2";
public static final String INTENT_VERSION = "version";
public static final String INTENT_LINK = "link";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
public static final String NOTIFICATION_CHANNEL = "magisk_update_notice";
public static final String BUSYBOXPATH = "/dev/magisk/bin";
public static final int UPDATE_SERVICE_ID = 1;
// Events
public final CallbackEvent<Void> magiskHideDone = new CallbackEvent<>();
public final CallbackEvent<Void> reloadMainActivity = new CallbackEvent<>();
public final CallbackEvent<Void> moduleLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
// Topics
public final Topic magiskHideDone = new Topic();
public final Topic reloadActivity = new Topic();
public final Topic moduleLoadDone = new Topic();
public final Topic repoLoadDone = new Topic();
public final Topic updateCheckDone = new Topic();
public final Topic safetyNetDone = new Topic();
public final Topic localeDone = new Topic();
// Info
public String magiskVersionString;
@@ -62,15 +79,15 @@ public class MagiskManager extends Application {
public boolean disabled;
// Data
public ValueSortedMap<String, Repo> repoMap;
public ValueSortedMap<String, Module> moduleMap;
public Map<String, Module> moduleMap;
public List<String> blockList;
public List<ApplicationInfo> appList;
public List<String> magiskHideList;
public List<Locale> locales;
// Configurations
public static boolean shellLogging;
public static boolean devLogging;
public static Locale locale;
public static Locale defaultLocale;
public boolean magiskHide;
public boolean isDarkTheme;
@@ -83,20 +100,90 @@ public class MagiskManager extends Application {
public int suResponseType;
public int suNotificationType;
public int suNamespaceMode;
public String localeConfig;
public int updateChannel;
public String bootFormat;
// Global resources
public SharedPreferences prefs;
public SuDatabaseHelper suDB;
public RepoDatabaseHelper repoDB;
public Shell shell;
private static Handler mHandler = new Handler();
private boolean started = false;
private static class LoadLocale extends ParallelTask<Void, Void, Void> {
LoadLocale(Context context) {
super(context);
}
@Override
protected Void doInBackground(Void... voids) {
getMagiskManager().locales = Utils.getAvailableLocale(getMagiskManager());
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
getMagiskManager().localeDone.publish();
}
}
@Override
public void onCreate() {
super.onCreate();
new File(getApplicationInfo().dataDir).mkdirs(); /* Create the app data directory */
prefs = PreferenceManager.getDefaultSharedPreferences(this);
shell = Shell.getShell();
if (getDatabasePath(SuDatabaseHelper.DB_NAME).exists()) {
// Don't migrate yet, wait and check Magisk version
suDB = new SuDatabaseHelper(this);
} else {
suDB = new SuDatabaseHelper(Utils.getEncContext(this));
}
repoDB = new RepoDatabaseHelper(this);
defaultLocale = Locale.getDefault();
setLocale();
loadConfig();
}
public void setLocale() {
localeConfig = prefs.getString("locale", "");
if (localeConfig.isEmpty()) {
locale = defaultLocale;
} else {
locale = Locale.forLanguageTag(localeConfig);
}
Resources res = getBaseContext().getResources();
Configuration config = new Configuration(res.getConfiguration());
config.setLocale(locale);
res.updateConfiguration(config, res.getDisplayMetrics());
}
public void loadConfig() {
isDarkTheme = prefs.getBoolean("dark_theme", false);
if (BuildConfig.DEBUG) {
devLogging = prefs.getBoolean("developer_logging", false);
shellLogging = prefs.getBoolean("shell_logging", false);
} else {
devLogging = false;
shellLogging = false;
}
// su
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", SuRequestActivity.PROMPT);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", SuReceiver.TOAST);
suReauth = prefs.getBoolean("su_reauth", false);
suAccessState = suDB.getSettings(SuDatabaseHelper.ROOT_ACCESS, SuDatabaseHelper.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = suDB.getSettings(SuDatabaseHelper.MULTIUSER_MODE, SuDatabaseHelper.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = suDB.getSettings(SuDatabaseHelper.MNT_NS, SuDatabaseHelper.NAMESPACE_MODE_REQUESTER);
updateNotification = prefs.getBoolean("notification", true);
updateChannel = Utils.getPrefsInt(prefs, "update_channel", CheckUpdates.STABLE_CHANNEL);
bootFormat = prefs.getString("boot_format", ".img");
}
public void toast(String msg, int duration) {
@@ -107,36 +194,66 @@ public class MagiskManager extends Application {
mHandler.post(() -> Toast.makeText(this, resId, duration).show());
}
public void init() {
isDarkTheme = prefs.getBoolean("dark_theme", false);
if (BuildConfig.DEBUG) {
devLogging = prefs.getBoolean("developer_logging", false);
shellLogging = prefs.getBoolean("shell_logging", false);
} else {
devLogging = false;
shellLogging = false;
public void startup() {
if (started)
return;
started = true;
boolean hasNetwork = Utils.checkNetworkStatus(this);
getMagiskInfo();
// Check if we need to migrate suDB
if (getDatabasePath(SuDatabaseHelper.DB_NAME).exists() && Utils.useFDE(this)) {
if (magiskVersionCode >= 1410) {
suDB.close();
Context de = createDeviceProtectedStorageContext();
de.moveDatabaseFrom(this, SuDatabaseHelper.DB_NAME);
suDB = new SuDatabaseHelper(de);
}
}
magiskHide = prefs.getBoolean("magiskhide", true);
updateNotification = prefs.getBoolean("notification", true);
initSU();
updateMagiskInfo();
updateBlockInfo();
// Initialize busybox
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
busybox.getParentFile().mkdirs();
new LoadLocale(this).exec();
// Root actions
if (Shell.rootAccess()) {
if (hasNetwork && !Utils.itemExist(shell, BUSYBOXPATH + "/busybox")) {
try {
// Force synchronous, make sure we have busybox to use
new DownloadBusybox(this).exec().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
try (InputStream in = getAssets().open(Utils.UTIL_FUNCTIONS)) {
shell.loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
shell.su_raw(
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
"chmod -R 755 " + busybox.getParent(),
busybox + " --install -s " + busybox.getParent()
"export PATH=" + BUSYBOXPATH + ":$PATH",
"mount_partitions",
"BOOTIMAGE=",
"find_boot_image",
"migrate_boot_backup"
);
List<String> res = shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(res)) {
bootBlock = res.get(0);
} else {
blockList = shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
}
}
// Initialize prefs
// Write back default values
prefs.edit()
.putBoolean("dark_theme", isDarkTheme)
.putBoolean("magiskhide", magiskHide)
.putBoolean("notification", updateNotification)
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
.putBoolean("hosts", Utils.itemExist(shell, MAGISK_HOST_FILE))
.putBoolean("disable", Utils.itemExist(shell, MAGISK_DISABLE_FILE))
.putBoolean("su_reauth", suReauth)
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
@@ -145,45 +262,43 @@ public class MagiskManager extends Application {
.putString("su_access", String.valueOf(suAccessState))
.putString("multiuser_mode", String.valueOf(multiuserMode))
.putString("mnt_ns", String.valueOf(suNamespaceMode))
.putString("busybox_version", BUSYBOX_VERSION)
.putString("update_channel", String.valueOf(updateChannel))
.putString("locale", localeConfig)
.putString("boot_format", bootFormat)
.apply();
// Add busybox to PATH
shell.su_raw("PATH=$PATH:" + busybox.getParent());
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
LoadModules loadModuleTask = new LoadModules(this);
// Start update check job
if (hasNetwork) {
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(this).exec());
}
// Fire asynctasks
loadModuleTask.exec();
}
public void initSUConfig() {
suDB = new SuDatabaseHelper(this);
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
suReauth = prefs.getBoolean("su_reauth", false);
}
public void initSU() {
initSUConfig();
List<String> ret = shell.sh("su -v");
public void getMagiskInfo() {
List<String> ret;
Shell.getShell(this);
ret = shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) {
suVersion = ret.get(0);
isSuClient = suVersion.toUpperCase().contains("MAGISK");
}
if (isSuClient) {
suAccessState = suDB.getSettings(SuDatabaseHelper.ROOT_ACCESS, 3);
multiuserMode = suDB.getSettings(SuDatabaseHelper.MULTIUSER_MODE, 0);
suNamespaceMode = suDB.getSettings(SuDatabaseHelper.MNT_NS, 1);
}
}
public void updateMagiskInfo() {
List<String> ret;
ret = shell.sh("magisk -v");
if (!Utils.isValidShellResponse(ret)) {
ret = shell.sh("getprop magisk.version");
@@ -213,21 +328,4 @@ public class MagiskManager extends Application {
magiskHide = true;
}
}
public void updateBlockInfo() {
List<String> res = shell.su(
"for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do",
"BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null",
"[ ! -z \"$BOOTIMAGE\" ] && break",
"done",
"[ ! -z \"$BOOTIMAGE\" -a -L \"$BOOTIMAGE\" ] && BOOTIMAGE=`readlink $BOOTIMAGE`",
"echo \"$BOOTIMAGE\""
);
if (Utils.isValidShellResponse(res)) {
bootBlock = res.get(0);
} else {
blockList = shell.su("ls -d /dev/block/mmc* /dev/block/sd* 2>/dev/null");
}
}
}

View File

@@ -1,15 +1,11 @@
package com.topjohnwu.magisk;
import android.Manifest;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
@@ -20,15 +16,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;
@@ -42,24 +38,20 @@ public class MainActivity extends Activity
@Override
protected void onCreate(final Bundle savedInstanceState) {
getMagiskManager().startup();
prefs = getApplicationContext().prefs;
prefs = getMagiskManager().prefs;
if (getApplicationContext().isDarkTheme) {
if (getMagiskManager().isDarkTheme) {
setTheme(R.style.AppTheme_Dark);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
setSupportActionBar(toolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) {
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.magisk, R.string.magisk) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
@@ -81,7 +73,6 @@ public class MainActivity extends Activity
navigate(getIntent().getStringExtra(MagiskManager.INTENT_SECTION));
navigationView.setNavigationItemSelectedListener(this);
getApplicationContext().reloadMainActivity.register(this);
}
@@ -91,12 +82,6 @@ public class MainActivity extends Activity
checkHideSection();
}
@Override
protected void onDestroy() {
getApplicationContext().reloadMainActivity.unRegister(this);
super.onDestroy();
}
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(navigationView)) {
@@ -117,22 +102,27 @@ public class MainActivity extends Activity
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
public void onTopicPublished(Topic topic) {
recreate();
}
@Override
public Topic[] getSubscription() {
return new Topic[] { getMagiskManager().reloadActivity };
}
public void checkHideSection() {
Menu menu = navigationView.getMenu();
menu.findItem(R.id.magiskhide).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 1300
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 1300
&& prefs.getBoolean("magiskhide", false));
menu.findItem(R.id.modules).setVisible(
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 0);
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus(this) &&
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 0);
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
menu.findItem(R.id.superuser).setVisible(
Shell.rootAccess() && getApplicationContext().isSuClient);
Shell.rootAccess() && getMagiskManager().isSuClient);
}
public void navigate(String item) {
@@ -140,7 +130,6 @@ public class MainActivity extends Activity
if (item != null) {
switch (item) {
case "magisk":
case "install":
itemId = R.id.magisk;
break;
case "superuser":

View File

@@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -16,17 +15,18 @@ import com.topjohnwu.magisk.adapters.ModulesAdapter;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.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;
@@ -34,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<>();
@@ -44,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();
@@ -67,41 +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
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(data.getData()).putExtra("ACTION", "flash");
intent.setData(data.getData()).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
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

@@ -13,16 +13,16 @@ import android.widget.SearchView;
import android.widget.TextView;
import com.topjohnwu.magisk.adapters.ReposAdapter;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
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 ReposFragment extends Fragment implements CallbackEvent.Listener<Void> {
public class ReposFragment extends Fragment implements Topic.Subscriber {
private Unbinder unbinder;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@@ -43,36 +43,33 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
View view = inflater.inflate(R.layout.fragment_repos, container, false);
unbinder = ButterKnife.bind(this, view);
adapter = new ReposAdapter(getApplication().repoMap);
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) {
onTrigger(null);
}
getActivity().setTitle(R.string.downloads);
return view;
}
@Override
public void onTrigger(CallbackEvent<Void> event) {
public void onTopicPublished(Topic topic) {
Logger.dev("ReposFragment: UI refresh triggered");
if (getApplication().repoMap.isEmpty()) {
recyclerView.setVisibility(View.GONE);
emptyRv.setVisibility(View.VISIBLE);
} else {
adapter.filter(getApplication().moduleMap, "");
recyclerView.setVisibility(View.VISIBLE);
emptyRv.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
}
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
@@ -87,25 +84,12 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
@Override
public boolean onQueryTextChange(String newText) {
adapter.filter(getApplication().moduleMap, newText);
adapter.filter(newText);
return false;
}
});
}
@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
public void onDestroyView() {
super.onDestroyView();

View File

@@ -1,9 +1,11 @@
package com.topjohnwu.magisk;
import android.Manifest;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
@@ -13,25 +15,28 @@ import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.MagiskHide;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.HideManager;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SettingsActivity extends Activity {
public class SettingsActivity extends Activity implements Topic.Subscriber {
@BindView(R.id.toolbar) Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getApplicationContext().isDarkTheme) {
if (getMagiskManager().isDarkTheme) {
setTheme(R.style.AppTheme_Transparent_Dark);
}
@@ -56,14 +61,27 @@ public class SettingsActivity extends Activity {
}
@Override
public void onTopicPublished(Topic topic) {
recreate();
}
@Override
public Topic[] getSubscription() {
return new Topic[] { getMagiskManager().reloadActivity };
}
public static class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
implements SharedPreferences.OnSharedPreferenceChangeListener,
Topic.Subscriber {
private SharedPreferences prefs;
private PreferenceScreen prefScreen;
private ListPreference suAccess, autoRes, suNotification, requestTimeout, multiuserMode, namespaceMode;
private MagiskManager magiskManager;
private ListPreference updateChannel, suAccess, autoRes, suNotification,
requestTimeout, multiuserMode, namespaceMode;
private MagiskManager mm;
private PreferenceCategory generalCatagory;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -71,12 +89,14 @@ public class SettingsActivity extends Activity {
addPreferencesFromResource(R.xml.app_settings);
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
prefScreen = getPreferenceScreen();
magiskManager = Utils.getMagiskManager(getActivity());
mm = Utils.getMagiskManager(getActivity());
generalCatagory = (PreferenceCategory) findPreference("general");
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
PreferenceCategory developer = (PreferenceCategory) findPreference("developer");
updateChannel = (ListPreference) findPreference("update_channel");
suAccess = (ListPreference) findPreference("su_access");
autoRes = (ListPreference) findPreference("su_auto_response");
requestTimeout = (ListPreference) findPreference("su_request_timeout");
@@ -84,6 +104,7 @@ public class SettingsActivity extends Activity {
multiuserMode = (ListPreference) findPreference("multiuser_mode");
namespaceMode = (ListPreference) findPreference("mnt_ns");
SwitchPreference reauth = (SwitchPreference) findPreference("su_reauth");
Preference hideManager = findPreference("hide");
setSummary();
@@ -91,6 +112,7 @@ public class SettingsActivity extends Activity {
if (getActivity().getApplicationInfo().uid > 99999) {
prefScreen.removePreference(magiskCategory);
prefScreen.removePreference(suCategory);
generalCatagory.removePreference(hideManager);
}
// Remove re-authentication option on Android O, it will not work
@@ -103,6 +125,13 @@ public class SettingsActivity extends Activity {
return true;
});
hideManager.setOnPreferenceClickListener((pref) -> {
Utils.runWithPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
() -> new HideManager(getActivity()).exec());
return true;
});
if (!BuildConfig.DEBUG) {
prefScreen.removePreference(developer);
}
@@ -110,26 +139,53 @@ public class SettingsActivity extends Activity {
if (!Shell.rootAccess()) {
prefScreen.removePreference(magiskCategory);
prefScreen.removePreference(suCategory);
generalCatagory.removePreference(hideManager);
} else {
if (!magiskManager.isSuClient) {
if (!mm.isSuClient) {
prefScreen.removePreference(suCategory);
}
if (magiskManager.magiskVersionCode < 1300) {
if (mm.magiskVersionCode < 1300) {
prefScreen.removePreference(magiskCategory);
}
}
}
private void setLocalePreference(ListPreference lp) {
boolean isNew = lp == null;
if (isNew) {
lp = new ListPreference(getActivity());
}
CharSequence[] entries = new CharSequence[mm.locales.size() + 1];
CharSequence[] entryValues = new CharSequence[mm.locales.size() + 1];
entries[0] = getString(R.string.system_default);
entryValues[0] = "";
int i = 1;
for (Locale locale : mm.locales) {
entries[i] = locale.getDisplayName(locale);
entryValues[i++] = locale.toLanguageTag();
}
lp.setEntries(entries);
lp.setEntryValues(entryValues);
lp.setTitle(R.string.language);
lp.setKey("locale");
lp.setSummary(MagiskManager.locale.getDisplayName(MagiskManager.locale));
if (isNew) {
generalCatagory.addPreference(lp);
}
}
@Override
public void onResume() {
super.onResume();
prefs.registerOnSharedPreferenceChangeListener(this);
subscribeTopics();
}
@Override
public void onPause() {
super.onPause();
prefs.unregisterOnSharedPreferenceChangeListener(this);
unsubscribeTopics();
super.onPause();
}
@Override
@@ -140,94 +196,90 @@ public class SettingsActivity extends Activity {
switch (key) {
case "dark_theme":
enabled = prefs.getBoolean("dark_theme", false);
if (magiskManager.isDarkTheme != enabled) {
magiskManager.isDarkTheme = enabled;
magiskManager.reloadMainActivity.trigger();
getActivity().recreate();
if (mm.isDarkTheme != enabled) {
mm.reloadActivity.publish(false);
}
break;
case "disable":
enabled = prefs.getBoolean("disable", false);
if (enabled) {
Utils.createFile(magiskManager.shell, MagiskManager.MAGISK_DISABLE_FILE);
Utils.createFile(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
} else {
Utils.removeItem(magiskManager.shell, MagiskManager.MAGISK_DISABLE_FILE);
Utils.removeItem(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
}
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
break;
case "magiskhide":
enabled = prefs.getBoolean("magiskhide", false);
if (enabled) {
if (!magiskManager.isSuClient) {
new AlertDialogBuilder(getActivity())
.setTitle(R.string.no_magisksu_title)
.setMessage(R.string.no_magisksu_msg)
.setPositiveButton(R.string.understand, (dialog, which) -> new MagiskHide(getActivity()).enable())
.setCancelable(false)
.show();
} else {
new MagiskHide(getActivity()).enable();
}
Utils.enableMagiskHide(getShell());
} else {
new MagiskHide(getActivity()).disable();
Utils.disableMagiskHide(getShell());
}
break;
case "hosts":
enabled = prefs.getBoolean("hosts", false);
if (enabled) {
magiskManager.shell.su_raw(
"cp -af /system/etc/hosts /magisk/.core/hosts",
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
getShell().su_raw(
"cp -af /system/etc/hosts " + MagiskManager.MAGISK_HOST_FILE,
"mount -o bind " + MagiskManager.MAGISK_HOST_FILE + " /system/etc/hosts");
} else {
magiskManager.shell.su_raw(
getShell().su_raw(
"umount -l /system/etc/hosts",
"rm -f /magisk/.core/hosts");
"rm -f " + MagiskManager.MAGISK_HOST_FILE);
}
break;
case "su_access":
magiskManager.suAccessState = Utils.getPrefsInt(prefs, "su_access", 3);
magiskManager.suDB.setSettings(SuDatabaseHelper.ROOT_ACCESS, magiskManager.suAccessState);
mm.suDB.setSettings(SuDatabaseHelper.ROOT_ACCESS, Utils.getPrefsInt(prefs, "su_access"));
break;
case "multiuser_mode":
magiskManager.multiuserMode = Utils.getPrefsInt(prefs, "multiuser_mode", 0);
magiskManager.suDB.setSettings(SuDatabaseHelper.MULTIUSER_MODE, magiskManager.multiuserMode);
mm.suDB.setSettings(SuDatabaseHelper.MULTIUSER_MODE, Utils.getPrefsInt(prefs, "multiuser_mode"));
break;
case "mnt_ns":
magiskManager.suNamespaceMode = Utils.getPrefsInt(prefs, "mnt_ns", 1);
magiskManager.suDB.setSettings(SuDatabaseHelper.MNT_NS, magiskManager.suNamespaceMode);
mm.suDB.setSettings(SuDatabaseHelper.MNT_NS, Utils.getPrefsInt(prefs, "mnt_ns"));
break;
case "su_request_timeout":
magiskManager.suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
case "locale":
mm.setLocale();
mm.reloadActivity.publish(false);
break;
case "su_auto_response":
magiskManager.suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
break;
case "su_notification":
magiskManager.suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
break;
case "developer_logging":
MagiskManager.devLogging = prefs.getBoolean("developer_logging", false);
break;
case "shell_logging":
MagiskManager.shellLogging = prefs.getBoolean("shell_logging", false);
case "update_channel":
mm.updateChannel = Utils.getPrefsInt(prefs, "update_channel");
new CheckUpdates(mm, true).exec();
break;
}
mm.loadConfig();
setSummary();
}
private Shell getShell() {
return Shell.getShell(getActivity());
}
private void setSummary() {
updateChannel.setSummary(getResources()
.getStringArray(R.array.update_channel)[mm.updateChannel]);
suAccess.setSummary(getResources()
.getStringArray(R.array.su_access)[magiskManager.suAccessState]);
.getStringArray(R.array.su_access)[mm.suAccessState]);
autoRes.setSummary(getResources()
.getStringArray(R.array.auto_response)[magiskManager.suResponseType]);
.getStringArray(R.array.auto_response)[mm.suResponseType]);
suNotification.setSummary(getResources()
.getStringArray(R.array.su_notification)[magiskManager.suNotificationType]);
.getStringArray(R.array.su_notification)[mm.suNotificationType]);
requestTimeout.setSummary(
getString(R.string.request_timeout_summary, prefs.getString("su_request_timeout", "10")));
multiuserMode.setSummary(getResources()
.getStringArray(R.array.multiuser_summary)[magiskManager.multiuserMode]);
.getStringArray(R.array.multiuser_summary)[mm.multiuserMode]);
namespaceMode.setSummary(getResources()
.getStringArray(R.array.namespace_summary)[magiskManager.suNamespaceMode]);
.getStringArray(R.array.namespace_summary)[mm.suNamespaceMode]);
}
@Override
public void onTopicPublished(Topic topic) {
setLocalePreference((ListPreference) findPreference("locale"));
}
@Override
public Topic[] getSubscription() {
return new Topic[] { mm.localeDone };
}
}

View File

@@ -1,51 +1,17 @@
package com.topjohnwu.magisk;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import com.topjohnwu.magisk.asyncs.LoadApps;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Utils;
public class SplashActivity extends Activity{
private static final int UPDATE_SERVICE_ID = 1;
public class SplashActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Init the info and configs and root sh
getApplicationContext().init();
// Now fire all async tasks
new LoadModules(this)
.setCallBack(() -> new LoadRepos(this).exec())
.exec();
new LoadApps(this).exec();
if (Utils.checkNetworkStatus(this)) {
// Initialize the update check service, notify every 8 hours
if (!TextUtils.equals("install", getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
}
}
getMagiskManager().startup();
Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);

View File

@@ -13,9 +13,6 @@ import android.widget.TextView;
import com.topjohnwu.magisk.adapters.SuLogAdapter;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -27,7 +24,8 @@ public class SuLogFragment extends Fragment {
@BindView(R.id.recyclerView) RecyclerView recyclerView;
private Unbinder unbinder;
private MagiskManager magiskManager;
private MagiskManager mm;
private SuLogAdapter adapter;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -47,7 +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);
magiskManager = getApplication();
mm = getApplication();
adapter = new SuLogAdapter(mm.suDB);
recyclerView.setAdapter(adapter);
updateList();
@@ -55,13 +55,12 @@ public class SuLogFragment extends Fragment {
}
private void updateList() {
List<SuLogEntry> logs = magiskManager.suDB.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);
}
@@ -74,7 +73,7 @@ public class SuLogFragment extends Fragment {
updateList();
return true;
case R.id.menu_clear:
magiskManager.suDB.clearLogs();
mm.suDB.clearLogs();
updateList();
return true;
default:

View File

@@ -32,15 +32,15 @@ public class SuperuserFragment extends Fragment {
unbinder = ButterKnife.bind(this, view);
PackageManager pm = getActivity().getPackageManager();
MagiskManager magiskManager = getApplication();
MagiskManager mm = getApplication();
List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
List<Policy> policyList = mm.suDB.getPolicyList(pm);
if (policyList.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
recyclerView.setAdapter(new PolicyAdapter(policyList, mm.suDB, pm));
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
@@ -14,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;
@@ -41,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
@@ -67,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
@@ -87,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((Activity) holder.itemView.getContext()).add(info.packageName);
Utils.addMagiskHide(shell, info.packageName);
mHideList.add(info.packageName);
} else {
new MagiskHide((Activity) holder.itemView.getContext()).rm(info.packageName);
Utils.rmMagiskHide(shell, info.packageName);
mHideList.remove(info.packageName);
}
});
@@ -106,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;
@@ -123,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

@@ -1,5 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
@@ -12,7 +13,7 @@ import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.ExpandableViewHolder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.superuser.Policy;
@@ -50,7 +51,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
holder.setExpanded(expandList.contains(policy));
holder.itemView.setOnClickListener(view -> {
if (holder.mExpanded) {
if (holder.isExpanded()) {
holder.collapse();
expandList.remove(policy);
} else {
@@ -92,7 +93,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
dbHelper.updatePolicy(policy);
}
});
holder.delete.setOnClickListener(v -> new AlertDialogBuilder(v.getContext())
holder.delete.setOnClickListener(v -> new AlertDialogBuilder((Activity) v.getContext())
.setTitle(R.string.su_revoke_title)
.setMessage(v.getContext().getString(R.string.su_revoke_msg, policy.appName))
.setPositiveButton(R.string.yes, (dialog, which) -> {
@@ -119,7 +120,7 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
return policyList.size();
}
static class ViewHolder extends ExpandableViewHolder {
static class ViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.package_name) TextView packageName;
@@ -127,18 +128,23 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
@BindView(R.id.master_switch) Switch masterSwitch;
@BindView(R.id.notification_switch) Switch notificationSwitch;
@BindView(R.id.logging_switch) Switch loggingSwitch;
@BindView(R.id.expand_layout) ViewGroup expandLayout;
@BindView(R.id.delete) ImageView delete;
@BindView(R.id.more_info) ImageView moreInfo;
private Container container = new Container();
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
container.expandLayout = expandLayout;
setupExpandable();
}
@Override
public void setExpandLayout(View itemView) {
expandLayout = itemView.findViewById(R.id.expand_layout);
public Container getContainer() {
return container;
}
}
}

View File

@@ -2,9 +2,10 @@ package com.topjohnwu.magisk.adapters;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.database.Cursor;
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;
@@ -13,176 +14,153 @@ 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 com.topjohnwu.magisk.utils.ValueSortedMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
public class ReposAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public class ReposAdapter extends SectionedAdapter<ReposAdapter.SectionHolder, ReposAdapter.RepoHolder> {
private static final int SECTION_TYPE = 0;
private static final int REPO_TYPE = 1;
private static final int UPDATES = 0;
private static final int INSTALLED = 1;
private static final int OTHERS = 2;
private List<Repo> mUpdateRepos, mInstalledRepos, mOthersRepos;
private int[] sectionList;
private int size;
private ValueSortedMap<String, Repo> repoMap;
private Cursor repoCursor = null;
private Map<String, Module> moduleMap;
private RepoDatabaseHelper repoDB;
private List<Pair<Integer, List<Repo>>> repoPairs;
public ReposAdapter(ValueSortedMap<String, Repo> map) {
repoMap = map;
mUpdateRepos = new ArrayList<>();
mInstalledRepos = new ArrayList<>();
mOthersRepos = new ArrayList<>();
sectionList = new int[3];
size = 0;
public ReposAdapter(RepoDatabaseHelper db, Map<String, Module> map) {
repoDB = db;
moduleMap = map;
repoPairs = new ArrayList<>();
}
@Override
public int getSectionCount() {
return repoPairs.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
View v;
RecyclerView.ViewHolder holder = null;
switch (viewType) {
case SECTION_TYPE:
v = LayoutInflater.from(context).inflate(R.layout.section, parent, false);
holder = new SectionHolder(v);
public int getItemCount(int section) {
return repoPairs.get(section).second.size();
}
@Override
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 REPO_TYPE:
v = LayoutInflater.from(context).inflate(R.layout.list_item_repo, parent, false);
holder = new RepoHolder(v);
case INSTALLED:
holder.sectionText.setText(R.string.installed);
break;
case OTHERS:
holder.sectionText.setText(R.string.not_installed);
break;
}
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
public void onBindItemViewHolder(RepoHolder holder, int section, int position) {
Repo repo = repoPairs.get(section).second.get(position);
Context context = holder.itemView.getContext();
switch (getItemViewType(position)) {
case SECTION_TYPE:
SectionHolder section = (SectionHolder) holder;
if (position == sectionList[0]) {
section.sectionText.setText(context.getString(R.string.update_available));
} else if (position == sectionList[1]) {
section.sectionText.setText(context.getString(R.string.installed));
} else {
section.sectionText.setText(context.getString(R.string.not_installed));
}
break;
case REPO_TYPE:
RepoHolder repoHolder = (RepoHolder) holder;
Repo repo = getRepo(position);
repoHolder.title.setText(repo.getName());
repoHolder.versionName.setText(repo.getVersion());
String author = repo.getAuthor();
repoHolder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
repoHolder.description.setText(repo.getDescription());
repoHolder.infoLayout.setOnClickListener(v -> new MarkDownWindow(null, repo.getDetailUrl(), context));
holder.title.setText(repo.getName());
holder.versionName.setText(repo.getVersion());
String author = repo.getAuthor();
holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
holder.description.setText(repo.getDescription());
repoHolder.downloadImage.setOnClickListener(v -> {
String filename = repo.getName() + "-" + repo.getVersion() + ".zip";
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(
context,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
new ProcessRepoZip((Activity) context, uri, true).exec();
}
},
repo.getZipUrl(),
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.download, (d, i) -> Utils.dlAndReceive(
context,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
new ProcessRepoZip((Activity) context, uri, false).exec();
}
},
repo.getZipUrl(),
Utils.getLegalFilename(filename)))
.setNegativeButton(R.string.no_thanks, null)
.show();
});
break;
}
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((Activity) 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) ->
new ProcessRepoZip((Activity) context, repo.getZipUrl(),
Utils.getLegalFilename(filename), true).exec()
)
.setNeutralButton(R.string.download, (d, i) ->
new ProcessRepoZip((Activity) context, repo.getZipUrl(),
Utils.getLegalFilename(filename), false).exec())
.setNegativeButton(R.string.no_thanks, null)
.show();
});
}
@Override
public int getItemViewType(int position) {
for (int i : sectionList) {
if (position == i)
return SECTION_TYPE;
}
return REPO_TYPE;
public void notifyDBChanged() {
if (repoCursor != null)
repoCursor.close();
repoCursor = repoDB.getRepoCursor();
filter("");
}
@Override
public int getItemCount() {
return size;
}
public void filter(String s) {
List<Repo> updates = new ArrayList<>();
List<Repo> installed = new ArrayList<>();
List<Repo> others = new ArrayList<>();
public void filter(ValueSortedMap<String, Module> moduleMap, String s) {
mUpdateRepos.clear();
mInstalledRepos.clear();
mOthersRepos.clear();
sectionList[0] = sectionList[1] = sectionList[2] = 0;
for (Repo repo : repoMap.values()) {
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 filter
// Passed the repoFilter
Module module = moduleMap.get(repo.getId());
if (module != null) {
if (repo.getVersionCode() > module.getVersionCode()) {
// Updates
mUpdateRepos.add(repo);
updates.add(repo);
} else {
mInstalledRepos.add(repo);
installed.add(repo);
}
} else {
mOthersRepos.add(repo);
others.add(repo);
}
}
}
repoCursor.moveToFirst();
sectionList[0] = mUpdateRepos.isEmpty() ? -1 : 0;
size = mUpdateRepos.isEmpty() ? 0 : mUpdateRepos.size() + 1;
sectionList[1] = mInstalledRepos.isEmpty() ? -1 : size;
size += mInstalledRepos.isEmpty() ? 0 : mInstalledRepos.size() + 1;
sectionList[2] = mOthersRepos.isEmpty() ? -1 : size;
size += mOthersRepos.isEmpty() ? 0 : mOthersRepos.size() + 1;
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();
}
private Repo getRepo(int position) {
if (!mUpdateRepos.isEmpty()) position -= 1;
if (position < mUpdateRepos.size()) return mUpdateRepos.get(position);
position -= mUpdateRepos.size();
if (!mInstalledRepos.isEmpty()) position -= 1;
if (position < mInstalledRepos.size()) return mInstalledRepos.get(position);
position -= mInstalledRepos.size();
if (!mOthersRepos.isEmpty()) position -= 1;
return mOthersRepos.get(position);
}
static class SectionHolder extends RecyclerView.ViewHolder {
@BindView(R.id.section_text) TextView sectionText;

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,6 +1,6 @@
package com.topjohnwu.magisk.adapters;
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@@ -10,147 +10,125 @@ import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;
import com.thoughtbot.expandablerecyclerview.ExpandableRecyclerViewAdapter;
import com.thoughtbot.expandablerecyclerview.models.ExpandableGroup;
import com.thoughtbot.expandablerecyclerview.viewholders.ChildViewHolder;
import com.thoughtbot.expandablerecyclerview.viewholders.GroupViewHolder;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.components.ExpandableViewHolder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.superuser.SuLogEntry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SuLogAdapter {
public class SuLogAdapter extends SectionedAdapter<SuLogAdapter.SectionHolder, SuLogAdapter.LogViewHolder> {
private ExpandableAdapter adapter;
private Set<SuLogEntry> expandList = new HashSet<>();
private List<List<Integer>> logEntryList;
private Set<Integer> itemExpanded, sectionExpanded;
private SuDatabaseHelper suDB;
private Cursor suLogCursor = null;
public SuLogAdapter(List<SuLogEntry> list) {
public SuLogAdapter(SuDatabaseHelper db) {
suDB = db;
logEntryList = Collections.emptyList();
sectionExpanded = new HashSet<>();
itemExpanded = new HashSet<>();
}
// Separate the logs with date
Map<String, List<SuLogEntry>> logEntryMap = new LinkedHashMap<>();
List<SuLogEntry> group;
for (SuLogEntry log : list) {
String date = log.getDateString();
group = logEntryMap.get(date);
if (group == null) {
group = new ArrayList<>();
logEntryMap.put(date, group);
@Override
public int getSectionCount() {
return logEntryList.size();
}
@Override
public int getItemCount(int section) {
return sectionExpanded.contains(section) ? logEntryList.get(section).size() : 0;
}
@Override
public SectionHolder onCreateSectionViewHolder(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sulog_group, parent, false);
return new SectionHolder(v);
}
@Override
public LogViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sulog, parent, false);
return new LogViewHolder(v);
}
@Override
public void onBindSectionViewHolder(SectionHolder holder, int section) {
suLogCursor.moveToPosition(logEntryList.get(section).get(0));
SuLogEntry entry = new SuLogEntry(suLogCursor);
holder.arrow.setRotation(sectionExpanded.contains(section) ? 180 : 0);
holder.itemView.setOnClickListener(v -> {
RotateAnimation rotate;
if (sectionExpanded.contains(section)) {
holder.arrow.setRotation(0);
rotate = new RotateAnimation(180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sectionExpanded.remove(section);
notifyItemRangeRemoved(getItemPosition(section, 0), logEntryList.get(section).size());
} else {
rotate = new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sectionExpanded.add(section);
notifyItemRangeInserted(getItemPosition(section, 0), logEntryList.get(section).size());
}
group.add(log);
}
// Then format them into expandable groups
List<LogGroup> logEntryGroups = new ArrayList<>();
for (Map.Entry<String, List<SuLogEntry>> entry : logEntryMap.entrySet()) {
logEntryGroups.add(new LogGroup(entry.getKey(), entry.getValue()));
}
adapter = new ExpandableAdapter(logEntryGroups);
rotate.setDuration(300);
rotate.setFillAfter(true);
holder.arrow.setAnimation(rotate);
});
holder.date.setText(entry.getDateString());
}
public RecyclerView.Adapter getAdapter() {
return adapter;
}
private class ExpandableAdapter
extends ExpandableRecyclerViewAdapter<LogGroupViewHolder, LogViewHolder> {
ExpandableAdapter(List<? extends ExpandableGroup> groups) {
super(groups);
expandableList.expandedGroupIndexes[0] = true;
}
@Override
public LogGroupViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sulog_group, parent, false);
return new LogGroupViewHolder(v);
}
@Override
public LogViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_sulog, parent, false);
return new LogViewHolder(v);
}
@Override
public void onBindChildViewHolder(LogViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
Context context = holder.itemView.getContext();
SuLogEntry logEntry = (SuLogEntry) group.getItems().get(childIndex);
holder.setExpanded(expandList.contains(logEntry));
holder.itemView.setOnClickListener(view -> {
if (holder.getExpanded()) {
holder.collapse();
expandList.remove(logEntry);
} else {
holder.expand();
expandList.add(logEntry);
}
});
holder.appName.setText(logEntry.appName);
holder.action.setText(context.getString(logEntry.action ? R.string.grant : R.string.deny));
holder.command.setText(logEntry.command);
holder.fromPid.setText(String.valueOf(logEntry.fromPid));
holder.toUid.setText(String.valueOf(logEntry.toUid));
holder.time.setText(logEntry.getTimeString());
}
@Override
public void onBindGroupViewHolder(LogGroupViewHolder holder, int flatPosition, ExpandableGroup group) {
holder.date.setText(group.getTitle());
if (isGroupExpanded(flatPosition)) {
@Override
public void onBindItemViewHolder(LogViewHolder holder, int section, int position) {
int sqlPosition = logEntryList.get(section).get(position);
suLogCursor.moveToPosition(sqlPosition);
SuLogEntry entry = new SuLogEntry(suLogCursor);
holder.setExpanded(itemExpanded.contains(sqlPosition));
holder.itemView.setOnClickListener(view -> {
if (holder.isExpanded()) {
holder.collapse();
itemExpanded.remove(sqlPosition);
} else {
holder.expand();
itemExpanded.add(sqlPosition);
}
}
});
holder.appName.setText(entry.appName);
holder.action.setText(entry.action ? R.string.grant : R.string.deny);
holder.command.setText(entry.command);
holder.fromPid.setText(String.valueOf(entry.fromPid));
holder.toUid.setText(String.valueOf(entry.toUid));
holder.time.setText(entry.getTimeString());
}
private class LogGroup extends ExpandableGroup<SuLogEntry> {
LogGroup(String title, List<SuLogEntry> items) {
super(title, items);
}
public void notifyDBChanged() {
if (suLogCursor != null)
suLogCursor.close();
suLogCursor = suDB.getLogCursor();
logEntryList = suDB.getLogStructure();
itemExpanded.clear();
sectionExpanded.clear();
sectionExpanded.add(0);
notifyDataSetChanged();
}
static class LogGroupViewHolder extends GroupViewHolder {
static class SectionHolder extends RecyclerView.ViewHolder {
@BindView(R.id.date) TextView date;
@BindView(R.id.arrow) ImageView arrow;
public LogGroupViewHolder(View itemView) {
SectionHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
@Override
public void expand() {
RotateAnimation rotate =
new RotateAnimation(360, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(300);
rotate.setFillAfter(true);
arrow.setAnimation(rotate);
}
@Override
public void collapse() {
RotateAnimation rotate =
new RotateAnimation(180, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(300);
rotate.setFillAfter(true);
arrow.setAnimation(rotate);
}
}
// Wrapper class
static class LogViewHolder extends ChildViewHolder {
private InternalViewHolder expandableViewHolder;
static class LogViewHolder extends RecyclerView.ViewHolder implements ExpandableView {
@BindView(R.id.app_name) TextView appName;
@BindView(R.id.action) TextView action;
@@ -158,40 +136,20 @@ public class SuLogAdapter {
@BindView(R.id.fromPid) TextView fromPid;
@BindView(R.id.toUid) TextView toUid;
@BindView(R.id.command) TextView command;
@BindView(R.id.expand_layout) ViewGroup expandLayout;
private Container container = new Container();
LogViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
expandableViewHolder = new InternalViewHolder(itemView);
container.expandLayout = expandLayout;
setupExpandable();
}
private class InternalViewHolder extends ExpandableViewHolder {
InternalViewHolder(View itemView) {
super(itemView);
}
@Override
public void setExpandLayout(View itemView) {
expandLayout = itemView.findViewById(R.id.expand_layout);
}
}
private boolean getExpanded() {
return expandableViewHolder.mExpanded;
}
private void setExpanded(boolean expanded) {
expandableViewHolder.setExpanded(expanded);
}
private void expand() {
expandableViewHolder.expand();
}
private void collapse() {
expandableViewHolder.collapse();
@Override
public Container getContainer() {
return container;
}
}
}

View File

@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import com.topjohnwu.magisk.BuildConfig;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
@@ -11,47 +12,65 @@ import org.json.JSONObject;
public class CheckUpdates extends ParallelTask<Void, Void, Void> {
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/magisk_update.json";
public static final int STABLE_CHANNEL = 0;
public static final int BETA_CHANNEL = 1;
private static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/stable.json";
private static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/beta.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 mm = getMagiskManager();
if (mm == null) return null;
String jsonStr;
switch (mm.updateChannel) {
case STABLE_CHANNEL:
jsonStr = WebService.getString(STABLE_URL);
break;
case BETA_CHANNEL:
jsonStr = WebService.getString(BETA_URL);
break;
default:
jsonStr = null;
}
try {
JSONObject json = new JSONObject(jsonStr);
JSONObject magisk = json.getJSONObject("magisk");
magiskManager.remoteMagiskVersionString = magisk.getString("version");
magiskManager.remoteMagiskVersionCode = magisk.getInt("versionCode");
magiskManager.magiskLink = magisk.getString("link");
magiskManager.releaseNoteLink = magisk.getString("note");
mm.remoteMagiskVersionString = magisk.getString("version");
mm.remoteMagiskVersionCode = magisk.getInt("versionCode");
mm.magiskLink = magisk.getString("link");
mm.releaseNoteLink = magisk.getString("note");
JSONObject manager = json.getJSONObject("app");
magiskManager.remoteManagerVersionString = manager.getString("version");
magiskManager.remoteManagerVersionCode = manager.getInt("versionCode");
magiskManager.managerLink = manager.getString("link");
mm.remoteManagerVersionString = manager.getString("version");
mm.remoteManagerVersionCode = manager.getInt("versionCode");
mm.managerLink = manager.getString("link");
} catch (JSONException ignored) {}
return null;
}
@Override
protected void onPostExecute(Void v) {
if (showNotification && magiskManager.updateNotification) {
if (BuildConfig.VERSION_CODE < magiskManager.remoteManagerVersionCode) {
Utils.showManagerUpdate(magiskManager);
} else if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode) {
Utils.showMagiskUpdate(magiskManager);
MagiskManager mm = getMagiskManager();
if (mm == null) return;
if (showNotification && mm.updateNotification) {
if (BuildConfig.VERSION_CODE < mm.remoteManagerVersionCode) {
Utils.showManagerUpdateNotification(mm);
} else if (mm.magiskVersionCode < mm.remoteMagiskVersionCode) {
Utils.showMagiskUpdateNotification(mm);
}
}
magiskManager.updateCheckDone.trigger();
mm.updateCheckDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -0,0 +1,65 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.os.Build;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class DownloadBusybox extends ParallelTask<Void, Void, Void> {
private static final String BUSYBOX_ARM = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-arm";
private static final String BUSYBOX_X86 = "https://github.com/topjohnwu/ndk-busybox/releases/download/1.27.2/busybox-x86";
private File busybox;
public DownloadBusybox(Context context) {
super(context);
busybox = new File(context.getCacheDir(), "busybox");
}
@Override
protected Void doInBackground(Void... voids) {
Context context = getMagiskManager();
Utils.removeItem(getShell(), context.getApplicationInfo().dataDir + "/busybox");
try {
FileOutputStream out = new FileOutputStream(busybox);
InputStream in = WebService.request(WebService.GET,
Build.SUPPORTED_32_BIT_ABIS[0].contains("x86") ?
BUSYBOX_X86 :
BUSYBOX_ARM,
null
);
if (in == null) throw new IOException();
BufferedInputStream bis = new BufferedInputStream(in);
byte[] buffer = new byte[4096];
int len;
while ((len = bis.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
if (busybox.exists()) {
getShell().su(
"rm -rf " + MagiskManager.BUSYBOXPATH,
"mkdir -p " + MagiskManager.BUSYBOXPATH,
"cp " + busybox + " " + MagiskManager.BUSYBOXPATH,
"chmod -R 755 " + MagiskManager.BUSYBOXPATH,
MagiskManager.BUSYBOXPATH + "/busybox --install -s " + MagiskManager.BUSYBOXPATH
);
busybox.delete();
}
return null;
}
}

View File

@@ -10,6 +10,8 @@ import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -18,52 +20,22 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class FlashZip extends ParallelTask<Void, String, Integer> {
public class FlashZip extends ParallelTask<Void, Void, Integer> {
private Uri mUri;
private File mCachedFile, mScriptFile, mCheckFile;
private String mFilename;
private File mCachedFile;
private AdaptiveList<String> mList;
public FlashZip(Activity context, Uri uri, AdaptiveList<String> list) {
super(context);
mUri = uri;
mList = list;
mCachedFile = new File(magiskManager.getCacheDir(), "install.zip");
mScriptFile = new File(magiskManager.getCacheDir(), "/META-INF/com/google/android/update-binary");
mCheckFile = new File(mScriptFile.getParent(), "updater-script");
// Try to get the filename ourselves
mFilename = Utils.getNameFromUri(magiskManager, mUri);
}
private void copyToCache() throws Exception {
mList.add(magiskManager.getString(R.string.copying_msg));
mCachedFile.delete();
try (
InputStream in = magiskManager.getContentResolver().openInputStream(mUri);
OutputStream outputStream = new FileOutputStream(mCachedFile)
) {
byte buffer[] = new byte[1024];
int length;
if (in == null) throw new FileNotFoundException();
while ((length = in.read(buffer)) > 0)
outputStream.write(buffer, 0, length);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Cannot copy to cache");
throw e;
}
mCachedFile = new File(context.getCacheDir(), "install.zip");
}
private boolean unzipAndCheck() throws Exception {
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
List<String> ret = Utils.readFile(magiskManager.shell, mCheckFile.getPath());
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true);
List<String> ret = Utils.readFile(getShell(), new File(mCachedFile.getParentFile(), "updater-script").getPath());
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
}
@@ -74,18 +46,40 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
}
@Override
protected void onProgressUpdate(String... values) {
protected void onProgressUpdate(Void... values) {
mList.updateView();
}
@Override
protected Integer doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return -1;
try {
copyToCache();
mList.add("- Copying zip to temp directory");
mCachedFile.delete();
try (
InputStream in = mm.getContentResolver().openInputStream(mUri);
OutputStream out = new BufferedOutputStream(new FileOutputStream(mCachedFile))
) {
if (in == null) throw new FileNotFoundException();
InputStream buf= new BufferedInputStream(in);
byte buffer[] = new byte[4096];
int length;
while ((length = buf.read(buffer)) > 0)
out.write(buffer, 0, length);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Cannot copy to cache");
throw e;
}
if (!unzipAndCheck()) return 0;
mList.add(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
magiskManager.shell.su(mList,
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile +
mList.add("- Installing " + Utils.getNameFromUri(mm, mUri));
getShell().su(mList,
"cd " + mCachedFile.getParent(),
"BOOTMODE=true sh update-binary dummy 1 " + mCachedFile +
" && echo 'Success!' || echo 'Failed!'"
);
if (TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
@@ -99,26 +93,25 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
// -1 = error, manual install; 0 = invalid zip; 1 = success
@Override
protected void onPostExecute(Integer result) {
magiskManager.shell.su_raw(
"rm -rf " + mCachedFile.getParent() + "/*",
MagiskManager mm = getMagiskManager();
if (mm == null) return;
getShell().su_raw(
"rm -rf " + mCachedFile.getParent(),
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
);
switch (result) {
case -1:
mList.add(magiskManager.getString(R.string.install_error));
Utils.showUriSnack(activity, mUri);
mList.add(mm.getString(R.string.install_error));
Utils.showUriSnack(getActivity(), mUri);
break;
case 0:
mList.add(magiskManager.getString(R.string.invalid_zip));
mList.add(mm.getString(R.string.invalid_zip));
break;
case 1:
onSuccess();
// Success
new LoadModules(mm).exec();
break;
}
super.onPostExecute(result);
}
protected void onSuccess() {
new LoadModules(activity).exec();
}
}

View File

@@ -0,0 +1,74 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.superuser.Policy;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.File;
import java.util.List;
public class HideManager extends ParallelTask<Void, Void, Boolean> {
public HideManager(Context context) {
super(context);
}
@Override
protected void onPreExecute() {
getMagiskManager().toast(R.string.hide_manager_toast, Toast.LENGTH_SHORT);
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return false;
// Generate a new unhide app with random package name
File unhideAPK = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", "unhide.apk");
unhideAPK.getParentFile().mkdirs();
String pkg = ZipUtils.generateUnhide(mm, unhideAPK);
// Install the application
List<String> ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
unhideAPK.delete();
if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0)))
return false;
try {
// Allow the application to gain root by default
PackageManager pm = mm.getPackageManager();
int uid = pm.getApplicationInfo(pkg, 0).uid;
Policy policy = new Policy(uid, pm);
policy.policy = Policy.ALLOW;
policy.notification = false;
policy.logging = false;
mm.suDB.addPolicy(policy);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
// Hide myself!
getShell().su_raw("pm hide " + mm.getPackageName());
return true;
}
@Override
protected void onPostExecute(Boolean b) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return;
if (!b) {
mm.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
}
super.onPostExecute(b);
}
}

View File

@@ -0,0 +1,230 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.AdaptiveList;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.TarEntry;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import org.kamranzafar.jtar.TarInputStream;
import org.kamranzafar.jtar.TarOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
private static final int PATCH_MODE = 0;
private static final int DIRECT_MODE = 1;
private Uri mBootImg, mZip;
private AdaptiveList<String> mList;
private String mBootLocation;
private boolean mKeepEnc, mKeepVerity;
private int mode;
private InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity) {
super(context);
mList = list;
mZip = zip;
mKeepEnc = enc;
mKeepVerity = verity;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, Uri boot) {
this(context, list, zip, enc, verity);
mBootImg = boot;
mode = PATCH_MODE;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, String boot) {
this(context, list, zip, enc, verity);
mBootLocation = boot;
mode = DIRECT_MODE;
}
@Override
protected void onPreExecute() {
// UI updates must run in the UI thread
mList.setCallback(this::publishProgress);
}
@Override
protected void onProgressUpdate(Void... values) {
mList.updateView();
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return false;
File install = new File(Utils.getEncContext(mm).getFilesDir().getParent(), "install");
getShell().sh_raw("rm -rf " + install);
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
String arch;
if (abis.contains("x86_64")) arch = "x64";
else if (abis.contains("arm64-v8a")) arch = "arm64";
else if (abis.contains("x86")) arch = "x86";
else arch = "arm";
mList.add("- Device platform: " + arch);
try {
// Unzip files
mList.add("- Extracting files");
try (InputStream in = mm.getContentResolver().openInputStream(mZip)) {
if (in == null) throw new FileNotFoundException();
BufferedInputStream buf = new BufferedInputStream(in);
buf.mark(Integer.MAX_VALUE);
ZipUtils.unzip(buf, install, arch + "/", true);
buf.reset();
ZipUtils.unzip(buf, install, "common/", true);
buf.reset();
ZipUtils.unzip(buf, install, "chromeos/", false);
buf.reset();
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (Exception e) {
mList.add("! Cannot unzip zip");
throw e;
}
File boot;
switch (mode) {
case PATCH_MODE:
boot = new File(install, "boot.img");
// Copy boot image to local
try (
InputStream in = mm.getContentResolver().openInputStream(mBootImg);
OutputStream out = new FileOutputStream(boot)
) {
InputStream source;
if (in == null) throw new FileNotFoundException();
if (Utils.getNameFromUri(mm, mBootImg).endsWith(".tar")) {
// Extract boot.img from tar
TarInputStream tar = new TarInputStream(new BufferedInputStream(in));
org.kamranzafar.jtar.TarEntry entry;
while ((entry = tar.getNextEntry()) != null) {
if (entry.getName().equals("boot.img"))
break;
}
source = tar;
} else {
// Direct copy raw image
source = new BufferedInputStream(in);
}
byte buffer[] = new byte[1024];
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Copy failed");
throw e;
}
break;
case DIRECT_MODE:
boot = new File(mBootLocation);
break;
default:
return false;
}
mList.add("- Use boot image: " + boot);
Shell shell;
if (mode == PATCH_MODE && Shell.rootAccess()) {
// Force non-root shell
shell = Shell.getShell("sh");
} else {
shell = getShell();
}
// Patch boot image
shell.sh(mList,
"cd " + install,
"KEEPFORCEENCRYPT=" + mKeepEnc + " KEEPVERITY=" + mKeepVerity + " sh " +
"update-binary indep boot_patch.sh " + boot +
" && echo 'Success!' || echo 'Failed!'"
);
if (!TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
return false;
File patched_boot = new File(install, "new-boot.img");
mList.add("");
switch (mode) {
case PATCH_MODE:
File dest = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/patched_boot" + mm.bootFormat);
dest.getParentFile().mkdirs();
switch (mm.bootFormat) {
case ".img":
getShell().sh_raw("cp -f " + patched_boot + " " + dest);
break;
case ".img.tar":
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
tar.putNextEntry(new TarEntry(patched_boot, "boot.img"));
byte buffer[] = new byte[4096];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot));
int len;
while ((len = in.read(buffer)) != -1) {
tar.write(buffer, 0, len);
}
tar.flush();
tar.close();
in.close();
break;
}
mList.add("*********************************");
mList.add(" Patched Boot Image is placed in ");
mList.add(" " + dest + " ");
mList.add("*********************************");
break;
case DIRECT_MODE:
// Direct flash boot image
getShell().su(mList, "flash_boot_image " + patched_boot + " " + mBootLocation);
break;
default:
return false;
}
// Finals
getShell().sh_raw(
"cd " + install,
"mv bin/busybox busybox",
"rm -rf bin *.img update-binary",
"cd /");
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
}
}

View File

@@ -1,39 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class LoadApps extends ParallelTask<Void, Void, Void> {
public LoadApps(Activity context) {
super(context);
}
@Override
protected Void doInBackground(Void... voids) {
PackageManager pm = magiskManager.getPackageManager();
List<ApplicationInfo> list = pm.getInstalledApplications(0);
for (Iterator<ApplicationInfo> i = list.iterator(); i.hasNext(); ) {
ApplicationInfo info = i.next();
if (ApplicationAdapter.BLACKLIST.contains(info.packageName) || !info.enabled) {
i.remove();
}
}
Collections.sort(list, (a, b) -> a.loadLabel(pm).toString().toLowerCase()
.compareTo(b.loadLabel(pm).toString().toLowerCase()));
magiskManager.appList = Collections.unmodifiableList(list);
return null;
}
@Override
protected void onPostExecute(Void v) {
new MagiskHide(activity).list();
}
}

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.content.Context;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.module.BaseModule;
@@ -11,21 +11,23 @@ import com.topjohnwu.magisk.utils.ValueSortedMap;
public class LoadModules extends ParallelTask<Void, Void, Void> {
public LoadModules(Activity context) {
public LoadModules(Context context) {
super(context);
}
@Override
protected Void doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return null;
Logger.dev("LoadModules: Loading modules");
magiskManager.moduleMap = new ValueSortedMap<>();
mm.moduleMap = new ValueSortedMap<>();
for (String path : Utils.getModList(magiskManager.shell, MagiskManager.MAGISK_PATH)) {
for (String path : Utils.getModList(getShell(), MagiskManager.MAGISK_PATH)) {
Logger.dev("LoadModules: Adding modules from " + path);
try {
Module module = new Module(magiskManager.shell, path);
magiskManager.moduleMap.put(module.getId(), module);
Module module = new Module(getShell(), path);
mm.moduleMap.put(module.getId(), module);
} catch (BaseModule.CacheModException ignored) {}
}
@@ -35,7 +37,9 @@ public class LoadModules extends ParallelTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void v) {
magiskManager.moduleLoadDone.trigger();
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.moduleLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -1,55 +0,0 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import java.util.List;
public class MagiskHide extends ParallelTask<Object, Void, Void> {
private boolean isList = false;
public MagiskHide(Activity context) {
super(context);
}
@Override
protected Void doInBackground(Object... params) {
String command = (String) params[0];
List<String> ret = magiskManager.shell.su("magiskhide --" + command);
if (isList) {
magiskManager.magiskHideList = ret;
}
return null;
}
@Override
protected void onPostExecute(Void v) {
if (isList) {
magiskManager.magiskHideDone.trigger();
}
super.onPostExecute(v);
}
public void add(CharSequence packageName) {
exec("add " + packageName);
}
public void rm(CharSequence packageName) {
exec("rm " + packageName);
}
public void enable() {
exec("enable");
}
public void disable() {
exec("disable");
}
public void list() {
isList = true;
if (magiskManager == null) return;
exec("ls");
}
}

View File

@@ -0,0 +1,47 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.webkit.WebView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.WebService;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
public class MarkDownWindow extends ParallelTask<Void, Void, String> {
private String mTitle, mUrl;
public MarkDownWindow(Activity context, String title, String url) {
super(context);
mTitle = title;
mUrl = url;
}
@Override
protected String doInBackground(Void... voids) {
String md = WebService.getString(mUrl);
Parser parser = Parser.builder().build();
HtmlRenderer renderer = HtmlRenderer.builder().build();
Node doc = parser.parse(md);
return String.format(
"<link rel='stylesheet' type='text/css' href='file:///android_asset/%s.css'/> %s",
getMagiskManager().isDarkTheme ? "dark" : "light", renderer.render(doc));
}
@Override
protected void onPostExecute(String html) {
AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
alert.setTitle(mTitle);
WebView wv = new WebView(getActivity());
wv.loadDataWithBaseURL("fake://", html, "text/html", "UTF-8", null);
alert.setView(wv);
alert.setNegativeButton(R.string.close, (dialog, id) -> dialog.dismiss());
alert.show();
}
}

View File

@@ -1,28 +1,50 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.lang.ref.WeakReference;
public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
protected Activity activity;
protected MagiskManager magiskManager;
private WeakReference<Activity> weakActivity;
private WeakReference<MagiskManager> weakMagiskManager;
private Runnable callback = null;
public ParallelTask() {}
public ParallelTask(Context context) {
weakMagiskManager = new WeakReference<>(Utils.getMagiskManager(context));
}
public ParallelTask(Activity context) {
activity = context;
magiskManager = Utils.getMagiskManager(context);
this((Context) context);
weakActivity = new WeakReference<>(context);
}
protected Activity getActivity() {
return weakActivity.get();
}
protected MagiskManager getMagiskManager() {
return weakMagiskManager.get();
}
protected Shell getShell() {
MagiskManager magiskManager = getMagiskManager();
return magiskManager == null ? null : Shell.getShell(magiskManager);
}
@SuppressWarnings("unchecked")
public void exec(Params... params) {
public ParallelTask<Params, Progress, Result> exec(Params... params) {
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
return this;
}
@Override

View File

@@ -1,9 +1,11 @@
package com.topjohnwu.magisk.asyncs;
import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
@@ -11,45 +13,66 @@ import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
private Uri mUri;
private ProgressDialog progressDialog;
private boolean mInstall;
private String mLink;
private File mFile;
public ProcessRepoZip(Activity context, Uri uri, boolean install) {
public ProcessRepoZip(Activity context, String link, String filename, boolean install) {
super(context);
mUri = uri;
mLink = link;
mFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", filename);
mFile.getParentFile().mkdirs();
mInstall = install;
}
@Override
protected void onPreExecute() {
Activity activity = getActivity();
progressDialog = ProgressDialog.show(activity,
activity.getString(R.string.zip_process_title),
activity.getString(R.string.zip_process_msg));
activity.getString(R.string.zip_download_title),
activity.getString(R.string.zip_download_msg));
}
@Override
protected void onProgressUpdate(Void... values) {
progressDialog.setTitle(R.string.zip_process_title);
progressDialog.setMessage(getActivity().getString(R.string.zip_process_msg));
}
@Override
protected Boolean doInBackground(Void... params) {
Activity activity = getActivity();
if (activity == null) return null;
try {
// Create temp file
File temp1 = new File(magiskManager.getCacheDir(), "1.zip");
File temp2 = new File(magiskManager.getCacheDir(), "2.zip");
magiskManager.getCacheDir().mkdirs();
temp1.createNewFile();
temp2.createNewFile();
// Request zip from Internet
InputStream in = WebService.request(WebService.GET, mLink, null);
if (in == null) return false;
in = new BufferedInputStream(in);
// First remove top folder in Github source zip, Uri -> temp1
ZipUtils.removeTopFolder(activity.getContentResolver().openInputStream(mUri), temp1);
// Temp files
File temp1 = new File(activity.getCacheDir(), "1.zip");
File temp2 = new File(temp1.getParentFile(), "2.zip");
temp1.getParentFile().mkdir();
// First remove top folder in Github source zip, Web -> temp1
ZipUtils.removeTopFolder(in, temp1);
publishProgress();
// Then sign the zip for the first time, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, false);
@@ -60,17 +83,17 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
// Finally, sign the whole zip file again, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, true);
// Write it back to the downloaded zip, temp2 -> Uri
FileInputStream in = new FileInputStream(temp2);
try (OutputStream target = activity.getContentResolver().openOutputStream(mUri)) {
// Write it to the target zip, temp2 -> file
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(mFile));
InputStream source = new BufferedInputStream(new FileInputStream(temp2))
) {
byte[] buffer = new byte[4096];
int length;
if (target == null) throw new FileNotFoundException();
while ((length = in.read(buffer)) > 0)
target.write(buffer, 0, length);
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
}
// Delete the temp file
// Delete temp files
temp1.delete();
temp2.delete();
@@ -84,15 +107,27 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
@Override
protected void onPostExecute(Boolean result) {
Activity activity = getActivity();
if (activity == null) return;
progressDialog.dismiss();
Uri uri = Uri.fromFile(mFile);
if (result) {
if (Shell.rootAccess() && mInstall) {
magiskManager.startActivity(new Intent(magiskManager, FlashActivity.class).setData(mUri));
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(uri).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
activity.startActivity(intent);
} else {
Utils.showUriSnack(activity, mUri);
Utils.showUriSnack(activity, uri);
}
} else {
magiskManager.toast(R.string.process_error, Toast.LENGTH_LONG);
Utils.getMagiskManager(activity).toast(R.string.process_error, Toast.LENGTH_LONG);
}
super.onPostExecute(result);
}
@Override
public ParallelTask<Void, Void, Boolean> exec(Void... voids) {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> super.exec(voids));
return this;
}
}

View File

@@ -0,0 +1,40 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.widget.Toast;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
public class RestoreStockBoot extends ParallelTask<Void, Void, Boolean> {
private String mBoot;
public RestoreStockBoot(Context context, String boot) {
super(context);
mBoot = boot;
}
@Override
protected Boolean doInBackground(Void... voids) {
List<String> ret = getShell().su("cat /init.magisk.rc | grep STOCKSHA1");
if (!Utils.isValidShellResponse(ret))
return false;
String stock_boot = "/data/stock_boot_" + ret.get(0).substring(ret.get(0).indexOf('=') + 1) + ".img.gz";
if (!Utils.itemExist(getShell(), stock_boot))
return false;
getShell().su_raw("flash_boot_image " + stock_boot + " " + mBoot);
return true;
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
getMagiskManager().toast(R.string.restore_done, Toast.LENGTH_SHORT);
} else {
getMagiskManager().toast(R.string.restore_fail, Toast.LENGTH_LONG);
}
}
}

View File

@@ -1,14 +1,14 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.module.BaseModule;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import com.topjohnwu.magisk.utils.WebService;
import org.json.JSONArray;
@@ -24,7 +24,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
public class LoadRepos extends ParallelTask<Void, Void, Void> {
public class UpdateRepos extends ParallelTask<Void, Void, Void> {
public static final String ETAG_KEY = "ETag";
@@ -37,15 +37,15 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
private static final int LOAD_PREV = 2;
private List<String> etags;
private ValueSortedMap<String, Repo> cached, fetched;
private List<String> cached;
private RepoDatabaseHelper repoDB;
private SharedPreferences prefs;
public LoadRepos(Activity context) {
public UpdateRepos(Context context) {
super(context);
prefs = magiskManager.prefs;
prefs = getMagiskManager().prefs;
repoDB = getMagiskManager().repoDB;
String prefsPath = context.getApplicationInfo().dataDir + "/shared_prefs";
repoDB = new RepoDatabaseHelper(magiskManager);
// Legacy data cleanup
File old = new File(prefsPath, "RepoMap.xml");
if (old.exists() || !prefs.getString("repomap", "empty").equals("empty")) {
@@ -54,7 +54,7 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
repoDB.clearRepo();
}
etags = new ArrayList<>(
Arrays.asList(magiskManager.prefs.getString(ETAG_KEY, "").split(",")));
Arrays.asList(prefs.getString(ETAG_KEY, "").split(",")));
}
private void loadJSON(String jsonString) throws Exception {
@@ -67,25 +67,27 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
String lastUpdate = jsonobject.getString("pushed_at");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
Date updatedDate = format.parse(lastUpdate);
Repo repo = cached.get(id);
Repo repo = repoDB.getRepo(id);
try {
Boolean updated;
if (repo == null) {
Logger.dev("LoadRepos: Create new repo " + id);
Logger.dev("UpdateRepos: Create new repo " + id);
repo = new Repo(name, updatedDate);
updated = true;
} else {
// Popout from cached
cached.remove(id);
repo.update(updatedDate);
updated = repo.update(updatedDate);
}
if (repo.getId() != null) {
fetched.put(id, repo);
if (updated) {
repoDB.addRepo(repo);
}
} catch (BaseModule.CacheModException ignored) {}
}
}
private boolean loadPage(int page, String url, int mode) {
Logger.dev("LoadRepos: Loading page: " + (page + 1));
Logger.dev("UpdateRepos: Loading page: " + (page + 1));
Map<String, String> header = new HashMap<>();
if (mode == CHECK_ETAG && page < etags.size() && !TextUtils.isEmpty(etags.get(page))) {
Logger.dev("ETAG: " + etags.get(page));
@@ -94,13 +96,13 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
if (url == null) {
url = String.format(Locale.US, REPO_URL, page + 1);
}
String jsonString = WebService.request(url, WebService.GET, header, true);
String jsonString = WebService.getString(url, header);
if (TextUtils.isEmpty(jsonString)) {
// At least check the pages we know
return page + 1 < etags.size() && loadPage(page + 1, null, CHECK_ETAG);
}
// The request succeed, parse the new stuffs
// The getString succeed, parse the new stuffs
try {
loadJSON(jsonString);
} catch (Exception e) {
@@ -154,18 +156,16 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
Logger.dev("LoadRepos: Loading repos");
Logger.dev("UpdateRepos: Loading repos");
cached = repoDB.getRepoMap(false);
fetched = new ValueSortedMap<>();
cached = repoDB.getRepoIDList();
if (!loadPage(0, null, CHECK_ETAG)) {
magiskManager.repoMap = repoDB.getRepoMap();
Logger.dev("LoadRepos: No updates, use DB");
Logger.dev("UpdateRepos: No updates, use DB");
return null;
}
repoDB.addRepoMap(fetched);
// The leftover cached means they are removed from online repo
repoDB.removeRepo(cached);
// Update ETag
@@ -176,14 +176,15 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
}
prefs.edit().putString(ETAG_KEY, etagBuilder.toString()).apply();
magiskManager.repoMap = repoDB.getRepoMap();
Logger.dev("LoadRepos: Done");
Logger.dev("UpdateRepos: Done");
return null;
}
@Override
protected void onPostExecute(Void v) {
magiskManager.repoLoadDone.trigger();
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.repoLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -1,18 +1,67 @@
package com.topjohnwu.magisk.components;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.WindowManager;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
public class Activity extends AppCompatActivity {
private Runnable permissionGrantCallback;
public Activity() {
super();
Configuration configuration = new Configuration();
configuration.setLocale(MagiskManager.locale);
applyOverrideConfiguration(configuration);
}
@Override
public MagiskManager getApplicationContext() {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).subscribeTopics();
}
}
@Override
protected void onDestroy() {
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).unsubscribeTopics();
}
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (permissionGrantCallback != null) {
permissionGrantCallback.run();
}
}
permissionGrantCallback = null;
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
}
public MagiskManager getMagiskManager() {
return (MagiskManager) super.getApplicationContext();
}
public Shell getShell() {
return Shell.getShell(this);
}
protected void setFloating() {
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
if (isTablet) {

View File

@@ -1,6 +1,6 @@
package com.topjohnwu.magisk.components;
import android.content.Context;
import android.app.Activity;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -37,12 +37,12 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
private AlertDialog dialog;
public AlertDialogBuilder(@NonNull Context context) {
public AlertDialogBuilder(@NonNull Activity context) {
super(context);
setup();
}
public AlertDialogBuilder(@NonNull Context context, @StyleRes int themeResId) {
public AlertDialogBuilder(@NonNull Activity context, @StyleRes int themeResId) {
super(context, themeResId);
setup();
}

View File

@@ -0,0 +1,84 @@
package com.topjohnwu.magisk.components;
import android.animation.ValueAnimator;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
public interface ExpandableView {
class Container {
public ViewGroup expandLayout;
ValueAnimator expandAnimator, collapseAnimator;
boolean mExpanded = false;
int expandHeight = 0;
}
// Provide state info
Container getContainer();
default void setupExpandable() {
Container container = getContainer();
container.expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (container.expandHeight == 0) {
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
container.expandLayout.measure(widthSpec, heightSpec);
container.expandHeight = container.expandLayout.getMeasuredHeight();
}
container.expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
container.expandLayout.setVisibility(View.GONE);
container.expandAnimator = slideAnimator(0, container.expandHeight);
container.collapseAnimator = slideAnimator(container.expandHeight, 0);
return true;
}
});
}
default boolean isExpanded() {
return getContainer().mExpanded;
}
default void setExpanded(boolean expanded) {
Container container = getContainer();
container.mExpanded = expanded;
ViewGroup.LayoutParams layoutParams = container.expandLayout.getLayoutParams();
layoutParams.height = expanded ? container.expandHeight : 0;
container.expandLayout.setLayoutParams(layoutParams);
container.expandLayout.setVisibility(expanded ? View.VISIBLE : View.GONE);
}
default void expand() {
Container container = getContainer();
if (container.mExpanded) return;
container.expandLayout.setVisibility(View.VISIBLE);
container.expandAnimator.start();
container.mExpanded = true;
}
default void collapse() {
Container container = getContainer();
if (!container.mExpanded) return;
container.collapseAnimator.start();
container.mExpanded = false;
}
default ValueAnimator slideAnimator(int start, int end) {
Container container = getContainer();
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = container.expandLayout.getLayoutParams();
layoutParams.height = value;
container.expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

View File

@@ -1,77 +0,0 @@
package com.topjohnwu.magisk.components;
import android.animation.ValueAnimator;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
public abstract class ExpandableViewHolder extends RecyclerView.ViewHolder {
protected ViewGroup expandLayout;
private ValueAnimator expandAnimator, collapseAnimator;
private static int expandHeight = 0;
public boolean mExpanded = false;
public ExpandableViewHolder(View itemView) {
super(itemView);
setExpandLayout(itemView);
expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (expandHeight == 0) {
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
expandLayout.measure(widthSpec, heightSpec);
expandHeight = expandLayout.getMeasuredHeight();
}
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
expandLayout.setVisibility(View.GONE);
expandAnimator = slideAnimator(0, expandHeight);
collapseAnimator = slideAnimator(expandHeight, 0);
return true;
}
});
}
public void setExpanded(boolean expanded) {
mExpanded = expanded;
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = expanded ? expandHeight : 0;
expandLayout.setLayoutParams(layoutParams);
expandLayout.setVisibility(expanded ? View.VISIBLE : View.GONE);
}
public void expand() {
if (mExpanded) return;
expandLayout.setVisibility(View.VISIBLE);
expandAnimator.start();
mExpanded = true;
}
public void collapse() {
if (!mExpanded) return;
collapseAnimator.start();
mExpanded = false;
}
public abstract void setExpandLayout(View itemView);
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = value;
expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

View File

@@ -1,12 +1,53 @@
package com.topjohnwu.magisk.components;
import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
public class Fragment extends android.support.v4.app.Fragment {
private ActivityResultListener activityResultListener;
public MagiskManager getApplication() {
return Utils.getMagiskManager(getActivity());
}
public Shell getShell() {
return Shell.getShell(getActivity());
}
@Override
public void onResume() {
super.onResume();
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).subscribeTopics();
}
}
@Override
public void onPause() {
if (this instanceof Topic.Subscriber) {
((Topic.Subscriber) this).unsubscribeTopics();
}
super.onPause();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (activityResultListener != null)
activityResultListener.onActivityResult(requestCode, resultCode, data);
activityResultListener = null;
}
public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) {
activityResultListener = listener;
super.startActivityForResult(intent, requestCode);
}
public interface ActivityResultListener {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
}

View File

@@ -1,31 +0,0 @@
package com.topjohnwu.magisk.components;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils;
import us.feras.mdv.MarkdownView;
public class MarkDownWindow {
public MarkDownWindow(String title, String url, Context context) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setTitle(title);
Logger.dev("WebView: URL = " + url);
MarkdownView md = new MarkdownView(context);
md.loadMarkdownFile(url, "file:///android_asset/" +
(magiskManager.isDarkTheme ? "dark" : "light") + ".css");
alert.setView(md);
alert.setNegativeButton(R.string.close, (dialog, id) -> dialog.dismiss());
alert.show();
}
}

View File

@@ -6,8 +6,6 @@ import android.support.design.widget.Snackbar;
import android.view.View;
import android.widget.TextView;
import butterknife.ButterKnife;
public class SnackbarMaker {
public static Snackbar make(Activity activity, CharSequence text, int duration) {
@@ -32,7 +30,7 @@ public class SnackbarMaker {
}
private static void setup(Snackbar snack) {
TextView text = ButterKnife.findById(snack.getView(), android.support.design.R.id.snackbar_text);
TextView text = snack.getView().findViewById(android.support.design.R.id.snackbar_text);
text.setMaxLines(Integer.MAX_VALUE);
}

View File

@@ -5,11 +5,13 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.ValueSortedMap;
import com.topjohnwu.magisk.utils.Utils;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class RepoDatabaseHelper extends SQLiteOpenHelper {
@@ -17,8 +19,13 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
private static final String TABLE_NAME = "repos";
private static final int MIN_TEMPLATE_VER = 3;
private SQLiteDatabase mDb;
private MagiskManager mm;
public RepoDatabaseHelper(Context context) {
super(context, "repo.db", null, DATABASE_VER);
mDb = getWritableDatabase();
mm = Utils.getMagiskManager(context);
}
@Override
@@ -42,52 +49,41 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
}
}
public void addRepoMap(ValueSortedMap<String, Repo> map) {
SQLiteDatabase db = getWritableDatabase();
Collection<Repo> list = map.values();
for (Repo repo : list) {
Logger.dev("Add to DB: " + repo.getId());
db.replace(TABLE_NAME, null, repo.getContentValues());
}
db.close();
}
public void clearRepo() {
SQLiteDatabase db = getWritableDatabase();
db.delete(TABLE_NAME, null, null);
db.close();
mDb.delete(TABLE_NAME, null, null);
}
public void removeRepo(ValueSortedMap<String, Repo> map) {
SQLiteDatabase db = getWritableDatabase();
Collection<Repo> list = map.values();
for (Repo repo : list) {
Logger.dev("Remove from DB: " + repo.getId());
db.delete(TABLE_NAME, "id=?", new String[] { repo.getId() });
public void removeRepo(List<String> list) {
for (String id : list) {
Logger.dev("Remove from DB: " + id);
mDb.delete(TABLE_NAME, "id=?", new String[] { id });
}
db.close();
}
public ValueSortedMap<String, Repo> getRepoMap() {
return getRepoMap(true);
public void addRepo(Repo repo) {
mDb.replace(TABLE_NAME, null, repo.getContentValues());
}
public ValueSortedMap<String, Repo> getRepoMap(boolean filtered) {
ValueSortedMap<String, Repo> ret = new ValueSortedMap<>();
SQLiteDatabase db = getReadableDatabase();
Repo repo;
try (Cursor c = db.query(TABLE_NAME, null, null, null, null, null, null)) {
while (c.moveToNext()) {
repo = new Repo(c);
if (repo.getTemplateVersion() < MIN_TEMPLATE_VER && filtered) {
Logger.dev("Outdated repo: " + repo.getId());
} else {
// Logger.dev("Load from DB: " + repo.getId());
ret.put(repo.getId(), repo);
}
public Repo getRepo(String id) {
try (Cursor c = mDb.query(TABLE_NAME, null, "id=?", new String[] { id }, null, null, null)) {
if (c.moveToNext()) {
return new Repo(c);
}
}
return null;
}
public Cursor getRepoCursor() {
return mDb.query(TABLE_NAME, null, "template>=? AND template<=?", new String[] { String.valueOf(MIN_TEMPLATE_VER), String.valueOf(mm.magiskVersionCode) }, null, null, "name COLLATE NOCASE");
}
public List<String> getRepoIDList() {
LinkedList<String> ret = new LinkedList<>();
try (Cursor c = mDb.query(TABLE_NAME, null, null, null, null, null, null)) {
while (c.moveToNext()) {
ret.add(c.getString(c.getColumnIndex("id")));
}
}
db.close();
return ret;
}
}

View File

@@ -4,8 +4,10 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.superuser.Policy;
@@ -13,28 +15,45 @@ import com.topjohnwu.magisk.superuser.SuLogEntry;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class SuDatabaseHelper extends SQLiteOpenHelper {
public static final String ROOT_ACCESS = "root_access";
public static final String MULTIUSER_MODE = "multiuser_mode";
public static final String MNT_NS = "mnt_ns";
public static final int ROOT_ACCESS_DISABLED = 0;
public static final int ROOT_ACCESS_APPS_ONLY = 1;
public static final int ROOT_ACCESS_ADB_ONLY = 2;
public static final int ROOT_ACCESS_APPS_AND_ADB = 3;
private static final int DATABASE_VER = 2;
public static final String MULTIUSER_MODE = "multiuser_mode";
public static final int MULTIUSER_MODE_OWNER_ONLY = 0;
public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
public static final int MULTIUSER_MODE_USER = 2;
public static final String MNT_NS = "mnt_ns";
public static final int NAMESPACE_MODE_GLOBAL = 0;
public static final int NAMESPACE_MODE_REQUESTER = 1;
public static final int NAMESPACE_MODE_ISOLATE = 2;
public static final String DB_NAME = "su.db";
private static final int DATABASE_VER = 3;
private static final String POLICY_TABLE = "policies";
private static final String LOG_TABLE = "logs";
private static final String SETTINGS_TABLE = "settings";
private MagiskManager magiskManager;
private MagiskManager mm;
private PackageManager pm;
private SQLiteDatabase mDb;
public SuDatabaseHelper(Context context) {
super(context, "su.db", null, DATABASE_VER);
magiskManager = Utils.getMagiskManager(context);
super(context, DB_NAME, null, DATABASE_VER);
mm = Utils.getMagiskManager(context);
pm = context.getPackageManager();
mDb = getWritableDatabase();
cleanup();
}
@@ -63,13 +82,17 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
"FROM " + POLICY_TABLE + "_old");
db.execSQL("DROP TABLE " + POLICY_TABLE + "_old");
File oldDB = magiskManager.getDatabasePath("sulog.db");
File oldDB = mm.getDatabasePath("sulog.db");
if (oldDB.exists()) {
migrateLegacyLogList(oldDB, db);
magiskManager.deleteDatabase("sulog.db");
mm.deleteDatabase("sulog.db");
}
++oldVersion;
}
if (oldVersion == 2) {
db.execSQL("UPDATE " + LOG_TABLE + " SET time=time*1000");
++oldVersion;
}
}
private void createTables(SQLiteDatabase db) {
@@ -93,13 +116,12 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
}
private void cleanup() {
SQLiteDatabase db = getWritableDatabase();
// Clear outdated policies
db.delete(POLICY_TABLE, "until > 0 AND until < ?",
mDb.delete(POLICY_TABLE, "until > 0 AND until < ?",
new String[] { String.valueOf(System.currentTimeMillis() / 1000) });
// Clear outdated logs
db.delete(LOG_TABLE, "time < ?", new String[] { String.valueOf(
System.currentTimeMillis() / 1000 - magiskManager.suLogTimeout * 86400) });
mDb.delete(LOG_TABLE, "time < ?", new String[] { String.valueOf(
System.currentTimeMillis() - mm.suLogTimeout * 86400000) });
}
public void deletePolicy(Policy policy) {
@@ -107,25 +129,16 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
}
public void deletePolicy(String pkg) {
SQLiteDatabase db = getWritableDatabase();
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
db.close();
mDb.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
}
public void deletePolicy(int uid) {
SQLiteDatabase db = getWritableDatabase();
deletePolicy(db, uid);
db.close();
}
private void deletePolicy(SQLiteDatabase db, int uid) {
db.delete(POLICY_TABLE, "uid=?", new String[]{String.valueOf(uid)});
mDb.delete(POLICY_TABLE, "uid=?", new String[]{String.valueOf(uid)});
}
public Policy getPolicy(int uid) {
Policy policy = null;
SQLiteDatabase db = getReadableDatabase();
try (Cursor c = db.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
try (Cursor c = mDb.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
if (c.moveToNext()) {
policy = new Policy(c, pm);
}
@@ -133,14 +146,12 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
deletePolicy(uid);
return null;
}
db.close();
return policy;
}
public Policy getPolicy(String pkg) {
Policy policy = null;
SQLiteDatabase db = getReadableDatabase();
try (Cursor c = db.query(POLICY_TABLE, null, "package_name=?", new String[] { pkg }, null, null, null)) {
try (Cursor c = mDb.query(POLICY_TABLE, null, "package_name=?", new String[] { pkg }, null, null, null)) {
if (c.moveToNext()) {
policy = new Policy(c, pm);
}
@@ -148,116 +159,107 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
deletePolicy(pkg);
return null;
}
db.close();
return policy;
}
public void addPolicy(Policy policy) {
SQLiteDatabase db = getWritableDatabase();
db.replace(POLICY_TABLE, null, policy.getContentValues());
db.close();
mDb.replace(POLICY_TABLE, null, policy.getContentValues());
}
public void updatePolicy(Policy policy) {
SQLiteDatabase db = getWritableDatabase();
updatePolicy(db, policy);
db.close();
}
private void updatePolicy(SQLiteDatabase db, Policy policy) {
db.update(POLICY_TABLE, policy.getContentValues(), "package_name=?",
mDb.update(POLICY_TABLE, policy.getContentValues(), "package_name=?",
new String[] { policy.packageName });
}
public List<Policy> getPolicyList(PackageManager pm) {
List<Policy> ret = new ArrayList<>();
SQLiteDatabase db = getWritableDatabase();
Policy policy;
try (Cursor c = db.query(POLICY_TABLE, null, null, null, null, null, null)) {
try (Cursor c = mDb.query(POLICY_TABLE, null, null, null, null, null, null)) {
List<Policy> ret = new ArrayList<>(c.getCount());
while (c.moveToNext()) {
try {
policy = new Policy(c, pm);
Policy policy = new Policy(c, pm);
// The application changed UID for some reason, check user config
if (policy.info.uid != policy.uid) {
if (magiskManager.suReauth) {
if (mm.suReauth) {
// Reauth required, remove from DB
deletePolicy(db, policy.uid);
deletePolicy(policy);
continue;
} else {
// No reauth, update to use the new UID
policy.uid = policy.info.uid;
updatePolicy(db, policy);
updatePolicy(policy);
}
}
ret.add(policy);
} catch (PackageManager.NameNotFoundException e) {
// The app no longer exist, remove from DB
deletePolicy(db, c.getInt(c.getColumnIndex("uid")));
deletePolicy(c.getInt(c.getColumnIndex("uid")));
}
}
Collections.sort(ret);
return ret;
}
db.close();
Collections.sort(ret);
return ret;
}
private List<SuLogEntry> getLogList(SQLiteDatabase db, String selection) {
List<SuLogEntry> ret = new ArrayList<>();
try (Cursor c = db.query(LOG_TABLE, null, selection, null, null, null, "time DESC")) {
public List<List<Integer>> getLogStructure() {
try (Cursor c = mDb.query(LOG_TABLE, new String[] { "time" }, null, null, null, null, "time DESC")) {
List<List<Integer>> ret = new ArrayList<>();
List<Integer> list = null;
String dateString = null, newString;
while (c.moveToNext()) {
ret.add(new SuLogEntry(c));
Date date = new Date(c.getLong(c.getColumnIndex("time")));
newString = DateFormat.getDateInstance(DateFormat.MEDIUM, MagiskManager.locale).format(date);
if (!TextUtils.equals(dateString, newString)) {
dateString = newString;
list = new ArrayList<>();
ret.add(list);
}
list.add(c.getPosition());
}
return ret;
}
db.close();
return ret;
}
public Cursor getLogCursor() {
return getLogCursor(mDb);
}
public Cursor getLogCursor(SQLiteDatabase db) {
return db.query(LOG_TABLE, null, null, null, null, null, "time DESC");
}
private void migrateLegacyLogList(File oldDB, SQLiteDatabase newDB) {
SQLiteDatabase db = SQLiteDatabase.openDatabase(oldDB.getPath(), null, SQLiteDatabase.OPEN_READWRITE);
List<SuLogEntry> logs = getLogList(db, null);
for (SuLogEntry log : logs) {
newDB.insert(LOG_TABLE, null, log.getContentValues());
try (SQLiteDatabase oldDb = SQLiteDatabase.openDatabase(oldDB.getPath(), null, SQLiteDatabase.OPEN_READWRITE);
Cursor c = getLogCursor(oldDb)) {
while (c.moveToNext()) {
ContentValues values = new ContentValues();
DatabaseUtils.cursorRowToContentValues(c, values);
newDB.insert(LOG_TABLE, null, values);
}
}
}
public List<SuLogEntry> getLogList() {
return getLogList(null);
}
public List<SuLogEntry> getLogList(String selection) {
return getLogList(getReadableDatabase(), selection);
}
public void addLog(SuLogEntry log) {
SQLiteDatabase db = getWritableDatabase();
db.insert(LOG_TABLE, null, log.getContentValues());
db.close();
mDb.insert(LOG_TABLE, null, log.getContentValues());
}
public void clearLogs() {
SQLiteDatabase db = getWritableDatabase();
db.delete(LOG_TABLE, null, null);
db.close();
mDb.delete(LOG_TABLE, null, null);
}
public void setSettings(String key, int value) {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
SQLiteDatabase db = getWritableDatabase();
db.replace(SETTINGS_TABLE, null, data);
db.close();
mDb.replace(SETTINGS_TABLE, null, data);
}
public int getSettings(String key, int defaultValue) {
SQLiteDatabase db = getReadableDatabase();
int value = defaultValue;
try (Cursor c = db.query(SETTINGS_TABLE, null, "key=?", new String[] { key }, null, null, null)) {
while (c.moveToNext()) {
try (Cursor c = mDb.query(SETTINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getInt(c.getColumnIndex("value"));
}
}
db.close();
return value;
}
}

View File

@@ -29,17 +29,19 @@ public class Repo extends BaseModule {
}
public void update() throws CacheModException {
String props = WebService.request(getManifestUrl(), WebService.GET);
String props = WebService.getString(getManifestUrl());
String lines[] = props.split("\\n");
parseProps(lines);
Logger.dev("Repo: Fetching prop: " + getId());
}
public void update(Date lastUpdate) throws CacheModException {
public boolean update(Date lastUpdate) throws CacheModException {
if (lastUpdate.after(mLastUpdate)) {
mLastUpdate = lastUpdate;
update();
return true;
}
return false;
}
public ContentValues getContentValues() {

View File

@@ -6,7 +6,6 @@ import android.content.Intent;
import android.os.Build;
import com.topjohnwu.magisk.services.OnBootIntentService;
import com.topjohnwu.magisk.utils.Utils;
public class BootReceiver extends BroadcastReceiver {
@@ -21,7 +20,6 @@ public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Utils.getMagiskManager(context).initSU();
// There is currently no need to start an IntentService onBoot
// startIntentService(context);
}

View File

@@ -34,7 +34,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
onDownloadDone(uri);
break;
default:
Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show();
Utils.getMagiskManager(context).toast(R.string.download_file_error, Toast.LENGTH_LONG);
break;
}
context.unregisterReceiver(this);

View File

@@ -7,6 +7,7 @@ import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
@@ -34,8 +35,8 @@ public class ManagerUpdate extends BroadcastReceiver {
}
}
},
intent.getStringExtra("link"),
intent.getStringExtra(MagiskManager.INTENT_LINK),
Utils.getLegalFilename("MagiskManager-v" +
intent.getStringExtra("version") + ".apk"));
intent.getStringExtra(MagiskManager.INTENT_VERSION) + ".apk"));
}
}

View File

@@ -12,7 +12,6 @@ public class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
magiskManager.initSUConfig();
String pkg = intent.getData().getEncodedSchemeSpecificPart();
Policy policy = magiskManager.suDB.getPolicy(pkg);

View File

@@ -4,24 +4,15 @@ import android.app.job.JobParameters;
import android.app.job.JobService;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.utils.Utils;
public class UpdateCheckService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
new CheckUpdates(this, true){
@Override
protected Void doInBackground(Void... voids) {
magiskManager.updateMagiskInfo();
magiskManager.updateNotification = magiskManager.prefs.getBoolean("notification", true);
return super.doInBackground(voids);
}
@Override
protected void onPostExecute(Void v) {
jobFinished(params, false);
super.onPostExecute(v);
}
}.exec();
Utils.getMagiskManager(this).getMagiskInfo();
new CheckUpdates(this, true)
.setCallBack(() -> jobFinished(params, false)).exec();
return true;
}

View File

@@ -17,7 +17,6 @@ public class RequestActivity extends Activity {
return;
}
getApplicationContext().initSUConfig();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class);
startActivity(intent);
finish();

View File

@@ -2,15 +2,14 @@ package com.topjohnwu.magisk.superuser;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import com.topjohnwu.magisk.MagiskManager;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class SuLogEntry implements Parcelable {
public class SuLogEntry {
public int fromUid, toUid, fromPid;
public String packageName, appName, command;
@@ -31,7 +30,7 @@ public class SuLogEntry implements Parcelable {
appName = c.getString(c.getColumnIndex("app_name"));
command = c.getString(c.getColumnIndex("command"));
action = c.getInt(c.getColumnIndex("action")) != 0;
date = new Date(c.getLong(c.getColumnIndex("time")) * 1000);
date = new Date(c.getLong(c.getColumnIndex("time")));
}
public ContentValues getContentValues() {
@@ -43,56 +42,15 @@ public class SuLogEntry implements Parcelable {
values.put("command", command);
values.put("to_uid", toUid);
values.put("action", action ? 1 : 0);
values.put("time", date.getTime() / 1000);
values.put("time", date.getTime());
return values;
}
public String getDateString() {
return DateFormat.getDateInstance(DateFormat.MEDIUM).format(date);
return DateFormat.getDateInstance(DateFormat.MEDIUM, MagiskManager.locale).format(date);
}
public String getTimeString() {
return new SimpleDateFormat("h:mm a", Locale.US).format(date);
}
public static final Creator<SuLogEntry> CREATOR = new Creator<SuLogEntry>() {
@Override
public SuLogEntry createFromParcel(Parcel in) {
return new SuLogEntry(in);
}
@Override
public SuLogEntry[] newArray(int size) {
return new SuLogEntry[size];
}
};
protected SuLogEntry(Parcel in) {
fromUid = in.readInt();
toUid = in.readInt();
fromPid = in.readInt();
packageName = in.readString();
appName = in.readString();
command = in.readString();
action = in.readByte() != 0;
date = new Date(in.readLong());
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(fromUid);
dest.writeInt(toUid);
dest.writeInt(fromPid);
dest.writeString(packageName);
dest.writeString(appName);
dest.writeString(command);
dest.writeByte((byte) (action ? 1 : 0));
dest.writeLong(date.getTime());
return new SimpleDateFormat("h:mm a", MagiskManager.locale).format(date);
}
}

View File

@@ -14,8 +14,9 @@ import java.util.Date;
public class SuReceiver extends BroadcastReceiver {
private static final int NO_NOTIFICATION = 0;
private static final int TOAST = 1;
public static final int NO_NOTIFICATION = 0;
public static final int TOAST = 1;
private static final int NOTIFY_NORMAL_LOG = 0;
private static final int NOTIFY_USER_TOASTS = 1;
private static final int NOTIFY_USER_TO_OWNER = 2;
@@ -27,7 +28,6 @@ public class SuReceiver extends BroadcastReceiver {
Policy policy;
MagiskManager magiskManager = (MagiskManager) context.getApplicationContext();
magiskManager.initSUConfig();
if (intent == null) return;

View File

@@ -30,10 +30,11 @@ import butterknife.ButterKnife;
public class SuRequestActivity extends Activity {
public static final int PROMPT = 0;
public static final int AUTO_DENY = 1;
public static final int AUTO_ALLOW = 2;
private static final int[] timeoutList = {0, -1, 10, 20, 30, 60};
private static final int PROMPT = 0;
private static final int AUTO_DENY = 1;
private static final int AUTO_ALLOW = 2;
@BindView(R.id.su_popup) LinearLayout suPopup;
@BindView(R.id.timeout) Spinner timeout;
@@ -58,7 +59,7 @@ public class SuRequestActivity extends Activity {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
pm = getPackageManager();
magiskManager = getApplicationContext();
magiskManager = getMagiskManager();
Intent intent = getIntent();
socketPath = intent.getStringExtra("socket");

View File

@@ -1,18 +0,0 @@
package com.topjohnwu.magisk.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayInOutStream extends ByteArrayOutputStream {
public ByteArrayInputStream getInputStream() {
ByteArrayInputStream in = new ByteArrayInputStream(buf, 0, count);
count = 0;
buf = new byte[32];
return in;
}
public void setBuffer(byte[] buffer) {
buf = buffer;
count = buffer.length;
}
}

View File

@@ -1,50 +0,0 @@
package com.topjohnwu.magisk.utils;
import java.util.HashSet;
import java.util.Set;
public class CallbackEvent<Result> {
public boolean isTriggered = false;
private Result result;
private Set<Listener<Result>> listeners;
public void register(Listener<Result> l) {
if (listeners == null) {
listeners = new HashSet<>();
}
listeners.add(l);
}
public void unRegister() {
listeners = null;
}
public void unRegister(Listener<Result> l) {
if (listeners != null) {
listeners.remove(l);
}
}
public void trigger() {
trigger(null);
}
public void trigger(Result r) {
result = r;
isTriggered = true;
if (listeners != null) {
for (Listener<Result> listener : listeners) {
listener.onTrigger(this);
}
}
}
public Result getResult() {
return result;
}
public interface Listener<R> {
void onTrigger(CallbackEvent<R> event);
}
}

View File

@@ -1,13 +1,18 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@@ -25,6 +30,17 @@ public class Shell {
private boolean isValid;
private void testRootShell(DataOutputStream in, DataInputStream out) throws IOException {
in.write(("id\n").getBytes("UTF-8"));
in.flush();
String s = new BufferedReader(new InputStreamReader(out)).readLine();
if (TextUtils.isEmpty(s) || !s.contains("uid=0")) {
in.close();
out.close();
throw new IOException();
}
}
private Shell() {
rootStatus = 1;
Process process = null;
@@ -32,45 +48,36 @@ public class Shell {
DataInputStream out = null;
try {
process = Runtime.getRuntime().exec("su");
// Try getting global namespace
process = Runtime.getRuntime().exec("su --mount-master");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e) {
rootStatus = 0;
// Feature not implemented, normal root shell
try {
process = Runtime.getRuntime().exec("su");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e1) {
rootStatus = 0;
}
}
while (true) {
if (rootAccess()) {
try {
in.write(("id\n").getBytes("UTF-8"));
in.flush();
String s = new BufferedReader(new InputStreamReader(out)).readLine();
if (s.isEmpty() || !s.contains("uid=0")) {
in.close();
out.close();
process.destroy();
throw new IOException();
}
} catch (IOException e) {
rootStatus = -1;
continue;
}
break;
} else {
// Try to gain non-root sh
try {
process = Runtime.getRuntime().exec("sh");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
break;
if (!rootAccess()) {
// Try to gain non-root sh
try {
process = Runtime.getRuntime().exec("sh");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
}
@@ -81,18 +88,64 @@ public class Shell {
sh_raw("umask 022");
}
private Shell(String command) {
Process process;
DataOutputStream in;
DataInputStream out;
try {
process = Runtime.getRuntime().exec(command);
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
isValid = true;
shellProcess = process;
STDIN = in;
STDOUT = out;
}
public static Shell getShell() {
return new Shell();
}
public static Shell getShell(String command) {
return new Shell(command);
}
public static Shell getShell(Context context) {
return Utils.getMagiskManager(context).shell;
MagiskManager magiskManager = Utils.getMagiskManager(context);
if (magiskManager.shell == null || !magiskManager.shell.isValid) {
// Get new shell if needed
magiskManager.shell = getShell();
}
return magiskManager.shell;
}
public static boolean rootAccess() {
return rootStatus > 0;
}
public void loadInputStream(InputStream in) {
try {
int read;
byte[] bytes = new byte[4096];
while ((read = in.read(bytes)) != -1) {
STDIN.write(bytes, 0, read);
}
STDIN.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public List<String> sh(String... commands) {
List<String> res = new ArrayList<>();
if (!isValid) return res;
@@ -101,11 +154,16 @@ public class Shell {
}
public void sh_raw(String... commands) {
sh_raw(false, commands);
}
public void sh_raw(boolean stdout, String... commands) {
if (!isValid) return;
synchronized (shellProcess) {
try {
for (String command : commands) {
STDIN.write((command + "\n").getBytes("UTF-8"));
Logger.shell(command);
STDIN.write((command + (stdout ? "\n" : " >/dev/null\n")).getBytes("UTF-8"));
STDIN.flush();
}
} catch (IOException e) {
@@ -116,7 +174,7 @@ public class Shell {
}
}
public void sh(List<String> output, String... commands) {
public void sh(Collection<String> output, String... commands) {
if (!isValid) return;
try {
shellProcess.exitValue();
@@ -126,10 +184,10 @@ public class Shell {
// This should be the expected result
}
synchronized (shellProcess) {
StreamGobbler out = new StreamGobbler(this.STDOUT, output);
StreamGobbler out = new StreamGobbler(STDOUT, output);
out.start();
sh_raw(commands);
sh_raw("echo \'-shell-done-\'");
sh_raw(true, commands);
sh_raw(true, "echo \'-shell-done-\'");
try { out.join(); } catch (InterruptedException ignored) {}
}
}
@@ -144,8 +202,24 @@ public class Shell {
sh_raw(commands);
}
public void su(List<String> output, String... commands) {
public void su(Collection<String> output, String... commands) {
if (!rootAccess()) return;
sh(output, commands);
}
public static abstract class AbstractList<E> extends java.util.AbstractList<E> {
@Override
public abstract boolean add(E e);
@Override
public E get(int i) {
return null;
}
@Override
public int size() {
return 0;
}
}
}

View File

@@ -6,7 +6,7 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Collection;
/**
* Modified by topjohnwu, based on Chainfire's libsuperuser
@@ -15,8 +15,7 @@ import java.util.List;
public class StreamGobbler extends Thread {
private BufferedReader reader = null;
private List<String> writer = null;
private boolean isRoot = false;
private Collection<String> writer = null;
/**
* <p>StreamGobbler constructor</p>
@@ -28,7 +27,7 @@ public class StreamGobbler extends Thread {
* @param inputStream InputStream to read from
* @param outputList {@literal List<String>} to write to, or null
*/
public StreamGobbler(InputStream inputStream, List<String> outputList) {
public StreamGobbler(InputStream inputStream, Collection<String> outputList) {
try {
while (inputStream.available() != 0) {
inputStream.skip(inputStream.available());

View File

@@ -0,0 +1,64 @@
package com.topjohnwu.magisk.utils;
import org.kamranzafar.jtar.TarHeader;
import java.io.File;
import java.util.Arrays;
public class TarEntry extends org.kamranzafar.jtar.TarEntry {
public TarEntry(File file, String entryName) {
super(file, entryName);
}
/*
* Workaround missing java.nio.file.attribute.PosixFilePermission
* Simply just assign a default permission to the file
* */
@Override
public void extractTarHeader(String entryName) {
int permissions = file.isDirectory() ? 000755 : 000644;
header = TarHeader.createHeader(entryName, file.length(), file.lastModified() / 1000, file.isDirectory(), permissions);
header.userName = new StringBuffer("");
header.groupName = header.userName;
}
/*
* Rewrite the header to GNU format
* */
@Override
public void writeEntryHeader(byte[] outbuf) {
super.writeEntryHeader(outbuf);
System.arraycopy("ustar \0".getBytes(), 0, outbuf, 257, TarHeader.USTAR_MAGICLEN);
getOctalBytes(header.mode, outbuf, 100, TarHeader.MODELEN);
getOctalBytes(header.userId, outbuf, 108, TarHeader.UIDLEN);
getOctalBytes(header.groupId, outbuf, 116, TarHeader.GIDLEN);
getOctalBytes(header.size, outbuf, 124, TarHeader.SIZELEN);
getOctalBytes(header.modTime, outbuf, 136, TarHeader.MODTIMELEN);
Arrays.fill(outbuf, 148, 148 + TarHeader.CHKSUMLEN, (byte) ' ');
Arrays.fill(outbuf, 329, 329 + TarHeader.USTAR_DEVLEN, (byte) '\0');
Arrays.fill(outbuf, 337, 337 + TarHeader.USTAR_DEVLEN, (byte) '\0');
// Recalculate checksum
getOctalBytes(computeCheckSum(outbuf), outbuf, 148, TarHeader.CHKSUMLEN);
}
/*
* Proper octal to ASCII conversion
* */
private void getOctalBytes(long value, byte[] buf, int offset, int length) {
int idx = length - 1;
buf[offset + idx] = 0;
--idx;
for (long val = value; idx >= 0; --idx) {
buf[offset + idx] = (byte) ((byte) '0' + (byte) (val & 7));
val = val >> 3;
}
}
}

View File

@@ -0,0 +1,68 @@
package com.topjohnwu.magisk.utils;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class Topic {
public boolean hasPublished = false;
private List<WeakReference<Subscriber>> subscribers;
public void subscribe(Subscriber sub) {
if (subscribers == null) {
subscribers = new LinkedList<>();
}
subscribers.add(new WeakReference<>(sub));
}
public void unsubscribe() {
subscribers = null;
}
public void unsubscribe(Subscriber sub) {
for (Iterator<WeakReference<Subscriber>> i = subscribers.iterator(); i.hasNext();) {
WeakReference<Subscriber> subscriber = i.next();
if (subscriber.get() == null || subscriber.get() == sub) {
i.remove();
}
}
}
public void publish() {
publish(true);
}
public void publish(boolean record) {
hasPublished = record;
if (subscribers != null) {
for (WeakReference<Subscriber> subscriber : subscribers) {
if (subscriber.get() != null)
subscriber.get().onTopicPublished(this);
}
}
}
public interface Subscriber {
default void subscribeTopics() {
for (Topic topic : getSubscription()) {
if (topic.hasPublished) {
onTopicPublished(topic);
}
topic.subscribe(this);
}
}
default void unsubscribeTopics() {
for (Topic event : getSubscription()) {
event.unsubscribe(this);
}
}
default void onTopicPublished() {
onTopicPublished(null);
}
void onTopicPublished(Topic topic);
Topic[] getSubscription();
}
}

View File

@@ -5,39 +5,59 @@ import android.app.Activity;
import android.app.DownloadManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskFragment;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.asyncs.RestoreStockBoot;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
public class Utils {
public static final int SELECT_BOOT_IMG = 3;
public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String UTIL_FUNCTIONS= "util_functions.sh";
public static boolean isDownloading = false;
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
@@ -61,12 +81,12 @@ public class Utils {
}
public static List<String> getModList(Shell shell, String path) {
String command = "find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\"";
String command = "ls -d " + path + "/* | grep -v lost+found";
return shell.su(command);
}
public static List<String> readFile(Shell shell, String path) {
String command = "cat " + path;
String command = "cat " + path + " | sed '$a\\ ' | sed '$d'";
return shell.su(command);
}
@@ -74,32 +94,28 @@ public class Utils {
if (isDownloading)
return;
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
return;
}
runWithPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs())
|| (file.exists() && !file.delete())) {
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
return;
}
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs())
|| (file.exists() && !file.delete())) {
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
return;
}
Toast.makeText(context, context.getString(R.string.downloading_toast, filename), Toast.LENGTH_LONG).show();
isDownloading = true;
Toast.makeText(context, context.getString(R.string.downloading_toast, filename), Toast.LENGTH_LONG).show();
isDownloading = true;
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
if (link != null) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link));
request.setDestinationUri(Uri.fromFile(file));
receiver.setDownloadID(downloadManager.enqueue(request));
}
receiver.setFilename(filename);
context.getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
if (link != null) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link));
request.setDestinationUri(Uri.fromFile(file));
receiver.setDownloadID(downloadManager.enqueue(request));
}
receiver.setFilename(filename);
context.getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
});
}
public static String getLegalFilename(CharSequence filename) {
@@ -108,23 +124,6 @@ public class Utils {
.replace("#", "").replace("@", "").replace("*", "");
}
public static String detectBootImage(Shell shell) {
String[] commands = {
"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",
"echo \"$BOOTIMAGE\""
};
List<String> ret = shell.su(commands);
if (isValidShellResponse(ret)) {
return ret.get(0);
}
return null;
}
public static boolean lowercaseContains(CharSequence string, CharSequence nonNullLowercaseSearch) {
return !TextUtils.isEmpty(string) && string.toString().toLowerCase().contains(nonNullLowercaseSearch);
}
@@ -143,6 +142,10 @@ public class Utils {
return Integer.parseInt(prefs.getString(key, String.valueOf(def)));
}
public static int getPrefsInt(SharedPreferences prefs, String key) {
return getPrefsInt(prefs, key, 0);
}
public static MagiskManager getMagiskManager(Context context) {
return (MagiskManager) context.getApplicationContext();
}
@@ -152,16 +155,16 @@ public class Utils {
@Override
public void handleResults(Result result) {
getMagiskManager(mActivity).SNCheckResult = result;
getMagiskManager(mActivity).safetyNetDone.trigger();
getMagiskManager(mActivity).safetyNetDone.publish(false);
}
}.requestTest();
}
public static void clearRepoCache(Activity activity) {
MagiskManager magiskManager = getMagiskManager(activity);
magiskManager.prefs.edit().remove(LoadRepos.ETAG_KEY).apply();
new RepoDatabaseHelper(activity).clearRepo();
Toast.makeText(activity, R.string.repo_cache_cleared, Toast.LENGTH_SHORT).show();
public static void clearRepoCache(Context context) {
MagiskManager mm = getMagiskManager(context);
mm.prefs.edit().remove(UpdateRepos.ETAG_KEY).apply();
mm.repoDB.clearRepo();
mm.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
}
public static String getNameFromUri(Context context, Uri uri) {
@@ -195,51 +198,348 @@ public class Utils {
return networkInfo != null && networkInfo.isConnected();
}
public static boolean checkBits(int bits, int... masks) {
for (int mask : masks) {
if ((bits & mask) == 0)
return false;
}
return true;
}
public static void showMagiskUpdate(MagiskManager magiskManager) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager);
public static void showMagiskUpdateNotification(MagiskManager mm) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, MagiskManager.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(magiskManager.getString(R.string.magisk_update_title))
.setContentText(magiskManager.getString(R.string.magisk_update_available, magiskManager.remoteMagiskVersionString))
.setChannelId(MagiskManager.NOTIFICATION_CHANNEL)
.setContentTitle(mm.getString(R.string.magisk_update_title))
.setContentText(mm.getString(R.string.magisk_update_available, mm.remoteMagiskVersionString))
.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);
Intent intent = new Intent(mm, SplashActivity.class);
intent.putExtra(MagiskManager.INTENT_SECTION, "magisk");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void showManagerUpdate(MagiskManager magiskManager) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager);
public static void showManagerUpdateNotification(MagiskManager mm) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, MagiskManager.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(magiskManager.getString(R.string.manager_update_title))
.setContentText(magiskManager.getString(R.string.manager_download_install))
.setChannelId(MagiskManager.NOTIFICATION_CHANNEL)
.setContentTitle(mm.getString(R.string.manager_update_title))
.setContentText(mm.getString(R.string.manager_download_install))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true);
Intent intent = new Intent(magiskManager, ManagerUpdate.class);
intent.putExtra("link", magiskManager.managerLink);
intent.putExtra("version", magiskManager.remoteManagerVersionString);
PendingIntent pendingIntent = PendingIntent.getBroadcast(magiskManager,
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(MagiskManager.INTENT_LINK, mm.managerLink);
intent.putExtra(MagiskManager.INTENT_VERSION, mm.remoteManagerVersionString);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(APK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void enableMagiskHide(Shell shell) {
shell.su_raw("magiskhide --enable");
}
public static void disableMagiskHide(Shell shell) {
shell.su_raw("magiskhide --disable");
}
public static List<String> listMagiskHide(Shell shell) {
return shell.su("magiskhide --ls");
}
public static void addMagiskHide(Shell shell, String pkg) {
shell.su_raw("magiskhide --add " + pkg);
}
public static void rmMagiskHide(Shell shell, String pkg) {
shell.su_raw("magiskhide --rm " + pkg);
}
public static String getLocaleString(Context context, Locale locale, @StringRes int id) {
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
Context localizedContext = context.createConfigurationContext(config);
return localizedContext.getString(id);
}
public static List<Locale> getAvailableLocale(Context context) {
List<Locale> locales = new ArrayList<>();
HashSet<String> set = new HashSet<>();
Locale locale;
int compareId = R.string.download_file_error;
// Add default locale
locales.add(Locale.ENGLISH);
set.add(getLocaleString(context, Locale.ENGLISH, compareId));
// Add some special locales
locales.add(Locale.TAIWAN);
set.add(getLocaleString(context, Locale.TAIWAN, compareId));
locale = new Locale("pt", "BR");
locales.add(locale);
set.add(getLocaleString(context, locale, compareId));
// Other locales
for (String s : context.getAssets().getLocales()) {
locale = Locale.forLanguageTag(s);
if (set.add(getLocaleString(context, locale, compareId))) {
locales.add(locale);
}
}
Collections.sort(locales, (l1, l2) -> l1.getDisplayName(l1).compareTo(l2.getDisplayName(l2)));
return locales;
}
public static String genPackageName(String prefix, int length) {
StringBuilder builder = new StringBuilder(length);
builder.append(prefix);
length -= prefix.length();
SecureRandom random = new SecureRandom();
String base = "abcdefghijklmnopqrstuvwxyz";
String alpha = base + base.toUpperCase();
String full = alpha + "0123456789..........";
char next, prev = '\0';
for (int i = 0; i < length; ++i) {
if (prev == '.' || i == length - 1 || i == 0) {
next = alpha.charAt(random.nextInt(alpha.length()));
} else {
next = full.charAt(random.nextInt(full.length()));
}
builder.append(next);
prev = next;
}
return builder.toString();
}
public static void runWithPermission(Context context, String permission, Runnable callback) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
// Passed in context should be an activity if not granted, need to show dialog!
if (!(context instanceof com.topjohnwu.magisk.components.Activity))
return;
com.topjohnwu.magisk.components.Activity activity = (com.topjohnwu.magisk.components.Activity) context;
activity.setPermissionGrantCallback(callback);
ActivityCompat.requestPermissions(activity, new String[] { permission }, 0);
} else {
callback.run();
}
}
public static void showMagiskInstallDialog(MagiskFragment fragment, boolean enc, boolean verity) {
MagiskManager mm = getMagiskManager(fragment.getActivity());
String filename = getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip");
new AlertDialogBuilder(fragment.getActivity())
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.magisk)))
.setMessage(mm.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
List<String> options = new ArrayList<>();
options.add(mm.getString(R.string.download_zip_only));
options.add(mm.getString(R.string.patch_boot_file));
if (Shell.rootAccess()) {
options.add(mm.getString(R.string.direct_install));
}
List<String> res = Shell.getShell(mm).su("echo $SLOT");
if (isValidShellResponse(res)) {
options.add(mm.getString(R.string.install_second_slot));
}
char[] slot = isValidShellResponse(res) ? res.get(0).toCharArray() : null;
new AlertDialog.Builder(fragment.getActivity())
.setTitle(R.string.select_method)
.setItems(
options.toArray(new String [0]),
(dialog, idx) -> {
String boot;
DownloadReceiver receiver = null;
switch (idx) {
case 1:
if (mm.remoteMagiskVersionCode < 1400) {
mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG);
return;
}
mm.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
fragment.startActivityForResult(intent, SELECT_BOOT_IMG,
(requestCode, resultCode, data) -> {
if (requestCode == SELECT_BOOT_IMG
&& resultCode == Activity.RESULT_OK && data != null) {
dlAndReceive(
fragment.getActivity(),
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, data.getData())
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT);
mm.startActivity(intent);
}
},
mm.magiskLink,
filename
);
}
});
return;
case 0:
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
showUriSnack(fragment.getActivity(), uri);
}
};
break;
case 2:
boot = fragment.getSelectedBootImage();
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, boot)
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
mm.startActivity(intent);
}
};
break;
case 3:
assert (slot != null);
// Choose the other slot
if (slot[1] == 'a') slot[1] = 'b';
else slot[1] = 'a';
// Then find the boot image again
List<String> ret = Shell.getShell(mm).su(
"BOOTIMAGE=",
"SLOT=" + String.valueOf(slot),
"find_boot_image",
"echo \"$BOOTIMAGE\""
);
boot = isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null;
Shell.getShell(mm).su_raw("mount_partitions");
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, boot)
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
mm.startActivity(intent);
}
};
default:
}
Utils.dlAndReceive(
fragment.getActivity(),
receiver,
mm.magiskLink,
filename
);
}
).show();
})
.setNeutralButton(R.string.release_notes, (d, i) -> {
if (mm.releaseNoteLink != null) {
Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink));
openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mm.startActivity(openLink);
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
public static void showManagerInstallDialog(Activity activity) {
MagiskManager mm = Utils.getMagiskManager(activity);
new AlertDialogBuilder(activity)
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.app_name)))
.setMessage(mm.getString(R.string.repo_install_msg,
Utils.getLegalFilename("MagiskManager-v" +
mm.remoteManagerVersionString + ".apk")))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(MagiskManager.INTENT_LINK, mm.managerLink);
intent.putExtra(MagiskManager.INTENT_VERSION, mm.remoteManagerVersionString);
mm.sendBroadcast(intent);
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
public static void showUninstallDialog(MagiskFragment fragment) {
MagiskManager mm = Utils.getMagiskManager(fragment.getActivity());
new AlertDialogBuilder(fragment.getActivity())
.setTitle(R.string.uninstall_magisk_title)
.setMessage(R.string.uninstall_magisk_msg)
.setPositiveButton(R.string.complete_uninstall, (d, i) -> {
try {
InputStream in = mm.getAssets().open(UNINSTALLER);
File uninstaller = new File(mm.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();
in = mm.getAssets().open(UTIL_FUNCTIONS);
File utils = new File(mm.getCacheDir(), UTIL_FUNCTIONS);
out = new FileOutputStream(utils);
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.close();
Shell.getShell(mm).su(
"cat " + uninstaller + " > /cache/" + UNINSTALLER,
"cat " + utils + " > /data/magisk/" + UTIL_FUNCTIONS
);
mm.toast(R.string.uninstall_toast, Toast.LENGTH_LONG);
Shell.getShell(mm).su_raw(
"sleep 5",
"pm uninstall " + mm.getApplicationInfo().packageName
);
} catch (IOException e) {
e.printStackTrace();
}
})
.setNeutralButton(R.string.restore_stock_boot, (d, i) -> {
String boot = fragment.getSelectedBootImage();
if (boot == null) return;
new RestoreStockBoot(mm, boot).exec();
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
public static boolean useFDE(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& context.getSystemService(DevicePolicyManager.class).getStorageEncryptionStatus()
== DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
}
public static Context getEncContext(Context context) {
if (useFDE(context))
return context.createDeviceProtectedStorageContext();
else
return context;
}
}

View File

@@ -1,6 +1,8 @@
package com.topjohnwu.magisk.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
@@ -14,36 +16,32 @@ public class WebService {
public final static int GET = 1;
public final static int POST = 2;
/**
* Making web service call
*
* @url - url to make request
* @requestmethod - http request method
*/
public static String request(String url, int method) {
return request(url, method, null, true);
public static String getString(String url) {
return getString(url, null);
}
public static String request(String url, int method, boolean newline) {
return request(url, method, null, newline);
}
/**
* Making service call
*
* @url - url to make request
* @requestmethod - http request method
* @params - http request params
* @header - http request header
* @newline - true to append a newline each line
*/
public static String request(String urlAddress, int method,
Map<String, String> header, boolean newline) {
Logger.dev("WebService: Service call " + urlAddress);
URL url;
StringBuilder response = new StringBuilder();
public static String getString(String url, Map<String, String> header) {
InputStream in = request(GET, url, header);
if (in == null) return "";
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int len;
StringBuilder builder = new StringBuilder();
char buf[] = new char[4096];
try {
url = new URL(urlAddress);
while ((len = br.read(buf)) != -1) {
builder.append(buf, 0, len);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
return builder.toString();
}
public static InputStream request(int method, String address, Map<String, String> header) {
Logger.dev("WebService: Service call " + address);
try {
URL url = new URL(address);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(15000);
@@ -62,18 +60,7 @@ public class WebService {
}
}
int responseCode = conn.getResponseCode();
if (responseCode == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = br.readLine()) != null) {
if (newline) {
response.append(line).append("\n");
} else {
response.append(line);
}
}
if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK) {
if (header != null) {
header.clear();
for (Map.Entry<String, List<String>> entry : conn.getHeaderFields().entrySet()) {
@@ -81,12 +68,12 @@ public class WebService {
header.put(entry.getKey(), l.get(l.size() - 1));
}
}
return conn.getInputStream();
}
} catch (Exception e) {
e.printStackTrace();
}
return response.toString();
return null;
}
}

View File

@@ -1,26 +1,29 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.text.TextUtils;
import org.spongycastle.asn1.ASN1InputStream;
import org.spongycastle.asn1.ASN1ObjectIdentifier;
import org.spongycastle.asn1.DEROutputStream;
import org.spongycastle.asn1.cms.CMSObjectIdentifiers;
import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
import org.spongycastle.cert.jcajce.JcaCertStore;
import org.spongycastle.cms.CMSException;
import org.spongycastle.cms.CMSProcessableByteArray;
import org.spongycastle.cms.CMSSignedData;
import org.spongycastle.cms.CMSSignedDataGenerator;
import org.spongycastle.cms.CMSTypedData;
import org.spongycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.operator.ContentSigner;
import org.spongycastle.operator.OperatorCreationException;
import org.spongycastle.operator.jcajce.JcaContentSignerBuilder;
import org.spongycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.spongycastle.util.encoders.Base64;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.CMSTypedData;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
import org.bouncycastle.util.encoders.Base64;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -65,10 +68,14 @@ public class ZipUtils {
// File name in assets
private static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
private static final String PRIVATE_KEY_NAME = "private.key.pk8";
private static final String UNHIDE_APK = "unhide.apk";
private static final String CERT_SF_NAME = "META-INF/CERT.SF";
private static final String CERT_SIG_NAME = "META-INF/CERT.%s";
private static final String ANDROID_MANIFEST = "AndroidManifest.xml";
private static final byte[] UNHIDE_PKG_NAME = "com.topjohnwu.unhide\0".getBytes();
private static Provider sBouncyCastleProvider;
// bitmasks for which hash algorithms we need the manifest to include.
private static final int USE_SHA1 = 1;
@@ -82,10 +89,67 @@ public class ZipUtils {
public native static void zipAdjust(String filenameIn, String filenameOut);
public static String generateUnhide(Context context, File output) {
File temp = new File(context.getCacheDir(), "temp.apk");
String pkg = "";
try {
JarInputStream source = new JarInputStream(context.getAssets().open(UNHIDE_APK));
JarOutputStream dest = new JarOutputStream(new FileOutputStream(temp));
JarEntry entry;
int size;
byte buffer[] = new byte[4096];
while ((entry = source.getNextJarEntry()) != null) {
dest.putNextEntry(new JarEntry(entry.getName()));
if (TextUtils.equals(entry.getName(), ANDROID_MANIFEST)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while((size = source.read(buffer)) != -1) {
baos.write(buffer, 0, size);
}
int offset = -1;
byte xml[] = baos.toByteArray();
// Linear search pattern offset
for (int i = 0; i < xml.length - UNHIDE_PKG_NAME.length; ++i) {
boolean match = true;
for (int j = 0; j < UNHIDE_PKG_NAME.length; ++j) {
if (xml[i + j] != UNHIDE_PKG_NAME[j]) {
match = false;
break;
}
}
if (match) {
offset = i;
break;
}
}
if (offset < 0)
return "";
// Patch binary XML with new package name
pkg = Utils.genPackageName("com.", UNHIDE_PKG_NAME.length - 1);
System.arraycopy(pkg.getBytes(), 0, xml, offset, pkg.length());
dest.write(xml);
} else {
while((size = source.read(buffer)) != -1) {
dest.write(buffer, 0, size);
}
}
}
source.close();
dest.close();
signZip(context, temp, output, false);
temp.delete();
} catch (IOException e) {
e.printStackTrace();
return pkg;
}
return pkg;
}
public static void removeTopFolder(InputStream in, File output) throws IOException {
try {
JarInputStream source = new JarInputStream(in);
JarOutputStream dest = new JarOutputStream(new FileOutputStream(output));
JarOutputStream dest = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output)));
JarEntry entry;
String path;
int size;
@@ -98,11 +162,11 @@ public class ZipUtils {
continue;
}
// Don't include placeholder
if (path.contains("system/placeholder")) {
if (path.equals("system/placeholder")) {
continue;
}
dest.putNextEntry(new JarEntry(path));
while((size = source.read(buffer, 0, 2048)) != -1) {
while((size = source.read(buffer)) != -1) {
dest.write(buffer, 0, size);
}
}
@@ -115,34 +179,38 @@ public class ZipUtils {
}
}
public static void unzip(File file, File folder, String path) throws Exception {
int count;
FileOutputStream out;
File dest;
InputStream is;
JarEntry entry;
public static void unzip(File zip, File folder, String path, boolean junkPath) throws Exception {
InputStream in = new BufferedInputStream(new FileInputStream(zip));
unzip(in, folder, path, junkPath);
in.close();
}
public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception {
byte data[] = new byte[4096];
try (JarFile zipfile = new JarFile(file)) {
Enumeration<JarEntry> e = zipfile.entries();
while(e.hasMoreElements()) {
entry = e.nextElement();
if (!entry.getName().contains(path) || entry.isDirectory()){
try {
JarInputStream zipfile = new JarInputStream(zip);
JarEntry entry;
while ((entry = zipfile.getNextJarEntry()) != null) {
if (!entry.getName().startsWith(path) || entry.isDirectory()){
// Ignore directories, only create files
continue;
}
Logger.dev("ZipUtils: Extracting: " + entry);
is = zipfile.getInputStream(entry);
dest = new File(folder, entry.getName());
if (dest.getParentFile().mkdirs()) {
dest.createNewFile();
String name;
if (junkPath) {
name = entry.getName().substring(entry.getName().lastIndexOf('/') + 1);
} else {
name = entry.getName();
}
out = new FileOutputStream(dest);
while ((count = is.read(data)) != -1) {
Logger.dev("ZipUtils: Extracting: " + entry);
File dest = new File(folder, name);
dest.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(dest);
int count;
while ((count = zipfile.read(data)) != -1) {
out.write(data, 0, count);
}
out.flush();
out.close();
is.close();
}
} catch(Exception e) {
e.printStackTrace();
@@ -153,7 +221,7 @@ public class ZipUtils {
public static void signZip(Context context, File input, File output, boolean minSign) {
int alignment = 4;
JarFile inputJar = null;
FileOutputStream outputFile = null;
BufferedOutputStream outputFile = null;
int hashes = 0;
try {
X509Certificate publicKey = readPublicKey(context.getAssets().open(PUBLIC_KEY_NAME));
@@ -165,7 +233,7 @@ public class ZipUtils {
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
PrivateKey privateKey = readPrivateKey(context.getAssets().open(PRIVATE_KEY_NAME));
outputFile = new FileOutputStream(output);
outputFile = new BufferedOutputStream(new FileOutputStream(output));
if (minSign) {
ZipUtils.signWholeFile(input, publicKey, privateKey, outputFile);
} else {

View File

@@ -383,6 +383,7 @@
android:layout_marginTop="4dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
android:visibility="gone"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation">
@@ -399,7 +400,7 @@
android:id="@+id/imageView"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_marginEnd="5dp"
android:layout_weight="0"
app:srcCompat="@mipmap/ic_launcher" />
@@ -411,6 +412,7 @@
android:ems="10"
android:fontFamily="sans-serif"
android:gravity="center"
android:text="@string/install"
android:textAllCaps="false"
android:textSize="20sp"
android:textStyle="bold" />
@@ -418,7 +420,7 @@
<FrameLayout
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginStart="5dp"
android:layout_weight="0">
</FrameLayout>

View File

@@ -1,23 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="@+id/arrow"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:src="@drawable/ic_arrow"
android:id="@+id/arrow"
android:layout_marginEnd="10dp" />
android:layout_marginEnd="10dp"
android:src="@drawable/ic_arrow" />
<TextView
android:text="2017/1/1"
android:id="@+id/date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/date"
android:textColor="?android:attr/textColorPrimary"
android:gravity="center_vertical"
android:text="2017/1/1"
android:textAppearance="?android:attr/textAppearanceSmall"
android:gravity="center_vertical" />
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>

View File

@@ -2,40 +2,28 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">فتح درج التنقل</string>
<string name="navigation_drawer_close">إغلاق درج التنقل</string>
<string name="modules">الإضافات</string>
<string name="downloads">التنزيلات</string>
<string name="superuser">Superuser</string>
<string name="log">السجل</string>
<string name="settings">الإعدادات</string>
<string name="status">الحالة</string>
<string name="install">التثبيت</string>
<!--Status Fragment-->
<string name="magisk_version">المثبت Magisk v%1$s</string>
<string name="magisk_version_core_only">المثبت Magisk v%1$s (الوضع الأساسي فقط)</string>
<string name="magisk_version_error">Magisk غير مثبت</string>
<string name="checking_for_updates">البحث عن تحديثات…</string>
<string name="magisk_update_available">Magisk v%1$s متاح!</string>
<string name="cannot_check_updates">لا يمكن التحقق من التحديثات، لا يوجد إنترنت؟</string>
<string name="up_to_date">تم تثبيت أحدث إصدار من %1$s</string>
<string name="root_error">مروت لكن لا يوجد إذن الروت، غير مسموح به؟</string>
<string name="not_rooted">غير مروت</string>
<string name="proper_root">مروت فعلاً</string>
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
<string name="safetyNet_connection_failed">لا يمكن الاتصال بـ Google API</string>
<string name="safetyNet_connection_suspended">تم تعليق الاتصال بـ Google API</string>
<string name="safetyNet_no_response">لا يمكن التحقق من SafetyNet، لا يوجد إنترنت؟</string>
<string name="safetyNet_fail">فشل SafetyNet: عدم تطابق التشكيل الجانبي CTS</string>
<string name="safetyNet_pass">SafetyNet تخطى</string>
<string name="safetyNet_network_loss">فقدان الاتصال بالشبكة</string>
<string name="safetyNet_service_disconnected">تم إنهاء الخدمة</string>
<string name="safetyNet_res_invalid">الاستجابة غير صالحه</string>
<string name="root_info_warning">وظائف محدودة إلى حد كبير</string>
<!--Install Fragment-->
<string name="auto_detect">(تلقائي) %1$s</string>
@@ -50,8 +38,6 @@
<string name="uninstall">إلغاء التثبيت</string>
<string name="reboot_countdown">إعادة التشغيل في %1$d</string>
<string name="uninstall_magisk_title">إلغاء تثبيت Magisk</string>
<string name="uninstall_magisk_msg">سيؤدي هذا إلى إزالة جميع الإضافات، MagiskSU، وربما تشفير البيانات الخاصة بك إذا لم يتم تشفيرها\nهل أنت متأكد من الاستمرار؟</string>
<string name="version_none">(بدون)</string>
<!--Module Fragment-->
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
@@ -62,7 +48,6 @@
<string name="disable_file_created">سيتم تعطيل الإضافة في إعادة التشغيل التالي</string>
<string name="disable_file_removed">سيتم تمكين الإضافة في إعادة التشغيل التالي</string>
<string name="author">انشئ بواسطة %1$s</string>
<string name="fab_flash_zip">تثبيت الملف المضغوط للإضافة</string>
<!--Repo Fragment-->
<string name="update_available">يتوفر تحديث</string>
@@ -97,32 +82,18 @@
<string name="close">إغلاق</string>
<string name="repo_install_title">تثبيت %1$s</string>
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
<string name="download_install">التنزيل &amp; التثبيت</string>
<string name="download">التنزيل</string>
<string name="goto_install">انتقل إلى قسم \"التثبيت\"</string>
<string name="download_file_error">خطأ تنزيل الملف</string>
<string name="install_error">خطأ في التثبيت!</string>
<string name="invalid_zip">الملف المضغوط ليس إضافة Magisk!!</string>
<string name="reboot_title">التثبيت نجح!</string>
<string name="reboot_msg">هل تريد إعادة التشغيل الآن؟</string>
<string name="reboot">إعادة التشغيل</string>
<string name="copying_msg">نسخ الملف المضغوط إلى دليل مؤقت</string>
<string name="zip_install_progress_title">التثبيت</string>
<string name="zip_unzip_msg">فك الضغط عن الملف المضغوط …</string>
<string name="zip_process_msg">معالجة الملف المضغوط …</string>
<string name="zip_install_progress_msg">تثبيت %1$s …</string>
<string name="no_magisk_title">لا يوجد Magisk مثبت!</string>
<string name="no_magisk_msg">هل ترغب في تنزيل وتثبيت Magisk؟</string>
<string name="downloading_toast">جاري التنزيل %1$s</string>
<string name="magisk_update_title">تحديث Magisk جديد متوفر!</string>
<string name="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
<string name="release_notes">ملاحظات الإصدار</string>
<string name="repo_cache_cleared">تم مسح الذاكرة المؤقته للمستودع</string>
<string name="safetyNet_hide_notice">يستخدم هذا التطبيق SafetyNet, تم التعامل معها بالفعل من قبل MagiskHide بشكل افتراضي</string>
<string name="start_magiskhide">بدءا إخفاء Magisk …</string>
<string name="no_magisksu_title">لا تستخدم MagiskSU!</string>
<string name="no_magisksu_msg">غير مروت بأستخدام MagiskSU, إستخدام Magisk أخفاء لوحده قد لا يكون كافياً!\nانه غير معتمدة رسمياً, وأنت بحاجه إلى أدوات اضافيه (مثلاً suhide) لتخطي SafetyNet.</string>
<string name="understand">أنا أفهم</string>
<string name="process_error">خطأ في العملية</string>
<string name="internal_storage">يتم تخزين الملف المضغوط في:\n[التخزين الداخلي]%1$s</string>
<string name="zip_process_title">معالجة</string>
@@ -140,8 +111,6 @@
<string name="settings_core_only_title">Magisk الوضع الأساسي فقط</string>
<string name="settings_core_only_summary">تمكين الميزات الأساسية فقط، لن يتم تحميل جميع الإضافات. MagiskSU، MagiskHide، systemless hosts، و لا يزال ممكنا</string>
<string name="settings_magiskhide_summary">إخفاء Magisk من مختلف الاكتشافات</string>
<string name="settings_busybox_title">تفعيل BusyBox</string>
<string name="settings_busybox_summary">ربط تحميل Magisk\'s المدمج في busybox إلى xbin</string>
<string name="settings_hosts_title">تمكين المضيفين(الهوست) لـ systemless</string>
<string name="settings_hosts_summary">Systemless يدعم تطبيقات حجب الإعلانات</string>

View File

@@ -2,35 +2,24 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Otevřít postranní panel</string>
<string name="navigation_drawer_close">Zavřít postranní panel</string>
<string name="modules">Moduly</string>
<string name="downloads">Stahování</string>
<string name="superuser">Superuser</string>
<string name="log">Log</string>
<string name="settings">Nastavení</string>
<string name="status">Stav</string>
<string name="install">Instalovat</string>
<!--Status Fragment-->
<string name="magisk_version">Nainstalován Magisk v%1$s</string>
<string name="magisk_version_error">Magisk není nainstalován</string>
<string name="checking_for_updates">Kontrola aktualizací…</string>
<string name="magisk_update_available">Magisk v%1$s je dostupný!</string>
<string name="cannot_check_updates">Nelze zkontrolovat aktualizace. Jste připojeni k Internetu?</string>
<string name="up_to_date">Poslední verze z %1$s nainstalovaných</string>
<string name="root_error">Zařízení s rootem ale chybí root povolení, máte jej zpřístupněno?</string>
<string name="not_rooted">Nemáte root</string>
<string name="proper_root">Správně provedený root</string>
<string name="safetyNet_check_text">Kliknutím zahájíte SafetyNet kontrolu</string>
<string name="checking_safetyNet_status">Kontrola stavu SafetyNet…</string>
<string name="safetyNet_connection_failed">Nelze se spojit s Google API</string>
<string name="safetyNet_connection_suspended">Spojení s Google API bylo přerušeno</string>
<string name="safetyNet_no_response">Nelze zkontrolovat SafetyNet. Jste připojeni k Internetu?</string>
<string name="safetyNet_fail">SafetyNet dopadl neúspěšně: CTS profile mismatch</string>
<string name="safetyNet_pass">SafetyNet Schváleno</string>
<string name="root_info_warning">Funkčnost omezena</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -45,8 +34,6 @@
<string name="uninstall">Odinstalovat</string>
<string name="reboot_countdown">Restart za %1$d</string>
<string name="uninstall_magisk_title">Odinstalovat Magisk</string>
<string name="uninstall_magisk_msg">Tímto odstraníte veškeré moduly, MagiskSU a potencionálně zašifrujete svá data pokud ještě nejsou\nOpravdu chcete pokračovat?</string>
<string name="version_none">(Žádná)</string>
<!--Module Fragment-->
<string name="no_info_provided">(Žádné info)</string>
@@ -57,7 +44,6 @@
<string name="disable_file_created">Modul bude zakázán během příštího restartu</string>
<string name="disable_file_removed">Modul bude povolen během příštího restartu</string>
<string name="author">Vytvořeno %1$s</string>
<string name="fab_flash_zip">Flash Zip Modulu</string>
<!--Repo Fragment-->
<string name="update_available">Dostupná Aktualizace</string>
@@ -92,32 +78,18 @@
<string name="close">Zavřít</string>
<string name="repo_install_title">Instalovat %1$s</string>
<string name="repo_install_msg">Chcete nainstalovat %1$s ?</string>
<string name="download_install">Stažení &amp; Instalace</string>
<string name="download">Stáhnout</string>
<string name="goto_install">Jděte do sekce \"Instalovat\"</string>
<string name="download_file_error">Chyba při Stahování souboru</string>
<string name="install_error">Chyba při Instalaci!</string>
<string name="invalid_zip">Soubor zip není Magisk Modul!!</string>
<string name="reboot_title">Instalace proběhla úspěšně!</string>
<string name="reboot_msg">Chcete nyní restartovat vaše zařízení?</string>
<string name="reboot">Restart</string>
<string name="copying_msg">Kopírovat zip do temp adresáře</string>
<string name="zip_install_progress_title">Instalování</string>
<string name="zip_unzip_msg">Extrahování zip souboru …</string>
<string name="zip_process_msg">Zpracování zip souboru …</string>
<string name="zip_install_progress_msg">Instalování %1$s …</string>
<string name="no_magisk_title">Magisk není Nainstalován!</string>
<string name="no_magisk_msg">Chcete stáhnout a nainstalovat Magisk?</string>
<string name="downloading_toast">Stahování %1$s</string>
<string name="magisk_update_title">K dispozici je aktualizace Magisk!</string>
<string name="settings_reboot_toast">Restartovat pro použití nastavení</string>
<string name="release_notes">Poznámky k vydání</string>
<string name="repo_cache_cleared">Mezipaměť smazána</string>
<string name="safetyNet_hide_notice">Tato aplikace využívá SafetyNet\nVe výchozím nastavení již ovládaný skrze MagiskHide</string>
<string name="start_magiskhide">Spouštění MagiskHide …</string>
<string name="no_magisksu_title">Nepoužíváte MagiskSU!</string>
<string name="no_magisksu_msg">Nemáte root s MagiskSU, používání MagiskHide samotného nebude stačit!\nNení to oficiálně podporováno a potřebovali byste další nástroje (např. suhide) k prolomení Safety Net.</string>
<string name="understand">Rozumím</string>
<string name="process_error">Chyba při Zpracování</string>
<string name="internal_storage">Zip je uchován v:\n[Interním Úložišti]%1$s</string>
<string name="zip_process_title">Zpracování</string>
@@ -133,8 +105,6 @@
<string name="settings_clear_cache_summary">Smaže informace online použití v Mezipaměti, donutí aplikaci obnovit informace online</string>
<string name="settings_magiskhide_summary">Skryje root (MagiskSU) před různými aplikacemi</string>
<string name="settings_busybox_title">Povolit BusyBox</string>
<string name="settings_busybox_summary">Nasadí vestavěný Magisk busybox do xbin</string>
<string name="settings_hosts_title">Nesystémová "hosts" data</string>
<string name="settings_hosts_summary">Podpora nesystémových dat "hosts" pro Adblock aplikace</string>

View File

@@ -4,41 +4,29 @@
<!--Welcome Activity-->
<string name="navigation_drawer_open">Navigationsmenü öffnen</string>
<string name="navigation_drawer_close">Navigationsmenü schließen</string>
<string name="modules">Module</string>
<string name="downloads">Downloads</string>
<string name="superuser">Superuser</string>
<string name="log">Log</string>
<string name="settings">Einstellungen</string>
<string name="status">Status</string>
<string name="install">Installieren</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk %1$s ist installiert</string>
<string name="magisk_version_core_only">Magisk %1$s ist installiert (nur Kernfunktionen)</string>
<string name="magisk_version_error">Magisk ist nicht installiert</string>
<string name="checking_for_updates">Suche nach Updates…</string>
<string name="magisk_update_available">Magisk %1$s ist verfügbar!</string>
<string name="cannot_check_updates">Updatesuche fehlgeschlagen.\nIst eine Internetverbindung verfügbar?</string>
<string name="up_to_date">Die neueste Version von %1$s ist bereits installiert</string>
<string name="root_error">Gerootet, aber keine root-Rechte. Wurde der root-Zugriff verweigert?</string>
<string name="not_rooted">Nicht gerootet</string>
<string name="proper_root">Ordnungsgemäß gerootet</string>
<string name="safetyNet_check_text">SafetyNet-Status abfragen</string>
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status…</string>
<string name="safetyNet_check_success">SafetyNet-Test erfolgreich</string>
<string name="safetyNet_connection_failed">Verbindung zur Google-API fehlgeschlagen</string>
<string name="safetyNet_connection_suspended">Verbindung zur Google-API wurde ausgesetzt</string>
<string name="safetyNet_no_response">SafetyNet-Status konnte nicht geprüft werden. Ist eine Internetverbindung verfügbar?</string>
<string name="safetyNet_fail">SafetyNet nicht bestanden: \"CTS profile mismatch\"</string>
<string name="safetyNet_pass">SafetyNet bestanden</string>
<string name="safetyNet_network_loss">Netzwerkverbindung verloren</string>
<string name="safetyNet_service_disconnected">Der Dienst wurde beendet</string>
<string name="safetyNet_res_invalid">Die Antwort ist ungültig</string>
<string name="root_info_warning">Funktionalität stark eingeschränkt</string>
<!--Install Fragment-->
<string name="auto_detect">%1$s (autom.)</string>
@@ -53,8 +41,6 @@
<string name="uninstall">Deinstallieren</string>
<string name="reboot_countdown">Neustart in %1$d</string>
<string name="uninstall_magisk_title">Magisk deinstallieren</string>
<string name="uninstall_magisk_msg">Dies entfernt alle Module, MagiskSU und verschlüsselt unter Umständen deine Daten, falls nicht bereits verschlüsselt.\nMöchtest du wirklich fortfahren?</string>
<string name="version_none">(keine)</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nichts angegeben)</string>
@@ -65,7 +51,6 @@
<string name="disable_file_created">Modul wird beim nächsten Neustart deaktiviert</string>
<string name="disable_file_removed">Modul wird beim nächsten Neustart aktiviert</string>
<string name="author">Erstellt von %1$s</string>
<string name="fab_flash_zip">Modul aus Zip-Datei flashen</string>
<!--Repo Fragment-->
<string name="update_available">Update verfügbar</string>
@@ -85,7 +70,7 @@
<string name="app_developers">Hauptentwickler</string>
<string name="app_developers_"><![CDATA[App entwickelt von <a href="https://github.com/topjohnwu">topjohnwu</a> unter Mitwirkung von <a href="https://github.com/d8ahazard">Digitalhigh</a> und <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Änderungen</string>
<string name="translators">skalnet, c727</string>
<string name="translators">skalnet, c727, jenslody</string>
<string name="app_version">Version</string>
<string name="app_source_code">Quelltext</string>
<string name="donation">Spende</string>
@@ -100,38 +85,35 @@
<string name="close">Schließen</string>
<string name="repo_install_title">Installiere %1$s</string>
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
<string name="download_install">Herunterladen &amp; installieren</string>
<string name="download">Herunterladen</string>
<string name="goto_install">Zu \"Installieren\" wechseln</string>
<string name="download_file_error">Fehler beim Herunterladen der Datei</string>
<string name="install_error">Fehler bei der Installation!</string>
<string name="invalid_zip">Die Zip-Datei ist kein Magisk-Modul!</string>
<string name="reboot_title">Installation erfolgreich!</string>
<string name="reboot_msg">Möchtest du jetzt neustarten?</string>
<string name="reboot">Neustart</string>
<string name="copying_msg">Kopiere Zip ins temp-Verzeichnis</string>
<string name="zip_install_progress_title">Installiere</string>
<string name="zip_unzip_msg">Entpacke Zip-Datei…</string>
<string name="zip_process_msg">Verarbeite Zip-Datei…</string>
<string name="zip_install_progress_msg">Installiere %1$s…</string>
<string name="no_magisk_title">Magisk ist nicht installiert!</string>
<string name="no_magisk_msg">Möchtest du Magisk herunterladen und installieren?</string>
<string name="downloading_toast">Herunterladen von %1$s</string>
<string name="magisk_update_title">Neues Magisk-Update verfügbar!</string>
<string name="settings_reboot_toast">Neustarten, um die Änderungen anzuwenden</string>
<string name="release_notes">Änderungen</string>
<string name="repo_cache_cleared">Repo-Cache gelöscht</string>
<string name="safetyNet_hide_notice">Diese App benutzt SafetyNet, welches standardmäßig von Magisk Hide gehandhabt</string>
<string name="start_magiskhide">Starte Magisk Hide…</string>
<string name="no_magisksu_title">Du benutzt nicht MagiskSU!</string>
<string name="no_magisksu_msg">Deine root-Lösung wird nicht offiziell unterstützt und Magisk Hide allein ist eventuell nicht ausreichend!\nEventuell benötigst du weitere Programme (z.B. \"suhide\"), um SafetyNet zu bestehen.</string>
<string name="understand">Ich verstehe</string>
<string name="process_error">Prozessfehler</string>
<string name="internal_storage">Die zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
<string name="zip_download_title">Herunterladen</string>
<string name="zip_download_msg">Lade Zip-Datei herunter…</string>
<string name="zip_process_title">Verarbeite</string>
<string name="zip_process_msg">Verarbeite Zip-Datei…</string>
<string name="manual_boot_image">Bitte Boot-Image auswählen!</string>
<string name="manager_update_title">Update für Magisk Manager verfügbar!</string>
<string name="manager_download_install">Herunterladen und installieren</string>
<string name="magisk_updates">Magisk Updates</string>
<string name="flashing">Flashing</string>
<string name="hide_manager_toast">Verberge Magisk Manager…</string>
<string name="hide_manager_fail_toast">Verbergen von Magisk Manager fehlgeschlagen…</string>
<string name="download_zip_only">Zip-Datei nur herunterladen</string>
<string name="patch_boot_file">Boot-Image-Datei patchen</string>
<string name="direct_install">Direkt installieren (empfohlen)</string>
<string name="select_method">Methode auswählen</string>
<string name="no_boot_file_patch_support">Magisk Zielversion unterstützt das Patchen des Boot-Images nicht</string>
<!--Settings Activity -->
<string name="settings_general_category">Allgemein</string>
@@ -141,12 +123,20 @@
<string name="settings_notification_summary">Benachrichtigung, wenn eine neue Version verfügbar ist</string>
<string name="settings_clear_cache_title">Repo-Cache löschen</string>
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen der Online-Repos. Erzwingt eine Aktualisierung</string>
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
<string name="settings_hide_manager_summary">Magisk Manager temporär verbergen.\nDies installiert eine neue App namens \"Unhide Magisk Manager\"</string>
<string name="language">Sprache</string>
<string name="system_default">(Systemstandard)</string>
<string name="settings_update">Update-Einstellungen</string>
<string name="settings_update_channel_title">Update-Kanal</string>
<string name="settings_update_stable">Stabil</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Ausgabeformat des gepatchten Boot-Images</string>
<string name="settings_boot_format_summary">Wähle das Ausgabeformat des gepatchten Boot-Images.\nWähle .img, um mit \"fastboot/download mode\" zu flashen; wähle .img.tar zum Flashen mit ODIN.</string>
<string name="settings_core_only_title">Nur Kernfunktionen</string>
<string name="settings_core_only_summary">Aktiviert lediglich die Kernfunktionen, Module werden nicht geladen. MagiskSU, Magisk Hide und Systemless hosts bleiben weiterhin aktiv</string>
<string name="settings_magiskhide_summary">Versteckt Magisk vor diversen Entdeckungsmethoden</string>
<string name="settings_busybox_title">BusyBox aktivieren</string>
<string name="settings_busybox_summary">Magisk\'s integriertes BusyBox nach xbin mounten</string>
<string name="settings_hosts_title">Systemlose hosts-Datei</string>
<string name="settings_hosts_summary">Systemlose Unterstützung für Werbeblocker</string>

View File

@@ -1,39 +1,27 @@
<resources>
<!--Welcome Activity-->
<string name="navigation_drawer_open">Άνοιγμα συρταριού πλοήγησης</string>
<string name="navigation_drawer_close">Κλείσιμο συρταριού πλοήγησης</string>
<string name="modules">Ενότητες</string>
<string name="downloads">Λήψεις</string>
<string name="superuser">Υπερχρήστης</string>
<string name="log">Aρχείο Kαταγραφής</string>
<string name="settings">Ρυθμίσεις</string>
<string name="status">Κατάσταση</string>
<string name="install">Εγκατάσταση</string>
<!--Status Fragment-->
<string name="magisk_version">Εγκατεστημένο Magisk v%1$s</string>
<string name="magisk_version_core_only">Εγκατεστημένο Magisk v%1$s (Λειτουργία Πυρήνα Μόνο)</string>
<string name="magisk_version_error">Το Magisk δεν είναι εγκατεστημένο</string>
<string name="checking_for_updates">Έλεγχος για ενημερώσεις…</string>
<string name="magisk_update_available">Το Magisk v%1$s είναι διαθέσιμο!</string>
<string name="cannot_check_updates">Αδυναμία ελέγχου για ενημερώσεις, δεν έχει Internet;</string>
<string name="up_to_date">Τελευταία έκδοση του %1$s εγκατεστημένη</string>
<string name="cannot_check_updates">Αδυναμία ελέγχου για ενημερώσεις, δεν έχει internet;</string>
<string name="root_error">Υπάρχει root αλλά όχι άδεια για root, δεν επιτρέπεται;</string>
<string name="not_rooted">Δεν υπάρχει root</string>
<string name="proper_root">Rooted κανονικά</string>
<string name="safetyNet_check_text">Πατήστε για έλεγχο του SafetyNet</string>
<string name="checking_safetyNet_status">Έλεγχος κατάστασης SafetyNet…</string>
<string name="safetyNet_check_success">Επιτυχημένος έλεγχος SafetyNet</string>
<string name="safetyNet_connection_failed">Αδυναμία σύνδεσης στο Google API</string>
<string name="safetyNet_connection_suspended">Η σύνδεση στο Google API διακόπηκε</string>
<string name="safetyNet_no_response">Αδυναμία ελέγχου SafetyNet, δεν έχει Internet;</string>
<string name="safetyNet_fail">Αποτυχία SafetyNet: CTS profile mismatch</string>
<string name="safetyNet_pass">Το SafetyNet Πέρασε</string>
<string name="safetyNet_network_loss">Χάθηκε η σύνδεση στο δίκτυο</string>
<string name="safetyNet_check_success">Ο Έλεγχος του SafetyNet Ήταν Επιτυχής</string>
<string name="safetyNet_no_response">Αδυναμία επαλήθευσης SafetyNet, δεν έχει internet;</string>
<string name="safetyNet_network_loss">Αδυναμία σύνδεσης στο δίκτυο</string>
<string name="safetyNet_service_disconnected">Η υπηρεσία τερματίστηκε</string>
<string name="safetyNet_res_invalid">Η απόκριση είναι άκυρη</string>
<string name="root_info_warning">Η λειτουργία είναι πολύ περιορισμένη</string>
<!--Install Fragment-->
<string name="auto_detect">(Αυτόματα) %1$s</string>
@@ -48,8 +36,7 @@
<string name="uninstall">Απεγκατάσταση</string>
<string name="reboot_countdown">Επανεκκίνηση σε %1$d</string>
<string name="uninstall_magisk_title">Απεγκατάσταση Magisk</string>
<string name="uninstall_magisk_msg">Αυτό θα αφαιρέσει όλες τις ενότητες, το MagiskSU και πιθανόν να κρυπτογραφύσει τα δεδομένα σας αν δεν είναι κρυπτογραφυμένα\nΕίστε σίγουρος/η ότι θέλετε να συνεχίσετε;</string>
<string name="version_none">(Καμία)</string>
<string name="update">Ενημέρωση %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Δεν δόθηκαν πληροφορίες)</string>
@@ -60,7 +47,6 @@
<string name="disable_file_created">Η ενότητα θα απενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="disable_file_removed">Η ενότητα θα ενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="author">Δημιουργήθηκε από τον/την %1$s</string>
<string name="fab_flash_zip">Flash Zip Ενότητας</string>
<!--Repo Fragment-->
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
@@ -94,40 +80,34 @@
<string name="ok">OK</string>
<string name="close">Κλείσιμο</string>
<string name="repo_install_title">Εγκατάσταση %1$s</string>
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε %1$s ;</string>
<string name="download_install">Κατέβασμα &amp; Εγκατάσταση</string>
<string name="download">Κατέβασμα</string>
<string name="goto_install">Μεταφορά στο τμήμα \"Εγκατάσταση\"</string>
<string name="download_file_error">Σφάλμα στο κατέβασμα του αρχείου</string>
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
<string name="download">Λήψη</string>
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
<string name="install_error">Σφάλμα εγκατάστασης!</string>
<string name="invalid_zip">Αυτό το zip δεν είναι Ενότητα Magisk!!</string>
<string name="reboot_title">Η εγκατάσταση πέτυχε!</string>
<string name="reboot_msg">Θέλετε να κάνετε επανεκκίνηση τώρα;</string>
<string name="reboot">Επανεκκίνηση</string>
<string name="copying_msg">Αντιγραφή zip στον προσωρινό κατάλογο</string>
<string name="zip_install_progress_title">Εγκατάσταση</string>
<string name="zip_unzip_msg">Αποσυμπίεση αρχείου zip …</string>
<string name="zip_process_msg">Επεξεργασία αρχείου zip …</string>
<string name="zip_install_progress_msg">Εγκατάσταση %1$s …</string>
<string name="no_magisk_title">Το Magisk δεν είναι εγκατεστημένο!</string>
<string name="no_magisk_msg">Θέλετε να κατεβάσετε και να εγκαταστήσετε το Magisk;</string>
<string name="downloading_toast">Κατέβασμα %1$s</string>
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
<string name="settings_reboot_toast">Επανεκκίνηση για εφαρμογή ρυθμίσεων</string>
<string name="release_notes">Σημειώσεις έκδοσης</string>
<string name="repo_cache_cleared">Η Repo cache καθαρίστηκε</string>
<string name="safetyNet_hide_notice">Αυτή η εφαρμογή χρησιμοποιεί SafetyNet\nΉδη διαχειρίζεται από το MagiskHide από προεπιλογή</string>
<string name="start_magiskhide">Εκκίνηση MagiskHide …</string>
<string name="no_magisksu_title">Δεν χρησιμοποιείται το MagiskSU!</string>
<string name="no_magisksu_msg">Δεν είστε rooted με το MagiskSU, η χρήση του MagiskHide μόνο μπορεί να μην είναι αρκετή!\nΔεν υποτηρίζεται επισήμως, και θα χρειαζόσασταν πρόσθετα εργαλεία (π.χ. suhide) για να περάσετε το Safety Net.</string>
<string name="understand">Καταλαβαίνω</string>
<string name="process_error">Σφάλμα διαδικασίας</string>
<string name="internal_storage">Το zip είναι αποθηκευμένο σε:\n[Εσωτερική μνήμη]%1$s</string>
<string name="zip_process_title">Επεξεργασία</string>
<string name="manual_boot_image">Παρακαλώ επιλέξτε χειροκίνητα μια εικόνα boot!</string>
<string name="manager_update_title">Νέα Ενημέρωση Magisk Manager Διαθέσιμη!</string>
<string name="manager_download_install">Πιέστε για κατέβασμα και εγκατάσταση</string>
<string name="manager_download_install">Πιέστε για λήψη και εγκατάσταση</string>
<string name="magisk_updates">Ενημερώσεις Magisk</string>
<string name="flashing">Γίνεται Flash</string>
<string name="hide_manager_toast">Κρύβοντας το Magisk Manager…</string>
<string name="hide_manager_fail_toast">Το κρύψιμο Magisk Manager απέτυχε…</string>
<string name="download_zip_only">Λήψη Zip Μόνο</string>
<string name="patch_boot_file">Εφαρμογή Patch στο Αρχείο Εικόνας Boot</string>
<string name="direct_install">Απευθείας Εγκατάσταση (Προτείνεται)</string>
<string name="select_method">Επιλογή Μεθόδου</string>
<!--Settings Activity -->
<string name="settings_general_category">Γενικά</string>
<string name="settings_dark_theme_title">Σκούρο θέμα</string>
@@ -136,12 +116,20 @@
<string name="settings_notification_summary">Εμφάνιση ειδοποιήσεων ενημέρωσης όταν είναι διαθέσιμη νέα έκδοση</string>
<string name="settings_clear_cache_title">Εκκαθάριση προσωρινής μνήμης αποθετηρίων</string>
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για απευθείας συνδεδεμένα αποθετήρια, αναγκάζει την εφαρμογή να κάνει ανανέωση σε απευθείας σύνδεση</string>
<string name="settings_hide_manager_title">Κρύψιμο Magisk Manager</string>
<string name="settings_hide_manager_summary">Προσωρινό κρύψιμο του Magisk Manager.\nΑυτό θα εγκαταστήσει μια νέα εφαρμογή με το όνομα \"Unhide Magisk Manager\"</string>
<string name="language">Γλώσσα</string>
<string name="system_default">(Προεπιλογή Συστήματος)</string>
<string name="settings_update">Ρυθμίσεις Ενημερώσεων</string>
<string name="settings_update_channel_title">Κανάλι Ενημερώσεων</string>
<string name="settings_update_stable">Σταθερή</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Μορφή Τροποποιημένης Εικόνας Boot</string>
<string name="settings_boot_format_summary">Επιλέξτε τη μορφή της εξαγόμενης εικόνας boot μετά το patch.\nΕπιλέξτε .img για flash μέσω λειτουργίας fastboot/download· επιλέξτε .img.tar για flash μέσω ODIN.</string>
<string name="settings_core_only_title">Magisk Λειτουργία Πυρήνα Μόνο</string>
<string name="settings_core_only_summary">Ενεργοποίηση μόνο των λειτουργιών πυρήνα, καμία από τις ενότητες δεν θα ενεργοποιηθεί. Τα MagiskSU, MagiskHide, και systemless hosts θα παραμείνουν ενεργά</string>
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
<string name="settings_busybox_title">Ενεργοποίηση BusyBox</string>
<string name="settings_busybox_summary">Υποχρεωτική προσάρτηση του ενσωματωμένου busybox του Magisk στο xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
@@ -158,8 +146,8 @@
<string name="request_timeout">Χρονικό όριο Αιτήματος</string>
<string name="superuser_notification">Ειδοποίηση Υπερχρήστη</string>
<string name="request_timeout_summary">%1$s δευτερόλεπτα</string>
<string name="settings_su_reauth_title">Επανα-πιστοποίηση μετά από αναβάθμιση</string>
<string name="settings_su_reauth_summary">Επανα-πιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
<string name="settings_su_reauth_title">Επαναπιστοποίηση μετά από αναβάθμιση</string>
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
<string name="multiuser_mode">Λειτουργία Πολλών Χρηστών</string>
<string name="settings_owner_only">Μόνο Ιδιοκτήτης Συσκευής</string>
@@ -197,8 +185,8 @@
<string name="twentymin">20 λεπτά</string>
<string name="thirtymin">30 λεπτά</string>
<string name="sixtymin">60 λεπτά</string>
<string name="su_allow_toast">Στο %1$s παραχορούνται δικαιώματα υπερχρήστη</string>
<string name="su_deny_toast">Στο %1$s απορρίπτονται τα δικαιώματα υπερχρήστη</string>
<string name="su_allow_toast">Παραχωρήθηκαν δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_deny_toast">Απορρίφθηκαν τα δικαιώματα υπερχρήστη του %1$s</string>
<string name="no_apps_found">Δεν βρέθηκαν εφαρμογές</string>
<string name="su_snack_grant">Παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_snack_deny">Δεν παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>

View File

@@ -2,38 +2,32 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Abrir menú de navegación</string>
<string name="navigation_drawer_close">Cerrar menú de navegación</string>
<string name="modules">Módulos</string>
<string name="downloads">Descargas</string>
<string name="superuser">Superusuario</string>
<string name="log">Registro</string>
<string name="settings">Ajustes</string>
<string name="status">Estado</string>
<string name="install">Instalar</string>
<!--Magisk Fragment-->
<string name="magisk_version">Instalado Magisk v%1$s</string>
<string name="magisk_version_error">Magisk no está instalado</string>
<string name="checking_for_updates">Comprobando actualizaciones…</string>
<string name="magisk_update_available">¡Disponible Magisk v%1$s!</string>
<string name="cannot_check_updates">No se pueden comprobar actualizaciones ¿No tiene internet?</string>
<string name="up_to_date">Última versión de %1$s instalada</string>
<string name="root_error">Rooteado pero sin permiso root, ¿No lo permitiste?</string>
<string name="not_rooted">No rooteado</string>
<string name="proper_root">Correctamente rooteado</string>
<string name="safetyNet_check_text">Toque para empezar la comprobación de SafetyNet</string>
<string name="checking_safetyNet_status">Comprobando estado de SafetyNet…</string>
<string name="safetyNet_connection_failed">No puede conectar con la API de Google</string>
<string name="safetyNet_connection_suspended">La conexión con la API de Google API fue suspendida</string>
<string name="safetyNet_check_success">La comprobación de SafetyNet fue exitosa</string>
<string name="safetyNet_no_response">No puede comprobar SafetyNet, ¿No tiene internet?</string>
<string name="safetyNet_fail">SafetyNet: Error, no coincide el perfil CTS</string>
<string name="safetyNet_pass">SafetyNet: Correcto</string>
<string name="root_info_warning">Funcionalidad enormemente limitada</string>
<string name="safetyNet_network_loss">Conexión de red perdida</string>
<string name="safetyNet_service_disconnected">Se ha detenido el servicio</string>
<string name="safetyNet_res_invalid">La respuesta no es válida</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(No se puede detectar automáticamente)</string>
<string name="boot_image_title">Ubicación de la imagen boot</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Ajustes avanzados</string>
@@ -43,7 +37,10 @@
<string name="install_magisk_title">Última versión de Magisk: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="reboot_countdown">Reiniciando en %1$d</string>
<string name="uninstall_magisk_msg">Todos los módulos serán desactivados / eliminados. El acceso Root se eliminará y, posiblemente, encriptará los datos si los datos no están cifrados actualmente.</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="update">Actualización %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(No hay información)</string>
<string name="no_modules_found">No se han encontrado módulos</string>
@@ -53,7 +50,6 @@
<string name="disable_file_created">El módulo se desactivará en el siguiente reinicio</string>
<string name="disable_file_removed">El módulo se activará en el siguiente reinicio</string>
<string name="author">Creado por %1$s</string>
<string name="fab_flash_zip">Flashear el zip del módulo</string>
<!--Repo Fragment-->
<string name="update_available">Actualización disponible</string>
@@ -70,7 +66,7 @@
<!--About Activity-->
<string name="about">Acerca de</string>
<string name="app_developers">Desarroladores principales</string>
<string name="app_developers">Desarrolladores principales</string>
<string name="app_developers_"><![CDATA[Aplicación creada por <a href="https://github.com/topjohnwu">topjohnwu</a> en colaboración con <a href="https://github.com/d8ahazard">Digitalhigh</a> y <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Registro de cambios de la aplicación</string>
<string name="translators">Gawenda, netizen, Deiki, Nosi>, dark-basic</string>
@@ -87,48 +83,64 @@
<string name="ok">Aceptar</string>
<string name="close">Cerrar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">¿ Quieres instalar %1$s ?</string>
<string name="download_install">Descargar e instalar</string>
<string name="repo_install_msg">¿Quieres instalar %1$s ahora?</string>
<string name="download">Descargar</string>
<string name="goto_install">Ir a la sección \"Instalar\"</string>
<string name="download_file_error">Error descargando archivo</string>
<string name="install_error">¡Error en la instalación!</string>
<string name="invalid_zip">¡El zip no es un módulo Magisk!</string>
<string name="reboot_title">¡Instalación correcta!</string>
<string name="reboot_msg">¿Deseas reiniciar ahora?</string>
<string name="reboot">Reiniciar</string>
<string name="copying_msg">Copiando zip a un directorio temporal</string>
<string name="zip_install_progress_title">Instalando</string>
<string name="zip_unzip_msg">Descomprimiendo archivo zip …</string>
<string name="zip_process_msg">Procesando archivo zip …</string>
<string name="zip_install_progress_msg">Instalando %1$s …</string>
<string name="no_magisk_title">¡Magisk no instalado!</string>
<string name="no_magisk_msg">¿Deseas descargar e instalar Magisk?</string>
<string name="downloading_toast">Descargando %1$s</string>
<string name="magisk_update_title">¡Nueva actualización de Magisk disponible!</string>
<string name="settings_reboot_toast">Reinicia para aplicar los ajustes</string>
<string name="release_notes">Notas de lanzamiento</string>
<string name="repo_cache_cleared">Caché del repositorio limpiada</string>
<string name="safetyNet_hide_notice">Esta aplicación usa SafetyNet\nYa manejado por defecto por MagiskHide</string>
<string name="start_magiskhide">Iniciando MagiskHide …</string>
<string name="no_magisksu_title">¡No está usando MagiskSU!</string>
<string name="no_magisksu_msg">No estás rooteado con MagiskSU, ¡Usando MagiskHide por si mismo podría no ser suficiente!\nNo está oficialmente soportado, y necesitaria herramientas adiccionales (ej. suhide) para pasar Safety Net.</string>
<string name="understand">Entendido</string>
<string name="process_error">Error de proceso</string>
<string name="internal_storage">El zip es almacenado en:\n[Internal Storage]%1$s</string>
<string name="zip_download_title">Descargando</string>
<string name="zip_download_msg">Descargando el archivo zip …</string>
<string name="zip_process_title">Procesando</string>
<string name="manual_boot_image">¡Selecciona manualmente una imagen boot!</string>
<string name="manager_update_title">Nueva actualización de Magisk Manager disponible!</string>
<string name="manager_download_install">Pulse para descargar e instalar</string>
<string name="magisk_updates">Actualización de Magisk</string>
<string name="flashing">Flasheando</string>
<string name="hide_manager_toast">Ocultando Magisk Manager...</string>
<string name="hide_manager_fail_toast">La Ocultación de Magisk Manager ha fallado…</string>
<string name="download_zip_only">Descargar sólo el archivo ZIP</string>
<string name="patch_boot_file">Parcheo de la imagen boot</string>
<string name="direct_install">Instalación Directa (Recomendado)</string>
<string name="install_second_slot">Instalación en el segundo espacio (Después de OTA)</string>
<string name="select_method">Seleccionar Método</string>
<string name="no_boot_file_patch_support">La versión de Magisk no admite el parcheo de la imagen boot</string>
<string name="boot_file_patch_msg">Seleccione el volcado de la imagen boot en formato .img o .img.tar</string>
<string name="complete_uninstall">Desinstalación completa</string>
<string name="restore_stock_boot">Restaurar imagen boot Stock</string>
<string name="restore_done">¡Restauración Terminada!</string>
<string name="restore_fail">¡El respaldo de la imagen boot Stock no existe!</string>
<string name="uninstall_toast">Desinstalación de Magisk Manager en 5 segundos, por favor después reinicie manualmente </string>
<!--Settings Activity -->
<string name="settings_general_category">General</string>
<string name="settings_dark_theme_title">Tema oscuro</string>
<string name="settings_dark_theme_summary">Habilita el tema oscuro</string>
<string name="settings_dark_theme_summary">Habilitar el tema oscuro</string>
<string name="settings_notification_title">Notificar Actualización</string>
<string name="settings_notification_summary">Notificar cuando una nueva versión esté disponible</string>
<string name="settings_clear_cache_title">Limpiar caché del repositorio</string>
<string name="settings_clear_cache_summary">Limpiar la información en caché para los repositorios en línea, fuerza a la aplicación a actualizar en línea</string>
<string name="settings_core_only_title">Magisk Modo Sólo Núcleo</string>
<string name="settings_core_only_summary">Habilitar sólo funciones principales, no se cargarán todos los módulos. MagiskSU, MagiskHide, y hosts fuera de la partición de sistema seguiran habilitados</string>
<string name="settings_hide_manager_title">Ocultar Magisk Manager</string>
<string name="settings_hide_manager_summary">Ocultar temporalmente Magisk Manager.\nEsto instalará una nueva aplicación llamada \"Unhide Magisk Manager\"</string>
<string name="language">Idioma</string>
<string name="system_default">(Idioma del sistema)</string>
<string name="settings_update">Ajustes de Actualización</string>
<string name="settings_update_channel_title">Canal de Actualización</string>
<string name="settings_update_stable">Estable</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Parchear imagen boot por tipo de formato</string>
<string name="settings_boot_format_summary">Seleccionar el formato de salida para parchear la imagen boot.\nEscoja .img para flashear mediante fastboot/download mode; escoja .img.tar para flashear con ODIN.</string>
<string name="settings_core_only_summary">Habilitar sólo funciones principales, no se cargarán todos los módulos. MagiskSU, MagiskHide, y archivo hosts fuera de la partición de sistema seguirán habilitados</string>
<string name="settings_magiskhide_summary">Ocultar Magisk de varias detecciones</string>
<string name="settings_hosts_title">Habilitar archivo hosts fuera de la partición de sistema</string>
<string name="settings_hosts_summary">Soporte para aplicaciones de bloqueo de publicidad fuera de la partición de sistema</string>
@@ -147,16 +159,16 @@
<string name="superuser_notification">Notificación de superusuario</string>
<string name="request_timeout_summary">%1$s segundos</string>
<string name="settings_su_reauth_title">Re-autenticación</string>
<string name="settings_su_reauth_summary">Pedir permisos de superusuario nuevamente si una aplicación es actualizada</string>
<string name="settings_su_reauth_summary">Pedir permisos de superusuario nuevamente si una aplicación es actualizada o reinstalada</string>
<string name="multiuser_mode">Modo MultiUsuario</string>
<string name="settings_owner_only">Solo propietario del dispositivo</string>
<string name="settings_owner_manage">Administrador del dispositivo</string>
<string name="settings_owner_only">Sólo Administrador del Dispositivo</string>
<string name="settings_owner_manage">Administrador del Dispositivo</string>
<string name="settings_user_independent">Usuario Independiente</string>
<string name="owner_only_summary">Sólo el propietario tiene acceso root</string>
<string name="owner_manage_summary">Sólo el administrador puede supervisar el acceso root y recibir solicitudes</string>
<string name="owner_only_summary">Sólo el administrador tiene acceso root</string>
<string name="owner_manage_summary">Sólo el administrador puede supervisar el acceso root y recibir solicitudes de otros usuarios</string>
<string name="user_indepenent_summary">Cada usuario tiene separadas sus propias reglas de root </string>
<string name="multiuser_hint_owner_request">Se ha enviado una solicitud al propietario del dispositivo. Por favor, cambie a la sesión del propietario y conceda el permiso</string>
<string name="multiuser_hint_owner_request">Se ha enviado una solicitud al administrador del dispositivo. Por favor, cambie a la cuenta del administrador y conceda el permiso</string>
<string name="mount_namespace_mode">Montar Namespace </string>
<string name="settings_ns_global">Global Namespace</string>

View File

@@ -1,38 +1,30 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Ouvrir le menu de navigation</string>
<string name="navigation_drawer_close">Fermer le menu de navigation</string>
<string name="modules">Modules</string>
<string name="downloads">Téléchargements</string>
<string name="superuser">Superuser</string>
<string name="log">Journal</string>
<string name="settings">Paramètres</string>
<string name="status">État</string>
<string name="install">Installer</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s installée</string>
<string name="magisk_version_core_only">Magisk v%1$s installée (Mode Core uniquement)</string>
<string name="magisk_version_error">Magisk non installé</string>
<string name="checking_for_updates">Vérification de mises à jour…</string>
<string name="magisk_update_available">Magisk v%1$s disponible !</string>
<string name="cannot_check_updates">Impossible de vérifier les mises à jour, pas d\'Internet ?</string>
<string name="up_to_date">Dernière version %1$s installée</string>
<string name="root_error">Rooté mais aucune permission root, non acceptée ?</string>
<string name="root_error">Rooté mais aucune permission root, non autorisée ?</string>
<string name="not_rooted">Non rooté</string>
<string name="proper_root">Correctement rooté</string>
<string name="safetyNet_check_text">Appuyer pour lancer le contrôle SafetyNet</string>
<string name="checking_safetyNet_status">Vérification de l\'état de SafetyNet…</string>
<string name="safetyNet_connection_failed">Impossible de se connecter à l\'API Google</string>
<string name="safetyNet_connection_suspended">La connexion à l\'API Google a été suspendue</string>
<string name="safetyNet_no_response">Impossible de contrôler SafetyNet, pas d\'Internet?</string>
<string name="safetyNet_fail">Échec SafetyNet: erreur de profil CTS</string>
<string name="safetyNet_pass">SafetyNet réussi</string>
<string name="root_info_warning">Fonctionnalités largement limitées</string>
<string name="safetyNet_check_success">Contrôle SafetyNet passé avec succès</string>
<string name="safetyNet_network_loss">Connexion réseau indisponible unavailable</string>
<string name="safetyNet_service_disconnected">Le service a été tué</string>
<string name="safetyNet_res_invalid">La réponse est invalide</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Auto détection impossible)</string>
<string name="boot_image_title">Emplacement de l\'Image Boot</string>
<string name="boot_image_title">Emplacement de l\'image Boot</string>
<string name="detect_button">Détection</string>
<string name="advanced_settings_title">Paramètres avancés</string>
<string name="keep_force_encryption">Garder le chiffrement forcé</string>
@@ -42,18 +34,17 @@
<string name="uninstall">Désinstaller</string>
<string name="reboot_countdown">Redémarrage dans %1$d</string>
<string name="uninstall_magisk_title">Désinstaller Magisk</string>
<string name="uninstall_magisk_msg">Cela va supprimer tous les modules, MagiskSU et éventuellement chiffrer vos données si vous n\'êtes pas chiffré\nÊtes-vous sûr de vouloir continuer ?</string>
<string name="version_none">(Aucune)</string>
<string name="uninstall_magisk_msg">Tous les modules seront désactivés/effacés. Le root sera enlevé et vos données seront potentiellement chiffrées si ce n'est actuellement pas le cas</string>
<string name="update">Mise à jour %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Aucune information transmise)</string>
<string name="no_modules_found">Aucun module trouvé</string>
<string name="update_file_created">Le module va être mis à jour au prochain redémarrage</string>
<string name="remove_file_created">Le module va être supprimé au prochain redémarrage</string>
<string name="remove_file_deleted">Le modufle ne va pas être supprimé au prochain redémarrage</string>
<string name="remove_file_deleted">Le module ne va pas être supprimé au prochain redémarrage</string>
<string name="disable_file_created">Le module va être désactivé au prochain redémarrage</string>
<string name="disable_file_removed">Le module va être activé au prochain redémarrage</string>
<string name="author">Créé par %1$s</string>
<string name="fab_flash_zip">Flasher un Module Zip</string>
<!--Repo Fragment-->
<string name="update_available">Mise à jour disponible</string>
<string name="installed">Installé</string>
@@ -64,11 +55,11 @@
<string name="menuClearLog">Effacer le journal maintenant</string>
<string name="logs_cleared">Journal effacé avec succès</string>
<string name="log_is_empty">Journal vide</string>
<string name="logs_save_failed">Impossible d\'écrire le journal sur la SD card:</string>
<string name="logs_save_failed">Impossible d\'écrire le journal sur la carte SD:</string>
<!--About Activity-->
<string name="about">À propos</string>
<string name="app_developers">Principaux développeurs</string>
<string name="app_developers_"><![CDATA[App created by <a href="https://github.com/topjohnwu">topjohnwu</a> in collaboration with <a href="https://github.com/d8ahazard">Digitalhigh</a> and <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_developers_"><![CDATA[Appli créée par <a href="https://github.com/topjohnwu">topjohnwu</a> en collaboration avec <a href="https://github.com/d8ahazard">Digitalhigh</a> et <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Modifications de l\'application</string>
<string name="translators" />
<string name="app_version">Version de l\'application</string>
@@ -84,36 +75,39 @@
<string name="close">Fermer</string>
<string name="repo_install_title">Installer %1$s</string>
<string name="repo_install_msg">Voulez-vous installer %1$s ?</string>
<string name="download_install">Télécharger &amp; Installer</string>
<string name="download">Télécharger</string>
<string name="goto_install">Aller à la section \"Installer\"</string>
<string name="download_file_error">Erreur de téléchargement du fichier</string>
<string name="install_error">Échec de l\'installation !</string>
<string name="invalid_zip">Ce zip n\'est pas un Module Magisk !!</string>
<string name="reboot_title">Installation réussie !</string>
<string name="reboot_msg">Voulez-vous redémarrer maintenant ?</string>
<string name="reboot">Redémarrer</string>
<string name="copying_msg">Copie du zip dans le répertoire temp</string>
<string name="zip_install_progress_title">Installation</string>
<string name="zip_unzip_msg">Décompression du fichier zip…</string>
<string name="zip_process_msg">Exécution du fichier zip…</string>
<string name="zip_install_progress_msg">Installation %1$s…</string>
<string name="no_magisk_title">Magisk non installé !</string>
<string name="no_magisk_msg">Voulez-vous télécharger et installer Magisk ?</string>
<string name="downloading_toast">Téléchargement %1$s</string>
<string name="magisk_update_title">Nouvelle mise à jour de Magisk disponible !</string>
<string name="settings_reboot_toast">Redémarrer pour appliquer les changements</string>
<string name="release_notes">Notes de version</string>
<string name="repo_cache_cleared">Cache du dépôt effacé</string>
<string name="safetyNet_hide_notice">Cette application utilise SafetyNet\nDéjà pris en charge par MagiskHide par défaut</string>
<string name="start_magiskhide">Lancement de MagiskHide …</string>
<string name="no_magisksu_title">MagiskSU non utilisé !</string>
<string name="no_magisksu_msg">Vous n\'êtes pas rooté avec MagiskSU, utiliser uniquement MagiskHide peut ne pas suffire !\nCeci n\'est officiellement pas supporté et vous devriez avoir besoin d\'autres outils (ex : suhide) pour passer SafetyNet.</string>
<string name="understand">Je comprends</string>
<string name="process_error">Erreur d\'exécution</string>
<string name="internal_storage">Le zip est stocké dans :\n[Internal Storage]%1$s</string>
<string name="zip_process_title">Exécution</string>
<string name="manual_boot_image">Veuillez sélectionner l\'image boot manuellement !</string>
<string name="zip_download_title">Téléchargement</string>
<string name="zip_download_msg">Téléchargement du fichier zip...</string>
<string name="manager_update_title">Nouvelle mise à jour Magisk Manager disponible !</string>
<string name="manager_download_install">Appuyez pour télécharger et installer</string>
<string name="magisk_updates">Mises à jour Magisk</string>
<string name="flashing">Flash en-cours</string>
<string name="hide_manager_toast">Masquage de Magisk Manager…</string>
<string name="hide_manager_fail_toast">Échec du masquage de Magisk Manager...</string>
<string name="download_zip_only">Télécharger uniquement le zip</string>
<string name="patch_boot_file">Patcher le fichier image Boot</string>
<string name="direct_install">Installation directe (recommandée)</string>
<string name="select_method">Choisir une méthode</string>
<string name="no_boot_file_patch_support">La version cible de Magisk ne supporte pas la modification du fichier image Boot</string>
<string name="complete_uninstall">Désinstaller complètement</string>
<string name="restore_stock_boot">Restaurer le Boot stock</string>
<string name="restore_done">Restauration effectuée !</string>
<string name="restore_fail">Pas de sauvegarde stock disponible !</string>
<!--Settings Activity -->
<string name="settings_general_category">Général</string>
<string name="settings_dark_theme_title">Thème sombre</string>
@@ -125,8 +119,6 @@
<string name="settings_core_only_title">Mode Magisk Core uniquement</string>
<string name="settings_core_only_summary">Activer uniquement les fonctionnalités de base, tous les modules ne seront pas chargés. MagiskSU, MagiskHide et les hosts systemless restent activés</string>
<string name="settings_magiskhide_summary">Masquer Magisk de diverses détections</string>
<string name="settings_busybox_title">Activer BusyBox</string>
<string name="settings_busybox_summary">Monter le busybox de Magisk sur xbin</string>
<string name="settings_hosts_title">Hosts systemless</string>
<string name="settings_hosts_summary">Support hosts systemless pour les applications type Adblock</string>
<string name="settings_su_app_adb">Applications et ADB</string>
@@ -142,11 +134,38 @@
<string name="request_timeout">Délai de requête</string>
<string name="superuser_notification">Notification Superuser</string>
<string name="request_timeout_summary">%1$s secondes</string>
<string name="settings_development_category">Dévellopement de l\'application</string>
<string name="settings_development_category">Développement de l\'application</string>
<string name="settings_developer_logging_title">Activer le journal de débogage avancé</string>
<string name="settings_developer_logging_summary">Cocher ceci pour activer la journalisation "verbose" (tout)</string>
<string name="settings_shell_logging_title">Activer la journalisation de débogage de commande shell</string>
<string name="settings_shell_logging_summary">Cocher ceci pour activer la journalisation de toutes les commandes shell et leurs données de sortie</string>
<string name="settings_hide_manager_title">Masquer Magisk Manager</string>
<string name="settings_hide_manager_summary">Masquer temporairement Magisk Manager.\nCeci installera une nouvelle appli appelée \"Unhide Magisk Manager\"</string>
<string name="language">Langue</string>
<string name="system_default">(Selon système)</string>
<string name="settings_update">Paramètres de mises à jour</string>
<string name="settings_update_channel_title">Canal de mise à jour</string>
<string name="settings_update_stable">Stable</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Format de sortie du boot patché</string>
<string name="settings_boot_format_summary">Sélectionner le format de l\'image boot patchée finale.\nChoisir .img pour flasher via fastboot/mode download ; choisir .img.tar pour flasher via ODIN.</string>
<string name="settings_su_reauth_title">Ré-authentifier après mise à jour</string>
<string name="settings_su_reauth_summary">Ré-authentifier les permissions superuser après les mises à jour d\'une application</string>
<string name="multiuser_mode">Mode multi-utilisateurs</string>
<string name="settings_owner_only">Appareil du propriétaire uniquement</string>
<string name="settings_owner_manage">Appareil du propriétaire géré</string>
<string name="settings_user_independent">Utilisateur indépendant</string>
<string name="owner_only_summary">Seul le propriétaire a l\'accès root</string>
<string name="owner_manage_summary">Seul le propriétaire peut gérer les accès root et recevoir des demandes de permissions</string>
<string name="user_indepenent_summary">Chaque utilisateur dispose de ses propres règles root</string>
<string name="multiuser_hint_owner_request">Une requête a été envoyée au propriétaire de l\'appareil. Veuillez basculer sur le profil du propriétaire et accorder la permission</string>
<string name="mount_namespace_mode">Monter le mode espace de noms</string>
<string name="settings_ns_global">Espace de noms global</string>
<string name="settings_ns_requester">Hériter de l\'espace de noms</string>
<string name="settings_ns_isolate">Espace de noms isolé</string>
<string name="global_summary">Toutes les sessions root utilisent l\'espace de noms global monté</string>
<string name="requester_summary">Les sessions root hériteront des espaces de noms du demandeur</string>
<string name="isolate_summary">Chaque session root aura son propre espace de noms isolé</string>
<!--Superuser-->
<string name="su_request_title">Requête Superuser</string>
<string name="deny_with_str">Refuser%1$s</string>

View File

@@ -2,40 +2,28 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Apri drawer navigazione</string>
<string name="navigation_drawer_close">Chiudi drawer navigazione</string>
<string name="modules">Moduli</string>
<string name="modules">Moduli</string>
<string name="downloads">Download</string>
<string name="superuser">Superuser</string>
<string name="log">Registro eventi</string>
<string name="settings">Impostazioni</string>
<string name="status">Stato</string>
<string name="install">Installa</string>
<!--Status Fragment-->
<string name="magisk_version">Versione Magisk: v%1$s</string>
<string name="magisk_version_core_only">Versione Magisk v%1$s (modo core)</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk non installato</string>
<string name="checking_for_updates">Controllo aggiornamenti…</string>
<string name="magisk_update_available">È disponibile Magisk v%1$s!</string>
<string name="cannot_check_updates">Impossibile controllare aggiornamenti</string>
<string name="up_to_date">La versione di %1$s è aggiornata</string>
<string name="root_error">Rootato ma senza permessi. Non sei autorizzato?</string>
<string name="not_rooted">Non rootato</string>
<string name="proper_root">Rootato correttamente</string>
<string name="safetyNet_check_text">Tocca per avviare controllo SafetyNet</string>
<string name="checking_safetyNet_status">Controllo stato SafetyNet</string>
<string name="safetyNet_check_success">Controllo SafetyNet OK</string>
<string name="safetyNet_connection_failed">Impossibile collegarsi alle API Google</string>
<string name="safetyNet_connection_suspended">Connessione alle API Google sospesa</string>
<string name="safetyNet_no_response">Impossibile controllare SafetyNet. Nessuna connessione internet?</string>
<string name="safetyNet_fail">Errore SafetyNet. Il profilo CTS non corrisponde</string>
<string name="safetyNet_pass">Controllo SafetyNet OK</string>
<string name="safetyNet_network_loss">persa conenssioen di rete</string>
<string name="safetyNet_service_disconnected">Ils ervizio è stato terminato</string>
<string name="safetyNet_res_invalid">La risposta non è valida</string>
<string name="root_info_warning">Funzionalità molto limitata</string>
<!--Install Fragment-->
<string name="auto_detect">%1$s (auto)</string>
@@ -50,8 +38,7 @@
<string name="uninstall">Disinstalla</string>
<string name="reboot_countdown">Riavvio tra %1$d</string>
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
<string name="uninstall_magisk_msg">Questo rimuoverà tutti i moduli, MagiskSU, e potenzialmente crittograferà i dati, se non crittografati/nVuoi continuare?</string>
<string name="version_none">(nessuna)</string>
<string name="update">Aggiorna %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(nessuna informazione)</string>
@@ -62,7 +49,6 @@
<string name="disable_file_created">Il modulo sarà disattivato al prossimo riavvio</string>
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio</string>
<string name="author">Creato da: %1$s</string>
<string name="fab_flash_zip">Flasha modulo ZIP</string>
<!--Repo Fragment-->
<string name="update_available">Aggiornamento disponibile</string>
@@ -97,36 +83,26 @@
<string name="close">Chiudi</string>
<string name="repo_install_title">Installazione %1$s</string>
<string name="repo_install_msg">Vuoi installare %1$s ?</string>
<string name="download_install">Scarica e installa</string>
<string name="download">Download</string>
<string name="goto_install">Vai alla sezione \"Installa\"</string>
<string name="download_file_error">Errore nel download del file</string>
<string name="install_error">Errore di installazione!</string>
<string name="invalid_zip">Lo ZIP non è un modulo Magisk!!</string>
<string name="reboot_title">Installazione completata</string>
<string name="reboot_msg">Vuoi riavviare ora?</string>
<string name="reboot">Riavvia</string>
<string name="copying_msg">Copia file ZIP in una cartella temporanea</string>
<string name="zip_install_progress_title">Installazione</string>
<string name="zip_unzip_msg">Decompressione file ZIP…</string>
<string name="zip_process_msg">Elaborazione file ZIP…</string>
<string name="zip_install_progress_msg">Installazione di %1$s…</string>
<string name="no_magisk_title">Magisk non installato!</string>
<string name="no_magisk_msg">Vuoi scaricare ed installare Magisk?</string>
<string name="downloading_toast">Download di %1$s</string>
<string name="magisk_update_title">Disponibile nuovo aggiornamento Magisk!</string>
<string name="settings_reboot_toast">Riavvia per applicare</string>
<string name="release_notes">Note di rilascio</string>
<string name="repo_cache_cleared">Cache reposititory azzerata</string>
<string name="safetyNet_hide_notice">Quest\'app usa SafetyNet\ned è già gestita da MagiskHide</string>
<string name="start_magiskhide">Avvio MagiskHide…</string>
<string name="no_magisksu_title">MagiskSU non in uso!</string>
<string name="no_magisksu_msg">Non hai rootato con MagiskSU. L\'uso del solo MagiskHide potrebbe non essere suffciiente!\nNon è ufficialmente supportato, e potrebbe richiedere altri strumenti (es. suhide) per passare il test Safety Net.</string>
<string name="understand">Accetto</string>
<string name="process_error">Errore di elaborazione</string>
<string name="internal_storage">Lo ZIP si trova in:\n[memoria interna]%1$s</string>
<string name="zip_process_title">Elaborazione</string>
<string name="manual_boot_image">Seleziona manualmente l\'immagine di boot!</string>
<string name="manager_update_title">Nuovo aggiornamento di Magisk Manager disponibile!</string>
<string name="manager_download_install">Premere per scaricare e installare</string>
<string name="magisk_updates">Aggiornamenti Magisk</string>
<string name="flashing">Flashando</string>
<!--Settings Activity -->
<string name="settings_general_category">Generale</string>
@@ -140,8 +116,6 @@
<string name="settings_core_only_title">Solo modo core Magisk</string>
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Non tutti i moduli verranno caricati. MagiskSU, MagiskHide, e host systemless rimarranno abilitati</string>
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
<string name="settings_busybox_title">Abilita BusyBox</string>
<string name="settings_busybox_summary">Collega il mount della busybox interna di Magisk a xbin</string>
<string name="settings_hosts_title">Host systemless</string>
<string name="settings_hosts_summary">Supporto host systemless per app blocco pubblicità</string>
@@ -158,7 +132,7 @@
<string name="request_timeout">Timeout richiesta</string>
<string name="superuser_notification">Notifica Superuser</string>
<string name="request_timeout_summary">%1$s secondi</string>
<string name="settings_su_reauth_title">Ri-autentifica dopo aggironamento</string>
<string name="settings_su_reauth_title">Ri-autentifica dopo aggiornamento</string>
<string name="settings_su_reauth_summary">Ri-autentifica permessi superuser dopo aggiornamento applicazione</string>
<string name="multiuser_mode">Modo multiutente</string>

View File

@@ -2,36 +2,24 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">ナビゲーションドロワーを開く</string>
<string name="navigation_drawer_close">ナビゲーションドロワーを閉じる</string>
<string name="modules">モジュール</string>
<string name="downloads">ダウンロード</string>
<string name="superuser">スーパーユーザー</string>
<string name="log">ログ</string>
<string name="settings">設定</string>
<string name="status">ステータス</string>
<string name="install">インストール</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s がインストール済</string>
<string name="magisk_version_core_only">Magisk v%1$s がインストール済(コアモード)</string>
<string name="magisk_version_error">Magisk がインストールされていません</string>
<string name="checking_for_updates">更新を確認中...</string>
<string name="magisk_update_available">Magisk v%1$s が利用可能です!</string>
<string name="cannot_check_updates">更新を確認できませんでした。インターネットに接続されていますか?</string>
<string name="up_to_date">最新の %1$s がインストール済です</string>
<string name="root_error">Root化はされていますが権限がありません。拒否していませんか</string>
<string name="not_rooted">Root化されていません</string>
<string name="proper_root">正常にroot化済</string>
<string name="safetyNet_check_text">タップしてSafetyNetチェックを開始</string>
<string name="checking_safetyNet_status">SafetyNet Statusをチェック中…</string>
<string name="safetyNet_connection_failed">Google APIに接続できませんでした</string>
<string name="safetyNet_connection_suspended">Google APIへの接続が中断されました</string>
<string name="safetyNet_no_response">SafetyNetをチェックできませんでした。インターネットに接続されていますか</string>
<string name="safetyNet_fail">SafetyNet Failed: CTSプロファイルが不一致</string>
<string name="safetyNet_pass">SafetyNet Passed</string>
<string name="root_info_warning">機能が大幅に制限されています</string>
<!--Install Fragment-->
<string name="auto_detect">(自動) %1$s</string>
@@ -46,8 +34,6 @@
<string name="uninstall">アンインストール</string>
<string name="reboot_countdown">%1$dで再起動します</string>
<string name="uninstall_magisk_title">Magiskをアンインストールします</string>
<string name="uninstall_magisk_msg">これにより、すべてのモジュールとMagiskSUを削除します。暗号化されていないデータが暗号化される可能性があります。\ n続行しますか</string>
<string name="version_none">(なし)</string>
<!--Module Fragment-->
<string name="no_info_provided">(情報がありません)</string>
@@ -58,7 +44,6 @@
<string name="disable_file_created">次の再起動時にモジュールを無効にする</string>
<string name="disable_file_removed">次の再起動時にモジュールを有効にする</string>
<string name="author">作者: %1$s</string>
<string name="fab_flash_zip">モジュールのzipを焼く</string>
<!--Repo Fragment-->
<string name="update_available">利用可能な更新</string>
@@ -93,32 +78,18 @@
<string name="close">閉じる</string>
<string name="repo_install_title">%1$s をインストール</string>
<string name="repo_install_msg">%1$s をインストールしますか?</string>
<string name="download_install">ダウンロード &amp; インストール</string>
<string name="download">ダウンロード</string>
<string name="goto_install">インストール画面に移動する</string>
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
<string name="install_error">インストールエラー!</string>
<string name="invalid_zip">このzipはMagiskモジュールではありません</string>
<string name="reboot_title">インストールに成功しました!</string>
<string name="reboot_msg">今すぐ再起動しますか?</string>
<string name="reboot">再起動</string>
<string name="copying_msg">一時ディレクトリへのzipをコピー中</string>
<string name="zip_install_progress_title">インストール中…</string>
<string name="zip_unzip_msg">zipファイルの解凍中…</string>
<string name="zip_process_msg">zipファイルの処理中…</string>
<string name="zip_install_progress_msg">%1$s をインストール中…</string>
<string name="no_magisk_title">Magiskがインストールされていません</string>
<string name="no_magisk_msg"> Magiskをダウンロードしてインストールしますか</string>
<string name="downloading_toast">%1$s をダウンロード中</string>
<string name="magisk_update_title">新しいMagiskの更新が利用可能です</string>
<string name="settings_reboot_toast">再起動して設定を適用する</string>
<string name="release_notes">リリースノート</string>
<string name="repo_cache_cleared">リポジトリキャッシュを消去しました</string>
<string name="safetyNet_hide_notice">このアプリはSafetyNetを使用しています。\n既定ではMagiskHideで既に処理されています</string>
<string name="start_magiskhide">MagiskHideを開始中…</string>
<string name="no_magisksu_title">MagiskSUを使用していません</string>
<string name="no_magisksu_msg">あなたのデバイスはMagiskSUにrootされていません。MagiskHideを使用するだけでは十分ではありません。\nそれは正式にサポートされておらず、あなたはSafetyNetを通過するために追加ツール例えばsuhideが必要です。</string>
<string name="understand">了解</string>
<string name="process_error">プロセスエラー</string>
<string name="internal_storage">zipは:\n[Internal Storage]%1$sに保存されます</string>
<string name="zip_process_title">処理</string>
@@ -136,8 +107,6 @@
<string name="settings_core_only_title">Magisk コアモード</string>
<string name="settings_core_only_summary">コア機能のみを有効にすると、すべてのモジュールがロードされなくなります。 MagiskSU、MagiskHide、systemless hostsは引き続き有効になります。</string>
<string name="settings_magiskhide_summary">さまざまな検出からMagiskを隠す</string>
<string name="settings_busybox_title">BusyBoxを有効にする</string>
<string name="settings_busybox_summary">Magiskに搭載するBusyBoxをxbinにバインドする</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">AdblockのためのSystemless hostsサポート</string>

View File

@@ -2,36 +2,24 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">내비게이션 서랍 열기</string>
<string name="navigation_drawer_close">내비게이션 서랍 닫기</string>
<string name="modules">모듈</string>
<string name="downloads">다운로드</string>
<string name="superuser">슈퍼유저</string>
<string name="log">로그</string>
<string name="settings">설정</string>
<string name="status">상태</string>
<string name="install">설치</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s 설치됨</string>
<string name="magisk_version_core_only">Magisk v%1$s 설치됨 (핵심 기능 모드)</string>
<string name="magisk_version_error">Magisk가 설치되지 않음</string>
<string name="checking_for_updates">업데이트 확인 중…</string>
<string name="magisk_update_available">Magisk v%1$s 사용 가능!</string>
<string name="cannot_check_updates">업데이트를 확인할 수 없음. 인터넷 연결을 확인하세요.</string>
<string name="up_to_date">최신 버전의 %1$s 설치됨</string>
<string name="root_error">루팅은 되어 있으나 루트 권한을 얻을 수 없음. 루트 권한 허용 상태를 확인하세요.</string>
<string name="not_rooted">루팅이 되어 있지 않음</string>
<string name="proper_root">정상적으로 루팅됨</string>
<string name="safetyNet_check_text">SafetyNet 체크를 시작하려면 누르기</string>
<string name="checking_safetyNet_status">SafetyNet 상태 확인 중…</string>
<string name="safetyNet_connection_failed">Google API에 연결할 수 없음</string>
<string name="safetyNet_connection_suspended">Google API에 대한 연결이 일시 중지됨</string>
<string name="safetyNet_no_response">SafetyNet 체크 실패. 인터넷 연결을 확인하세요.</string>
<string name="safetyNet_fail">SafetyNet 실패: CTS 프로필 불일치</string>
<string name="safetyNet_pass">SafetyNet 통과</string>
<string name="root_info_warning">기능이 크게 제한됨</string>
<!--Install Fragment-->
<string name="auto_detect">(자동) %1$s</string>
@@ -46,8 +34,6 @@
<string name="uninstall">제거</string>
<string name="reboot_countdown">%1$d초 안에 다시 시작됨</string>
<string name="uninstall_magisk_title">Magisk 제거</string>
<string name="uninstall_magisk_msg">모든 모듈과 MagiskSU를 제거합니다. 또한 데이터가 암호화되어 있지 않은 경우 암호화될 가능성이 있습니다.\n정말 계속하시겠습니까?</string>
<string name="version_none">(없음)</string>
<!--Module Fragment-->
<string name="no_info_provided">(제공된 정보 없음)</string>
@@ -58,7 +44,6 @@
<string name="disable_file_created">모듈이 다음 다시 시작 시 비활성화됨</string>
<string name="disable_file_removed">모듈이 다음 다시 시작 시 활성화됨</string>
<string name="author">제작: %1$s</string>
<string name="fab_flash_zip">모듈 ZIp 파일 플래싱</string>
<!--Repo Fragment-->
<string name="update_available">업데이트 있음</string>
@@ -93,31 +78,17 @@
<string name="close">닫기</string>
<string name="repo_install_title">%1$s 설치</string>
<string name="repo_install_msg">정말 %1$s을(를) 설치하시겠습니까?</string>
<string name="download_install">다운로드 및 설치</string>
<string name="goto_install">\"설치\" 섹션으로 이동</string>
<string name="download_file_error">파일 다운로드 오류</string>
<string name="install_error">설치 오류!</string>
<string name="invalid_zip">이 zip 파일은 Magisk 모듈이 아닙니다!!</string>
<string name="reboot_title">설치 성공!</string>
<string name="reboot_msg">지금 기기를 다시 시작하시겠습니까?</string>
<string name="reboot">다시 시작</string>
<string name="copying_msg">임시 디렉터리에 zip 파일 복사 중</string>
<string name="zip_install_progress_title">설치 중</string>
<string name="zip_unzip_msg">zip 파일 압축 해제 중…</string>
<string name="zip_process_msg">zip 파일 처리 중…</string>
<string name="zip_install_progress_msg">%1$s 설치 중…</string>
<string name="no_magisk_title">Magisk가 설치되어 있지 않습니다!</string>
<string name="no_magisk_msg">Magisk를 다운로드하고 설치하시겠습니까?</string>
<string name="downloading_toast">%1$s 다운로드 중</string>
<string name="magisk_update_title">새 버전의 Magisk를 사용할 수 있습니다!</string>
<string name="settings_reboot_toast">기기를 다시 시작하면 설정이 적용됩니다.</string>
<string name="release_notes">릴리즈 노트</string>
<string name="repo_cache_cleared">저장소 캐시 비워짐</string>
<string name="safetyNet_hide_notice">이 앱은 MagiskHide에서\n이미 기본적으로 관리하는 SafetyNet을 사용합니다.</string>
<string name="start_magiskhide">MagiskHide 시작 중…</string>
<string name="no_magisksu_title">MagiskSU를 사용하고 있지 않습니다!</string>
<string name="no_magisksu_msg">MagiskSU로 루팅이 되어있지 않아 MagiskHide 하나만으로는 충분하지 않을 수 있습니다!\n이는 공식적으로 지원되지 않으며, SafetyNet을 통과하려면 추가적인 도구(suhide 등)가 필요할 수 있습니다.</string>
<string name="understand">알겠습니다</string>
<string name="process_error">처리 오류</string>
<string name="internal_storage">zip 파일이 다음 위치에 저장됨:\n[내부 저장소]%1$s</string>
<string name="zip_process_title">처리 중</string>
@@ -135,8 +106,6 @@
<string name="settings_core_only_title">Magisk 핵심 기능 모드</string>
<string name="settings_core_only_summary">핵심 기능만 사용합니다. 모든 모듈은 로드하지 않습니다. MagiskSU, MagiskHide 및 systemless hosts 는 계속 사용할 수 있습니다.</string>
<string name="settings_magiskhide_summary">다양한 감지로부터 Magisk를 숨깁니다.</string>
<string name="settings_busybox_title">BusyBox 사용</string>
<string name="settings_busybox_summary">xbin 디렉터리에 Magisk의 빌트인 busybox를 바인드합니다.</string>
<string name="settings_hosts_title">systemless hosts</string>
<string name="settings_hosts_summary">광고 차단 앱에서 사용하는 systemless hosts를 지원합니다.</string>
@@ -192,5 +161,6 @@
<string name="pid">PID:\u0020</string>
<string name="target_uid">대상 UID:\u0020</string>
<string name="command">명령:\u0020</string>
<string name="download">다운로드</string>
</resources>

View File

@@ -2,40 +2,28 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Navigatielade openen</string>
<string name="navigation_drawer_close">Navigatielade sluiten</string>
<string name="modules">Modules</string>
<string name="downloads">Downloads</string>
<string name="superuser">Superuser</string>
<string name="log">Log</string>
<string name="settings">Instellingen</string>
<string name="status">Status</string>
<string name="install">Installeren</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s geïnstalleerd</string>
<string name="magisk_version_core_only">Magisk v%1$s geïnstalleerd (basismodus)</string>
<string name="magisk_version_error">Magisk niet geïnstalleerd</string>
<string name="checking_for_updates">Controleren op updates…</string>
<string name="magisk_update_available">Magisk v%1$s beschikbaar!</string>
<string name="cannot_check_updates">Kan niet controleren op updates. Geen internet?</string>
<string name="up_to_date">Laatste versie van %1$s geïnstalleerd</string>
<string name="root_error">Geroot, maar geen root-permissie. Niet toegestaan?</string>
<string name="not_rooted">Niet geroot</string>
<string name="proper_root">Correct geroot</string>
<string name="safetyNet_check_text">Tik om SafetyNet controle te starten</string>
<string name="checking_safetyNet_status">SafetyNet status controleren…</string>
<string name="safetyNet_check_success">SafetyNet controle succesvol</string>
<string name="safetyNet_connection_failed">Kan niet verbinden met Google API</string>
<string name="safetyNet_connection_suspended">Verbinding met Google API was geschorst</string>
<string name="safetyNet_no_response">Kan SafetyNet niet controleren. Geen internet?</string>
<string name="safetyNet_fail">SafetyNet gefaald</string>
<string name="safetyNet_pass">SafetyNet geslaagd</string>
<string name="safetyNet_network_loss">Netwerkverbinding verloren</string>
<string name="safetyNet_service_disconnected">Service is beëindigd</string>
<string name="safetyNet_res_invalid">Reactie is ongeldig</string>
<string name="root_info_warning">Functionaliteit zeer beperkt</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -50,8 +38,8 @@
<string name="uninstall">Deïnstalleren</string>
<string name="reboot_countdown">Herstarten in %1$d</string>
<string name="uninstall_magisk_title">Magisk deïnstalleren</string>
<string name="uninstall_magisk_msg">Dit verwijdert alle modules, MagiskSU, en versleutelt mogelijk alle niet-versleutelde data\nZeker weten voortzetten?</string>
<string name="version_none">(Geen)</string>
<string name="uninstall_magisk_msg">Alle modules worden uitgeschakeld/verwijderd. Root wordt verwijderd, en je data wordt mogelijk versleuteld als deze dat momenteel niet is</string>
<string name="update">Bijwerken %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Geen info verstrekt)</string>
@@ -62,7 +50,6 @@
<string name="disable_file_created">Module wordt uitgeschakeld bij volgende herstart</string>
<string name="disable_file_removed">Module wordt ingeschakeld bij volgende herstart</string>
<string name="author">Gemaakt door %1$s</string>
<string name="fab_flash_zip">Module zip flashen</string>
<!--Repo Fragment-->
<string name="update_available">Update beschikbaar</string>
@@ -97,36 +84,40 @@
<string name="close">Sluiten</string>
<string name="repo_install_title">%1$s installeren</string>
<string name="repo_install_msg">Zeker weten %1$s installeren?</string>
<string name="download_install">Downloaden &amp; installeren</string>
<string name="download">Downloaden</string>
<string name="goto_install">Ga naar \"Installeren\" sectie</string>
<string name="download_file_error">Fout tijdens downloaden</string>
<string name="install_error">Installatiefout!</string>
<string name="invalid_zip">De zip is geen Magisk module!</string>
<string name="reboot_title">Installatie geslaagd!</string>
<string name="reboot_msg">Wil je nu herstarten?</string>
<string name="reboot">Herstarten</string>
<string name="copying_msg">Zip naar tijdelijke map kopiëren</string>
<string name="zip_install_progress_title">Installeren</string>
<string name="zip_unzip_msg">Zip-bestand uitpakken…</string>
<string name="zip_process_msg">Zip-bestand verwerken…</string>
<string name="zip_install_progress_msg">%1$s installeren…</string>
<string name="no_magisk_title">Geen Magisk geïnstalleerd!</string>
<string name="no_magisk_msg">Wil je Magisk downloaden en installeren?</string>
<string name="downloading_toast">%1$s downloaden</string>
<string name="magisk_update_title">Nieuwe Magisk update beschikbaar!</string>
<string name="settings_reboot_toast">Herstarten om instellingen toe te passen</string>
<string name="release_notes">Publicatie notities</string>
<string name="repo_cache_cleared">Opslagcache gewist</string>
<string name="safetyNet_hide_notice">Deze app gebruikt SafetyNet\nReeds afgehandeld door standaard MagiskHide</string>
<string name="start_magiskhide">MagiskHide starten…</string>
<string name="no_magisksu_title">Geen gebruik van MagiskSU!</string>
<string name="no_magisksu_msg">Je bent niet geroot met MagiskSU, waardoor alleen MagiskHide mogelijk onvoldoende is!\nHet wordt niet officieel ondersteund, waardoor aanvullende acties (bijv. suhide) benodigd zijn om te slagen voor SafetyNet.</string>
<string name="understand">Ik begrijp het</string>
<string name="process_error">Verwerkingsfout</string>
<string name="internal_storage">De zip is opgeslagen in:\n[Interne opslag]%1$s</string>
<string name="zip_download_title">Downloaden</string>
<string name="zip_download_msg">Zip-bestand downloaden…</string>
<string name="zip_process_title">Verwerken</string>
<string name="zip_process_msg">Zip-bestand verwerken…</string>
<string name="manual_boot_image">Gelieve handmatig een boot image te selecteren!</string>
<string name="manager_update_title">Nieuwe Magisk Manager update beschikbaar!</string>
<string name="manager_download_install">Tik om te downloaden en installeren</string>
<string name="magisk_updates">Magisk updates</string>
<string name="flashing">Flashen</string>
<string name="hide_manager_toast">Magisk Manager verbergen…</string>
<string name="hide_manager_fail_toast">Magisk Manager verbergen mislukt…</string>
<string name="download_zip_only">Alleen zip downloaden</string>
<string name="patch_boot_file">Boot image-bestand patchen</string>
<string name="direct_install">Direct installeren (aangeraden)</string>
<string name="select_method">Methode kiezen</string>
<string name="no_boot_file_patch_support">Magisk versie ondersteund geen boot image-bestand patchen</string>
<string name="boot_file_patch_msg">Kies originele boot image-dump in .img- of .img.tar-formaat</string>
<string name="complete_uninstall">Compleet deïnstalleren</string>
<string name="restore_stock_boot">Originele boot herstellen</string>
<string name="restore_done">Herstel voltooid!</string>
<string name="restore_fail">Originele back-up bestaat niet!</string>
<!--Settings Activity -->
<string name="settings_general_category">Algemeen</string>
@@ -136,12 +127,20 @@
<string name="settings_notification_summary">Een update melding weergeven wanneer een nieuwe versie beschikbaar is</string>
<string name="settings_clear_cache_title">Opslagcache wissen</string>
<string name="settings_clear_cache_summary">Wis de gecachte informatie voor online opslagplaatsen. Dit dwingt de app om online te verversen</string>
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
<string name="settings_hide_manager_summary">Magisk Manager tijdelijk verbergen.\nDit installeert een nieuwe app genaamd \"Unhide Magisk Manager\"</string>
<string name="language">Taal</string>
<string name="system_default">(Systeem standaard)</string>
<string name="settings_update">Instellingen bijwerken</string>
<string name="settings_update_channel_title">Update-kanaal</string>
<string name="settings_update_stable">Stabiel</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Gepatchte boot uitvoerformaat</string>
<string name="settings_boot_format_summary">Kies het formaat van de boot image uitvoer.\nKies .img om via fastboot/downloadmodus te flashen; kies .img.tar om via ODIN te flashen.</string>
<string name="settings_core_only_title">Magisk basismodus</string>
<string name="settings_core_only_summary">Alleen kernfuncties inschakelen. Alle modules worden niet geladen. MagiskSU, MagiskHide, en systeemloze hosts blijven ingeschakeld</string>
<string name="settings_magiskhide_summary">Magisk van verschillende detecties verbergen</string>
<string name="settings_busybox_title">Busybox inschakelen</string>
<string name="settings_busybox_summary">Magisk\'s ingebouwde busybox naar xbin bind mounten</string>
<string name="settings_hosts_title">Systeemloze hosts</string>
<string name="settings_hosts_summary">Systemloze hosts ondersteuning voor Adblock apps</string>

View File

@@ -4,41 +4,29 @@
<!--Welcome Activity-->
<string name="navigation_drawer_open">Otwórz szufladę nawigacji</string>
<string name="navigation_drawer_close">Zamknij szufladę nawigacji</string>
<string name="modules">Moduły</string>
<string name="downloads">Pobieranie</string>
<string name="superuser">Superuser</string>
<string name="log">Log</string>
<string name="settings">Ustawienia</string>
<string name="status">Status</string>
<string name="install">Instalacja</string>
<!--Status Fragment-->
<string name="magisk_version">Zainstalowany Magisk v%1$s</string>
<string name="magisk_version_core_only">Zainstalowany Magisk v%1$s (Tylko Tryb Rdzeni)</string>
<string name="magisk_version_error">Magisk nie jest zainstalowany</string>
<string name="checking_for_updates">Sprawdzanie aktualizacji…</string>
<string name="magisk_update_available">Magisk v%1$s dostępny!</string>
<string name="cannot_check_updates">Nie można sprawdzić dostępności aktualizacji, brak internetu</string>
<string name="up_to_date">Zainstalowana najnowsza wersja %1$s</string>
<string name="root_error">Root dostępny, ale dostęp nie przyznany</string>
<string name="not_rooted">Brak Roota</string>
<string name="proper_root">Root Dostępny</string>
<string name="safetyNet_check_text">Dotknij aby sprawdzić SafetyNet</string>
<string name="checking_safetyNet_status">Sprawdzanie statusu SafetyNet…</string>
<string name="safetyNet_check_success">Sprawdzanie SafetyNet z Powodzeniem</string>
<string name="safetyNet_connection_failed">Nie można połączyć się z Google API</string>
<string name="safetyNet_connection_suspended">Połączenie z Google API zostało zawieszone</string>
<string name="safetyNet_no_response">Nie można sprawdzić SafetyNet bez internetu</string>
<string name="safetyNet_fail">Błąd SafetyNet: Niezgodność profilu CTS</string>
<string name="safetyNet_pass">SafetyNet Poprawny</string>
<string name="safetyNet_network_loss">Brak połączenia z internetem</string>
<string name="safetyNet_service_disconnected">Usługa została zamknięta</string>
<string name="safetyNet_res_invalid">Usługa nie odpowiada</string>
<string name="root_info_warning">Funkcjonalność znacznie ograniczona</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -53,8 +41,8 @@
<string name="uninstall">Odinstaluj</string>
<string name="reboot_countdown">Restartuj do %1$d</string>
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
<string name="uninstall_magisk_msg">Spowoduje to usunięcie wszystkich modułów, MagiskSU i potencjalnie szyfrowanie danych jeśli nie były szyfrowane \ nCzy na pewno kontynuować?</string>
<string name="version_none">(Brak)</string>
<string name="uninstall_magisk_msg">Wszystkie moduły będą wyłączone/usunięte.Root zostanie usunięty i przywrócone szyfrowanie danych, jeśli nie są te dane obecnie szyfrowane</string>
<string name="update">Aktualizacja %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nie umieszczono informacji)</string>
@@ -65,7 +53,6 @@
<string name="disable_file_created">Moduł zostanie wyłączony przy następnym restarcie</string>
<string name="disable_file_removed">Moduł zostanie włączony przy następnym restarcie</string>
<string name="author">Autor: %1$s</string>
<string name="fab_flash_zip">Zainstaluj Moduł Zip</string>
<!--Repo Fragment-->
<string name="update_available">Aktualizacja jest dostępna</string>
@@ -100,40 +87,44 @@
<string name="close">Zamknij</string>
<string name="repo_install_title">Zainstaluj %1$s</string>
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
<string name="download_install">Pobierz i zainstaluj</string>
<string name="download">Pobierz</string>
<string name="goto_install">Idź do sekcji \"Instalacja\"</string>
<string name="download_file_error">Błąd pobierania pliku</string>
<string name="install_error">Błąd instalacji!</string>
<string name="invalid_zip">Ten zip nie jest Modułem Magisk!!</string>
<string name="reboot_title">Instalacja zakończona powodzeniem!</string>
<string name="reboot_msg">Czy chcesz teraz ponownie uruchomić?</string>
<string name="reboot">Restart</string>
<string name="copying_msg">Kopiowanie zip do katalogu temp</string>
<string name="zip_install_progress_title">Instalacja</string>
<string name="zip_unzip_msg">Rozpakowywanie pliku zip …</string>
<string name="zip_process_msg">Przetwarzanie pliku zip …</string>
<string name="zip_install_progress_msg">Instalowanie %1$s …</string>
<string name="no_magisk_title">Brak zainstalowanego Magisk!</string>
<string name="no_magisk_msg">Chcesz pobrać i zainstalować Magisk?</string>
<string name="downloading_toast">Pobieranie %1$s</string>
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
<string name="settings_reboot_toast">Uruchom ponownie, aby zastosować ustawienia</string>
<string name="release_notes">Zmiany</string>
<string name="repo_cache_cleared">Cache repozytorium wyczyszczone</string>
<string name="safetyNet_hide_notice">Ta aplikacja wykorzystuje SafetyNet\nJest już domyślnie obsługiwana przez MagiskHide</string>
<string name="start_magiskhide">Uruchamianie MagiskHide …</string>
<string name="no_magisksu_title">Nie Używaj MagiskSU!</string>
<string name="no_magisksu_msg">Jeśli nie masz roota z MagiskSU, używanie samego MagiskHide może nie wystarczyć! Inne metody nie są oficjalnie obsługiwane. Do poprawnego działania SaftyNet potrzebne będą dodatkowe narzędzia (np suhide)</string>
<string name="understand">Rozumiem</string>
<string name="process_error">Błąd procesu</string>
<string name="internal_storage">Zip jest przechowywany w:\n[Pamięć Wewnętrzna]%1$s</string>
<string name="zip_process_title">Przetwarzanie</string>
<string name="manual_boot_image">Proszę ręcznie wybrać boot image!</string>
<string name="zip_download_title">Pobieranie</string>
<string name="zip_download_msg">Pobieranie pliku zip …</string>
<string name="zip_process_title">Przetwarzanie</string>
<string name="zip_process_msg">Przetwarzanie pliku zip …</string>
<string name="manual_boot_image">Proszę ręcznie wybrać boot image!</string>
<string name="manager_update_title">Nowa Wersja Magisk Manager Jest Dostępna!</string>
<string name="manager_download_install">Naciśnij aby pobrać i zainstalować</string>
<string name="magisk_updates">Aktualizacja Magisk</string>
<string name="flashing">Flashowanie</string>
<string name="hide_manager_toast">Ukryj Magisk Manager…</string>
<string name="hide_manager_fail_toast">Błąd ukrycia Magisk Manager</string>
<string name="download_zip_only">Pobierz Tylko Zip</string>
<string name="patch_boot_file">Patchowanie Pliku Boot Image</string>
<string name="direct_install">Bezpośrednia instalacja (Zalecane)</string>
<string name="install_second_slot">Zainstaluj na Drugim Slocie (Po OTA)</string>
<string name="select_method">Wybierz Metodę</string>
<string name="no_boot_file_patch_support">Wersja docelowa programu Magisk nie obsługuje ładowania pliku boot image</string>
<string name="boot_file_patch_msg">Wybierz stock boot image w formacie .img lub .img.tar</string>
<string name="complete_uninstall">Odinstalowywanie Zakończone</string>
<string name="restore_stock_boot">Przywróć Stockowy Boot</string>
<string name="restore_done">Przywracanie zakonczone!</string>
<string name="restore_fail">Stock backup nie istnieje!</string>
<string name="uninstall_toast">Odinstalowanie Magisk Manager w ciągu 5 sekund, proszę następnie ręcznie ponownie uruchomić urządzenie</string>
<!--Settings Activity -->
<!--Settings Activity -->
<string name="settings_general_category">Ogólne</string>
<string name="settings_dark_theme_title">Ciemny Motyw</string>
<string name="settings_dark_theme_summary">Włącz ciemny motyw</string>
@@ -141,12 +132,20 @@
<string name="settings_notification_summary">Pokaż powiadomienie o aktualizacji kiedy będzie dostępna nowa wersja</string>
<string name="settings_clear_cache_title">Wyczyść Pamięć Repozytorium</string>
<string name="settings_clear_cache_summary">Wymusza na aplikacji odświeżenie online repozytorium</string>
<string name="settings_core_only_title">Tylko Tryb Rdzeni Magisk</string>
<string name="settings_hide_manager_title">Ukryj Magisk Manager</string>
<string name="settings_hide_manager_summary">Tymczasowo ukryj Magisk Manager.\nSpowoduje to zainstalowanie nowej aplikacji o nazwie \"Pokaż Magisk Manager\"</string>
<string name="language">Język</string>
<string name="system_default">(Domyślny Systemu)</string>
<string name="settings_update">Aktualizacja Ustawień</string>
<string name="settings_update_channel_title">Aktualizacja Kanału</string>
<string name="settings_update_stable">Stabilna</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Poprawiony format wyjścia rozruchowego</string>
<string name="settings_boot_format_summary">Wybierz format wyjściowy pliku boot image.\nWybierz .img do programu za pośrednictwem fastboot/download mode; wybierz .img.tar za pomocą ODINA.</string>
<string name="settings_core_only_title">Tylko Tryb Rdzeni Magisk</string>
<string name="settings_core_only_summary">Włącz tylko podstawowe funkcje, wszystkie moduły nie zostaną załadowane. MagiskSU, MagiskHide i systemless hosts nadal będą włączone</string>
<string name="settings_magiskhide_summary">Włącz Hide Magisk dla wykrytych aplikacji</string>
<string name="settings_busybox_title">Włącz BusyBox</string>
<string name="settings_busybox_summary">Zmień montowanie Magisk z wbudowanego busybox do xbin</string>
<string name="settings_hosts_title">Włącz systemless hosts</string>
<string name="settings_hosts_summary">Wsparcie systemless dla aplikacji Adblock</string>

View File

@@ -4,41 +4,29 @@
<!--Welcome Activity-->
<string name="navigation_drawer_open">Abrir gaveta de notificação</string>
<string name="navigation_drawer_close">Fechar gaveta de notificação</string>
<string name="modules">Módulos</string>
<string name="downloads">Baixar</string>
<string name="superuser">Superusuário</string>
<string name="log">Registro</string>
<string name="settings">Configurações</string>
<string name="status">Status</string>
<string name="install">Instalar</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s Instalado</string>
<string name="magisk_version_core_only">Magisk v%1$s Instalado(Somente em modo Core)</string>
<string name="magisk_version_error">Magisk não instalado</string>
<string name="checking_for_updates">Checando por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="cannot_check_updates">Não é possível verificar se há atualizações</string>
<string name="up_to_date">Última versão do %1$s instalado</string>
<string name="root_error">Rooteado mas sem permissão de root, o acesso foi permitido?</string>
<string name="not_rooted">Sem root</string>
<string name="proper_root">Rooteado</string>
<string name="safetyNet_check_text">Pressione para checar o SafetyNet</string>
<string name="checking_safetyNet_status">Verificando status do SafetyNet…</string>
<string name="safetyNet_check_success">SafetyNet verificado</string>
<string name="safetyNet_connection_failed">Não é possível conectar-se à API do Google</string>
<string name="safetyNet_connection_suspended">A conexão com API do Google foi suspensa</string>
<string name="safetyNet_no_response">Não é possível verificar o SafetyNet, sem Internet?</string>
<string name="safetyNet_fail">SafetyNet Falhou: CTS profile mismatch</string>
<string name="safetyNet_pass">SafetyNet Passado</string>
<string name="safetyNet_network_loss">Conexão com a rede perdida</string>
<string name="safetyNet_network_loss">Conexão com a rede perdida</string>
<string name="safetyNet_service_disconnected">O serviço foi morto</string>
<string name="safetyNet_res_invalid">A resposta é inválida</string>
<string name="root_info_warning">Funcionalidade muito limitada</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -53,8 +41,6 @@
<string name="uninstall">Desinstalar</string>
<string name="reboot_countdown">Reiniciando em %1$d</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="uninstall_magisk_msg">Isso removerá todos os módulos, MagiskSU, e Potencialmente criptografar seus dados se não criptografados\nVocê deseja continuar?</string>
<string name="version_none">(Nenhum)</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
@@ -65,7 +51,6 @@
<string name="disable_file_created">Módulo será desativado na próxima reinicialização</string>
<string name="disable_file_removed">Módulo será ativado na próxima reinicialização</string>
<string name="author">Criado por %1$s</string>
<string name="fab_flash_zip">Flashear Módulo Zip</string>
<!--Repo Fragment-->
<string name="update_available">Atualização disponível</string>
@@ -100,32 +85,18 @@
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Você deseja instalar%1$s ?</string>
<string name="download_install">Baixar &amp; instalar</string>
<string name="download">Baixar</string>
<string name="goto_install">Ir na seção \"Instalar\"</string>
<string name="download">Baixar</string>
<string name="download_file_error">Erro ao baixar o arquivo</string>
<string name="install_error">Erro na instalação!</string>
<string name="invalid_zip">O zip não é um Módulo Magisk!!</string>
<string name="reboot_title">Instalação bem-sucedida!</string>
<string name="reboot_msg">Você quer reiniciar agora?</string>
<string name="reboot">Reiniciar</string>
<string name="copying_msg">Copiando zip para diretório temporário</string>
<string name="zip_install_progress_title">Instalando</string>
<string name="zip_unzip_msg">Descompactando arquivo zip …</string>
<string name="zip_process_msg">Processando arquivo zip …</string>
<string name="zip_install_progress_msg">Instalando %1$s</string>
<string name="no_magisk_title">Magisk Não Instalado!</string>
<string name="no_magisk_msg">Você quer baixar e instalar o Magisk?</string>
<string name="downloading_toast">Baixando %1$s</string>
<string name="downloading_toast">Baixando %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar configurações</string>
<string name="release_notes">Notas da atualização</string>
<string name="repo_cache_cleared">Cache do Repo. limpado</string>
<string name="safetyNet_hide_notice">Este aplicativo usa SafetyNet\nJá manipulado pelo MagiskHide por padrão</string>
<string name="start_magiskhide">Iniciando MagiskHide …</string>
<string name="no_magisksu_title">Não está usando MagiskSU!</string>
<string name="no_magisksu_msg">Você não está rooteado com MagiskSU, Usar MagiskHide em si pode não ser suficiente!\Ele não é oficialmente suportado, E você precisaria de ferramentas adicionais (ex: suhide) para passar pelo Safety Net.</string>
<string name="understand">Eu entendo</string>
<string name="process_error">Erro no processo</string>
<string name="internal_storage">O zip foi salvo em:\n[Armazenamento interno]%1$s</string>
<string name="zip_process_title">Processando</string>
@@ -146,8 +117,6 @@
<string name="settings_core_only_title">Magisk modo somente Core</string>
<string name="settings_core_only_summary">Ativar somente recursos principais, todos os módulos não serão carregados. MagiskSU, MagiskHide, e systemless hosts ainda estará ativado</string>
<string name="settings_magiskhide_summary">Ocultar Magisk de várias detecções</string>
<string name="settings_busybox_title">Ativar BusyBox</string>
<string name="settings_busybox_summary">Monta a busybox interna do Magisk\'s para xbin</string>
<string name="settings_hosts_title">Ativar systemless hosts</string>
<string name="settings_hosts_summary">Suporte do systemless para Adblock apps</string>

View File

@@ -1,224 +1,198 @@
<resources>
<!--Welcome Activity-->
<string name="navigation_drawer_open">Abrir gaveta de notificação</string>
<string name="navigation_drawer_close">Fechar gaveta de notificação</string>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Módulos</string>
<string name="downloads">Transferir</string>
<string name="superuser">Super-Utilizador</string>
<string name="log">Registo</string>
<string name="settings">Definições</string>
<string name="status">Estado</string>
<string name="downloads">Transferir</string>
<string name="superuser">Super-Utilizador</string>
<string name="log">Registo</string>
<string name="settings">Definições</string>
<string name="install">Instalar</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s Instalado</string>
<string name="magisk_version_core_only">Magisk v%1$s Instalado(Somente em modo Core)</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk não instalado</string>
<string name="checking_for_updates">A procurar por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="cannot_check_updates">Não foi possível verificar atualizações, sem internet?</string>
<string name="up_to_date">Última versão do %1$s instalado</string>
<string name="checking_for_updates">A procurar por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="cannot_check_updates">Não foi possível verificar atualizações, sem internet?</string>
<string name="root_error">Com root mas sem permissão de root, o acesso foi permitido?</string>
<string name="not_rooted">Sem root</string>
<string name="proper_root">Root instalado corretamente</string>
<string name="not_rooted">Sem root</string>
<string name="safetyNet_check_text">Pressione para verificar SafetyNet</string>
<string name="checking_safetyNet_status">A verificar o estado do SafetyNet…</string>
<string name="safetyNet_connection_failed">Não é possível ligar à API do Google</string>
<string name="safetyNet_connection_suspended">A ligação com API do Google foi suspensa</string>
<string name="checking_safetyNet_status">A verificar o estado do SafetyNet…</string>
<string name="safetyNet_check_success">SafetyNet verificado com sucesso</string>
<string name="safetyNet_no_response">Não é possível verificar o SafetyNet, sem Internet?</string>
<string name="safetyNet_fail">SafetyNet Falhou: perfil CTS não corresponde</string>
<string name="safetyNet_pass">SafetyNet Passado</string>
<string name="root_info_warning">Funcionalidade muito limitada</string>
<string name="safetyNet_network_loss">Perda de ligação</string>
<string name="safetyNet_service_disconnected">Serviço foi interrompido</string>
<string name="safetyNet_res_invalid">A resposta é inválida</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Não foi auto detetado)</string>
<string name="boot_image_title">Local da Imagem de Arranque</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Definições avançadas</string>
<string name="keep_force_encryption">Manter encriptação forçada</string>
<string name="keep_dm_verity">Manter dm-verity</string>
<string name="current_magisk_title">Versão instalada do Magisk: %1$s</string>
<string name="install_magisk_title">Última versão do Magisk: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="reboot_countdown">A reiniciar em %1$d</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="uninstall_magisk_msg">Isso irá remover todos os módulos, MagiskSU, e Potencialmente encriptar seus dados se estiverem encriptados\nDeseja continuar?</string>
<string name="version_none">(Nenhum)</string>
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Não foi auto detetado)</string>
<string name="boot_image_title">Local da Imagem de Arranque</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Definições avançadas</string>
<string name="keep_force_encryption">Manter encriptação forçada</string>
<string name="keep_dm_verity">Manter dm-verity</string>
<string name="current_magisk_title">Versão instalada do Magisk: %1$s</string>
<string name="install_magisk_title">Última versão do Magisk: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="reboot_countdown">A reiniciar em %1$d</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="update">Atualizar %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
<string name="no_modules_found">Nenhum módulo encontrado</string>
<string name="update_file_created">Módulo será atualizado depois de reiniciar</string>
<string name="remove_file_created">Módulo será removido depois de reiniciar</string>
<string name="remove_file_deleted">Módulo não será removido ao reiniciar</string>
<string name="disable_file_created">Módulo será desativado depois de reiniciar</string>
<string name="disable_file_removed">Módulo será ativado depois de reiniciar</string>
<string name="author">Criado por %1$s</string>
<string name="fab_flash_zip">Instalar Módulo Zip</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
<string name="no_modules_found">Nenhum módulo encontrado</string>
<string name="update_file_created">Módulo será atualizado depois de reiniciar</string>
<string name="remove_file_created">Módulo será removido depois de reiniciar</string>
<string name="remove_file_deleted">Módulo não será removido ao reiniciar</string>
<string name="disable_file_created">Módulo será desativado depois de reiniciar</string>
<string name="disable_file_removed">Módulo será ativado depois de reiniciar</string>
<string name="author">Criado por %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Atualização disponível</string>
<string name="installed">Instalado</string>
<string name="not_installed">Não Instalado</string>
<string name="update_available">Atualização disponível</string>
<string name="installed">Instalado</string>
<string name="not_installed">Não Instalado</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Gravar no SD</string>
<string name="menuReload">Recarregar</string>
<string name="menuClearLog">Limpar registo agora</string>
<string name="logs_cleared">Registo limpo com sucesso</string>
<string name="log_is_empty">Registo está vazio</string>
<string name="logs_save_failed">Não foi possível gravar o registo para o cartão SD:</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Gravar no SD</string>
<string name="menuReload">Recarregar</string>
<string name="menuClearLog">Limpar registo agora</string>
<string name="logs_cleared">Registo limpo com sucesso</string>
<string name="log_is_empty">Registo está vazio</string>
<string name="logs_save_failed">Não foi possível gravar o registo para o cartão SD:</string>
<!--About Activity-->
<string name="about">Sobre</string>
<string name="app_developers">Principais programadores</string>
<string name="app_developers_"><![CDATA[App criado por <a href="https://github.com/topjohnwu">topjohnwu</a> em colaboração com <a href="https://github.com/d8ahazard">Digitalhigh</a> e <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Lista de alterações da aplicação</string>
<string name="translators">Bruno Guerreiro</string>
<string name="app_version">Versão do aplicação</string>
<string name="app_source_code">Código fonte</string>
<string name="donation">Doar</string>
<string name="app_translators">Tradutores da Aplicação</string>
<string name="support_thread">Suporte</string>
<!--About Activity-->
<string name="about">Sobre</string>
<string name="app_developers">Principais programadores</string>
<string name="app_developers_"><![CDATA[App criado por <a href="https://github.com/topjohnwu">topjohnwu</a> em colaboração com <a href="https://github.com/d8ahazard">Digitalhigh</a> e <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Lista de alterações da aplicação</string>
<string name="app_version">Versão do aplicação</string>
<string name="app_source_code">Código fonte</string>
<string name="donation">Doar</string>
<string name="app_translators">Tradutores da Aplicação</string>
<string name="support_thread">Suporte</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Esta funcionalidade não funcionará sem permissão de escrita do armazenamento externo.</string>
<string name="no_thanks">Não, Obrigado</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Deseja instalar%1$s ?</string>
<string name="download_install">Transferir &amp; instalar</string>
<string name="download">Transferir</string>
<string name="goto_install">Ir para secção instalar</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Esta funcionalidade não funcionará sem permissão de escrita do armazenamento externo.</string>
<string name="no_thanks">Não, Obrigado</string>
<string name="yes">Sim</string>
<string name="ok">OK</string>
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Deseja instalar%1$s agora?</string>
<string name="download">Transferir</string>
<string name="download_file_error">Erro ao transferir ficheiro</string>
<string name="install_error">Erro na instalação!</string>
<string name="invalid_zip">O zip não é um Módulo Magisk!!</string>
<string name="reboot_title">Instalação bem-sucedida!</string>
<string name="reboot_msg">Deseja reiniciar agora?</string>
<string name="install_error">Erro na instalação!</string>
<string name="invalid_zip">Este zip não é um Módulo Magisk!!</string>
<string name="reboot">Reiniciar</string>
<string name="copying_msg">A copiar zip para diretório temporário</string>
<string name="zip_install_progress_title">A instalar</string>
<string name="zip_unzip_msg">A descompactar ficheiro zip …</string>
<string name="zip_process_msg">A processar ficheiro zip …</string>
<string name="zip_install_progress_msg">A instalar %1$s</string>
<string name="no_magisk_title">Magisk Não Instalado!</string>
<string name="no_magisk_msg">Deseja transferir e instalar o Magisk?</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar definições</string>
<string name="release_notes">Notas da atualização</string>
<string name="repo_cache_cleared">Cache do repositório apagado</string>
<string name="safetyNet_hide_notice">Esta aplicação usa SafetyNet\nJá manipulado pelo MagiskHide por padrão</string>
<string name="start_magiskhide">A iniciar MagiskHide …</string>
<string name="no_magisksu_title">Não está a usar MagiskSU!</string>
<string name="no_magisksu_msg">Não está root instalado com MagiskSU, Usar somente MagiskHide pode não ser suficiente!\nNão é oficialmente suportado, E precisaria de ferramentas adicionais (ex: suhide) para passar pelo SafetyNet.</string>
<string name="understand">Eu entendo</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar definições</string>
<string name="release_notes">Notas da atualização</string>
<string name="repo_cache_cleared">Cache do repositório apagado</string>
<string name="safetyNet_hide_notice">Esta aplicação usa SafetyNet
\nJá manipulado pelo MagiskHide por padrão</string>
<string name="process_error">Erro no processo</string>
<string name="internal_storage">O zip foi guardado em:\n[Armazenamento interno]%1$s</string>
<string name="zip_process_title">A processar</string>
<string name="manual_boot_image">Por Favor, selecione manualmente a imagem de Arranque</string>
<!--Settings Fragment -->
<string name="settings_general_category">Geral</string>
<string name="settings_dark_theme_title">Tema escuro</string>
<string name="settings_dark_theme_summary">Ativa o tema escuro</string>
<string name="settings_notification_title">Notificação de Atualização</string>
<string name="settings_notification_summary">Mostrar notificações de atualização quando a nova versão estiver disponível</string>
<string name="settings_clear_cache_title">Apagar Cache de Repositório</string>
<string name="settings_clear_cache_summary">Apaga a informação cache de repositórios online. online, forçando a aplicação a atualizar online</string>
<string name="internal_storage">O zip foi guardado em:
\n[Armazenamento interno]%1$s</string>
<string name="zip_process_title">A processar</string>
<string name="manual_boot_image">Por Favor, selecione manualmente a imagem de Arranque</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="manager_download_install">Pressione para transferir e instalar</string>
<string name="magisk_updates">Atualizações do Magisk</string>
<string name="flashing">A instalar</string>
<string name="settings_core_only_title">Magisk somente em Modo Core</string>
<string name="settings_core_only_summary">Ativar somente funcionalidades principais, todos os módulos não serão carregados. MagiskSU, MagiskHide, e systemless hosts ainda estará ativado</string>
<string name="settings_magiskhide_summary">Oculta Magisk de várias deteções</string>
<string name="settings_busybox_title">Ativar BusyBox</string>
<string name="settings_busybox_summary">Ativar systemless hosts</string>
<!--Settings Activity -->
<string name="settings_general_category">Geral</string>
<string name="settings_dark_theme_title">Tema escuro</string>
<string name="settings_dark_theme_summary">Ativa o tema escuro</string>
<string name="settings_notification_title">Notificação de Atualização</string>
<string name="settings_notification_summary">Mostrar notificações de atualização quando a nova versão estiver disponível</string>
<string name="settings_clear_cache_title">Apagar Cache de Repositório</string>
<string name="settings_clear_cache_summary">Apaga a informação cache de repositórios online. online, forçando a aplicação a atualizar online</string>
<string name="language">Língua</string>
<string name="system_default">(Padrão do Sistema)</string>
<string name="settings_core_only_title">Magisk somente em Modo Core</string>
<string name="settings_core_only_summary">Ativar somente funcionalidades principais, todos os módulos não serão carregados. MagiskSU, MagiskHide, e systemless hosts ainda estará ativado</string>
<string name="settings_magiskhide_summary">Oculta Magisk de várias deteções</string>
<string name="settings_hosts_title">Ativar systemless hosts</string>
<string name="settings_hosts_summary">Suporte de systemless para aplicações Adblock</string>
<string name="settings_hosts_summary">Suporte de systemless para aplicações Adblock</string>
<string name="settings_su_app_adb">Aplicações e ADB</string>
<string name="settings_su_app">Somente Aplicações</string>
<string name="settings_su_adb">Somente ADB</string>
<string name="settings_su_disable">Desativado</string>
<string name="settings_su_request_10">10 segundos</string>
<string name="settings_su_request_20">20 segundos</string>
<string name="settings_su_request_30">30 segundos</string>
<string name="settings_su_request_60">60 segundos</string>
<string name="superuser_access">Acesso de Super-Utilizador</string>
<string name="auto_response">Resposta Automática</string>
<string name="request_timeout">Tempo limite de solicitação</string>
<string name="superuser_notification">Notificação de Super-Utilizador</string>
<string name="request_timeout_summary">%1$s segundos</string>
<string name="settings_su_app_adb">Aplicações e ADB</string>
<string name="settings_su_app">Somente Aplicações</string>
<string name="settings_su_adb">Somente ADB</string>
<string name="settings_su_disable">Desativado</string>
<string name="settings_su_request_10">10 segundos</string>
<string name="settings_su_request_20">20 segundos</string>
<string name="settings_su_request_30">30 segundos</string>
<string name="settings_su_request_60">60 segundos</string>
<string name="superuser_access">Acesso de Super-Utilizador</string>
<string name="auto_response">Resposta Automática</string>
<string name="request_timeout">Tempo limite de solicitação</string>
<string name="superuser_notification">Notificação de Super-Utilizador</string>
<string name="request_timeout_summary">%1$s segundos</string>
<string name="settings_su_reauth_title">Autenticar novamente após atualizar</string>
<string name="settings_su_reauth_summary">Autenticar novamente permissões de Super-Utilizador após atualizar aplicações</string>
<string name="settings_development_category">Desenvolvimento</string>
<string name="settings_developer_logging_title">Ativar registo mais detalhado</string>
<string name="settings_developer_logging_summary">Marque essa opção para permitir um registo mais detalhado</string>
<string name="settings_shell_logging_title">Ativar registo da linha de comandos</string>
<string name="settings_shell_logging_summary">Marque esta opção para permitir o registo de todos os comandos</string>
<string name="multiuser_mode">Modo Multi-Utilizador</string>
<string name="settings_owner_only">Apenas Proprietário de Dispositivo</string>
<string name="settings_owner_manage">Gerido Proprietário do Dispositivo</string>
<string name="settings_user_independent">Independente de Utilizadores</string>
<string name="owner_only_summary">Apenas o proprietário tem acesso a root</string>
<string name="owner_manage_summary">Apenas o proprietário pode gerir acesso root e receber pedidos</string>
<string name="user_indepenent_summary">Cada utilizador tem suas próprias regras de root separadas</string>
<string name="multiuser_hint_owner_request">Um pedido foi enviado ao proprietário do dispositivo. Mude para o proprietário e conceda a permissão</string>
<!--Superuser-->
<string name="su_request_title">Pedido de Super-Utilizador</string>
<string name="deny_with_str">Negar%1$s</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="grant">Permitir</string>
<string name="su_warning">Concede acesso total ao seu dispositivo.\nNegue se não tiver certeza!</string>
<string name="forever">Sempre</string>
<string name="once">Uma vez</string>
<string name="tenmin">10 minutos</string>
<string name="twentymin">20 minutos</string>
<string name="thirtymin">30 minutos</string>
<string name="sixtymin">60 minutos</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de Super-Utilizador</string>
<string name="su_deny_toast">%1$s foi negado o acesso de Super-Utilizador</string>
<string name="no_apps_found">Não foram encontrados aplicações</string>
<string name="su_snack_grant">Acesso de Super-Utilizador a %1$s foi permitido</string>
<string name="su_snack_deny">Acesso de Super-Utilizador a %1$s foi negado</string>
<string name="su_snack_notif_on">Notificações de %1$s está ativado</string>
<string name="su_snack_notif_off">Notificações da %1$s está desativado</string>
<string name="su_snack_log_on">Registo de %1$s está ativado</string>
<string name="su_snack_log_off">Registo de %1$s está desativado</string>
<string name="su_snack_revoke">%1$s direitos foram revogados</string>
<string name="su_revoke_title">Revogar?</string>
<string name="su_revoke_msg">Revogar os diretos do %1$s, Confirmar?</string>
<string name="toast">Notificação(pop-up)</string>
<string name="none">Nenhum</string>
<string name="mount_namespace_mode">Cada sessão root terá sua própria identificação isolada</string>
<string name="settings_ns_global">Identificação Global</string>
<string name="settings_ns_requester">Herdar Identificação</string>
<string name="settings_ns_isolate">Identificação Isolada</string>
<string name="global_summary">Todas as sessões root usam a identificação de montagem global</string>
<string name="requester_summary">As sessões de root herdarão a identificação do seu solicitante</string>
<string name="isolate_summary">Cada sessão root terá sua própria identificação isolada</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Alvo UID:\u0020</string>
<string name="command">Comando:\u0020</string>
<string name="safetyNet_check_success">SafetyNet verificado com sucesso</string>
<string name="safetyNet_network_loss">Perda de ligação</string>
<string name="safetyNet_service_disconnected">Serviço foi interrompido</string>
<string name="safetyNet_res_invalid">A resposta é inválida</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="manager_download_install">Pressione para transferir e instalar</string>
<string name="settings_su_reauth_title">Autenticar novamente após atualizar</string>
<string name="settings_su_reauth_summary">Autenticar novamente permissões de Super-Utilizador após atualizar aplicações</string>
<string name="multiuser_mode">Modo Multi-Utilizador</string>
<string name="settings_owner_only">Apenas Proprietário de Dispositivo</string>
<string name="settings_owner_manage">Gerido Proprietário do Dispositivo</string>
<string name="settings_user_independent">Independente de Utilizadores</string>
<string name="owner_only_summary">Apenas o proprietário tem acesso a root</string>
<string name="owner_manage_summary">Apenas o proprietário pode gerir acesso root e receber pedidos</string>
<string name="user_indepenent_summary">Cada utilizador tem suas próprias regras de root separadas</string>
<string name="multiuser_hint_owner_request">Um pedido foi enviado ao proprietário do dispositivo. Mude para o proprietário e conceda a permissão</string>
<string name="mount_namespace_mode">Cada sessão root terá sua própria identificação isolada</string>
<string name="settings_ns_global">Identificação Global</string>
<string name="settings_ns_requester">Herdar Identificação</string>
<string name="settings_ns_isolate">Identificação Isolada</string>
<string name="global_summary">Todas as sessões root usam a identificação de montagem global</string>
<string name="requester_summary">As sessões de root herdarão a identificação do seu solicitante</string>
<string name="isolate_summary">Cada sessão root terá sua própria identificação isolada</string>
<string name="settings_development_category">Desenvolvimento</string>
<string name="settings_developer_logging_title">Ativar registo mais detalhado</string>
<string name="settings_developer_logging_summary">Marque essa opção para permitir um registo mais detalhado</string>
<string name="settings_shell_logging_title">Ativar registo da linha de comandos</string>
<string name="settings_shell_logging_summary">Marque esta opção para permitir o registo de todos os comandos</string>
<!--Superuser-->
<string name="su_request_title">Pedido de Super-Utilizador</string>
<string name="deny_with_str">Negar%1$s</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
<string name="grant">Permitir</string>
<string name="su_warning">Concede acesso total ao seu dispositivo.
\nNegue se não tiver certeza!</string>
<string name="forever">Sempre</string>
<string name="once">Uma vez</string>
<string name="tenmin">10 minutos</string>
<string name="twentymin">20 minutos</string>
<string name="thirtymin">30 minutos</string>
<string name="sixtymin">60 minutos</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de Super-Utilizador</string>
<string name="su_deny_toast">%1$s foi negado o acesso de Super-Utilizador</string>
<string name="no_apps_found">Não foram encontrados aplicações</string>
<string name="su_snack_grant">Acesso de Super-Utilizador a %1$s foi permitido</string>
<string name="su_snack_deny">Acesso de Super-Utilizador a %1$s foi negado</string>
<string name="su_snack_notif_on">Notificações de %1$s está ativado</string>
<string name="su_snack_notif_off">Notificações da %1$s está desativado</string>
<string name="su_snack_log_on">Registo de %1$s está ativado</string>
<string name="su_snack_log_off">Registo de %1$s está desativado</string>
<string name="su_snack_revoke">%1$s direitos foram revogados</string>
<string name="su_revoke_title">Revogar?</string>
<string name="su_revoke_msg">Revogar os diretos do %1$s, Confirmar?</string>
<string name="toast">Notificação(pop-up)</string>
<string name="none">Nenhum</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Alvo UID:\u0020</string>
<string name="command">Comando:\u0020</string>
</resources>

View File

@@ -1,35 +1,23 @@
<resources>
<!--Welcome Activity-->
<string name="navigation_drawer_open">Deschide sertarul de navigare</string>
<string name="navigation_drawer_close">Închide sertarul de navigare</string>
<string name="modules">Module</string>
<string name="downloads">Descărcări</string>
<string name="superuser">Superuser</string>
<string name="log">Jurnal</string>
<string name="settings">Setări</string>
<string name="status">Stare</string>
<string name="install">Instalare</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk instalat v%1$s</string>
<string name="magisk_version_core_only">Magisk instalat v%1$s (Mod de bază)</string>
<string name="magisk_version_error">Magisk nu este instalat</string>
<string name="checking_for_updates">Verificare actualizări…</string>
<string name="magisk_update_available">Magisk v%1$s disponibil!</string>
<string name="cannot_check_updates">Nu se pot verifica actualizările, nu este internet?</string>
<string name="up_to_date">Ultima versiune a %1$s este instalată</string>
<string name="root_error">Root obţinut, dar fără permisiune root, nu este permis?</string>
<string name="not_rooted">Nu este obţinut root</string>
<string name="proper_root">Root obţinut corect</string>
<string name="safetyNet_check_text">Apăsați pentru a începe verificarea SafetyNet</string>
<string name="safetyNet_check_text">Verificare SafetyNet</string>
<string name="checking_safetyNet_status">Verificarea stării SafetyNet…</string>
<string name="safetyNet_connection_failed">Nu se poate conecta la Google API</string>
<string name="safetyNet_connection_suspended">Conexiunea la API-ul Google a fost suspendată</string>
<string name="safetyNet_no_response">Nu se poate verifica SafetyNet, nu este internet?</string>
<string name="safetyNet_fail">SafetyNet eșuat: nepotrivire profil CTS</string>
<string name="safetyNet_pass">SafetyNet a trecut</string>
<string name="root_info_warning">Funcționalitatea este foarte limitată</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -44,8 +32,8 @@
<string name="uninstall">Dezinstalare</string>
<string name="reboot_countdown">Repornire în %1$d</string>
<string name="uninstall_magisk_title">Dezinstalare Magisk</string>
<string name="uninstall_magisk_msg">Aceasta va elimina toate modulele, MagiskSU, şi potențial să cripteze datele, dacă nu sunt criptate\nContinuaţi?</string>
<string name="version_none">(Niciuna)</string>
<string name="update">Actualizare %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nu sunt furnizate informații)</string>
@@ -56,7 +44,6 @@
<string name="disable_file_created">Modulul va fi dezactivat la următoarea repornire</string>
<string name="disable_file_removed">Modulul va fi activat la următoarea repornire</string>
<string name="author">Creat de %1$s</string>
<string name="fab_flash_zip">Modul Zip</string>
<!--Repo Fragment-->
<string name="update_available">Actualizare disponibilă</string>
@@ -91,38 +78,28 @@
<string name="close">Închide</string>
<string name="repo_install_title">Instalare %1$s</string>
<string name="repo_install_msg">Instalaţi %1$s?</string>
<string name="download_install">Descărcare şi instalare</string>
<string name="download">Descărcare</string>
<string name="goto_install">Accesaţi secţiunea \"Instalare\"</string>
<string name="download_file_error">Eroare la descărcarea fișierului</string>
<string name="install_error">Eroare de instalare!</string>
<string name="invalid_zip">Zip-ul nu este un modul Magisk!!</string>
<string name="reboot_title">Instalarea a reușit!</string>
<string name="reboot_msg">Reporniţi acum?</string>
<string name="invalid_zip">Zip-ul nu este un modul Magisk!</string>
<string name="reboot">Repornire</string>
<string name="copying_msg">Copierea zip-ului în dosarul temp</string>
<string name="zip_install_progress_title">Instalare</string>
<string name="zip_unzip_msg">Dezarhivarea fișierului zip…</string>
<string name="zip_process_msg">Procesare fişierului zip…</string>
<string name="zip_install_progress_msg">Instalare %1$s…</string>
<string name="no_magisk_title">Magisk nu este instalat!</string>
<string name="no_magisk_msg">Doriți să descărcați și să instalați Magisk?</string>
<string name="downloading_toast">Descărcare %1$s</string>
<string name="magisk_update_title">O nouă actualizare Magisk este disponibilă!</string>
<string name="settings_reboot_toast">Reporniți pentru a aplica setările</string>
<string name="release_notes">Note de lansare</string>
<string name="repo_cache_cleared">Arhive cache eliminate</string>
<string name="safetyNet_hide_notice">Această aplicație utilizează SafetyNet\nDeja gestionat de MagiskHide în mod implicit</string>
<string name="start_magiskhide">Pornire MagiskHide…</string>
<string name="no_magisksu_title">Nu se utilizează MagiskSU!</string>
<string name="no_magisksu_msg">Nu aţi obţinut acces la root cu MagiskSU, utilizarea MagiskHide s-ar putea să nu fie suficientă!\nNu este susținută oficial și veți avea nevoie de instrumente suplimentare (de ex. suhide) pentru a trece Safety Net.</string>
<string name="understand">Înţeleg</string>
<string name="process_error">Eroare de proces</string>
<string name="internal_storage">Zip stocat în:\n[Stocare internă]%1$s</string>
<string name="zip_process_title">Procesare</string>
<string name="manual_boot_image">Selectați manual o imagine de boot!</string>
<string name="manager_update_title">O nouă actualizare pentru Magisk Manager este disponibilă!</string>
<string name="manager_download_install">Apăsați pentru a descărca și instala</string>
<string name="magisk_updates">Actualizări Magisk</string>
<string name="flashing">Flashing</string>
<string name="hide_manager_toast">Ascundere Magisk Manager…</string>
<string name="hide_manager_fail_toast">Ascunderea Magisk Manager a eşuat</string>
<!--Settings Activity -->
<string name="settings_general_category">General</string>
@@ -132,12 +109,14 @@
<string name="settings_notification_summary">Se afișează notificări de actualizare atunci când este disponibilă o nouă versiune</string>
<string name="settings_clear_cache_title">Eliminare cache</string>
<string name="settings_clear_cache_summary">Ștergeți informațiile memorate în cache, forțează actualizarea aplicației online</string>
<string name="settings_hide_manager_title">Ascundeţi Magisk Manager</string>
<string name="settings_hide_manager_summary">Ascundeţi temporar Magisk Manager.\nAceasta va instala o nouă aplicație numită \"Unhide Magisk Manager\"</string>
<string name="language">Limbă</string>
<string name="system_default">(Implicit)</string>
<string name="settings_core_only_title">Mod de bază</string>
<string name="settings_core_only_summary">Se activează numai caracteristicile principale, toate modulele nu vor fi încărcate. MagiskSU, MagiskHide şi systemless hosts vor fi în continuare activate</string>
<string name="settings_magiskhide_summary">Ascundeţi Magisk de la diferite detectări</string>
<string name="settings_busybox_title">Activare BusyBox</string>
<string name="settings_busybox_summary">Montare busybox Magisk în xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Systemless hosts suport pentru aplicațiile Adblock</string>

View File

@@ -2,45 +2,33 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Открыть меню навигации</string>
<string name="navigation_drawer_close">Закрыть меню навигации</string>
<string name="modules">Модули</string>
<string name="downloads">Загрузки</string>
<string name="superuser">Суперпользователь</string>
<string name="log">История</string>
<string name="settings">Настройки</string>
<string name="status">Состояние</string>
<string name="install">Установка</string>
<!--Status Fragment-->
<string name="magisk_version">Установлен Magisk v%1$s</string>
<string name="magisk_version_core_only">Установлен Magisk v%1$s (Базовый режим)</string>
<string name="magisk_version_error">Magisk не установлен</string>
<string name="checking_for_updates">Проверка обновлений…</string>
<string name="magisk_update_available">Доступен Magisk v%1$s!</string>
<string name="cannot_check_updates">Невозможно проверить наличие обновлений</string>
<string name="up_to_date">Установлена последняя версия %1$s</string>
<string name="root_error">Root присутствует, но отсутствует разрешение</string>
<string name="not_rooted">Root отсутствует</string>
<string name="proper_root">Корректный root-доступ</string>
<string name="safetyNet_check_text">Проверить статус SafetyNet</string>
<string name="checking_safetyNet_status">Проверка статуса SafetyNet…</string>
<string name="safetyNet_check_success">Проверка SafetyNet пройдена</string>
<string name="safetyNet_connection_failed">Невозможно подключиться к Google API</string>
<string name="safetyNet_connection_suspended">Подключение к Google API было прервано</string>
<string name="safetyNet_no_response">Невозможно выполнить проверку SafetyNet</string>
<string name="safetyNet_fail">Проверка SafetyNet неудачна: несоответствие профиля CTS</string>
<string name="safetyNet_pass">Проверка SafetyNet пройдена</string>
<string name="safetyNet_network_loss">Подключение к интернету прервано</string>
<string name="safetyNet_service_disconnected">Служба была остановлена</string>
<string name="safetyNet_res_invalid">Некорректный ответ</string>
<string name="root_info_warning">Функциональность значительно ограничена</string>
<!--Install Fragment-->
<string name="auto_detect">(Авто) %1$s</string>
<string name="cannot_auto_detect">(Автоопределение невозможно)</string>
<string name="boot_image_title">Распоожение boot-образа</string>
<string name="boot_image_title">Расположение boot-образа</string>
<string name="detect_button">Определить</string>
<string name="advanced_settings_title">Расширенные настройки</string>
<string name="keep_force_encryption">Оставить принуд. шифрование</string>
@@ -50,9 +38,9 @@
<string name="uninstall">Удалить</string>
<string name="reboot_countdown">Перезагрузка через %1$d</string>
<string name="uninstall_magisk_title">Удалить Magisk</string>
<string name="uninstall_magisk_msg">Данное действие приведет к удалению всех модулей, MagiskSU, и может зашифровать данные, если они не зашифрованы.\nУверены, что желаете продолжить?</string>
<string name="version_none">(Нет данных)</string>
<string name="uninstall_magisk_msg">Все модули были отключены либо удалены. Root-доступ будет удален, данные зашифруются, если до сих пор не были зашифрованы</string>
<string name="update">Обновить %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Нет предоставленной информации)</string>
<string name="no_modules_found">Модули не обнаружены</string>
@@ -62,7 +50,6 @@
<string name="disable_file_created">Модуль будет отключен при перезагрузке</string>
<string name="disable_file_removed">Модуль будет включен при перезагрузке</string>
<string name="author">Автор: %1$s</string>
<string name="fab_flash_zip">Прошить архив с модулем</string>
<!--Repo Fragment-->
<string name="update_available">Доступно обновление</string>
@@ -97,38 +84,42 @@
<string name="close">Закрыть</string>
<string name="repo_install_title">Установить %1$s</string>
<string name="repo_install_msg">Желаете установить %1$s ?</string>
<string name="download_install">Скачать и установить</string>
<string name="download">Скачать</string>
<string name="goto_install">Перейти в раздел \"Установка\"</string>
<string name="download_file_error">Ошибка скачивания файла</string>
<string name="install_error">Ошибка во время установки!</string>
<string name="invalid_zip">В архив отсутствует модуль Magisk!</string>
<string name="reboot_title">Установка успешна!</string>
<string name="reboot_msg">Желаете перезагрузить сейчас?</string>
<string name="reboot">Перезагрузка</string>
<string name="copying_msg">Копирование архива во временную папку</string>
<string name="zip_install_progress_title">Установка</string>
<string name="zip_unzip_msg">Распаковка архива …</string>
<string name="zip_process_msg">Обработка архива …</string>
<string name="zip_install_progress_msg">Установка %1$s …</string>
<string name="no_magisk_title">Magisk не установлен!</string>
<string name="no_magisk_msg">Желаете скачать и установить Magisk?</string>
<string name="downloading_toast">Скачивание %1$s</string>
<string name="magisk_update_title">Доступно новое обновление Magisk!</string>
<string name="settings_reboot_toast">Для применения настроек выполните перезагрузку</string>
<string name="release_notes">Особенности версии</string>
<string name="repo_cache_cleared">Кеш репозитория очищен</string>
<string name="safetyNet_hide_notice">Данное приложение использует SafetyNet.\nУже обработано MagiskHide по умолчанию</string>
<string name="start_magiskhide">Запуск MagiskHide …</string>
<string name="no_magisksu_title">Не использовать MagiskSU!</string>
<string name="no_magisksu_msg">В том случае, если root-доступ получен не с помощью MagiskSU, использования MagiskHide может быть недостаточно!\nОфициально не поддерживается, следовательно, могут понадобиться дополнительные инструменты (например, suhide), для успешного прохождения проверки Safety Net</string>
<string name="understand">Понимаю</string>
<string name="process_error">Ошибка обработки</string>
<string name="internal_storage">Архив расположен:\n[Внутреннее Хранилище]%1$s</string>
<string name="zip_download_title">Загрузка</string>
<string name="zip_download_msg">Загрузка архива…</string>
<string name="zip_process_title">Обработка</string>
<string name="zip_process_msg">Обработка архива…</string>
<string name="manual_boot_image">Пожалуйста, выберите вручную boot-образ!</string>
<string name="manager_update_title">Доступно новое обновление менеджера Magisk!</string>
<string name="manager_download_install">Нажмите, чтобы скачать и установить</string>
<string name="magisk_updates">Обновления Magisk</string>
<string name="flashing">Прошивка…</string>
<string name="hide_manager_toast">Скрытие Менеджера Magisk…</string>
<string name="hide_manager_fail_toast">Скрытие Менеджера Magisk неудачно…</string>
<string name="download_zip_only">Загрузка только архива</string>
<string name="patch_boot_file">Пропатчить boot-образ</string>
<string name="direct_install">Непосредственная установка (рекомендуется)</string>
<string name="install_second_slot">Установить во Второй Слот (после OTA)</string>
<string name="select_method">Выбрать способ</string>
<string name="no_boot_file_patch_support">Целевая версия Magisk не поддерживает патчинг boot-образа</string>
<string name="boot_file_patch_msg">Выберите оригинальный дамп boot-образа, .img либо .img.tar формата</string>
<string name="complete_uninstall">Удаление завершено</string>
<string name="restore_stock_boot">Восстановить оригинальный boot-образ</string>
<string name="restore_done">Восстановление завершено!</string>
<string name="restore_fail">Резервная копия отсутствует!</string>
<string name="uninstall_toast">Удаление менеджера Magisk в течении 5 секунд, затем, пожалуйста, вручную выполните перезагрузку</string>
<!--Settings Activity -->
<string name="settings_general_category">Основные</string>
@@ -138,12 +129,20 @@
<string name="settings_notification_summary">Показывать уведомления об обновлении, когда доступна новая версия</string>
<string name="settings_clear_cache_title">Очистка кеша</string>
<string name="settings_clear_cache_summary">Очистить сохранённую информацию о сетевых репозиториях, заставляя приложение принудительно обновляться через Интернете</string>
<string name="settings_hide_manager_title">Скрыть Менеджер Magisk</string>
<string name="settings_hide_manager_summary">Временно скрывает Менеджер Magisk.\nБудет установлено новое приложение, называется \"Unhide Magisk Manager\"</string>
<string name="language">Язык</string>
<string name="system_default">По умолчанию (системный)</string>
<string name="settings_update">Настройки обновления</string>
<string name="settings_update_channel_title">Источник обновления</string>
<string name="settings_update_stable">Стабильный релиз</string>
<string name="settings_update_beta">Релиз beta</string>
<string name="settings_boot_format_title">Формат boot-образа</string>
<string name="settings_boot_format_summary">Выберите тип выходного формата патченого boot-образа.\n.img - для прошивки с помощью fastboot либо режима download\n.img.tar - для прошивки с помощью ODIN</string>
<string name="settings_core_only_title">Режим Magisk Core</string>
<string name="settings_core_only_summary">Включить возможности только уровня Core, все модули не будут загружены. MagiskSU, MagiskHide и внесистемные хосты останутся включенными</string>
<string name="settings_magiskhide_summary">Скрыть Magisk от различных проверок</string>
<string name="settings_busybox_title">Включить BusyBox</string>
<string name="settings_busybox_summary">Монтирование встроенного в Magisk busybox в xbin</string>
<string name="settings_hosts_title">Внесистемные хосты</string>
<string name="settings_hosts_summary">Поддержка внесистемных хостов для приложений блокировки рекламы</string>

View File

@@ -0,0 +1,193 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moduler</string>
<string name="downloads">Nerladdningar</string>
<string name="superuser">Superuser</string>
<string name="log">Logg</string>
<string name="settings">Inställningar</string>
<string name="install">Install</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk är inte installerad</string>
<string name="checking_for_updates">Söker efter uppdateringar…</string>
<string name="magisk_update_available">Magisk v%1$s tillgänglig!</string>
<string name="cannot_check_updates">Kan inte söka efter uppdateringar, inget internet?</string>
<string name="root_error">Rootad men inga root-rättigheter, inte tillåtet?</string>
<string name="not_rooted">Inte rootad</string>
<string name="safetyNet_check_text">Tryck för att starta SafetyNet-kontroll</string>
<string name="checking_safetyNet_status">Kontrollerar SafetyNet-status…</string>
<string name="safetyNet_check_success">SafetyNet-kontroll lyckades</string>
<string name="safetyNet_no_response">Kan inte kontrollera SafetyNet, inget internet?</string>
<string name="safetyNet_network_loss">Tappade nätverksanslutningen</string>
<string name="safetyNet_service_disconnected">Tjänsten har dödats</string>
<string name="safetyNet_res_invalid">Svaret är ogiltigt</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Det går inte att auto-detektera)</string>
<string name="boot_image_title">Boot-image plats</string>
<string name="detect_button">Detektera</string>
<string name="advanced_settings_title">Advancerade inställningar</string>
<string name="keep_force_encryption">Fortsätt tvinga kryptering</string>
<string name="keep_dm_verity">Behåll dm-verity</string>
<string name="current_magisk_title">Installerad Magisk: %1$s</string>
<string name="install_magisk_title">Senaste Magisk: %1$s</string>
<string name="uninstall">Avinstallera</string>
<string name="reboot_countdown">Omstart om %1$d</string>
<string name="uninstall_magisk_title">Avinstallera Magisk</string>
<string name="update">Uppdatera %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Ingen information tillhandahållen)</string>
<string name="no_modules_found">Hittade inga moduler</string>
<string name="update_file_created">Modulen kommer att uppdateras vid nästa omstart</string>
<string name="remove_file_created">Modulen kommer att tas bort vid nästa omstart</string>
<string name="remove_file_deleted">Modulen kommer att inte att tas bort vid nästa omstart</string>
<string name="disable_file_created">Modulen kommer att inaktiveras vid nästa omstart</string>
<string name="disable_file_removed">Modulen kommer att aktiveras vid nästa omstart</string>
<string name="author">Skapad av %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Uppdatering tillgänglig</string>
<string name="installed">Installerad</string>
<string name="not_installed">Inte installerad</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Spara till SD-kort</string>
<string name="menuReload">Uppdatera</string>
<string name="menuClearLog">Rensa loggen</string>
<string name="logs_cleared">Loggen rensad</string>
<string name="log_is_empty">Loggen är tom</string>
<string name="logs_save_failed">Loggen kunde inte skrivas till SD-kort:</string>
<!--About Activity-->
<string name="about">Om</string>
<string name="app_developers">Huvudutvecklare</string>
<string name="app_developers_"><![CDATA[Appen skapades av <a href="https://github.com/topjohnwu">topjohnwu</a> i samarbete med <a href="https://github.com/d8ahazard">Digitalhigh</a> och <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Ändringslogg</string>
<string name="translators" />
<string name="app_version">Version</string>
<string name="app_source_code">Källkod</string>
<string name="donation">Donation</string>
<string name="app_translators">Översättare</string>
<string name="support_thread">Supporttråd</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Denna funktionen måste ha behörighet att skriva till externt lagringsutrymme.</string>
<string name="no_thanks">Nej tack</string>
<string name="yes">Ja</string>
<string name="ok">OK</string>
<string name="close">Stäng</string>
<string name="repo_install_title">Installera %1$s</string>
<string name="repo_install_msg">Vill du installera %1$s ?</string>
<string name="download">Ladda ner</string>
<string name="download_file_error">Fel vid nerladdning av fil</string>
<string name="install_error">Installation error!</string>
<string name="invalid_zip">ZIP-filen är inte en modul till Magisk!</string>
<string name="reboot">Starta om</string>
<string name="zip_process_msg">Bearbetar ZIP-filen …</string>
<string name="downloading_toast">Laddar ner %1$s</string>
<string name="magisk_update_title">En uppdatering av Magisk finns tillgänglig!</string>
<string name="settings_reboot_toast">Starta om för att tillämpa inställningar</string>
<string name="release_notes">Release notes</string>
<string name="repo_cache_cleared">Repo-cache rensad</string>
<string name="safetyNet_hide_notice">Denna appen använder SafetyNet\nHanteras redan av MagiskHide som standard</string>
<string name="process_error">Processfel</string>
<string name="internal_storage">ZIP-filen är sparad i:\n[Internal Storage]%1$s</string>
<string name="zip_process_title">Arbetar</string>
<string name="manual_boot_image">Välj manuellt en boot-image!</string>
<string name="manager_update_title">En uppdatering av Magisk maneger finns tillgänglig!</string>
<string name="manager_download_install">Tryck för att ladda ner och installera</string>
<string name="magisk_updates">Magiska uppdateringar</string>
<!--Settings Activity -->
<string name="settings_general_category">Allmän</string>
<string name="settings_dark_theme_title">Mörkt tema</string>
<string name="settings_dark_theme_summary">Aktivera mörkt tema</string>
<string name="settings_notification_title">Uppdateringsavisering</string>
<string name="settings_notification_summary">Visa en avisering när det finns en ny version tillgänglig</string>
<string name="settings_clear_cache_title">Rensa repo-cache</string>
<string name="settings_clear_cache_summary">Rensa den lagrade information för online-repos, tvingar appen att uppdatera online</string>
<string name="settings_core_only_title">Endast Magisk kärnläge</string>
<string name="settings_core_only_summary">Aktiverar endast kärnfunktioner, alla moduler laddas inte. MagiskSU, MagiskHide och systemless hosts kommer fortfarande att vara aktiverade</string>
<string name="settings_magiskhide_summary">Dölj Magisk från att bli upptäckt</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Systemless hosts-stöd för Adblock-appar</string>
<string name="settings_su_app_adb">Apps och ADB</string>
<string name="settings_su_app">Endast appar</string>
<string name="settings_su_adb">Endast ADB</string>
<string name="settings_su_disable">Inaktiverad</string>
<string name="settings_su_request_10">10 sekunder</string>
<string name="settings_su_request_20">20 sekunder</string>
<string name="settings_su_request_30">30 sekunder</string>
<string name="settings_su_request_60">60 sekunder</string>
<string name="superuser_access">Superuser-tillgång</string>
<string name="auto_response">Automatiskt svar</string>
<string name="request_timeout">Förfrågnings-timeout</string>
<string name="superuser_notification">Superuser-avisering</string>
<string name="request_timeout_summary">%1$s sekunder</string>
<string name="settings_su_reauth_title">Återautentisera efter uppdatering</string>
<string name="settings_su_reauth_summary">Återautentisera superuser-behörigheter efter en applikationsuppdatering</string>
<string name="multiuser_mode">Multianvändarläge</string>
<string name="settings_owner_only">Endast ägaren av enheten</string>
<string name="settings_owner_manage">Enhetsägarhantering</string>
<string name="settings_user_independent">Användaroberoende</string>
<string name="owner_only_summary">Endast ägaren har root-tillgång</string>
<string name="owner_manage_summary">Endast ägaren kan hantera root-åtkomst och få begärda förfrågningar</string>
<string name="user_indepenent_summary">Varje användare har sina egna separata root-regler</string>
<string name="multiuser_hint_owner_request">En förfrågan har skickats till enhetens ägaren. Byt till ägaren och bevilja behörigheten</string>
<string name="mount_namespace_mode">Montera namnrymdsläge</string>
<string name="settings_ns_global">Global namnrymd</string>
<string name="settings_ns_requester">Ärv namnrymden</string>
<string name="settings_ns_isolate">Isolerad namnrymd</string>
<string name="global_summary">Alla root-sessioner använder den globala monteringsnamnrymden</string>
<string name="requester_summary">Root-sessioner kommer att ärva den sökandes namnrymd</string>
<string name="isolate_summary">Varje root-session kommer att ha sin egen isolerade namnrymd</string>
<string name="settings_development_category">Apputveckling</string>
<string name="settings_developer_logging_title">Aktivera avancerad debug-loggning</string>
<string name="settings_developer_logging_summary">Markera för att aktivera detaljerad loggning</string>
<string name="settings_shell_logging_title">Aktivera felsökningsloggning av shell-kommandon</string>
<string name="settings_shell_logging_summary">Markera för att aktivera loggning av alla shell-kommandon och dess utmatning</string>
<!--Superuser-->
<string name="su_request_title">Superuser-förfrågan</string>
<string name="deny_with_str">Neka%1$s</string>
<string name="deny">Neka</string>
<string name="prompt">Fråga</string>
<string name="grant">Bevilja</string>
<string name="su_warning">Beviljar full tillgång till din enhet.\nNeka om du är osäker!</string>
<string name="forever">För alltid</string>
<string name="once">En gång</string>
<string name="tenmin">10 min</string>
<string name="twentymin">20 min</string>
<string name="thirtymin">30 min</string>
<string name="sixtymin">60 min</string>
<string name="su_allow_toast">%1$s är beviljad Superuser-rättigheter</string>
<string name="su_deny_toast">%1$s är nekad Superuser-rättigheter</string>
<string name="no_apps_found">Hittade inga appar</string>
<string name="su_snack_grant">Superuser-rättigheter av %1$s är beviljad</string>
<string name="su_snack_deny">Superuser-rättigheter av %1$s är nekad</string>
<string name="su_snack_notif_on">Aviseringar från %1$s är aktiverad</string>
<string name="su_snack_notif_off">Aviseringar från %1$s är inaktiverade</string>
<string name="su_snack_log_on">Loggning av %1$s är aktiverad</string>
<string name="su_snack_log_off">Loggning av %1$s är inaktiverad</string>
<string name="su_snack_revoke">%1$s rättigheter är upphävda</string>
<string name="su_revoke_title">Upphäv?</string>
<string name="su_revoke_msg">Bekräfta upphävning av %1$s rättigheter?</string>
<string name="toast">Toast-meddelande</string>
<string name="none">Inga</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Mål-UID:\u0020</string>
<string name="command">Kommando:\u0020</string>
</resources>

View File

@@ -1,50 +1,44 @@
<resources>
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Gezinti çekmecesini aç</string>
<string name="navigation_drawer_close">Gezinti çekmecesini kapat</string>
<string name="modules">Modüller</string>
<string name="modules">Modüller</string>
<string name="downloads">İndir</string>
<string name="superuser">Yetkili kullanıcı</string>
<string name="log">Günlük</string>
<string name="settings">Ayarlar</string>
<string name="status">Durum</string>
<string name="install">Yükle</string>
<!--Status Fragment-->
<string name="magisk_version">Magisk v%1$s yüklü</string>
<string name="magisk_version_error">Magisk yüklü değil</string>
<string name="magisk_version_error">Magisk yüklü değil</string>
<string name="checking_for_updates">Güncelleştirmeler denetleniyor…</string>
<string name="magisk_update_available">Magisk v%1$s mevcut!</string>
<string name="cannot_check_updates">Güncelleştirmeler denetlenemiyor, İnternet yok mu?</string>
<string name="up_to_date">%1$s\'in son sürümü yüklü</string>
<string name="root_error">Rootlu ama root izni yok, izin verilmedi mi?</string>
<string name="not_rooted">Rootlu değil</string>
<string name="proper_root">Düzgünce rootlandı</string>
<string name="cannot_check_updates">Güncelleştirmeler denetlenemiyor, İnternet bağlantınız yok mu?</string>
<string name="root_error">Kök erişimli ama kök erişimi izni yok, izin verilmedi mi?</string>
<string name="not_rooted">Kök erişimli değil</string>
<string name="safetyNet_check_text">SafetyNet kontrolünü başlatmak için dokunun</string>
<string name="checking_safetyNet_status">SafetyNet durumu kontrol ediliyor…</string>
<string name="safetyNet_connection_failed">"Google API'ye bağlanılamıyor"</string>
<string name="safetyNet_connection_suspended">Google API bağlantısı askıya alındı</string>
<string name="safetyNet_no_response">SafetyNet kontrol edilemiyor, İnternet yok mu?</string>
<string name="safetyNet_fail">SafetyNet başarısız: CTS profili uyumsuzluğu</string>
<string name="safetyNet_pass">SafetyNet Gti</string>
<string name="root_info_warning">İşlevsellik çok sınırlıdır</string>
<string name="safetyNet_check_success">SafetyNet Kontrolü Başarılı</string>
<string name="safetyNet_no_response">SafetyNet doğrulanamıyor, İnternet bağlantınız yok mu?</string>
<string name="safetyNet_network_loss">Ağ bağlantısı kullanılamıyor</string>
<string name="safetyNet_service_disconnected">Servis sonlandırıldı</string>
<string name="safetyNet_res_invalid">Yanıt gersiz</string>
<!--Install Fragment-->
<string name="auto_detect">(Otomatik) %1$s</string>
<string name="cannot_auto_detect">(Otomatik algılanamıyor)</string>
<string name="boot_image_title">Boot İmajı Konumu</string>
<string name="boot_image_title">Önyükleme İmajı Konumu</string>
<string name="detect_button">Algıla</string>
<string name="advanced_settings_title">Gelişmiş Ayarlar</string>
<string name="keep_force_encryption">Şifrelemeyi zorlamayı sürdür</string>
<string name="keep_dm_verity">"Dm-verity'yi koru"</string>
<string name="keep_dm_verity">"Dm-verity\'yi koru"</string>
<string name="current_magisk_title">Yüklenmiş Magisk Sürümü: %1$s</string>
<string name="install_magisk_title">Son Magisk Sürümü: %1$s</string>
<string name="uninstall">Kaldır</string>
<string name="reboot_countdown">%1$d saniye içinde yeniden başlatılacak</string>
<string name="uninstall_magisk_title">"Magisk'i kaldır"</string>
<string name="uninstall_magisk_msg">"Bu, tüm modülleri, MagiskSU'yu kaldıracak ve şifrelenmemişse verilerinizi potansiyel olarak şifreleyecektir\nDevam etmek istediğinize emin misiniz?"</string>
<string name="version_none">(Hiçbiri)</string>
<string name="uninstall_magisk_title">"Magisk\'i kaldır"</string>
<string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacaktır. Kök erişimi kaldırılacak ve verileriniz şu anda şifrelenmemişse potansiyel olarak verilerinizi şifrelenecek</string>
<string name="update">Güncelle %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Hiçbir açıklama sağlanmadı)</string>
@@ -55,7 +49,6 @@
<string name="disable_file_created">Modül sonraki yeniden başlatmada devre dışı bırakılacak</string>
<string name="disable_file_removed">Modül sonraki yeniden başlatmada etkinleştirilecek</string>
<string name="author">Yapımcı: %1$s</string>
<string name="fab_flash_zip">"Modül Zip'ini Yükle"</string>
<!--Repo Fragment-->
<string name="update_available">Güncelleme Mevcut</string>
@@ -63,7 +56,7 @@
<string name="not_installed">Yüklenmemiş</string>
<!--Log Fragment-->
<string name="menuSaveToSd">"SD'ye kaydet"</string>
<string name="menuSaveToSd">"SD Kart\'a kaydet"</string>
<string name="menuReload">Yenile</string>
<string name="menuClearLog">Günlüğü temizle</string>
<string name="logs_cleared">Günlük başarıyla temizlendi</string>
@@ -73,13 +66,13 @@
<!--About Activity-->
<string name="about">Hakkında</string>
<string name="app_developers">Ana geliştiriciler</string>
<string name="app_developers_">"<![CDATA[<a href="https://github.com/topjohnwu">topjohnwu</a> tarafından <a href="https://github.com/d8ahazard">Digitalhigh</a> ve <a href="https://github.com/dvdandroid">Dvdandroid</a>]]>'in katkılarıyla oluşturuldu"</string>
<string name="app_developers_">"<![CDATA[<a href="https://github.com/topjohnwu">topjohnwu</a> tarafından <a href="https://github.com/d8ahazard">Digitalhigh</a> ve <a href="https://github.com/dvdandroid">Dvdandroid</a>]]>\'in katkılarıyla oluşturuldu"</string>
<string name="app_changelog">Uygulama değişiklikleri</string>
<string name="translators">Fatih Fırıncı</string>
<string name="translators">Fatih FIRINCI - Mevlüt TOPÇU</string>
<string name="app_version">Uygulama sürümü</string>
<string name="app_source_code">Kaynak kodu</string>
<string name="donation">Bağış</string>
<string name="app_translators">Çevirmen</string>
<string name="donation">Bağış Yapın</string>
<string name="app_translators">Çevirmenler</string>
<string name="support_thread">Destek konusu</string>
<!--Toasts, Dialogs-->
@@ -90,37 +83,41 @@
<string name="close">Kapat</string>
<string name="repo_install_title">%1$s yükle</string>
<string name="repo_install_msg">%1$s yüklensin mi?</string>
<string name="download_install">İndir &amp; Yükle</string>
<string name="download">İndir</string>
<string name="goto_install">\"Yükleme\" bölümüne git</string>
<string name="download_file_error">Dosya indirme hatası</string>
<string name="install_error">Yükleme hatası!</string>
<string name="invalid_zip">Zip Magisk Modülü değil!!</string>
<string name="reboot_title">Yükleme başarılı!</string>
<string name="reboot_msg">Şimdi yeniden başlatmak istiyor musunuz?</string>
<string name="reboot">Yeniden başlat</string>
<string name="copying_msg">Zip geçici klasöre kopyalanıyor</string>
<string name="zip_install_progress_title">Yükleniyor</string>
<string name="zip_unzip_msg">Zip dosyasıılıyor …</string>
<string name="zip_process_msg">Zip dosyası işleniyor …</string>
<string name="zip_install_progress_msg">%1$s yükleniyor …</string>
<string name="no_magisk_title">Magisk Yüklü Değil!</string>
<string name="no_magisk_msg">"Magisk'i indirip yüklemek istiyor musunuz?"</string>
<string name="downloading_toast">%1$s indiriliyor</string>
<string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string>
<string name="settings_reboot_toast">Ayarları uygulamak için yeniden başlatın</string>
<string name="release_notes">Sürüm notları</string>
<string name="repo_cache_cleared">Repo önbelleği temizlendi</string>
<string name="safetyNet_hide_notice">Bu uygulama, SafetyNet kullanıyor\nZaten MagiskHide tarafından varsayılan olarak ele alındı</string>
<string name="start_magiskhide">MagiskHide başlatılıyor …</string>
<string name="no_magisksu_title">MagiskSU kullanılmıyor!</string>
<string name="no_magisksu_msg">"MagiskSU ile rootlu değilsiniz, MagiskHide'ın kendisini kullanmak yeterli olmayabilir!\nResmi olarak desteklenmez ve SafetyNet'i geçmek için ek araçlar (ör. suhide) gerekir."</string>
<string name="understand">Anladım</string>
<string name="process_error">İşlem hatası</string>
<string name="internal_storage">Zip şuraya depolandı:\n[Dahili Hafıza]%1$s</string>
<string name="zip_download_title">İndiriliyor</string>
<string name="zip_download_msg">Zip dosyası indiriliyor …</string>
<string name="zip_process_title">İşleniyor</string>
<string name="zip_process_msg">Zip dosyası işleniyor …</string>
<string name="manual_boot_image">Lütfen elle bir boot imajı seçin!</string>
<string name="manager_update_title">Yeni Magisk Manager Güncellemesi Mevcut!</string>
<string name="manager_download_install">İndirmek ve yüklemek için dokunun</string>
<string name="magisk_updates">Magisk Güncellemeleri</string>
<string name="flashing">Yükleyin</string>
<string name="hide_manager_toast">Magisk Manager\'ı Gizle…</string>
<string name="hide_manager_fail_toast">Hide Magisk Manager\'ı Gizleme başarısız oldu…</string>
<string name="download_zip_only">Yalnızca Zip Dosyasını İndir</string>
<string name="patch_boot_file">Önyükleme İmaj Dosyasını Yamala</string>
<string name="direct_install">Doğrudan Yükleme (Önerilen)</string>
<string name="select_method">Yöntem Seçin</string>
<string name="no_boot_file_patch_support">Hedef Magisk sürümü önyükleme imaj dosyasını yamalamayı desteklemez</string>
<string name="boot_file_patch_msg">.img veya .img.tar formatında stok önyükleme imajını seçin</string>
<string name="complete_uninstall">Tamamen Kaldır</string>
<string name="restore_stock_boot">Stok Önyükleme Dosyasını Geri Yükle</string>
<string name="restore_done">Yenileme tamamlandı!</string>
<string name="restore_fail">Stok önyükleme yedeği yok!</string>
<!--Settings Activity -->
<string name="settings_general_category">Genel</string>
<string name="settings_dark_theme_title">Karanlık Tema</string>
@@ -129,10 +126,20 @@
<string name="settings_notification_summary">Yeni sürüm kullanılabilir olduğunda güncelleme bildirimlerini göster</string>
<string name="settings_clear_cache_title">Repo Önbelleğini Temizle</string>
<string name="settings_clear_cache_summary">Çevrimiçi repolar için önbellek bilgilerini temizle, uygulamayı çevrimiçi yenilemeye zorla</string>
<string name="settings_hide_manager_title">Magisk Manager\'ı Gizle</string>
<string name="settings_hide_manager_summary">Magisk Manager\'ı geçici olarak gizle.\nBu, \"Unhide Magisk Manager\" adlı yeni bir uygulama yükleyecektir.</string>
<string name="language">Dil</string>
<string name="system_default">(Sistem Varsayılanı)</string>
<string name="settings_update">Güncelleme Ayarları</string>
<string name="settings_update_channel_title">Güncelleme Kanalı</string>
<string name="settings_update_stable">Kararlı</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Yamalı Önyükleme Formatı</string>
<string name="settings_boot_format_summary">Yamalı önyükleme imaj dosyasının formatını seçin\nFastboot/indirme modunda yüklemek için .img seçeneğini seçin; ODIN ile yüklemek için .img.tar\'ı seçin.</string>
<string name="settings_magiskhide_summary">"Magisk'i çeşitli algılamalardan gizle"</string>
<string name="settings_busybox_title">"BusyBox'ı etkinleştir"</string>
<string name="settings_busybox_summary">"Magisk'in dahili busybox'ını xbin'e bağla"</string>
<string name="settings_core_only_title">Magisk Yalnızca Çekirdek Modu</string>
<string name="settings_core_only_summary">Yalnızca temel özellikleri etkinleştirin, tüm modüller yüklenmez. MagiskSU, MagiskHide ve host yine de etkinleştirilecektir</string>
<string name="settings_magiskhide_summary">"Magisk\'i çeşitli algılamalardan gizle"</string>
<string name="settings_hosts_title">Sistemsiz host</string>
<string name="settings_hosts_summary">Reklam engelleme uygulamaları için sistemsiz host desteği</string>
@@ -149,6 +156,25 @@
<string name="request_timeout">İstek Zaman Aşımı</string>
<string name="superuser_notification">Yetkili Kullanıcı Bildirimi</string>
<string name="request_timeout_summary">%1$s saniye</string>
<string name="settings_su_reauth_title">Yükseltmeden sonra yeniden kimlik doğrulaması yapın</string>
<string name="settings_su_reauth_summary">Uygulama yükseltmeleri sonrasında yetkili kullanıcı izinlerini yeniden doğrulama</string>
<string name="multiuser_mode">Çok Kullanıcılı Modu</string>
<string name="settings_owner_only">Yalnızca Cihaz Sahibi</string>
<string name="settings_owner_manage">Cihaz Sahibi Tarafından Yönetilen</string>
<string name="settings_user_independent">Bağımsız Kullanıcı</string>
<string name="owner_only_summary">Yalnızca kök erişimi olan kullanıcı</string>
<string name="owner_manage_summary">Yalnızca cihaz sahibi kök erişimini yönetebilir ve izin isteklerini alabilir</string>
<string name="user_indepenent_summary">Her kullanıcının kendi ayrı kök erişimi kuralları vardır</string>
<string name="multiuser_hint_owner_request">Cihaz sahibine bir istek gönderilmiştir. Lütfen cihaz sahibi hesabına geçin ve izin verin</string>
<string name="mount_namespace_mode">Ad Alanı Modunu Doldur</string>
<string name="settings_ns_global">Global Ad Alanı</string>
<string name="settings_ns_requester">Inherit Ad Alanı</string>
<string name="settings_ns_isolate">Isolated Ad Alanı</string>
<string name="global_summary">Tüm kök oturumları genel bağlama ad alanını kullanır</string>
<string name="requester_summary">Kök oturumları, istekte bulunanın ad alanını devralır</string>
<string name="isolate_summary">Her bir kök oturumunun kendi izole ad alanı olacaktır</string>
<string name="settings_development_category">Uygulama Geliştirme</string>
<string name="settings_developer_logging_title">Gelişmiş hata ayıklama günlüğünü etkinleştir</string>

View File

@@ -0,0 +1,220 @@
<resources>
<!--Welcome Activity-->
<string name="modules">Модулі</string>
<string name="downloads">Завантаження</string>
<string name="superuser">Суперкористувач</string>
<string name="log">Логи</string>
<string name="settings">Налаштування</string>
<!--Status Fragment-->
<string name="install">Встановлення</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk не встановлено</string>
<string name="checking_for_updates">Перевірка оновлень…</string>
<string name="magisk_update_available">Доступно Magisk v%1$s!</string>
<string name="cannot_check_updates">Неможливо перевірити наявність оновлень</string>
<string name="root_error">Root присутній, але немає дозволу</string>
<string name="not_rooted">Root відсутній</string>
<string name="safetyNet_check_text">Перевірити статус SafetyNet</string>
<string name="checking_safetyNet_status">Перевірка статусу SafetyNet…</string>
<string name="safetyNet_check_success">Перевірку SafetyNet завершено</string>
<string name="safetyNet_no_response">Неможливо виконати перевірку SafetyNet</string>
<string name="safetyNet_network_loss">Підключення до інтернету втрачено</string>
<string name="safetyNet_service_disconnected">Службу зупинено</string>
<string name="safetyNet_res_invalid">Невірна відповідь</string>
<!--Install Fragment-->
<string name="auto_detect">(Авто) %1$s</string>
<string name="cannot_auto_detect">(Автовизначення неможливе)</string>
<string name="boot_image_title">Розташування boot-образу</string>
<string name="detect_button">Визначити</string>
<string name="advanced_settings_title">Розширені налаштування</string>
<string name="keep_force_encryption">Залишити примусове шифрування</string>
<string name="keep_dm_verity">Залишити dm-verity</string>
<string name="current_magisk_title">Поточна версія Magisk: %1$s</string>
<string name="install_magisk_title">Найновіша версія Magisk: %1$s</string>
<string name="uninstall">Видалити</string>
<string name="reboot_countdown">Перезавантаження через %1$d</string>
<string name="uninstall_magisk_title">Видалити Magisk</string>
<string name="uninstall_magisk_msg">Ця дія призведе до видалення всіх модулів, MagiskSU, і може зашифрувати дані, якщо вони не зашифровані.\nВпевнені, що бажаєте продовжити?</string>
<!--Module Fragment-->
<string name="no_info_provided">(Немає наданої інформації)</string>
<string name="no_modules_found">Модулів не знайдено</string>
<string name="update_file_created">Модуль оновиться при перезавантаженні</string>
<string name="remove_file_created">Модуль видалиться при перезавантаженні</string>
<string name="remove_file_deleted">Модуль не видалиться при перезавантаженні</string>
<string name="disable_file_created">Модуль вимкнеться при перезавантаженні</string>
<string name="disable_file_removed">Модуль увімкнеться при перезавантаженні</string>
<string name="author">Автор: %1$s</string>
<string name="update">Оновити %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Доступне оновлення</string>
<string name="installed">Встановлено</string>
<string name="not_installed">Не встановлено</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Зберегти на карту пам\'яті</string>
<string name="menuReload">Оновити</string>
<string name="menuClearLog">Очистити логи</string>
<string name="logs_cleared">Логи очищено</string>
<string name="log_is_empty">Логи пусті</string>
<string name="logs_save_failed">Не вдалося записати логи на карту пам\'яті:</string>
<!--About Activity-->
<string name="about">Про програму</string>
<string name="app_developers">Головні розробники</string>
<string name="app_developers_"><![CDATA[Програму створив <a href="https://github.com/topjohnwu">topjohnwu</a>, разом з <a href="https://github.com/d8ahazard">Digitalhigh</a> і <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Список змін</string>
<string name="translators" />
<string name="app_version">Версія</string>
<string name="app_source_code">Вихідний код</string>
<string name="donation">Підтримати проект</string>
<string name="app_translators">Перекладачі</string>
<string name="support_thread">Сторінка підтримки</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ця функція не працюватиме без дозволу на запис у Внутрішнє сховище</string>
<string name="no_thanks">Ні, дякую</string>
<string name="yes">Так</string>
<string name="ok">OK</string>
<string name="close">Закрити</string>
<string name="repo_install_title">Встановити %1$s</string>
<string name="repo_install_msg">Бажаєте встановити %1$s ?</string>
<string name="download">Завантажити</string>
<string name="download_file_error">Помилка завантаження файлу</string>
<string name="install_error">Помилка під час встановлення</string>
<string name="invalid_zip">В архіві відсутній модуль Magisk!</string>
<string name="reboot">Перезавантаження</string>
<string name="zip_process_msg">Опрацювання архіву …</string>
<string name="downloading_toast">Завантаження %1$s</string>
<string name="magisk_update_title">Доступне оновлення Magisk!</string>
<string name="settings_reboot_toast">Для застосування змін перезавантажте пристрій</string>
<string name="release_notes">Особливості версії</string>
<string name="repo_cache_cleared">Кеш репозиторію очищено</string>
<string name="safetyNet_hide_notice">Ця програма використовує SafetyNet.\nВже опрацьовано MagiskHide за замовчуванням</string>
<string name="zip_download_title">Завантаження</string>
<string name="zip_download_msg">Завантаження zip файлу …</string>
<string name="process_error">Помилка опрацювання</string>
<string name="internal_storage">Архів розташований:\n[Внутрішнє Сховище]%1$s</string>
<string name="zip_process_title">Опрацювання</string>
<string name="manual_boot_image">Будь ласка, виберіть boot-образ!</string>
<string name="manager_update_title">Доступне оновлення Magisk Manager!</string>
<string name="manager_download_install">Натисніть, щоб завантажити і встановити</string>
<string name="magisk_updates">Оновлення Magisk</string>
<string name="flashing">Прошивання</string>
<string name="hide_manager_toast">Приховування Magisk Manager…</string>
<string name="hide_manager_fail_toast">Не вдалося приховати Magisk Manager…</string>
<string name="download_zip_only">Тільки завантажити</string>
<string name="patch_boot_file">Пропатчити boot образ</string>
<string name="direct_install">Пряме встановлення (рекомендовано)</string>
<string name="select_method">Виберіть спосіб</string>
<string name="no_boot_file_patch_support">Цільова версія Magisk не підтримує пропатчування boot образу</string>
<string name="boot_file_patch_msg">Виберіть дамп заводського boot образу в форматі .img чи .img.tar</string>
<string name="complete_uninstall">Видалення виконано</string>
<string name="restore_stock_boot">Відновити заводський образ</string>
<string name="restore_done">Відновлення завершено!</string>
<string name="restore_fail">Немає резервної копії заводського boot образу</string>
<!--Settings Activity -->
<string name="settings_general_category">Основні</string>
<string name="settings_dark_theme_title">Темна тема</string>
<string name="settings_dark_theme_summary">Увімкнути темне оформлення</string>
<string name="settings_notification_title">Сповіщення про оновлення</string>
<string name="settings_notification_summary">Показувати сповіщення про оновлення в Панелі сповіщень, коли доступна нова версія</string>
<string name="settings_clear_cache_title">Очищення кешу</string>
<string name="settings_clear_cache_summary">Очистити збережену інформацію про мережеві репозиторії, змушуючи програму примусово оновлюватися через Інтернет</string>
<string name="settings_hide_manager_title">Приховати Magisk Manager</string>
<string name="settings_hide_manager_summary">Тимчасово приховати Magisk Manager.\nЦя дія встановить новий додаток \"Unhide Magisk Manager\"</string>
<string name="language">Мова</string>
<string name="system_default">Стандартна (системна)</string>
<string name="settings_update">Оновити налаштування</string>
<string name="settings_update_channel_title">Канал оновлення</string>
<string name="settings_update_stable">Стабільний реліз</string>
<string name="settings_update_beta">Бета реліз</string>
<string name="settings_boot_format_title">Формат пропатченого образу</string>
<string name="settings_boot_format_summary">Виберіть формат вихідного пропатченого boot образу.\n.img - для прошивання через fastboot/download режим;\n.img.tar - для прошивання через ODIN.</string>
<string name="settings_core_only_title">Режим ядра Magisk</string>
<string name="settings_core_only_summary">Увімкнути тільки можливості ядра, всі модулі не будуть активними. MagiskSU, MagiskHide і позасистемні хости залишуться увімкненими</string>
<string name="settings_magiskhide_summary">Приховати Magisk від різних перевірок</string>
<string name="settings_hosts_title">Позасистемні хости</string>
<string name="settings_hosts_summary">Підтримка позасистемних хостів для програм блокування реклами</string>
<string name="settings_su_app_adb">Програми і ADB</string>
<string name="settings_su_app">Програми</string>
<string name="settings_su_adb">ADB</string>
<string name="settings_su_disable">Вимкнено</string>
<string name="settings_su_request_10">10 секунд</string>
<string name="settings_su_request_20">20 секунд</string>
<string name="settings_su_request_30">30 секунд</string>
<string name="settings_su_request_60">60 секунд</string>
<string name="superuser_access">Доступ суперкористувача</string>
<string name="auto_response">Автоматична відповідь</string>
<string name="request_timeout">Час запиту</string>
<string name="superuser_notification">Сповіщення суперкористувача</string>
<string name="request_timeout_summary">%1$s сек.</string>
<string name="settings_su_reauth_title">Повторна автентифікація</string>
<string name="settings_su_reauth_summary">Перевидача прав суперкористувача після оновлення програм</string>
<string name="multiuser_mode">Багатокористувацький режим</string>
<string name="settings_owner_only">Тільки власник</string>
<string name="settings_owner_manage">Регулювання власником</string>
<string name="settings_user_independent">Незалежний користувач</string>
<string name="owner_only_summary">Тільки власник має root-доступ</string>
<string name="owner_manage_summary">Тільки власник може керувати root-доступом і опрацьовувати запити на надання доступу</string>
<string name="user_indepenent_summary">Кожен користувач має власні правила root-доступу</string>
<string name="multiuser_hint_owner_request">Запит відправлено власнику. Будь ласка, перейдіть на профіль власника і надайте дозвіл</string>
<string name="mount_namespace_mode">Режим монтування простору імен</string>
<string name="settings_ns_global">Глобальний простір імен</string>
<string name="settings_ns_requester">Наслідуваний простір імен</string>
<string name="settings_ns_isolate">Ізольований простір імен</string>
<string name="global_summary">Всі сеанси Суперкористувача використовують глобальний простір імен</string>
<string name="requester_summary">Сеанси Суперкористувача наслідують простір імен запитувача</string>
<string name="isolate_summary">Кожнен сеанс Суперкористувача має власний ізольований простір імен</string>
<string name="settings_development_category">Розробники</string>
<string name="settings_developer_logging_title">Розширені логи</string>
<string name="settings_developer_logging_summary">Увімкнути детальне ведення логів налагодження</string>
<string name="settings_shell_logging_title">Логи команд оболонки</string>
<string name="settings_shell_logging_summary">Увімкнути детальний запис всіх команд оболонки і їх виведення</string>
<!--Superuser-->
<string name="su_request_title">Запит прав Суперкористувача</string>
<string name="deny_with_str">Відмовити %1$s</string>
<string name="deny">Відмовити</string>
<string name="prompt">Запит</string>
<string name="grant">Надати</string>
<string name="su_warning">Надати повний доступ до пристрою.\nЯкщо не впевнені, що бажаєте продовжити, відхиліть дану дію.</string>
<string name="forever">Назавжди</string>
<string name="once">Одноразово</string>
<string name="tenmin">10 хв.</string>
<string name="twentymin">20 хв.</string>
<string name="thirtymin">30 хв.</string>
<string name="sixtymin">60 хв.</string>
<string name="su_allow_toast">%1$s надані права Суперкористувача</string>
<string name="su_deny_toast">%1$s відмовлено в правах Суперкористувача</string>
<string name="no_apps_found">Програм не виявлено</string>
<string name="su_snack_grant">%1$s надані права Суперкористувача</string>
<string name="su_snack_deny">%1$s відмовлено в правах Суперкористувача</string>
<string name="su_snack_notif_on">Сповіщення для %1$s увімкнено</string>
<string name="su_snack_notif_off">Сповіщення для %1$s вимкнено</string>
<string name="su_snack_log_on">Логи подій для %1$s увімкнено</string>
<string name="su_snack_log_off">Логи подій для %1$s вимкнено</string>
<string name="su_snack_revoke">Права для %1$s відкликані</string>
<string name="su_revoke_title">Відкликати?</string>
<string name="su_revoke_msg">Підтвердити відкликання прав для %1$s?</string>
<string name="toast">Спливаюче сповіщення</string>
<string name="none">Нічого</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Цільовий UID:\u0020</string>
<string name="command">Команда:\u0020</string>
</resources>

View File

@@ -2,35 +2,24 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Mở thanh điều hướng</string>
<string name="navigation_drawer_close">Đóng thanh điều hướng</string>
<string name="modules">Mô-đun</string>
<string name="downloads">Tải xuống</string>
<string name="superuser">Superuser</string>
<string name="log">Nhật ký</string>
<string name="settings">Thiết lập</string>
<string name="status">Trạng thái</string>
<string name="install">Cài đặt</string>
<!--Status Fragment-->
<string name="magisk_version">Đã cài Magisk v%1$s</string>
<string name="magisk_version_error">Magisk chưa được cài đặt</string>
<string name="checking_for_updates">Đang kiểm tra cập nhật…</string>
<string name="magisk_update_available">Magisk v%1$s available!</string>
<string name="cannot_check_updates">Không thể kiểm tra cập nhật, không có Internet?</string>
<string name="up_to_date">Đã cài đặt phiên bản mới nhất của %1$s</string>
<string name="root_error">Đã root nhưng không có quyền root, chưa được cho phép?</string>
<string name="not_rooted">Chưa root</string>
<string name="proper_root">Đã root thành công</string>
<string name="safetyNet_check_text">Chạm để bắt đầu kiểm tra SafetyNet</string>
<string name="checking_safetyNet_status">Đang kiểm tra trạng thái SafetyNet…</string>
<string name="safetyNet_connection_failed">Không thể kết nối với API của Google</string>
<string name="safetyNet_connection_suspended">Kết nối với API của Google đã dừng</string>
<string name="safetyNet_no_response">Không thể kiểm tra SafetyNet, không có Internet?</string>
<string name="safetyNet_fail">SafetyNet thất bại: cấu hình CTS không phù hợp</string>
<string name="safetyNet_pass">SafetyNet thành công</string>
<string name="root_info_warning">Tính năng bị hạn chế rất nhiều</string>
<!--Install Fragment-->
<string name="auto_detect">(Tự động) %1$s</string>
@@ -45,8 +34,6 @@
<string name="uninstall">Gỡ bỏ</string>
<string name="reboot_countdown">Khởi động lại trong %1$d</string>
<string name="uninstall_magisk_title">Gỡ bỏ Magisk</string>
<string name="uninstall_magisk_msg">Việc này sẽ xoá tất cả các mô-đun, MagiskSU và có khả năng sẽ mã hoá dữ liệu nếu chưa được mã hoá\nBạn chắc muốn tiếp tục?</string>
<string name="version_none">(Không có)</string>
<!--Module Fragment-->
<string name="no_info_provided">(Không có thông tin được cung cấp)</string>
@@ -57,7 +44,6 @@
<string name="disable_file_created">Mô-đun sẽ bị vô hiệu ở lần khởi động lại kế tiếp</string>
<string name="disable_file_removed">Mô-đun sẽ được kích hoạt ở lần khởi động lại kế tiếp</string>
<string name="author">Tạo bởi %1$s</string>
<string name="fab_flash_zip">Cài file zip của Mô-đun</string>
<!--Repo Fragment-->
<string name="update_available">Có cập nhật mới</string>
@@ -92,32 +78,18 @@
<string name="close">Đóng</string>
<string name="repo_install_title">Cài đặt %1$s</string>
<string name="repo_install_msg">Bạn muốn cài đặt %1$s ?</string>
<string name="download_install">Tải xuống &amp; Cài đặt</string>
<string name="download">Tải xuống</string>
<string name="goto_install">Mở phần \"Cài đặt\"</string>
<string name="download_file_error">Lỗi tải tập tin</string>
<string name="install_error">Lỗi cài đặt!</string>
<string name="invalid_zip">Tập tin zip không phải mô-đun Magisk!!</string>
<string name="reboot_title">Cài đặt thành công!</string>
<string name="reboot_msg">Bạn muốn khởi động lại ngay chứ?</string>
<string name="reboot">Khởi động lại</string>
<string name="copying_msg">Đang chép zip vào thư mục tạm</string>
<string name="zip_install_progress_title">Đang cài đặt</string>
<string name="zip_unzip_msg">Đang giải nén tập tin …</string>
<string name="zip_process_msg">Đang xử lý tập tin zip …</string>
<string name="zip_install_progress_msg">Đang cài đặt %1$s …</string>
<string name="no_magisk_title">Chưa cài Magisk!</string>
<string name="no_magisk_msg">Bạn muốn tải xuống và cài đặt Magisk chứ?</string>
<string name="downloading_toast">Đang tải xuống %1$s</string>
<string name="magisk_update_title">Có cập nhật Magisk mới!</string>
<string name="settings_reboot_toast">Khởi động lại để áp dụng thiết lập</string>
<string name="release_notes">Ghi chú phát hành</string>
<string name="repo_cache_cleared">Đã xoá bộ đệm kho</string>
<string name="safetyNet_hide_notice">Ứng dụng này dùng SafetyNet\nĐã được MagiskHide xử lý theo mặc định</string>
<string name="start_magiskhide">Đang khởi động MagiskHide …</string>
<string name="no_magisksu_title">Không dùng MagiskSU!</string>
<string name="no_magisksu_msg">Bạn không root với MagiskSU, sử dụng mỗi MagiskHide có thể sẽ không đủ hiệu quả!\nViệc này không được hỗ trợ chính thức và có thể bạn cần thêm công cụ khác (suhide chẳng hạn) để vượt Safety Net.</string>
<string name="understand">Tôi hiểu</string>
<string name="process_error">Lỗi xử lý</string>
<string name="internal_storage">Tập tin zip được lưu vào:\n[Bộ nhớ trong]%1$s</string>
<string name="zip_process_title">Đang xử lý</string>
@@ -133,8 +105,6 @@
<string name="settings_clear_cache_summary">Xoá thông tin truy cập nhật về các kho mô-đun, buộc ứng dụng làm mới trực tuyến</string>
<string name="settings_magiskhide_summary">Ẩn Magisk khỏi nhiều phương thức phát hiện</string>
<string name="settings_busybox_title">Dùng BusyBox</string>
<string name="settings_busybox_summary">Gắn kết busy có sẵn của Magisk tới xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Systemless hosts hỗ trợ các ứng dụng chặn quảng cáo</string>

View File

@@ -2,40 +2,28 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="modules">模块</string>
<string name="downloads">下载</string>
<string name="superuser">超级用户</string>
<string name="log">日志</string>
<string name="settings">设置</string>
<string name="status">状态</string>
<string name="install">安装</string>
<!--Status Fragment-->
<string name="magisk_version">已安装 Magisk v%1$s</string>
<string name="magisk_version_core_only">已安装 Magisk v%1$s (仅核心功能)</string>
<string name="magisk_version_error">未安装 Magisk</string>
<string name="checking_for_updates">正在检查更新…</string>
<string name="magisk_update_available">Magisk 可更新到 v%1$s</string>
<string name="cannot_check_updates">无法检查更新,没有网络连接?</string>
<string name="up_to_date">已安装最新版本的 %1$s</string>
<string name="root_error">已 ROOT 但没有 ROOT 权限,未授予权限?</string>
<string name="not_rooted">未 ROOT</string>
<string name="proper_root">已正确 ROOT</string>
<string name="safetyNet_check_text">点击启动 SafetyNet 检查</string>
<string name="checking_safetyNet_status">正在检查 SafetyNet 状态…</string>
<string name="safetyNet_check_success">SafetyNet 检查成功</string>
<string name="safetyNet_connection_failed">无法连接至 Google API</string>
<string name="safetyNet_connection_suspended">与 Google API 的连接已暂停</string>
<string name="safetyNet_no_response">无法检查 SafetyNet没有网络连接</string>
<string name="safetyNet_fail">SafetyNet 失败CTS 配置文件不匹配</string>
<string name="safetyNet_pass">SafetyNet 已通过</string>
<string name="safetyNet_network_loss">网络断线</string>
<string name="safetyNet_no_response">无法验证 SafetyNet没有网络连接</string>
<string name="safetyNet_network_loss">网络连接不可用</string>
<string name="safetyNet_service_disconnected">服务已被取消</string>
<string name="safetyNet_res_invalid">回传值无效</string>
<string name="root_info_warning">功能严重受限</string>
<!--Install Fragment-->
<string name="auto_detect">(自动) %1$s</string>
@@ -50,8 +38,7 @@
<string name="uninstall">卸载</string>
<string name="reboot_countdown">将在 %1$d 后重启</string>
<string name="uninstall_magisk_title">卸载 Magisk</string>
<string name="uninstall_magisk_msg">将会删除所有模块及 MagiskSU并有可能在目前未加密的情况下加密你的数据\n你确定要继续吗</string>
<string name="version_none">(无)</string>
<string name="update">更新 %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(未提供信息)</string>
@@ -62,7 +49,6 @@
<string name="disable_file_created">模块将在下次重启后禁用</string>
<string name="disable_file_removed">模块将在下次重启后启用</string>
<string name="author">作者:%1$s</string>
<string name="fab_flash_zip">刷入模块 Zip</string>
<!--Repo Fragment-->
<string name="update_available">可更新</string>
@@ -96,39 +82,33 @@
<string name="ok">确定</string>
<string name="close">关闭</string>
<string name="repo_install_title">安装 %1$s</string>
<string name="repo_install_msg">你想要安装 %1$s 吗?</string>
<string name="download_install">下载并安装</string>
<string name="repo_install_msg">你想要立即安装 %1$s 吗?</string>
<string name="download">下载</string>
<string name="goto_install">前往“安装”界面</string>
<string name="download_file_error">下载文件时出错</string>
<string name="install_error">安装出错!</string>
<string name="invalid_zip">此 zip 文件不是 Magisk 模块!!</string>
<string name="reboot_title">安装成功!</string>
<string name="reboot_msg">你想要立即重启吗?</string>
<string name="reboot">重启</string>
<string name="copying_msg">正在复制 zip 到临时目录</string>
<string name="zip_install_progress_title">正在安装</string>
<string name="zip_unzip_msg">正在解压 zip 文件 …</string>
<string name="zip_process_msg">正在处理 zip 文件 …</string>
<string name="zip_install_progress_msg">正在安装 %1$s …</string>
<string name="no_magisk_title">未安装 Magisk</string>
<string name="no_magisk_msg">你想要下载并安装 Magisk 吗?</string>
<string name="downloading_toast">正在下载 %1$s</string>
<string name="magisk_update_title">Magisk 可更新!</string>
<string name="settings_reboot_toast">重启以应用设置</string>
<string name="release_notes">发布说明</string>
<string name="repo_cache_cleared">资源库缓存已清除</string>
<string name="safetyNet_hide_notice">此应用使用了 SafetyNet\n已默认由 MagiskHide 处理</string>
<string name="start_magiskhide">正在启动 MagiskHide …</string>
<string name="no_magisksu_title">未使用 MagiskSU</string>
<string name="no_magisksu_msg">你未使用 MagiskSU 进行 ROOT仅使用 MagiskHide 可能并不足够!\n官方并不支持你需要额外的工具如 suhide才能通过 Safety Net。</string>
<string name="understand">我明白</string>
<string name="process_error">处理失败</string>
<string name="internal_storage">Zip 已被储存到:\n[内部存储]%1$s</string>
<string name="zip_process_title">正在处理</string>
<string name="manual_boot_image">请手动选择 Boot 镜像位置!</string>
<string name="manager_update_title">Magisk Manager 有更新!</string>
<string name="manager_download_install">点击以下载并安装</string>
<string name="magisk_updates">Magisk 更新</string>
<string name="flashing">正在刷入</string>
<string name="hide_manager_toast">正在隐藏 Magisk Manager…</string>
<string name="hide_manager_fail_toast">隐藏 Magisk Manager 失败…</string>
<string name="download_zip_only">仅下载 Zip</string>
<string name="patch_boot_file">给 Boot 镜像文件打补丁</string>
<string name="direct_install">直接安装(推荐)</string>
<string name="select_method">选择方法</string>
<!--Settings Activity -->
<string name="settings_general_category">常规</string>
@@ -138,12 +118,17 @@
<string name="settings_notification_summary">当有新版本可用时显示更新通知</string>
<string name="settings_clear_cache_title">清除资源库缓存</string>
<string name="settings_clear_cache_summary">清除已缓存的在线资源库信息,强制刷新在线数据</string>
<string name="settings_hide_manager_title">隐藏 Magisk Manager</string>
<string name="settings_hide_manager_summary">临时隐藏 Magisk Manager。\n此功能将会安装一个名为“Unhide Magisk Manager取消隐藏 Magisk Manager”的新应用。</string>
<string name="language">语言</string>
<string name="system_default">(系统默认)</string>
<string name="settings_update_channel_title">更新通道</string>
<string name="settings_update_stable">稳定版</string>
<string name="settings_update_beta">测试版</string>
<string name="settings_core_only_title">Magisk 核心功能模式</string>
<string name="settings_core_only_summary">仅启用核心功能所有模块将不会被载入。MagiskSU、MagiskHide 和 systemless hosts 仍会持续运作</string>
<string name="settings_magiskhide_summary">隐藏 Magisk 使其不被多种方法检测到</string>
<string name="settings_busybox_title">启用 BusyBox</string>
<string name="settings_busybox_summary">将 Magisk 内置的 Busybox 挂载到 xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">为广告屏蔽应用提供 Systemless hosts 支持</string>

View File

@@ -2,35 +2,24 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="modules">模組</string>
<string name="downloads">下載</string>
<string name="superuser">超級用戶</string>
<string name="log">日誌</string>
<string name="settings">設置</string>
<string name="status">狀態</string>
<string name="install">安裝</string>
<!--Status Fragment-->
<string name="magisk_version">已安裝 Magisk v%1$s</string>
<string name="magisk_version_error">未安裝 Magisk</string>
<string name="checking_for_updates">正在檢查更新…</string>
<string name="magisk_update_available">Magisk 可更新到 v%1$s</string>
<string name="cannot_check_updates">無法檢查更新,沒有網絡連線?</string>
<string name="up_to_date">已安裝最新版本的 %1$s</string>
<string name="root_error">已 ROOT 但沒有 ROOT 權限,未授予權限?</string>
<string name="not_rooted">未 ROOT</string>
<string name="proper_root">已正確 ROOT</string>
<string name="safetyNet_check_text">點擊啟動 SafetyNet 檢查</string>
<string name="checking_safetyNet_status">正在檢查 SafetyNet 狀態…</string>
<string name="safetyNet_connection_failed">無法連接至 Google API</string>
<string name="safetyNet_connection_suspended">與 Google API 的連接已暫停</string>
<string name="safetyNet_no_response">無法檢查 SafetyNet沒有網絡連線</string>
<string name="safetyNet_fail">SafetyNet 失敗CTS 配置文件不匹配</string>
<string name="safetyNet_pass">SafetyNet 已通過</string>
<string name="root_info_warning">功能嚴重受限</string>
<!--Install Fragment-->
<string name="auto_detect">(自動) %1$s</string>
@@ -53,7 +42,6 @@
<string name="disable_file_created">模組將在下次重啟後禁用</string>
<string name="disable_file_removed">模組將在下次重啟後啟用</string>
<string name="author">作者:%1$s</string>
<string name="fab_flash_zip">刷入模組 Zip</string>
<!--Repo Fragment-->
<string name="update_available">可更新</string>
@@ -86,31 +74,17 @@
<string name="yes"></string>
<string name="repo_install_title">安裝 %1$s</string>
<string name="repo_install_msg">你想要安裝 %1$s 嗎?</string>
<string name="download_install">下載並安裝</string>
<string name="goto_install">前往“安裝”界面</string>
<string name="download_file_error">下載文件時出錯</string>
<string name="install_error">安裝出錯!</string>
<string name="invalid_zip">此 zip 文件不是 Magisk 模組!!</string>
<string name="reboot_title">安裝成功!</string>
<string name="reboot_msg">你想要立即重啟嗎?</string>
<string name="reboot">重啟</string>
<string name="copying_msg">正在復制 zip 到暫存目錄</string>
<string name="zip_install_progress_title">正在安裝</string>
<string name="zip_unzip_msg">正在解壓 zip 文件 …</string>
<string name="zip_process_msg">正在處理 zip 文件 …</string>
<string name="zip_install_progress_msg">正在安裝 %1$s …</string>
<string name="no_magisk_title">未安裝 Magisk</string>
<string name="no_magisk_msg">你想要下載並安裝 Magisk 嗎?</string>
<string name="downloading_toast">正在下載 %1$s</string>
<string name="magisk_update_title">Magisk 可更新!</string>
<string name="settings_reboot_toast">重啟以完成設定</string>
<string name="release_notes">發布說明</string>
<string name="repo_cache_cleared">資源庫暫存已清除</string>
<string name="safetyNet_hide_notice">此應用使用了 SafetyNet\n已默認由 MagiskHide 處理</string>
<string name="start_magiskhide">正在啟動 MagiskHide …</string>
<string name="no_magisksu_title">未使用 MagiskSU</string>
<string name="no_magisksu_msg">你未使用 MagiskSU 進行 ROOT僅使用 MagiskHide 可能並不足夠!\n官方並不支持你需要額外的工具如 suhide才能通過 Safety Net。</string>
<string name="understand">我明白</string>
<!--Settings Activity -->
<string name="settings_general_category">常規</string>
@@ -121,8 +95,6 @@
<string name="settings_core_only_title">Magisk 核心功能模式</string>
<string name="settings_magiskhide_summary">隱藏 Magisk 使其不被多種方法檢測到</string>
<string name="settings_busybox_title">啟用 BusyBox</string>
<string name="settings_busybox_summary">將 Magisk 內置的 Busybox 掛載到 xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">為廣告屏蔽應用提供 Systemless hosts 支持</string>
@@ -185,13 +157,11 @@
<string name="download">下載</string>
<string name="zip_process_title">處理中</string>
<string name="uninstall_magisk_title">解除安裝 Magisk</string>
<string name="uninstall_magisk_msg">這將會刪除所有模組MagiskSU,並有可能在目前資料未加密的情況下進行加密\n你確定要繼續嗎</string>
<string name="version_none">(無)</string>
<string name="uninstall_magisk_msg">所有模組將會被停用 / 刪除。root會被移除,並有可能在目前資料未加密的情況下被加密</string>
<string name="manual_boot_image">請手動選取 boot 映像位置</string>
<string name="cannot_auto_detect">(無法自動偵測)</string>
<string name="settings_notification_summary">有更新的時候顯示通知</string>
<string name="settings_notification_title">更新通知</string>
<string name="magisk_version_core_only">已安裝 Magisk v%1$s (僅核心功能)</string>
<string name="settings_core_only_summary">僅啟用核心功能所有模組將不會被載入。MagiskSU、MagiskHide 和 systemless hosts 仍會持續運作</string>
<string name="safetyNet_check_success">SafetyNet 檢查成功</string>
<string name="safetyNet_network_loss">網路斷線</string>
@@ -216,5 +186,34 @@
<string name="settings_ns_global">全域 Namespace</string>
<string name="settings_ns_isolate">獨立 Namespace</string>
<string name="settings_ns_requester">繼承 Namespace</string>
<string name="update">更新 %1$s</string>
<string name="magisk_updates">Magisk 更新</string>
<string name="system_default">(系統預設)</string>
<string name="language">語言</string>
<string name="flashing">正在刷入</string>
<string name="hide_manager_toast">正在隱藏 Magisk Manager…</string>
<string name="hide_manager_fail_toast">隱藏 Magisk Manager 失敗</string>
<string name="settings_hide_manager_title">隱藏 Magisk Manager</string>
<string name="settings_hide_manager_summary">暫時隱藏 Magisk Manager。\n這會新增一個新的 app 叫做 Unhide Magisk Manager</string>
<string name="settings_update_channel_title">更新頻道</string>
<string name="settings_update_stable">穩定版</string>
<string name="settings_update_beta">測試版</string>
<string name="download_zip_only">僅下載 Zip</string>
<string name="patch_boot_file">補丁 Boot 映像文件檔</string>
<string name="direct_install">直接安裝 (推薦)</string>
<string name="select_method">選擇安裝方法</string>
<string name="no_boot_file_patch_support">目標安裝版本不支援補丁 Boot 映像文件</string>
<string name="settings_update">更新設定</string>
<string name="settings_boot_format_title">已補丁 Boot 映像輸出格式</string>
<string name="zip_download_title">正在下載</string>
<string name="zip_download_msg">正在下載 Zip 文件 …</string>
<string name="settings_boot_format_summary">選擇已補丁 Boot 映像文件輸出格式\n若要透過 fastboot/download 模式刷入,請選擇 .img 格式;若要透過 ODIN 刷入,則選擇 .img.tar\n</string>
<string name="complete_uninstall">完全解除安裝</string>
<string name="restore_stock_boot">還原原廠 boot 映像</string>
<string name="restore_done">還原完成!</string>
<string name="restore_fail">原廠 boot 映像備份不存在!</string>
<string name="boot_file_patch_msg">選擇原廠 boot 映像備份;支援 .img 以及 .img.tar 格式</string>
<string name="install_second_slot">安裝到第二分區 (安裝完OTA後)</string>
<string name="uninstall_toast">將在 5 秒內解除安裝 Magisk Manager接下來請手動重新啟動</string>
</resources>

View File

@@ -14,7 +14,6 @@
<item>@string/settings_su_app</item>
<item>@string/settings_su_adb</item>
<item>@string/settings_su_app_adb</item>
</string-array>
<string-array name="value_array">
@@ -73,4 +72,14 @@
<item>@string/isolate_summary</item>
</string-array>
<string-array name="update_channel">
<item>@string/settings_update_stable</item>
<item>@string/settings_update_beta</item>
</string-array>
<string-array name="boot_formats">
<item>.img</item>
<item>.img.tar</item>
</string-array>
</resources>

View File

@@ -4,41 +4,29 @@
<string name="magisk" translatable="false">Magisk</string>
<!--Welcome Activity-->
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="magiskhide" translatable="false">Magisk Hide</string>
<string name="modules">Modules</string>
<string name="downloads">Downloads</string>
<string name="superuser">Superuser</string>
<string name="log">Log</string>
<string name="settings">Settings</string>
<string name="status">Status</string>
<string name="install">Install</string>
<!--Status Fragment-->
<string name="magisk_version">Installed Magisk v%1$s</string>
<string name="magisk_version_core_only">Installed Magisk v%1$s (Core Only Mode)</string>
<string name="magisk_version_error">Magisk not installed</string>
<string name="magisk_version_error">Magisk is not installed</string>
<string name="checking_for_updates">Checking for updates…</string>
<string name="magisk_update_available">Magisk v%1$s available!</string>
<string name="cannot_check_updates">Cannot check for updates, no Internet?</string>
<string name="up_to_date">Latest version of %1$s installed</string>
<string name="magisk_update_available">Magisk v%1$s is available!</string>
<string name="cannot_check_updates">Cannot check for updates, no internet?</string>
<string name="root_error">Rooted but no root permission, not allowed?</string>
<string name="not_rooted">Not rooted</string>
<string name="proper_root">Properly rooted</string>
<string name="safetyNet_check_text">Tap to start SafetyNet check</string>
<string name="checking_safetyNet_status">Checking SafetyNet status…</string>
<string name="safetyNet_check_success">SafetyNet Check Success</string>
<string name="safetyNet_connection_failed">Cannot connect to Google API</string>
<string name="safetyNet_connection_suspended">Connection to Google API was suspended</string>
<string name="safetyNet_no_response">Cannot check SafetyNet, no Internet?</string>
<string name="safetyNet_fail">SafetyNet Failed: CTS profile mismatch</string>
<string name="safetyNet_pass">SafetyNet Passed</string>
<string name="safetyNet_network_loss">Network connection loss</string>
<string name="safetyNet_check_success">SafetyNet Check Was Successful</string>
<string name="safetyNet_no_response">Cannot verify SafetyNet, no internet?</string>
<string name="safetyNet_network_loss">Network connection unavailable</string>
<string name="safetyNet_service_disconnected">Service has been killed</string>
<string name="safetyNet_res_invalid">The response is invalid</string>
<string name="root_info_warning">Functionality greatly limited</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
@@ -53,8 +41,8 @@
<string name="uninstall">Uninstall</string>
<string name="reboot_countdown">Rebooting in %1$d</string>
<string name="uninstall_magisk_title">Uninstall Magisk</string>
<string name="uninstall_magisk_msg">This will remove all modules, MagiskSU, and potentially encrypt your data if not encrypted\nAre you sure to continue?</string>
<string name="version_none">(None)</string>
<string name="uninstall_magisk_msg">All modules will be disabled/removed. Root will be removed, and potentially encrypt your data if your data is not currently encrypted</string>
<string name="update">Update %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(No info provided)</string>
@@ -65,7 +53,6 @@
<string name="disable_file_created">Module will be disabled at next reboot</string>
<string name="disable_file_removed">Module will be enabled at next reboot</string>
<string name="author">Created by %1$s</string>
<string name="fab_flash_zip">Flash Module Zip</string>
<!--Repo Fragment-->
<string name="update_available">Update Available</string>
@@ -99,41 +86,43 @@
<string name="ok">OK</string>
<string name="close">Close</string>
<string name="repo_install_title">Install %1$s</string>
<string name="repo_install_msg">Do you want to install %1$s ?</string>
<string name="download_install">Download &amp; Install</string>
<string name="repo_install_msg">Do you want to install %1$s now?</string>
<string name="download">Download</string>
<string name="goto_install">Go to \"Install\" section</string>
<string name="download_file_error">Error downloading file</string>
<string name="install_error">Installation error!</string>
<string name="invalid_zip">The zip is not a Magisk Module!!</string>
<string name="reboot_title">Installation succeeded!</string>
<string name="reboot_msg">Do you want to reboot now?</string>
<string name="invalid_zip">This zip is not a Magisk Module!</string>
<string name="reboot">Reboot</string>
<string name="copying_msg">Copying zip to temp directory</string>
<string name="zip_install_progress_title">Installing</string>
<string name="zip_unzip_msg">Unzipping zip file …</string>
<string name="zip_process_msg">Processing zip file …</string>
<string name="zip_install_progress_msg">Installing %1$s …</string>
<string name="no_magisk_title">No Magisk Installed!</string>
<string name="no_magisk_msg">Do you want to download and install Magisk?</string>
<string name="downloading_toast">Downloading %1$s</string>
<string name="magisk_update_title">New Magisk Update Available!</string>
<string name="settings_reboot_toast">Reboot to apply settings</string>
<string name="release_notes">Release notes</string>
<string name="repo_cache_cleared">Repo cache cleared</string>
<string name="safetyNet_hide_notice">This app uses SafetyNet\nAlready handled by MagiskHide by default</string>
<string name="start_magiskhide">Starting MagiskHide …</string>
<string name="no_magisksu_title">Not using MagiskSU!</string>
<string name="no_magisksu_msg">You are not rooted with MagiskSU, using MagiskHide itself might not be enough!\nIt\'s not officially supported, and you would need additional tools (e.g suhide) to pass Safety Net.</string>
<string name="understand">I understand</string>
<string name="process_error">Process error</string>
<string name="internal_storage">The zip is stored in:\n[Internal Storage]%1$s</string>
<string name="zip_download_title">Downloading</string>
<string name="zip_download_msg">Downloading zip file …</string>
<string name="zip_process_title">Processing</string>
<string name="zip_process_msg">Processing zip file …</string>
<string name="manual_boot_image">Please manually select a boot image!</string>
<string name="manager_update_title">New Magisk Manager Update Available!</string>
<string name="manager_download_install">Press to download and install</string>
<string name="magisk_updates">Magisk Updates</string>
<string name="flashing">Flashing</string>
<string name="hide_manager_toast">Hiding Magisk Manager…</string>
<string name="hide_manager_fail_toast">Hide Magisk Manager failed…</string>
<string name="download_zip_only">Download Zip Only</string>
<string name="patch_boot_file">Patch Boot Image File</string>
<string name="direct_install">Direct Install (Recommend)</string>
<string name="install_second_slot">Install to Second Slot (After OTA)</string>
<string name="select_method">Select Method</string>
<string name="no_boot_file_patch_support">Target Magisk version doesn\'t support boot image file patching</string>
<string name="boot_file_patch_msg">Select stock boot image dump in .img or .img.tar format</string>
<string name="complete_uninstall">Complete Uninstall</string>
<string name="restore_stock_boot">Restore Stock Boot</string>
<string name="restore_done">Restoration done!</string>
<string name="restore_fail">Stock backup does not exist!</string>
<string name="uninstall_toast">Uninstalling Magisk Manager in 5 seconds, please manually reboot afterwards</string>
<!--Settings Activity -->
<string name="settings_general_category">General</string>
@@ -143,12 +132,20 @@
<string name="settings_notification_summary">Show update notifications when new version is available</string>
<string name="settings_clear_cache_title">Clear Repo Cache</string>
<string name="settings_clear_cache_summary">Clear the cached information for online repos, forces the app to refresh online</string>
<string name="settings_hide_manager_title">Hide Magisk Manager</string>
<string name="settings_hide_manager_summary">Temporarily hide Magisk Manager.\nThis will install a new app called \"Unhide Magisk Manager\"</string>
<string name="language">Language</string>
<string name="system_default">(System Default)</string>
<string name="settings_update">Update Settings</string>
<string name="settings_update_channel_title">Update Channel</string>
<string name="settings_update_stable">Stable</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Patched Boot Output Format</string>
<string name="settings_boot_format_summary">Select the format of the output patched boot image.\nChoose .img to flash through fastboot/download mode; choose .img.tar to flash with ODIN.</string>
<string name="settings_core_only_title">Magisk Core Only Mode</string>
<string name="settings_core_only_summary">Enable only core features, all modules will not be loaded. MagiskSU, MagiskHide, and systemless hosts will still be enabled</string>
<string name="settings_magiskhide_summary">Hide Magisk from various detections</string>
<string name="settings_busybox_title">Enable BusyBox</string>
<string name="settings_busybox_summary">Bind mount Magisk\'s built-in busybox to xbin</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Systemless hosts support for Adblock apps</string>
@@ -204,13 +201,13 @@
<string name="twentymin">20 min</string>
<string name="thirtymin">30 min</string>
<string name="sixtymin">60 min</string>
<string name="su_allow_toast">%1$s is granted Superuser rights</string>
<string name="su_deny_toast">%1$s is denied Superuser rights</string>
<string name="su_allow_toast">%1$s was granted Superuser rights</string>
<string name="su_deny_toast">%1$s was denied Superuser rights</string>
<string name="no_apps_found">No apps found</string>
<string name="su_snack_grant">Superuser rights of %1$s is granted</string>
<string name="su_snack_deny">Superuser rights of %1$s is denied</string>
<string name="su_snack_notif_on">Notifications of %1$s is enabled</string>
<string name="su_snack_notif_off">Notifications of %1$s is disabled</string>
<string name="su_snack_grant">Superuser rights of %1$s are granted</string>
<string name="su_snack_deny">Superuser rights of %1$s are denied</string>
<string name="su_snack_notif_on">Notifications of %1$s are enabled</string>
<string name="su_snack_notif_off">Notifications of %1$s are disabled</string>
<string name="su_snack_log_on">Logging of %1$s is enabled</string>
<string name="su_snack_log_off">Logging of %1$s is disabled</string>
<string name="su_snack_revoke">%1$s rights are revoked</string>

View File

@@ -2,6 +2,7 @@
android:layout_marginTop="?attr/actionBarSize"
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:key="general"
android:title="@string/settings_general_category">
<SwitchPreference
@@ -9,15 +10,39 @@
android:title="@string/settings_dark_theme_title"
android:summary="@string/settings_dark_theme_summary" />
<Preference
android:key="clear"
android:title="@string/settings_clear_cache_title"
android:summary="@string/settings_clear_cache_summary" />
<Preference
android:key="hide"
android:title="@string/settings_hide_manager_title"
android:summary="@string/settings_hide_manager_summary" />
</PreferenceCategory>
<PreferenceCategory
android:key="update"
android:title="@string/settings_update">
<SwitchPreference
android:key="notification"
android:title="@string/settings_notification_title"
android:summary="@string/settings_notification_summary" />
<Preference
android:key="clear"
android:title="@string/settings_clear_cache_title"
android:summary="@string/settings_clear_cache_summary" />
<ListPreference
android:key="update_channel"
android:title="@string/settings_update_channel_title"
android:entries="@array/update_channel"
android:entryValues="@array/value_array" />
<ListPreference
android:key="boot_format"
android:title="@string/settings_boot_format_title"
android:entries="@array/boot_formats"
android:entryValues="@array/boot_formats"
android:summary="@string/settings_boot_format_summary"/>
</PreferenceCategory>

View File

@@ -7,7 +7,7 @@ buildscript {
maven { url "https://maven.google.com" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha7'
classpath 'com.android.tools.build:gradle:3.0.0-beta6'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -20,6 +20,3 @@ org.gradle.parallel=true
# When set to true the Gradle daemon is used to run the build. For local developer builds this is our favorite property.
# The developer environment is optimized for speed and feedback so we nearly always run Gradle jobs with the daemon.
org.gradle.daemon=true
# Enable AAPT2
android.enableAapt2=true

Binary file not shown.

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