mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 12:40:56 +00:00
Compare commits
85 Commits
manager-v4
...
manager-v5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4dc9419d2e | ||
![]() |
d2bcac813e | ||
![]() |
080c37a7f6 | ||
![]() |
f9a3838db6 | ||
![]() |
1e61db104b | ||
![]() |
30a9c7718d | ||
![]() |
34b052b5d3 | ||
![]() |
aaa12853ad | ||
![]() |
b0ab55b0bf | ||
![]() |
d2f8496f4e | ||
![]() |
1a69b16d36 | ||
![]() |
b5e8673e62 | ||
![]() |
264c6a50b6 | ||
![]() |
493642eb38 | ||
![]() |
28d42b9164 | ||
![]() |
42f29062ca | ||
![]() |
c4377ed6c2 | ||
![]() |
7d283ed65f | ||
![]() |
bf1f941e50 | ||
![]() |
789fef34ba | ||
![]() |
1daf5a611c | ||
![]() |
6aed1db67e | ||
![]() |
cf68854770 | ||
![]() |
711392c73b | ||
![]() |
9573c32481 | ||
![]() |
a15f80f79d | ||
![]() |
23e7475f06 | ||
![]() |
1eb571b787 | ||
![]() |
dd3b716d85 | ||
![]() |
28649c07e3 | ||
![]() |
961e02be0d | ||
![]() |
a161491bfd | ||
![]() |
e0b4d1c1e4 | ||
![]() |
fd4aaab137 | ||
![]() |
42d14d5ca2 | ||
![]() |
d3ff482c9b | ||
![]() |
f682368eeb | ||
![]() |
4a5d033efb | ||
![]() |
343161b195 | ||
![]() |
bc576a9659 | ||
![]() |
19e407fcc4 | ||
![]() |
bc7327d004 | ||
![]() |
666fa1c797 | ||
![]() |
0eda4a7821 | ||
![]() |
862058fd2b | ||
![]() |
69e5bcd57d | ||
![]() |
efeddda328 | ||
![]() |
ff6938280e | ||
![]() |
1e4425b30f | ||
![]() |
b5d1d8cdad | ||
![]() |
029be5ccca | ||
![]() |
29c2d785b5 | ||
![]() |
abda8cfa32 | ||
![]() |
44e7d79d4c | ||
![]() |
9a1dc8ee0e | ||
![]() |
27879c3f01 | ||
![]() |
29096eb5d7 | ||
![]() |
a573baea03 | ||
![]() |
5af07c4531 | ||
![]() |
44e36feb09 | ||
![]() |
2a7d996881 | ||
![]() |
738f943a68 | ||
![]() |
47e62a5681 | ||
![]() |
1ecbfd7590 | ||
![]() |
67c139a04b | ||
![]() |
31cc008249 | ||
![]() |
9cb026439d | ||
![]() |
e6f10176c6 | ||
![]() |
0917c79470 | ||
![]() |
597baa986d | ||
![]() |
75cc4b4843 | ||
![]() |
aac088d496 | ||
![]() |
a822e5bbc5 | ||
![]() |
c527249c21 | ||
![]() |
9ef798f534 | ||
![]() |
e69b99f089 | ||
![]() |
55b8079e86 | ||
![]() |
e272dbe9af | ||
![]() |
962f8354ac | ||
![]() |
20e4a960f7 | ||
![]() |
82249cb50a | ||
![]() |
fad417e553 | ||
![]() |
5ba692f50c | ||
![]() |
907e01e524 | ||
![]() |
b8ed23efa7 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,6 @@
|
||||
/local.properties
|
||||
.idea/
|
||||
/build
|
||||
app/app-release.apk
|
||||
app/release
|
||||
*.hprof
|
||||
app/.externalNativeBuild/
|
||||
|
@@ -1,4 +1,6 @@
|
||||
# Magisk Manager
|
||||
I used Java 8 features in the app, and official supported is added in Android Studio 2.4
|
||||
Aware that Android Studio 2.4 is currently in the Preview Channel
|
||||
# Magisk Manager
|
||||
You need to install CMake and NDK to build the zipadjust library for zip preprocessing
|
||||
|
||||
## Pre-built Binaries
|
||||
Busybox (arm and x86) compiled by osm0sis (`libbusybox.so` under `app\src\main\jniLibs`)
|
||||
Source and more info: [osm0sis' Odds and Ends](https://forum.xda-developers.com/showthread.php?t=2239421)
|
||||
|
@@ -1,24 +1,25 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "26.0.0-rc1"
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "26.0.0"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.topjohnwu.magisk"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 30
|
||||
versionName "4.3.2"
|
||||
targetSdkVersion 26
|
||||
versionCode 45
|
||||
versionName "5.0.5"
|
||||
ndk {
|
||||
moduleName 'zipadjust'
|
||||
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
abiFilters 'x86', 'armeabi-v7a'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
@@ -27,7 +28,8 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
dexOptions {
|
||||
preDexLibraries = true
|
||||
preDexLibraries true
|
||||
javaMaxHeapSize "2g"
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
@@ -41,22 +43,21 @@ android {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url "https://maven.google.com" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
|
||||
compile 'com.android.support:recyclerview-v7:25.3.1'
|
||||
compile 'com.android.support:cardview-v7:25.3.1'
|
||||
compile 'com.android.support:design:25.3.1'
|
||||
compile 'com.android.support:support-v4:25.3.1'
|
||||
compile 'com.jakewharton:butterknife:8.5.1'
|
||||
compile 'com.thoughtbot:expandablerecyclerview:1.4'
|
||||
compile 'us.feras.mdv:markdownview:1.1.0'
|
||||
compile 'com.madgag.spongycastle:core:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:pkix:1.54.0.0'
|
||||
compile 'com.madgag.spongycastle:pg:1.54.0.0'
|
||||
compile 'com.google.android.gms:play-services-safetynet:9.0.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:recyclerview-v7:26.0.0-beta2'
|
||||
implementation 'com.android.support:cardview-v7:26.0.0-beta2'
|
||||
implementation 'com.android.support:design:26.0.0-beta2'
|
||||
implementation 'com.android.support:support-v4:26.0.0-beta2'
|
||||
implementation 'com.jakewharton:butterknife:8.7.0'
|
||||
implementation 'com.thoughtbot:expandablerecyclerview:1.4'
|
||||
implementation 'us.feras.mdv:markdownview:1.1.0'
|
||||
implementation 'com.madgag.spongycastle:core:1.54.0.0'
|
||||
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
|
||||
implementation 'com.madgag.spongycastle:pkix:1.54.0.0'
|
||||
implementation 'com.google.android.gms:play-services-safetynet:9.0.1'
|
||||
annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0'
|
||||
}
|
||||
|
8
app/proguard-rules.pro
vendored
8
app/proguard-rules.pro
vendored
@@ -16,12 +16,10 @@
|
||||
# public *;
|
||||
#}
|
||||
|
||||
-keep class android.support.v7.internal.** { *; }
|
||||
-keep interface android.support.v7.internal.** { *; }
|
||||
-keep class android.support.v7.** { *; }
|
||||
-keep interface android.support.v7.** { *; }
|
||||
|
||||
# SpongyCastle
|
||||
-keep class org.spongycastle.** { *; }
|
||||
-dontwarn javax.naming.**
|
||||
|
||||
-dontwarn android.content.**
|
||||
-dontwarn android.animation.**
|
||||
|
||||
|
@@ -1,14 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.topjohnwu.magisk"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<manifest
|
||||
package="com.topjohnwu.magisk"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<application
|
||||
android:name=".MagiskManager"
|
||||
@@ -52,8 +53,7 @@
|
||||
android:taskAffinity="internal.superuser"
|
||||
android:theme="@style/SuRequest" />
|
||||
|
||||
<receiver
|
||||
android:name=".superuser.SuReceiver" />
|
||||
<receiver android:name=".superuser.SuReceiver" />
|
||||
|
||||
<receiver android:name=".receivers.BootReceiver">
|
||||
<intent-filter>
|
||||
@@ -61,7 +61,17 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name=".services.BootupIntentService" />
|
||||
<receiver android:name=".receivers.PackageReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||
<data android:scheme="package" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receivers.ManagerUpdate" />
|
||||
|
||||
<service android:name=".services.OnBootIntentService" />
|
||||
|
||||
<service
|
||||
android:name=".services.UpdateCheckService"
|
||||
|
@@ -1,133 +1,137 @@
|
||||
#!/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
|
||||
|
||||
# This path should work in any cases
|
||||
TMPDIR=/dev/tmp
|
||||
|
||||
BOOTTMP=$TMPDIR/boottmp
|
||||
MAGISKBIN=/data/magisk
|
||||
CHROMEDIR=$MAGISKBIN/chromeos
|
||||
|
||||
SYSTEMLIB=/system/lib
|
||||
[ -d /system/lib64 ] && SYSTEMLIB=/system/lib64
|
||||
|
||||
# Default permissions
|
||||
umask 022
|
||||
|
||||
ui_print_wrapper() {
|
||||
type ui_print >/dev/null && ui_print "$1" || echo "$1"
|
||||
}
|
||||
|
||||
grep_prop() {
|
||||
REGEX="s/^$1=//p"
|
||||
shift
|
||||
FILES=$@
|
||||
if [ -z "$FILES" ]; then
|
||||
FILES='/system/build.prop'
|
||||
fi
|
||||
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
|
||||
}
|
||||
|
||||
find_boot_image() {
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for PARTITION in kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
|
||||
BOOTIMAGE=`readlink /dev/block/by-name/$PARTITION || readlink /dev/block/platform/*/by-name/$PARTITION || readlink /dev/block/platform/*/*/by-name/$PARTITION`
|
||||
if [ ! -z "$BOOTIMAGE" ]; then break; fi
|
||||
done
|
||||
fi
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
FSTAB="/etc/recovery.fstab"
|
||||
[ ! -f "$FSTAB" ] && FSTAB="/etc/recovery.fstab.bak"
|
||||
[ -f "$FSTAB" ] && BOOTIMAGE=`grep -E '\b/boot\b' "$FSTAB" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
|
||||
fi
|
||||
}
|
||||
|
||||
# Environments
|
||||
# Set permissions
|
||||
chmod -R 755 $CHROMEDIR/futility $MAGISKBIN 2>/dev/null
|
||||
# Temporary busybox for installation
|
||||
mkdir -p $TMPDIR/busybox
|
||||
$MAGISKBIN/busybox --install -s $TMPDIR/busybox
|
||||
rm -f $TMPDIR/busybox/su $TMPDIR/busybox/sh $TMPDIR/busybox/reboot
|
||||
PATH=$TMPDIR/busybox:$PATH
|
||||
# Load utility functions
|
||||
. $MAGISKBIN/util_functions.sh
|
||||
|
||||
# Find the boot image
|
||||
find_boot_image
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
ui_print_wrapper "! Unable to detect boot image"
|
||||
exit 1
|
||||
fi
|
||||
[ -z $BOOTIMAGE ] && abort "! Unable to detect boot image"
|
||||
|
||||
ui_print_wrapper "- Found Boot Image: $BOOTIMAGE"
|
||||
ui_print_wrap "- Found Boot Image: $BOOTIMAGE"
|
||||
|
||||
rm -rf $BOOTTMP 2>/dev/null
|
||||
mkdir -p $BOOTTMP
|
||||
cd $BOOTTMP
|
||||
cd $MAGISKBIN
|
||||
|
||||
ui_print_wrapper "- Unpacking boot image"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --unpack $BOOTIMAGE
|
||||
if [ $? -ne 0 ]; then
|
||||
ui_print_wrapper "! Unable to unpack boot image"
|
||||
exit 1
|
||||
fi
|
||||
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=`LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --sha1 /data/stock_boot.img | tail -n 1`
|
||||
SHA1=`./magiskboot --sha1 /data/stock_boot.img | tail -n 1`
|
||||
STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
mv /data/stock_boot.img $STOCKDUMP
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --compress $STOCKDUMP
|
||||
./magiskboot --compress $STOCKDUMP
|
||||
fi
|
||||
|
||||
# Detect boot image state
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-test ramdisk.cpio
|
||||
./magiskboot --cpio-test ramdisk.cpio
|
||||
case $? in
|
||||
0 )
|
||||
ui_print_wrapper "! Magisk is not installed!"
|
||||
ui_print_wrapper "! Nothing to uninstall"
|
||||
0 ) # Stock boot
|
||||
ui_print_wrap "- Stock boot image detected!"
|
||||
ui_print_wrap "! Magisk is not installed!"
|
||||
exit
|
||||
;;
|
||||
1 )
|
||||
1 ) # Magisk patched
|
||||
ui_print_wrap "- Magisk patched image detected!"
|
||||
# Find SHA1 of stock boot image
|
||||
if [ -z $SHA1 ]; then
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-extract ramdisk.cpio init.magisk.rc init.magisk.rc
|
||||
SHA1=`grep_prop "# STOCKSHA1" init.magisk.rc`
|
||||
[ ! -z $SHA1 ] && STOCKDUMP=/data/stock_boot_${SHA1}.img
|
||||
rm -f init.magisk.rc
|
||||
./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_wrapper "- Boot image backup found!"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
ui_print_wrap "- Boot image backup found!"
|
||||
./magiskboot --decompress ${STOCKDUMP}.gz stock_boot.img
|
||||
else
|
||||
ui_print_wrapper "! Boot image backup unavailable"
|
||||
ui_print_wrapper "- Restoring ramdisk with backup"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
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 )
|
||||
ui_print_wrapper "- SuperSU patched image detected"
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --cpio-restore ramdisk.cpio
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $MAGISKBIN/magiskboot --repack $BOOTIMAGE stock_boot.img
|
||||
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 > config
|
||||
echo > bootloader
|
||||
LD_LIBRARY_PATH=$SYSTEMLIB $CHROMEDIR/futility vbutil_kernel --pack stock_boot.img.signed --keyblock $CHROMEDIR/kernel.keyblock --signprivate $CHROMEDIR/kernel_data_key.vbprivk --version 1 --vmlinuz stock_boot.img --config config --arch arm --bootloader bootloader --flags 0x1
|
||||
rm -f stock_boot.img
|
||||
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_wrapper "- Flashing stock/reverted image"
|
||||
[ ! -L "$BOOTIMAGE" ] && dd if=/dev/zero of=$BOOTIMAGE bs=4096 2>/dev/null
|
||||
dd if=stock_boot.img of=$BOOTIMAGE bs=4096
|
||||
ui_print_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_wrapper "- Removing Magisk files"
|
||||
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.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
|
||||
|
192
app/src/main/assets/util_functions.sh
Normal file
192
app/src/main/assets/util_functions.sh
Normal file
@@ -0,0 +1,192 @@
|
||||
##########################################################################################
|
||||
#
|
||||
# Magisk General Utility Functions
|
||||
# by topjohnwu
|
||||
#
|
||||
# Used in flash_script.sh, addon.d.sh, magisk module installers, and uninstaller
|
||||
#
|
||||
##########################################################################################
|
||||
|
||||
get_outfd() {
|
||||
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
OUTFD=0
|
||||
|
||||
for FD in `ls /proc/$$/fd`; do
|
||||
readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
ps | grep " 3 $FD " | grep -v grep >/dev/null
|
||||
if [ "$?" -eq "0" ]; then
|
||||
OUTFD=$FD
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
ui_print() {
|
||||
if $BOOTMODE; then
|
||||
echo "$1"
|
||||
else
|
||||
echo -n -e "ui_print $1\n" >> /proc/self/fd/$OUTFD
|
||||
echo -n -e "ui_print\n" >> /proc/self/fd/$OUTFD
|
||||
fi
|
||||
}
|
||||
|
||||
getvar() {
|
||||
local VARNAME=$1
|
||||
local VALUE=$(eval echo \$"$VARNAME");
|
||||
for FILE in /dev/.magisk /data/.magisk /cache/.magisk /system/.magisk; do
|
||||
if [ -z "$VALUE" ]; then
|
||||
LINE=$(cat $FILE 2>/dev/null | grep "$VARNAME=")
|
||||
if [ ! -z "$LINE" ]; then
|
||||
VALUE=${LINE#*=}
|
||||
fi
|
||||
fi
|
||||
done
|
||||
eval $VARNAME=\$VALUE
|
||||
}
|
||||
|
||||
find_boot_image() {
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do
|
||||
BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null
|
||||
[ ! -z $BOOTIMAGE ] && break
|
||||
done
|
||||
fi
|
||||
# Recovery fallback
|
||||
if [ -z "$BOOTIMAGE" ]; then
|
||||
for FSTAB in /etc/*fstab*; do
|
||||
BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -v "#" | grep -oE '/dev/[a-zA-Z0-9_./-]*'`
|
||||
[ ! -z $BOOTIMAGE ] && break
|
||||
done
|
||||
fi
|
||||
[ -L "$BOOTIMAGE" ] && BOOTIMAGE=`readlink $BOOTIMAGE`
|
||||
}
|
||||
|
||||
is_mounted() {
|
||||
if [ ! -z "$2" ]; then
|
||||
cat /proc/mounts | grep $1 | grep $2, >/dev/null
|
||||
else
|
||||
cat /proc/mounts | grep $1 >/dev/null
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
|
||||
grep_prop() {
|
||||
REGEX="s/^$1=//p"
|
||||
shift
|
||||
FILES=$@
|
||||
if [ -z "$FILES" ]; then
|
||||
FILES='/system/build.prop'
|
||||
fi
|
||||
cat $FILES 2>/dev/null | sed -n "$REGEX" | head -n 1
|
||||
}
|
||||
|
||||
remove_system_su() {
|
||||
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
|
||||
ui_print "! System installed root detected, mount rw :("
|
||||
mount -o rw,remount /system
|
||||
# SuperSU
|
||||
if [ -e /system/bin/.ext/.su ]; then
|
||||
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
|
||||
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
|
||||
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
|
||||
cd /system/bin
|
||||
if [ -e app_process64 ]; then
|
||||
ln -sf app_process64 app_process
|
||||
else
|
||||
ln -sf app_process32 app_process
|
||||
fi
|
||||
fi
|
||||
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
|
||||
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
|
||||
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
|
||||
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
|
||||
/system/.supersu /cache/.supersu /data/.supersu \
|
||||
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
api_level_arch_detect() {
|
||||
API=`grep_prop ro.build.version.sdk`
|
||||
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
|
||||
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
|
||||
ABILONG=`grep_prop ro.product.cpu.abi`
|
||||
|
||||
ARCH=arm
|
||||
IS64BIT=false
|
||||
if [ "$ABI" = "x86" ]; then ARCH=x86; fi;
|
||||
if [ "$ABI2" = "x86" ]; then ARCH=x86; fi;
|
||||
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi;
|
||||
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi;
|
||||
}
|
||||
|
||||
recovery_actions() {
|
||||
# TWRP bug fix
|
||||
mount -o bind /dev/urandom /dev/random
|
||||
# Temporarily block out all custom recovery binaries/libs
|
||||
mv /sbin /sbin_tmp
|
||||
# Add all possible library paths
|
||||
OLD_LD_PATH=$LD_LIBRARY_PATH
|
||||
$IS64BIT && export LD_LIBRARY_PATH=/system/lib64:/system/vendor/lib64 || export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib
|
||||
}
|
||||
|
||||
recovery_cleanup() {
|
||||
mv /sbin_tmp /sbin
|
||||
# Clear LD_LIBRARY_PATH
|
||||
export LD_LIBRARY_PATH=$OLD_LD_PATH
|
||||
ui_print "- Unmounting partitions"
|
||||
umount -l /system
|
||||
umount -l /vendor 2>/dev/null
|
||||
umount -l /dev/random
|
||||
}
|
||||
|
||||
abort() {
|
||||
ui_print "$1"
|
||||
mv /sbin_tmp /sbin 2>/dev/null
|
||||
exit 1
|
||||
}
|
||||
|
||||
set_perm() {
|
||||
chown $2:$3 $1 || exit 1
|
||||
chmod $4 $1 || exit 1
|
||||
if [ ! -z $5 ]; then
|
||||
chcon $5 $1 2>/dev/null
|
||||
else
|
||||
chcon 'u:object_r:system_file:s0' $1 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
set_perm_recursive() {
|
||||
find $1 -type d 2>/dev/null | while read dir; do
|
||||
set_perm $dir $2 $3 $4 $6
|
||||
done
|
||||
find $1 -type f 2>/dev/null | while read file; do
|
||||
set_perm $file $2 $3 $5 $6
|
||||
done
|
||||
}
|
||||
|
||||
mktouch() {
|
||||
mkdir -p ${1%/*}
|
||||
if [ -z "$2" ]; then
|
||||
touch $1
|
||||
else
|
||||
echo $2 > $1
|
||||
fi
|
||||
chmod 644 $1
|
||||
}
|
||||
|
||||
request_size_check() {
|
||||
reqSizeM=`du -s $1 | cut -f1`
|
||||
reqSizeM=$((reqSizeM / 1024 + 1))
|
||||
}
|
||||
|
||||
image_size_check() {
|
||||
SIZE="`$MAGISKBIN/magisk --imgsize $IMG`"
|
||||
curUsedM=`echo "$SIZE" | cut -d" " -f1`
|
||||
curSizeM=`echo "$SIZE" | cut -d" " -f2`
|
||||
curFreeM=$((curSizeM - curUsedM))
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
@@ -13,13 +12,11 @@ import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.components.AboutCardRow;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -29,7 +26,7 @@ import butterknife.ButterKnife;
|
||||
|
||||
public class AboutActivity extends Activity {
|
||||
|
||||
private static final String DONATION_URL = "http://topjohnwu.github.io/donate";
|
||||
private static final String DONATION_URL = "https://www.paypal.me/topjohnwu";
|
||||
private static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
|
||||
private static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/MagiskManager";
|
||||
|
||||
@@ -45,10 +42,8 @@ public class AboutActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String theme = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("theme", "");
|
||||
Logger.dev("AboutActivity: Theme is " + theme);
|
||||
if (getApplicationContext().isDarkTheme) {
|
||||
setTheme(R.style.AppTheme_Dark);
|
||||
setTheme(R.style.AppTheme_Transparent_Dark);
|
||||
}
|
||||
setContentView(R.layout.activity_about);
|
||||
ButterKnife.bind(this);
|
||||
@@ -135,18 +130,4 @@ public class AboutActivity extends Activity {
|
||||
setFloating();
|
||||
}
|
||||
|
||||
public void setFloating() {
|
||||
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
|
||||
if (isTablet) {
|
||||
WindowManager.LayoutParams params = getWindow().getAttributes();
|
||||
params.height = getResources().getDimensionPixelSize(R.dimen.floating_height);
|
||||
params.width = getResources().getDimensionPixelSize(R.dimen.floating_width);
|
||||
params.alpha = 1.0f;
|
||||
params.dimAmount = 0.6f;
|
||||
params.flags |= 2;
|
||||
getWindow().setAttributes(params);
|
||||
setFinishOnTouchOutside(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,228 +0,0 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.ProcessMagiskZip;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class InstallFragment extends Fragment implements CallbackEvent.Listener<Void> {
|
||||
|
||||
|
||||
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||
|
||||
@BindView(R.id.current_version_title) TextView currentVersionTitle;
|
||||
@BindView(R.id.install_title) TextView installTitle;
|
||||
@BindView(R.id.block_spinner) Spinner spinner;
|
||||
@BindView(R.id.detect_bootimage) Button detectButton;
|
||||
@BindView(R.id.install_button) CardView installButton;
|
||||
@BindView(R.id.install_text) TextView installText;
|
||||
@BindView(R.id.uninstall_button) CardView uninstallButton;
|
||||
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
|
||||
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
|
||||
|
||||
@OnClick(R.id.detect_bootimage)
|
||||
public void toAutoDetect() {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.install_button)
|
||||
public void install() {
|
||||
String bootImage = null;
|
||||
if (magiskManager.blockList != null) {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
}
|
||||
} else {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
} else {
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
final String finalBootImage = bootImage;
|
||||
String filename = "Magisk-v" + magiskManager.remoteMagiskVersion + ".zip";
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
|
||||
(dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
if (magiskManager.releaseNoteLink != null) {
|
||||
Intent openReleaseNoteLink = new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink));
|
||||
openReleaseNoteLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
magiskManager.startActivity(openReleaseNoteLink);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@OnClick(R.id.uninstall_button)
|
||||
public void uninstall() {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.uninstall_magisk_title)
|
||||
.setMessage(R.string.uninstall_magisk_msg)
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||
try {
|
||||
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
||||
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||
byte[] bytes = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(bytes)) != -1) {
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
ProgressDialog progress = new ProgressDialog(getActivity());
|
||||
progress.setTitle(R.string.reboot);
|
||||
progress.show();
|
||||
new CountDownTimer(5000, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, millisUntilFinished / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||
Shell.su(true, "mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
||||
"reboot");
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private Unbinder unbinder;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_install, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
magiskManager = getApplication();
|
||||
if (magiskManager.magiskVersion < 0) {
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, getString(R.string.version_none)));
|
||||
} else {
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, "v" + magiskManager.magiskVersionString));
|
||||
}
|
||||
installTitle.setText(getString(R.string.install_magisk_title, "v" + String.format(Locale.US, "%.1f", magiskManager.remoteMagiskVersion)));
|
||||
|
||||
updateUI();
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Void> event) {
|
||||
updateUI();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
if (magiskManager.blockList == null || !Shell.rootAccess()) {
|
||||
uninstallButton.setVisibility(View.GONE);
|
||||
installText.setText(R.string.download);
|
||||
detectButton.setEnabled(false);
|
||||
keepEncChkbox.setEnabled(false);
|
||||
keepVerityChkbox.setEnabled(false);
|
||||
spinner.setEnabled(false);
|
||||
} else {
|
||||
uninstallButton.setVisibility(magiskManager.magiskVersion > 10.3 ? View.VISIBLE : View.GONE);
|
||||
installText.setText(R.string.download_install);
|
||||
detectButton.setEnabled(true);
|
||||
keepEncChkbox.setEnabled(true);
|
||||
keepVerityChkbox.setEnabled(true);
|
||||
spinner.setEnabled(true);
|
||||
|
||||
List<String> items = new ArrayList<>();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
|
||||
} else {
|
||||
items.add(getString(R.string.cannot_auto_detect));
|
||||
}
|
||||
items.addAll(magiskManager.blockList);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
toAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
getActivity().setTitle(R.string.install);
|
||||
magiskManager.blockDetectionDone.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
magiskManager.blockDetectionDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unbinder.unbind();
|
||||
}
|
||||
}
|
509
app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java
Normal file
509
app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java
Normal file
@@ -0,0 +1,509 @@
|
||||
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.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
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;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.ProcessMagiskZip;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class MagiskFragment extends Fragment
|
||||
implements CallbackEvent.Listener<Void>, SwipeRefreshLayout.OnRefreshListener {
|
||||
|
||||
private static boolean noDialog = false;
|
||||
private static int expandHeight = 0;
|
||||
private static boolean mExpanded = false;
|
||||
|
||||
private MagiskManager magiskManager;
|
||||
private Unbinder unbinder;
|
||||
|
||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
@BindView(R.id.magisk_update_card) CardView magiskUpdateCard;
|
||||
@BindView(R.id.magisk_update_icon) ImageView magiskUpdateIcon;
|
||||
@BindView(R.id.magisk_update_status) TextView magiskUpdateText;
|
||||
@BindView(R.id.magisk_update_progress) ProgressBar magiskUpdateProgress;
|
||||
|
||||
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
|
||||
@BindView(R.id.magisk_version) TextView magiskVersionText;
|
||||
@BindView(R.id.root_status_icon) ImageView rootStatusIcon;
|
||||
@BindView(R.id.root_status) TextView rootStatusText;
|
||||
|
||||
@BindView(R.id.safetyNet_card) CardView safetyNetCard;
|
||||
@BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon;
|
||||
@BindView(R.id.safetyNet_status) TextView safetyNetStatusText;
|
||||
@BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress;
|
||||
@BindView(R.id.expand_layout) LinearLayout expandLayout;
|
||||
@BindView(R.id.cts_status_icon) ImageView ctsStatusIcon;
|
||||
@BindView(R.id.cts_status) TextView ctsStatusText;
|
||||
@BindView(R.id.basic_status_icon) ImageView basicStatusIcon;
|
||||
@BindView(R.id.basic_status) TextView basicStatusText;
|
||||
|
||||
@BindView(R.id.bootimage_card) CardView bootImageCard;
|
||||
@BindView(R.id.block_spinner) Spinner spinner;
|
||||
@BindView(R.id.detect_bootimage) Button detectButton;
|
||||
@BindView(R.id.install_option_card) CardView installOptionCard;
|
||||
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
|
||||
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
|
||||
@BindView(R.id.install_button) CardView installButton;
|
||||
@BindView(R.id.install_text) TextView installText;
|
||||
@BindView(R.id.uninstall_button) CardView uninstallButton;
|
||||
|
||||
@BindColor(R.color.red500) int colorBad;
|
||||
@BindColor(R.color.green500) int colorOK;
|
||||
@BindColor(R.color.yellow500) int colorWarn;
|
||||
@BindColor(R.color.grey500) int colorNeutral;
|
||||
@BindColor(R.color.blue500) int colorInfo;
|
||||
|
||||
@OnClick(R.id.safetyNet_title)
|
||||
public void safetyNet() {
|
||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||
safetyNetRefreshIcon.setVisibility(View.GONE);
|
||||
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
||||
Utils.checkSafetyNet(getActivity());
|
||||
collapse();
|
||||
}
|
||||
|
||||
@OnClick(R.id.detect_bootimage)
|
||||
public void toAutoDetect() {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.install_button)
|
||||
public void install() {
|
||||
String bootImage = null;
|
||||
if (magiskManager.blockList != null) {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
bootImage = magiskManager.bootBlock;
|
||||
} else {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
} else {
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
|
||||
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,
|
||||
(dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
if (magiskManager.releaseNoteLink != null) {
|
||||
Intent openReleaseNoteLink = new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink));
|
||||
openReleaseNoteLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
magiskManager.startActivity(openReleaseNoteLink);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@OnClick(R.id.uninstall_button)
|
||||
public void uninstall() {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.uninstall_magisk_title)
|
||||
.setMessage(R.string.uninstall_magisk_msg)
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||
try {
|
||||
InputStream in = magiskManager.getAssets().open(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));
|
||||
Shell.su(true,
|
||||
"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();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
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();
|
||||
|
||||
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);
|
||||
setExpanded();
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
updateUI();
|
||||
|
||||
magiskUpdateText.setText(R.string.checking_for_updates);
|
||||
magiskUpdateProgress.setVisibility(View.VISIBLE);
|
||||
magiskUpdateIcon.setVisibility(View.GONE);
|
||||
|
||||
safetyNetStatusText.setText(R.string.safetyNet_check_text);
|
||||
|
||||
magiskManager.safetyNetDone.isTriggered = false;
|
||||
magiskManager.updateCheckDone.isTriggered = false;
|
||||
magiskManager.remoteMagiskVersionString = null;
|
||||
magiskManager.remoteMagiskVersionCode = -1;
|
||||
collapse();
|
||||
noDialog = false;
|
||||
|
||||
// Trigger state check
|
||||
if (Utils.checkNetworkStatus(magiskManager)) {
|
||||
new CheckUpdates(getActivity()).exec();
|
||||
} else {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Void> event) {
|
||||
if (event == magiskManager.updateCheckDone) {
|
||||
updateCheckUI();
|
||||
} else if (event == magiskManager.safetyNetDone) {
|
||||
updateSafetyNetUI();
|
||||
} else if (event == magiskManager.blockDetectionDone) {
|
||||
updateInstallUI();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
// Manual trigger if already done
|
||||
if (magiskManager.updateCheckDone.isTriggered)
|
||||
updateCheckUI();
|
||||
if (magiskManager.safetyNetDone.isTriggered)
|
||||
updateSafetyNetUI();
|
||||
if (magiskManager.blockDetectionDone.isTriggered || !Shell.rootAccess())
|
||||
updateInstallUI();
|
||||
magiskManager.updateCheckDone.register(this);
|
||||
magiskManager.safetyNetDone.register(this);
|
||||
magiskManager.blockDetectionDone.register(this);
|
||||
getActivity().setTitle(R.string.magisk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
magiskManager.updateCheckDone.unRegister(this);
|
||||
magiskManager.safetyNetDone.unRegister(this);
|
||||
magiskManager.blockDetectionDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unbinder.unbind();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
((MainActivity) getActivity()).checkHideSection();
|
||||
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);
|
||||
updateVersionUI();
|
||||
}
|
||||
|
||||
private void updateVersionUI() {
|
||||
int image, color;
|
||||
|
||||
magiskManager.updateMagiskInfo();
|
||||
|
||||
if (magiskManager.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));
|
||||
}
|
||||
|
||||
magiskStatusIcon.setImageResource(image);
|
||||
magiskStatusIcon.setColorFilter(color);
|
||||
|
||||
switch (Shell.rootStatus) {
|
||||
case 0:
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
rootStatusText.setText(R.string.not_rooted);
|
||||
break;
|
||||
case 1:
|
||||
if (magiskManager.suVersion != null) {
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
rootStatusText.setText(magiskManager.suVersion);
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
default:
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
rootStatusText.setText(R.string.root_error);
|
||||
}
|
||||
|
||||
rootStatusIcon.setImageResource(image);
|
||||
rootStatusIcon.setColorFilter(color);
|
||||
}
|
||||
|
||||
private void updateCheckUI() {
|
||||
int image, color;
|
||||
|
||||
if (magiskManager.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));
|
||||
}
|
||||
|
||||
magiskUpdateIcon.setImageResource(image);
|
||||
magiskUpdateIcon.setColorFilter(color);
|
||||
magiskUpdateIcon.setVisibility(View.VISIBLE);
|
||||
|
||||
magiskUpdateProgress.setVisibility(View.GONE);
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
private void updateInstallUI() {
|
||||
if (!Shell.rootAccess()) {
|
||||
installText.setText(R.string.download);
|
||||
} 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);
|
||||
toAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSafetyNetUI() {
|
||||
int image, color;
|
||||
safetyNetProgress.setVisibility(View.GONE);
|
||||
safetyNetRefreshIcon.setVisibility(View.VISIBLE);
|
||||
if (magiskManager.SNCheckResult.failed) {
|
||||
safetyNetStatusText.setText(magiskManager.SNCheckResult.errmsg);
|
||||
collapse();
|
||||
} else {
|
||||
safetyNetStatusText.setText(R.string.safetyNet_check_success);
|
||||
if (magiskManager.SNCheckResult.ctsProfile) {
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
} else {
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
}
|
||||
ctsStatusText.setText("ctsProfile: " + magiskManager.SNCheckResult.ctsProfile);
|
||||
ctsStatusIcon.setImageResource(image);
|
||||
ctsStatusIcon.setColorFilter(color);
|
||||
|
||||
if (magiskManager.SNCheckResult.basicIntegrity) {
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
} else {
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
}
|
||||
basicStatusText.setText("basicIntegrity: " + magiskManager.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;
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.SerialTask;
|
||||
import com.topjohnwu.magisk.asyncs.RootTask;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@@ -127,14 +127,14 @@ public class MagiskLogFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
public class LogManager extends SerialTask<Object, Void, Object> {
|
||||
private class LogManager extends RootTask<Object, Void, Object> {
|
||||
|
||||
int mode;
|
||||
File targetFile;
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
@Override
|
||||
protected Object doInBackground(Object... params) {
|
||||
protected Object doInRoot(Object... params) {
|
||||
mode = (int) params[0];
|
||||
switch (mode) {
|
||||
case 0:
|
||||
|
@@ -1,17 +1,22 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.app.Application;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.SparseArray;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.module.Module;
|
||||
import com.topjohnwu.magisk.module.Repo;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.SafetyNetHelper;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
||||
@@ -22,10 +27,15 @@ import java.util.List;
|
||||
public class MagiskManager extends Application {
|
||||
|
||||
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
|
||||
public static final String MAGISK_HIDE_PATH = "/magisk/.core/magiskhide/";
|
||||
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 MAGISKHIDE_PROP = "persist.magisk.hide";
|
||||
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
|
||||
public static final String NOTIFICATION_CHANNEL = "magisk_update_notice";
|
||||
|
||||
// Events
|
||||
public final CallbackEvent<Void> blockDetectionDone = new CallbackEvent<>();
|
||||
@@ -35,20 +45,22 @@ public class MagiskManager extends Application {
|
||||
public final CallbackEvent<Void> repoLoadDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> updateCheckDone = new CallbackEvent<>();
|
||||
public final CallbackEvent<Void> safetyNetDone = new CallbackEvent<>();
|
||||
public final SparseArray<CallbackEvent<Policy>> uidSuRequest = new SparseArray<>();
|
||||
|
||||
// Info
|
||||
public double magiskVersion;
|
||||
public String magiskVersionString;
|
||||
public double remoteMagiskVersion = -1;
|
||||
public int magiskVersionCode = -1;
|
||||
public String remoteMagiskVersionString;
|
||||
public int remoteMagiskVersionCode = -1;
|
||||
public String magiskLink;
|
||||
public String releaseNoteLink;
|
||||
public int SNCheckResult = -1;
|
||||
public String remoteManagerVersionString;
|
||||
public int remoteManagerVersionCode = -1;
|
||||
public String managerLink;
|
||||
public SafetyNetHelper.Result SNCheckResult;
|
||||
public String bootBlock = null;
|
||||
public boolean isSuClient = false;
|
||||
public String suVersion = null;
|
||||
public boolean disabled;
|
||||
public boolean magiskHideStarted;
|
||||
|
||||
// Data
|
||||
public ValueSortedMap<String, Repo> repoMap;
|
||||
@@ -64,14 +76,18 @@ public class MagiskManager extends Application {
|
||||
public boolean magiskHide;
|
||||
public boolean isDarkTheme;
|
||||
public boolean updateNotification;
|
||||
public boolean busybox;
|
||||
public boolean suReauth;
|
||||
public int suRequestTimeout;
|
||||
public int suLogTimeout = 14;
|
||||
public int suAccessState;
|
||||
public int multiuserMode;
|
||||
public int suResponseType;
|
||||
public int suNotificationType;
|
||||
public int suNamespaceMode;
|
||||
|
||||
// Global resources
|
||||
public SharedPreferences prefs;
|
||||
public SuDatabaseHelper suDB;
|
||||
|
||||
private static Handler mHandler = new Handler();
|
||||
|
||||
@@ -91,86 +107,111 @@ public class MagiskManager extends Application {
|
||||
|
||||
public void init() {
|
||||
isDarkTheme = prefs.getBoolean("dark_theme", false);
|
||||
devLogging = prefs.getBoolean("developer_logging", false);
|
||||
shellLogging = prefs.getBoolean("shell_logging", false);
|
||||
magiskHide = prefs.getBoolean("magiskhide", false);
|
||||
if (BuildConfig.DEBUG) {
|
||||
devLogging = prefs.getBoolean("developer_logging", false);
|
||||
shellLogging = prefs.getBoolean("shell_logging", false);
|
||||
} else {
|
||||
devLogging = false;
|
||||
shellLogging = false;
|
||||
}
|
||||
magiskHide = prefs.getBoolean("magiskhide", true);
|
||||
updateNotification = prefs.getBoolean("notification", true);
|
||||
initSU();
|
||||
// Always start a new root shell manually, just for safety
|
||||
Shell.init();
|
||||
updateMagiskInfo();
|
||||
initSuAccess();
|
||||
initSuConfigs();
|
||||
// Initialize busybox
|
||||
File busybox = new File(getApplicationInfo().dataDir + "/busybox/busybox");
|
||||
if (!busybox.exists() || !TextUtils.equals(prefs.getString("busybox_version", ""), BUSYBOX_VERSION)) {
|
||||
busybox.getParentFile().mkdirs();
|
||||
Shell.su(
|
||||
"cp -f " + new File(getApplicationInfo().nativeLibraryDir, "libbusybox.so") + " " + busybox,
|
||||
"chmod -R 755 " + busybox.getParent(),
|
||||
busybox + " --install -s " + busybox.getParent()
|
||||
);
|
||||
}
|
||||
// Initialize prefs
|
||||
prefs.edit()
|
||||
.putBoolean("dark_theme", isDarkTheme)
|
||||
.putBoolean("magiskhide", magiskHide)
|
||||
.putBoolean("notification", updateNotification)
|
||||
.putBoolean("busybox", busybox)
|
||||
.putBoolean("hosts", new File("/magisk/.core/hosts").exists())
|
||||
.putBoolean("disable", Utils.itemExist(MAGISK_DISABLE_FILE))
|
||||
.putBoolean("su_reauth", suReauth)
|
||||
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
|
||||
.putString("su_auto_response", String.valueOf(suResponseType))
|
||||
.putString("su_notification", String.valueOf(suNotificationType))
|
||||
.putString("su_access", String.valueOf(suAccessState))
|
||||
.putString("multiuser_mode", String.valueOf(multiuserMode))
|
||||
.putString("mnt_ns", String.valueOf(suNamespaceMode))
|
||||
.putString("busybox_version", BUSYBOX_VERSION)
|
||||
.apply();
|
||||
// Add busybox to PATH
|
||||
Shell.su("PATH=$PATH:" + busybox.getParent());
|
||||
|
||||
// Create notification channel on Android O
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL,
|
||||
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
|
||||
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void initSuConfigs() {
|
||||
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 initSuAccess() {
|
||||
public void initSU() {
|
||||
// Create the app data directory, so su binary can work properly
|
||||
new File(getApplicationInfo().dataDir).mkdirs();
|
||||
|
||||
initSUConfig();
|
||||
|
||||
List<String> ret = Shell.sh("su -v");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suVersion = ret.get(0);
|
||||
isSuClient = suVersion.toUpperCase().contains("MAGISK");
|
||||
}
|
||||
if (isSuClient) {
|
||||
ret = Shell.sh("getprop persist.sys.root_access");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suAccessState = Integer.parseInt(ret.get(0));
|
||||
} else {
|
||||
Shell.su(true, "setprop persist.sys.root_access 3");
|
||||
suAccessState = 3;
|
||||
}
|
||||
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 = Shell.sh("getprop magisk.version");
|
||||
List<String> ret;
|
||||
ret = Shell.sh("magisk -v");
|
||||
if (!Utils.isValidShellResponse(ret)) {
|
||||
magiskVersion = -1;
|
||||
} else {
|
||||
try {
|
||||
magiskVersionString = ret.get(0);
|
||||
magiskVersion = Double.parseDouble(ret.get(0));
|
||||
} catch (NumberFormatException e) {
|
||||
// Custom version don't need to receive updates
|
||||
magiskVersion = Double.POSITIVE_INFINITY;
|
||||
ret = Shell.sh("getprop magisk.version");
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
try {
|
||||
magiskVersionString = ret.get(0);
|
||||
magiskVersionCode = (int) Double.parseDouble(ret.get(0)) * 10;
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
} else {
|
||||
magiskVersionString = ret.get(0).split(":")[0];
|
||||
ret = Shell.sh("magisk -V");
|
||||
try {
|
||||
magiskVersionCode = Integer.parseInt(ret.get(0));
|
||||
} catch (NumberFormatException ignored) {}
|
||||
}
|
||||
ret = Shell.sh("getprop persist.magisk.busybox");
|
||||
try {
|
||||
busybox = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
busybox = false;
|
||||
}
|
||||
ret = Shell.sh("getprop ro.magisk.disable");
|
||||
ret = Shell.sh("getprop " + DISABLE_INDICATION_PROP);
|
||||
try {
|
||||
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
disabled = false;
|
||||
}
|
||||
ret = Shell.sh("getprop persist.magisk.hide");
|
||||
ret = Shell.sh("getprop " + MAGISKHIDE_PROP);
|
||||
try {
|
||||
magiskHideStarted = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
|
||||
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
|
||||
} catch (NumberFormatException e) {
|
||||
magiskHideStarted = false;
|
||||
}
|
||||
|
||||
if (magiskHideStarted) {
|
||||
magiskHide = true;
|
||||
}
|
||||
|
||||
|
@@ -22,6 +22,7 @@ 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.Utils;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
@@ -81,7 +82,6 @@ public class MainActivity extends Activity
|
||||
|
||||
navigationView.setNavigationItemSelectedListener(this);
|
||||
getApplicationContext().reloadMainActivity.register(this);
|
||||
getApplicationContext().updateCheckDone.register(this);
|
||||
|
||||
}
|
||||
|
||||
@@ -91,31 +91,21 @@ public class MainActivity extends Activity
|
||||
checkHideSection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
navigate(savedInstanceState.getInt(MagiskManager.INTENT_SECTION, R.id.status));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt(MagiskManager.INTENT_SECTION, mDrawerItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
getApplicationContext().reloadMainActivity.unRegister(this);
|
||||
getApplicationContext().updateCheckDone.unRegister(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (drawer.isDrawerOpen(navigationView))
|
||||
if (drawer.isDrawerOpen(navigationView)) {
|
||||
drawer.closeDrawer(navigationView);
|
||||
else
|
||||
} else if (mDrawerItem != R.id.magisk) {
|
||||
navigate(R.id.magisk);
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,37 +118,30 @@ public class MainActivity extends Activity
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Void> event) {
|
||||
if (event == getApplicationContext().reloadMainActivity) {
|
||||
recreate();
|
||||
} else if (event == getApplicationContext().updateCheckDone) {
|
||||
checkHideSection();
|
||||
}
|
||||
recreate();
|
||||
}
|
||||
|
||||
private void checkHideSection() {
|
||||
public void checkHideSection() {
|
||||
Menu menu = navigationView.getMenu();
|
||||
menu.findItem(R.id.magiskhide).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 8
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 1300
|
||||
&& prefs.getBoolean("magiskhide", false));
|
||||
menu.findItem(R.id.modules).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.downloads).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus(this) &&
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersionCode >= 0);
|
||||
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
|
||||
menu.findItem(R.id.superuser).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().isSuClient);
|
||||
menu.findItem(R.id.install).setVisible(getApplicationContext().remoteMagiskVersion > 0);
|
||||
}
|
||||
|
||||
public void navigate(String item) {
|
||||
int itemId = R.id.status;
|
||||
int itemId = R.id.magisk;
|
||||
if (item != null) {
|
||||
switch (item) {
|
||||
case "status":
|
||||
itemId = R.id.status;
|
||||
break;
|
||||
case "magisk":
|
||||
case "install":
|
||||
itemId = R.id.install;
|
||||
itemId = R.id.magisk;
|
||||
break;
|
||||
case "superuser":
|
||||
itemId = R.id.superuser;
|
||||
@@ -191,11 +174,8 @@ public class MainActivity extends Activity
|
||||
mDrawerItem = itemId;
|
||||
navigationView.setCheckedItem(itemId);
|
||||
switch (itemId) {
|
||||
case R.id.status:
|
||||
displayFragment(new StatusFragment(), "status", true);
|
||||
break;
|
||||
case R.id.install:
|
||||
displayFragment(new InstallFragment(), "install", true);
|
||||
case R.id.magisk:
|
||||
displayFragment(new MagiskFragment(), "magisk", true);
|
||||
break;
|
||||
case R.id.superuser:
|
||||
displayFragment(new SuperuserFragment(), "superuser", true);
|
||||
|
@@ -1,21 +1,22 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceFragment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.SwitchPreference;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.MagiskHide;
|
||||
import com.topjohnwu.magisk.asyncs.SerialTask;
|
||||
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.Utils;
|
||||
@@ -31,10 +32,10 @@ public class SettingsActivity extends Activity {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getApplicationContext().isDarkTheme) {
|
||||
setTheme(R.style.AppTheme_Dark);
|
||||
setTheme(R.style.AppTheme_Transparent_Dark);
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_container);
|
||||
setContentView(R.layout.activity_settings);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
setSupportActionBar(toolbar);
|
||||
@@ -55,31 +56,14 @@ public class SettingsActivity extends Activity {
|
||||
|
||||
}
|
||||
|
||||
public void setFloating() {
|
||||
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
|
||||
if (isTablet) {
|
||||
WindowManager.LayoutParams params = getWindow().getAttributes();
|
||||
params.height = getResources().getDimensionPixelSize(R.dimen.floating_height);
|
||||
params.width = getResources().getDimensionPixelSize(R.dimen.floating_width);
|
||||
params.alpha = 1.0f;
|
||||
params.dimAmount = 0.6f;
|
||||
params.flags |= 2;
|
||||
getWindow().setAttributes(params);
|
||||
setFinishOnTouchOutside(true);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SettingsFragment extends PreferenceFragment
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private SharedPreferences prefs;
|
||||
private PreferenceScreen prefScreen;
|
||||
|
||||
private ListPreference suAccess, autoRes, suNotification, requestTimeout;
|
||||
|
||||
private MagiskManager getApplication() {
|
||||
return Utils.getMagiskManager(getActivity());
|
||||
}
|
||||
private ListPreference suAccess, autoRes, suNotification, requestTimeout, multiuserMode, namespaceMode;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -87,30 +71,50 @@ public class SettingsActivity extends Activity {
|
||||
addPreferencesFromResource(R.xml.app_settings);
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
prefScreen = getPreferenceScreen();
|
||||
magiskManager = Utils.getMagiskManager(getActivity());
|
||||
|
||||
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
|
||||
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
|
||||
PreferenceCategory developer = (PreferenceCategory) findPreference("developer");
|
||||
|
||||
suAccess = (ListPreference) findPreference("su_access");
|
||||
autoRes = (ListPreference) findPreference("su_auto_response");
|
||||
requestTimeout = (ListPreference) findPreference("su_request_timeout");
|
||||
suNotification = (ListPreference) findPreference("su_notification");
|
||||
multiuserMode = (ListPreference) findPreference("multiuser_mode");
|
||||
namespaceMode = (ListPreference) findPreference("mnt_ns");
|
||||
SwitchPreference reauth = (SwitchPreference) findPreference("su_reauth");
|
||||
|
||||
setSummary();
|
||||
|
||||
// Disable dangerous settings in user mode if selected owner manage
|
||||
if (getActivity().getApplicationInfo().uid > 99999) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
prefScreen.removePreference(suCategory);
|
||||
}
|
||||
|
||||
// Remove re-authentication option on Android O, it will not work
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
suCategory.removePreference(reauth);
|
||||
}
|
||||
|
||||
findPreference("clear").setOnPreferenceClickListener((pref) -> {
|
||||
Utils.clearRepoCache(getActivity());
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!BuildConfig.DEBUG) {
|
||||
prefScreen.removePreference(developer);
|
||||
}
|
||||
|
||||
if (!Shell.rootAccess()) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
prefScreen.removePreference(suCategory);
|
||||
} else {
|
||||
if (!getApplication().isSuClient) {
|
||||
if (!magiskManager.isSuClient) {
|
||||
prefScreen.removePreference(suCategory);
|
||||
}
|
||||
if (getApplication().magiskVersion < 11) {
|
||||
if (magiskManager.magiskVersionCode < 1300) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
}
|
||||
}
|
||||
@@ -136,51 +140,25 @@ public class SettingsActivity extends Activity {
|
||||
switch (key) {
|
||||
case "dark_theme":
|
||||
enabled = prefs.getBoolean("dark_theme", false);
|
||||
if (getApplication().isDarkTheme != enabled) {
|
||||
getApplication().isDarkTheme = enabled;
|
||||
getApplication().reloadMainActivity.trigger();
|
||||
if (magiskManager.isDarkTheme != enabled) {
|
||||
magiskManager.isDarkTheme = enabled;
|
||||
magiskManager.reloadMainActivity.trigger();
|
||||
getActivity().recreate();
|
||||
}
|
||||
break;
|
||||
case "disable":
|
||||
enabled = prefs.getBoolean("disable", false);
|
||||
new SerialTask<Void, Void, Void>() {
|
||||
private boolean enable = enabled;
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (enable) {
|
||||
Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
} else {
|
||||
Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
if (enabled) {
|
||||
Utils.createFile(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
} else {
|
||||
Utils.removeItem(MagiskManager.MAGISK_DISABLE_FILE);
|
||||
}
|
||||
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
|
||||
break;
|
||||
case "busybox":
|
||||
enabled = prefs.getBoolean("busybox", false);
|
||||
new SerialTask<Void, Void, Void>() {
|
||||
private boolean enable = enabled;
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (enable) {
|
||||
Shell.su(
|
||||
"setprop persist.magisk.busybox 1",
|
||||
"sh /sbin/magic_mask.sh mount_busybox");
|
||||
} else {
|
||||
Shell.su(
|
||||
"setprop persist.magisk.busybox 0",
|
||||
"umount /system/xbin");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
break;
|
||||
case "magiskhide":
|
||||
enabled = prefs.getBoolean("magiskhide", false);
|
||||
if (enabled) {
|
||||
if (!getApplication().isSuClient) {
|
||||
if (!magiskManager.isSuClient) {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.no_magisksu_title)
|
||||
.setMessage(R.string.no_magisksu_msg)
|
||||
@@ -196,33 +174,36 @@ public class SettingsActivity extends Activity {
|
||||
break;
|
||||
case "hosts":
|
||||
enabled = prefs.getBoolean("hosts", false);
|
||||
new SerialTask<Void, Void, Void>() {
|
||||
private boolean enable = enabled;
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (enable) {
|
||||
Shell.su("cp -af /system/etc/hosts /magisk/.core/hosts",
|
||||
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
|
||||
} else {
|
||||
Shell.su("umount -l /system/etc/hosts",
|
||||
"rm -f /magisk/.core/hosts");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
if (enabled) {
|
||||
Shell.su_async(null,
|
||||
"cp -af /system/etc/hosts /magisk/.core/hosts",
|
||||
"mount -o bind /magisk/.core/hosts /system/etc/hosts");
|
||||
} else {
|
||||
Shell.su_async(null,
|
||||
"umount -l /system/etc/hosts",
|
||||
"rm -f /magisk/.core/hosts");
|
||||
}
|
||||
break;
|
||||
case "su_access":
|
||||
getApplication().suAccessState = Utils.getPrefsInt(prefs, "su_access", 0);
|
||||
Shell.su("setprop persist.sys.root_access " + getApplication().suAccessState);
|
||||
magiskManager.suAccessState = Utils.getPrefsInt(prefs, "su_access", 3);
|
||||
magiskManager.suDB.setSettings(SuDatabaseHelper.ROOT_ACCESS, magiskManager.suAccessState);
|
||||
break;
|
||||
case "multiuser_mode":
|
||||
magiskManager.multiuserMode = Utils.getPrefsInt(prefs, "multiuser_mode", 0);
|
||||
magiskManager.suDB.setSettings(SuDatabaseHelper.MULTIUSER_MODE, magiskManager.multiuserMode);
|
||||
break;
|
||||
case "mnt_ns":
|
||||
magiskManager.suNamespaceMode = Utils.getPrefsInt(prefs, "mnt_ns", 1);
|
||||
magiskManager.suDB.setSettings(SuDatabaseHelper.MNT_NS, magiskManager.suNamespaceMode);
|
||||
break;
|
||||
case "su_request_timeout":
|
||||
getApplication().suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
|
||||
magiskManager.suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
|
||||
break;
|
||||
case "su_auto_response":
|
||||
getApplication().suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
|
||||
magiskManager.suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", 0);
|
||||
break;
|
||||
case "su_notification":
|
||||
getApplication().suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
|
||||
magiskManager.suNotificationType = Utils.getPrefsInt(prefs, "su_notification", 1);
|
||||
break;
|
||||
case "developer_logging":
|
||||
MagiskManager.devLogging = prefs.getBoolean("developer_logging", false);
|
||||
@@ -236,13 +217,17 @@ public class SettingsActivity extends Activity {
|
||||
|
||||
private void setSummary() {
|
||||
suAccess.setSummary(getResources()
|
||||
.getStringArray(R.array.su_access)[getApplication().suAccessState]);
|
||||
.getStringArray(R.array.su_access)[magiskManager.suAccessState]);
|
||||
autoRes.setSummary(getResources()
|
||||
.getStringArray(R.array.auto_response)[getApplication().suResponseType]);
|
||||
.getStringArray(R.array.auto_response)[magiskManager.suResponseType]);
|
||||
suNotification.setSummary(getResources()
|
||||
.getStringArray(R.array.su_notification)[getApplication().suNotificationType]);
|
||||
.getStringArray(R.array.su_notification)[magiskManager.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]);
|
||||
namespaceMode.setSummary(getResources()
|
||||
.getStringArray(R.array.namespace_summary)[magiskManager.suNamespaceMode]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,15 +6,15 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.asyncs.GetBootBlocks;
|
||||
import com.topjohnwu.magisk.asyncs.LoadApps;
|
||||
import com.topjohnwu.magisk.asyncs.LoadModules;
|
||||
import com.topjohnwu.magisk.asyncs.LoadRepos;
|
||||
import com.topjohnwu.magisk.asyncs.MagiskHide;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class SplashActivity extends Activity{
|
||||
|
||||
@@ -25,49 +25,34 @@ public class SplashActivity extends Activity{
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
MagiskManager magiskManager = getApplicationContext();
|
||||
|
||||
// Init the info and configs and root shell
|
||||
magiskManager.init();
|
||||
|
||||
// Initialize the update check service, notify every 3 hours
|
||||
if (!"install".equals(getIntent().getStringExtra(MagiskManager.INTENT_SECTION))) {
|
||||
ComponentName service = new ComponentName(magiskManager, UpdateCheckService.class);
|
||||
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
|
||||
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
||||
.setPersisted(true)
|
||||
.setPeriodic(3 * 60 * 60 * 1000)
|
||||
.build();
|
||||
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
scheduler.schedule(jobInfo);
|
||||
}
|
||||
getApplicationContext().init();
|
||||
|
||||
// Now fire all async tasks
|
||||
new GetBootBlocks(this).exec();
|
||||
if (magiskManager.magiskHide && magiskManager.magiskVersion > 11 &&
|
||||
!magiskManager.magiskHideStarted) {
|
||||
new MagiskHide().enable();
|
||||
}
|
||||
new LoadModules(this) {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
super.onPostExecute(v);
|
||||
new LoadRepos(activity).exec();
|
||||
}
|
||||
}.exec();
|
||||
new LoadModules(this).setCallBack(() -> new LoadRepos(this).exec()).exec();
|
||||
new LoadApps(this).exec();
|
||||
new CheckUpdates(this, false){
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
super.onPostExecute(v);
|
||||
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
|
||||
Intent intent = new Intent(magiskManager, MainActivity.class);
|
||||
if (section != null) {
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, section);
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
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);
|
||||
}
|
||||
}.exec();
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
|
||||
if (section != null) {
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, section);
|
||||
}
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@@ -1,264 +0,0 @@
|
||||
package com.topjohnwu.magisk;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class StatusFragment extends Fragment implements CallbackEvent.Listener<Void> {
|
||||
|
||||
private static boolean noDialog = false;
|
||||
|
||||
private Unbinder unbinder;
|
||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
|
||||
@BindView(R.id.magisk_status_container) View magiskStatusContainer;
|
||||
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
|
||||
@BindView(R.id.magisk_version) TextView magiskVersionText;
|
||||
@BindView(R.id.magisk_update_status) TextView magiskUpdateText;
|
||||
@BindView(R.id.magisk_check_updates_progress) ProgressBar magiskCheckUpdatesProgress;
|
||||
|
||||
@BindView(R.id.root_status_container) View rootStatusContainer;
|
||||
@BindView(R.id.root_status_icon) ImageView rootStatusIcon;
|
||||
@BindView(R.id.root_status) TextView rootStatusText;
|
||||
@BindView(R.id.root_info) TextView rootInfoText;
|
||||
|
||||
@BindView(R.id.safetyNet_container) View safetyNetContainer;
|
||||
@BindView(R.id.safetyNet_icon) ImageView safetyNetIcon;
|
||||
@BindView(R.id.safetyNet_status) TextView safetyNetStatusText;
|
||||
@BindView(R.id.safetyNet_check_progress) ProgressBar safetyNetProgress;
|
||||
|
||||
@BindColor(R.color.red500) int colorBad;
|
||||
@BindColor(R.color.green500) int colorOK;
|
||||
@BindColor(R.color.yellow500) int colorWarn;
|
||||
@BindColor(R.color.grey500) int colorNeutral;
|
||||
@BindColor(R.color.blue500) int colorInfo;
|
||||
@BindColor(android.R.color.transparent) int trans;
|
||||
|
||||
@OnClick(R.id.safetyNet_container)
|
||||
public void safetyNet() {
|
||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||
safetyNetContainer.setBackgroundColor(trans);
|
||||
safetyNetIcon.setImageResource(0);
|
||||
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
||||
Utils.checkSafetyNet(getApplication());
|
||||
}
|
||||
|
||||
@OnClick(R.id.magisk_status_container)
|
||||
public void gotoInstall() {
|
||||
if (getApplication().remoteMagiskVersion > 0) {
|
||||
((MainActivity) getActivity()).navigate(R.id.install);
|
||||
}
|
||||
}
|
||||
|
||||
private int defaultColor;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_status, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
|
||||
defaultColor = magiskUpdateText.getCurrentTextColor();
|
||||
|
||||
mSwipeRefreshLayout.setOnRefreshListener(() -> {
|
||||
magiskStatusContainer.setBackgroundColor(trans);
|
||||
magiskStatusIcon.setImageResource(0);
|
||||
magiskUpdateText.setText(R.string.checking_for_updates);
|
||||
magiskCheckUpdatesProgress.setVisibility(View.VISIBLE);
|
||||
magiskUpdateText.setTextColor(defaultColor);
|
||||
|
||||
safetyNetProgress.setVisibility(View.GONE);
|
||||
safetyNetContainer.setBackgroundColor(colorNeutral);
|
||||
safetyNetIcon.setImageResource(R.drawable.ic_safetynet);
|
||||
safetyNetStatusText.setText(R.string.safetyNet_check_text);
|
||||
safetyNetStatusText.setTextColor(defaultColor);
|
||||
|
||||
getApplication().safetyNetDone.isTriggered = false;
|
||||
noDialog = false;
|
||||
|
||||
updateUI();
|
||||
new CheckUpdates(getActivity()).exec();
|
||||
});
|
||||
|
||||
if (getApplication().magiskVersion < 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) -> gotoInstall())
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
updateUI();
|
||||
|
||||
if (getApplication().updateCheckDone.isTriggered)
|
||||
updateCheckUI();
|
||||
if (getApplication().safetyNetDone.isTriggered)
|
||||
updateSafetyNetUI();
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Void> event) {
|
||||
if (event == getApplication().updateCheckDone) {
|
||||
Logger.dev("StatusFragment: Update Check UI refresh triggered");
|
||||
updateCheckUI();
|
||||
} else if (event == getApplication().safetyNetDone) {
|
||||
Logger.dev("StatusFragment: SafetyNet UI refresh triggered");
|
||||
updateSafetyNetUI();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
getApplication().updateCheckDone.register(this);
|
||||
getApplication().safetyNetDone.register(this);
|
||||
getActivity().setTitle(R.string.status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
getApplication().updateCheckDone.unRegister(this);
|
||||
getApplication().safetyNetDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
unbinder.unbind();
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
int image, color;
|
||||
|
||||
getApplication().updateMagiskInfo();
|
||||
|
||||
if (getApplication().magiskVersion < 0) {
|
||||
magiskVersionText.setText(R.string.magisk_version_error);
|
||||
} else if (getApplication().disabled) {
|
||||
magiskVersionText.setText(getString(R.string.magisk_version_core_only, getApplication().magiskVersionString));
|
||||
} else {
|
||||
magiskVersionText.setText(getString(R.string.magisk_version, getApplication().magiskVersionString));
|
||||
}
|
||||
|
||||
switch (Shell.rootStatus) {
|
||||
case 0:
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
rootStatusText.setText(R.string.not_rooted);
|
||||
rootInfoText.setText(R.string.root_info_warning);
|
||||
break;
|
||||
case 1:
|
||||
if (getApplication().suVersion != null) {
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
rootStatusText.setText(R.string.proper_root);
|
||||
rootInfoText.setText(getApplication().suVersion);
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
default:
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
rootStatusText.setText(R.string.root_error);
|
||||
rootInfoText.setText(R.string.root_info_warning);
|
||||
}
|
||||
rootStatusContainer.setBackgroundColor(color);
|
||||
rootStatusText.setTextColor(color);
|
||||
rootInfoText.setTextColor(color);
|
||||
rootStatusIcon.setImageResource(image);
|
||||
}
|
||||
|
||||
private void updateCheckUI() {
|
||||
int image, color;
|
||||
|
||||
if (getApplication().remoteMagiskVersion < 0) {
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
magiskUpdateText.setText(R.string.cannot_check_updates);
|
||||
} else if (getApplication().remoteMagiskVersion > getApplication().magiskVersion) {
|
||||
color = colorInfo;
|
||||
image = R.drawable.ic_update;
|
||||
magiskUpdateText.setText(getString(R.string.magisk_update_available, getApplication().remoteMagiskVersion));
|
||||
} else {
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
magiskUpdateText.setText(getString(R.string.up_to_date, getString(R.string.magisk)));
|
||||
}
|
||||
|
||||
if (getApplication().magiskVersion < 0) {
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
}
|
||||
|
||||
magiskStatusContainer.setBackgroundColor(color);
|
||||
magiskVersionText.setTextColor(color);
|
||||
magiskUpdateText.setTextColor(color);
|
||||
magiskStatusIcon.setImageResource(image);
|
||||
|
||||
magiskCheckUpdatesProgress.setVisibility(View.GONE);
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
private void updateSafetyNetUI() {
|
||||
int image, color;
|
||||
safetyNetProgress.setVisibility(View.GONE);
|
||||
switch (getApplication().SNCheckResult) {
|
||||
case -3:
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
safetyNetStatusText.setText(R.string.safetyNet_connection_suspended);
|
||||
break;
|
||||
case -2:
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
safetyNetStatusText.setText(R.string.safetyNet_connection_failed);
|
||||
break;
|
||||
case -1:
|
||||
color = colorNeutral;
|
||||
image = R.drawable.ic_help;
|
||||
safetyNetStatusText.setText(R.string.safetyNet_error);
|
||||
break;
|
||||
case 0:
|
||||
color = colorBad;
|
||||
image = R.drawable.ic_cancel;
|
||||
safetyNetStatusText.setText(R.string.safetyNet_fail);
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
color = colorOK;
|
||||
image = R.drawable.ic_check_circle;
|
||||
safetyNetStatusText.setText(R.string.safetyNet_pass);
|
||||
break;
|
||||
}
|
||||
safetyNetContainer.setBackgroundColor(color);
|
||||
safetyNetStatusText.setTextColor(color);
|
||||
safetyNetIcon.setImageResource(image);
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.SuLogAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
|
||||
import java.util.List;
|
||||
@@ -28,7 +27,7 @@ public class SuLogFragment extends Fragment {
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
|
||||
private Unbinder unbinder;
|
||||
private SuLogDatabaseHelper dbHelper;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -48,8 +47,7 @@ public class SuLogFragment extends Fragment {
|
||||
// Inflate the layout for this fragment
|
||||
View v = inflater.inflate(R.layout.fragment_su_log, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
|
||||
dbHelper = new SuLogDatabaseHelper(getActivity());
|
||||
magiskManager = getApplication();
|
||||
|
||||
updateList();
|
||||
|
||||
@@ -57,7 +55,7 @@ public class SuLogFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
List<SuLogEntry> logs = dbHelper.getLogList();
|
||||
List<SuLogEntry> logs = magiskManager.suDB.getLogList();
|
||||
|
||||
if (logs.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
@@ -76,7 +74,7 @@ public class SuLogFragment extends Fragment {
|
||||
updateList();
|
||||
return true;
|
||||
case R.id.menu_clear:
|
||||
dbHelper.clearLogs();
|
||||
magiskManager.suDB.clearLogs();
|
||||
updateList();
|
||||
return true;
|
||||
default:
|
||||
|
@@ -11,7 +11,6 @@ import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
|
||||
import java.util.List;
|
||||
@@ -33,15 +32,15 @@ public class SuperuserFragment extends Fragment {
|
||||
unbinder = ButterKnife.bind(this, view);
|
||||
|
||||
PackageManager pm = getActivity().getPackageManager();
|
||||
MagiskManager magiskManager = getApplication();
|
||||
|
||||
SuDatabaseHelper dbHelper = new SuDatabaseHelper(getActivity());
|
||||
List<Policy> policyList = dbHelper.getPolicyList(pm);
|
||||
List<Policy> policyList = magiskManager.suDB.getPolicyList(pm);
|
||||
|
||||
if (policyList.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, dbHelper, pm));
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, magiskManager.suDB, pm));
|
||||
emptyRv.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
@@ -12,7 +12,6 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.SerialTask;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.module.Module;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@@ -53,44 +52,31 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
||||
|
||||
holder.checkBox.setOnCheckedChangeListener(null);
|
||||
holder.checkBox.setChecked(module.isEnabled());
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> new SerialTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (isChecked) {
|
||||
module.removeDisableFile();
|
||||
} else {
|
||||
module.createDisableFile();
|
||||
}
|
||||
return null;
|
||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
int snack;
|
||||
if (isChecked) {
|
||||
module.removeDisableFile();
|
||||
snack = R.string.disable_file_removed;
|
||||
} else {
|
||||
module.createDisableFile();
|
||||
snack = R.string.disable_file_created;
|
||||
}
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
});
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
int snack = isChecked ? R.string.disable_file_removed : R.string.disable_file_created;
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
holder.delete.setOnClickListener(v -> {
|
||||
boolean removed = module.willBeRemoved();
|
||||
int snack;
|
||||
if (removed) {
|
||||
module.deleteRemoveFile();
|
||||
snack = R.string.remove_file_deleted;
|
||||
} else {
|
||||
module.createRemoveFile();
|
||||
snack = R.string.remove_file_created;
|
||||
}
|
||||
}.exec());
|
||||
|
||||
holder.delete.setOnClickListener(v -> new SerialTask<Void, Void, Void>() {
|
||||
private final boolean removed = module.willBeRemoved();
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (removed) {
|
||||
module.deleteRemoveFile();
|
||||
} else {
|
||||
module.createRemoveFile();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
int snack = removed ? R.string.remove_file_deleted : R.string.remove_file_created;
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
updateDeleteButton(holder, module);
|
||||
}
|
||||
}.exec());
|
||||
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
|
||||
updateDeleteButton(holder, module);
|
||||
});
|
||||
|
||||
if (module.isUpdated()) {
|
||||
holder.notice.setVisibility(View.VISIBLE);
|
||||
|
@@ -1,21 +1,18 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Switch;
|
||||
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.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
@@ -49,78 +46,72 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Policy policy = policyList.get(position);
|
||||
try {
|
||||
holder.setExpanded(expandList.contains(policy));
|
||||
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
holder.collapse();
|
||||
expandList.remove(policy);
|
||||
} else {
|
||||
holder.expand();
|
||||
expandList.add(policy);
|
||||
}
|
||||
});
|
||||
holder.setExpanded(expandList.contains(policy));
|
||||
|
||||
holder.appName.setText(policy.appName);
|
||||
holder.packageName.setText(policy.packageName);
|
||||
holder.appIcon.setImageDrawable(pm.getPackageInfo(policy.packageName, 0).applicationInfo.loadIcon(pm));
|
||||
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && policy.policy == Policy.DENY) ||
|
||||
(!isChecked && policy.policy == Policy.ALLOW)) {
|
||||
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.addPolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && !policy.notification) ||
|
||||
(!isChecked && policy.notification)) {
|
||||
policy.notification = isChecked;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_notif_on : R.string.su_snack_notif_off, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.addPolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.loggingSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && !policy.logging) ||
|
||||
(!isChecked && policy.logging)) {
|
||||
policy.logging = isChecked;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_log_on : R.string.su_snack_log_off, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.addPolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.delete.setOnClickListener(v -> new AlertDialogBuilder(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) -> {
|
||||
policyList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
notifyItemRangeChanged(position, policyList.size());
|
||||
SnackbarMaker.make(holder.itemView, v.getContext().getString(R.string.su_snack_revoke, policy.appName),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.deletePolicy(policy.uid);
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setCancelable(true)
|
||||
.show());
|
||||
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
||||
holder.notificationSwitch.setChecked(policy.notification);
|
||||
holder.loggingSwitch.setChecked(policy.logging);
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
holder.collapse();
|
||||
expandList.remove(policy);
|
||||
} else {
|
||||
holder.expand();
|
||||
expandList.add(policy);
|
||||
}
|
||||
});
|
||||
|
||||
// Hide for now
|
||||
holder.moreInfo.setVisibility(View.GONE);
|
||||
holder.appName.setText(policy.appName);
|
||||
holder.packageName.setText(policy.packageName);
|
||||
holder.appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||
holder.masterSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && policy.policy == Policy.DENY) ||
|
||||
(!isChecked && policy.policy == Policy.ALLOW)) {
|
||||
policy.policy = isChecked ? Policy.ALLOW : Policy.DENY;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_grant : R.string.su_snack_deny, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.updatePolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.notificationSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && !policy.notification) ||
|
||||
(!isChecked && policy.notification)) {
|
||||
policy.notification = isChecked;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_notif_on : R.string.su_snack_notif_off, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.updatePolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.loggingSwitch.setOnCheckedChangeListener((v, isChecked) -> {
|
||||
if ((isChecked && !policy.logging) ||
|
||||
(!isChecked && policy.logging)) {
|
||||
policy.logging = isChecked;
|
||||
String message = v.getContext().getString(
|
||||
isChecked ? R.string.su_snack_log_on : R.string.su_snack_log_off, policy.appName);
|
||||
SnackbarMaker.make(holder.itemView, message, Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.updatePolicy(policy);
|
||||
}
|
||||
});
|
||||
holder.delete.setOnClickListener(v -> new AlertDialogBuilder(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) -> {
|
||||
policyList.remove(position);
|
||||
notifyItemRemoved(position);
|
||||
notifyItemRangeChanged(position, policyList.size());
|
||||
SnackbarMaker.make(holder.itemView, v.getContext().getString(R.string.su_snack_revoke, policy.appName),
|
||||
Snackbar.LENGTH_SHORT).show();
|
||||
dbHelper.deletePolicy(policy);
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setCancelable(true)
|
||||
.show());
|
||||
holder.masterSwitch.setChecked(policy.policy == Policy.ALLOW);
|
||||
holder.notificationSwitch.setChecked(policy.notification);
|
||||
holder.loggingSwitch.setChecked(policy.logging);
|
||||
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
policyList.remove(position);
|
||||
dbHelper.deletePolicy(policy.uid);
|
||||
onBindViewHolder(holder, position);
|
||||
}
|
||||
// Hide for now
|
||||
holder.moreInfo.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,11 +119,10 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
return policyList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
static class ViewHolder extends ExpandableViewHolder {
|
||||
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.package_name) TextView packageName;
|
||||
@BindView(R.id.expand_layout) LinearLayout expandLayout;
|
||||
@BindView(R.id.app_icon) ImageView appIcon;
|
||||
@BindView(R.id.master_switch) Switch masterSwitch;
|
||||
@BindView(R.id.notification_switch) Switch notificationSwitch;
|
||||
@@ -141,83 +131,14 @@ public class PolicyAdapter extends RecyclerView.Adapter<PolicyAdapter.ViewHolder
|
||||
@BindView(R.id.delete) ImageView delete;
|
||||
@BindView(R.id.more_info) ImageView moreInfo;
|
||||
|
||||
private ValueAnimator mAnimator;
|
||||
private boolean mExpanded = false;
|
||||
private static int expandHeight = 0;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, 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);
|
||||
mAnimator = slideAnimator(0, expandHeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private 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);
|
||||
@Override
|
||||
public void setExpandLayout(View itemView) {
|
||||
expandLayout = itemView.findViewById(R.id.expand_layout);
|
||||
}
|
||||
|
||||
private void expand() {
|
||||
expandLayout.setVisibility(View.VISIBLE);
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -65,6 +66,7 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
|
||||
new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
Activity activity = (Activity) mContext;
|
||||
new ProcessRepoZip(activity, uri, true).exec();
|
||||
}
|
||||
},
|
||||
@@ -75,6 +77,7 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
|
||||
new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
Activity activity = (Activity) mContext;
|
||||
new ProcessRepoZip(activity, uri, false).exec();
|
||||
}
|
||||
},
|
||||
|
@@ -1,17 +1,13 @@
|
||||
package com.topjohnwu.magisk.adapters;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.RotateAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.thoughtbot.expandablerecyclerview.ExpandableRecyclerViewAdapter;
|
||||
@@ -19,6 +15,7 @@ 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.superuser.SuLogEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -90,7 +87,7 @@ public class SuLogAdapter {
|
||||
SuLogEntry logEntry = (SuLogEntry) group.getItems().get(childIndex);
|
||||
holder.setExpanded(expandList.contains(logEntry));
|
||||
holder.itemView.setOnClickListener(view -> {
|
||||
if (holder.mExpanded) {
|
||||
if (holder.getExpanded()) {
|
||||
holder.collapse();
|
||||
expandList.remove(logEntry);
|
||||
} else {
|
||||
@@ -150,92 +147,50 @@ public class SuLogAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrapper class
|
||||
static class LogViewHolder extends ChildViewHolder {
|
||||
|
||||
private InternalViewHolder expandableViewHolder;
|
||||
|
||||
@BindView(R.id.app_name) TextView appName;
|
||||
@BindView(R.id.action) TextView action;
|
||||
@BindView(R.id.time) TextView time;
|
||||
@BindView(R.id.fromPid) TextView fromPid;
|
||||
@BindView(R.id.toUid) TextView toUid;
|
||||
@BindView(R.id.command) TextView command;
|
||||
@BindView(R.id.expand_layout) LinearLayout expandLayout;
|
||||
|
||||
private ValueAnimator mAnimator;
|
||||
private boolean mExpanded = false;
|
||||
private static int expandHeight = 0;
|
||||
|
||||
public LogViewHolder(View itemView) {
|
||||
LogViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
expandLayout.getViewTreeObserver().addOnPreDrawListener(
|
||||
new ViewTreeObserver.OnPreDrawListener() {
|
||||
expandableViewHolder = new InternalViewHolder(itemView);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
private class InternalViewHolder extends ExpandableViewHolder {
|
||||
|
||||
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
expandLayout.setVisibility(View.GONE);
|
||||
mAnimator = slideAnimator(0, expandHeight);
|
||||
return true;
|
||||
}
|
||||
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) {
|
||||
mExpanded = expanded;
|
||||
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
|
||||
layoutParams.height = expanded ? expandHeight : 0;
|
||||
expandLayout.setLayoutParams(layoutParams);
|
||||
expandLayout.setVisibility(expanded ? View.VISIBLE : View.GONE);
|
||||
expandableViewHolder.setExpanded(expanded);
|
||||
}
|
||||
|
||||
private void expand() {
|
||||
expandLayout.setVisibility(View.VISIBLE);
|
||||
mAnimator.start();
|
||||
mExpanded = true;
|
||||
expandableViewHolder.expand();
|
||||
}
|
||||
|
||||
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;
|
||||
expandableViewHolder.collapse();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,15 +1,8 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.SplashActivity;
|
||||
import com.topjohnwu.magisk.BuildConfig;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.WebService;
|
||||
|
||||
@@ -18,8 +11,7 @@ import org.json.JSONObject;
|
||||
|
||||
public class CheckUpdates extends ParallelTask<Void, Void, Void> {
|
||||
|
||||
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json";
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
private static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/magisk_update.json";
|
||||
|
||||
private boolean showNotification = false;
|
||||
|
||||
@@ -38,35 +30,28 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
|
||||
try {
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
JSONObject magisk = json.getJSONObject("magisk");
|
||||
magiskManager.remoteMagiskVersion = magisk.getDouble("versionCode");
|
||||
magiskManager.remoteMagiskVersionString = magisk.getString("version");
|
||||
magiskManager.remoteMagiskVersionCode = magisk.getInt("versionCode");
|
||||
magiskManager.magiskLink = magisk.getString("link");
|
||||
magiskManager.releaseNoteLink = magisk.getString("note");
|
||||
} catch (JSONException ignored) {
|
||||
}
|
||||
JSONObject manager = json.getJSONObject("app");
|
||||
magiskManager.remoteManagerVersionString = manager.getString("version");
|
||||
magiskManager.remoteManagerVersionCode = manager.getInt("versionCode");
|
||||
magiskManager.managerLink = manager.getString("link");
|
||||
} catch (JSONException ignored) {}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
if (magiskManager.magiskVersion < magiskManager.remoteMagiskVersion
|
||||
&& showNotification && magiskManager.updateNotification) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(magiskManager);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk)
|
||||
.setContentTitle(magiskManager.getString(R.string.magisk_update_title))
|
||||
.setContentText(magiskManager.getString(R.string.magisk_update_available, magiskManager.remoteMagiskVersion))
|
||||
.setVibrate(new long[]{0, 100, 100, 100})
|
||||
.setAutoCancel(true);
|
||||
Intent intent = new Intent(magiskManager, SplashActivity.class);
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, "install");
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager);
|
||||
stackBuilder.addParentStack(SplashActivity.class);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent pendingIntent = stackBuilder.getPendingIntent(NOTIFICATION_ID, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(NOTIFICATION_ID, builder.build());
|
||||
if (showNotification && magiskManager.updateNotification) {
|
||||
if (BuildConfig.VERSION_CODE < magiskManager.remoteManagerVersionCode) {
|
||||
Utils.showManagerUpdate(magiskManager);
|
||||
} else if (magiskManager.magiskVersionCode < magiskManager.remoteMagiskVersionCode) {
|
||||
Utils.showMagiskUpdate(magiskManager);
|
||||
}
|
||||
}
|
||||
magiskManager.updateCheckDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
public class FlashZip extends RootTask<Void, String, Integer> {
|
||||
|
||||
private Uri mUri;
|
||||
private File mCachedFile, mScriptFile, mCheckFile;
|
||||
@@ -68,7 +68,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean unzipAndCheck() throws Exception {
|
||||
private boolean unzipAndCheck() throws Exception {
|
||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
||||
List<String> ret;
|
||||
ret = Utils.readFile(mCheckFile.getPath());
|
||||
@@ -96,7 +96,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(Void... voids) {
|
||||
protected Integer doInRoot(Void... voids) {
|
||||
Logger.dev("FlashZip Running... " + mFilename);
|
||||
List<String> ret;
|
||||
try {
|
||||
@@ -124,7 +124,6 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
// -1 = error, manual install; 0 = invalid zip; 1 = success
|
||||
@Override
|
||||
protected void onPostExecute(Integer result) {
|
||||
super.onPostExecute(result);
|
||||
progress.dismiss();
|
||||
switch (result) {
|
||||
case -1:
|
||||
@@ -138,6 +137,7 @@ public class FlashZip extends SerialTask<Void, String, Integer> {
|
||||
onSuccess();
|
||||
break;
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
||||
protected void onSuccess() {
|
||||
|
@@ -5,15 +5,17 @@ import android.app.Activity;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class GetBootBlocks extends SerialTask<Void, Void, Void> {
|
||||
public class GetBootBlocks extends RootTask<Void, Void, Void> {
|
||||
|
||||
public GetBootBlocks(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
magiskManager.blockList = Shell.su("ls /dev/block | grep mmc");
|
||||
protected Void doInRoot(Void... params) {
|
||||
magiskManager.blockList = Shell.su(
|
||||
"find /dev/block -type b -maxdepth 1 | grep -v -E \"loop|ram|dm-0\""
|
||||
);
|
||||
if (magiskManager.bootBlock == null) {
|
||||
magiskManager.bootBlock = Utils.detectBootImage();
|
||||
}
|
||||
@@ -23,5 +25,6 @@ public class GetBootBlocks extends SerialTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.blockDetectionDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
@@ -9,14 +9,14 @@ import com.topjohnwu.magisk.utils.Logger;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
import com.topjohnwu.magisk.utils.ValueSortedMap;
|
||||
|
||||
public class LoadModules extends SerialTask<Void, Void, Void> {
|
||||
public class LoadModules extends RootTask<Void, Void, Void> {
|
||||
|
||||
public LoadModules(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
protected Void doInRoot(Void... voids) {
|
||||
Logger.dev("LoadModules: Loading modules");
|
||||
|
||||
magiskManager.moduleMap = new ValueSortedMap<>();
|
||||
@@ -37,5 +37,6 @@ public class LoadModules extends SerialTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.moduleLoadDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
@@ -184,5 +184,6 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
magiskManager.repoLoadDone.trigger();
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
}
|
||||
|
@@ -2,12 +2,11 @@ package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
public class MagiskHide extends RootTask<Object, Void, Void> {
|
||||
|
||||
private boolean isList = false;
|
||||
|
||||
@@ -18,9 +17,9 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Object... params) {
|
||||
protected Void doInRoot(Object... params) {
|
||||
String command = (String) params[0];
|
||||
List<String> ret = Shell.su(MagiskManager.MAGISK_HIDE_PATH + command);
|
||||
List<String> ret = Shell.su("magiskhide --" + command);
|
||||
if (isList) {
|
||||
magiskManager.magiskHideList = ret;
|
||||
}
|
||||
@@ -32,6 +31,7 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
if (isList) {
|
||||
magiskManager.magiskHideDone.trigger();
|
||||
}
|
||||
super.onPostExecute(v);
|
||||
}
|
||||
|
||||
public void add(CharSequence packageName) {
|
||||
@@ -43,17 +43,17 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
exec("enable; setprop persist.magisk.hide 1");
|
||||
exec("enable");
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
exec("disable; setprop persist.magisk.hide 0");
|
||||
exec("disable");
|
||||
}
|
||||
|
||||
public void list() {
|
||||
isList = true;
|
||||
if (magiskManager == null) return;
|
||||
exec("list");
|
||||
exec("ls");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,9 +7,12 @@ import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
|
||||
|
||||
protected Activity activity;
|
||||
protected MagiskManager magiskManager;
|
||||
|
||||
private Runnable callback = null;
|
||||
|
||||
public ParallelTask() {}
|
||||
|
||||
public ParallelTask(Activity context) {
|
||||
@@ -17,8 +20,18 @@ public abstract class ParallelTask<Params, Progress, Result> extends AsyncTask<P
|
||||
magiskManager = Utils.getMagiskManager(context);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void exec(Params... params) {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void exec(Params... params) {
|
||||
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Result result) {
|
||||
if (callback != null) callback.run();
|
||||
}
|
||||
|
||||
public ParallelTask<Params, Progress, Result> setCallBack(Runnable next) {
|
||||
callback = next;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@@ -4,14 +4,9 @@ import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
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.ZipUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
@@ -38,26 +33,12 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
if (Shell.rootAccess()) {
|
||||
try {
|
||||
// We might not have busybox yet, unzip with Java
|
||||
// We shall have complete busybox after Magisk installation
|
||||
File tempdir = new File(magiskManager.getCacheDir(), "magisk");
|
||||
ZipUtils.unzip(magiskManager.getContentResolver().openInputStream(mUri), tempdir);
|
||||
// Running in parallel mode, open new shell
|
||||
Shell.su(true,
|
||||
"rm -f /dev/.magisk",
|
||||
(mBoot != null) ? "echo \"BOOTIMAGE=/dev/block/" + mBoot + "\" >> /dev/.magisk" : "",
|
||||
synchronized (Shell.lock) {
|
||||
Shell.su("rm -f /dev/.magisk",
|
||||
(mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
|
||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk",
|
||||
"mkdir -p " + MagiskManager.TMP_FOLDER_PATH,
|
||||
"cp -af " + tempdir + "/. " + MagiskManager.TMP_FOLDER_PATH + "/magisk",
|
||||
"mv -f " + tempdir + "/META-INF " + magiskManager.getCacheDir() + "/META-INF",
|
||||
"rm -rf " + tempdir
|
||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logger.error("ProcessMagiskZip: Error!");
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -68,29 +49,10 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
protected void onPostExecute(Boolean result) {
|
||||
progressDialog.dismiss();
|
||||
if (result) {
|
||||
new FlashZip(activity, mUri) {
|
||||
@Override
|
||||
protected boolean unzipAndCheck() throws Exception {
|
||||
// Don't need to check, as it is downloaded in correct form
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
new SerialTask<Void, Void, Void>(activity) {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
Shell.su("setprop magisk.version "
|
||||
+ String.valueOf(magiskManager.remoteMagiskVersion));
|
||||
magiskManager.updateCheckDone.trigger();
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
super.onSuccess();
|
||||
}
|
||||
}.exec();
|
||||
new FlashZip(activity, mUri).exec();
|
||||
} else {
|
||||
Utils.showUriSnack(activity, mUri);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
}
|
||||
|
@@ -14,7 +14,6 @@ import com.topjohnwu.magisk.utils.ZipUtils;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
|
||||
@@ -38,51 +37,33 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
|
||||
FileInputStream in;
|
||||
FileOutputStream out;
|
||||
|
||||
try {
|
||||
|
||||
// Create temp file
|
||||
File temp1 = new File(magiskManager.getCacheDir(), "1.zip");
|
||||
File temp2 = new File(magiskManager.getCacheDir(), "2.zip");
|
||||
if (magiskManager.getCacheDir().mkdirs()) {
|
||||
temp1.createNewFile();
|
||||
temp2.createNewFile();
|
||||
}
|
||||
|
||||
out = new FileOutputStream(temp1);
|
||||
magiskManager.getCacheDir().mkdirs();
|
||||
temp1.createNewFile();
|
||||
temp2.createNewFile();
|
||||
|
||||
// First remove top folder in Github source zip, Uri -> temp1
|
||||
ZipUtils.removeTopFolder(activity.getContentResolver().openInputStream(mUri), out);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
out = new FileOutputStream(temp2);
|
||||
ZipUtils.removeTopFolder(activity.getContentResolver().openInputStream(mUri), temp1);
|
||||
|
||||
// Then sign the zip for the first time, temp1 -> temp2
|
||||
ZipUtils.signZip(activity, temp1, out, false);
|
||||
out.flush();
|
||||
out.close();
|
||||
ZipUtils.signZip(activity, temp1, temp2, false);
|
||||
|
||||
// Adjust the zip to prevent unzip issues, temp2 -> temp2
|
||||
ZipUtils.adjustZip(temp2);
|
||||
// Adjust the zip to prevent unzip issues, temp2 -> temp1
|
||||
ZipUtils.zipAdjust(temp2.getPath(), temp1.getPath());
|
||||
|
||||
out = new FileOutputStream(temp1);
|
||||
// Finally, sign the whole zip file again, temp1 -> temp2
|
||||
ZipUtils.signZip(activity, temp1, temp2, true);
|
||||
|
||||
// Finally, sign the whole zip file again, temp2 -> temp1
|
||||
ZipUtils.signZip(activity, temp2, out, true);
|
||||
out.flush();
|
||||
out.close();
|
||||
|
||||
in = new FileInputStream(temp1);
|
||||
|
||||
// Write it back to the downloaded zip, temp1 -> Uri
|
||||
// Write it back to the downloaded zip, temp2 -> Uri
|
||||
FileInputStream in = new FileInputStream(temp2);
|
||||
try (OutputStream target = activity.getContentResolver().openOutputStream(mUri)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int length;
|
||||
if (target == null) throw new FileNotFoundException();
|
||||
if (target == null) throw new FileNotFoundException();
|
||||
while ((length = in.read(buffer)) > 0)
|
||||
target.write(buffer, 0, length);
|
||||
}
|
||||
|
33
app/src/main/java/com/topjohnwu/magisk/asyncs/RootTask.java
Normal file
33
app/src/main/java/com/topjohnwu/magisk/asyncs/RootTask.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
|
||||
public abstract class RootTask <Params, Progress, Result> extends ParallelTask<Params, Progress, Result> {
|
||||
|
||||
public RootTask() {}
|
||||
|
||||
public RootTask(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@Override
|
||||
final protected Result doInBackground(Params... params) {
|
||||
synchronized (Shell.lock) {
|
||||
return doInRoot(params);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
abstract protected Result doInRoot(Params... params);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void exec(Params... params) {
|
||||
if (Shell.rootAccess()) {
|
||||
super.exec(params);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
package com.topjohnwu.magisk.asyncs;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
/**
|
||||
* This class is only used for running root commands
|
||||
**/
|
||||
|
||||
public abstract class SerialTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
|
||||
protected Activity activity;
|
||||
protected MagiskManager magiskManager;
|
||||
|
||||
public SerialTask() {}
|
||||
|
||||
public SerialTask(Activity context) {
|
||||
activity = context;
|
||||
magiskManager = Utils.getMagiskManager(context);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void exec(Params... params) {
|
||||
if (!Shell.rootAccess()) return;
|
||||
executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
|
||||
}
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
package com.topjohnwu.magisk.components;
|
||||
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
|
||||
public class Activity extends AppCompatActivity {
|
||||
|
||||
@@ -10,4 +12,19 @@ public class Activity extends AppCompatActivity {
|
||||
public MagiskManager getApplicationContext() {
|
||||
return (MagiskManager) super.getApplicationContext();
|
||||
}
|
||||
|
||||
protected void setFloating() {
|
||||
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
|
||||
if (isTablet) {
|
||||
WindowManager.LayoutParams params = getWindow().getAttributes();
|
||||
params.height = getResources().getDimensionPixelSize(R.dimen.floating_height);
|
||||
params.width = getResources().getDimensionPixelSize(R.dimen.floating_width);
|
||||
params.alpha = 1.0f;
|
||||
params.dimAmount = 0.6f;
|
||||
params.flags |= 2;
|
||||
getWindow().setAttributes(params);
|
||||
setFinishOnTouchOutside(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,77 @@
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,23 +1,41 @@
|
||||
package com.topjohnwu.magisk.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final int DATABASE_VER = 1;
|
||||
private static final String TABLE_NAME = "policies";
|
||||
public static final String ROOT_ACCESS = "root_access";
|
||||
public static final String MULTIUSER_MODE = "multiuser_mode";
|
||||
public static final String MNT_NS = "mnt_ns";
|
||||
|
||||
private static final int DATABASE_VER = 2;
|
||||
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 PackageManager pm;
|
||||
|
||||
public SuDatabaseHelper(Context context) {
|
||||
super(context, "su.db", null, DATABASE_VER);
|
||||
magiskManager = Utils.getMagiskManager(context);
|
||||
pm = context.getPackageManager();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -28,29 +46,107 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 0) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(uid INT, package_name TEXT, app_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
createTables(db);
|
||||
oldVersion = 2;
|
||||
}
|
||||
if (oldVersion == 1) {
|
||||
// We're dropping column app_name, rename and re-construct table
|
||||
db.execSQL("ALTER TABLE " + POLICY_TABLE + " RENAME TO " + POLICY_TABLE + "_old");
|
||||
|
||||
// Create the new tables
|
||||
createTables(db);
|
||||
|
||||
// Migrate old data to new tables
|
||||
db.execSQL(
|
||||
"INSERT INTO " + POLICY_TABLE + " SELECT " +
|
||||
"uid, package_name, policy, until, logging, notification " +
|
||||
"FROM " + POLICY_TABLE + "_old");
|
||||
db.execSQL("DROP TABLE " + POLICY_TABLE + "_old");
|
||||
|
||||
File oldDB = magiskManager.getDatabasePath("sulog.db");
|
||||
if (oldDB.exists()) {
|
||||
migrateLegacyLogList(oldDB, db);
|
||||
magiskManager.deleteDatabase("sulog.db");
|
||||
}
|
||||
++oldVersion;
|
||||
}
|
||||
// Currently new database, no upgrading
|
||||
}
|
||||
|
||||
public boolean deletePolicy(int uid) {
|
||||
private void createTables(SQLiteDatabase db) {
|
||||
// Policies
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + POLICY_TABLE + " " +
|
||||
"(uid INT, package_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
|
||||
// Logs
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + LOG_TABLE + " " +
|
||||
"(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
|
||||
// Settings
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + SETTINGS_TABLE + " " +
|
||||
"(key TEXT, value INT, PRIMARY KEY(key))");
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(TABLE_NAME, "uid=?", new String[] { String.valueOf(uid) });
|
||||
// Clear outdated policies
|
||||
db.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) });
|
||||
}
|
||||
|
||||
public void deletePolicy(Policy policy) {
|
||||
deletePolicy(policy.packageName);
|
||||
}
|
||||
|
||||
public void deletePolicy(String pkg) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(POLICY_TABLE, "package_name=?", new String[] { pkg });
|
||||
db.close();
|
||||
return getPolicy(uid) == null;
|
||||
}
|
||||
|
||||
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)});
|
||||
}
|
||||
|
||||
public Policy getPolicy(int uid) {
|
||||
Policy policy = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
try (Cursor c = db.query(TABLE_NAME, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
|
||||
try (Cursor c = db.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
|
||||
if (c.moveToNext()) {
|
||||
policy = new Policy(c);
|
||||
policy = new Policy(c, pm);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
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)) {
|
||||
if (c.moveToNext()) {
|
||||
policy = new Policy(c, pm);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
deletePolicy(pkg);
|
||||
return null;
|
||||
}
|
||||
db.close();
|
||||
return policy;
|
||||
@@ -58,28 +154,110 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
public void addPolicy(Policy policy) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.replace(TABLE_NAME, null, policy.getContentValues());
|
||||
db.replace(POLICY_TABLE, null, policy.getContentValues());
|
||||
db.close();
|
||||
}
|
||||
|
||||
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=?",
|
||||
new String[] { policy.packageName });
|
||||
}
|
||||
|
||||
public List<Policy> getPolicyList(PackageManager pm) {
|
||||
List<Policy> ret = new ArrayList<>();
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
Policy policy;
|
||||
// Clear outdated policies
|
||||
db.delete(TABLE_NAME, "until > 0 and until < ?", new String[] { String.valueOf(System.currentTimeMillis()) });
|
||||
try (Cursor c = db.query(TABLE_NAME, null, null, null, null, null, "app_name ASC")) {
|
||||
try (Cursor c = db.query(POLICY_TABLE, null, null, null, null, null, null)) {
|
||||
while (c.moveToNext()) {
|
||||
policy = new Policy(c);
|
||||
// Package is uninstalled
|
||||
if (pm.getPackagesForUid(policy.uid) == null) {
|
||||
deletePolicy(policy.uid);
|
||||
} else {
|
||||
try {
|
||||
policy = new Policy(c, pm);
|
||||
// The application changed UID for some reason, check user config
|
||||
if (policy.info.uid != policy.uid) {
|
||||
if (magiskManager.suReauth) {
|
||||
// Reauth required, remove from DB
|
||||
deletePolicy(db, policy.uid);
|
||||
continue;
|
||||
} else {
|
||||
// No reauth, update to use the new UID
|
||||
policy.uid = policy.info.uid;
|
||||
updatePolicy(db, policy);
|
||||
}
|
||||
}
|
||||
ret.add(policy);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// The app no longer exist, remove from DB
|
||||
deletePolicy(db, c.getInt(c.getColumnIndex("uid")));
|
||||
}
|
||||
}
|
||||
}
|
||||
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")) {
|
||||
while (c.moveToNext()) {
|
||||
ret.add(new SuLogEntry(c));
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void clearLogs() {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(LOG_TABLE, null, null);
|
||||
db.close();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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()) {
|
||||
value = c.getInt(c.getColumnIndex("value"));
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
@@ -1,76 +0,0 @@
|
||||
package com.topjohnwu.magisk.database;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.superuser.SuLogEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SuLogDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final int DATABASE_VER = 1;
|
||||
private static final String TABLE_NAME = "logs";
|
||||
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
public SuLogDatabaseHelper(Context context) {
|
||||
super(context, "sulog.db", null, DATABASE_VER);
|
||||
magiskManager = (MagiskManager) context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
onUpgrade(db, 0, DATABASE_VER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 0) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
}
|
||||
// Currently new database, no upgrading
|
||||
}
|
||||
|
||||
public void addLog(SuLogEntry log) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.insert(TABLE_NAME, null, log.getContentValues());
|
||||
db.close();
|
||||
}
|
||||
|
||||
public void clearLogs() {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
db.delete(TABLE_NAME, null, null);
|
||||
db.close();
|
||||
}
|
||||
|
||||
public List<SuLogEntry> getLogList() {
|
||||
return getLogList(null);
|
||||
}
|
||||
|
||||
public List<SuLogEntry> getLogList(int uid) {
|
||||
return getLogList("uid=" + uid);
|
||||
}
|
||||
|
||||
public List<SuLogEntry> getLogList(String selection) {
|
||||
List<SuLogEntry> ret = new ArrayList<>();
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
// Clear outdated logs
|
||||
db.delete(TABLE_NAME, "time < ?", new String[] { String.valueOf(
|
||||
System.currentTimeMillis() / 1000 - magiskManager.suLogTimeout * 86400) });
|
||||
try (Cursor c = db.query(TABLE_NAME, null, selection, null, null, null, "time DESC")) {
|
||||
while (c.moveToNext()) {
|
||||
ret.add(new SuLogEntry(c));
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
return ret;
|
||||
}
|
||||
}
|
@@ -33,11 +33,13 @@ public class Module extends BaseModule {
|
||||
}
|
||||
|
||||
public void createDisableFile() {
|
||||
mEnable = !Utils.createFile(mDisableFile);
|
||||
mEnable = false;
|
||||
Utils.createFile(mDisableFile);
|
||||
}
|
||||
|
||||
public void removeDisableFile() {
|
||||
mEnable = Utils.removeItem(mDisableFile);
|
||||
mEnable = true;
|
||||
Utils.removeItem(mDisableFile);
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
@@ -45,11 +47,13 @@ public class Module extends BaseModule {
|
||||
}
|
||||
|
||||
public void createRemoveFile() {
|
||||
mRemove = Utils.createFile(mRemoveFile);
|
||||
mRemove = true;
|
||||
Utils.createFile(mRemoveFile);
|
||||
}
|
||||
|
||||
public void deleteRemoveFile() {
|
||||
mRemove = !Utils.removeItem(mRemoveFile);
|
||||
mRemove = false;
|
||||
Utils.removeItem(mRemoveFile);
|
||||
}
|
||||
|
||||
public boolean willBeRemoved() {
|
||||
|
@@ -3,14 +3,28 @@ package com.topjohnwu.magisk.receivers;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
|
||||
import com.topjohnwu.magisk.services.BootupIntentService;
|
||||
import com.topjohnwu.magisk.services.OnBootIntentService;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class BootReceiver extends BroadcastReceiver {
|
||||
|
||||
private void startIntentService(Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
context.startForegroundService(new Intent(context, OnBootIntentService.class));
|
||||
} else {
|
||||
context.startService(new Intent(context, OnBootIntentService.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
context.startService(new Intent(context, BootupIntentService.class));
|
||||
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
|
||||
Utils.getMagiskManager(context).initSU();
|
||||
// There is currently no need to start an IntentService onBoot
|
||||
// startIntentService(context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
@@ -13,7 +12,7 @@ import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public abstract class DownloadReceiver extends BroadcastReceiver {
|
||||
public Activity activity;
|
||||
public Context mContext;
|
||||
public String mFilename;
|
||||
long downloadID;
|
||||
|
||||
@@ -21,7 +20,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
activity = (Activity) context;
|
||||
mContext = context;
|
||||
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||
String action = intent.getAction();
|
||||
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
|
||||
|
@@ -0,0 +1,41 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.v4.content.FileProvider;
|
||||
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ManagerUpdate extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Utils.dlAndReceive(
|
||||
context,
|
||||
new DownloadReceiver() {
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
||||
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
Uri content = FileProvider.getUriForFile(mContext,
|
||||
"com.topjohnwu.magisk.provider", new File(uri.getPath()));
|
||||
install.setData(content);
|
||||
mContext.startActivity(install);
|
||||
} else {
|
||||
Intent install = new Intent(Intent.ACTION_VIEW);
|
||||
install.setDataAndType(uri, "application/vnd.android.package-archive");
|
||||
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(install);
|
||||
}
|
||||
}
|
||||
},
|
||||
intent.getStringExtra("link"),
|
||||
Utils.getLegalFilename("MagiskManager-v" +
|
||||
intent.getStringExtra("version") + ".apk"));
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package com.topjohnwu.magisk.receivers;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.superuser.Policy;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
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);
|
||||
if (policy == null)
|
||||
return;
|
||||
|
||||
switch (intent.getAction()) {
|
||||
case Intent.ACTION_PACKAGE_REPLACED:
|
||||
// This will only work pre-O
|
||||
if (magiskManager.suReauth) {
|
||||
magiskManager.suDB.deletePolicy(policy);
|
||||
} else {
|
||||
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
|
||||
// Update the UID if available
|
||||
if (uid > 0) {
|
||||
policy.uid = uid % 100000;
|
||||
}
|
||||
magiskManager.suDB.updatePolicy(policy);
|
||||
}
|
||||
break;
|
||||
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
|
||||
magiskManager.suDB.deletePolicy(policy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
package com.topjohnwu.magisk.services;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
import com.topjohnwu.magisk.utils.Utils;
|
||||
|
||||
public class BootupIntentService extends IntentService {
|
||||
|
||||
public BootupIntentService() {
|
||||
super("BootupIntentService");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
MagiskManager magiskManager = Utils.getMagiskManager(this);
|
||||
magiskManager.initSuAccess();
|
||||
magiskManager.updateMagiskInfo();
|
||||
if (magiskManager.prefs.getBoolean("magiskhide", false) &&
|
||||
!magiskManager.disabled && !magiskManager.magiskHideStarted && magiskManager.magiskVersion > 11) {
|
||||
magiskManager.toast(R.string.start_magiskhide, Toast.LENGTH_LONG);
|
||||
Shell.su(true, MagiskManager.MAGISK_HIDE_PATH + "enable",
|
||||
"setprop persist.magisk.hide 1");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.topjohnwu.magisk.services;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
|
||||
public class OnBootIntentService extends IntentService {
|
||||
|
||||
private static final int ONBOOT_NOTIFICATION_ID = 3;
|
||||
|
||||
public OnBootIntentService() {
|
||||
super("OnBootIntentService");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
builder.setSmallIcon(R.drawable.ic_magisk)
|
||||
.setContentTitle("onBoot")
|
||||
.setContentText("Running onBoot operations...");
|
||||
startForeground(ONBOOT_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {
|
||||
// Currently nothing to do
|
||||
}
|
||||
}
|
@@ -1,51 +1,57 @@
|
||||
package com.topjohnwu.magisk.superuser;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
|
||||
public class Policy {
|
||||
public class Policy implements Comparable<Policy>{
|
||||
public static final int INTERACTIVE = 0;
|
||||
public static final int DENY = 1;
|
||||
public static final int ALLOW = 2;
|
||||
|
||||
public int uid, policy;
|
||||
public int uid, policy = INTERACTIVE;
|
||||
public long until;
|
||||
public boolean logging = true, notification = true;
|
||||
public String packageName, appName;
|
||||
public PackageInfo info;
|
||||
public ApplicationInfo info;
|
||||
|
||||
public Policy(int uid, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
String[] pkgs = pm.getPackagesForUid(uid);
|
||||
if (pkgs != null && pkgs.length > 0) {
|
||||
info = pm.getPackageInfo(pkgs[0], 0);
|
||||
this.uid = uid;
|
||||
packageName = pkgs[0];
|
||||
appName = info.applicationInfo.loadLabel(pm).toString();
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
appName = info.loadLabel(pm).toString();
|
||||
} else throw new PackageManager.NameNotFoundException();
|
||||
}
|
||||
|
||||
public Policy(Cursor c) {
|
||||
public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {
|
||||
uid = c.getInt(c.getColumnIndex("uid"));
|
||||
packageName = c.getString(c.getColumnIndex("package_name"));
|
||||
appName = c.getString(c.getColumnIndex("app_name"));
|
||||
policy = c.getInt(c.getColumnIndex("policy"));
|
||||
until = c.getLong(c.getColumnIndex("until"));
|
||||
logging = c.getInt(c.getColumnIndex("logging")) != 0;
|
||||
notification = c.getInt(c.getColumnIndex("notification")) != 0;
|
||||
info = pm.getApplicationInfo(packageName, 0);
|
||||
appName = info.loadLabel(pm).toString();
|
||||
}
|
||||
|
||||
public ContentValues getContentValues() {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put("uid", uid);
|
||||
values.put("package_name", packageName);
|
||||
values.put("app_name", appName);
|
||||
values.put("policy", policy);
|
||||
values.put("until", until);
|
||||
values.put("logging", logging ? 1 : 0);
|
||||
values.put("notification", notification ? 1 : 0);
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NonNull Policy policy) {
|
||||
return appName.toLowerCase().compareTo(policy.appName.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ public class RequestActivity extends Activity {
|
||||
return;
|
||||
}
|
||||
|
||||
getApplicationContext().initSuConfigs();
|
||||
getApplicationContext().initSUConfig();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setClass(this, SuRequestActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
@@ -3,13 +3,12 @@ package com.topjohnwu.magisk.superuser;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Process;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.database.SuLogDatabaseHelper;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@@ -17,18 +16,29 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
|
||||
private static final int NO_NOTIFICATION = 0;
|
||||
private 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;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
int fromUid, toUid, pid;
|
||||
int fromUid, toUid, pid, mode;
|
||||
String command, action;
|
||||
Policy policy;
|
||||
|
||||
MagiskManager magiskManager = (MagiskManager) context.getApplicationContext();
|
||||
magiskManager.initSUConfig();
|
||||
|
||||
if (intent == null) return;
|
||||
|
||||
mode = intent.getIntExtra("mode", -1);
|
||||
if (mode < 0) return;
|
||||
|
||||
if (mode == NOTIFY_USER_TO_OWNER) {
|
||||
magiskManager.toast(R.string.multiuser_hint_owner_request, Toast.LENGTH_LONG);
|
||||
return;
|
||||
}
|
||||
|
||||
fromUid = intent.getIntExtra("from.uid", -1);
|
||||
if (fromUid < 0) return;
|
||||
if (fromUid == Process.myUid()) return; // Don't show anything if it's Magisk Manager
|
||||
@@ -36,18 +46,16 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
action = intent.getStringExtra("action");
|
||||
if (action == null) return;
|
||||
|
||||
SuDatabaseHelper suDbHelper = new SuDatabaseHelper(context);
|
||||
policy = suDbHelper.getPolicy(fromUid);
|
||||
policy = magiskManager.suDB.getPolicy(fromUid);
|
||||
if (policy == null) {
|
||||
try {
|
||||
policy = new Policy(fromUid, context.getPackageManager());
|
||||
} catch (Throwable throwable) {
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
magiskManager.initSuConfigs();
|
||||
|
||||
SuLogEntry log = new SuLogEntry(policy);
|
||||
|
||||
String message;
|
||||
@@ -64,10 +72,11 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
if (policy.notification && magiskManager.suNotificationType == TOAST)
|
||||
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||
if (policy.notification && magiskManager.suNotificationType == TOAST) {
|
||||
magiskManager.toast(message, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
if (policy.logging) {
|
||||
if (mode == NOTIFY_NORMAL_LOG && policy.logging) {
|
||||
toUid = intent.getIntExtra("to.uid", -1);
|
||||
if (toUid < 0) return;
|
||||
pid = intent.getIntExtra("pid", -1);
|
||||
@@ -78,8 +87,7 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
log.fromPid = pid;
|
||||
log.command = command;
|
||||
log.date = new Date();
|
||||
SuLogDatabaseHelper logDbHelper = new SuLogDatabaseHelper(context);
|
||||
logDbHelper.addLog(log);
|
||||
magiskManager.suDB.addLog(log);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,8 +21,6 @@ import com.topjohnwu.magisk.MagiskManager;
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||
import com.topjohnwu.magisk.components.Activity;
|
||||
import com.topjohnwu.magisk.database.SuDatabaseHelper;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
@@ -30,13 +28,9 @@ import java.io.IOException;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class SuRequestActivity extends Activity implements CallbackEvent.Listener<Policy> {
|
||||
public class SuRequestActivity extends Activity {
|
||||
|
||||
private static final int[] timeoutList = {0, -1, 10, 20, 30, 60};
|
||||
private static final int SU_PROTOCOL_PARAM_MAX = 20;
|
||||
private static final int SU_PROTOCOL_NAME_MAX = 20;
|
||||
private static final int SU_PROTOCOL_VALUE_MAX = 256;
|
||||
|
||||
private static final int PROMPT = 0;
|
||||
private static final int AUTO_DENY = 1;
|
||||
private static final int AUTO_ALLOW = 2;
|
||||
@@ -54,11 +48,9 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
private PackageManager pm;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
private int uid;
|
||||
private boolean hasTimeout;
|
||||
private Policy policy;
|
||||
private CountDownTimer timer;
|
||||
private CallbackEvent.Listener<Policy> self;
|
||||
private CallbackEvent<Policy> event = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -70,15 +62,12 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
|
||||
Intent intent = getIntent();
|
||||
socketPath = intent.getStringExtra("socket");
|
||||
self = this;
|
||||
hasTimeout = intent.getBooleanExtra("timeout", true);
|
||||
|
||||
new FileObserver(socketPath) {
|
||||
@Override
|
||||
public void onEvent(int fileEvent, String path) {
|
||||
if (fileEvent == FileObserver.DELETE_SELF) {
|
||||
if (event != null) {
|
||||
event.trigger();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -87,8 +76,13 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
new SocketManager(this).exec();
|
||||
}
|
||||
|
||||
void showRequest() {
|
||||
private boolean cancelTimeout() {
|
||||
timer.cancel();
|
||||
deny_btn.setText(getString(R.string.deny));
|
||||
return false;
|
||||
}
|
||||
|
||||
private void showRequest() {
|
||||
switch (magiskManager.suResponseType) {
|
||||
case AUTO_DENY:
|
||||
handleAction(Policy.DENY, 0);
|
||||
@@ -100,10 +94,16 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
default:
|
||||
}
|
||||
|
||||
// If not interactive, response directly
|
||||
if (policy.policy != Policy.INTERACTIVE) {
|
||||
handleAction();
|
||||
return;
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_request);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
appIcon.setImageDrawable(policy.info.applicationInfo.loadIcon(pm));
|
||||
appIcon.setImageDrawable(policy.info.loadIcon(pm));
|
||||
appNameView.setText(policy.appName);
|
||||
packageNameView.setText(policy.packageName);
|
||||
|
||||
@@ -120,40 +120,49 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
@Override
|
||||
public void onFinish() {
|
||||
deny_btn.setText(getString(R.string.deny_with_str, "(0)"));
|
||||
event.trigger();
|
||||
handleAction(Policy.DENY);
|
||||
}
|
||||
};
|
||||
|
||||
grant_btn.setOnClickListener(v -> handleAction(Policy.ALLOW));
|
||||
deny_btn.setOnClickListener(v -> handleAction(Policy.DENY));
|
||||
suPopup.setOnClickListener((v) -> {
|
||||
grant_btn.setOnClickListener(v -> {
|
||||
handleAction(Policy.ALLOW);
|
||||
timer.cancel();
|
||||
deny_btn.setText(getString(R.string.deny));
|
||||
});
|
||||
timeout.setOnTouchListener((v, event) -> {
|
||||
deny_btn.setOnClickListener(v -> {
|
||||
handleAction(Policy.DENY);
|
||||
timer.cancel();
|
||||
deny_btn.setText(getString(R.string.deny));
|
||||
return false;
|
||||
});
|
||||
suPopup.setOnClickListener(v -> cancelTimeout());
|
||||
timeout.setOnTouchListener((v, event) -> cancelTimeout());
|
||||
|
||||
timer.start();
|
||||
if (hasTimeout) {
|
||||
timer.start();
|
||||
} else {
|
||||
cancelTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
event.trigger();
|
||||
if (policy != null) {
|
||||
handleAction(Policy.DENY);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrigger(CallbackEvent<Policy> event) {
|
||||
Policy policy = event.getResult();
|
||||
String response = "socket:DENY";
|
||||
if (policy != null &&policy.policy == Policy.ALLOW ) {
|
||||
void handleAction() {
|
||||
String response;
|
||||
if (policy.policy == Policy.ALLOW) {
|
||||
response = "socket:ALLOW";
|
||||
} else {
|
||||
response = "socket:DENY";
|
||||
}
|
||||
try {
|
||||
socket.getOutputStream().write((response).getBytes());
|
||||
} catch (Exception ignored) {}
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -163,16 +172,16 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
|
||||
void handleAction(int action, int time) {
|
||||
policy.policy = action;
|
||||
event.trigger(policy);
|
||||
if (time >= 0) {
|
||||
policy.until = time == 0 ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
||||
new SuDatabaseHelper(this).addPolicy(policy);
|
||||
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
|
||||
magiskManager.suDB.addPolicy(policy);
|
||||
}
|
||||
handleAction();
|
||||
}
|
||||
|
||||
private class SocketManager extends ParallelTask<Void, Void, Boolean> {
|
||||
|
||||
public SocketManager(Activity context) {
|
||||
SocketManager(Activity context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@@ -183,40 +192,33 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM));
|
||||
|
||||
DataInputStream is = new DataInputStream(socket.getInputStream());
|
||||
|
||||
ContentValues payload = new ContentValues();
|
||||
|
||||
for (int i = 0; i < SU_PROTOCOL_PARAM_MAX; i++) {
|
||||
|
||||
while (true) {
|
||||
int nameLen = is.readInt();
|
||||
if (nameLen > SU_PROTOCOL_NAME_MAX)
|
||||
throw new IllegalArgumentException("name length too long: " + nameLen);
|
||||
|
||||
byte[] nameBytes = new byte[nameLen];
|
||||
is.readFully(nameBytes);
|
||||
|
||||
String name = new String(nameBytes);
|
||||
|
||||
if (TextUtils.equals(name, "eof"))
|
||||
break;
|
||||
|
||||
int dataLen = is.readInt();
|
||||
if (dataLen > SU_PROTOCOL_VALUE_MAX)
|
||||
throw new IllegalArgumentException(name + " data length too long: " + dataLen);
|
||||
|
||||
byte[] dataBytes = new byte[dataLen];
|
||||
is.readFully(dataBytes);
|
||||
|
||||
String data = new String(dataBytes);
|
||||
|
||||
payload.put(name, data);
|
||||
}
|
||||
|
||||
if (payload.getAsInteger("uid") == null)
|
||||
if (payload.getAsInteger("uid") == null) {
|
||||
return false;
|
||||
uid = payload.getAsInteger("uid");
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
int uid = payload.getAsInteger("uid");
|
||||
policy = magiskManager.suDB.getPolicy(uid);
|
||||
if (policy == null) {
|
||||
policy = new Policy(uid, pm);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
@@ -225,35 +227,10 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (!result) {
|
||||
if (result) {
|
||||
showRequest();
|
||||
} else {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
boolean showRequest = false;
|
||||
event = magiskManager.uidSuRequest.get(uid);
|
||||
if (event == null) {
|
||||
showRequest = true;
|
||||
event = new CallbackEvent<Policy>() {
|
||||
@Override
|
||||
public void trigger(Policy result) {
|
||||
super.trigger(result);
|
||||
unRegister();
|
||||
magiskManager.uidSuRequest.remove(uid);
|
||||
}
|
||||
};
|
||||
magiskManager.uidSuRequest.put(uid, event);
|
||||
}
|
||||
event.register(self);
|
||||
try {
|
||||
if (showRequest) {
|
||||
policy = new Policy(uid, pm);
|
||||
showRequest();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
event.trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,37 +4,30 @@ import android.util.Log;
|
||||
|
||||
import com.topjohnwu.magisk.MagiskManager;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class Logger {
|
||||
|
||||
public static final String TAG = "Magisk";
|
||||
public static final String MAIN_TAG = "Magisk";
|
||||
public static final String DEBUG_TAG = "MagiskManager";
|
||||
|
||||
public static void debug(String msg) {
|
||||
Log.d(TAG, "DEBUG: " + msg);
|
||||
public static void debug(String fmt, Object... args) {
|
||||
Log.d(DEBUG_TAG, "DEBUG: " + String.format(Locale.US, fmt, args));
|
||||
}
|
||||
|
||||
public static void error(String msg) {
|
||||
Log.e(TAG, "MANAGERERROR: " + msg);
|
||||
public static void error(String fmt, Object... args) {
|
||||
Log.e(MAIN_TAG, "MANAGERERROR: " + String.format(Locale.US, fmt, args));
|
||||
}
|
||||
|
||||
public static void dev(String msg, Object... args) {
|
||||
public static void dev(String fmt, Object... args) {
|
||||
if (MagiskManager.devLogging) {
|
||||
if (args.length == 1 && args[0] instanceof Throwable) {
|
||||
Log.d(TAG, "MANAGER: " + msg, (Throwable) args[0]);
|
||||
} else {
|
||||
Log.d(TAG, "MANAGER: " + String.format(msg, args));
|
||||
}
|
||||
Log.d(DEBUG_TAG, String.format(Locale.US, fmt, args));
|
||||
}
|
||||
}
|
||||
|
||||
public static void dev(String msg) {
|
||||
if (MagiskManager.devLogging) {
|
||||
Log.d(TAG, "MANAGER: " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void shell(boolean root, String msg) {
|
||||
public static void shell(boolean root, String fmt, Object... args) {
|
||||
if (MagiskManager.shellLogging) {
|
||||
Log.d(TAG, root ? "MANAGERSU" : "MANAGERSH" + msg);
|
||||
Log.d(DEBUG_TAG, (root ? "MANAGERSU: " : "MANAGERSH: ") + String.format(Locale.US, fmt, args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,15 +1,16 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.api.GoogleApiClient;
|
||||
import com.google.android.gms.common.api.Status;
|
||||
import com.google.android.gms.safetynet.SafetyNet;
|
||||
import com.topjohnwu.magisk.R;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -19,40 +20,55 @@ import java.security.SecureRandom;
|
||||
public abstract class SafetyNetHelper
|
||||
implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
|
||||
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private static boolean isRunning = false;
|
||||
|
||||
public SafetyNetHelper(Context context) {
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(context)
|
||||
private GoogleApiClient mGoogleApiClient;
|
||||
private Result ret;
|
||||
protected FragmentActivity mActivity;
|
||||
|
||||
public SafetyNetHelper(FragmentActivity activity) {
|
||||
ret = new Result();
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
// Entry point to start test
|
||||
public void requestTest() {
|
||||
if (isRunning)
|
||||
return;
|
||||
// Connect Google Service
|
||||
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
|
||||
.enableAutoManage(mActivity, this)
|
||||
.addApi(SafetyNet.API)
|
||||
.addConnectionCallbacks(this)
|
||||
.addOnConnectionFailedListener(this)
|
||||
.build();
|
||||
mGoogleApiClient.connect();
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionFailed(@NonNull ConnectionResult result) {
|
||||
Logger.dev("SN: Google API fail");
|
||||
handleResults(-2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected(@Nullable Bundle bundle) {
|
||||
Logger.dev("SN: Google API Connected");
|
||||
safetyNetCheck();
|
||||
ret.errmsg = result.getErrorMessage();
|
||||
handleResults(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionSuspended(int i) {
|
||||
Logger.dev("SN: Google API Suspended");
|
||||
handleResults(-3);
|
||||
switch (i) {
|
||||
case CAUSE_NETWORK_LOST:
|
||||
ret.errmsg = mActivity.getString(R.string.safetyNet_network_loss);
|
||||
break;
|
||||
case CAUSE_SERVICE_DISCONNECTED:
|
||||
ret.errmsg = mActivity.getString(R.string.safetyNet_service_disconnected);
|
||||
break;
|
||||
}
|
||||
handleResults(ret);
|
||||
}
|
||||
|
||||
public void requestTest() {
|
||||
// Connect Google Service
|
||||
mGoogleApiClient.connect();
|
||||
}
|
||||
|
||||
private void safetyNetCheck() {
|
||||
@Override
|
||||
public void onConnected(@Nullable Bundle bundle) {
|
||||
Logger.dev("SN: Google API Connected");
|
||||
// Create nonce
|
||||
byte[] nonce = new byte[24];
|
||||
new SecureRandom().nextBytes(nonce);
|
||||
@@ -68,16 +84,31 @@ public abstract class SafetyNetHelper
|
||||
Logger.dev("SN: Response: " + json);
|
||||
try {
|
||||
JSONObject decoded = new JSONObject(json);
|
||||
handleResults(decoded.getBoolean("ctsProfileMatch") ? 1 : 0);
|
||||
} catch (JSONException ignored) {}
|
||||
ret.ctsProfile = decoded.getBoolean("ctsProfileMatch");
|
||||
ret.basicIntegrity = decoded.getBoolean("basicIntegrity");
|
||||
ret.failed = false;
|
||||
} catch (JSONException e) {
|
||||
ret.errmsg = mActivity.getString(R.string.safetyNet_res_invalid);
|
||||
}
|
||||
} else {
|
||||
Logger.dev("SN: No response");
|
||||
handleResults(-1);
|
||||
ret.errmsg = mActivity.getString(R.string.safetyNet_no_response);
|
||||
}
|
||||
// Disconnect
|
||||
mGoogleApiClient.stopAutoManage(mActivity);
|
||||
mGoogleApiClient.disconnect();
|
||||
isRunning = false;
|
||||
handleResults(ret);
|
||||
});
|
||||
}
|
||||
|
||||
public abstract void handleResults(int i);
|
||||
// Callback function to save the results
|
||||
public abstract void handleResults(Result result);
|
||||
|
||||
public static class Result {
|
||||
public boolean failed = true;
|
||||
public String errmsg;
|
||||
public boolean ctsProfile = false;
|
||||
public boolean basicIntegrity = false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package com.topjohnwu.magisk.utils;
|
||||
|
||||
import com.topjohnwu.magisk.asyncs.RootTask;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -14,6 +16,7 @@ public class Shell {
|
||||
|
||||
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
|
||||
public static int rootStatus;
|
||||
public static final Object lock = new Object();
|
||||
|
||||
private static boolean isInit = false;
|
||||
private static Process rootShell;
|
||||
@@ -40,7 +43,6 @@ public class Shell {
|
||||
|
||||
// Setup umask and PATH
|
||||
su("umask 022");
|
||||
su("PATH=`[ -e /dev/busybox ] && echo /dev/busybox || echo /data/busybox`:$PATH");
|
||||
|
||||
List<String> ret = su("echo -BOC-", "id");
|
||||
|
||||
@@ -138,9 +140,6 @@ public class Shell {
|
||||
// Run the new shell with busybox and proper umask
|
||||
STDIN.write(("umask 022\n").getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
STDIN.write(("PATH=`[ -e /dev/busybox ] && echo /dev/busybox || " +
|
||||
"echo /data/busybox`:$PATH\n").getBytes("UTF-8"));
|
||||
STDIN.flush();
|
||||
} catch (IOException err) {
|
||||
return null;
|
||||
}
|
||||
@@ -216,4 +215,15 @@ public class Shell {
|
||||
|
||||
return new ArrayList<>(res);
|
||||
}
|
||||
|
||||
public static void su_async(List<String> result, String... commands) {
|
||||
new RootTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInRoot(Void... params) {
|
||||
List<String> ret = Shell.su(commands);
|
||||
if (result != null) result.addAll(ret);
|
||||
return null;
|
||||
}
|
||||
}.exec();
|
||||
}
|
||||
}
|
||||
|
@@ -3,25 +3,35 @@ package com.topjohnwu.magisk.utils;
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.TaskStackBuilder;
|
||||
import android.support.v7.app.NotificationCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
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.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.util.List;
|
||||
@@ -30,29 +40,24 @@ public class Utils {
|
||||
|
||||
public static boolean isDownloading = false;
|
||||
|
||||
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
|
||||
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
||||
|
||||
public static boolean itemExist(String path) {
|
||||
String command = "if [ -e " + path + " ]; then echo true; else echo false; fi";
|
||||
List<String> ret = Shell.su(command);
|
||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||
}
|
||||
|
||||
public static boolean commandExists(String s) {
|
||||
String command = "if [ -z $(which " + s + ") ]; then echo false; else echo true; fi";
|
||||
List<String> ret = Shell.sh(command);
|
||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||
}
|
||||
|
||||
public static boolean createFile(String path) {
|
||||
public static void createFile(String path) {
|
||||
String folder = path.substring(0, path.lastIndexOf('/'));
|
||||
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi";
|
||||
List<String> ret = Shell.su(command);
|
||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||
Shell.su_async(null, command);
|
||||
}
|
||||
|
||||
public static boolean removeItem(String path) {
|
||||
public static void removeItem(String path) {
|
||||
String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi";
|
||||
List<String> ret = Shell.su(command);
|
||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||
Shell.su_async(null, command);
|
||||
}
|
||||
|
||||
public static List<String> getModList(String path) {
|
||||
@@ -75,14 +80,16 @@ public class Utils {
|
||||
if (isDownloading)
|
||||
return;
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
|
||||
|
||||
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) || (file.exists() && !file.delete())) {
|
||||
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs())
|
||||
|| (file.exists() && !file.delete())) {
|
||||
Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
@@ -98,7 +105,7 @@ public class Utils {
|
||||
receiver.setDownloadID(downloadManager.enqueue(request));
|
||||
}
|
||||
receiver.setFilename(filename);
|
||||
context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||
context.getApplicationContext().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||
}
|
||||
|
||||
public static String getLegalFilename(CharSequence filename) {
|
||||
@@ -110,10 +117,12 @@ public class Utils {
|
||||
public static String detectBootImage() {
|
||||
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`",
|
||||
"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##*/}\""
|
||||
"echo \"$BOOTIMAGE\""
|
||||
};
|
||||
List<String> ret = Shell.su(commands);
|
||||
if (isValidShellResponse(ret)) {
|
||||
@@ -144,12 +153,12 @@ public class Utils {
|
||||
return (MagiskManager) context.getApplicationContext();
|
||||
}
|
||||
|
||||
public static void checkSafetyNet(MagiskManager magiskManager) {
|
||||
new SafetyNetHelper(magiskManager) {
|
||||
public static void checkSafetyNet(FragmentActivity activity) {
|
||||
new SafetyNetHelper(activity) {
|
||||
@Override
|
||||
public void handleResults(int i) {
|
||||
magiskManager.SNCheckResult = i;
|
||||
magiskManager.safetyNetDone.trigger();
|
||||
public void handleResults(Result result) {
|
||||
getMagiskManager(mActivity).SNCheckResult = result;
|
||||
getMagiskManager(mActivity).safetyNetDone.trigger();
|
||||
}
|
||||
}.requestTest();
|
||||
}
|
||||
@@ -185,4 +194,58 @@ public class Utils {
|
||||
Snackbar.LENGTH_LONG)
|
||||
.setAction(R.string.ok, (v)->{}).show();
|
||||
}
|
||||
|
||||
public static boolean checkNetworkStatus(Context context) {
|
||||
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
|
||||
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);
|
||||
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)
|
||||
.setVibrate(new long[]{0, 100, 100, 100})
|
||||
.setAutoCancel(true);
|
||||
Intent intent = new Intent(magiskManager, SplashActivity.class);
|
||||
intent.putExtra(MagiskManager.INTENT_SECTION, "install");
|
||||
TaskStackBuilder stackBuilder = TaskStackBuilder.create(magiskManager);
|
||||
stackBuilder.addParentStack(SplashActivity.class);
|
||||
stackBuilder.addNextIntent(intent);
|
||||
PendingIntent pendingIntent = stackBuilder.getPendingIntent(MAGISK_UPDATE_NOTIFICATION_ID,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) magiskManager.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);
|
||||
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)
|
||||
.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,
|
||||
APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
builder.setContentIntent(pendingIntent);
|
||||
NotificationManager notificationManager =
|
||||
(NotificationManager) magiskManager.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager.notify(APK_UPDATE_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -3,58 +3,17 @@
|
||||
//
|
||||
|
||||
#include <jni.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "zipadjust.h"
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_com_topjohnwu_magisk_utils_ZipUtils_zipAdjust___3BI(JNIEnv *env, jclass type,
|
||||
jbyteArray jbytes, jint size) {
|
||||
fin = (*env)->GetPrimitiveArrayCritical(env, jbytes, NULL);
|
||||
insize = (size_t) size;
|
||||
|
||||
zipadjust(0);
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jbytes, fin, 0);
|
||||
|
||||
jbyteArray ret = (*env)->NewByteArray(env, outsize);
|
||||
(*env)->SetByteArrayRegion(env, ret, 0, outsize, (const jbyte*) fout);
|
||||
free(fout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_topjohnwu_magisk_utils_ZipUtils_zipAdjust__Ljava_lang_String_2(JNIEnv *env, jclass type, jstring name) {
|
||||
const char *filename = (*env)->GetStringUTFChars(env, name, NULL);
|
||||
int fd = open(filename, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return;
|
||||
Java_com_topjohnwu_magisk_utils_ZipUtils_zipAdjust(JNIEnv *env, jclass type, jstring filenameIn_,
|
||||
jstring filenameOut_) {
|
||||
const char *filenameIn = (*env)->GetStringUTFChars(env, filenameIn_, 0);
|
||||
const char *filenameOut = (*env)->GetStringUTFChars(env, filenameOut_, 0);
|
||||
|
||||
// Load the file to memory
|
||||
insize = lseek(fd, 0, SEEK_END);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
fin = malloc(insize);
|
||||
read(fd, fin, insize);
|
||||
// TODO
|
||||
zipadjust(filenameIn, filenameOut, 0);
|
||||
|
||||
zipadjust(0);
|
||||
|
||||
close(fd);
|
||||
|
||||
// Open file for output
|
||||
fd = open(filename, O_WRONLY | O_TRUNC);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, name, filename);
|
||||
|
||||
// Write back to file
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, fout, outsize);
|
||||
|
||||
close(fd);
|
||||
free(fin);
|
||||
free(fout);
|
||||
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, filenameIn_, filenameIn);
|
||||
(*env)->ReleaseStringUTFChars(env, filenameOut_, filenameOut);
|
||||
}
|
@@ -1,11 +1,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <zlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <unistd.h>
|
||||
#include "zipadjust.h"
|
||||
|
||||
size_t insize = 0, outsize = 0, alloc = 0;
|
||||
unsigned char *fin = NULL, *fout = NULL;
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
struct local_header_struct {
|
||||
@@ -83,41 +86,43 @@ static int xerror(char* message) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xseekread(off_t offset, void* buf, size_t bytes) {
|
||||
memcpy(buf, fin + offset, bytes);
|
||||
static int xseekread(int fd, off_t offset, void* buf, size_t bytes) {
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
|
||||
if (read(fd, buf, bytes) != bytes) return xerror("Read failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xseekwrite(off_t offset, const void* buf, size_t bytes) {
|
||||
if (offset + bytes > outsize) outsize = offset + bytes;
|
||||
if (outsize > alloc) {
|
||||
fout = realloc(fout, outsize);
|
||||
alloc = outsize;
|
||||
}
|
||||
memcpy(fout + offset, buf, bytes);
|
||||
static int xseekwrite(int fd, off_t offset, void* buf, size_t bytes) {
|
||||
if (lseek(fd, offset, SEEK_SET) == (off_t)-1) return xerror("Seek failed");
|
||||
if (write(fd, buf, bytes) != bytes) return xerror("Write failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xfilecopy(off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
unsigned int CHUNK = 256 * 1024;
|
||||
unsigned char* buf = malloc(CHUNK);
|
||||
static int xfilecopy(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
|
||||
int CHUNK = 256 * 1024;
|
||||
void* buf = malloc(CHUNK);
|
||||
if (buf == NULL) return xerror("malloc failed");
|
||||
size_t left = bytes;
|
||||
while (left > 0) {
|
||||
size_t wanted = (left < CHUNK) ? left : CHUNK;
|
||||
xseekread(offsetIn, buf, wanted);
|
||||
xseekwrite(offsetOut, buf, wanted);
|
||||
offsetIn += wanted;
|
||||
offsetOut += wanted;
|
||||
left -= wanted;
|
||||
size_t r = read(fdIn, buf, wanted);
|
||||
if (r <= 0) return xerror("Read failed");
|
||||
if (write(fdOut, buf, r) != r) return xerror("Write failed");
|
||||
left -= r;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int xdecompress(off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
unsigned int CHUNK = 256 * 1024;
|
||||
static int xdecompress(int fdIn, int fdOut, off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
if ((offsetIn != (off_t)-1) && (lseek(fdIn, offsetIn, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
if ((offsetOut != (off_t)-1) && (lseek(fdOut, offsetOut, SEEK_SET) == (off_t)-1)) return xerror("Seek failed");
|
||||
|
||||
int CHUNK = 256 * 1024;
|
||||
|
||||
int ret;
|
||||
unsigned have;
|
||||
@@ -134,12 +139,9 @@ static int xdecompress(off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
if (ret != Z_OK) return xerror("ret != Z_OK");
|
||||
|
||||
do {
|
||||
strm.avail_in = insize - offsetIn;
|
||||
strm.avail_in = read(fdIn, in, CHUNK);
|
||||
if (strm.avail_in == 0) break;
|
||||
strm.avail_in = (strm.avail_in > CHUNK) ? CHUNK : strm.avail_in;
|
||||
xseekread(offsetIn, in, strm.avail_in);
|
||||
strm.next_in = in;
|
||||
offsetIn += strm.avail_in;
|
||||
|
||||
do {
|
||||
strm.avail_out = CHUNK;
|
||||
@@ -157,8 +159,10 @@ static int xdecompress(off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
}
|
||||
|
||||
have = CHUNK - strm.avail_out;
|
||||
xseekwrite(offsetOut, out, have);
|
||||
offsetOut += have;
|
||||
if (write(fdOut, out, have) != have) {
|
||||
(void)inflateEnd(&strm);
|
||||
return xerror("Write failed");
|
||||
}
|
||||
} while (strm.avail_out == 0);
|
||||
} while (ret != Z_STREAM_END);
|
||||
(void)inflateEnd(&strm);
|
||||
@@ -166,118 +170,128 @@ static int xdecompress(off_t offsetIn, off_t offsetOut, size_t bytes) {
|
||||
return ret == Z_STREAM_END ? 1 : 0;
|
||||
}
|
||||
|
||||
int zipadjust(int decompress) {
|
||||
int zipadjust(const char* filenameIn, const char* filenameOut, int decompress) {
|
||||
int ok = 0;
|
||||
|
||||
char filename[1024];
|
||||
int fin = open(filenameIn, O_RDONLY | O_BINARY);
|
||||
if (fin > 0) {
|
||||
unsigned int size = lseek(fin, 0, SEEK_END);
|
||||
lseek(fin, 0, SEEK_SET);
|
||||
LOGD("%d bytes\n", size);
|
||||
|
||||
central_footer_t central_footer;
|
||||
uint32_t central_directory_in_position = 0;
|
||||
uint32_t central_directory_in_size = 0;
|
||||
uint32_t central_directory_out_size = 0;
|
||||
char filename[1024];
|
||||
|
||||
int i;
|
||||
for (i = insize - 4; i >= 0; i--) {
|
||||
uint32_t magic = 0;
|
||||
if (!xseekread(i, &magic, sizeof(uint32_t))) return 0;
|
||||
if (magic == MAGIC_CENTRAL_FOOTER) {
|
||||
LOGD("central footer @ %08X\n", i);
|
||||
if (!xseekread(i, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
central_footer_t central_footer;
|
||||
uint32_t central_directory_in_position = 0;
|
||||
uint32_t central_directory_in_size = 0;
|
||||
uint32_t central_directory_out_size = 0;
|
||||
|
||||
central_header_t central_header;
|
||||
if (!xseekread(central_footer.central_directory_offset, ¢ral_header, sizeof(central_header_t))) return 0;
|
||||
if ( central_header.signature == MAGIC_CENTRAL_HEADER ) {
|
||||
central_directory_in_position = central_footer.central_directory_offset;
|
||||
central_directory_in_size = insize - central_footer.central_directory_offset;
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
break;
|
||||
int i;
|
||||
for (i = size - 4; i >= 0; i--) {
|
||||
uint32_t magic = 0;
|
||||
if (!xseekread(fin, i, &magic, sizeof(uint32_t))) return 0;
|
||||
if (magic == MAGIC_CENTRAL_FOOTER) {
|
||||
LOGD("central footer @ %08X\n", i);
|
||||
if (!xseekread(fin, i, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
|
||||
central_header_t central_header;
|
||||
if (!xseekread(fin, central_footer.central_directory_offset, ¢ral_header, sizeof(central_header_t))) return 0;
|
||||
if ( central_header.signature == MAGIC_CENTRAL_HEADER ) {
|
||||
central_directory_in_position = central_footer.central_directory_offset;
|
||||
central_directory_in_size = size - central_footer.central_directory_offset;
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (central_directory_in_position == 0) return 0;
|
||||
|
||||
unsigned char* central_directory_in = (unsigned char*)malloc(central_directory_in_size);
|
||||
unsigned char* central_directory_out = (unsigned char*)malloc(central_directory_in_size);
|
||||
if (!xseekread(fin, central_directory_in_position, central_directory_in, central_directory_in_size)) return 0;
|
||||
memset(central_directory_out, 0, central_directory_in_size);
|
||||
|
||||
unlink(filenameOut);
|
||||
int fout = open(filenameOut, O_CREAT | O_WRONLY | O_BINARY, 0644);
|
||||
if (fout > 0) {
|
||||
|
||||
uintptr_t central_directory_in_index = 0;
|
||||
uintptr_t central_directory_out_index = 0;
|
||||
|
||||
central_header_t* central_header = NULL;
|
||||
|
||||
uint32_t out_index = 0;
|
||||
|
||||
while (1) {
|
||||
central_header = (central_header_t*)¢ral_directory_in[central_directory_in_index];
|
||||
if (central_header->signature != MAGIC_CENTRAL_HEADER) break;
|
||||
|
||||
filename[central_header->length_filename] = (char)0;
|
||||
memcpy(filename, ¢ral_directory_in[central_directory_in_index + sizeof(central_header_t)], central_header->length_filename);
|
||||
LOGD("%s (%d --> %d) [%08X] (%d)\n", filename, central_header->size_uncompressed, central_header->size_compressed, central_header->crc32, central_header->length_extra + central_header->length_comment);
|
||||
|
||||
local_header_t local_header;
|
||||
if (!xseekread(fin, central_header->offset, &local_header, sizeof(local_header_t))) return 0;
|
||||
|
||||
// save and update to next index before we clobber the data
|
||||
uint16_t compression_method_old = central_header->compression_method;
|
||||
uint32_t size_compressed_old = central_header->size_compressed;
|
||||
uint32_t offset_old = central_header->offset;
|
||||
uint32_t length_extra_old = central_header->length_extra;
|
||||
central_directory_in_index += sizeof(central_header_t) + central_header->length_filename + central_header->length_extra + central_header->length_comment;
|
||||
|
||||
// copying, rewriting, and correcting local and central headers so all the information matches, and no data descriptors are necessary
|
||||
central_header->offset = out_index;
|
||||
central_header->flags = central_header->flags & !8;
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
central_header->compression_method = 0;
|
||||
central_header->size_compressed = central_header->size_uncompressed;
|
||||
}
|
||||
central_header->length_extra = 0;
|
||||
central_header->length_comment = 0;
|
||||
local_header.compression_method = central_header->compression_method;
|
||||
local_header.flags = central_header->flags;
|
||||
local_header.crc32 = central_header->crc32;
|
||||
local_header.size_uncompressed = central_header->size_uncompressed;
|
||||
local_header.size_compressed = central_header->size_compressed;
|
||||
local_header.length_extra = 0;
|
||||
|
||||
if (!xseekwrite(fout, out_index, &local_header, sizeof(local_header_t))) return 0;
|
||||
out_index += sizeof(local_header_t);
|
||||
if (!xseekwrite(fout, out_index, &filename[0], central_header->length_filename)) return 0;
|
||||
out_index += central_header->length_filename;
|
||||
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
if (!xdecompress(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
} else {
|
||||
if (!xfilecopy(fin, fout, offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
}
|
||||
out_index += local_header.size_compressed;
|
||||
|
||||
memcpy(¢ral_directory_out[central_directory_out_index], central_header, sizeof(central_header_t) + central_header->length_filename);
|
||||
central_directory_out_index += sizeof(central_header_t) + central_header->length_filename;
|
||||
}
|
||||
|
||||
central_directory_out_size = central_directory_out_index;
|
||||
central_footer.central_directory_size = central_directory_out_size;
|
||||
central_footer.central_directory_offset = out_index;
|
||||
central_footer.length_comment = 0;
|
||||
if (!xseekwrite(fout, out_index, central_directory_out, central_directory_out_size)) return 0;
|
||||
out_index += central_directory_out_size;
|
||||
if (!xseekwrite(fout, out_index, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
LOGD("central footer @ %08X\n", out_index);
|
||||
|
||||
close(fout);
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
free(central_directory_in);
|
||||
free(central_directory_out);
|
||||
close(fin);
|
||||
}
|
||||
|
||||
if (central_directory_in_position == 0) return 0;
|
||||
|
||||
unsigned char* central_directory_in = (unsigned char*)malloc(central_directory_in_size);
|
||||
unsigned char* central_directory_out = (unsigned char*)malloc(central_directory_in_size);
|
||||
if (!xseekread(central_directory_in_position, central_directory_in, central_directory_in_size)) return 0;
|
||||
memset(central_directory_out, 0, central_directory_in_size);
|
||||
|
||||
|
||||
|
||||
fout = (unsigned char*) malloc(insize);
|
||||
alloc = insize;
|
||||
|
||||
uintptr_t central_directory_in_index = 0;
|
||||
uintptr_t central_directory_out_index = 0;
|
||||
|
||||
central_header_t* central_header = NULL;
|
||||
|
||||
uint32_t out_index = 0;
|
||||
|
||||
while (1) {
|
||||
central_header = (central_header_t*)¢ral_directory_in[central_directory_in_index];
|
||||
if (central_header->signature != MAGIC_CENTRAL_HEADER) break;
|
||||
|
||||
filename[central_header->length_filename] = (char)0;
|
||||
memcpy(filename, ¢ral_directory_in[central_directory_in_index + sizeof(central_header_t)], central_header->length_filename);
|
||||
LOGD("%s (%d --> %d) [%08X] (%d)\n", filename, central_header->size_uncompressed, central_header->size_compressed, central_header->crc32, central_header->length_extra + central_header->length_comment);
|
||||
|
||||
local_header_t local_header;
|
||||
if (!xseekread(central_header->offset, &local_header, sizeof(local_header_t))) return 0;
|
||||
|
||||
// save and update to next index before we clobber the data
|
||||
uint16_t compression_method_old = central_header->compression_method;
|
||||
uint32_t size_compressed_old = central_header->size_compressed;
|
||||
uint32_t offset_old = central_header->offset;
|
||||
uint32_t length_extra_old = central_header->length_extra;
|
||||
central_directory_in_index += sizeof(central_header_t) + central_header->length_filename + central_header->length_extra + central_header->length_comment;
|
||||
|
||||
// copying, rewriting, and correcting local and central headers so all the information matches, and no data descriptors are necessary
|
||||
central_header->offset = out_index;
|
||||
central_header->flags = central_header->flags & !8;
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
central_header->compression_method = 0;
|
||||
central_header->size_compressed = central_header->size_uncompressed;
|
||||
}
|
||||
central_header->length_extra = 0;
|
||||
central_header->length_comment = 0;
|
||||
local_header.compression_method = central_header->compression_method;
|
||||
local_header.flags = central_header->flags;
|
||||
local_header.crc32 = central_header->crc32;
|
||||
local_header.size_uncompressed = central_header->size_uncompressed;
|
||||
local_header.size_compressed = central_header->size_compressed;
|
||||
local_header.length_extra = 0;
|
||||
|
||||
if (!xseekwrite(out_index, &local_header, sizeof(local_header_t))) return 0;
|
||||
out_index += sizeof(local_header_t);
|
||||
if (!xseekwrite(out_index, &filename[0], central_header->length_filename)) return 0;
|
||||
out_index += central_header->length_filename;
|
||||
|
||||
if (decompress && (compression_method_old == 8)) {
|
||||
if (!xdecompress(offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
} else {
|
||||
if (!xfilecopy(offset_old + sizeof(local_header_t) + central_header->length_filename + length_extra_old, out_index, size_compressed_old)) return 0;
|
||||
}
|
||||
out_index += local_header.size_compressed;
|
||||
|
||||
memcpy(¢ral_directory_out[central_directory_out_index], central_header, sizeof(central_header_t) + central_header->length_filename);
|
||||
central_directory_out_index += sizeof(central_header_t) + central_header->length_filename;
|
||||
}
|
||||
|
||||
central_directory_out_size = central_directory_out_index;
|
||||
central_footer.central_directory_size = central_directory_out_size;
|
||||
central_footer.central_directory_offset = out_index;
|
||||
central_footer.length_comment = 0;
|
||||
if (!xseekwrite(out_index, central_directory_out, central_directory_out_size)) return 0;
|
||||
out_index += central_directory_out_size;
|
||||
if (!xseekwrite(out_index, ¢ral_footer, sizeof(central_footer_t))) return 0;
|
||||
|
||||
LOGD("central header @ %08X (%d)\n", central_footer.central_directory_offset, central_footer.central_directory_size);
|
||||
LOGD("central footer @ %08X\n", out_index);
|
||||
|
||||
ok = 1;
|
||||
|
||||
free(central_directory_in);
|
||||
free(central_directory_out);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
@@ -3,10 +3,7 @@
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
int zipadjust(int decompress);
|
||||
|
||||
extern size_t insize, outsize, alloc;
|
||||
extern unsigned char *fin, *fout;
|
||||
int zipadjust(const char* filenameIn, const char* filenameOut, int decompress);
|
||||
|
||||
#define LOG_TAG "zipadjust"
|
||||
|
||||
|
BIN
app/src/main/jniLibs/armeabi-v7a/libbusybox.so
Normal file
BIN
app/src/main/jniLibs/armeabi-v7a/libbusybox.so
Normal file
Binary file not shown.
BIN
app/src/main/jniLibs/x86/libbusybox.so
Normal file
BIN
app/src/main/jniLibs/x86/libbusybox.so
Normal file
Binary file not shown.
@@ -1,251 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/install_info_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="5dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/install_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_version_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:maxWidth="400dp"
|
||||
android:minWidth="400dp">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/bootimage_card"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="15dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="10dp"
|
||||
android:text="@string/boot_image_title"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginStart="15dp">
|
||||
|
||||
<Spinner
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/block_spinner"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:text="@string/detect_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detect_bootimage"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/install_option_card"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true"
|
||||
android:layout_width="match_parent">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginBottom="15dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="10dp"
|
||||
android:text="@string/advanced_settings_title"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<CheckBox
|
||||
android:text="@string/keep_force_encryption"
|
||||
android:id="@+id/keep_force_enc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginStart="25dp" />
|
||||
|
||||
<CheckBox
|
||||
android:text="@string/keep_dm_verity"
|
||||
android:id="@+id/keep_verity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginStart="25dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/install_button"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true"
|
||||
android:layout_width="match_parent"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:clickable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginStart="25dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@mipmap/ic_launcher"
|
||||
android:id="@+id/imageView"
|
||||
android:layout_weight="0"
|
||||
android:layout_marginEnd="20dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/install_text"
|
||||
android:ems="10"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:textStyle="bold"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="20sp"
|
||||
android:fontFamily="sans-serif" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0"
|
||||
android:layout_marginStart="20dp">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/uninstall_button"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true"
|
||||
android:layout_width="match_parent"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:clickable="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/uninstall"
|
||||
android:ems="10"
|
||||
android:gravity="center"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:textStyle="bold"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="20sp"
|
||||
android:fontFamily="sans-serif" />
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</ScrollView>
|
464
app/src/main/res/layout/fragment_magisk.xml
Normal file
464
app/src/main/res/layout/fragment_magisk.xml
Normal file
@@ -0,0 +1,464 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/magisk_update_card"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/magisk_update_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_toStartOf="@+id/magisk_update_status"
|
||||
android:src="@drawable/ic_refresh"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/magisk_update_progress"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_toStartOf="@+id/magisk_update_status" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/magisk_update_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:minWidth="225dp"
|
||||
android:padding="6dp"
|
||||
android:text="@string/checking_for_updates"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/magisk_status_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toStartOf="@+id/magisk_version" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/magisk_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:minWidth="225dp"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/root_status_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:layout_marginStart="15dp"
|
||||
android:layout_toStartOf="@+id/root_status" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/root_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:minWidth="225dp"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/safetyNet_card"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/safetyNet_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/safetyNet_refresh"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_toStartOf="@+id/safetyNet_status"
|
||||
android:src="@drawable/ic_refresh"
|
||||
android:tint="?attr/imageColorTint" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/safetyNet_check_progress"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_toStartOf="@+id/safetyNet_status"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/safetyNet_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:gravity="center"
|
||||
android:minWidth="175dp"
|
||||
android:padding="6dp"
|
||||
android:text="@string/safetyNet_check_text"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/expand_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingStart="10dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cts_status_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cts_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:minWidth="150dp"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/basic_status_icon"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="25dp"
|
||||
android:layout_margin="10dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/basic_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:minWidth="150dp"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/bootimage_card"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation" >
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="10dp"
|
||||
android:text="@string/boot_image_title"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:minHeight="35dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/block_spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/detect_bootimage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/detect_button"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/install_option_card"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="10dp"
|
||||
android:text="@string/advanced_settings_title"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/keep_force_enc"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:text="@string/keep_force_encryption" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/keep_verity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:text="@string/keep_dm_verity" />
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/install_button"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:layout_weight="0"
|
||||
app:srcCompat="@mipmap/ic_launcher" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/install_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:ems="10"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_weight="0">
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/uninstall_button"
|
||||
style="?attr/cardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
app:cardCornerRadius="@dimen/card_corner_radius"
|
||||
app:cardElevation="@dimen/card_elevation">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:ems="10"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center"
|
||||
android:text="@string/uninstall"
|
||||
android:textAllCaps="false"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
@@ -1,196 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="?attr/actionBarSize"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/magiskStatusView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="5dip"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/magisk_version"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/magisk_status_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:foregroundGravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/magisk_status_icon"
|
||||
android:layout_width="84dp"
|
||||
android:layout_height="84dp"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/magisk_check_updates_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/magisk_update_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/checking_for_updates" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/rootStatusView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="5dip"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/root_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/root_status_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:foregroundGravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/root_status_icon"
|
||||
android:layout_width="84dp"
|
||||
android:layout_height="84dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/root_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/safetyNetView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="5dip"
|
||||
android:layout_marginRight="5dip"
|
||||
android:layout_marginTop="6dp"
|
||||
style="?attr/cardStyle"
|
||||
app:cardUseCompatPadding="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/safetyNet_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:foregroundGravity="center"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/grey500">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/safetyNet_icon"
|
||||
android:layout_width="84dp"
|
||||
android:layout_height="84dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_safetynet"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/safetyNet_check_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/safetyNet_status"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:padding="6dp"
|
||||
android:textStyle="bold"
|
||||
android:text="@string/safetyNet_check_text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
@@ -6,15 +6,9 @@
|
||||
android:id="@+id/main_group">
|
||||
|
||||
<item
|
||||
android:id="@+id/status"
|
||||
android:icon="@drawable/ic_device_information"
|
||||
android:title="@string/status"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/install"
|
||||
android:id="@+id/magisk"
|
||||
android:icon="@drawable/ic_magisk"
|
||||
android:title="@string/install"
|
||||
android:visible="false"/>
|
||||
android:title="@string/magisk"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/superuser"
|
||||
|
@@ -6,18 +6,52 @@
|
||||
<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>
|
||||
|
||||
<!--Magisk Fragment-->
|
||||
<!--Status Fragment-->
|
||||
<string name="magisk_version">المثبت Magisk v%1$s</string>
|
||||
<string name="magisk_version_error">هل قمت بتثبيت Magisk؟</string>
|
||||
<string name="magisk_version_core_only">المثبت Magisk v%1$s (الوضع الأساسي فقط)</string>
|
||||
<string name="magisk_version_error">Magisk غير مثبت</string>
|
||||
|
||||
<string name="magisk_update_available">Magisk v%1$.1f تحديث!</string>
|
||||
<string name="cannot_check_updates">لا يمكن التحقق من التحديثات</string>
|
||||
<string name="up_to_date">أحدث إصدار من %1$s مثبت</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>
|
||||
|
||||
<!--Root Fragment-->
|
||||
<!--Install Fragment-->
|
||||
<string name="auto_detect">(تلقائي) %1$s</string>
|
||||
<string name="cannot_auto_detect">(لا يمكن الكشف التلقائي)</string>
|
||||
<string name="boot_image_title">موقع ملف الإقلاع</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>
|
||||
<string name="version_none">(بدون)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(لم يتم توفير أي معلومات)</string>
|
||||
@@ -27,7 +61,7 @@
|
||||
<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="author">انشئ بواسطة %1$s</string>
|
||||
<string name="fab_flash_zip">تثبيت الملف المضغوط للإضافة</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
@@ -58,61 +92,119 @@
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">أن هذه الميزة لا تعمل دون الحصول على إذن الكتابة على التخزين الخارجي.</string>
|
||||
<string name="no_thanks">لا شكراً</string>
|
||||
<string name="yes">نعم</string>
|
||||
<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="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="zip_install_progress_title">تثبيت</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>
|
||||
|
||||
<!--URL Templates-->
|
||||
<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>
|
||||
<string name="manual_boot_image">يرجى تحديد ملف الإقلاع يدوياً!</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_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_magiskhide_summary">إخفاء Magisk من مختلف حالات الإكتشاف</string>
|
||||
<string name="settings_busybox_title">تمكين BusyBox</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\'s المدمج في busybox إلى xbin</string>
|
||||
<string name="settings_hosts_title">تمكين المضيفين(الهوست) لـ systemless</string>
|
||||
<string name="settings_hosts_summary">Systemless يدعم تطبيقات حجب الإعلانات</string>
|
||||
|
||||
<string name="settings_development_category">التطوير</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">Superuser صلاحيات</string>
|
||||
<string name="auto_response">استجابة تلقائية</string>
|
||||
<string name="request_timeout">مهلة الطلب</string>
|
||||
<string name="superuser_notification">Superuser إشعارات</string>
|
||||
<string name="request_timeout_summary">%1$s ثانية</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">المالك فقط لديه صلاحيات الروت</string>
|
||||
<string name="owner_manage_summary">يمكن للمالك فقط إدارة صلاحيات الروت وتلقي مطالبات الطلب</string>
|
||||
<string name="user_indepenent_summary">كل مستخدم لديه قواعد روت منفصلة خاصة به</string>
|
||||
<string name="multiuser_hint_owner_request">تم إرسال طلب إلى مالك الجهاز. يرجى التبديل إلى المالك ومنح الإذن</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>
|
||||
|
||||
<string name="settings_reboot_toast">إعادة التشغيل لتطبيق الإعدادات</string>
|
||||
<string name="auto_detect">(تلقائي) %1$s</string>
|
||||
<string name="checking_for_updates">البحث عن تحديثات…</string>
|
||||
<string name="install">التثبيت</string>
|
||||
<string name="not_rooted">غير مروت</string>
|
||||
<string name="proper_root">مروت فعلاً</string>
|
||||
<string name="advanced_settings_title">إعدادات متقدمة</string>
|
||||
<string name="boot_image_title">موقع ملف الإقلاع</string>
|
||||
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
|
||||
<string name="copying_msg">نسخ الملف المضغوط إلى دليل مؤقت</string>
|
||||
<string name="detect_button">تحقق</string>
|
||||
<string name="downloading_toast">جاري التنزيل %1$s</string>
|
||||
<string name="install_magisk_title">تثبيت Magisk الإصدار: %1$s</string>
|
||||
<string name="keep_force_encryption">إبقاء التشفير القوى</string>
|
||||
<string name="keep_dm_verity">إبقاء dm-verity</string>
|
||||
<string name="root_error">مروت لكن لا يوجد إذن الروت، غير مسموح به؟</string>
|
||||
<string name="root_info_warning">وظائف محدودة إلى حد كبير</string>
|
||||
<string name="safetyNet_error">تعذر التحقق من SafetyNet، لا يوجد إنترنت؟</string>
|
||||
<string name="safetyNet_pass">SafetyNet تخطى</string>
|
||||
<string name="safetyNet_fail">فشل SafetyNet: عدم تطابق التشكيل الجانبي CTS</string>
|
||||
<string name="status">الحالة</string>
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser طلبات</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 يتم منح صلاحيات Superuser</string>
|
||||
<string name="su_deny_toast">%1$s يتم رفض صلاحيات Superuser</string>
|
||||
<string name="no_apps_found">لا توجد تطبيقات</string>
|
||||
<string name="su_snack_grant">Superuser الصلاحيات لـ %1$s تم منحها</string>
|
||||
<string name="su_snack_deny">Superuser الصلاحيات لـ %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>
|
||||
|
||||
</resources>
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">الهدف UID:\u0020</string>
|
||||
<string name="command">الأمر:\u0020</string>
|
||||
|
||||
</resources>
|
@@ -17,7 +17,7 @@
|
||||
<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$.1f je dostupný!</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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<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_error">Nelze zkontrolovat SafetyNet. Jste připojeni k Internetu?</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>
|
||||
|
@@ -8,19 +8,20 @@
|
||||
<string name="navigation_drawer_close">Navigationsmenü schließen</string>
|
||||
|
||||
<string name="modules">Module</string>
|
||||
<string name="downloads">Download</string>
|
||||
<string name="downloads">Downloads</string>
|
||||
<string name="superuser">Superuser</string>
|
||||
<string name="log">Log</string>
|
||||
<string name="settings">Einstellungen</string>
|
||||
<string name="status">Übersicht</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$.1f ist verfügbar!</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>
|
||||
@@ -28,11 +29,15 @@
|
||||
<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_error">SafetyNet-Status konnte nicht geprüft werden. Ist eine Internetverbindung verfügbar?</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-->
|
||||
@@ -125,7 +130,9 @@
|
||||
<string name="internal_storage">Die zip-Datei ist gespeichert unter:\n[Interner Speicher]%1$s</string>
|
||||
<string name="zip_process_title">Verarbeite</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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Allgemein</string>
|
||||
<string name="settings_dark_theme_title">Dunkles Theme</string>
|
||||
@@ -135,6 +142,8 @@
|
||||
<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_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>
|
||||
@@ -154,7 +163,26 @@
|
||||
<string name="request_timeout">Zeitlimit für Anfrage</string>
|
||||
<string name="superuser_notification">Superuser-Benachrichtigung</string>
|
||||
<string name="request_timeout_summary">%1$s Sekunden</string>
|
||||
<string name="settings_su_reauth_title">Nach Updates erneut authentifizieren</string>
|
||||
<string name="settings_su_reauth_summary">Superuser-Zugriff nach App-Updates erneut abfragen</string>
|
||||
|
||||
<string name="multiuser_mode">Mehrbenutzermodus</string>
|
||||
<string name="settings_owner_only">Nur der Gerätebesitzer</string>
|
||||
<string name="settings_owner_manage">Durch Gerätebesitzer verwaltet</string>
|
||||
<string name="settings_user_independent">User Independent</string>
|
||||
<string name="owner_only_summary">Nur der Besitzer hat root-Zugriff</string>
|
||||
<string name="owner_manage_summary">Nur der Besitzer verwaltet den root-Zugriff und erhält Zugriffs-Anfragen</string>
|
||||
<string name="user_indepenent_summary">Jeder Nutzer hat seine eingenen root-Regeln</string>
|
||||
<string name="multiuser_hint_owner_request">Eine Anfrage wurde an den Gerätebesitzer gesendet. Bitte wechsle zum Bersitzerkonto und gewähre die Rechte</string>
|
||||
|
||||
<string name="mount_namespace_mode">Namensraum-Modus</string>
|
||||
<string name="settings_ns_global">Globaler Namensraum</string>
|
||||
<string name="settings_ns_requester">Geerbter Namensraum</string>
|
||||
<string name="settings_ns_isolate">Isolierter Namensraum</string>
|
||||
<string name="global_summary">Alle root-Sitzungen benutzen den global angelegten Namensraum</string>
|
||||
<string name="requester_summary">Root-Sitzungen erben den Namensraum des Abfragenden</string>
|
||||
<string name="isolate_summary">Jede root-Sitzung hat ihren isolierten Namensraum</string>
|
||||
|
||||
<string name="settings_development_category">Entwickler</string>
|
||||
<string name="settings_developer_logging_title">Erweiterte Fehlerprotokolle</string>
|
||||
<string name="settings_developer_logging_summary">Für ausführliches Logging aktivieren</string>
|
||||
|
220
app/src/main/res/values-el/strings.xml
Normal file
220
app/src/main/res/values-el/strings.xml
Normal file
@@ -0,0 +1,220 @@
|
||||
<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="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_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="detect_button">Εύρεση</string>
|
||||
<string name="advanced_settings_title">Προηγμένες ρυθμίσεις</string>
|
||||
<string name="keep_force_encryption">Διατήρηση 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>
|
||||
<string name="version_none">(Καμία)</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="fab_flash_zip">Flash Module Zip</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
|
||||
<string name="installed">Εγκαταστάθηκε</string>
|
||||
<string name="not_installed">Μη εγκατεστημένη</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">Αποθήκευση σε SD</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">Αποτυχία αποθήκευσης αρχείου καταγραφής στην κάρτα SD:</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">JpegXguy</string>
|
||||
<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_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">Αυτό το 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>
|
||||
|
||||
<!--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">Εκκαθάριση Repo Cache</string>
|
||||
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για online repos, αναγκάζει την εφαρμογή να ανανεώσει online</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">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 για εφαρμογές Adblock</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">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">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
|
||||
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
|
||||
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
|
||||
|
||||
<string name="settings_development_category">Ανάπτυξη Εφαρμογής</string>
|
||||
<string name="settings_developer_logging_title">Ενεργοποίηση προηγμένης καταγραφής ελέγχου σφαλμάτων</string>
|
||||
<string name="settings_developer_logging_summary">Επιλέξτε αυτό για να ενεργοποιήσετε τη verbose καταγραφή</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">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>
|
@@ -17,7 +17,7 @@
|
||||
<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$.1f!</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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<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_error">No puede comprobar SafetyNet, ¿No tiene internet?</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>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
<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$.1f disponible !</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>
|
||||
@@ -25,7 +25,7 @@
|
||||
<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_error">Impossible de contrôler SafetyNet, pas d\'Internet?</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>
|
||||
@@ -123,7 +123,7 @@
|
||||
<string name="settings_clear_cache_title">Effacer le cache du dépôt</string>
|
||||
<string name="settings_clear_cache_summary">Effacer les informations en cache des dépôts en ligne, pour forcer une actualisation de l\'application</string>
|
||||
<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, les hosts systemless et busybox restent activés</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>
|
||||
|
@@ -2,64 +2,68 @@
|
||||
<!--Universal-->
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="navigation_drawer_open">Apri drawer di navigazione</string>
|
||||
<string name="navigation_drawer_close">Chiudi drawer di navigazione</string>
|
||||
<string name="modules">Moduli</string>
|
||||
<string name="downloads">Downloads</string>
|
||||
<string name="log">Log</string>
|
||||
<string name="settings">Impostazioni</string>
|
||||
<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="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_error">Hai installato Magisk?</string>
|
||||
<string name="checking_for_updates">Controlla aggiornamenti…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$.1f update!</string>
|
||||
<string name="magisk_version_core_only">Versione Magisk v%1$s (modo core)</string>
|
||||
<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">L\'ultima versione di %1$s è installata</string>
|
||||
<string name="root_error">Rootato ma senza permessi, non autorizzato?</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">Tap per avviare controllo SafetyNet</string>
|
||||
<string name="checking_safetyNet_status">Controllo SafetyNet</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_error">Impossibile controllare SafetyNet, no Internet?</string>
|
||||
<string name="safetyNet_fail">Errore SafetyNet: il profilo CTS non corrisponde</string>
|
||||
<string name="safetyNet_pass">SafetyNet corretto</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">(Auto) %1$s</string>
|
||||
<string name="cannot_auto_detect">(Cannot auto detect)</string>
|
||||
<string name="boot_image_title">Immagine Boot</string>
|
||||
<string name="detect_button">Identifica</string>
|
||||
<string name="advanced_settings_title">Impostazioni Avanzate</string>
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="auto_detect">%1$s (auto)</string>
|
||||
<string name="cannot_auto_detect">(impossibile rilevare automaticamente)</string>
|
||||
<string name="boot_image_title">Percorso immagine boot</string>
|
||||
<string name="detect_button">Rileva</string>
|
||||
<string name="advanced_settings_title">Impostazioni avanzate</string>
|
||||
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
|
||||
<string name="keep_dm_verity">Mantieni dm-verity</string>
|
||||
<string name="current_magisk_title">Versione Magisk installata: %1$s</string>
|
||||
<string name="install_magisk_title">Ultima versione Magisk: %1$s</string>
|
||||
<string name="uninstall">Disinstalla</string>
|
||||
<string name="reboot_countdown">Riavvio in %1$d</string>
|
||||
<string name="install_magisk_title">Versione Magisk aggiornata: %1$s</string>
|
||||
<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 crittografare i dati, se non crittografati/nVuoi continuare?</string>
|
||||
<string name="version_none">(None)</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>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nessuna informazione)</string>
|
||||
<string name="no_info_provided">(nessuna informazione)</string>
|
||||
<string name="no_modules_found">Nessun modulo trovato</string>
|
||||
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio</string>
|
||||
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio</string>
|
||||
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio</string>
|
||||
<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">Flash Modulo Zip</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>
|
||||
<string name="installed">Installato</string>
|
||||
@@ -68,80 +72,81 @@
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">Salva nella SD</string>
|
||||
<string name="menuReload">Ricarica</string>
|
||||
<string name="menuClearLog">Cancella log</string>
|
||||
<string name="logs_cleared">Log creato con successo</string>
|
||||
<string name="log_is_empty">Il log è vuoto</string>
|
||||
<string name="logs_save_failed">Impossibile scrivere il log sulla SD</string>
|
||||
<string name="menuClearLog">Azzera registro eventi</string>
|
||||
<string name="logs_cleared">Registro eventi creato correttamente</string>
|
||||
<string name="log_is_empty">Il registro eventi è vuoto</string>
|
||||
<string name="logs_save_failed">Impossibile scrivere registro eventi nella SD</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Informazioni</string>
|
||||
<string name="app_developers">Sviluppatori</string>
|
||||
<string name="app_developers_"><![CDATA[App creata da <a href="https://github.com/topjohnwu">topjohnwu</a> in collaborazione con <a href="https://github.com/d8ahazard">Digitalhigh</a> e <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
|
||||
<string name="app_changelog">Changelog</string>
|
||||
<string name="translators">Fabb2303</string>
|
||||
<string name="app_version">Versione App</string>
|
||||
<string name="app_changelog">Novità</string>
|
||||
<string name="translators">Fabb2303 - bovirus</string>
|
||||
<string name="app_version">Versione app</string>
|
||||
<string name="app_source_code">Codice sorgente</string>
|
||||
<string name="donation">Donazione</string>
|
||||
<string name="app_translators">Traduttori App</string>
|
||||
<string name="support_thread">Thread di supporto</string>
|
||||
<string name="donation">Dona</string>
|
||||
<string name="app_translators">Traduttori app</string>
|
||||
<string name="support_thread">Supporto app</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">Questa funzione non funziona senza il permesso di scrivere sulla memoria di archiviazione esterna</string>
|
||||
<string name="permissionNotGranted">Questa funzione non sarà operativa senza il permesso di scrittura nella memoria di archiviazione esterna</string>
|
||||
<string name="no_thanks">No grazie</string>
|
||||
<string name="yes">Sì</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="close">Chiuso</string>
|
||||
<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">Valla alla sezione \"Install\"</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="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 Zip in una directory temporanea</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">Unzip zip file …</string>
|
||||
<string name="zip_process_msg">Elaborazione file Zip …</string>
|
||||
<string name="zip_install_progress_msg">Installazione %1$s …</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 %1$s</string>
|
||||
<string name="magisk_update_title">Nuovo aggiornamento Magisk disponibile!</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 Repo cancellata</string>
|
||||
<string name="safetyNet_hide_notice">Quest\'app usa SafetyNet\nè già gestita da Magisk Hide</string>
|
||||
<string name="start_magiskhide">Avvio MagiskHide …</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">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">Capisco</string>
|
||||
<string name="process_error">Errore di processo</string>
|
||||
<string name="internal_storage">Lo zip si trova in:\n[Internal Storage]%1$s</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="manual_boot_image">Seleziona manualmente l\'immagine di boot!</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
<string name="settings_dark_theme_title">Tema Scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita Tema Scuro</string>
|
||||
<string name="settings_notification_title">Notifica Aggiornamento</string>
|
||||
<string name="settings_notification_summary">Mostra notifiche quando sono diponibili nuovi aggiornamenti</string>
|
||||
<string name="settings_clear_cache_title">Pulisci Cache Repo</string>
|
||||
<string name="settings_clear_cache_summary">Clear the cached information for online repos, forces the app to refresh online</string>
|
||||
<string name="settings_general_category">Generale</string>
|
||||
<string name="settings_dark_theme_title">Tema scuro</string>
|
||||
<string name="settings_dark_theme_summary">Abilita tema scuro</string>
|
||||
<string name="settings_notification_title">Notifica aggiornamenti</string>
|
||||
<string name="settings_notification_summary">Visualizza notifica quando sono diponibili aggiornamenti</string>
|
||||
<string name="settings_clear_cache_title">Azzera cache repository</string>
|
||||
<string name="settings_clear_cache_summary">Azzera le informazioni nella cache per i repository online, e forza l\'aggiornamento online dell\'app</string>
|
||||
|
||||
<string name="settings_magiskhide_summary">Hide Magisk from various detections</string>
|
||||
<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">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>
|
||||
<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>
|
||||
|
||||
<string name="settings_su_app_adb">Apps e ADB</string>
|
||||
<string name="settings_su_app">Solo Apps</string>
|
||||
<string name="settings_su_app_adb">App e ADB</string>
|
||||
<string name="settings_su_app">Solo app</string>
|
||||
<string name="settings_su_adb">Solo ADB</string>
|
||||
<string name="settings_su_disable">Disabilitato</string>
|
||||
<string name="settings_su_request_10">10 secondi</string>
|
||||
@@ -149,22 +154,33 @@
|
||||
<string name="settings_su_request_30">30 secondi</string>
|
||||
<string name="settings_su_request_60">60 secondi</string>
|
||||
<string name="superuser_access">Accesso Superuser</string>
|
||||
<string name="auto_response">Risposta Automatica</string>
|
||||
<string name="request_timeout">Timeout richiesto</string>
|
||||
<string name="auto_response">Risposta automatica</string>
|
||||
<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_summary">Ri-autentifica permessi superuser dopo aggiornamento applicazione</string>
|
||||
|
||||
<string name="settings_development_category">App Development</string>
|
||||
<string name="settings_developer_logging_title">Abilita Debug Log Avanzato</string>
|
||||
<string name="settings_developer_logging_summary">Check this to enable verbose logging</string>
|
||||
<string name="settings_shell_logging_title">Abilita comandi shell debug log</string>
|
||||
<string name="settings_shell_logging_summary">Check this to enable logging all shell commands and its output</string>
|
||||
<string name="multiuser_mode">Modo multiutente</string>
|
||||
<string name="settings_owner_only">Solo proprietario dispositivo</string>
|
||||
<string name="settings_owner_manage">gestito da propietario utente</string>
|
||||
<string name="settings_user_independent">Utente indipendente</string>
|
||||
<string name="owner_only_summary">Solo proprietario che ha accesso root</string>
|
||||
<string name="owner_manage_summary">Solo il propietario può gestire accesso root e ricevere richieste</string>
|
||||
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root separate</string>
|
||||
<string name="multiuser_hint_owner_request">Una richiestà è stata inviata al propietario dipositivo. Accedi come propietario dispositivo e concedi i permessi.</string>
|
||||
|
||||
<string name="settings_development_category">Sviluppo app</string>
|
||||
<string name="settings_developer_logging_title">Abilita registro eventi avanzato debug</string>
|
||||
<string name="settings_developer_logging_summary">Spunta questo per abilitare il registro eventi dettagliato</string>
|
||||
<string name="settings_shell_logging_title">Abilita registro eventi debug comandi shell</string>
|
||||
<string name="settings_shell_logging_summary">Spunta questo per abilitare il registro eventi dettagliato dei comandi shell e dei relativi risultati</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Richiesta Superuser</string>
|
||||
<string name="deny_with_str">Nega%1$s</string>
|
||||
<string name="deny_with_str">Nega %1$s</string>
|
||||
<string name="deny">Nega</string>
|
||||
<string name="prompt">Prompt</string>
|
||||
<string name="prompt">Richiedi</string>
|
||||
<string name="grant">Concedi</string>
|
||||
<string name="su_warning">Concede il pieno accesso al dispositivo.\nNega se non sei sicuro</string>
|
||||
<string name="forever">Sempre</string>
|
||||
@@ -173,24 +189,24 @@
|
||||
<string name="twentymin">20 minuti</string>
|
||||
<string name="thirtymin">30 minuti</string>
|
||||
<string name="sixtymin">60 minuti</string>
|
||||
<string name="su_allow_toast">%1$s ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_deny_toast">%1$s non ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_allow_toast">%1$s HA ottenuto i permessi Superuser</string>
|
||||
<string name="su_deny_toast">%1$s NON ha ottenuto i permessi Superuser</string>
|
||||
<string name="no_apps_found">Nessuna app trovata</string>
|
||||
<string name="su_snack_grant">Permessi Superuser per %1$s ottenuti</string>
|
||||
<string name="su_snack_deny">Permessi Superuser per %1$s non ottenuti</string>
|
||||
<string name="su_snack_grant"> %1$s HA ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_deny"> %1$s NON ha ottenuto i permessi Superuser</string>
|
||||
<string name="su_snack_notif_on">Notifiche per %1$s abilitate</string>
|
||||
<string name="su_snack_notif_off">Notifiche per %1$s disabilitate</string>
|
||||
<string name="su_snack_log_on">Log per %1$s è abilitato</string>
|
||||
<string name="su_snack_log_off">Log per %1$s è disabilitato</string>
|
||||
<string name="su_snack_revoke">%1$s rights are revoked</string>
|
||||
<string name="su_revoke_title">Revoke?</string>
|
||||
<string name="su_revoke_msg">Confirm to revoke %1$s rights?</string>
|
||||
<string name="su_snack_log_on">Registro eventi abilitato per %1$s</string>
|
||||
<string name="su_snack_log_off">Registro eventi NON abilitato per %1$s</string>
|
||||
<string name="su_snack_revoke">I diritti di %1$s sono stati revocati</string>
|
||||
<string name="su_revoke_title">Revocare?</string>
|
||||
<string name="su_revoke_msg">Confermi la revoca dei diritti di %1$s?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Nessuno</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">Target UID:\u0020</string>
|
||||
<string name="command">Command:\u0020</string>
|
||||
<string name="target_uid">UID destinazione:\u0020</string>
|
||||
<string name="command">Comando:\u0020</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -2,83 +2,83 @@
|
||||
<!--Universal-->
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="navigation_drawer_open">ナビゲーション• ドロワーを開く</string>
|
||||
<string name="navigation_drawer_close">ナビゲーション• ドロワーを閉じる</string>
|
||||
<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="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="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$.1fが利用可能!</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_connection_failed">Google APIに接続できない</string>
|
||||
<string name="safetyNet_connection_suspended">Google APIへの接続が中断された</string>
|
||||
<string name="safetyNet_error">SafetyNetチェックできない、ネットがないか?</string>
|
||||
<string name="safetyNet_fail">SafetyNet失敗: CTSプロファイルが不一致</string>
|
||||
<string name="safetyNet_pass">SafetyNet通過した</string>
|
||||
<string name="root_info_warning">機能が大幅に制限されている。</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>
|
||||
<string name="cannot_auto_detect">(自動検出できない)</string>
|
||||
<string name="boot_image_title">Boot イメージ場所</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="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="reboot_countdown">%1$dで再起動します</string>
|
||||
<string name="uninstall_magisk_title">Magiskをアンインストールします</string>
|
||||
<string name="uninstall_magisk_msg">これにより、すべてのモジュールとMagiskSUを削除する、暗号化されていないデータが暗号化される可能性があります。\ n続行しますか?</string>
|
||||
<string name="uninstall_magisk_msg">これにより、すべてのモジュールとMagiskSUを削除します。暗号化されていないデータが暗号化される可能性があります。\ n続行しますか?</string>
|
||||
<string name="version_none">(なし)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(情報を提供されない)</string>
|
||||
<string name="no_modules_found">モジュールが見つかない/string>
|
||||
<string name="update_file_created">>次の再起動時にモジュールを更新する</string>
|
||||
<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="fab_flash_zip">モジュールジップを焼く</string>
|
||||
<string name="author">作者: %1$s</string>
|
||||
<string name="fab_flash_zip">モジュールのzipを焼く</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">利用可能な更新</string>
|
||||
<string name="installed">インストールされた</string>
|
||||
<string name="not_installed">いんすとーるさていない</string>
|
||||
<string name="installed">インストール済</string>
|
||||
<string name="not_installed">未インストール</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">SDカードに保存</string>
|
||||
<string name="menuReload">リロード</string>
|
||||
<string name="menuClearLog">ログを消去する</string>
|
||||
<string name="logs_cleared">ログを正常にクリアされた</string>
|
||||
<string name="logs_cleared">ログは正常にクリアされました</string>
|
||||
<string name="log_is_empty">ログは空です</string>
|
||||
<string name="logs_save_failed">SDカードにログを書き込むことができない</string>
|
||||
<string name="logs_save_failed">SDカードにログを書き込むことができません:</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">説明</string>
|
||||
<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">に作成された</a>.]]></string>
|
||||
<string name="app_changelog">アプリのチェンジログ</string>
|
||||
<string name="translators" />神楽坂桜(Sakura_Sa233#Twitter)</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">神楽坂桜(Sakura_Sa233#Twitter)/ hota (@lindwurm)</string>
|
||||
<string name="app_version">アプリのバージョン</string>
|
||||
<string name="app_source_code">ソースコード</string>
|
||||
<string name="donation">寄付</string>
|
||||
@@ -86,41 +86,41 @@
|
||||
<string name="support_thread">サポートスレッド</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">この機能は外部ストレージを書き込む権限がないと作動しない</string>
|
||||
<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_install">ダウンロードとインストール</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="download_file_error">ダウンロード中にエラーが発生しました</string>
|
||||
<string name="install_error">インストールエラー!</string>
|
||||
<string name="invalid_zip">このジップはMagiskモジュールじゃない</string>
|
||||
<string name="reboot_title">インストール成功した!</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="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="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="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="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">ジップは:\n[Internal Storage]%1$sに保存されている</string>
|
||||
<string name="internal_storage">zipは:\n[Internal Storage]%1$sに保存されます</string>
|
||||
<string name="zip_process_title">処理</string>
|
||||
<string name="manual_boot_image">ブートイメージを手動で選択してください!</string>
|
||||
|
||||
@@ -129,16 +129,17 @@
|
||||
<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_notification_summary">新しいバージョンが利用可能になったときに通知する</string>
|
||||
<string name="settings_clear_cache_title">キャッシュを消去</string>
|
||||
<string name="settings_clear_cache_summary">オンラインリポジトリのキャッシュされた情報をクリアし、アプリをオンラインで更新する</string>
|
||||
<string name="settings_core_only_title">Magiskコアのみのモード</string>
|
||||
<string name="settings_core_only_summary">コア機能のみを有効にすると、すべてのモジュールがロードされません。 MagiskSU、MagiskHide、systemless hosts、BusyBoxは引き続き有効になります。</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にAdblockアプリのサポート</string>
|
||||
<string name="settings_hosts_summary">AdblockのためのSystemless hostsサポート</string>
|
||||
|
||||
<string name="settings_su_app_adb">アプリとADB</string>
|
||||
<string name="settings_su_app">アプリのみ</string>
|
||||
@@ -156,36 +157,36 @@
|
||||
|
||||
<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>
|
||||
<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_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="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">のスーパーユーザー権限が許可されました</string>
|
||||
<string name="su_snack_deny">%1$s のスーパーユーザー権限が拒否されました</string>
|
||||
<string name="su_snack_notif_on">%1$の通知は有効になって。</string>
|
||||
<string name="su_snack_notif_off">%1$の通知は無効になって。</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="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-->
|
||||
|
@@ -18,7 +18,7 @@
|
||||
<string name="magisk_version_error">Magisk가 설치되지 않음</string>
|
||||
|
||||
<string name="checking_for_updates">업데이트 확인 중…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$.1f 사용 가능!</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>
|
||||
@@ -28,7 +28,7 @@
|
||||
<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_error">SafetyNet 체크 실패. 인터넷 연결을 확인하세요.</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>
|
||||
@@ -133,7 +133,7 @@
|
||||
<string name="settings_clear_cache_summary">온라인 저장소에 대해 캐시된 정보를 지우고, 온라인에서 정보를 강제로 새로 고칩니다.</string>
|
||||
|
||||
<string name="settings_core_only_title">Magisk 핵심 기능 모드</string>
|
||||
<string name="settings_core_only_summary">핵심 기능만 사용합니다. 모든 모듈은 로드하지 않습니다. MagiskSU, MagiskHide, systemless hosts 및 busybox는 계속 사용할 수 있습니다.</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>
|
||||
|
@@ -2,97 +2,219 @@
|
||||
<!--Universal-->
|
||||
|
||||
<!--Welcome Activity-->
|
||||
<string name="navigation_drawer_open">Open navigatie</string>
|
||||
<string name="navigation_drawer_close">Sluit navigatie</string>
|
||||
<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>
|
||||
|
||||
<!--Magisk Fragment-->
|
||||
<string name="magisk_version">Geïnstalleerde Magisk: v%1$s</string>
|
||||
<string name="magisk_version_error">Heb jij Magisk wel geïnstalleerd?</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="magisk_update_available">Magisk v%1$.1f update!</string>
|
||||
<string name="cannot_check_updates">Kan niet controleren op updates.</string>
|
||||
<string name="up_to_date">Nieuwste versie van %1$s 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>
|
||||
|
||||
<!--Root Fragment-->
|
||||
<!--Install Fragment-->
|
||||
<string name="auto_detect">(Auto) %1$s</string>
|
||||
<string name="cannot_auto_detect">(Kan niet auto-detecteren)</string>
|
||||
<string name="boot_image_title">Boot image locatie</string>
|
||||
<string name="detect_button">Detecteren</string>
|
||||
<string name="advanced_settings_title">Geavanceerde instellingen</string>
|
||||
<string name="keep_force_encryption">Behoud afgedwongen versleuteling</string>
|
||||
<string name="keep_dm_verity">Behoud dm-verity</string>
|
||||
<string name="current_magisk_title">Geïnstalleerde Magisk versie: %1$s</string>
|
||||
<string name="install_magisk_title">Recentste Magisk versie: %1$s</string>
|
||||
<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>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Geen informatie gegeven)</string>
|
||||
<string name="no_info_provided">(Geen info verstrekt)</string>
|
||||
<string name="no_modules_found">Geen modules gevonden</string>
|
||||
<string name="update_file_created">Module wordt geüpdatet bij de volgende reboot.</string>
|
||||
<string name="remove_file_created">Module wordt verwijderd bij de volgende reboot.</string>
|
||||
<string name="remove_file_deleted">Module wordt niet verwijderd bij de volgende reboot.</string>
|
||||
<string name="disable_file_created">Module wordt uitgeschakeld bij de volgende reboot.</string>
|
||||
<string name="disable_file_removed">Module wordt ingeschakeld bij de volgende reboot.</string>
|
||||
<string name="author">Gemaakt door: %1$s</string>
|
||||
<string name="update_file_created">Module wordt bijgewerkt bij volgende herstart</string>
|
||||
<string name="remove_file_created">Module wordt verwijderd bij volgende herstart</string>
|
||||
<string name="remove_file_deleted">Module wordt niet verwijderd bij volgende herstart</string>
|
||||
<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>
|
||||
<string name="update_available">Update beschikbaar</string>
|
||||
<string name="installed">Geïnstalleerd</string>
|
||||
<string name="not_installed">Niet geïnstalleerd</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">Opslaan op SD-kaart</string>
|
||||
<string name="menuReload">Herladen</string>
|
||||
<string name="menuClearLog">Maak log leeg</string>
|
||||
<string name="logs_cleared">Log succesvol geleegd</string>
|
||||
<string name="menuClearLog">Log nu wissen</string>
|
||||
<string name="logs_cleared">Log succesvol gewist</string>
|
||||
<string name="log_is_empty">Log is leeg</string>
|
||||
<string name="logs_save_failed">Kon niet naar SD-kaart schrijven:</string>
|
||||
<string name="logs_save_failed">Kon log niet naar SD-kaart schrijven:</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Over</string>
|
||||
<string name="app_developers">Hoofddevelopers</string>
|
||||
<string name="app_developers_"><![CDATA[App gemaakt door <a href="https://github.com/topjohnwu">topjohnwu</a> in samenwerking met <a href="https://github.com/d8ahazard">Digitalhigh</a> en <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
|
||||
<string name="app_developers">Hoofdontwikkelaars</string>
|
||||
<string name="app_developers_"><![CDATA[App gemaakt door <a href="https://github.com/topjohnwu">Topjohnwu</a> in samenwerking met <a href="https://github.com/d8ahazard">Digitalhigh</a> en <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
|
||||
<string name="app_changelog">App\'s changelog</string>
|
||||
<string name="translators">NaamloosDT, Klaessen</string>
|
||||
<string name="translators" />
|
||||
<string name="app_version">App\'s versie</string>
|
||||
<string name="app_source_code">Source code</string>
|
||||
<string name="app_source_code">Broncode</string>
|
||||
<string name="donation">Donatie</string>
|
||||
<string name="app_translators">App\'s vertalers</string>
|
||||
<string name="support_thread">Support thread</string>
|
||||
<string name="support_thread">Hulp thread</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">Deze feature zal niet werken zonder permissie om op de externe opslag te schrijven.</string>
|
||||
<string name="permissionNotGranted">Deze functie werkt niet zonder schrijfpermissie voor externe opslag.</string>
|
||||
<string name="no_thanks">Nee bedankt</string>
|
||||
<string name="repo_install_title">Installeer %1$s</string>
|
||||
<string name="repo_install_msg">Wilt u %1$s installeren?</string>
|
||||
<string name="download_install">Downloaden en installeren</string>
|
||||
<string name="download_file_error">Er is een fout opgetreden bij het downloaden van het bestand</string>
|
||||
<string name="install_error">Er is een fout opgetreden in de installatie</string>
|
||||
<string name="invalid_zip">Zip bestand is geen Magisk Module!</string>
|
||||
<string name="reboot_title">Installatie succesvol!</string>
|
||||
<string name="reboot_msg">Wilt u nu rebooten?</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
<string name="yes">Ja</string>
|
||||
<string name="ok">Oké</string>
|
||||
<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 & 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_install_progress_msg">Instalatievoortgang: %1$s …</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">Wilt u Magisk downloaden en installeren?</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_process_title">Verwerken</string>
|
||||
<string name="manual_boot_image">Gelieve handmatig een boot image te selecteren!</string>
|
||||
|
||||
<!--URL Templates-->
|
||||
|
||||
<!--Settings Fragment -->
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">Algemeen</string>
|
||||
<string name="settings_dark_theme_title">Thema</string>
|
||||
<string name="settings_dark_theme_summary">Selecteer een thema</string>
|
||||
<string name="settings_dark_theme_title">Donker thema</string>
|
||||
<string name="settings_dark_theme_summary">Donker thema inschakelen</string>
|
||||
<string name="settings_notification_title">Update melding</string>
|
||||
<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_busybox_title">Schakel BusyBox in</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>
|
||||
|
||||
<string name="settings_development_category">Development</string>
|
||||
<string name="settings_developer_logging_title">Geavanceerde debug logging</string>
|
||||
<string name="settings_developer_logging_summary">Schakel dit in voor uitgebreidere logging.</string>
|
||||
<string name="settings_shell_logging_title">Shell command debug loggin</string>
|
||||
<string name="settings_shell_logging_summary">Schakel dit in om alle shell commands en output te loggen</string>
|
||||
<string name="settings_magiskhide_summary">Reboot om de instellingen toe te passen</string>
|
||||
<string name="settings_su_app_adb">Apps en ADB</string>
|
||||
<string name="settings_su_app">Alleen apps</string>
|
||||
<string name="settings_su_adb">Alleen ADB</string>
|
||||
<string name="settings_su_disable">Uitgeschakeld</string>
|
||||
<string name="settings_su_request_10">10 seconden</string>
|
||||
<string name="settings_su_request_20">20 seconden</string>
|
||||
<string name="settings_su_request_30">30 seconden</string>
|
||||
<string name="settings_su_request_60">60 seconden</string>
|
||||
<string name="superuser_access">Superuser toegang</string>
|
||||
<string name="auto_response">Automatisch antwoord</string>
|
||||
<string name="request_timeout">Verzoek time-out</string>
|
||||
<string name="superuser_notification">Superuser melding</string>
|
||||
<string name="request_timeout_summary">%1$s seconden</string>
|
||||
<string name="settings_su_reauth_title">Opnieuw verzoeken na bijwerken</string>
|
||||
<string name="settings_su_reauth_summary">Superuser rechten opnieuw opvragen na bijwerken applicatie</string>
|
||||
|
||||
<string name="multiuser_mode">Multi-gebruiker modus</string>
|
||||
<string name="settings_owner_only">Alleen apparaateigenaar</string>
|
||||
<string name="settings_owner_manage">Beheerd door apparaateigenaar</string>
|
||||
<string name="settings_user_independent">Gebruiker onafhankelijk</string>
|
||||
<string name="owner_only_summary">Alleen eigenaar heeft roottoegang</string>
|
||||
<string name="owner_manage_summary">Alleen eigenaar kan roottoegang beheren en prompt verzoeken ontvangen</string>
|
||||
<string name="user_indepenent_summary">Iedere gebruiker heeft eigen afzonderlijke rootregels</string>
|
||||
<string name="multiuser_hint_owner_request">Een verzoek is naar de apparaateigenaar verstuurd. Wissel van gebruiker en sta de rechten toe</string>
|
||||
|
||||
<!-- Strings related to Settings -->
|
||||
<string name="mount_namespace_mode">Naamruimte-mount modus</string>
|
||||
<string name="settings_ns_global">Globale naamruimte</string>
|
||||
<string name="settings_ns_requester">Verkrijg naamruimte</string>
|
||||
<string name="settings_ns_isolate">Geïsoleerde naamruimte</string>
|
||||
<string name="global_summary">Alle rootsessies gebruiken de globale naamruimte</string>
|
||||
<string name="requester_summary">Rootsessies verkrijgen de verzoeker\'s naamruimte</string>
|
||||
<string name="isolate_summary">Iedere rootsessie heeft een eigen geïsoleerde naamruimte</string>
|
||||
|
||||
<string name="settings_development_category">App-ontwikkeling</string>
|
||||
<string name="settings_developer_logging_title">Geavanceerde debug logs inschakelen</string>
|
||||
<string name="settings_developer_logging_summary">Aanvinken om uitgebreide logs in te schakelen</string>
|
||||
<string name="settings_shell_logging_title">Shell-opdracht debug logs inschakelen</string>
|
||||
<string name="settings_shell_logging_summary">Aanvinken om alle shell-opdracht en uitvoer logs in te schakelen</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Superuser verzoek</string>
|
||||
<string name="deny_with_str">Weigeren %1$s</string>
|
||||
<string name="deny">Weigeren</string>
|
||||
<string name="prompt">Prompt</string>
|
||||
<string name="grant">Toestaan</string>
|
||||
<string name="su_warning">Verleent volledige toegang aan je apparaat.\nWeigeren als je het niet zeker weet!</string>
|
||||
<string name="forever">Altijd</string>
|
||||
<string name="once">Eénmalig</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">Superuser rechten voor %1$s toegestaan</string>
|
||||
<string name="su_deny_toast">Superuser rechten voor %1$s geweigerd</string>
|
||||
<string name="no_apps_found">Geen apps gevonden</string>
|
||||
<string name="su_snack_grant">Superuser rechten van %1$s toegestaan</string>
|
||||
<string name="su_snack_deny">Superuser rechten van %1$s geweigerd</string>
|
||||
<string name="su_snack_notif_on">Meldingen van %1$s ingeschakeld</string>
|
||||
<string name="su_snack_notif_off">Meldingen van %1$s uitgeschakeld</string>
|
||||
<string name="su_snack_log_on">Loggen van %1$s ingeschakeld</string>
|
||||
<string name="su_snack_log_off">Loggen of %1$s uitgeschakeld</string>
|
||||
<string name="su_snack_revoke">%1$s rechten zijn ingetrokken</string>
|
||||
<string name="su_revoke_title">Intrekken?</string>
|
||||
<string name="su_revoke_msg">De rechten van %1$s intrekken?</string>
|
||||
<string name="toast">Toast</string>
|
||||
<string name="none">Geen</string>
|
||||
|
||||
<!-- Example General settings -->
|
||||
|
||||
<!-- Example settings for Data & Sync -->
|
||||
|
||||
<!-- Example settings for Notifications -->
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">Doel UID:\u0020</string>
|
||||
<string name="command">Opdracht:\u0020</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -17,11 +17,11 @@
|
||||
|
||||
<!--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_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$.1f dostępny!</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>
|
||||
@@ -29,11 +29,15 @@
|
||||
<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_error">Nie można sprawdzić SafetyNet bez internetu</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-->
|
||||
@@ -126,8 +130,10 @@
|
||||
<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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<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>
|
||||
|
||||
<!--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>
|
||||
@@ -136,8 +142,8 @@
|
||||
<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_core_only_summary">Włącz tylko podstawowe funkcje, wszystkie moduły nie zostaną załadowane. MagiskSU, MagiskHide, systemless hosts i BusyBox nadal będą włączone</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>
|
||||
@@ -157,7 +163,26 @@
|
||||
<string name="request_timeout">Czas na decyzję</string>
|
||||
<string name="superuser_notification">Powiadomienia Superusera</string>
|
||||
<string name="request_timeout_summary">%1$s sekund</string>
|
||||
<string name="settings_su_reauth_title">Ponowienie uwierzytelnienia po aktualizacji</string>
|
||||
<string name="settings_su_reauth_summary">Ponowne uwierzytelnianie uprawnienia superużytkownika po aktualizacji aplikacji</string>
|
||||
|
||||
<string name="multiuser_mode">Tryb Multiusera</string>
|
||||
<string name="settings_owner_only">Tylko Właściciel Urządzenia</string>
|
||||
<string name="settings_owner_manage">Zarządzanie Właścicielami Urządzenia</string>
|
||||
<string name="settings_user_independent">Niezależny Użytkownik</string>
|
||||
<string name="owner_only_summary">Tylko właściciel ma dostęp do roota</string>
|
||||
<string name="owner_manage_summary">Tylko właściciel może zarządzać prawami dostępu użytkownika do roota iwyświetlać żądania dostępu</string>
|
||||
<string name="user_indepenent_summary">Każdy użytkownik ma swoje własne odrębne ustawienia dostępu</string>
|
||||
<string name="multiuser_hint_owner_request">Żądanie zostało wysłane do właściciela urządzenia. Proszę przejść do właściciela i udzielić pozwolenia</string>
|
||||
|
||||
<string name="mount_namespace_mode">Montuj Tryb Nazw</string>
|
||||
<string name="settings_ns_global">Globalna Nazwa</string>
|
||||
<string name="settings_ns_requester">Dziedziczenie Nazw</string>
|
||||
<string name="settings_ns_isolate">Izolacja Nazw</string>
|
||||
<string name="global_summary">Wszystkie sesje root za pomocą globalnej przestrzeni montowań nazw</string>
|
||||
<string name="requester_summary">Sesje Root będzie dziedziczyć prośby i nazwy</string>
|
||||
<string name="isolate_summary">W każdej sesji root będzie miał własną odosobnioną nazwę</string>
|
||||
|
||||
<string name="settings_development_category">Dla Developerów</string>
|
||||
<string name="settings_developer_logging_title">Włącz zaawansowane logowanie debugowania</string>
|
||||
<string name="settings_developer_logging_summary">Zaznacz, aby umożliwić pełne rejestrowanie</string>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<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$.1f disponível!</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>
|
||||
@@ -31,7 +31,7 @@
|
||||
<string name="checking_safetyNet_status">Checando status do SafetyNet…</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_error">Não é possível verificar o SafetyNet, sem Internet?</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="root_info_warning">Funcionalidade muito limitada</string>
|
||||
@@ -137,7 +137,7 @@
|
||||
<string name="settings_clear_cache_summary">Limpe as informações armazenadas em cache para repos. online, forçando o aplicativo a atualizar online</string>
|
||||
|
||||
<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, systemless hosts, e busybox ainda estará ativado</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>
|
224
app/src/main/res/values-pt-rPT/strings.xml
Normal file
224
app/src/main/res/values-pt-rPT/strings.xml
Normal file
@@ -0,0 +1,224 @@
|
||||
<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>
|
||||
|
||||
<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="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">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="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="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="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>
|
||||
|
||||
<!--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>
|
||||
|
||||
<!--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>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<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>
|
||||
|
||||
<!--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>
|
||||
|
||||
<!--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 & instalar</string>
|
||||
<string name="download">Transferir</string>
|
||||
<string name="goto_install">Ir para secção instalar</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="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="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="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>
|
||||
<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_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_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>
|
||||
<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>
|
||||
|
||||
|
||||
</resources>
|
216
app/src/main/res/values-ro/strings.xml
Normal file
216
app/src/main/res/values-ro/strings.xml
Normal file
@@ -0,0 +1,216 @@
|
||||
<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="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>
|
||||
<string name="cannot_auto_detect">(Nu se poate detecta automat)</string>
|
||||
<string name="boot_image_title">Locaţie imagine Boot</string>
|
||||
<string name="detect_button">Detectare</string>
|
||||
<string name="advanced_settings_title">Setări avansate</string>
|
||||
<string name="keep_force_encryption">Păstrare criptare forţată</string>
|
||||
<string name="keep_dm_verity">Păstrare dm-verity</string>
|
||||
<string name="current_magisk_title">Versiune Magisk instalată: %1$s</string>
|
||||
<string name="install_magisk_title">Ultima versiune Magisk: %1$s</string>
|
||||
<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>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Nu sunt furnizate informații)</string>
|
||||
<string name="no_modules_found">Niciun modul</string>
|
||||
<string name="update_file_created">Modulul va fi actualizat la următoarea repornire</string>
|
||||
<string name="remove_file_created">Modulul va fi eliminat la următoarea repornire</string>
|
||||
<string name="remove_file_deleted">Modulul nu va fi eliminat la următoarea repornire</string>
|
||||
<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>
|
||||
<string name="installed">Instalat</string>
|
||||
<string name="not_installed">Nu este instalat</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">Salvare pe cardul SD</string>
|
||||
<string name="menuReload">Reîncărcare</string>
|
||||
<string name="menuClearLog">Șterge jurnal acum</string>
|
||||
<string name="logs_cleared">Jurnal şters</string>
|
||||
<string name="log_is_empty">Jurnal gol</string>
|
||||
<string name="logs_save_failed">Nu s-a putut scrie jurnalul pe cardul SD:</string>
|
||||
|
||||
<!--About Activity-->
|
||||
<string name="about">Despre</string>
|
||||
<string name="app_developers">Dezvoltatori principali</string>
|
||||
<string name="app_developers_"><![CDATA[Aplicație creată de <a href="https://github.com/topjohnwu">topjohnwu</a> în colaborare cu <a href="https://github.com/d8ahazard">Digitalhigh</a> şi <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
|
||||
<string name="app_changelog">Lista modificărilor</string>
|
||||
<string name="translators" />
|
||||
<string name="app_version">Versiune aplicaţie</string>
|
||||
<string name="app_source_code">Cod sursă</string>
|
||||
<string name="donation">Donaţie</string>
|
||||
<string name="app_translators">Traducători</string>
|
||||
<string name="support_thread">Pagina de suport</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">Această caracteristică nu va funcționa fără permisiunea de a scrie pe memoria externă.</string>
|
||||
<string name="no_thanks">Nu, mulţumesc</string>
|
||||
<string name="yes">Da</string>
|
||||
<string name="ok">OK</string>
|
||||
<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="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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
<string name="settings_dark_theme_title">Temă întunecată</string>
|
||||
<string name="settings_dark_theme_summary">Activare temă întunecată</string>
|
||||
<string name="settings_notification_title">Notificare actualizare</string>
|
||||
<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_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>
|
||||
|
||||
<string name="settings_su_app_adb">Aplicaţii şi ADB</string>
|
||||
<string name="settings_su_app">Doar aplicaţii</string>
|
||||
<string name="settings_su_adb">Doar ADB</string>
|
||||
<string name="settings_su_disable">Dezactivat</string>
|
||||
<string name="settings_su_request_10">10 secunde</string>
|
||||
<string name="settings_su_request_20">20 de secunde</string>
|
||||
<string name="settings_su_request_30">30 de secunde</string>
|
||||
<string name="settings_su_request_60">60 de secunde</string>
|
||||
<string name="superuser_access">Acces Superuser</string>
|
||||
<string name="auto_response">Răspuns automat</string>
|
||||
<string name="request_timeout">Expirare</string>
|
||||
<string name="superuser_notification">Notificare Superuser</string>
|
||||
<string name="request_timeout_summary">%1$s secunde</string>
|
||||
<string name="settings_su_reauth_title">Reautentificare după actualizare</string>
|
||||
<string name="settings_su_reauth_summary">Reautentificare permisiuni pentru superuser după o actualizare a aplicației</string>
|
||||
|
||||
<string name="multiuser_mode">Mod Multiutilizator</string>
|
||||
<string name="settings_owner_only">Numai proprietarul dispozitivului</string>
|
||||
<string name="settings_owner_manage">Gestionat de proprietarul dispozitivului</string>
|
||||
<string name="settings_user_independent">Utilizator independent</string>
|
||||
<string name="owner_only_summary">Numai proprietarul are acces la root</string>
|
||||
<string name="owner_manage_summary">Numai proprietarul poate gestiona accesul la root și să primească solicitări</string>
|
||||
<string name="user_indepenent_summary">Fiecare utilizator are propriile reguli de acces la root</string>
|
||||
<string name="multiuser_hint_owner_request">A fost trimisă o solicitare proprietarului dispozitivului. Comutaţi la proprietar și acordați permisiunea</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mod montare spaţiu de nume</string>
|
||||
<string name="settings_ns_global">Spaţiu de nume global</string>
|
||||
<string name="settings_ns_requester">Spaţiu de nume moştenit</string>
|
||||
<string name="settings_ns_isolate">Spațiu de nume izolat</string>
|
||||
<string name="global_summary">Toate sesiunile de root utilizează spațiul de nume global</string>
|
||||
<string name="requester_summary">Sesiunile de root vor moșteni spațiul de nume al solicitantului</string>
|
||||
<string name="isolate_summary">Fiecare sesiune de root va avea propriul spațiu de nume izolat</string>
|
||||
|
||||
<string name="settings_development_category">Dezvoltare aplicaţie</string>
|
||||
<string name="settings_developer_logging_title">Activați logarea avansată de depanare</string>
|
||||
<string name="settings_developer_logging_summary">Bifați această opțiune pentru a activa înregistrarea detaliată</string>
|
||||
<string name="settings_shell_logging_title">Activați logarea comenzilor shell</string>
|
||||
<string name="settings_shell_logging_summary">Bifați această opțiune pentru a permite logarea tuturor comenzilor shell și ieșirea acestora</string>
|
||||
|
||||
<!--Superuser-->
|
||||
<string name="su_request_title">Solicitare Superuser</string>
|
||||
<string name="deny_with_str">Refuzaţi %1$s</string>
|
||||
<string name="deny">Refuzaţi</string>
|
||||
<string name="prompt">Solicitare</string>
|
||||
<string name="grant">Permiteţi</string>
|
||||
<string name="su_warning">Acordă acces complet la dispozitivul dvs..\nRefuzaţi dacă nu sunteţi sigur!</string>
|
||||
<string name="forever">Pentru totdeauna</string>
|
||||
<string name="once">O singura dată</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 i-au fost acordate drepturi Superuser</string>
|
||||
<string name="su_deny_toast">%1$s i-au fost refuzate drepturi Superuser</string>
|
||||
<string name="no_apps_found">Nicio aplicaţie</string>
|
||||
<string name="su_snack_grant">Drepturile Superuser pentru %1$s au fost acordate</string>
|
||||
<string name="su_snack_deny">Drepturile Superuser pentru %1$s au fost refuzate</string>
|
||||
<string name="su_snack_notif_on">Notificările pentru %1$s au fost acordate</string>
|
||||
<string name="su_snack_notif_off">Notificările pentru %1$s au fost refuzate</string>
|
||||
<string name="su_snack_log_on">Logarea pentru %1$s a fost activată</string>
|
||||
<string name="su_snack_log_off">Logarea pentru %1$s a fost dezactivată</string>
|
||||
<string name="su_snack_revoke">Drepturile pentru %1$s sunt revocate</string>
|
||||
<string name="su_revoke_title">Revocaţi?</string>
|
||||
<string name="su_revoke_msg">Confirmați revocarea drepturilor pentru %1$s?</string>
|
||||
<string name="toast">Mesaj</string>
|
||||
<string name="none">Nimic</string>
|
||||
|
||||
<!--Superuser logs-->
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">UID:\u0020</string>
|
||||
<string name="command">Comandă:\u0020</string>
|
||||
|
||||
</resources>
|
@@ -1,57 +1,68 @@
|
||||
<resources>
|
||||
<!--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="log">История</string>
|
||||
<string name="settings">Настройки</string>
|
||||
<string name="status">Статус</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$.1f!</string>
|
||||
<string name="cannot_check_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="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_connection_failed">Невозможно соединиться с API Google</string>
|
||||
<string name="safetyNet_connection_suspended">Соединение с API Google было приостановлено</string>
|
||||
<string name="safetyNet_error">Невозможно выполнить проверку SafetyNet, нет соединения?</string>
|
||||
<string name="safetyNet_fail">SafetyNet не пройден: несовпадение профиля CTS</string>
|
||||
<string name="safetyNet_pass">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="boot_image_title">Местоположение образа Boot</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="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="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>
|
||||
<string name="version_none">(Нет данных)</string>
|
||||
|
||||
<!--Module Fragment-->
|
||||
<string name="no_info_provided">(Нет информации)</string>
|
||||
<string name="no_modules_found">Модули не найдены</string>
|
||||
<string name="update_file_created">Модуль будет обновлён при перезагрузке</string>
|
||||
<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="disable_file_created">Модуль будет отключен при перезагрузке</string>
|
||||
<string name="disable_file_removed">Модуль будет включен при перезагрузке</string>
|
||||
<string name="author">Автор: %1$s</string>
|
||||
<string name="fab_flash_zip">Прошить модуль из zip-архива</string>
|
||||
<string name="fab_flash_zip">Прошить архив с модулем</string>
|
||||
|
||||
<!--Repo Fragment-->
|
||||
<string name="update_available">Доступно обновление</string>
|
||||
@@ -59,122 +70,153 @@
|
||||
<string name="not_installed">Не установлен</string>
|
||||
|
||||
<!--Log Fragment-->
|
||||
<string name="menuSaveToSd">Сохранить на SD-карту</string>
|
||||
<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">Не удалось сохранить лог на SD-карту:</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">Главные разработчики</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">Exalm</string>
|
||||
<string name="translators" />
|
||||
<string name="app_version">Версия</string>
|
||||
<string name="app_source_code">Исходный код</string>
|
||||
<string name="donation">Пожертвовать</string>
|
||||
<string name="donation">Поддержать проект</string>
|
||||
<string name="app_translators">Переводчики</string>
|
||||
<string name="support_thread">Страница поддержки</string>
|
||||
|
||||
<!--Toasts, Dialogs-->
|
||||
<string name="permissionNotGranted">Это не будет работать без доступа к внешнему хранилищу</string>
|
||||
<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="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">Этот архив не содержит модуль Magisk!!</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_msg">Желаете перезагрузить сейчас?</string>
|
||||
<string name="reboot">Перезагрузка</string>
|
||||
<string name="copying_msg">Копирование архива во временную директорию</string>
|
||||
<string name="copying_msg">Копирование архива во временную папку</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="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="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, использования MagiskHide может не хватить!\nЭто официально не поддерживается, и вам могут понадобиться дополнительные инструменты (например, suhide), чтобы пройти SafetyNet.</string>
|
||||
<string name="understand">Я понимаю</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_process_title">Обработка</string>
|
||||
<string name="manual_boot_image">Пожалуйста, выберите вручную boot-образ!</string>
|
||||
<string name="manager_update_title">Доступно новое обновление менеджера Magisk!</string>
|
||||
<string name="manager_download_install">Нажмите, чтобы скачать и установить</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_clear_cache_title">Очистить кэш репозиториев</string>
|
||||
<string name="settings_clear_cache_summary">Удалить сохранённую информацию о сетевых репозиториях, чтобы приложение обновило информацию из сети</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_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">Примонтировать встроенный busybox из Magisk в xbin</string>
|
||||
<string name="settings_hosts_title">Включить Systemless hosts</string>
|
||||
<string name="settings_hosts_summary">Поддержа Systemless hosts для блокировщиков рекламы</string>
|
||||
<string name="settings_busybox_summary">Монтирование встроенного в Magisk busybox в xbin</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_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="auto_response">Автоответ</string>
|
||||
<string name="request_timeout">Период запроса</string>
|
||||
<string name="superuser_notification">Уведомление суперпользователя</string>
|
||||
<string name="request_timeout_summary">%1$s секунд</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>
|
||||
<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="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="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="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="target_uid">Целевой UID:\u0020</string>
|
||||
<string name="command">Команда:\u0020</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -1,7 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="AppTheme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<style name="AppTheme.Transparent" parent="AppTheme">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Transparent.Dark" parent="AppTheme.Dark">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
|
@@ -15,7 +15,7 @@
|
||||
<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$.1f mevcut!</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>
|
||||
@@ -25,7 +25,7 @@
|
||||
<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_error">SafetyNet kontrol edilemiyor, İnternet yok mu?</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 Geçti</string>
|
||||
<string name="root_info_warning">İşlevsellik çok sınırlıdır</string>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
<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$.1f available!</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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<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_error">Không thể kiểm tra SafetyNet, không có Internet?</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>
|
||||
|
@@ -14,11 +14,11 @@
|
||||
|
||||
<!--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_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$.1f!</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>
|
||||
@@ -26,15 +26,20 @@
|
||||
<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_error">无法检查 SafetyNet,没有网络连接?</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="detect_button">检测</string>
|
||||
<string name="advanced_settings_title">高级设置</string>
|
||||
@@ -46,6 +51,7 @@
|
||||
<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>
|
||||
@@ -120,15 +126,21 @@
|
||||
<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>
|
||||
|
||||
<!--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_core_only_summary">仅启用核心功能,所有模组将不会被载入。MagiskSU丶MagiskHide丶systemless hosts丶和 busybox 仍会持续运作</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>
|
||||
@@ -148,6 +160,25 @@
|
||||
<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">仅设备所有者账户有超级用户权限</string>
|
||||
<string name="owner_manage_summary">仅设备所有者账户能管理超级用户并接收权限请求提示</string>
|
||||
<string name="user_indepenent_summary">每个用户有独立的权限规则</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">所有的 ROOT 会话使用全局挂载命名空间</string>
|
||||
<string name="requester_summary">ROOT 会话继承原程序的命名空间</string>
|
||||
<string name="isolate_summary">每一个 ROOT 会话使用自己独立的命名空间</string>
|
||||
|
||||
<string name="settings_development_category">开发</string>
|
||||
<string name="settings_developer_logging_title">启用高级日志记录</string>
|
||||
@@ -187,6 +218,5 @@
|
||||
<string name="pid">PID:\u0020</string>
|
||||
<string name="target_uid">目标 UID:\u0020</string>
|
||||
<string name="command">命令:\u0020</string>
|
||||
<string name="settings_core_only_title">Magisk 核心功能模式</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -17,7 +17,7 @@
|
||||
<string name="magisk_version_error">未安裝 Magisk</string>
|
||||
|
||||
<string name="checking_for_updates">正在檢查更新…</string>
|
||||
<string name="magisk_update_available">Magisk 可更新到 v%1$.1f!</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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<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_error">無法檢查 SafetyNet,沒有網絡連線?</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>
|
||||
@@ -192,6 +192,29 @@
|
||||
<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、和 busybox 仍會持續運作</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>
|
||||
<string name="safetyNet_res_invalid">回傳值無效</string>
|
||||
<string name="safetyNet_service_disconnected">服務已被取消</string>
|
||||
<string name="multiuser_hint_owner_request">已發送權限請求到擁有者帳戶中。請切換到擁有者帳戶進行准許</string>
|
||||
<string name="multiuser_mode">多使用者設定</string>
|
||||
<string name="owner_manage_summary">僅裝置擁有者帳戶能管理超級用戶權限並接收權限請求通知</string>
|
||||
<string name="owner_only_summary">僅裝置擁有者帳戶有超級用戶權限</string>
|
||||
<string name="user_indepenent_summary">每一位使用者有獨立的權限規則</string>
|
||||
<string name="settings_user_independent">各使用者獨立</string>
|
||||
<string name="settings_owner_only">僅裝置擁有者</string>
|
||||
<string name="settings_owner_manage">由裝置擁有者管理</string>
|
||||
<string name="manager_download_install">點擊以下載並安裝</string>
|
||||
<string name="manager_update_title">有 Magisk Manager 更新!</string>
|
||||
<string name="settings_su_reauth_summary">應用程式更新後,重新認證root權限</string>
|
||||
<string name="settings_su_reauth_title">更新後重新認證</string>
|
||||
<string name="global_summary">所有 root 工作使用全域 mount namespace</string>
|
||||
<string name="isolate_summary">每一 root 工作有自己獨立的 namespace</string>
|
||||
<string name="mount_namespace_mode">掛載命名空間(Namespace)模式</string>
|
||||
<string name="requester_summary">Root 工作繼承原程式之 namespace</string>
|
||||
<string name="settings_ns_global">全域 Namespace</string>
|
||||
<string name="settings_ns_isolate">獨立 Namespace</string>
|
||||
<string name="settings_ns_requester">繼承 Namespace</string>
|
||||
|
||||
</resources>
|
||||
|
@@ -49,4 +49,28 @@
|
||||
<item>@string/toast</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="multiuser_mode">
|
||||
<item>@string/settings_owner_only</item>
|
||||
<item>@string/settings_owner_manage</item>
|
||||
<item>@string/settings_user_independent</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="multiuser_summary">
|
||||
<item>@string/owner_only_summary</item>
|
||||
<item>@string/owner_manage_summary</item>
|
||||
<item>@string/user_indepenent_summary</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="namespace">
|
||||
<item>@string/settings_ns_global</item>
|
||||
<item>@string/settings_ns_requester</item>
|
||||
<item>@string/settings_ns_isolate</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="namespace_summary">
|
||||
<item>@string/global_summary</item>
|
||||
<item>@string/requester_summary</item>
|
||||
<item>@string/isolate_summary</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
@@ -30,5 +30,6 @@
|
||||
</declare-styleable>
|
||||
|
||||
<attr name="colorAccentFallback" format="reference" />
|
||||
<attr name="imageColorTint" format="reference" />
|
||||
|
||||
</resources>
|
@@ -10,7 +10,7 @@
|
||||
<color name="red500">#F44336</color>
|
||||
<color name="green500">#4CAF50</color>
|
||||
<color name="grey500">#9E9E9E</color>
|
||||
<color name="blue500">#2196F3</color>
|
||||
<color name="blue500">#2196f3</color>
|
||||
<color name="yellow500">#FFC107</color>
|
||||
|
||||
<color name="dark_secondary_text">#dedede</color>
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<string name="magisk_version_error">Magisk not installed</string>
|
||||
|
||||
<string name="checking_for_updates">Checking for updates…</string>
|
||||
<string name="magisk_update_available">Magisk v%1$.1f available!</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="root_error">Rooted but no root permission, not allowed?</string>
|
||||
@@ -29,11 +29,15 @@
|
||||
<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_error">Cannot check SafetyNet, no Internet?</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_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-->
|
||||
@@ -126,6 +130,9 @@
|
||||
<string name="internal_storage">The zip is stored in:\n[Internal Storage]%1$s</string>
|
||||
<string name="zip_process_title">Processing</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>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
@@ -137,7 +144,7 @@
|
||||
<string name="settings_clear_cache_summary">Clear the cached information for online repos, forces the app to refresh online</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, systemless hosts, and busybox will still be enabled</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>
|
||||
@@ -157,6 +164,25 @@
|
||||
<string name="request_timeout">Request Timeout</string>
|
||||
<string name="superuser_notification">Superuser Notification</string>
|
||||
<string name="request_timeout_summary">%1$s seconds</string>
|
||||
<string name="settings_su_reauth_title">Re-authenticate after upgrade</string>
|
||||
<string name="settings_su_reauth_summary">Re-authenticate superuser permissions after an application upgrades</string>
|
||||
|
||||
<string name="multiuser_mode">Multiuser Mode</string>
|
||||
<string name="settings_owner_only">Device Owner Only</string>
|
||||
<string name="settings_owner_manage">Device Owner Managed</string>
|
||||
<string name="settings_user_independent">User Independent</string>
|
||||
<string name="owner_only_summary">Only owner has root access</string>
|
||||
<string name="owner_manage_summary">Only owner can manage root access and receive request prompts</string>
|
||||
<string name="user_indepenent_summary">Each user has its own separate root rules</string>
|
||||
<string name="multiuser_hint_owner_request">A request has been sent to the device owner. Please switch to the owner and grant the permission</string>
|
||||
|
||||
<string name="mount_namespace_mode">Mount Namespace Mode</string>
|
||||
<string name="settings_ns_global">Global Namespace</string>
|
||||
<string name="settings_ns_requester">Inherit Namespace</string>
|
||||
<string name="settings_ns_isolate">Isolated Namespace</string>
|
||||
<string name="global_summary">All root sessions use the global mount namespace</string>
|
||||
<string name="requester_summary">Root sessions will inherit its requester\'s namespace</string>
|
||||
<string name="isolate_summary">Each root session will have its own isolated namespace</string>
|
||||
|
||||
<string name="settings_development_category">App Development</string>
|
||||
<string name="settings_developer_logging_title">Enable advanced debug logging</string>
|
||||
|
@@ -12,6 +12,7 @@
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="imageColorTint">@android:color/background_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Dark" parent="Theme.AppCompat.NoActionBar">
|
||||
@@ -24,6 +25,7 @@
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:textColorSecondary">@color/dark_secondary_text</item>
|
||||
<item name="imageColorTint">@android:color/background_light</item>
|
||||
</style>
|
||||
|
||||
<style name="CardViewStyle.Dark" parent="CardView">
|
||||
@@ -34,7 +36,12 @@
|
||||
<item name="cardBackgroundColor">@android:color/background_light</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<style name="AppTheme.Transparent" parent="AppTheme">
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Transparent.Dark" parent="AppTheme.Dark">
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryDark</item>
|
||||
</style>
|
||||
|
||||
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
|
||||
|
@@ -5,15 +5,14 @@
|
||||
android:title="@string/settings_general_category">
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="dark_theme"
|
||||
android:title="@string/settings_dark_theme_title"
|
||||
android:summary="@string/settings_dark_theme_summary"
|
||||
android:key="dark_theme" />
|
||||
android:summary="@string/settings_dark_theme_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="notification"
|
||||
android:title="@string/settings_notification_title"
|
||||
android:summary="@string/settings_notification_summary"
|
||||
android:key="notification" />
|
||||
android:summary="@string/settings_notification_summary" />
|
||||
|
||||
<Preference
|
||||
android:key="clear"
|
||||
@@ -31,21 +30,13 @@
|
||||
android:title="@string/settings_core_only_title"
|
||||
android:summary="@string/settings_core_only_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="busybox"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/settings_busybox_title"
|
||||
android:summary="@string/settings_busybox_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="magiskhide"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/magiskhide"
|
||||
android:summary="@string/settings_magiskhide_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="hosts"
|
||||
android:defaultValue="false"
|
||||
android:title="@string/settings_hosts_title"
|
||||
android:summary="@string/settings_hosts_summary" />
|
||||
|
||||
@@ -61,6 +52,18 @@
|
||||
android:entries="@array/su_access"
|
||||
android:entryValues="@array/value_array" />
|
||||
|
||||
<ListPreference
|
||||
android:key="multiuser_mode"
|
||||
android:title="@string/multiuser_mode"
|
||||
android:entries="@array/multiuser_mode"
|
||||
android:entryValues="@array/value_array" />
|
||||
|
||||
<ListPreference
|
||||
android:key="mnt_ns"
|
||||
android:title="@string/mount_namespace_mode"
|
||||
android:entries="@array/namespace"
|
||||
android:entryValues="@array/value_array" />
|
||||
|
||||
<ListPreference
|
||||
android:key="su_auto_response"
|
||||
android:title="@string/auto_response"
|
||||
@@ -79,9 +82,15 @@
|
||||
android:entries="@array/su_notification"
|
||||
android:entryValues="@array/value_array" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="su_reauth"
|
||||
android:title="@string/settings_su_reauth_title"
|
||||
android:summary="@string/settings_su_reauth_summary"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="developer"
|
||||
android:title="@string/settings_development_category">
|
||||
|
||||
<SwitchPreference
|
||||
|
@@ -4,9 +4,10 @@ buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url "https://maven.google.com" }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.4.0-alpha6'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-alpha6'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
@@ -10,7 +10,7 @@
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.jvmargs=-Xmx2560m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
@@ -19,4 +19,7 @@ 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
|
||||
org.gradle.daemon=true
|
||||
|
||||
# Enable AAPT2
|
||||
android.enableAapt2=true
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Wed Apr 05 09:31:45 CST 2017
|
||||
#Sat Jul 01 15:55:10 CST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip
|
||||
|
Reference in New Issue
Block a user