Compare commits

...

144 Commits
v21.1 ... v21.3

Author SHA1 Message Date
topjohnwu
7f8257152f Add v21.3 release notes 2021-01-16 04:55:44 -08:00
topjohnwu
0cd80f2556 Update app changelog 2021-01-16 04:42:14 -08:00
rydwhelchel
1717387876 Grammatical changes to the install docs 2021-01-15 21:32:29 -08:00
Mspy1
109363ebf6 Fixed typo 2021-01-15 21:31:58 -08:00
LLZN
716c4fa386 new update values-cs
update czech strings.xml
2021-01-15 21:31:17 -08:00
Arbri çoçka
9a09b4eb20 fix strings-sq 2021-01-15 21:29:53 -08:00
Rikka
95a5b57265 Remove "Flashing" overlay
Fix #3579, fix #3250
2021-01-15 21:28:59 -08:00
topjohnwu
13fbf397d1 Isolated processes might still be hide-able 2021-01-15 20:22:49 -08:00
vvb2060
20be99ec8a Restore mistakenly deleted codes 2021-01-15 19:59:55 -08:00
topjohnwu
04c53c3578 Legacy SAR: use a simpler method to detect is_two_stage 2021-01-15 02:44:40 -08:00
topjohnwu
51bc27a869 Avoid F2FS like a plague 2021-01-15 02:24:11 -08:00
topjohnwu
71b083794c Maintain global mount list 2021-01-14 21:14:54 -08:00
topjohnwu
b100d0c503 Revert DTB fstab changes 2021-01-14 19:48:00 -08:00
topjohnwu
76061296c9 Let MagiskBoot handle dtb fstab patching 2021-01-14 06:20:12 -08:00
topjohnwu
bb303d2da1 Remove old unused code 2021-01-14 05:59:53 -08:00
topjohnwu
c91c070343 Re-enable DTB table rebuilding 2021-01-14 05:45:05 -08:00
topjohnwu
aec06a6f61 Get proper total image size 2021-01-14 03:55:27 -08:00
topjohnwu
e8ba671fc2 Guard all injection features behind a global flag 2021-01-13 20:07:23 -08:00
topjohnwu
1860e5d133 Dynamically find libselinux.so path 2021-01-13 19:41:57 -08:00
topjohnwu
f2cb3c38fe Update mmap implementation
Always map memory as writable, but private when read-only
2021-01-12 22:50:55 -08:00
topjohnwu
9a28dd4f6e Implement MagiskHide through code injection 2021-01-12 03:28:00 -08:00
topjohnwu
d2acd59ea8 Minor code refactoring 2021-01-12 00:07:48 -08:00
topjohnwu
79dfdb29e7 Minor tweaks for patching tar files 2021-01-11 19:47:36 -08:00
topjohnwu
eb21c8b42e Code cleanups 2021-01-11 02:19:10 -08:00
topjohnwu
541bb53553 Update links in README 2021-01-10 20:36:58 -08:00
Hen Ry
fe8997efae Fix 2021-01-10 20:17:20 -08:00
Arbri çoçka
23455c722c fix in Values-sq 2021-01-10 20:16:57 -08:00
topjohnwu
5ce29c30d2 Fix sepolicy copying 2021-01-10 20:16:02 -08:00
topjohnwu
70d67728fd Add global toggle for ptrace monitor 2021-01-10 19:27:54 -08:00
topjohnwu
e546884b08 Remove isolated process handling in ptrace
Impossible to achieve only through ptrace
2021-01-10 17:18:42 -08:00
topjohnwu
b36e6d987d Reorganize MagiskHide code
Prepare for zygote injection hiding
2021-01-10 17:11:00 -08:00
topjohnwu
53c3dd5e8b Auto track JNI method hooks 2021-01-10 05:07:17 -08:00
topjohnwu
da723b207a Allow 3rd party code to load pre-specializing
Magisk's policy is to never allow 3rd party code to be loaded in the
zygote daemon process so we have 100% control over injection and hiding.
However, this makes it impossible for 3rd party modules to run anything
before process specialization, which includes the ability to modify the
arguments being sent to these original nativeForkAndXXX methods.

The trick here is to fork before calling the original nativeForkAndXXX
methods, and hook `fork` in libandroid_runtime.so to skip the next
invocation; basically, we're moving the responsibility of process
forking to our own hands.
2021-01-10 01:25:30 -08:00
topjohnwu
e050f77198 Don't hook SystemProperties#set
Doesn't seem necessary
2021-01-09 20:39:59 -08:00
topjohnwu
540b4b7ea9 Update pre/post hooks implementation 2021-01-09 17:41:25 -08:00
topjohnwu
bbef22daf7 More macro magic to automate more code 2021-01-09 04:28:26 -08:00
topjohnwu
9ed110c91b Add JNI hooks to critical methods 2021-01-08 05:25:44 -08:00
topjohnwu
a30d510eb1 Use xHook to hook functions in PLT 2021-01-08 00:53:24 -08:00
topjohnwu
ef98eaed8f Proper injection entry and unloading 2021-01-06 23:59:05 -08:00
topjohnwu
2a257f327c Sanitize /proc/PID/environ 2021-01-06 23:41:37 -08:00
topjohnwu
4060c2107c Add preliminary zygote code injection support
Prototyping the injection setup and a clean "self unloading" mechanism.
2021-01-06 22:21:17 -08:00
topjohnwu
cd23d27048 Fix remote_write implementation 2021-01-06 21:56:29 -08:00
topjohnwu
18b86e4fd2 Update Android.mk for test binary
Make Android Studio happy
2021-01-05 00:01:02 -08:00
topjohnwu
5f2e22a259 Support remote function call with ptrace
End up not used for anything, but keep it for good
2021-01-02 21:29:45 -08:00
topjohnwu
4e97b18977 Move libsystemproperties to external 2020-12-31 15:06:19 -08:00
topjohnwu
f9bde347bc Convert indentation to spaces
The tab war is lost
2020-12-30 22:11:24 -08:00
Billy Laws
947a7d6a2f Support rootwait cmdline parameter on legacy SAR
On devices where the primary storage is slow to probe it makes sense to
wait forever for the system partition to mount, this emulates the
kernel's behaviour when waiting for rootfs on SAR if the rootwait
parameter is supplied.

This issue was encountered with some SD cards on the Nintendo Switch.
2020-12-30 16:43:28 -08:00
Björn Engel
872ab2e99b Change translation for next
Nächste sounds a little bit strange.
2020-12-30 16:41:22 -08:00
kubalav
90b8813bb7 Fixed typo 2020-12-30 16:41:01 -08:00
Arbri çoçka
88d0f63294 Fix text in strings_sq 2020-12-30 16:40:47 -08:00
topjohnwu
79fa0d3a90 Hide selection improvements 2020-12-30 16:40:22 -08:00
topjohnwu
8e61080a4a Preparation for hiding isolated processes 2020-12-30 15:55:53 -08:00
topjohnwu
3f9a64417b Disable gradle daemon on Windows CI 2020-12-29 02:46:57 -08:00
topjohnwu
eb959379e8 Prevent resource ID clash 2020-12-29 02:39:47 -08:00
topjohnwu
41a644afb9 Open source stub APK loader
Close #3537
2020-12-29 01:44:02 -08:00
topjohnwu
6b42db943d Better bug report details 2020-12-28 17:03:20 -08:00
topjohnwu
1c325459eb Only run CI when it matters 2020-12-28 16:38:25 -08:00
John Wu
6d88d8ad95 Add issue templates 2020-12-28 16:26:10 -08:00
topjohnwu
246997f273 Update links 2020-12-28 15:58:53 -08:00
topjohnwu
b6144ae582 Add v21.2 release notes 2020-12-28 15:35:09 -08:00
Arbri çoçka
afe17c73b4 Update strings.xml
Fix same text in Values-sq
2020-12-28 15:29:27 -08:00
topjohnwu
b51b884fc7 Fix module installs in recovery
Close #3494
2020-12-28 00:25:01 -08:00
topjohnwu
d3e4b29e62 Update README.md 2020-12-27 22:36:03 -08:00
dark-basic
24059e7403 Update Stub-es version 2020-12-27 22:09:03 -08:00
dark-basic
107a2a6682 Update String-es 2020-12-27 22:08:34 -08:00
Arbri çoçka
56b4ab6672 Fix any text in strings sq 2020-12-27 22:07:44 -08:00
topjohnwu
4662454938 More attempts to fix gradle cache on Windows 2020-12-27 20:13:50 -08:00
topjohnwu
db4f78d463 Unblock signals before executing commands 2020-12-27 15:05:39 -08:00
topjohnwu
880de21596 Update Github Actions
Disable gradle daemon on Windows and always upload artifacts
2020-12-27 04:02:20 -08:00
topjohnwu
622dd84c9e Fix uninstaller zip 2020-12-26 22:45:05 -08:00
topjohnwu
f983bfc883 Embed keys into dex files 2020-12-26 21:33:30 -08:00
topjohnwu
45cdb3fdb0 Update dependencies 2020-12-26 17:05:12 -08:00
topjohnwu
9a707236b8 Move signing code into main app sources 2020-12-26 17:03:10 -08:00
topjohnwu
e9e6ad3bb0 Sign zips with apksigner 2020-12-26 16:04:41 -08:00
topjohnwu
ab78a81d15 Fix GitHub actions 2020-12-25 15:54:47 -08:00
John Wu
18340099b7 Add GitHub actions
Enable GitHub actions to run CI on all 3 platforms
2020-12-25 15:01:02 -08:00
topjohnwu
a013696a41 Default to config.prop in buildSrc 2020-12-25 13:03:25 -08:00
topjohnwu
8a2a6d9232 Make versionCode unconfigurable 2020-12-25 05:34:15 -08:00
topjohnwu
12aa6d86e4 Make config.prop optional 2020-12-24 04:46:31 -08:00
topjohnwu
7d08969d28 Fix strings 2020-12-23 01:33:46 -08:00
Fs00
dda4aa8488 Translate missing Italian strings 2020-12-22 23:33:20 -08:00
binarynoise
cdaef3d801 Update install.md
I wanted to share my experiences with rooting my S10e.
2020-12-22 23:32:53 -08:00
amninder singh
9159166128 Update strings.xml
Updating strings.xml
regarding #3566 adding punjabi translation
2020-12-22 23:32:01 -08:00
Arbri çoçka
dc0882e043 fixing some errors in sq strings 2020-12-22 23:31:40 -08:00
amninder singh
c811f015ef Added Punjabi Translation
- Written in Gurmukhi Script containing different foreign punctuations both inscript and Phonetic
2020-12-22 23:31:12 -08:00
nkh0472
d8f0b66fe1 Improve Correctness and Clarity of guides.md 2020-12-22 23:30:37 -08:00
Mohd Faraz
dc3d57deba utils_functions: Added a check for the system_root
now on addon while flashing recovery usign mount point /system_root by which this is causing a flashing error.
Let's first check and unmount /system_root if mounted

Signed-off-by: Mohd Faraz <androiabledroid@gmail.com>
2020-12-22 23:30:14 -08:00
topjohnwu
d089698475 Don't use root for logging getprop
Might contain sensitive info that shouldn't be shared
2020-12-19 23:09:36 -08:00
vvb2060
8ed2dd6687 Skip query for log files and patched boot file 2020-12-19 22:26:10 -08:00
vvb2060
50305ca1fe Support save manager log 2020-12-19 22:25:44 -08:00
vvb2060
3e91567636 Add a suffix to magisk_patched.img
prevent it from being used as input file
2020-12-19 21:53:16 -08:00
vvb2060
0b4dd63d36 Stub module always use release build 2020-12-19 21:02:05 -08:00
vvb2060
38d0f85deb Avoid unnecessary builds 2020-12-19 15:57:11 -08:00
vvb2060
c5b452f369 Get boot config properly
https://android.googlesource.com/platform/system/core/+/refs/tags/android-11.0.0_r16/fs_mgr/fs_mgr_boot_config.cpp#93
2020-12-19 15:55:33 -08:00
vvb2060
6ce9225f52 Check block dev ro status
magisk is shared object, use static busybox instead
2020-12-19 14:12:12 -08:00
vvb2060
13a8820603 Double check $DATA_DE 2020-12-19 14:08:32 -08:00
vvb2060
503997a09a Trim out \r 2020-12-19 14:08:06 -08:00
vvb2060
17efdff134 remove_system_su only on recovery mode
We may mount su to /system/bin/su
2020-12-19 13:59:08 -08:00
vvb2060
984f32f994 Move copy_sepolicy_rules to manager
We don’t need it when patch boot
2020-12-19 13:58:53 -08:00
topjohnwu
eee7f097e3 Make post-fs-data scripts block at most 35 secs 2020-12-17 16:54:53 -08:00
topjohnwu
086059ec30 Make sure boot stages are mutually exclusive 2020-12-15 03:40:37 -08:00
topjohnwu
7ff22c68c7 Only try to install APK when no manager is active 2020-12-09 02:15:16 -08:00
topjohnwu
1232113772 Update preference migration implementation
Only try to read preference through content provider when the app
is fresh install and a previous package ID is set. Also catch all
Exceptions to prevent crashing the app.

This prevents malicious settings injection and crashes when multiple
manager is installed.

Fix #3542
2020-12-09 02:07:58 -08:00
vvb2060
039d4936cb Disable superuser fragment properly 2020-12-09 01:16:30 -08:00
topjohnwu
784dd80965 Update MediaStoreUtils 2020-12-09 01:15:56 -08:00
vvb2060
1ffe9bd83b Fix update channel without description on release build 2020-12-09 00:40:33 -08:00
topjohnwu
0c28b23224 Fix install_module command 2020-12-09 00:37:15 -08:00
vvb2060
ec1af9dc1e Delete useless arrays 2020-12-09 00:17:58 -08:00
vvb2060
ff4cea229a Check environment on emulator
We need to test modules on emulator.
2020-12-09 00:16:27 -08:00
vvb2060
3f81f9371f Disable installation while downloading metadata 2020-12-09 00:16:13 -08:00
vvb2060
60e89a7d22 Ignore manager not installed state 2020-12-09 00:15:58 -08:00
vvb2060
c50daa5c9e Allow restore boot when no network 2020-12-09 00:15:41 -08:00
topjohnwu
58d00ab863 Remove some warnings 2020-12-07 00:06:02 -08:00
topjohnwu
ce916459c5 Fix strings 2020-12-07 00:04:41 -08:00
Antikruk
4094d560ab Belarusian update 2020-12-06 23:50:33 -08:00
RikkaW
4dbf7eb04b Fix spacing in module filter list 2020-12-06 23:49:23 -08:00
RikkaW
a39577c44d Fix extra spacing in module list 2020-12-06 23:49:23 -08:00
osm0sis
125ee46685 scripts: fix find_manager_apk
- the strings fallback was broken when the preceding character changed from 5 to ! recently, this new regex should cover any preceding character going forward
2020-12-06 23:49:03 -08:00
osm0sis
ce84f1762c scripts: fix sloppy/unpredictable cmd && this || that statements
- be a bit more POSIX to avoid any potential issues when full shell stdout/err are redirected
- actual logic chains remain unchanged
2020-12-06 23:48:43 -08:00
Hafitz Setya
a687d1347b Tidying up IN 2020-12-06 23:48:01 -08:00
Arbri çoçka
6d9db20614 Create strings.xml 2020-12-06 23:46:18 -08:00
topjohnwu
c62dfc1bcc Make logging less error prone 2020-12-06 23:09:24 -08:00
topjohnwu
aabe2696fe Cleanup implementations 2020-12-06 03:07:47 -08:00
topjohnwu
ae0d605310 Make sure patch_rootdir does not cause crashes 2020-12-06 02:19:57 -08:00
topjohnwu
2a694596b5 Better error handling and logging 2020-12-05 10:23:49 -08:00
topjohnwu
ff0a76606e Detect 2SI after system_root mount on legacy SAR 2020-12-04 03:06:21 -08:00
topjohnwu
dead74801d Setup log file when manually starting daemon 2020-12-04 01:07:47 -08:00
topjohnwu
ab207a1bb3 va_list cannot be reused on x86 2020-12-03 20:53:19 -08:00
topjohnwu
f152e8c33d Directly log to log file 2020-12-03 20:15:18 -08:00
topjohnwu
797ba4fbf4 Make sure all logging ends with newline 2020-12-02 00:55:22 -08:00
topjohnwu
a848f10bba Update Kotlin 2020-11-23 12:35:24 -08:00
topjohnwu
552ec1eb35 Header v3 does not have name entry 2020-11-20 22:52:09 -08:00
topjohnwu
1385d2a4f4 Fix strings 2020-11-19 23:34:02 -08:00
RikkaW
3b5c9abf7a Remove filterTouchesWhenObscured in Magisk dialog
Fix #3363
2020-11-19 23:32:23 -08:00
tzagim
e0fa032bd3 Update HE strings and fix typos 2020-11-19 23:29:47 -08:00
omerakgoz34
7b69650fcd app: Update Turkish translations 2020-11-19 23:27:54 -08:00
kubalav
08a8df489f Slovak language formating 2020-11-19 23:27:07 -08:00
cristisilaghi
9f35a8a520 Update Romanian 2020-11-19 23:26:38 -08:00
RikkaW
0df891b336 Handle window insets with a new way
For example, switching pages in home should only have scale and alpha animations, but a "translate y" animation shows. This is because Data Binding is triggered later (like "in the next frame"), causing the animation runs before view attribute changes.

This commit introduces WindowInsetsHelper class and use it to handle all window insets. With the help of LayoutInflaterFactory from the previous commit, we can control insets behavior by adding our attributes to the XML and anything is done by WindowInsetsHelper class.

As changes are highly coupling, this commit also contains new ItemDecoration for lists, replacing the random combination of padding and empty drawable. And "fixEdgeEffect" extension for RecyclerView, making edge effects respect padding.
2020-11-19 23:24:39 -08:00
RikkaW
385853a290 Introduce LayoutInflaterFactory
This add the ability touch layout XML instantiates process. And most importantly, we can access AttributeSet, making custom view attribute possible.

Some other changes requires this.
2020-11-19 23:24:39 -08:00
RikkaW
fa3ef8a1c1 Significantly simplify MagiskDialog layout
The goal of original implementation, wrap view again and again, seems to be use the shadow and customizable round corners from MaterialCardView. But this can be done with use MaterialShapeDrawable which used in MaterialCardView directly. This will significantly simplify the layout and MagiskDialog class.
2020-11-19 23:21:36 -08:00
RikkaW
c93ada03c7 Implement Edge-to-edge with newer APIs
The implementation adds a "Base" family styles, making creating themes across multiple API versions more clearer and easier.
2020-11-19 23:21:36 -08:00
topjohnwu
0064b01ae0 Trim out \r from string
Fix #3490
2020-11-15 06:30:29 -08:00
topjohnwu
1469b82aa2 Update README 2020-11-13 04:38:17 -08:00
259 changed files with 15722 additions and 12375 deletions

28
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
## READ BEFORE OPENING ISSUES
All bug reports require you to **USE CANARY BUILDS**. Please include the version name and version code in the bug report.
If you experience a bootloop, attach a `dmesg` (kernel logs) when the device refuse to boot. This may very likely require a custom kernel on some devices as `last_kmsg` or `pstore ramoops` are usually not enabled by default. In addition, please also upload the result of `cat /proc/mounts` when your device is working correctly **WITHOUT ROOT**.
If you experience issues during installation, in recovery, upload the recovery logs, or in Magisk Manager, upload the install logs. Please also upload the `boot.img` or `recovery.img` that you are using for patching.
If you experience a crash of Magisk Manager, dump the full `logcat` **when the crash happens**. **DO NOT** upload `magisk.log`.
If you experience other issues related to Magisk, upload `magisk.log`, and preferably also include a boot `logcat` (start dumping `logcat` when the device boots up)
**DO NOT** open issues regarding root detection.
**DO NOT** ask for instructions.
**DO NOT** report issues if you have any modules installed.
Without following the rules above, your issue will be closed without explanation.

94
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,94 @@
name: Magisk Build
on:
push:
branches: [ master ]
paths:
- 'app/**'
- 'native/**'
- 'stub/**'
- 'buildSrc/**'
- 'build.py'
- 'gradle.properties'
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macOS-latest ]
steps:
- name: Check out
uses: actions/checkout@v2
with:
submodules: 'recursive'
fetch-depth: 0
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11'
- name: Set up Python 3
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Set up GitHub env (Windows)
if: runner.os == 'Windows'
run: |
$oldAndroidPath = $env:ANDROID_SDK_ROOT
$sdk_root = "C:\Android"
New-Item -Path $sdk_root -ItemType SymbolicLink -Value $oldAndroidPath
$ndk_ver = Select-String -Path "gradle.properties" -Pattern "^magisk.fullNdkVersion=" | % { $_ -replace ".*=" }
echo "ANDROID_SDK_ROOT=$sdk_root" >> $env:GITHUB_ENV
echo "ANDROID_HOME=$sdk_root" >> $env:GITHUB_ENV
echo "MAGISK_NDK_VERSION=$ndk_ver" >> $env:GITHUB_ENV
echo "GRADLE_OPTS=-Dorg.gradle.daemon=false" >> $env:GITHUB_ENV
- name: Set up GitHub env (Unix)
if: runner.os != 'Windows'
run: |
ndk_ver=$(sed -n 's/^magisk.fullNdkVersion=//p' gradle.properties)
echo ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT >> $GITHUB_ENV
echo MAGISK_NDK_VERSION=$ndk_ver >> $GITHUB_ENV
- name: Cache Gradle
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle.kts') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Cache NDK
id: ndk-cache
uses: actions/cache@v2
with:
path: ${{ env.ANDROID_SDK_ROOT }}/ndk/magisk
key: ${{ runner.os }}-ndk-${{ env.MAGISK_NDK_VERSION }}
- name: Set up NDK
if: steps.ndk-cache.outputs.cache-hit != 'true'
run: python build.py ndk
- name: Build release
run: python build.py -vr all
- name: Build debug
run: python build.py -v all
# Only upload artifacts built on Linux
- name: Upload build artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v2
with:
name: ${{ github.sha }}
path: out

3
.gitmodules vendored
View File

@@ -25,6 +25,9 @@
[submodule "pcre"]
path = native/jni/external/pcre
url = https://android.googlesource.com/platform/external/pcre
[submodule "xhook"]
path = native/jni/external/xhook
url = https://github.com/iqiyi/xHook.git
[submodule "termux-elf-cleaner"]
path = tools/termux-elf-cleaner
url = https://github.com/termux/termux-elf-cleaner.git

View File

@@ -15,11 +15,11 @@ Here are some feature highlights:
## Downloads
[![](https://img.shields.io/badge/Magisk%20Manager-v8.0.2-green)](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.2/MagiskManager-v8.0.2.apk)
[![](https://img.shields.io/badge/Magisk%20Manager-v8.0.5-green)](https://github.com/topjohnwu/Magisk/releases/download/manager-v8.0.5/MagiskManager-v8.0.5.apk)
[![](https://img.shields.io/badge/Magisk%20Manager-Canary-red)](https://raw.githubusercontent.com/topjohnwu/magisk_files/canary/app-debug.apk)
<br>
[![](https://img.shields.io/badge/Magisk-v20.4-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v20.4)
[![](https://img.shields.io/badge/Magisk%20Beta-v21.0-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v21.0)
[![](https://img.shields.io/badge/Magisk-v21.2-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v21.2)
[![](https://img.shields.io/badge/Magisk%20Beta-v21.2-blue)](https://github.com/topjohnwu/Magisk/releases/tag/v21.2)
## Useful Links
@@ -58,11 +58,11 @@ For Magisk Manager crashes, record and upload the logcat when the crash occurs.
- Windows: Add `C:\Path\To\Android Studio\jre\bin` to environment variable `PATH`
- Set environment variable `ANDROID_SDK_ROOT` to the Android SDK folder (can be found in Android Studio settings)
- Run `./build.py ndk` to let the script download and install NDK for you
- Set configurations in `config.prop`. A sample `config.prop.sample` is provided.
- To start building, run `build.py` to see your options. \
For each action, use `-h` to access help (e.g. `./build.py all -h`)
- To start development, open the project in Android Studio. Both app (Kotlin/Java) and native (C++/C) source code can be properly developed using the IDE, but *always* use `build.py` for building.
- `build.py` builds in debug mode by default. If you want release builds (with `-r, --release`), you need a Java Keystore to sign APKs and zips. For more information, check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key).
- Optionally, set custom configs with `config.prop`. A sample `config.prop.sample` is provided.
- To sign APKs and zips with your own private keys, set signing configs in `config.prop`. For more info, check [Google's Documentation](https://developer.android.com/studio/publish/app-signing.html#generate-key).
## Translation Contributions

View File

@@ -1,7 +1,9 @@
import java.io.PrintStream
plugins {
id("com.android.application")
kotlin("android")
kotlin("android.extensions")
kotlin("plugin.parcelize")
kotlin("kapt")
id("androidx.navigation.safeargs.kotlin")
}
@@ -20,12 +22,11 @@ android {
applicationId = "com.topjohnwu.magisk"
vectorDrawables.useSupportLibrary = true
multiDexEnabled = true
versionName = Config["appVersion"]
versionCode = Config["appVersionCode"]?.toInt()
buildConfigField("int", "LATEST_MAGISK", Config["versionCode"] ?: "Integer.MAX_VALUE")
versionName = Config.appVersion
versionCode = Config.appVersionCode
javaCompileOptions.annotationProcessorOptions.arguments(
mapOf("room.incremental" to "true")
mapOf("room.incremental" to "true")
)
}
@@ -64,28 +65,61 @@ android {
}
}
androidExtensions {
isExperimental = true
}
val copyUtils = tasks.register("copyUtils", Copy::class) {
tasks["preBuild"]?.dependsOn(tasks.register("copyUtils", Copy::class) {
from(rootProject.file("scripts/util_functions.sh"))
into("src/main/res/raw")
}
})
tasks["preBuild"]?.dependsOn(copyUtils)
android.applicationVariants.all {
val keysDir = rootProject.file("tools/keys")
val outSrcDir = File(buildDir, "generated/source/keydata/$name")
val outSrc = File(outSrcDir, "com/topjohnwu/signing/KeyData.java")
fun PrintStream.newField(name: String, file: File) {
println("public static byte[] $name() {")
print("byte[] buf = {")
val bytes = file.readBytes()
print(bytes.joinToString(",") { "(byte)(${it.toInt() and 0xff})" })
println("};")
println("return buf;")
println("}")
}
val genSrcTask = tasks.register("generate${name.capitalize()}KeyData") {
inputs.dir(keysDir)
outputs.file(outSrc)
doLast {
outSrc.parentFile.mkdirs()
PrintStream(outSrc).use {
it.println("package com.topjohnwu.signing;")
it.println("public final class KeyData {")
it.newField("testCert", File(keysDir, "testkey.x509.pem"))
it.newField("testKey", File(keysDir, "testkey.pk8"))
it.newField("verityCert", File(keysDir, "verity.x509.pem"))
it.newField("verityKey", File(keysDir, "verity.pk8"))
it.println("}")
}
}
}
registerJavaGeneratingTask(genSrcTask.get(), outSrcDir)
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
implementation(kotlin("stdlib"))
implementation(project(":app:shared"))
implementation(project(":app:signing"))
implementation("com.github.topjohnwu:jtar:1.0.0")
implementation("com.github.topjohnwu:indeterminate-checkbox:1.0.7")
implementation("com.github.topjohnwu:lz4-java:1.7.1")
implementation("com.jakewharton.timber:timber:4.7.1")
val vBC = "1.68"
implementation("org.bouncycastle:bcprov-jdk15on:${vBC}")
implementation("org.bouncycastle:bcpkix-jdk15on:${vBC}")
val vBAdapt = "4.0.0"
val bindingAdapter = "me.tatarka.bindingcollectionadapter2:bindingcollectionadapter"
implementation("${bindingAdapter}:${vBAdapt}")
@@ -124,7 +158,7 @@ dependencies {
implementation("com.squareup.moshi:moshi:${vMoshi}")
kapt("com.squareup.moshi:moshi-kotlin-codegen:${vMoshi}")
val vRoom = "2.3.0-alpha03"
val vRoom = "2.3.0-alpha04"
implementation("androidx.room:room-runtime:${vRoom}")
implementation("androidx.room:room-ktx:${vRoom}")
kapt("androidx.room:room-compiler:${vRoom}")
@@ -136,7 +170,7 @@ dependencies {
implementation("androidx.biometric:biometric:1.0.1")
implementation("androidx.constraintlayout:constraintlayout:2.0.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.browser:browser:1.2.0")
implementation("androidx.browser:browser:1.3.0")
implementation("androidx.preference:preference:1.1.1")
implementation("androidx.recyclerview:recyclerview:1.1.0")
implementation("androidx.fragment:fragment-ktx:1.2.5")

View File

@@ -1 +0,0 @@
/build

View File

@@ -1,35 +0,0 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
id("java-library")
id("java")
id("com.github.johnrengelman.shadow") version "6.0.0"
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
val jar by tasks.getting(Jar::class) {
manifest {
attributes["Main-Class"] = "com.topjohnwu.signing.ZipSigner"
}
}
val shadowJar by tasks.getting(ShadowJar::class) {
archiveBaseName.set("zipsigner")
archiveClassifier.set(null as String?)
archiveVersion.set("4.0")
}
repositories {
jcenter()
}
dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))
api("org.bouncycastle:bcprov-jdk15on:1.67")
api("org.bouncycastle:bcpkix-jdk15on:1.67")
}

View File

@@ -1,49 +0,0 @@
package com.topjohnwu.signing;
import java.io.FileInputStream;
import java.io.InputStream;
public class BootSigner {
public static void main(String[] args) throws Exception {
if (args.length > 0 && "-verify".equals(args[0])) {
String certPath = "";
if (args.length >= 2) {
/* args[1] is the path to a public key certificate */
certPath = args[1];
}
boolean signed = SignBoot.verifySignature(System.in,
certPath.isEmpty() ? null : new FileInputStream(certPath));
System.exit(signed ? 0 : 1);
} else if (args.length > 0 && "-sign".equals(args[0])) {
InputStream cert = null;
InputStream key = null;
String name = "/boot";
if (args.length >= 3) {
cert = new FileInputStream(args[1]);
key = new FileInputStream(args[2]);
}
if (args.length == 2) {
name = args[1];
} else if (args.length >= 4) {
name = args[3];
}
boolean success = SignBoot.doSignature(name, System.in, System.out, cert, key);
System.exit(success ? 0 : 1);
} else {
System.err.println(
"BootSigner <actions> [args]\n" +
"Input from stdin, outputs to stdout\n" +
"\n" +
"Actions:\n" +
" -verify [x509.pem]\n" +
" verify image, cert is optional\n" +
" -sign [x509.pem] [pk8] [name]\n" +
" sign image, name, cert and key pair are optional\n" +
" name should be /boot (default) or /recovery\n"
);
}
}
}

View File

@@ -1,81 +0,0 @@
package com.topjohnwu.signing;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class ZipSigner {
private static void usage() {
System.err.println("ZipSigner usage:");
System.err.println(" zipsigner.jar input.jar output.jar");
System.err.println(" sign jar with AOSP test keys");
System.err.println(" zipsigner.jar x509.pem pk8 input.jar output.jar");
System.err.println(" sign jar with certificate / private key pair");
System.err.println(" zipsigner.jar keyStore keyStorePass alias keyPass input.jar output.jar");
System.err.println(" sign jar with Java KeyStore");
System.exit(2);
}
private static void sign(JarMap input, FileOutputStream output) throws Exception {
sign(SignApk.class.getResourceAsStream("/keys/testkey.x509.pem"),
SignApk.class.getResourceAsStream("/keys/testkey.pk8"), input, output);
}
private static void sign(InputStream certIs, InputStream keyIs,
JarMap input, FileOutputStream output) throws Exception {
X509Certificate cert = CryptoUtils.readCertificate(certIs);
PrivateKey key = CryptoUtils.readPrivateKey(keyIs);
SignApk.sign(cert, key, input, output);
}
private static void sign(String keyStore, String keyStorePass, String alias, String keyPass,
JarMap in, FileOutputStream out) throws Exception {
KeyStore ks;
try {
ks = KeyStore.getInstance("JKS");
try (InputStream is = new FileInputStream(keyStore)) {
ks.load(is, keyStorePass.toCharArray());
}
} catch (KeyStoreException|IOException|CertificateException|NoSuchAlgorithmException e) {
ks = KeyStore.getInstance("PKCS12");
try (InputStream is = new FileInputStream(keyStore)) {
ks.load(is, keyStorePass.toCharArray());
}
}
X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPass.toCharArray());
SignApk.sign(cert, key, in, out);
}
public static void main(String[] args) throws Exception {
if (args.length != 2 && args.length != 4 && args.length != 6)
usage();
Security.insertProviderAt(new BouncyCastleProvider(), 1);
try (JarMap in = JarMap.open(args[args.length - 2], false);
FileOutputStream out = new FileOutputStream(args[args.length - 1])) {
if (args.length == 2) {
sign(in, out);
} else if (args.length == 4) {
try (InputStream cert = new FileInputStream(args[0]);
InputStream key = new FileInputStream(args[1])) {
sign(cert, key, in, out);
}
} else if (args.length == 6) {
sign(args[0], args[1], args[2], args[3], in, out);
}
}
}
}

View File

@@ -12,7 +12,7 @@
<application
android:icon="@drawable/ic_launcher"
android:name="a.e"
android:allowBackup="true"
android:allowBackup="false"
tools:ignore="UnusedAttribute,GoogleAppIndexingWarning">
<!-- Splash -->

View File

@@ -8,10 +8,10 @@ import com.topjohnwu.magisk.core.SplashActivity
import com.topjohnwu.magisk.core.download.DownloadService
import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.ui.surequest.SuRequestActivity
import com.topjohnwu.signing.BootSigner
import com.topjohnwu.signing.SignBoot
fun main(args: Array<String>) {
BootSigner.main(args)
SignBoot.main(args)
}
class b : MainActivity()

View File

@@ -1,5 +1,8 @@
package com.topjohnwu.magisk.arch
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.View
@@ -14,6 +17,7 @@ import androidx.navigation.fragment.NavHostFragment
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.ui.inflater.LayoutInflaterFactory
import com.topjohnwu.magisk.ui.theme.Theme
abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
@@ -41,6 +45,8 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
}
override fun onCreate(savedInstanceState: Bundle?) {
layoutInflater.factory2 = LayoutInflaterFactory(delegate)
setTheme(themeRes)
super.onCreate(savedInstanceState)
@@ -59,6 +65,31 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
directionsDispatcher.value = null
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window?.decorView?.let {
it.systemUiVisibility = (it.systemUiVisibility
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
window?.decorView?.post {
// If navigation bar is short enough (gesture navigation enabled), make it transparent
if (window.decorView.rootWindowInsets?.systemWindowInsetBottom ?: 0 < Resources.getSystem().displayMetrics.density * 40) {
window.navigationBarColor = Color.TRANSPARENT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
window.navigationBarDividerColor = Color.TRANSPARENT
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
window.isNavigationBarContrastEnforced = false
window.isStatusBarContrastEnforced = false
}
}
}
}
}
}
fun setContentView() {
@@ -66,8 +97,6 @@ abstract class BaseUIActivity<VM : BaseViewModel, Binding : ViewDataBinding> :
it.setVariable(BR.viewModel, viewModel)
it.lifecycleOwner = this
}
ensureInsets()
}
fun setAccessibilityDelegate(delegate: View.AccessibilityDelegate?) {

View File

@@ -1,12 +1,9 @@
package com.topjohnwu.magisk.arch
import android.view.View
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.LifecycleOwner
interface BaseUIComponent<VM : BaseViewModel>: LifecycleOwner {
interface BaseUIComponent<VM : BaseViewModel> : LifecycleOwner {
val viewRoot: View
val viewModel: VM
@@ -17,47 +14,8 @@ interface BaseUIComponent<VM : BaseViewModel>: LifecycleOwner {
}
}
fun consumeSystemWindowInsets(insets: Insets): Insets? = null
/**
* Called for all [ViewEvent]s published by associated viewModel.
*/
fun onEventDispatched(event: ViewEvent) {}
fun ensureInsets() {
ViewCompat.setOnApplyWindowInsetsListener(viewRoot) { _, insets ->
insets.asInsets()
.also { viewModel.insets = it }
.let { consumeSystemWindowInsets(it) }
?.subtractBy(insets) ?: insets
}
if (ViewCompat.isAttachedToWindow(viewRoot)) {
ViewCompat.requestApplyInsets(viewRoot)
} else {
viewRoot.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewDetachedFromWindow(v: View) = Unit
override fun onViewAttachedToWindow(v: View) {
ViewCompat.requestApplyInsets(v)
}
})
}
}
private fun WindowInsetsCompat.asInsets() = Insets.of(
systemWindowInsetLeft,
systemWindowInsetTop,
systemWindowInsetRight,
systemWindowInsetBottom
)
private fun Insets.subtractBy(insets: WindowInsetsCompat) =
WindowInsetsCompat.Builder(insets).setSystemWindowInsets(
Insets.of(
insets.systemWindowInsetLeft - left,
insets.systemWindowInsetTop - top,
insets.systemWindowInsetRight - right,
insets.systemWindowInsetBottom - bottom
)
).build()
}

View File

@@ -24,8 +24,6 @@ abstract class BaseUIFragment<VM : BaseViewModel, Binding : ViewDataBinding> :
override val viewRoot: View get() = binding.root
private val navigation get() = activity.navigation
override fun consumeSystemWindowInsets(insets: Insets) = insets
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startObserveEvents()
@@ -43,6 +41,11 @@ abstract class BaseUIFragment<VM : BaseViewModel, Binding : ViewDataBinding> :
return binding.root
}
override fun onStart() {
super.onStart()
activity.supportActionBar?.subtitle = null
}
override fun onEventDispatched(event: ViewEvent) = when(event) {
is ContextExecutor -> event(requireContext())
is ActivityExecutor -> event(activity)
@@ -65,7 +68,6 @@ abstract class BaseUIFragment<VM : BaseViewModel, Binding : ViewDataBinding> :
return true
}
})
ensureInsets()
}
override fun onResume() {

View File

@@ -18,7 +18,6 @@ import com.topjohnwu.magisk.ktx.inject
import com.topjohnwu.magisk.ui.theme.Theme
import org.xmlpull.v1.XmlPullParser
import java.io.File
import java.io.IOException
import java.io.InputStream
object Config : PreferenceModel, DBConfig {
@@ -159,12 +158,13 @@ object Config : PreferenceModel, DBConfig {
private const val SU_FINGERPRINT = "su_fingerprint"
fun load(pkg: String) {
try {
fun load(pkg: String?) {
// Only try to load prefs when fresh install and a previous package name is set
if (pkg != null && prefs.all.isEmpty()) runCatching {
context.contentResolver.openInputStream(Provider.PREFS_URI(pkg))?.use {
prefs.edit { parsePrefs(it) }
}
} catch (e: IOException) {}
}
prefs.edit {
// Settings migration

View File

@@ -16,8 +16,6 @@ object Const {
const val BOOTCTL_REVISION = "18ab78817087c337ae0edd1ecac38aec49217880"
// Misc
const val ANDROID_MANIFEST = "AndroidManifest.xml"
const val MAGISK_INSTALL_LOG_FILENAME = "magisk_install_log_%s.log"
val USER_ID = Process.myUid() / 100000
object Version {
@@ -27,6 +25,7 @@ object Const {
fun atLeast_20_2() = Info.env.magiskVersionCode >= 20200 || isCanary()
fun atLeast_20_4() = Info.env.magiskVersionCode >= 20400 || isCanary()
fun atLeast_21_0() = Info.env.magiskVersionCode >= 21000 || isCanary()
fun atLeast_21_2() = Info.env.magiskVersionCode >= 21200 || isCanary()
fun isCanary() = Info.env.magiskVersionCode % 100 != 0
}
@@ -38,7 +37,6 @@ object Const {
// notifications
const val MAGISK_UPDATE_NOTIFICATION_ID = 4
const val APK_UPDATE_NOTIFICATION_ID = 5
const val HIDE_MANAGER_NOTIFICATION_ID = 8
const val UPDATE_NOTIFICATION_CHANNEL = "update"
const val PROGRESS_NOTIFICATION_CHANNEL = "progress"
const val CHECK_MAGISK_UPDATE_WORKER_ID = "magisk_update"
@@ -58,7 +56,7 @@ object Const {
object Key {
// intents
const val OPEN_SECTION = "section"
const val HIDDEN_PKG = "hidden_pkg"
const val PREV_PKG = "prev_pkg"
}
object Value {

View File

@@ -48,10 +48,10 @@ open class SplashActivity : Activity() {
// Pre-initialize root shell
Shell.getShell()
val hiddenPackage = intent.getStringExtra(Const.Key.HIDDEN_PKG)
val prevPkg = intent.getStringExtra(Const.Key.PREV_PKG)
Config.load(hiddenPackage ?: APPLICATION_ID)
handleRepackage(hiddenPackage)
Config.load(prevPkg)
handleRepackage(prevPkg)
Notifications.setup(this)
UpdateCheckService.schedule(this)
Shortcuts.setupDynamic(this)

View File

@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.core.download
import android.net.Uri
import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
import kotlinx.parcelize.Parcelize
sealed class Action : Parcelable {

View File

@@ -12,8 +12,8 @@ import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.ktx.cachedFile
import com.topjohnwu.magisk.ktx.get
import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
private fun cachedFile(name: String) = get<Context>().cachedFile(name).apply { delete() }.toUri()
@@ -101,7 +101,6 @@ sealed class Subject : Parcelable {
Action.Download -> Download()
Action.Uninstall -> Uninstall()
Action.EnvFix, is Action.Flash, is Action.Patch -> Internal(config)
else -> throw IllegalArgumentException()
}
}

View File

@@ -2,7 +2,7 @@ package com.topjohnwu.magisk.core.model
import android.os.Parcelable
import com.squareup.moshi.JsonClass
import kotlinx.android.parcel.Parcelize
import kotlinx.parcelize.Parcelize
@JsonClass(generateAdapter = true)
data class UpdateInfo(

View File

@@ -27,13 +27,13 @@ class LocalModule(path: String) : Module() {
val dir = "$PERSIST/$id"
if (enable) {
disableFile.delete()
if (Const.Version.isCanary())
if (Const.Version.atLeast_21_2())
Shell.su("copy_sepolicy_rules").submit()
else
Shell.su("mkdir -p $dir", "cp -af $ruleFile $dir").submit()
} else {
!disableFile.createNewFile()
if (Const.Version.isCanary())
if (Const.Version.atLeast_21_2())
Shell.su("copy_sepolicy_rules").submit()
else
Shell.su("rm -rf $dir").submit()
@@ -45,13 +45,13 @@ class LocalModule(path: String) : Module() {
set(remove) {
if (remove) {
removeFile.createNewFile()
if (Const.Version.isCanary())
if (Const.Version.atLeast_21_2())
Shell.su("copy_sepolicy_rules").submit()
else
Shell.su("rm -rf $PERSIST/$id").submit()
} else {
!removeFile.delete()
if (Const.Version.isCanary())
if (Const.Version.atLeast_21_2())
Shell.su("copy_sepolicy_rules").submit()
else
Shell.su("cp -af $ruleFile $PERSIST/$id").submit()

View File

@@ -7,7 +7,7 @@ import com.topjohnwu.magisk.core.model.ModuleJson
import com.topjohnwu.magisk.data.repository.NetworkService
import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.ktx.legalFilename
import kotlinx.android.parcel.Parcelize
import kotlinx.parcelize.Parcelize
import java.text.DateFormat
import java.util.*

View File

@@ -33,6 +33,7 @@ object HideAPK {
private const val ALPHA = "abcdefghijklmnopqrstuvwxyz"
private const val ALPHADOTS = "$ALPHA....."
private const val APP_NAME = "Magisk Manager"
private const val ANDROID_MANIFEST = "AndroidManifest.xml"
// Some arbitrary limit
const val MAX_LABEL_LENGTH = 32
@@ -71,7 +72,7 @@ object HideAPK {
): Boolean {
try {
val jar = JarMap.open(apk)
val je = jar.getJarEntry(Const.ANDROID_MANIFEST)
val je = jar.getJarEntry(ANDROID_MANIFEST)
val xml = AXML(jar.getRawData(je))
if (!xml.findAndPatch(APPLICATION_ID to pkg, APP_NAME to label.toString()))
@@ -123,6 +124,7 @@ object HideAPK {
Config.suManager = pkg
grantUriPermission(pkg, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
grantUriPermission(pkg, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.putExtra(Const.Key.PREV_PKG, packageName)
startActivity(intent)
}
@@ -167,7 +169,7 @@ object HideAPK {
Config.suManager = ""
grantUriPermission(APPLICATION_ID, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
grantUriPermission(APPLICATION_ID, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.putExtra(Const.Key.HIDDEN_PKG, packageName)
intent.putExtra(Const.Key.PREV_PKG, packageName)
startActivity(intent)
}

View File

@@ -8,8 +8,10 @@ import android.widget.Toast
import androidx.annotation.WorkerThread
import androidx.core.os.postDelayed
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.inputStream
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
@@ -40,6 +42,8 @@ import org.koin.core.inject
import timber.log.Timber
import java.io.*
import java.nio.ByteBuffer
import java.security.SecureRandom
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
@@ -107,6 +111,8 @@ abstract class MagiskInstallImpl : KoinComponent {
}
console.add("- Device platform: " + Build.CPU_ABI)
console.add("- Magisk Manager: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
console.add("- Install target: ${Info.remote.magisk.version} (${Info.remote.magisk.versionCode})")
try {
ZipInputStream(zipUri.inputStream().buffered()).use { zi ->
@@ -185,9 +191,10 @@ abstract class MagiskInstallImpl : KoinComponent {
if (rawData.size < 256)
continue
// Patch flags to AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
// Patch flags to AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED |
// AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED
console.add("-- Patching: vbmeta.img")
ByteBuffer.wrap(rawData).putInt(120, 2)
ByteBuffer.wrap(rawData).putInt(120, 3)
tarOut.putNextEntry(newEntry("vbmeta.img", rawData.size.toLong()))
tarOut.write(rawData)
} else {
@@ -198,7 +205,7 @@ abstract class MagiskInstallImpl : KoinComponent {
}
val boot = SuFile.open(installDir, "boot.img")
val recovery = SuFile.open(installDir, "recovery.img")
if (recovery.exists() && boot.exists()) {
if (Config.recovery && recovery.exists() && boot.exists()) {
// Install Magisk to recovery
srcBoot = recovery.path
// Repack boot image to prevent restore
@@ -225,7 +232,7 @@ abstract class MagiskInstallImpl : KoinComponent {
private fun handleFile(uri: Uri): Boolean {
val outStream: OutputStream
val outFile: MediaStoreUtils.UriFile
var outFile: MediaStoreUtils.UriFile? = null
// Process input file
try {
@@ -237,27 +244,40 @@ abstract class MagiskInstallImpl : KoinComponent {
return false
}
src.reset()
val alpha = "abcdefghijklmnopqrstuvwxyz"
val alphaNum = "$alpha${alpha.toUpperCase(Locale.ROOT)}0123456789"
val random = SecureRandom()
val suffix = StringBuilder()
for (i in 1..5) {
suffix.append(alphaNum[random.nextInt(alphaNum.length)])
}
val filename = "magisk_patched_$suffix"
outStream = if (magic.contentEquals("ustar".toByteArray())) {
outFile = MediaStoreUtils.getFile("magisk_patched.tar")
handleTar(src, outFile.uri.outputStream())
outFile = MediaStoreUtils.getFile("$filename.tar", true)
handleTar(src, outFile!!.uri.outputStream())
} else {
// Raw image
srcBoot = File(installDir, "boot.img").path
console.add("- Copying image to cache")
FileOutputStream(srcBoot).use { src.copyTo(it) }
outFile = MediaStoreUtils.getFile("magisk_patched.img")
outFile.uri.outputStream()
outFile = MediaStoreUtils.getFile("$filename.img", true)
outFile!!.uri.outputStream()
}
}
} catch (e: IOException) {
console.add("! Process error")
outFile?.delete()
Timber.e(e)
return false
}
// Patch file
if (!patchBoot())
if (!patchBoot()) {
outFile!!.delete()
return false
}
// Output file
try {
@@ -276,6 +296,7 @@ abstract class MagiskInstallImpl : KoinComponent {
console.add("****************************")
} catch (e: IOException) {
console.add("! Failed to output to $outFile")
outFile!!.delete()
Timber.e(e)
return false
}
@@ -325,7 +346,7 @@ abstract class MagiskInstallImpl : KoinComponent {
val signed = File(installDir, "signed.img")
try {
withStreams(SuFileInputStream(patched), signed.outputStream().buffered()) {
input, out -> SignBoot.doSignature("/boot", input, out, null, null)
input, out -> SignBoot.doSignature(null, null, input, out, "/boot")
}
} catch (e: IOException) {
console.add("! Unable to sign image")
@@ -339,6 +360,13 @@ abstract class MagiskInstallImpl : KoinComponent {
return true
}
private fun copySepolicyRules(): Boolean {
if (Info.remote.magisk.versionCode >= 21100) return true
// Copy existing rules for migration
"copy_sepolicy_rules".sh()
return true
}
private fun flashBoot(): Boolean {
if (!"direct_install $installDir $srcBoot".sh().isSuccess)
return false
@@ -373,10 +401,11 @@ abstract class MagiskInstallImpl : KoinComponent {
protected fun doPatchFile(patchFile: Uri) = extractZip() && handleFile(patchFile)
protected fun direct() = findImage() && extractZip() && patchBoot() && flashBoot()
protected fun direct() = findImage() && extractZip() && patchBoot() &&
copySepolicyRules() && flashBoot()
protected suspend fun secondSlot() =
findSecondaryImage() && extractZip() && patchBoot() && flashBoot() && postOTA()
protected suspend fun secondSlot() = findSecondaryImage() && extractZip() &&
patchBoot() && copySepolicyRules() && flashBoot() && postOTA()
protected fun fixEnv(zip: Uri): Boolean {
installDir = SuFile("/data/adb/magisk")

View File

@@ -7,10 +7,12 @@ import android.util.Base64OutputStream
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.signing.CryptoUtils.readCertificate
import com.topjohnwu.signing.CryptoUtils.readPrivateKey
import com.topjohnwu.signing.KeyData
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.math.BigInteger
import java.security.KeyPairGenerator
@@ -58,10 +60,10 @@ class Keygen(context: Context) : CertKeyProvider {
class TestProvider : CertKeyProvider {
override val cert by lazy {
readCertificate(javaClass.getResourceAsStream("/keys/testkey.x509.pem"))
readCertificate(ByteArrayInputStream(KeyData.testCert()))
}
override val key by lazy {
readPrivateKey(javaClass.getResourceAsStream("/keys/testkey.pk8"))
readPrivateKey(ByteArrayInputStream(KeyData.testKey()))
}
}

View File

@@ -1,6 +1,5 @@
package com.topjohnwu.magisk.core.utils
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.ContentUris
import android.content.ContentValues
@@ -40,15 +39,17 @@ object MediaStoreUtils {
private val relativePath get() = relativePath(Config.downloadDir)
@RequiresApi(api = 29)
@RequiresApi(api = 30)
@Throws(IOException::class)
private fun insertFile(displayName: String): MediaStoreFile {
val values = ContentValues()
values.put(MediaStore.MediaColumns.RELATIVE_PATH, relativePath)
values.put(MediaStore.MediaColumns.DISPLAY_NAME, displayName)
// before Android 11, MediaStore can not rename new file when file exists,
// insert will return null. use newFile() instead.
// When a file with the same name exists and was not created by us:
// - Before Android 11, insert will return null
// - On Android 11+, the system will automatically create a new name
// Thus the reason to restrict this method call to API 30+
val fileUri = cr.insert(tableUri, values) ?: throw IOException("Can't insert $displayName.")
val projection = arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA)
@@ -65,14 +66,8 @@ object MediaStoreUtils {
throw IOException("Can't insert $displayName.")
}
@RequiresApi(api = 29)
private fun queryFile(displayName: String): UriFile? {
if (Build.VERSION.SDK_INT < 30) {
// Fallback to file based I/O pre Android 11
val parent = File(Environment.getExternalStorageDirectory(), relativePath)
parent.mkdirs()
return LegacyUriFile(File(parent, displayName))
}
val projection = arrayOf(MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATA)
// Before Android 10, we wrote the DISPLAY_NAME field when insert, so it can be used.
val selection = "${MediaStore.MediaColumns.DISPLAY_NAME} == ?"
@@ -92,11 +87,17 @@ object MediaStoreUtils {
return null
}
@SuppressLint("NewApi")
@Throws(IOException::class)
fun getFile(displayName: String): UriFile {
return queryFile(displayName) ?:
/* this code path will never happen pre 29 */ insertFile(displayName)
fun getFile(displayName: String, skipQuery: Boolean = false): UriFile {
if (Build.VERSION.SDK_INT < 30) {
// Fallback to file based I/O pre Android 11
val parent = File(Environment.getExternalStorageDirectory(), relativePath)
parent.mkdirs()
return LegacyUriFile(File(parent, displayName))
}
return if (skipQuery) insertFile(displayName)
else queryFile(displayName) ?: insertFile(displayName)
}
fun Uri.inputStream() = cr.openInputStream(this) ?: throw FileNotFoundException()

View File

@@ -29,6 +29,6 @@ val viewModelModules = module {
viewModel { MainViewModel() }
// Legacy
viewModel { (args: FlashFragmentArgs) -> FlashViewModel(args, get()) }
viewModel { (args: FlashFragmentArgs) -> FlashViewModel(args) }
viewModel { SuRequestViewModel(get(), get(), get(SUTimeout), get()) }
}

View File

@@ -0,0 +1,193 @@
@file:Suppress("unused")
package com.topjohnwu.magisk.ktx
import android.graphics.Canvas
import android.graphics.Rect
import android.view.View
import android.widget.EdgeEffect
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.R
fun RecyclerView.addInvalidateItemDecorationsObserver() {
adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
invalidateItemDecorations()
}
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
invalidateItemDecorations()
}
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
invalidateItemDecorations()
}
})
}
fun RecyclerView.addVerticalPadding(paddingTop: Int = 0, paddingBottom: Int = 0) {
addItemDecoration(VerticalPaddingDecoration(paddingTop, paddingBottom))
}
private class VerticalPaddingDecoration(private val paddingTop: Int = 0, private val paddingBottom: Int = 0) : RecyclerView.ItemDecoration() {
private var allowTop: Boolean = true
private var allowBottom: Boolean = true
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val adapter = parent.adapter ?: return
val position = parent.getChildAdapterPosition(view)
val count = adapter.itemCount
if (position == 0 && allowTop) {
outRect.top = paddingTop
} else if (position == count - 1 && allowBottom) {
outRect.bottom = paddingBottom
}
}
}
fun RecyclerView.addSimpleItemDecoration(
left: Int = 0,
top: Int = 0,
right: Int = 0,
bottom: Int = 0,
) {
addItemDecoration(SimpleItemDecoration(left, top, right, bottom))
}
private class SimpleItemDecoration(
private val left: Int = 0,
private val top: Int = 0,
private val right: Int = 0,
private val bottom: Int = 0
) : RecyclerView.ItemDecoration() {
private var allowLeft: Boolean = true
private var allowTop: Boolean = true
private var allowRight: Boolean = true
private var allowBottom: Boolean = true
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
if (parent.adapter == null) {
return
}
if (allowLeft) {
outRect.left = left
}
if (allowTop) {
outRect.top = top
}
if (allowRight) {
outRect.right = right
}
if (allowBottom) {
outRect.top = bottom
}
}
}
fun RecyclerView.fixEdgeEffect(overScrollIfContentScrolls: Boolean = true, alwaysClipToPadding: Boolean = true) {
if (overScrollIfContentScrolls) {
val listener = OverScrollIfContentScrollsListener()
addOnLayoutChangeListener(listener)
setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, listener)
} else {
val listener = getTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener) as? OverScrollIfContentScrollsListener
if (listener != null) {
removeOnLayoutChangeListener(listener)
setTag(R.id.tag_rikka_recyclerView_OverScrollIfContentScrollsListener, null)
}
}
edgeEffectFactory = if (alwaysClipToPadding && !clipToPadding) {
AlwaysClipToPaddingEdgeEffectFactory()
} else {
RecyclerView.EdgeEffectFactory()
}
}
private class OverScrollIfContentScrollsListener : View.OnLayoutChangeListener {
private var show = true
override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
if (shouldDrawOverScroll(v as RecyclerView) != show) {
show = !show
if (show) {
v.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS)
} else {
v.setOverScrollMode(View.OVER_SCROLL_NEVER)
}
}
}
fun shouldDrawOverScroll(recyclerView: RecyclerView): Boolean {
if (recyclerView.layoutManager == null || recyclerView.adapter == null || recyclerView.adapter!!.itemCount == 0) {
return false
}
if (recyclerView.layoutManager is LinearLayoutManager) {
val itemCount = recyclerView.layoutManager!!.itemCount
val firstPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findFirstCompletelyVisibleItemPosition()
val lastPosition: Int = (recyclerView.layoutManager as LinearLayoutManager?)!!.findLastCompletelyVisibleItemPosition()
return firstPosition != 0 || lastPosition != itemCount - 1
}
return true
}
}
private class AlwaysClipToPaddingEdgeEffectFactory : RecyclerView.EdgeEffectFactory() {
override fun createEdgeEffect(view: RecyclerView, direction: Int): EdgeEffect {
return object : EdgeEffect(view.context) {
private var ensureSize = false
private fun ensureSize() {
if (ensureSize) return
ensureSize = true
when (direction) {
DIRECTION_LEFT -> {
setSize(view.measuredHeight - view.paddingTop - view.paddingBottom,
view.measuredWidth - view.paddingLeft - view.paddingRight)
}
DIRECTION_TOP -> {
setSize(view.measuredWidth - view.paddingLeft - view.paddingRight,
view.measuredHeight - view.paddingTop - view.paddingBottom)
}
DIRECTION_RIGHT -> {
setSize(view.measuredHeight - view.paddingTop - view.paddingBottom,
view.measuredWidth - view.paddingLeft - view.paddingRight)
}
DIRECTION_BOTTOM -> {
setSize(view.measuredWidth - view.paddingLeft - view.paddingRight,
view.measuredHeight - view.paddingTop - view.paddingBottom)
}
}
}
override fun draw(c: Canvas): Boolean {
ensureSize()
val restore = c.save()
when (direction) {
DIRECTION_LEFT -> {
c.translate(view.paddingBottom.toFloat(), 0f)
}
DIRECTION_TOP -> {
c.translate(view.paddingLeft.toFloat(), view.paddingTop.toFloat())
}
DIRECTION_RIGHT -> {
c.translate(-view.paddingTop.toFloat(), 0f)
}
DIRECTION_BOTTOM -> {
c.translate(view.paddingRight.toFloat(), view.paddingBottom.toFloat())
}
}
val res = super.draw(c)
c.restoreToCount(restore)
return res
}
}
}
}

View File

@@ -7,9 +7,11 @@ import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.ComponentInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.*
import android.content.pm.ServiceInfo
import android.content.pm.ServiceInfo.FLAG_ISOLATED_PROCESS
import android.content.pm.ServiceInfo.FLAG_USE_APP_ZYGOTE
import android.content.res.Configuration
import android.content.res.Resources
import android.database.Cursor
@@ -57,32 +59,10 @@ import java.lang.reflect.Array as JArray
val packageName: String get() = get<Context>().packageName
val ApplicationInfo.processes: List<String> @SuppressLint("InlinedApi") get() {
val pm = get<PackageManager>()
val appProcessName = processName ?: packageName
val baseFlag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES
val packageInfo = try {
val request = GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS
pm.getPackageInfo(packageName, baseFlag or request)
} catch (e: NameNotFoundException) { // EdXposed hooked, issue#3276
return listOf(appProcessName)
} catch (e: Exception) {
// Exceed binder data transfer limit, fetch each component type separately
pm.getPackageInfo(packageName, baseFlag).apply {
runCatching { activities = pm.getPackageInfo(packageName, GET_ACTIVITIES).activities }
runCatching { services = pm.getPackageInfo(packageName, GET_SERVICES).services }
runCatching { receivers = pm.getPackageInfo(packageName, GET_RECEIVERS).receivers }
runCatching { providers = pm.getPackageInfo(packageName, GET_PROVIDERS).providers }
}
}
fun Array<out ComponentInfo>.processNames() = map { it.processName ?: appProcessName }
return with(packageInfo) {
activities?.processNames().orEmpty() +
services?.processNames().orEmpty() +
receivers?.processNames().orEmpty() +
providers?.processNames().orEmpty()
}
}
val ServiceInfo.isIsolated get() = (flags and FLAG_ISOLATED_PROCESS) != 0
@get:SuppressLint("InlinedApi")
val ServiceInfo.useAppZygote get() = (flags and FLAG_USE_APP_ZYGOTE) != 0
fun Context.rawResource(id: Int) = resources.openRawResource(id)

View File

@@ -10,7 +10,6 @@ import android.view.WindowManager
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.forEach
import androidx.core.view.setPadding
import androidx.core.view.updateLayoutParams
import androidx.navigation.NavDirections
import com.google.android.material.card.MaterialCardView
@@ -26,9 +25,9 @@ import com.topjohnwu.magisk.ui.home.HomeFragmentDirections
import com.topjohnwu.magisk.utils.HideBottomViewOnScrollBehavior
import com.topjohnwu.magisk.utils.HideTopViewOnScrollBehavior
import com.topjohnwu.magisk.utils.HideableBehavior
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.view.MagiskDialog
import com.topjohnwu.magisk.view.Shortcuts
import com.topjohnwu.superuser.Shell
import org.koin.androidx.viewmodel.ext.android.viewModel
class MainViewModel : BaseViewModel()
@@ -39,14 +38,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
override val viewModel by viewModel<MainViewModel>()
override val navHost: Int = R.id.main_nav_host
//This temporarily fixes unwanted feature of BottomNavigationView - where the view applies
//padding on itself given insets are not consumed beforehand. Unfortunately the listener
//implementation doesn't favor us against the design library, so on re-create it's often given
//upper hand.
private val navObserver = ViewTreeObserver.OnGlobalLayoutListener {
binding.mainNavigation.setPadding(0)
}
private var isRootFragment = true
override fun onCreate(savedInstanceState: Bundle?) {
@@ -100,8 +91,6 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
(currentFragment as? ReselectionTarget)?.onReselected()
}
binding.mainNavigation.viewTreeObserver.addOnGlobalLayoutListener(navObserver)
val section = if (intent.action == ACTION_APPLICATION_PREFERENCES) Const.Nav.SETTINGS
else intent.getStringExtra(Const.Key.OPEN_SECTION)
getScreen(section)?.navigate()
@@ -116,16 +105,11 @@ open class MainActivity : BaseUIActivity<MainViewModel, ActivityMainMd2Binding>(
override fun onResume() {
super.onResume()
binding.mainNavigation.menu.apply {
findItem(R.id.superuserFragment)?.isEnabled = Info.env.isActive
findItem(R.id.superuserFragment)?.isEnabled = Utils.showSuperUser()
findItem(R.id.logFragment)?.isEnabled = Info.env.isActive
}
}
override fun onDestroy() {
binding.mainNavigation.viewTreeObserver.removeOnGlobalLayoutListener(navObserver)
super.onDestroy()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> onBackPressed()

View File

@@ -32,6 +32,10 @@ class FlashFragment : BaseUIFragment<FlashViewModel, FragmentFlashMd2Binding>()
super.onStart()
setHasOptionsMenu(true)
activity.setTitle(R.string.flash_screen_title)
viewModel.subtitle.observe(this) {
activity.supportActionBar?.setSubtitle(it)
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {

View File

@@ -1,9 +1,10 @@
package com.topjohnwu.magisk.ui.flash
import android.content.res.Resources
import android.net.Uri
import android.view.MenuItem
import androidx.databinding.Bindable
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
@@ -13,31 +14,28 @@ import com.topjohnwu.magisk.arch.itemBindingOf
import com.topjohnwu.magisk.core.Const
import com.topjohnwu.magisk.core.tasks.FlashZip
import com.topjohnwu.magisk.core.tasks.MagiskInstaller
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.databinding.RvBindingAdapter
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.ktx.*
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.utils.set
import com.topjohnwu.magisk.view.Notifications
import com.topjohnwu.superuser.CallbackList
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class FlashViewModel(
args: FlashFragmentArgs,
private val resources: Resources
args: FlashFragmentArgs
) : BaseViewModel() {
@get:Bindable
var showReboot = Shell.rootAccess()
set(value) = set(value, field, { field = it }, BR.showReboot)
@get:Bindable
var behaviorText = resources.getString(R.string.flashing)
set(value) = set(value, field, { field = it }, BR.behaviorText)
private val _subtitle = MutableLiveData(R.string.flashing)
val subtitle get() = _subtitle as LiveData<Int>
val adapter = RvBindingAdapter<ConsoleItem>()
val items = diffListOf<ConsoleItem>()
@@ -92,9 +90,9 @@ class FlashViewModel(
private fun onResult(success: Boolean) {
state = if (success) State.LOADED else State.LOADING_FAILED
behaviorText = when {
success -> resources.getString(R.string.done)
else -> resources.getString(R.string.failure)
when {
success -> _subtitle.postValue(R.string.done)
else -> _subtitle.postValue(R.string.failure)
}
}
@@ -106,18 +104,16 @@ class FlashViewModel(
}
private fun savePressed() = withExternalRW {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val name = Const.MAGISK_INSTALL_LOG_FILENAME.format(now.toTime(timeFormatStandard))
val file = MediaStoreUtils.getFile(name)
file.uri.outputStream().bufferedWriter().use { writer ->
logItems.forEach {
writer.write(it)
writer.newLine()
}
viewModelScope.launch(Dispatchers.IO) {
val name = "magisk_install_log_%s.log".format(now.toTime(timeFormatStandard))
val file = MediaStoreUtils.getFile(name, true)
file.uri.outputStream().bufferedWriter().use { writer ->
logItems.forEach {
writer.write(it)
writer.newLine()
}
SnackbarEvent(file.toString()).publish()
}
SnackbarEvent(file.toString()).publish()
}
}

View File

@@ -1,47 +0,0 @@
package com.topjohnwu.magisk.ui.hide
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.ktx.getLabel
class HideTarget(line: String) {
val packageName: String
val process: String
init {
val split = line.split(Regex("\\|"), 2)
packageName = split[0]
process = split.getOrElse(1) { packageName }
}
}
class HideAppInfo(info: ApplicationInfo, pm: PackageManager)
: ApplicationInfo(info), Comparable<HideAppInfo> {
val label = info.getLabel(pm)
val iconImage: Drawable = info.loadIcon(pm)
override fun compareTo(other: HideAppInfo) = comparator.compare(this, other)
companion object {
private val comparator = compareBy<HideAppInfo>(
{ it.label.toLowerCase(currentLocale) },
{ it.packageName }
)
}
}
data class HideProcessInfo(
val name: String,
val packageName: String,
val isHidden: Boolean
)
class HideAppTarget(
val info: HideAppInfo,
val processes: List<HideProcessInfo>
) : Comparable<HideAppTarget> {
override fun compareTo(other: HideAppTarget) = compareValuesBy(this, other) { it.info }
}

View File

@@ -12,6 +12,9 @@ import androidx.recyclerview.widget.RecyclerView
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentHideMd2Binding
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
import com.topjohnwu.magisk.ktx.addVerticalPadding
import com.topjohnwu.magisk.ktx.fixEdgeEffect
import com.topjohnwu.magisk.ktx.hideKeyboard
import com.topjohnwu.magisk.utils.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -49,6 +52,21 @@ class HideFragment : BaseUIFragment<HideViewModel, FragmentHideMd2Binding>() {
}
})
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.hideContent.addVerticalPadding(
l_50,
l1 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size)
)
binding.hideContent.addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
binding.hideContent.fixEdgeEffect()
val lama = binding.hideContent.layoutManager ?: return
lama.isAutoMeasureEnabled = false
}

View File

@@ -0,0 +1,105 @@
package com.topjohnwu.magisk.ui.hide
import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
import android.content.pm.ComponentInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.*
import android.content.pm.ServiceInfo
import android.graphics.drawable.Drawable
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.ktx.getLabel
import com.topjohnwu.magisk.ktx.isIsolated
import com.topjohnwu.magisk.ktx.useAppZygote
class CmdlineHiddenItem(line: String) {
val packageName: String
val process: String
init {
val split = line.split(Regex("\\|"), 2)
packageName = split[0]
process = split.getOrElse(1) { packageName }
}
}
const val ISOLATED_MAGIC = "isolated"
@SuppressLint("InlinedApi")
class HideAppInfo(info: ApplicationInfo, pm: PackageManager, hideList: List<CmdlineHiddenItem>)
: ApplicationInfo(info), Comparable<HideAppInfo> {
val label = info.getLabel(pm)
val iconImage: Drawable = info.loadIcon(pm)
val processes = fetchProcesses(pm, hideList)
override fun compareTo(other: HideAppInfo) = comparator.compare(this, other)
private fun fetchProcesses(
pm: PackageManager,
hideList: List<CmdlineHiddenItem>
): List<HideProcessInfo> {
// Fetch full PackageInfo
val baseFlag = MATCH_DISABLED_COMPONENTS or MATCH_UNINSTALLED_PACKAGES
val packageInfo = try {
val request = GET_ACTIVITIES or GET_SERVICES or GET_RECEIVERS or GET_PROVIDERS
pm.getPackageInfo(packageName, baseFlag or request)
} catch (e: NameNotFoundException) {
// EdXposed hooked, issue#3276
return emptyList()
} catch (e: Exception) {
// Exceed binder data transfer limit, fetch each component type separately
pm.getPackageInfo(packageName, baseFlag).apply {
runCatching { activities = pm.getPackageInfo(packageName, baseFlag or GET_ACTIVITIES).activities }
runCatching { services = pm.getPackageInfo(packageName, baseFlag or GET_SERVICES).services }
runCatching { receivers = pm.getPackageInfo(packageName, baseFlag or GET_RECEIVERS).receivers }
runCatching { providers = pm.getPackageInfo(packageName, baseFlag or GET_PROVIDERS).providers }
}
}
val hidden = hideList.filter { it.packageName == packageName || it.packageName == ISOLATED_MAGIC }
fun createProcess(name: String, pkg: String = packageName): HideProcessInfo {
return HideProcessInfo(name, pkg, hidden.any { it.process == name })
}
var haveAppZygote = false
fun Array<out ComponentInfo>.processes() = map { createProcess(it.processName) }
fun Array<ServiceInfo>.processes() = map {
if (it.isIsolated) {
if (it.useAppZygote) {
haveAppZygote = true
// Using app zygote, don't need to track the process
null
} else {
createProcess("${it.processName}:${it.name}", ISOLATED_MAGIC)
}
} else {
createProcess(it.processName)
}
}
return with(packageInfo) {
activities?.processes().orEmpty() +
services?.processes().orEmpty() +
receivers?.processes().orEmpty() +
providers?.processes().orEmpty() +
listOf(if (haveAppZygote) createProcess("${processName}_zygote") else null)
}.filterNotNull().distinctBy { it.name }.sortedBy { it.name }
}
companion object {
private val comparator = compareBy<HideAppInfo>(
{ it.label.toLowerCase(currentLocale) },
{ it.packageName }
)
}
}
data class HideProcessInfo(
val name: String,
val packageName: String,
var isHidden: Boolean
) {
val isIsolated get() = name == ISOLATED_MAGIC
val isAppZygote get() = name.endsWith("_zygote")
}

View File

@@ -12,14 +12,13 @@ import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell
import kotlin.math.roundToInt
class HideItem(
app: HideAppTarget
) : ObservableItem<HideItem>(), Comparable<HideItem> {
class HideRvItem(
val info: HideAppInfo
) : ObservableItem<HideRvItem>(), Comparable<HideRvItem> {
override val layoutRes = R.layout.item_hide_md2
override val layoutRes get() = R.layout.item_hide_md2
val info = app.info
val processes = app.processes.map { HideProcessItem(it) }
val processes = info.processes.map { HideProcessRvItem(it) }
@get:Bindable
var isExpanded = false
@@ -41,11 +40,10 @@ class HideItem(
if (value == true) {
processes
.filterNot { it.isHidden }
.filter { isExpanded || it.process.name == it.process.packageName }
.filter { isExpanded || it.defaultSelection }
} else {
processes
.filter { it.isHidden }
.filter { isExpanded || it.process.name == it.process.packageName }
}.forEach { it.toggle() }
}
@@ -69,14 +67,19 @@ class HideItem(
else -> null
}
} else {
processes.find { it.isHidden && it.process.name == it.process.packageName } != null
val defaultProcesses = processes.filter { it.defaultSelection }
when (defaultProcesses.count { it.isHidden }) {
0 -> false
defaultProcesses.size -> true
else -> null
}
}
}
override fun compareTo(other: HideItem) = comparator.compare(this, other)
override fun compareTo(other: HideRvItem) = comparator.compare(this, other)
companion object {
private val comparator = compareBy<HideItem>(
private val comparator = compareBy<HideRvItem>(
{ it.itemsChecked == 0 },
{ it.info }
)
@@ -84,16 +87,17 @@ class HideItem(
}
class HideProcessItem(
class HideProcessRvItem(
val process: HideProcessInfo
) : ObservableItem<HideProcessItem>() {
) : ObservableItem<HideProcessRvItem>() {
override val layoutRes = R.layout.item_hide_process_md2
override val layoutRes get() = R.layout.item_hide_process_md2
@get:Bindable
var isHidden = process.isHidden
set(value) = set(value, field, { field = it }, BR.hidden) {
val arg = if (isHidden) "add" else "rm"
var isHidden
get() = process.isHidden
set(value) = set(value, process.isHidden, { process.isHidden = it }, BR.hidden) {
val arg = if (it) "add" else "rm"
val (name, pkg) = process
Shell.su("magiskhide --$arg $pkg $name").submit()
}
@@ -102,7 +106,10 @@ class HideProcessItem(
isHidden = !isHidden
}
override fun contentSameAs(other: HideProcessItem) = process == other.process
override fun itemSameAs(other: HideProcessItem) = process.name == other.process.name
val defaultSelection get() =
process.isIsolated || process.isAppZygote || process.name == process.packageName
override fun contentSameAs(other: HideProcessRvItem) = process == other.process
override fun itemSameAs(other: HideProcessRvItem) = process.name == other.process.name
}

View File

@@ -3,6 +3,7 @@ package com.topjohnwu.magisk.ui.hide
import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import android.os.Process
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
@@ -14,7 +15,6 @@ import com.topjohnwu.magisk.arch.itemBindingOf
import com.topjohnwu.magisk.core.Config
import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.ktx.packageName
import com.topjohnwu.magisk.ktx.processes
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell
@@ -45,11 +45,11 @@ class HideViewModel : BaseViewModel(), Queryable {
submitQuery()
}
val items = filterableListOf<HideItem>()
val itemBinding = itemBindingOf<HideItem> {
val items = filterableListOf<HideRvItem>()
val itemBinding = itemBindingOf<HideRvItem> {
it.bindExtra(BR.viewModel, this)
}
val itemInternalBinding = itemBindingOf<HideProcessItem> {
val itemInternalBinding = itemBindingOf<HideProcessRvItem> {
it.bindExtra(BR.viewModel, this)
}
@@ -62,14 +62,13 @@ class HideViewModel : BaseViewModel(), Queryable {
state = State.LOADING
val (apps, diff) = withContext(Dispatchers.Default) {
val pm = get<PackageManager>()
val hides = Shell.su("magiskhide --ls").exec().out.map { HideTarget(it) }
val apps = pm.getInstalledApplications(PackageManager.MATCH_UNINSTALLED_PACKAGES)
val hideList = Shell.su("magiskhide --ls").exec().out.map { CmdlineHiddenItem(it) }
val apps = pm.getInstalledApplications(MATCH_UNINSTALLED_PACKAGES)
.asSequence()
.filter { it.enabled && !blacklist.contains(it.packageName) }
.map { HideAppInfo(it, pm) }
.map { createTarget(it, hides) }
.map { HideAppInfo(it, pm, hideList) }
.filter { it.processes.isNotEmpty() }
.map { HideItem(it) }
.map { HideRvItem(it) }
.toList()
.sorted()
apps to items.calculateDiff(apps)
@@ -80,18 +79,6 @@ class HideViewModel : BaseViewModel(), Queryable {
// ---
private fun createTarget(info: HideAppInfo, hideList: List<HideTarget>): HideAppTarget {
val pkg = info.packageName
val hidden = hideList.filter { it.packageName == pkg }
val processNames = info.processes.distinct()
val processes = processNames.map { name ->
HideProcessInfo(name, pkg, hidden.any { name == it.process })
}
return HideAppTarget(info, processes)
}
// ---
override fun query() {
items.filter {
fun showHidden() = it.itemsChecked != 0

View File

@@ -1,6 +1,5 @@
package com.topjohnwu.magisk.ui.home
import android.os.Build
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BuildConfig
@@ -68,8 +67,7 @@ class HomeViewModel(
set(value) = set(value, field, { field = it }, BR.stateManagerProgress)
@get:Bindable
val showUninstall get() =
Info.env.magiskVersionCode > 0 && stateMagisk != MagiskState.LOADING && isConnected.get()
val showUninstall get() = Info.env.isActive && state != State.LOADING
@get:Bindable
val showSafetyNet get() = Info.hasGMS && isConnected.get()
@@ -82,8 +80,6 @@ class HomeViewModel(
override fun refresh() = viewModelScope.launch {
state = State.LOADING
notifyPropertyChanged(BR.showUninstall)
notifyPropertyChanged(BR.showSafetyNet)
svc.fetchUpdate()?.apply {
state = State.LOADED
stateMagisk = when {
@@ -93,7 +89,6 @@ class HomeViewModel(
}
stateManager = when {
!app.isUpdateChannelCorrect && isConnected.get() -> MagiskState.NOT_INSTALLED
app.isObsolete -> MagiskState.OBSOLETE
else -> MagiskState.UP_TO_DATE
}
@@ -107,6 +102,8 @@ class HomeViewModel(
ensureEnv()
}
} ?: apply { state = State.LOADING_FAILED }
notifyPropertyChanged(BR.showUninstall)
notifyPropertyChanged(BR.showSafetyNet)
}
val showTest = false
@@ -127,14 +124,18 @@ class HomeViewModel(
fun onDeletePressed() = UninstallDialog().publish()
fun onManagerPressed() =
if (isConnected.get()) ManagerInstallDialog().publish()
else SnackbarEvent(R.string.no_connection).publish()
fun onManagerPressed() = when (state) {
State.LOADED -> ManagerInstallDialog().publish()
State.LOADING -> SnackbarEvent(R.string.loading).publish()
else -> SnackbarEvent(R.string.no_connection).publish()
}
fun onMagiskPressed() = if (isConnected.get()) withExternalRW {
HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish()
} else {
SnackbarEvent(R.string.no_connection).publish()
fun onMagiskPressed() = when (state) {
State.LOADED -> withExternalRW {
HomeFragmentDirections.actionHomeFragmentToInstallFragment().publish()
}
State.LOADING -> SnackbarEvent(R.string.loading).publish()
else -> SnackbarEvent(R.string.no_connection).publish()
}
fun onSafetyNetPressed() =
@@ -150,17 +151,7 @@ class HomeViewModel(
MagiskState.NOT_INSTALLED,
MagiskState.LOADING
)
// Don't bother checking env when magisk is not installed, loading or already has been shown
if (
invalidStates.any { it == stateMagisk } ||
shownDialog ||
// don't care for emulators either
Build.DEVICE.orEmpty().contains("generic") ||
Build.PRODUCT.orEmpty().contains("generic")
) {
return
}
if (invalidStates.any { it == stateMagisk } || shownDialog) return
val result = Shell.su("env_check").await()
if (!result.isSuccess) {
@@ -171,8 +162,6 @@ class HomeViewModel(
private val MagiskJson.isObsolete
get() = Info.env.isActive && Info.env.magiskVersionCode < versionCode
private val ManagerJson.isUpdateChannelCorrect
get() = versionCode > 0
private val ManagerJson.isObsolete
get() = BuildConfig.VERSION_CODE < versionCode

View File

@@ -0,0 +1,88 @@
package com.topjohnwu.magisk.ui.inflater
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.view.InflateException
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.app.AppCompatDelegate
import androidx.collection.SimpleArrayMap
import java.lang.reflect.Constructor
open class LayoutInflaterFactory(private val delegate: AppCompatDelegate) : LayoutInflater.Factory2 {
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
return onCreateView(null, name, context, attrs)
}
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
val view = delegate.createView(parent, name, context, attrs)
?: LayoutInflaterFactoryDefaultImpl.createViewFromTag(context, name, attrs)
onViewCreated(view, parent, name, context, attrs)
return view
}
open fun onViewCreated(view: View?, parent: View?, name: String, context: Context, attrs: AttributeSet) {
if (view == null) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WindowInsetsHelper.attach(view, attrs)
}
}
}
private object LayoutInflaterFactoryDefaultImpl {
private val constructorSignature = arrayOf(
Context::class.java, AttributeSet::class.java)
private val classPrefixList = arrayOf(
"android.widget.",
"android.view.",
"android.webkit."
)
private val constructorMap = SimpleArrayMap<String, Constructor<out View?>>()
fun createViewFromTag(context: Context, name: String, attrs: AttributeSet): View? {
var name = name
if (name == "view") {
name = attrs.getAttributeValue(null, "class")
}
return try {
if (-1 == name.indexOf('.')) {
for (prefix in classPrefixList) {
val view: View? = createViewByPrefix(context, name, attrs, prefix)
if (view != null) {
return view
}
}
null
} else {
createViewByPrefix(context, name, attrs, null)
}
} catch (e: Exception) {
null
}
}
@Throws(ClassNotFoundException::class, InflateException::class)
private fun createViewByPrefix(context: Context, name: String, attrs: AttributeSet, prefix: String?): View? {
var constructor = constructorMap[name]
return try {
if (constructor == null) { // Class not found in the cache, see if it's real, and try to add it
val clazz = Class.forName(
if (prefix != null) prefix + name else name,
false,
context.classLoader).asSubclass(View::class.java)
constructor = clazz.getConstructor(*constructorSignature)
constructorMap.put(name, constructor)
}
constructor!!.isAccessible = true
constructor.newInstance(context, attrs)
} catch (e: Exception) {
null
}
}
}

View File

@@ -0,0 +1,284 @@
@file:Suppress("unused")
package com.topjohnwu.magisk.ui.inflater
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.graphics.Rect
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity.*
import android.view.View
import android.view.ViewGroup
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.topjohnwu.magisk.R
private typealias ApplyInsetsCallback<T> = (insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) -> T
private class ApplyInsets(private val out: Rect) : ApplyInsetsCallback<Unit> {
override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean) {
out.left += if (left) insets.left else 0
out.top += if (top) insets.top else 0
out.right += if (right) insets.right else 0
out.bottom += if (bottom) insets.bottom else 0
}
}
private class ConsumeInsets : ApplyInsetsCallback<Insets> {
override fun invoke(insets: Insets, left: Boolean, top: Boolean, right: Boolean, bottom: Boolean): Insets {
val insetsLeft = if (left) 0 else insets.left
val insetsTop = if (top) 0 else insets.top
val insetsRight = if (right) 0 else insets.right
val insetsBottom = if (bottom) 0 else insets.bottom
return Insets.of(insetsLeft, insetsTop, insetsRight, insetsBottom)
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
open class WindowInsetsHelper private constructor(
private val view: View,
private val fitSystemWindows: Int,
private val layout_fitsSystemWindowsInsets: Int,
private val consumeSystemWindows: Int) : OnApplyWindowInsetsListener {
internal var initialPaddingLeft: Int = view.paddingLeft
internal var initialPaddingTop: Int = view.paddingTop
internal var initialPaddingRight: Int = view.paddingRight
internal var initialPaddingBottom: Int = view.paddingBottom
private var initialMargin = false
internal var initialMarginLeft: Int = 0
internal var initialMarginTop: Int = 0
internal var initialMarginRight: Int = 0
internal var initialMarginBottom: Int = 0
internal var initialMarginStart: Int = 0
internal var initialMarginEnd: Int = 0
private var lastInsets: WindowInsetsCompat? = null
open fun setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) {
initialPaddingLeft = left
initialPaddingTop = top
initialPaddingRight = right
initialPaddingBottom = bottom
lastInsets?.let { applyWindowInsets(it) }
}
open fun setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL
if (isRTL) {
setInitialPadding(start, top, end, bottom)
} else {
setInitialPadding(start, top, end, bottom)
}
}
open fun setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) {
initialPaddingLeft = left
initialPaddingTop = top
initialPaddingRight = right
initialPaddingBottom = bottom
lastInsets?.let { applyWindowInsets(it) }
}
open fun setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) {
initialMarginStart = start
initialMarginTop = top
initialMarginEnd = end
initialMarginBottom = bottom
lastInsets?.let { applyWindowInsets(it) }
}
@SuppressLint("RtlHardcoded")
private fun <T> applyInsets(insets: Insets, fit: Int, callback: ApplyInsetsCallback<T>): T {
val relativeMode = (fit and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION
val isRTL = view.layoutDirection == View.LAYOUT_DIRECTION_RTL
val left: Boolean
val top = fit and TOP == TOP
val right: Boolean
val bottom = fit and BOTTOM == BOTTOM
if (relativeMode) {
val start = fit and START == START
val end = fit and END == END
left = (!isRTL && start) || (isRTL && end)
right = (!isRTL && end) || (isRTL && start)
} else {
left = fit and LEFT == LEFT
right = fit and RIGHT == RIGHT
}
return callback.invoke(insets, left, top, right, bottom)
}
private fun applyWindowInsets(windowInsets: WindowInsetsCompat): WindowInsetsCompat {
if (fitSystemWindows != 0) {
val padding = Rect(initialPaddingLeft, initialPaddingTop, initialPaddingRight, initialPaddingBottom)
applyInsets(windowInsets.systemWindowInsets, fitSystemWindows, ApplyInsets(padding))
view.setPadding(padding.left, padding.top, padding.right, padding.bottom)
}
if (layout_fitsSystemWindowsInsets != 0) {
if (!initialMargin) {
initialMarginLeft = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.leftMargin ?: 0
initialMarginTop = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.topMargin ?: 0
initialMarginRight = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.rightMargin ?: 0
initialMarginBottom = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin ?: 0
initialMarginStart = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginStart ?: 0
initialMarginEnd = (view.layoutParams as? ViewGroup.MarginLayoutParams)?.marginEnd ?: 0
initialMargin = true
}
val margin = if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION)
Rect(initialMarginLeft, initialMarginTop, initialMarginRight, initialMarginBottom)
else
Rect(initialMarginStart, initialMarginTop, initialMarginEnd, initialMarginBottom)
applyInsets(windowInsets.systemWindowInsets, layout_fitsSystemWindowsInsets, ApplyInsets(margin))
val lp = view.layoutParams
if (lp is ViewGroup.MarginLayoutParams) {
lp.topMargin = margin.top
lp.bottomMargin = margin.bottom
if ((layout_fitsSystemWindowsInsets and RELATIVE_LAYOUT_DIRECTION) == RELATIVE_LAYOUT_DIRECTION) {
lp.marginStart = margin.left
lp.marginEnd = margin.right
} else {
lp.leftMargin = margin.left
lp.rightMargin = margin.right
}
view.layoutParams = lp
}
}
val systemWindowInsets = if (consumeSystemWindows != 0) applyInsets(windowInsets.systemWindowInsets, consumeSystemWindows, ConsumeInsets()) else windowInsets.systemWindowInsets
return WindowInsetsCompat.Builder(windowInsets)
.setSystemWindowInsets(systemWindowInsets)
.build()
}
override fun onApplyWindowInsets(view: View, insets: WindowInsetsCompat): WindowInsetsCompat {
if (lastInsets == insets) {
return insets
}
lastInsets = insets
return applyWindowInsets(insets)
}
companion object {
@JvmStatic
fun attach(view: View, attrs: AttributeSet) {
val a = view.context.obtainStyledAttributes(attrs, R.styleable.WindowInsetsHelper, 0, 0)
val edgeToEdge = a.getBoolean(R.styleable.WindowInsetsHelper_edgeToEdge, false)
val fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_fitsSystemWindowsInsets, 0)
val layout_fitsSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_layout_fitsSystemWindowsInsets, 0)
val consumeSystemWindowsInsets = a.getInt(R.styleable.WindowInsetsHelper_consumeSystemWindowsInsets, 0)
a.recycle()
attach(view, edgeToEdge, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets)
}
@JvmStatic
fun attach(view: View, edgeToEdge: Boolean, fitsSystemWindowsInsets: Int, layout_fitsSystemWindowsInsets: Int, consumeSystemWindowsInsets: Int) {
if (edgeToEdge) {
view.systemUiVisibility = (view.systemUiVisibility
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
}
if (fitsSystemWindowsInsets == 0 && layout_fitsSystemWindowsInsets == 0 && consumeSystemWindowsInsets == 0) {
return
}
val listener = WindowInsetsHelper(view, fitsSystemWindowsInsets, layout_fitsSystemWindowsInsets, consumeSystemWindowsInsets)
ViewCompat.setOnApplyWindowInsetsListener(view, listener)
view.setTag(R.id.tag_rikka_material_WindowInsetsHelper, listener)
if (!view.isAttachedToWindow) {
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
v.removeOnAttachStateChangeListener(this)
v.requestApplyInsets()
}
override fun onViewDetachedFromWindow(v: View) = Unit
})
}
}
}
}
val View.windowInsetsHelper: WindowInsetsHelper?
get() {
val value = getTag(R.id.tag_rikka_material_WindowInsetsHelper)
return if (value is WindowInsetsHelper) value else null
}
val View.initialPaddingLeft: Int
get() = windowInsetsHelper?.initialPaddingLeft ?: 0
val View.initialPaddingTop: Int
get() = windowInsetsHelper?.initialPaddingTop ?: 0
val View.initialPaddingRight: Int
get() = windowInsetsHelper?.initialPaddingRight ?: 0
val View.initialPaddingBottom: Int
get() = windowInsetsHelper?.initialPaddingBottom ?: 0
val View.initialPaddingStart: Int
get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingRight else initialPaddingLeft
val View.initialPaddingEnd: Int
get() = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) initialPaddingLeft else initialPaddingRight
fun View.setInitialPadding(left: Int, top: Int, right: Int, bottom: Int) {
windowInsetsHelper?.setInitialPadding(left, top, right, bottom)
}
fun View.setInitialPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
windowInsetsHelper?.setInitialPaddingRelative(start, top, end, bottom)
}
val View.initialMarginLeft: Int
get() = windowInsetsHelper?.initialMarginLeft ?: 0
val View.initialMarginTop: Int
get() = windowInsetsHelper?.initialMarginTop ?: 0
val View.initialMarginRight: Int
get() = windowInsetsHelper?.initialMarginRight ?: 0
val View.initialMarginBottom: Int
get() = windowInsetsHelper?.initialMarginBottom ?: 0
val View.initialMarginStart: Int
get() = windowInsetsHelper?.initialMarginStart ?: 0
val View.initialMarginEnd: Int
get() = windowInsetsHelper?.initialMarginEnd ?: 0
fun View.setInitialMargin(left: Int, top: Int, right: Int, bottom: Int) {
windowInsetsHelper?.setInitialMargin(left, top, right, bottom)
}
fun View.setInitialMarginRelative(start: Int, top: Int, end: Int, bottom: Int) {
windowInsetsHelper?.setInitialMarginRelative(start, top, end, bottom)
}

View File

@@ -9,6 +9,9 @@ import androidx.core.view.isVisible
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentLogMd2Binding
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
import com.topjohnwu.magisk.ktx.addVerticalPadding
import com.topjohnwu.magisk.ktx.fixEdgeEffect
import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.utils.MotionRevealHelper
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -42,6 +45,21 @@ class LogFragment : BaseUIFragment<LogViewModel, FragmentLogMd2Binding>() {
binding.logFilterToggle.setOnClickListener {
isMagiskLogVisible = true
}
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.logFilterSuperuser.logSuperuser.addVerticalPadding(
0,
l1
)
binding.logFilterSuperuser.logSuperuser.addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
binding.logFilterSuperuser.logSuperuser.fixEdgeEffect()
}

View File

@@ -3,20 +3,24 @@ package com.topjohnwu.magisk.ui.log
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.arch.diffListOf
import com.topjohnwu.magisk.arch.itemBindingOf
import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.utils.MediaStoreUtils
import com.topjohnwu.magisk.core.utils.MediaStoreUtils.outputStream
import com.topjohnwu.magisk.data.repository.LogRepository
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.ktx.now
import com.topjohnwu.magisk.ktx.timeFormatStandard
import com.topjohnwu.magisk.ktx.toTime
import com.topjohnwu.magisk.utils.set
import com.topjohnwu.magisk.view.TextItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.*
class LogViewModel(
private val repo: LogRepository
@@ -54,14 +58,23 @@ class LogViewModel(
fun saveMagiskLog() = withExternalRW {
viewModelScope.launch(Dispatchers.IO) {
val now = Calendar.getInstance()
val filename = "magisk_log_%04d%02d%02d_%02d%02d%02d.log".format(
now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1,
now.get(Calendar.DAY_OF_MONTH), now.get(Calendar.HOUR_OF_DAY),
now.get(Calendar.MINUTE), now.get(Calendar.SECOND)
)
val logFile = MediaStoreUtils.getFile(filename)
logFile.uri.outputStream().writer().use { it.write(consoleText) }
val filename = "magisk_log_%s.log".format(now.toTime(timeFormatStandard))
val logFile = MediaStoreUtils.getFile(filename, true)
logFile.uri.outputStream().bufferedWriter().use { file ->
file.write("---System Properties---\n\n")
ProcessBuilder("getprop").start()
.inputStream.reader().use { it.copyTo(file) }
file.write("\n---Magisk Logs---\n")
file.write("${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})\n\n")
file.write(consoleText)
file.write("\n---Manager Logs---\n")
file.write("${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})\n\n")
ProcessBuilder("logcat", "-d").start()
.inputStream.reader().use { it.copyTo(file) }
}
SnackbarEvent(logFile.toString()).publish()
}
}

View File

@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.arch.ReselectionTarget
import com.topjohnwu.magisk.arch.ViewEvent
import com.topjohnwu.magisk.core.download.BaseDownloader
import com.topjohnwu.magisk.databinding.FragmentModuleMd2Binding
import com.topjohnwu.magisk.ktx.hideKeyboard
import com.topjohnwu.magisk.ktx.*
import com.topjohnwu.magisk.ui.MainActivity
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import com.topjohnwu.magisk.utils.MotionRevealHelper
@@ -62,6 +62,40 @@ class ModuleFragment : BaseUIFragment<ModuleViewModel, FragmentModuleMd2Binding>
if (newState != RecyclerView.SCROLL_STATE_IDLE) hideKeyboard()
}
})
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.moduleList.apply {
addVerticalPadding(
l_50,
l1 + l_50 + resource.getDimensionPixelSize(R.dimen.internal_action_bar_size)
)
addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
fixEdgeEffect()
post {
addInvalidateItemDecorationsObserver()
}
}
binding.moduleFilterInclude.moduleFilterList.apply {
addVerticalPadding(
l_50,
l_50
)
addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
fixEdgeEffect()
}
}
override fun onDestroyView() {

View File

@@ -158,7 +158,7 @@ sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() {
runCatching { getStringArray(id) }.getOrDefault(emptyArray())
override fun onPressed(view: View, callback: Callback) {
if (entries.isEmpty() || entryValues.isEmpty()) return
if (entries.isEmpty()) return
super.onPressed(view, callback)
}

View File

@@ -5,6 +5,9 @@ import android.view.View
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentSettingsMd2Binding
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
import com.topjohnwu.magisk.ktx.addVerticalPadding
import com.topjohnwu.magisk.ktx.fixEdgeEffect
import com.topjohnwu.magisk.ktx.setOnViewReadyListener
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -24,6 +27,21 @@ class SettingsFragment : BaseUIFragment<SettingsViewModel, FragmentSettingsMd2Bi
binding.settingsList.setOnViewReadyListener {
binding.settingsList.scrollToPosition(0)
}
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.settingsList.addVerticalPadding(
0,
l1
)
binding.settingsList.addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
binding.settingsList.fixEdgeEffect()
}
override fun onResume() {

View File

@@ -20,6 +20,7 @@ import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.utils.TransitiveText
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.asTransitive
import com.topjohnwu.magisk.utils.set
@@ -143,11 +144,12 @@ object UpdateChannel : BaseSettingsItem.Selector() {
set(value) = setV(value, field, { field = it }) { Config.updateChannel = it }
override val title = R.string.settings_update_channel_title.asTransitive()
override val entries
get() = resources.getStringArray(R.array.update_channel).let {
if (BuildConfig.DEBUG) it.toMutableList().apply { add("Canary") }.toTypedArray() else it
}
override val entryValRes = R.array.value_array
override val entries: Array<String> = resources.getStringArray(R.array.update_channel).let {
if (BuildConfig.DEBUG) it.toMutableList().apply { add("Canary") }.toTypedArray() else it
}
override val description
get() = entries.getOrNull(value)?.asTransitive()
?: TransitiveText.String(if (value == -1) entries[0] else "Canary")
}
object UpdateChannelUrl : BaseSettingsItem.Input() {
@@ -256,22 +258,20 @@ object Superuser : BaseSettingsItem.Section() {
object AccessMode : BaseSettingsItem.Selector() {
override val title = R.string.superuser_access.asTransitive()
override val entryRes = R.array.su_access
override val entryValRes = R.array.value_array
override var value = Config.rootMode
set(value) = setV(value, field, { field = it }) {
Config.rootMode = entryValues[it].toInt()
Config.rootMode = it
}
}
object MultiuserMode : BaseSettingsItem.Selector() {
override val title = R.string.multiuser_mode.asTransitive()
override val entryRes = R.array.multiuser_mode
override val entryValRes = R.array.value_array
override var value = Config.suMultiuserMode
set(value) = setV(value, field, { field = it }) {
Config.suMultiuserMode = entryValues[it].toInt()
Config.suMultiuserMode = it
}
override val description
@@ -285,11 +285,10 @@ object MultiuserMode : BaseSettingsItem.Selector() {
object MountNamespaceMode : BaseSettingsItem.Selector() {
override val title = R.string.mount_namespace_mode.asTransitive()
override val entryRes = R.array.namespace
override val entryValRes = R.array.value_array
override var value = Config.suMntNamespaceMode
set(value) = setV(value, field, { field = it }) {
Config.suMntNamespaceMode = entryValues[it].toInt()
Config.suMntNamespaceMode = it
}
override val description
@@ -299,11 +298,10 @@ object MountNamespaceMode : BaseSettingsItem.Selector() {
object AutomaticResponse : BaseSettingsItem.Selector() {
override val title = R.string.auto_response.asTransitive()
override val entryRes = R.array.auto_response
override val entryValRes = R.array.value_array
override var value = Config.suAutoResponse
set(value) = setV(value, field, { field = it }) {
Config.suAutoResponse = entryValues[it].toInt()
Config.suAutoResponse = it
}
}
@@ -324,10 +322,9 @@ object RequestTimeout : BaseSettingsItem.Selector() {
object SUNotification : BaseSettingsItem.Selector() {
override val title = R.string.superuser_notification.asTransitive()
override val entryRes = R.array.su_notification
override val entryValRes = R.array.value_array
override var value = Config.suNotification
set(value) = setV(value, field, { field = it }) {
Config.suNotification = entryValues[it].toInt()
Config.suNotification = it
}
}

View File

@@ -1,8 +1,13 @@
package com.topjohnwu.magisk.ui.superuser
import android.os.Bundle
import android.view.View
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentSuperuserMd2Binding
import com.topjohnwu.magisk.ktx.addSimpleItemDecoration
import com.topjohnwu.magisk.ktx.addVerticalPadding
import com.topjohnwu.magisk.ktx.fixEdgeEffect
import org.koin.androidx.viewmodel.ext.android.viewModel
class SuperuserFragment : BaseUIFragment<SuperuserViewModel, FragmentSuperuserMd2Binding>() {
@@ -15,6 +20,25 @@ class SuperuserFragment : BaseUIFragment<SuperuserViewModel, FragmentSuperuserMd
activity.title = resources.getString(R.string.superuser)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val resource = requireContext().resources
val l_50 = resource.getDimensionPixelSize(R.dimen.l_50)
val l1 = resource.getDimensionPixelSize(R.dimen.l1)
binding.superuserList.addVerticalPadding(
l_50,
l1
)
binding.superuserList.addSimpleItemDecoration(
left = l1,
top = l_50,
right = l1,
bottom = l_50,
)
binding.superuserList.fixEdgeEffect()
}
override fun onPreBind(binding: FragmentSuperuserMd2Binding) {}
}

View File

@@ -2,25 +2,24 @@ package com.topjohnwu.magisk.view
import android.content.Context
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.graphics.drawable.InsetDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatDialog
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.ViewCompat
import androidx.core.view.updatePadding
import androidx.databinding.Bindable
import androidx.databinding.PropertyChangeRegistry
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.google.android.material.shape.MaterialShapeDrawable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.itemBindingOf
@@ -47,36 +46,22 @@ class MagiskDialog(
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
super.setContentView(binding.root)
val surfaceColor = MaterialColors.getColor(context, R.attr.colorSurfaceSurfaceVariant, javaClass.canonicalName)
val materialShapeDrawable = MaterialShapeDrawable(context, null, R.attr.alertDialogStyle, R.style.MaterialAlertDialog_MaterialComponents)
materialShapeDrawable.initializeElevationOverlay(context)
materialShapeDrawable.fillColor = ColorStateList.valueOf(surfaceColor)
materialShapeDrawable.elevation = context.resources.getDimension(R.dimen.margin_generic)
materialShapeDrawable.setCornerSize(context.resources.getDimension(R.dimen.l_50))
val inset = context.resources.getDimensionPixelSize(R.dimen.appcompat_dialog_background_inset)
window?.apply {
setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT
)
}
val paddingTop = binding.root.paddingTop
val paddingBottom = binding.root.paddingBottom
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { view, insets ->
view.updatePadding(
top = paddingTop + insets.systemWindowInsetTop,
bottom = paddingBottom + insets.systemWindowInsetBottom
)
insets
setBackgroundDrawable(InsetDrawable(materialShapeDrawable, inset, inset, inset, inset))
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
}
override fun setCancelable(flag: Boolean) {
val listener = if (!flag) {
null
} else {
setCanceledOnTouchOutside(true)
View.OnClickListener { dismiss() }
}
binding.dialogBaseOutsideContainer.setOnClickListener(listener)
}
inner class Data: ObservableHost {
inner class Data : ObservableHost {
override var callbacks: PropertyChangeRegistry? = null
@get:Bindable
@@ -88,7 +73,7 @@ class MagiskDialog(
set(value) = set(value, field, { field = it }, BR.title)
@get:Bindable
var message : CharSequence = ""
var message: CharSequence = ""
set(value) = set(value, field, { field = it }, BR.message)
val buttonPositive = Button()
@@ -101,7 +86,7 @@ class MagiskDialog(
POSITIVE, NEUTRAL, NEGATIVE, IDGAF
}
inner class Button: ObservableHost {
inner class Button : ObservableHost {
override var callbacks: PropertyChangeRegistry? = null
@get:Bindable

View File

@@ -1,5 +1,8 @@
package com.topjohnwu.signing;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
@@ -14,6 +17,7 @@ import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -84,8 +88,10 @@ public class SignBoot {
}
}
public static boolean doSignature(String target, InputStream imgIn, OutputStream imgOut,
InputStream cert, InputStream key) {
public static boolean doSignature(
@Nullable X509Certificate cert, @Nullable PrivateKey key,
@NonNull InputStream imgIn, @NonNull OutputStream imgOut, @NonNull String target
) {
try {
PushBackRWStream in = new PushBackRWStream(imgIn, imgOut);
byte[] hdr = new byte[BOOT_IMAGE_HEADER_SIZE_MAXIMUM];
@@ -96,16 +102,16 @@ public class SignBoot {
in.unread(hdr);
BootSignature bootsig = new BootSignature(target, signableSize);
if (cert == null) {
cert = SignBoot.class.getResourceAsStream("/keys/verity.x509.pem");
cert = CryptoUtils.readCertificate(
new ByteArrayInputStream(KeyData.verityCert()));
}
X509Certificate certificate = CryptoUtils.readCertificate(cert);
bootsig.setCertificate(certificate);
bootsig.setCertificate(cert);
if (key == null) {
key = SignBoot.class.getResourceAsStream("/keys/verity.pk8");
key = CryptoUtils.readPrivateKey(
new ByteArrayInputStream(KeyData.verityKey()));
}
PrivateKey privateKey = CryptoUtils.readPrivateKey(key);
byte[] sig = bootsig.sign(privateKey, in, signableSize);
bootsig.setSignature(sig, CryptoUtils.getSignatureAlgorithmIdentifier(privateKey));
byte[] sig = bootsig.sign(key, in, signableSize);
bootsig.setSignature(sig, CryptoUtils.getSignatureAlgorithmIdentifier(key));
byte[] encoded_bootsig = bootsig.getEncoded();
imgOut.write(encoded_bootsig);
imgOut.flush();
@@ -116,7 +122,7 @@ public class SignBoot {
}
}
public static boolean verifySignature(InputStream imgIn, InputStream certIn) {
public static boolean verifySignature(InputStream imgIn, X509Certificate cert) {
try {
// Read the header for size
byte[] hdr = new byte[BOOT_IMAGE_HEADER_SIZE_MAXIMUM];
@@ -142,8 +148,8 @@ public class SignBoot {
}
BootSignature bootsig = new BootSignature(signature);
if (certIn != null) {
bootsig.setCertificate(CryptoUtils.readCertificate(certIn));
if (cert != null) {
bootsig.setCertificate(cert);
}
if (bootsig.verify(rawImg, signableSize)) {
System.err.println("Signature is VALID");
@@ -314,4 +320,46 @@ public class SignBoot {
}
}
public static void main(String[] args) throws Exception {
if (args.length > 0 && "-verify".equals(args[0])) {
X509Certificate cert = null;
if (args.length >= 2) {
// args[1] is the path to a public key certificate
cert = CryptoUtils.readCertificate(new FileInputStream(args[1]));
}
boolean signed = SignBoot.verifySignature(System.in, cert);
System.exit(signed ? 0 : 1);
} else if (args.length > 0 && "-sign".equals(args[0])) {
X509Certificate cert = null;
PrivateKey key = null;
String name = "/boot";
if (args.length >= 3) {
cert = CryptoUtils.readCertificate(new FileInputStream(args[1]));
key = CryptoUtils.readPrivateKey(new FileInputStream(args[2]));
}
if (args.length == 2) {
name = args[1];
} else if (args.length >= 4) {
name = args[3];
}
boolean result = SignBoot.doSignature(cert, key, System.in, System.out, name);
System.exit(result ? 0 : 1);
} else {
System.err.println(
"BootSigner <actions> [args]\n" +
"Input from stdin, output to stdout\n" +
"\n" +
"Actions:\n" +
" -verify [x509.pem]\n" +
" verify image. cert is optional.\n" +
" -sign [x509.pem] [pk8] [name]\n" +
" sign image. name and the cert/key pair are optional.\n" +
" name should be either /boot (default) or /recovery.\n"
);
}
}
}

View File

@@ -17,8 +17,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@{viewModel.insets.left}"
android:paddingRight="@{viewModel.insets.right}"
app:consumeSystemWindowsInsets="start|end"
app:edgeToEdge="true"
app:fitsSystemWindowsInsets="start|end"
tools:ignore="RtlHardcoded">
<androidx.fragment.app.FragmentContainerView
@@ -34,7 +35,7 @@
style="@style/WidgetFoundation.Appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@{viewModel.insets.top}">
app:fitsSystemWindowsInsets="top">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/main_toolbar"
@@ -72,7 +73,9 @@
android:layout_gravity="bottom|center_horizontal"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:layout_marginBottom="@{(int) @dimen/l1 + viewModel.insets.bottom}"
android:layout_marginBottom="@dimen/l1"
android:fitsSystemWindows="false"
app:layout_fitsSystemWindowsInsets="bottom"
tools:layout_marginBottom="64dp">
<com.google.android.material.bottomnavigation.BottomNavigationView
@@ -81,6 +84,9 @@
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:textStyle="bold"
android:fitsSystemWindows="false"
android:paddingBottom="0dp"
app:fitsSystemWindowsInsets="start|end"
app:elevation="0dp"
app:itemHorizontalTranslationEnabled="false"
app:itemIconTint="@color/color_menu_tint"

View File

@@ -12,219 +12,185 @@
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/dialog_base_outside_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_width="match_parent">
<FrameLayout
android:layout_width="0dp"
<androidx.constraintlayout.widget.Guideline
android:id="@+id/dialog_base_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/dialog_base_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="16dp" />
<ImageView
android:id="@+id/dialog_base_icon"
style="@style/WidgetFoundation.Image.Big"
gone="@{data.icon == null}"
android:layout_gravity="center"
android:layout_marginTop="@dimen/l1"
android:src="@{data.icon}"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="400dp">
tools:src="@drawable/ic_delete_md2" />
<com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card.Elevated"
<TextView
android:id="@+id/dialog_base_title"
gone="@{data.title.length == 0}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l1"
android:gravity="center"
android:text="@{data.title}"
android:textAppearance="@style/AppearanceFoundation.Title"
app:layout_constraintEnd_toEndOf="@+id/dialog_base_end"
app:layout_constraintStart_toStartOf="@+id/dialog_base_start"
app:layout_constraintTop_toBottomOf="@+id/dialog_base_icon"
tools:lines="1"
tools:text="@tools:sample/lorem/random" />
<androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l_50"
android:overScrollMode="ifContentScrolls"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_space"
app:layout_constraintEnd_toEndOf="@+id/dialog_base_end"
app:layout_constraintStart_toStartOf="@+id/dialog_base_start"
app:layout_constraintTop_toBottomOf="@+id/dialog_base_title">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
app:cardElevation="@dimen/margin_generic"
app:cardUseCompatPadding="true">
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
<TextView
android:id="@+id/dialog_base_message"
gone="@{data.message.length == 0}"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="match_parent"
android:text="@{data.message}"
android:textAppearance="@style/AppearanceFoundation.Body"
tools:lines="3"
tools:text="@tools:sample/lorem/random" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/dialog_base_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />
<FrameLayout
android:id="@+id/dialog_base_container"
gone="@{data.message.length != 0}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/dialog_base_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="16dp" />
</FrameLayout>
<ImageView
android:id="@+id/dialog_base_icon"
style="@style/WidgetFoundation.Image.Big"
gone="@{data.icon == null}"
android:layout_gravity="center"
android:layout_marginTop="@dimen/l1"
android:src="@{data.icon}"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_delete_md2" />
</androidx.core.widget.NestedScrollView>
<TextView
android:id="@+id/dialog_base_title"
gone="@{data.title.length == 0}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l1"
android:gravity="center"
android:text="@{data.title}"
android:textAppearance="@style/AppearanceFoundation.Title"
app:layout_constraintEnd_toEndOf="@+id/dialog_base_end"
app:layout_constraintStart_toStartOf="@+id/dialog_base_start"
app:layout_constraintTop_toBottomOf="@+id/dialog_base_icon"
tools:lines="1"
tools:text="@tools:sample/lorem/random" />
<Space
android:id="@+id/dialog_base_space"
android:layout_width="wrap_content"
android:layout_height="@dimen/l_50"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_buttons"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.core.widget.NestedScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/l_50"
android:overScrollMode="ifContentScrolls"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_space"
app:layout_constraintEnd_toEndOf="@+id/dialog_base_end"
app:layout_constraintStart_toStartOf="@+id/dialog_base_start"
app:layout_constraintTop_toBottomOf="@+id/dialog_base_title">
<androidx.appcompat.widget.ButtonBarLayout
android:id="@+id/dialog_base_buttons"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="bottom|center_horizontal"
android:layoutDirection="locale"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/dialog_base_button_4"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonIDGAF.icon == 0 &amp;&amp; data.buttonIDGAF.title.length == 0}"
isEnabled="@{data.buttonIDGAF.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonIDGAF.isEnabled()}"
android:focusable="@{data.buttonIDGAF.isEnabled()}"
android:onClick="@{() -> data.buttonIDGAF.clicked()}"
android:text="@{data.buttonIDGAF.title}"
app:icon="@{data.buttonIDGAF.icon}"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<TextView
android:id="@+id/dialog_base_message"
gone="@{data.message.length == 0}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@{data.message}"
android:textAppearance="@style/AppearanceFoundation.Body"
tools:lines="3"
tools:text="@tools:sample/lorem/random" />
<Button
android:id="@+id/dialog_base_button_2"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonNeutral.icon == 0 &amp;&amp; data.buttonNeutral.title.length == 0}"
isEnabled="@{data.buttonNeutral.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonNeutral.isEnabled()}"
android:focusable="@{data.buttonNeutral.isEnabled()}"
android:onClick="@{() -> data.buttonNeutral.clicked()}"
android:text="@{data.buttonNeutral.title}"
app:icon="@{data.buttonNeutral.icon}"
app:iconGravity="textStart"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<FrameLayout
android:id="@+id/dialog_base_container"
gone="@{data.message.length != 0}"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Space
android:id="@+id/spacer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="invisible" />
</FrameLayout>
<Button
android:id="@+id/dialog_base_button_3"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonNegative.icon == 0 &amp;&amp; data.buttonNegative.title.length == 0}"
isEnabled="@{data.buttonNegative.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonNegative.isEnabled()}"
android:focusable="@{data.buttonNegative.isEnabled()}"
android:onClick="@{() -> data.buttonNegative.clicked()}"
android:text="@{data.buttonNegative.title}"
app:icon="@{data.buttonNegative.icon}"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
</androidx.core.widget.NestedScrollView>
<Button
android:id="@+id/dialog_base_button_1"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonPositive.icon == 0 &amp;&amp; data.buttonPositive.title.length == 0}"
isEnabled="@{data.buttonPositive.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonPositive.isEnabled()}"
android:focusable="@{data.buttonPositive.isEnabled()}"
android:onClick="@{() -> data.buttonPositive.clicked()}"
android:text="@{data.buttonPositive.title}"
app:icon="@{data.buttonPositive.icon}"
app:iconGravity="textStart"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<Space
android:id="@+id/dialog_base_space"
android:layout_width="wrap_content"
android:layout_height="@dimen/l_50"
app:layout_constraintBottom_toTopOf="@+id/dialog_base_buttons"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.ButtonBarLayout
android:id="@+id/dialog_base_buttons"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="bottom|center_horizontal"
android:layoutDirection="locale"
android:orientation="horizontal"
android:paddingStart="12dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/dialog_base_button_4"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonIDGAF.icon == 0 &amp;&amp; data.buttonIDGAF.title.length == 0}"
isEnabled="@{data.buttonIDGAF.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonIDGAF.isEnabled()}"
android:filterTouchesWhenObscured="true"
android:focusable="@{data.buttonIDGAF.isEnabled()}"
android:onClick="@{() -> data.buttonIDGAF.clicked()}"
android:text="@{data.buttonIDGAF.title}"
app:icon="@{data.buttonIDGAF.icon}"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<Button
android:id="@+id/dialog_base_button_2"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonNeutral.icon == 0 &amp;&amp; data.buttonNeutral.title.length == 0}"
isEnabled="@{data.buttonNeutral.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonNeutral.isEnabled()}"
android:filterTouchesWhenObscured="true"
android:focusable="@{data.buttonNeutral.isEnabled()}"
android:onClick="@{() -> data.buttonNeutral.clicked()}"
android:text="@{data.buttonNeutral.title}"
app:icon="@{data.buttonNeutral.icon}"
app:iconGravity="textStart"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<Space
android:id="@+id/spacer"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="invisible" />
<Button
android:id="@+id/dialog_base_button_3"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonNegative.icon == 0 &amp;&amp; data.buttonNegative.title.length == 0}"
isEnabled="@{data.buttonNegative.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonNegative.isEnabled()}"
android:filterTouchesWhenObscured="true"
android:focusable="@{data.buttonNegative.isEnabled()}"
android:onClick="@{() -> data.buttonNegative.clicked()}"
android:text="@{data.buttonNegative.title}"
app:icon="@{data.buttonNegative.icon}"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
<Button
android:id="@+id/dialog_base_button_1"
style="@style/WidgetFoundation.Button.Text"
gone="@{data.buttonPositive.icon == 0 &amp;&amp; data.buttonPositive.title.length == 0}"
isEnabled="@{data.buttonPositive.isEnabled()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:clickable="@{data.buttonPositive.isEnabled()}"
android:filterTouchesWhenObscured="true"
android:focusable="@{data.buttonPositive.isEnabled()}"
android:onClick="@{() -> data.buttonPositive.clicked()}"
android:text="@{data.buttonPositive.title}"
app:icon="@{data.buttonPositive.icon}"
app:iconGravity="textStart"
tools:icon="@drawable/ic_bug_md2"
tools:text="Button 1" />
</androidx.appcompat.widget.ButtonBarLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
</androidx.appcompat.widget.ButtonBarLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -18,7 +18,8 @@
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:layout_marginTop="@dimen/internal_action_bar_size"
app:layout_fitsSystemWindowsInsets="top"
tools:layout_marginTop="@dimen/internal_action_bar_size">
<androidx.recyclerview.widget.RecyclerView
@@ -31,9 +32,7 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingLeft="@{viewModel.insets.left}"
android:paddingRight="@{viewModel.insets.right}"
android:paddingBottom="@{viewModel.insets.bottom}"
app:fitsSystemWindowsInsets="start|end|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:listitem="@layout/item_console_md2" />
@@ -46,39 +45,17 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/l1"
android:layout_marginBottom="@{(int) @dimen/l1 + viewModel.insets.bottom}"
android:layout_marginBottom="@dimen/l1"
android:onClick="@{() -> viewModel.restartPressed()}"
android:text="@string/reboot"
android:textAllCaps="false"
android:textColor="?colorOnPrimary"
android:textStyle="bold"
app:layout_fitsSystemWindowsInsets="bottom"
app:backgroundTint="?colorPrimary"
app:icon="@drawable/ic_restart"
app:iconTint="?colorOnPrimary" />
<com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card.Elevated"
goneUnless="@{viewModel.loading}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:contentPadding="@dimen/l1">
<TextView
movieBehavior="@{viewModel.loading}"
movieBehaviorText="@{viewModel.behaviorText}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="monospace"
android:gravity="center"
android:textAppearance="@style/AppearanceFoundation.Body"
android:textColor="?colorOnSurface"
android:textStyle="bold"
tools:text="Flashing..." />
</com.google.android.material.card.MaterialCardView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

View File

@@ -17,7 +17,6 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/hide_content"
dividerVertical="@{@drawable/divider_l_50}"
invisibleUnless="@{viewModel.loaded || !viewModel.items.empty}"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
@@ -25,10 +24,8 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_hide_md2"
tools:paddingTop="40dp" />
@@ -41,8 +38,9 @@
android:layout_gravity="bottom|end"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:layout_marginBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:layout_marginBottom="@dimen/l1"
app:backgroundTint="?colorSurfaceSurfaceVariant"
app:layout_fitsSystemWindowsInsets="bottom"
app:srcCompat="@drawable/ic_search_md2"
app:tint="?colorPrimary"
tools:layout_marginBottom="64dp" />

View File

@@ -22,8 +22,9 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l3}"
android:paddingTop="@dimen/internal_action_bar_size"
android:paddingBottom="@dimen/l3"
app:fitsSystemWindowsInsets="top|bottom"
tools:layout_marginTop="24dp">
<LinearLayout

View File

@@ -20,8 +20,9 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l2}"
android:paddingTop="@dimen/internal_action_bar_size"
android:paddingBottom="@dimen/l2"
app:fitsSystemWindowsInsets="top|bottom"
tools:paddingTop="24dp">
<FrameLayout
@@ -34,7 +35,7 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="@dimen/l1">
android:paddingTop="@dimen/l_50">
<com.google.android.material.card.MaterialCardView
style="@style/WidgetFoundation.Card"

View File

@@ -29,7 +29,8 @@
android:layout_gravity="bottom|end"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:layout_marginBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:layout_marginBottom="@dimen/l1"
app:layout_fitsSystemWindowsInsets="bottom"
app:backgroundTint="?colorSurfaceSurfaceVariant"
app:srcCompat="@drawable/ic_folder_list"
app:tint="?colorPrimary"

View File

@@ -31,8 +31,6 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_list"
adapter="@{viewModel.adapter}"
dividerHorizontal="@{@drawable/divider_l1}"
dividerVertical="@{@drawable/divider_l_50}"
gone="@{viewModel.loading &amp;&amp; viewModel.items.empty}"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
@@ -40,10 +38,8 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingEnd="0dp"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_module_md2" />
@@ -54,7 +50,8 @@
android:layout_gravity="bottom|end"
android:layout_marginStart="@dimen/l1"
android:layout_marginEnd="@dimen/l1"
android:layout_marginBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:layout_marginBottom="@dimen/l1"
app:layout_fitsSystemWindowsInsets="bottom"
app:backgroundTint="?colorSurfaceSurfaceVariant"
app:srcCompat="@drawable/ic_search_md2"
app:tint="?colorPrimary"

View File

@@ -22,8 +22,8 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingBottom="@{viewModel.insets.bottom}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
tools:paddingBottom="48dp"
tools:paddingTop="24dp">

View File

@@ -15,8 +15,6 @@
<androidx.recyclerview.widget.RecyclerView
adapter="@{viewModel.adapter}"
dividerHorizontal="@{@drawable/divider_l_50}"
dividerVertical="@{@drawable/divider_l_50}"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
android:id="@+id/settings_list"
@@ -25,10 +23,8 @@
android:focusableInTouchMode="false"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingEnd="@dimen/l_50"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:layout_marginTop="24dp"
tools:listitem="@layout/item_settings"

View File

@@ -20,8 +20,6 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/superuser_list"
adapter="@{viewModel.adapter}"
dividerHorizontal="@{@drawable/divider_l1}"
dividerVertical="@{@drawable/divider_l_50}"
goneUnless="@{viewModel.loaded || !viewModel.items.empty}"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
@@ -29,9 +27,8 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l2}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_policy_md2" />

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
@@ -17,15 +18,17 @@
android:clipToPadding="false"
android:fillViewport="true"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingTop="@dimen/internal_action_bar_size"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l1}">
android:paddingBottom="@dimen/l1"
app:fitsSystemWindowsInsets="top|bottom">
<LinearLayout
android:id="@+id/theme_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/l1"
android:useDefaultMargins="true">
<include

View File

@@ -21,7 +21,8 @@
android:paddingStart="@dimen/l1"
android:paddingTop="@dimen/l1"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:paddingBottom="@dimen/l1"
app:fitsSystemWindowsInsets="bottom"
tools:layout_gravity="bottom"
tools:paddingBottom="64dp">

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
@@ -32,8 +33,8 @@
precomputedText="@{viewModel.consoleText}"
android:textAppearance="@style/AppearanceFoundation.Caption"
android:textSize="10sp"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingBottom="@{viewModel.insets.bottom}"
android:paddingTop="@dimen/internal_action_bar_size"
app:layout_fitsSystemWindowsInsets="top|bottom"
tools:text="@tools:sample/lorem/random" />
</HorizontalScrollView>

View File

@@ -16,16 +16,15 @@
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/log_superuser"
itemBinding="@{viewModel.itemBinding}"
items="@{viewModel.items}"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size}"
android:paddingEnd="@dimen/l1"
android:paddingBottom="@{viewModel.insets.bottom}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top|bottom"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_log_access_md2"
tools:paddingTop="24dp" />

View File

@@ -18,14 +18,13 @@
android:layout_height="match_parent"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingBottom="@{viewModel.insets.bottom + (int) @dimen/l1}"
android:paddingBottom="@dimen/l1"
app:fitsSystemWindowsInsets="bottom"
tools:layout_gravity="bottom"
tools:paddingBottom="64dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/module_filter_list"
dividerHorizontal="@{@drawable/divider_l1}"
dividerVertical="@{@drawable/divider_l_50}"
itemBinding="@{viewModel.itemSearchBinding}"
items="@{viewModel.itemsSearch}"
android:layout_width="match_parent"
@@ -33,8 +32,8 @@
android:layout_marginBottom="@dimen/l1"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingStart="@dimen/l1"
android:paddingTop="@{viewModel.insets.top + (int) @dimen/internal_action_bar_size + (int) @dimen/l1}"
android:paddingTop="@dimen/internal_action_bar_size"
app:fitsSystemWindowsInsets="top"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toTopOf="@+id/module_filter_title_search"

View File

@@ -9,7 +9,7 @@
<variable
name="item"
type="com.topjohnwu.magisk.ui.hide.HideItem" />
type="com.topjohnwu.magisk.ui.hide.HideRvItem" />
<variable
name="viewModel"

View File

@@ -7,7 +7,7 @@
<variable
name="item"
type="com.topjohnwu.magisk.ui.hide.HideProcessItem" />
type="com.topjohnwu.magisk.ui.hide.HideProcessRvItem" />
<variable
name="viewModel"

View File

@@ -1,5 +1,8 @@
## v8.0.3
## v8.0.6
- Switch to the new Magisk Module Repo setup in preparation to allow 3rd party repos
- Add tapjacking protection on Superuser request dialog
- Stability changes and bug fixes
- Minor UI changes
- Update internal scripts
## v8.0.5
- Fix sepolicy rule copying

View File

@@ -30,10 +30,16 @@ direct_install() {
rm -f $MAGISKBIN/new-boot.img
echo "- Flashing new boot image"
flash_image $1/new-boot.img $2
if [ $? -ne 0 ]; then
echo "! Insufficient partition size"
return 1
fi
case $? in
1)
echo "! Insufficient partition size"
return 1
;;
2)
echo "! $2 is read only"
return 2
;;
esac
rm -rf $1
return 0
}

View File

@@ -6,8 +6,8 @@
<string name="logs">Журналы</string>
<string name="settings">Налады</string>
<string name="refresh">Абнавіць даныя</string>
<string name="install">Усталяваць</string>
<string name="section_home">На хатнюю старонку</string>
<string name="install">Усталёўка</string>
<string name="section_home">Хатняя старонка</string>
<string name="section_theme">Тэмы</string>
<string name="safetynet">SafetyNet</string>
<!--Home-->
@@ -16,7 +16,7 @@
<string name="manager">Кіраўнік</string>
<string name="loading">Загрузка…</string>
<string name="update">Абнавіць</string>
<string name="not_available">Н</string>
<string name="not_available">Не</string>
<string name="hide">Схаваць</string>
<string name="status">Статус</string>
<string name="home_package">Пакунак</string>
@@ -26,7 +26,7 @@
<string name="home_support_content">Magisk ёсць і заўсёды будзе бясплатным праектам з адкрытым зыходным кодам. Але вы заўсёды можаце ахвяраваць нам на распрацоўку.</string>
<string name="home_status_normal">Звычайны</string>
<string name="home_status_stub">Хаванне</string>
<string name="home_installed_version">Усталяваны</string>
<string name="home_installed_version">Усталявана</string>
<string name="home_latest_version">Апошні</string>
<string name="invalid_update_channel">Хібны канал абнаўлення</string>
<string name="uninstall_magisk_title">Выдаліць Magisk</string>

View File

@@ -1,169 +1,247 @@
<resources>
<!--Welcome Activity-->
<string name="modules">Moduly</string>
<string name="superuser">Superuser</string>
<string name="logs">Log</string>
<!--Sections-->
<string name="modules">Správce modulů</string>
<string name="superuser">SuperUser</string>
<string name="logs">Protokol</string>
<string name="settings">Nastavení</string>
<string name="refresh">Obnovit lokální data</string>
<string name="install">Instalovat</string>
<string name="unsupport_magisk_title">Nepodporovaná verze Magisk</string>
<string name="section_home">Domů</string>
<string name="section_theme">Téma</string>
<string name="safetynet">SafetyNet</string>
<!--Status Fragment-->
<string name="invalid_update_channel">Neplatný kanál aktualizace</string>
<string name="safetynet_api_error">Chyba SafetyNet API</string>
<string name="safetynet_res_invalid">Odpověď je neplatná.</string>
<string name="keep_force_encryption">Udržet "force encryption"</string>
<string name="keep_dm_verity">Udržet "AVB 2.0/dm-verity"</string>
<string name="uninstall_magisk_title">Odinstalovat Magisk</string>
<string name="uninstall_magisk_msg">Všechny moduly budou zakázány/odstraněny. Root bude odstraněn a pokud jsou data dešifrována, můžou být zašifrována.</string>
<string name="update">Aktualizovat</string>
<!--Module Fragment-->
<string name="no_info_provided">(Žádné informace)</string>
<string name="reboot_recovery">Restartovat do Recovery</string>
<string name="reboot_bootloader">Restartovat do Bootloaderu</string>
<string name="reboot_download">Restartovat do Download</string>
<!--Repo Fragment-->
<string name="update_available">Dostupná aktualizace</string>
<string name="home_installed_version">Nainstalováno</string>
<string name="sorting_order">Pořadí řazení</string>
<!--Log Fragment-->
<string name="menuSaveLog">Uložit log</string>
<string name="menuClearLog">Smazat log</string>
<string name="logs_cleared">Log byl smazán.</string>
<!--About Activity-->
<!--Home-->
<string name="no_connection">Žádné připojení</string>
<string name="app_changelog">Seznam změn</string>
<string name="manager">Správce</string>
<string name="loading">Načítání…</string>
<string name="update">Aktualizovat</string>
<string name="not_available">N/A</string>
<string name="hide">Skrýt</string>
<string name="status">Stav</string>
<string name="home_package">Balíček</string>
<!-- System Components, Notifications -->
<string name="update_channel">Aktualizace Magisk</string>
<string name="progress_channel">Oznámení o průběhu</string>
<string name="download_complete">Stahování dokončeno</string>
<string name="download_file_error">Chyba při stahování souboru</string>
<string name="magisk_update_title">Aktualizace Magisk je dostupná!</string>
<string name="manager_update_title">Aktualizace Magisk Manager je dostup!</string>
<string name="home_notice_content">Zkontrolujte, zda používáte Magisk Manager s otevřeným kódem. Správce z neznámého zdroje může provádět nebezpečné akce!</string>
<string name="home_support_title">Podpořte nás</string>
<string name="home_item_source">Zdroj</string>
<string name="home_support_content">Magisk je a vždy bude svobodný s otevřeným kódem. Můžete nám však zaslat malý dar jako poděkování.</string>
<string name="home_status_normal">Normální</string>
<string name="home_status_stub">Testovací</string>
<string name="home_installed_version">Nainstalova</string>
<string name="home_latest_version">Poslední</string>
<string name="invalid_update_channel">Neplatný kanál aktualizace</string>
<string name="uninstall_magisk_title">Odinstalovat Magisk</string>
<string name="uninstall_magisk_msg">Všechny moduly budou zakázány/odstraněny!\nROOT bude odstraněn!\nPokud jsou data dešifrována, můžou být zašifrována!</string>
<string name="home_check_safetynet">Zkontrolovat SafetyNet</string>
<!-- Installation -->
<string name="manager_download_install">Stiskněte pro stažení a instalaci.</string>
<string name="download_zip_only">Stáhnout pouze zip</string>
<!--Install-->
<string name="keep_force_encryption">Ponechat Force Encryption</string>
<string name="keep_dm_verity">Ponechat AVB 2.0/DM-Verity</string>
<string name="recovery_mode">Režim Recovery</string>
<string name="install_options_title">Možnosti</string>
<string name="install_method_title">Způsob</string>
<string name="install_next">Další</string>
<string name="install_start">Spustit</string>
<string name="manager_download_install">Stiskněte pro stažení a instalaci</string>
<string name="download_zip_only">Stáhnout pouze soubor ZIP</string>
<string name="direct_install">Přímá instalace (doporučeno)</string>
<string name="install_inactive_slot">Instalace do druhého slotu (po OTA)</string>
<string name="install_inactive_slot_msg">Vaše zařízení bude po restartu VYNUCENĚ spuštěno do aktuálního neaktivního slotu!\nTuto možnost použijte pouze po dokončení OTA.\nPokračovat?</string>
<string name="install_inactive_slot_msg">Vaše zařízení bude po restartu VYNUCENĚ spuštěno do aktuálního neaktivního slotu!\nTuto možnost použijte pouze po dokončení OTA.\nChcete pokračovat?</string>
<string name="setup_title">Další nastavení</string>
<string name="select_patch_file">Vybrat a opravit soubor</string>
<string name="patch_file_msg">Vyberte obraz raw (*.img) nebo soubor tar pro ODIN (*.tar)</string>
<string name="patch_file_msg">Vyberte soubor RAW (*.img) nebo soubor TAR pro ODIN (*.tar)</string>
<string name="reboot_delay_toast">Restartování za 5 sekund…</string>
<string name="flash_screen_title">Instalace</string>
<!--Toasts, Dialogs-->
<string name="repo_install_title">Instalovat %1$s</string>
<string name="repo_install_msg">Chcete nyní nainstalovat %1$s?</string>
<string name="download">Stáhnout</string>
<string name="reboot">Restartovat</string>
<string name="release_notes">Poznámky k vydání</string>
<string name="repo_cache_cleared">Mezipaměť smazána</string>
<!--Superuser-->
<string name="su_request_title">Požadavek SuperUser</string>
<string name="touch_filtered_warning">Protože aplikace zavírá požadavek SuperUser, Magisk nemůže ověřit Vaši odpověď</string>
<string name="deny">Zakázat</string>
<string name="prompt">Zeptat se</string>
<string name="grant">Povolit</string>
<string name="su_warning">Povolí plný přístup k Vašemu zařízení.\nZakažte, pokud si nejste jisti!</string>
<string name="forever">Trvale</string>
<string name="once">Jednou</string>
<string name="tenmin">10 minut</string>
<string name="twentymin">20 minut</string>
<string name="thirtymin">30 minut</string>
<string name="sixtymin">60 minut</string>
<string name="su_allow_toast">Pro %1$s bylo oprávnění SuperUser povoleno</string>
<string name="su_deny_toast">Pro %1$s bylo oprávnění SuperUser zakázáno</string>
<string name="su_snack_grant">SuperUser oprávnění pro %1$s je povoleno</string>
<string name="su_snack_deny">SuperUser oprávnění pro %1$s je zakázáno</string>
<string name="su_snack_notif_on">Oznámení pro %1$s jsou povolena</string>
<string name="su_snack_notif_off">Oznámení pro %1$s jsou zakázána</string>
<string name="su_snack_log_on">Protokolování %1$s je povoleno</string>
<string name="su_snack_log_off">Protokolování %1$s je zakázáno</string>
<string name="su_revoke_title">Smazat?</string>
<string name="su_revoke_msg">Chcete smazat protokol k oprávnění pro %1$s?</string>
<string name="toast">Text</string>
<string name="none">Žádné</string>
<string name="flashing">Instalová</string>
<string name="hide_manager_title">Skrytí Magisk Manageru…</string>
<string name="hide_manager_fail_toast">Skrytí Magisk Manageru selhalo.</string>
<string name="open_link_failed_toast">Nebyla nalezena žádná aplikace pro otevření odkazu.</string>
<string name="complete_uninstall">Dokončete odinstalaci</string>
<string name="restore_img">Obnovit obrazy</string>
<string name="restore_img_msg">Obnovování…</string>
<string name="restore_done">Obnovení bylo provedeno!</string>
<string name="restore_fail">Výchozí záloha neexistuje!</string>
<string name="proprietary_title">Stáhnout proprietární kód</string>
<string name="proprietary_notice">Magisk Manager je FOSS a neobsahuje proprietární kód SafetyNet API společnosti Google.\n\nChcete povolit aplikaci Magisk Manager stažení rozšíření (obsahuje GoogleApiClient) pro kontrolu SafetyNet?</string>
<string name="setup_fail">Nastavení selhalo.</string>
<string name="env_fix_title">Vyžaduje se další nastavení</string>
<string name="env_fix_msg">Vaše zařízení potřebuje další nastavení, aby Magisk fungoval správně. Stáhne se instalační zip Magisk, chcete pokračovat?</string>
<string name="setup_msg">Nastavení je spuštěno…</string>
<string name="superuser_toggle_notification">Oznáme</string>
<string name="superuser_toggle_revoke">Smazat</string>
<string name="superuser_policy_none">Žádná aplikace nepožádala o oprávnění SuperUser.</string>
<!--Settings Activity -->
<string name="settings_clear_cache_title">Smazat uchovanou mezipaměť</string>
<string name="settings_clear_cache_summary">Smaže informace online použití v mezipaměti, donutí aplikaci obnovit informace online.</string>
<!--Logs-->
<string name="log_data_none">Žádné protokoly. Vyzkoušejte nějakou aplikaci vyžadující oprávnění SuperUser.</string>
<string name="log_data_magisk_none">Protokoly Magisk jsou prázdné. To je zvláštní!</string>
<string name="menuSaveLog">Uložit protokol</string>
<string name="menuClearLog">Smazat protokol</string>
<string name="logs_cleared">Protokol byl smazán</string>
<string name="pid">PID:%1$d</string>
<string name="target_uid">Cílové UID: %1$d</string>
<!--SafetyNet-->
<string name="safetynet_api_error">Chyba SafetyNet API</string>
<string name="safetynet_res_invalid">Odpověď je neplatná</string>
<string name="safetynet_attest_success">Úspěšné!</string>
<string name="safetynet_attest_failure">Chyba ověření!</string>
<string name="safetynet_attest_loading">Čekejte…</string>
<string name="safetynet_attest_restart">Zkusit znovu</string>
<!--MagiskHide-->
<string name="show_system_app">Zobrazit systémové aplikace</string>
<string name="show_os_app">Zobrazit OS aplikace</string>
<string name="hide_filter_hint">Filtrovat podle názvu</string>
<string name="hide_scroll_up">Posunout nahoru</string>
<string name="hide_filters">Filtry</string>
<string name="hide_search">Vyhledávání</string>
<!--Module-->
<string name="no_info_provided">(žádné informace)</string>
<string name="reboot_userspace">Restartovat do UserSpace</string>
<string name="reboot_recovery">Restartovat do Recovery</string>
<string name="reboot_bootloader">Restartovat do Bootloader</string>
<string name="reboot_download">Restartovat do Download</string>
<string name="reboot_edl">Restartovat do EDL</string>
<string name="module_version_author">%1$s z %2$s</string>
<string name="module_section_pending">Aktualizace</string>
<string name="module_section_pending_action">Aktualizovat vše</string>
<string name="module_state_remove">Odstranit</string>
<string name="module_state_restore">Obnovit</string>
<string name="module_action_install_external">Instalace z úložiště</string>
<string name="update_available">Dostupná aktualizace</string>
<string name="module_installed">@string/home_installed_version</string>
<string name="module_section_online">Online</string>
<string name="sorting_order">Seřadit</string>
<!--Settings-->
<string name="settings_dark_mode_title">Režim motivu</string>
<string name="settings_dark_mode_message">Vyberte režim, který nejlépe vyhovuje Vašemu stylu!</string>
<string name="settings_dark_mode_light">Světlý</string>
<string name="settings_dark_mode_system">Podle systému</string>
<string name="settings_dark_mode_dark">Tmavý</string>
<string name="settings_download_path_title">Složka pro stahování</string>
<string name="settings_download_path_message">Soubory budou uloženy do %1$s.</string>
<string name="settings_clear_cache_title">Smazat mezipaměť</string>
<string name="settings_clear_cache_summary">Smažete online informace o použití z mezipaměti, a tím na aplikaci vynutíte obnovení online informací.</string>
<string name="settings_hide_manager_title">Skrýt Magisk Manager</string>
<string name="settings_hide_manager_summary">Nahradí Magisk Manager náhodným názvem balíčku.</string>
<string name="settings_hide_manager_summary">Nahradíte Magisk Manager náhodným názvem balíčku.</string>
<string name="settings_restore_manager_title">Obnovit Magisk Manager</string>
<string name="settings_restore_manager_summary">Obnoví Magisk Manager na původní název balíčku.</string>
<string name="settings_restore_manager_summary">Obnovíte Magisk Manager na původní název balíčku.</string>
<string name="language">Jazyk</string>
<string name="system_default">(Výchozí systémový)</string>
<string name="settings_check_update_title">Zkontrolovat aktualizace</string>
<string name="settings_check_update_summary">Pravidelně kontrolujte aktualizace na pozadí.</string>
<string name="system_default">(výchozí podle systému)</string>
<string name="settings_check_update_title">Automatické aktualizace</string>
<string name="settings_check_update_summary">Povolíte pravidelnou kontrolu aktualizace na pozadí.</string>
<string name="settings_update_channel_title">Kanál aktualizace</string>
<string name="settings_update_stable">Stabilní</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Vlastní</string>
<string name="settings_update_custom_msg">Vložte vlastní URL</string>
<string name="settings_magiskhide_summary">Skrýt Magisk z různých detekcí.</string>
<string name="settings_hosts_title">Nesystémoví hostitelé</string>
<string name="settings_hosts_summary">Podpora nesystémových hostitelů pro aplikace Adblock.</string>
<string name="settings_magiskhide_summary">Skryjete Magisk před různými detekcemi.</string>
<string name="settings_hosts_title">Nesystémový hostitel</string>
<string name="settings_hosts_summary">Přidáte modul pro podporu nesystémových hostitelů v aplikaci AdBlock.</string>
<string name="settings_hosts_toast">Přidán systémový modul hostitelů</string>
<string name="settings_app_name_hint">Nový název</string>
<string name="settings_app_name_helper">Název aplikace bude nahrazen tímto názvem.</string>
<string name="settings_app_name_error">Neplatný formát</string>
<string name="settings_su_app_adb">Aplikace a ADB</string>
<string name="settings_su_app">Pouze aplikace</string>
<string name="settings_su_adb">Pouze ADB</string>
<string name="settings_su_disable">Zakázáno</string>
<string name="settings_su_disable">Zakázat</string>
<string name="settings_su_request_10">10 sekund</string>
<string name="settings_su_request_15">15 sekund</string>
<string name="settings_su_request_20">20 sekund</string>
<string name="settings_su_request_30">30 sekund</string>
<string name="settings_su_request_45">45 sekund</string>
<string name="settings_su_request_60">60 sekund</string>
<string name="superuser_access">Přístup Superuser</string>
<string name="superuser_access">Přístup SuperUser</string>
<string name="auto_response">Automatická odezva</string>
<string name="request_timeout">Časový limit požadavku</string>
<string name="superuser_notification">Oznámení Superuser</string>
<string name="superuser_notification">Oznámení SuperUser</string>
<string name="settings_su_reauth_title">Opětovné ověření po aktualizaci</string>
<string name="settings_su_reauth_summary">Opětovné ověření oprávnění Superuser po aktualizaci aplikace</string>
<string name="settings_su_reauth_summary">Opětovné ověření oprávnění SuperUser po aktualizaci aplikace.</string>
<string name="settings_su_tapjack_title">Povolit ochranu před TapJack</string>
<string name="settings_su_tapjack_summary">Okno dialogu SuperUser nebude reagovat na kliknutí v případě, že je zavřené nebo překryté jiným oknem.</string>
<string name="settings_su_biometric_title">Povolit biometrické ověření</string>
<string name="settings_su_biometric_summary">Použijte biometrické ověření pro povolení požadavků SuperUser.</string>
<string name="no_biometric">Nepodporované zařízení nebo není biometrické ověření povolené</string>
<string name="settings_customization">Přizpůsobit</string>
<string name="setting_add_shortcut_summary">Přidejte odkaz na domovskou obrazovku v případě, že se po skrytí aplikace její název a ikona těžko rozpoznávají.</string>
<string name="settings_doh_title">DNS nebo HTTPS</string>
<string name="settings_doh_description">Řešení pro opravy DNS v některých zemích.</string>
<string name="multiuser_mode">Režim více uživatelů</string>
<string name="settings_owner_only">Pouze vlastník zařízení</string>
<string name="settings_owner_manage">Spravováno vlastníkem zařízení</string>
<string name="settings_user_independent">Nezávislý uživatel</string>
<string name="owner_only_summary">Pouze vlastník má root přístup.</string>
<string name="owner_manage_summary">Root přístup spravuje pouze vlastník a přijímá požadavky k přístupu.</string>
<string name="user_indepenent_summary">Každý uživatel má svá vlastní pravidla root.</string>
<string name="settings_owner_only">Vlastník zařízení</string>
<string name="settings_owner_manage">Správce zařízení</string>
<string name="settings_user_independent">Všichni uživatelé</string>
<string name="owner_only_summary">Pouze vlastník má přístup ROOT.</string>
<string name="owner_manage_summary">Přístup ROOT má správce zařízení, který přijímá požadavky k přístupu.</string>
<string name="user_indepenent_summary">Každý uživatel má svá vlastní pravidla přístupu ROOT.</string>
<string name="mount_namespace_mode">Režim připojení jmenného prostoru</string>
<string name="settings_ns_global">Globální jmenný prostor</string>
<string name="settings_ns_requester">Zděděný jmenný prostor</string>
<string name="settings_ns_requester">Odvozený jmenný prostor</string>
<string name="settings_ns_isolate">Izolovaný jmenný prostor</string>
<string name="global_summary">Všechny relace root používají globální připojení jmenného prostoru.</string>
<string name="requester_summary">Kořenové relace dědí jmenný prostor žadatele.</string>
<string name="isolate_summary">Každá relace root bude mít svůj vlastní izolovaný jmenný prostor.</string>
<string name="global_summary">Všechny relace ROOT používají globální jmenný prostor.</string>
<string name="requester_summary">Relace ROOT je odvozena od jmenného prostoru žadatele.</string>
<string name="isolate_summary">Každá relace ROOT má svůj vlastní izolovaný jmenný prostor.</string>
<!--Superuser-->
<string name="su_request_title">Požadavek Superuser</string>
<string name="deny">Zamítnout</string>
<string name="prompt">Dotaz</string>
<string name="grant">Povolit</string>
<string name="su_warning">Povolí plný přístup k vašemu zařízení.\nZamítněte, pokud si nejste jisti!</string>
<string name="forever">Navždy</string>
<string name="once">Jednou</string>
<string name="tenmin">10 minut</string>
<string name="twentymin">20 minut</string>
<string name="thirtymin">30 minut</string>
<string name="sixtymin">60 minut</string>
<string name="su_allow_toast">Pro %1$s bylo oprávnění Superuser povoleno</string>
<string name="su_deny_toast">Pro %1$s bylo oprávnění Superuser zamítnuto</string>
<string name="su_snack_grant">Superuser oprávnění pro %1$s je povoleno</string>
<string name="su_snack_deny">Superuser oprávnění pro %1$s je zamítnuto</string>
<string name="su_snack_notif_on">Oznámení pro %1$s jsou povolena</string>
<string name="su_snack_notif_off">Oznámení pro %1$s jsou zakázána</string>
<string name="su_snack_log_on">Logování %1$s je povoleno</string>
<string name="su_snack_log_off">Logování %1$s je zakázáno</string>
<string name="su_revoke_title">Smazat?</string>
<string name="su_revoke_msg">Smazat záznam ohledně oprávnění pro %1$s?</string>
<string name="toast">Informační text</string>
<string name="none">Žádný</string>
<!--Notifications-->
<string name="update_channel">Aktualizace Magisk</string>
<string name="progress_channel">Oznámení o průběhu</string>
<string name="download_complete">Stahování dokončeno</string>
<string name="download_file_error">Chyba při stahování souboru</string>
<string name="download_open_parent">Zobrazit výchozí složku</string>
<string name="download_open_self">Zobrazit soubor</string>
<string name="magisk_update_title">Aktualizace Magisk je dostupná!</string>
<string name="manager_update_title">Aktualizace Magisk Manager je dostupná!</string>
<!--Superuser logs-->
<string name="pid">PID: %1$d</string>
<string name="target_uid">Cílové UID: %1$d</string>
<!-- MagiskHide -->
<string name="show_system_app">Zobrazit systémové aplikace</string>
<!--Toasts, Dialogs-->
<string name="yes">ANO</string>
<string name="no">NE</string>
<string name="repo_install_title">Instalovat %1$s</string>
<string name="repo_install_msg">Chcete nyní nainstalovat %1$s?</string>
<string name="download">Stáhnout</string>
<string name="reboot">Restartovat</string>
<string name="release_notes">Poznámky k vydání</string>
<string name="repo_cache_cleared">Mezipaměť smazána</string>
<string name="flashing">Instalování…</string>
<string name="done">Hotovo!</string>
<string name="failure">Selhalo!</string>
<string name="hide_manager_title">Skrývání Magisk Manager…</string>
<string name="hide_manager_fail_toast">Skrývání Magisk Manager selhalo.</string>
<string name="restore_manager_fail_toast">Obnovení Magisk Manager selhalo.</string>
<string name="open_link_failed_toast">Nebyla nalezena žádná aplikace pro otevření odkazu.</string>
<string name="complete_uninstall">Odinstalovat</string>
<string name="restore_img">Obnovit obrazy</string>
<string name="restore_img_msg">Obnovování…</string>
<string name="restore_done">Obnovení bylo provedeno!</string>
<string name="restore_fail">Výchozí záloha neexistuje!</string>
<string name="proprietary_title">Stáhnout kód</string>
<string name="proprietary_notice">Magisk Manager je FOSS a neobsahuje kód SafetyNet API společnosti Google.\n\nChcete povolit aplikaci Magisk Manager stažení rozšíření (obsahuje GoogleApiClient) pro kontrolu SafetyNet?</string>
<string name="setup_fail">Nastavení selhalo</string>
<string name="env_fix_title">Vyžaduje se další nastavení</string>
<string name="env_fix_msg">Vaše zařízení potřebuje další nastavení, aby Magisk fungoval správně. Stáhne se instalační soubor (.zip) Magisk. Chcete pokračovat?</string>
<string name="setup_msg">Nastavení je spuštěno…</string>
<string name="authenticate">Ověřit</string>
<string name="unsupport_magisk_title">Nepodporovaná verze Magisk</string>
<string name="unsupport_magisk_msg">Tato verze Magisk Manager nepodporuje verzi Magisk nižší než %1$s.\n\nMůžete buď ručně aktualizovat Magisk, nebo nainstalovat starší verzi aplikace.</string>
<string name="external_rw_permission_denied">Udělte oprávnění pro povolení této funkce.</string>
<string name="add_shortcut_title">Přidat odkaz na domovskou obrazovku</string>
<string name="add_shortcut_msg">Po skrytí Magisk Manager se může jeho název a ikona těžko rozpoznat. Chcete přidat odkaz na domovskou obrazovku?</string>
<string name="app_not_found">Nelze nalézt žádnou aplikaci, která dokáže provést tuto akci.</string>
</resources>

View File

@@ -15,7 +15,7 @@
<string name="no_connection">Keine Verbindung verfügbar</string>
<string name="app_changelog">Änderungen</string>
<string name="manager">Manager</string>
<string name="loading">Lädt</string>
<string name="loading">Laden</string>
<string name="update">Update</string>
<string name="not_available">N/A</string>
<string name="hide">Verstecken</string>
@@ -40,7 +40,7 @@
<string name="recovery_mode">Recovery Modus</string>
<string name="install_options_title">Optionen</string>
<string name="install_method_title">Methode</string>
<string name="install_next">Nächste</string>
<string name="install_next">Nächster Schritt</string>
<string name="install_start">Los geht\'s</string>
<string name="manager_download_install">Tippen zum Herunterladen und Installieren</string>
<string name="download_zip_only">Nur Zip herunterladen</string>

View File

@@ -170,6 +170,8 @@
<string name="superuser_notification">Notificación de superusuario</string>
<string name="settings_su_reauth_title">Re-autenticación</string>
<string name="settings_su_reauth_summary">Pedir permisos de superusuario nuevamente si una aplicación es actualizada o reinstalada</string>
<string name="settings_su_tapjack_title">Habilitar Protección contra Tapjacking</string>
<string name="settings_su_tapjack_summary">El cuadro de solicitud de superusuario no responderá mientras esté oculto por cualquier otra ventana o superposición</string>
<string name="settings_su_biometric_title">Habilitar autenticación biométrica</string>
<string name="settings_su_biometric_summary">Usar autenticación biométrica para permitir solicitudes de superusuario</string>
<string name="no_biometric">Dispositivo no compatible o las configuraciones biométricas no están habilitadas</string>

View File

@@ -22,7 +22,7 @@
<string name="status">Status</string>
<string name="home_package">Paket</string>
<string name="home_notice_content">Pastikan selalu menggunakan Magisk Manager dari sumber terbuka. Manager dari sumber yang tidak dikenal dapat melakukan tindakan jahat.</string>
<string name="home_notice_content">Pastikan selalu menggunakan Magisk Manager dari sumber terbuka. Manager dari sumber yang tidak dikenal dapat melakukan tindakan jahat!</string>
<string name="home_support_title">Dukung kami</string>
<string name="home_item_source">Sumber</string>
<string name="home_support_content">Magisk gratis dan bersumber terbuka, dan akan selalu seperti itu. Bagaimanapun juga Anda dapat menunjukan kepedulian Anda kepada kami dengan mengirimkan sedikit donasi.</string>
@@ -85,11 +85,11 @@
<string name="superuser_policy_none">Belum ada aplikasi yang meminta izin superuser.</string>
<!--Logs-->
<string name="log_data_none">Log Anda masih kosong, coba gunakan lebih banyak aplikasi yang membutuhkan SU Anda.</string>
<string name="log_data_magisk_none">Log Magisk kosong, ini aneh.</string>
<string name="log_data_none">Log Anda masih kosong, coba gunakan lebih banyak aplikasi yang membutuhkan SU Anda</string>
<string name="log_data_magisk_none">Log Magisk kosong, ini aneh</string>
<string name="menuSaveLog">Simpan log</string>
<string name="menuClearLog">Hapus log sekarang</string>
<string name="logs_cleared">Log berhasil dihapus.</string>
<string name="logs_cleared">Log berhasil dihapus</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Target UID: %1$d</string>
@@ -101,7 +101,7 @@
<string name="safetynet_attest_loading">Tunggu sebentar…</string>
<string name="safetynet_attest_restart">Coba lagi</string>
<!-- MagiskHide -->
<!--MagiskHide-->
<string name="show_system_app">Tampilkan aplikasi sistem</string>
<string name="show_os_app">Tampilkan aplikasi OS</string>
<string name="hide_filter_hint">Filter menurut nama</string>
@@ -109,7 +109,7 @@
<string name="hide_filters">Filter</string>
<string name="hide_search">Telusuri</string>
<!--Module -->
<!--Module-->
<string name="no_info_provided">(Info tidak tersedia)</string>
<string name="reboot_userspace">Nyalakan ulang secara halus</string>
<string name="reboot_recovery">Nyalakan ke mode Recovery</string>
@@ -127,7 +127,7 @@
<string name="module_section_online">Online</string>
<string name="sorting_order">Urutan sortir</string>
<!--Settings -->
<!--Settings-->
<string name="settings_dark_mode_title">Mode tema</string>
<string name="settings_dark_mode_message">Pilih mode yang paling cocok dengan gaya Anda!</string>
<string name="settings_dark_mode_light">Selalu terang</string>
@@ -220,7 +220,7 @@
<string name="repo_cache_cleared">Cache repo dihapus</string>
<string name="flashing">Memasang…</string>
<string name="done">Selesai!</string>
<string name="failure">Gagal</string>
<string name="failure">Gagal!</string>
<string name="hide_manager_title">Menyembunyikan Magisk Manager…</string>
<string name="hide_manager_fail_toast">Gagal menyembunyikan Magisk Manager.</string>
<string name="restore_manager_fail_toast">Gagal memulihkan Magisk Manager</string>

View File

@@ -55,6 +55,7 @@
<!--Superuser-->
<string name="su_request_title">Richiesta di accesso root</string>
<string name="touch_filtered_warning">Magisk non può verificare la tua risposta perché un\'app sta oscurando una richiesta di accesso root</string>
<string name="deny">Nega</string>
<string name="prompt">Chiedi</string>
<string name="grant">Consenti</string>
@@ -101,6 +102,7 @@
<!-- MagiskHide -->
<string name="show_system_app">Mostra app di sistema</string>
<string name="show_os_app">Mostra app del sistema operativo</string>
<string name="hide_filter_hint">Filtra per nome</string>
<string name="hide_scroll_up">Scorri verso l\'alto</string>
<string name="hide_filters">Filtri</string>
@@ -108,6 +110,7 @@
<!--Module Fragment-->
<string name="no_info_provided">(Nessuna informazione)</string>
<string name="reboot_userspace">Riavvio veloce</string>
<string name="reboot_recovery">Riavvia in recovery</string>
<string name="reboot_bootloader">Riavvia in bootloader</string>
<string name="reboot_download">Riavvia in modalità download</string>
@@ -169,6 +172,8 @@
<string name="superuser_notification">Notifica di accesso root</string>
<string name="settings_su_reauth_title">Riautentica dopo aggiornamento</string>
<string name="settings_su_reauth_summary">Richiedi nuovamente i permessi di root dopo l\'aggiornamento di un\'app</string>
<string name="settings_su_tapjack_title">Abilita protezione anti-tapjacking</string>
<string name="settings_su_tapjack_summary">La schermata di richiesta dei permessi di root non risponderà al tocco mentre è oscurata da altre finestre o elementi in sovraimpressione</string>
<string name="settings_su_biometric_title">Abilita autenticazione biometrica</string>
<string name="settings_su_biometric_summary">Utilizza l\'autenticazione biometrica per accettare le richieste di accesso root</string>
<string name="no_biometric">Il dispositivo non è supportato o le impostazioni biometriche sono disattivate</string>
@@ -217,6 +222,7 @@
<string name="failure">Fallito</string>
<string name="hide_manager_title">Nascondendo Magisk Manager…</string>
<string name="hide_manager_fail_toast">Non è stato possibile nascondere Magisk Manager.</string>
<string name="restore_manager_fail_toast">Non è stato possibile ripristinare Magisk Manager.</string>
<string name="open_link_failed_toast">Nessuna app disponibile per aprire il link</string>
<string name="complete_uninstall">Disinstalla completamente</string>
<string name="restore_img">Ripristina immagini</string>

View File

@@ -15,7 +15,7 @@
<string name="no_connection">אין חיבור זמין</string>
<string name="app_changelog">רשימת שינויים</string>
<string name="manager">מנהל</string>
<string name="loading">טוען</string>
<string name="loading">טוען</string>
<string name="update">עדכון</string>
<string name="not_available">ל/ז</string>
<string name="hide">הסתרה</string>
@@ -33,6 +33,7 @@
<string name="invalid_update_channel">ערוץ עדכון לא חוקי</string>
<string name="uninstall_magisk_title">הסרת Magisk</string>
<string name="uninstall_magisk_msg">כל המודולים יושבתו/יוסרו!\nגישת שורש תושבת!\nהנתונים שלך עשויים להיות מוצפנים אם לא הוצפנו כבר!</string>
<string name="home_check_safetynet">בדיקת SafetyNet</string>
<!--Install-->
<string name="keep_force_encryption">שמירה על הצפנה בכח</string>
@@ -41,7 +42,7 @@
<string name="install_options_title">אפשרויות</string>
<string name="install_method_title">שיטה</string>
<string name="install_next">הבא</string>
<string name="install_start">מצא לדרך</string>
<string name="install_start">צא לדרך</string>
<string name="manager_download_install">לחץ להורדה והתקנה</string>
<string name="download_zip_only">הורד ZIP בלבד</string>
<string name="direct_install">התקנה ישירה (מומלץ)</string>
@@ -55,7 +56,8 @@
<!--Superuser-->
<string name="su_request_title">בקשות משתמש על</string>
<string name="deny">דחה</string>
<string name="touch_filtered_warning">מכיוון שאפליקציה מסתירה בקשה של משתמש על, Magisk לא יכולה לאמת את תגובתך</string>
<string name="deny">דחה</string>
<string name="prompt">מיידי</string>
<string name="grant">הענק</string>
<string name="su_warning">מעניק גישה מלאה להתקן שלך.\nדחה באם אינך בטוח!</string>
@@ -93,7 +95,7 @@
<!--SafetyNet-->
<string name="safetynet_api_error">SafetyNet שגיאת API</string>
<string name="safetynet_res_invalid">התגובה אינה חוקים</string>
<string name="safetynet_res_invalid">תגובה אינה חוקית</string>
<string name="safetynet_attest_success">הצליח!</string>
<string name="safetynet_attest_failure">האישור נכשל!</string>
<string name="safetynet_attest_loading">רק רגע…</string>
@@ -101,6 +103,7 @@
<!-- MagiskHide -->
<string name="show_system_app">הצגת יישומי מערכת</string>
<string name="show_os_app">הצגת יישומי מערכת הפעלה</string>
<string name="hide_filter_hint">סינון לפי שם</string>
<string name="hide_scroll_up">גלול למעלה</string>
<string name="hide_filters">מסננים</string>
@@ -108,6 +111,7 @@
<!--Module Fragment-->
<string name="no_info_provided">(לא סופק מידע)</string>
<string name="reboot_userspace">אתחול מהיר</string>
<string name="reboot_recovery">אתחול למצב שחזור</string>
<string name="reboot_bootloader">אתחול מצב מנהל האתחול</string>
<string name="reboot_download">אתחול מצב הורדה</string>
@@ -120,8 +124,8 @@
<string name="module_action_install_external">התקן מהאחסון</string>
<string name="update_available">עדכונים זמינים</string>
<string name="module_installed">@string/home_installed_version</string>
<string name="module_section_online">מקוון</string>
<string name="sorting_order">סדר מיון</string>
<string name="external_rw_permission_denied">הענק הרשאה לאחסון כדי לאפשר פונקציונליות זו</string>
<!--Settings -->
<string name="settings_dark_mode_title">מצב עיצוב</string>
@@ -168,12 +172,15 @@
<string name="request_timeout">בקש פסק זמן</string>
<string name="superuser_notification">התראות משתמש על</string>
<string name="settings_su_reauth_title">אמת מחדש לאחר שדרוג</string>
<string name="settings_su_reauth_summary">אמת מחדש הרשאות משתמש על לאחר שדרוג יישום</string>
<string name="settings_su_biometric_title">אפשר אימות ביומטרי</string>
<string name="settings_su_reauth_summary">אימות מחדש הרשאות של משתמש על לאחר שדרוג יישום</string>
<string name="settings_su_tapjack_title">הפעלת הגנת Tapjacking</string>
<string name="settings_su_tapjack_summary">תיבת הדו שיח של משתמש העל לא תגיב לקלט כשהיא מוסתרת על ידי חלון או כיסוי אחר</string> <string name="settings_su_biometric_title">אפשר אימות ביומטרי</string>
<string name="settings_su_biometric_summary">השתמש באימות ביומטרי כדי לאפשר בקשות לשימוש במשתמש על</string>
<string name="no_biometric">התקן לא נתמך או הגדרות ביומטריות אינן מאופשרות</string>
<string name="settings_customization">התאמה אישית</string>
<string name="setting_add_shortcut_summary">הוסף קיצור דרך יפה במסך הבית למקרה שקשה לזהות את השם ואת הסמל לאחר הסתרת האפליקציה</string>
<string name="settings_doh_title">DNS על HTTPS</string>
<string name="settings_doh_description">עקיפת DNS מורעל במדינות מסוימות</string>
<string name="multiuser_mode">מצב מרובה משתמשים</string>
<string name="settings_owner_only">בעל ההתקן בלבד</string>
<string name="settings_owner_manage">אחראי ניהול ההתקן</string>
@@ -214,8 +221,9 @@
<string name="failure">נכשל</string>
<string name="hide_manager_title">מסתיר את מנהל Magisk…</string>
<string name="hide_manager_fail_toast">הסתרת מנהל Magisk כשלה.</string>
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
<string name="complete_uninstall">הוסר סהצלחה</string>
<string name="restore_manager_fail_toast">שחזור מנהל Magisk נכשל</string>
<string name="open_link_failed_toast">לא נמצאו יישומים לפתיחת קישור זה</string>
<string name="complete_uninstall">הסרה מלאה</string>
<string name="restore_img">שיחזור תמונות</string>
<string name="restore_img_msg">משחזר…</string>
<string name="restore_done">השיחזור בוצע!</string>
@@ -229,5 +237,8 @@
<string name="authenticate">אימות</string>
<string name="unsupport_magisk_title">גרסת Magisk אינה נתמכת</string>
<string name="unsupport_magisk_msg">גרסה זו של מנהל Magisk אינה תומכת בגרסת Magisk הנמוכה מ-%1$s.\n\nהיישום יתנהג כאילו לא הותקן Magisk, אנא שדרג את Magisk בהקדם האפשרי.</string>
<string name="external_rw_permission_denied">הענק הרשאת אחסון להפעלת פונקציונליות זו</string>
<string name="add_shortcut_title">הוסף קיצור דרך למסך הבית</string>
<string name="add_shortcut_msg">לאחר שהסתיר את Magisk Manager, השם והסמל שלו עשויים להיות קשים לזיהוי. האם אתה רוצה להוסיף קיצור דרך יפה למסך הבית?</string>
<string name="app_not_found">לא נמצא יישום לטיפול בפעולה זו</string>
</resources>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SplashTheme" parent="Theme.Splash" />
<style name="Foundation" parent="Theme.Foundation" />
</resources>

View File

@@ -0,0 +1,244 @@
<resources>
<!--Sections-->
<string name="modules">ਮੋਡੀਊਲ</string>
<string name="superuser">ਸੁਪਰਯੂਜ਼ਰ</string>
<string name="logs">ਲੋਗਜ਼</string>
<string name="settings">ਸੈਟਿੰਗਜ਼</string>
<string name="refresh">ਸਥਾਨਕ ਡੇਟਾ ਨੂੰ ਤਾਜ਼ਾ ਕਰੋ</string>
<string name="install">ਇੰਸਟਾਲ</string>
<string name="section_home">ਹੋਮ</string>
<string name="section_theme">ਥੀਮ</string>
<string name="safetynet">ਸੇਫਟੀਨੇਟ</string>
<!--Home-->
<string name="no_connection">ਕੋਈ ਸੰਪਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ</string>
<string name="app_changelog">ਬਦਲਾਓ</string>
<string name="manager">ਮੈਨੇਜਰ</string>
<string name="loading">ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ</string>
<string name="update">ਅੱਪਡੇਟ</string>
<string name="not_available">N/A</string>
<string name="hide">ਓਹਲੇ</string>
<string name="status">ਸਥਿਤੀ</string>
<string name="home_package">ਪੈਕੇਜ</string>
<string name="home_notice_content">ਹਮੇਸ਼ਾਂ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਓਪਨ-ਸੋਰਸ ਮੈਜਿਸਕ ਮੈਨੀਜ਼ਰ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੇ ਹੋ। ਅਗਿਆਤ ਸਰੋਤ ਪ੍ਰਬੰਧਕ ਦੁਰਭਾਵਨਾਤਮਕ ਕਾਰਜ ਕਰ ਸਕਦੇ ਹਨ।</string>
<string name="home_support_title">ਸਾਡਾ ਸਮਰਥਨ ਕਰੋ</string>
<string name="home_item_source">ਸਰੋਤ</string>
<string name="home_support_content">ਮੈਜਿਸਕ ਮੁਫਤ ਅਤੇ ਖੁੱਲਾ ਸਰੋਤ ਹੈ, ਅਤੇ ਹਮੇਸ਼ਾਂ ਰਹੇਗਾ। ਹਾਲਾਂਕਿ, ਤੁਸੀਂ ਦਿਖਾ ਸਕਦੇ ਹੋ ਕਿ ਤੁਸੀਂ ਇੱਕ ਛੋਟਾ ਜਿਹਾ ਦਾਨ ਭੇਜ ਕੇ ਦੇਖਭਾਲ ਕਰਦੇ ਹੋ।</string>
<string name="home_status_normal">ਸਧਾਰਨ</string>
<string name="home_status_stub">ਸਟੱਬ</string>
<string name="home_installed_version">ਇੰਸਟਾਲਡ</string>
<string name="home_latest_version">ਨਵੀਨਤਮ</string>
<string name="invalid_update_channel">ਅਵੈਧ ਅਪਡੇਟ ਚੈਨਲ</string>
<string name="uninstall_magisk_title">ਮੈਜਿਸਕ ਨੂੰ ਅਣਇੰਸਟੌਲ ਕਰੋ</string>
<string name="uninstall_magisk_msg">ਸਾਰੇ ਮੋਡੀਊਲ ਅਯੋਗ/ਮਿਟਾ ਦਿੱਤੇ ਜਾਣਗੇ!\n ਰੂਟ ਨੂੰ ਹਟਾਇਆ ਜਾਏਗਾ!\n ਤੁਹਾਡਾ ਡਾਟਾ ਸੰਭਾਵਤ ਤੌਰ ਤੇ ਐਨਕ੍ਰਿਪਟ ਕੀਤਾ ਗਿਆ ਹੈ ਜੇ ਪਹਿਲਾਂ ਹੀ ਨਹੀਂ!</string>
<string name="home_check_safetynet">ਸੇਫਟੀਨੇਟ ਦੀ ਜਾਂਚ ਕਰੋ</string>
<!--Install-->
<string name="keep_force_encryption">ਫੋਰਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਨੂੰ ਸੁਰੱਖਿਅਤ ਰੱਖੋ</string>
<string name="keep_dm_verity">AVB 2.0/dm-verity ਨੂੰ ਸੁਰੱਖਿਅਤ ਰੱਖੋ</string>
<string name="recovery_mode">ਰਿਕਵਰੀ ਮੋਡ</string>
<string name="install_options_title">ਚੋਣ</string>
<string name="install_method_title">ਤਰੀਕਾ</string>
<string name="install_next">ਅੱਗੇ</string>
<string name="install_start">ਤਾਂ ਆਓ ਸ਼ੁਰੂ ਕਰੀਏ!</string>
<string name="manager_download_install">ਡਾਊਨਲੋਡ ਅਤੇ ਇੰਸਟੌਲ ਕਰਨ ਲਈ ਦਬਾਓ</string>
<string name="download_zip_only">ਸਿਰਫ ਜ਼ਿਪ ਡਾਊਨਲੋਡ ਕਰੋ</string>
<string name="direct_install">ਸਿੱਦਾ ਇੰਸਟਾਲ (ਸਿਫਾਰਸ਼ੀ)</string>
<string name="install_inactive_slot">ਨਾ-ਸਰਗਰਮ ਸਲਾਟ ਵਿੱਚ ਇੰਸਟਾਲ ਕਰੋ (OTA ਤੋਂ ਬਾਅਦ)</string>
<string name="install_inactive_slot_msg">ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਨੂੰ ਮੁੜ ਚਾਲੂ ਹੋਣ ਤੋਂ ਬਾਅਦ ਮੌਜੂਦਾ ਨਿਸ਼ਕਿਰਿਆ ਨੰਬਰ ਤੇ ਬੂਟ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕੀਤਾ ਜਾਏਗਾ!\n OTA ਪੂਰਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਹੀ ਇਸ ਵਿਕਲਪ ਦੀ ਵਰਤੋਂ ਕਰੋ।\n ਜਾਰੀ ਰੱਖਣਾ ਹੈ?</string>
<string name="setup_title">ਅਤਿਰਿਕਤ ਸੈਟਅਪ</string>
<string name="select_patch_file">ਇੱਕ ਫਾਈਲ ਚੁਣੋ ਅਤੇ ਪੈਚ ਕਰੋ</string>
<string name="patch_file_msg">ਇੱਕ ਰੋ ਛੱਞੀ ਨੂੰ (* .img) ਜਾਂ ਇੱਕ Odin tarfile (* .tar) ਦੀ ਚੋਣ ਕਰੋ</string>
<string name="reboot_delay_toast">5 ਸਕਿੰਟਾਂ ਵਿੱਚ ਰੀਬੂਟ ਹੋ ਰਿਹਾ ਹੈ …</string>
<string name="flash_screen_title">ਇੰਸਟਾਲੇਸ਼ਨ</string>
<!--Superuser-->
<string name="su_request_title">ਸੁਪਰਯੂਜ਼ਰ ਮੰਗ</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="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_revoke_title">ਅਧਿਕਾਰ ਵਾਪਸ ਲਓ?</string>
<string name="su_revoke_msg"> %1$s ਦੇ ਅਧਿਕਾਰਾਂ ਨੂੰ ਰੱਦ ਕਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦੇ ਹੋ?</string>
<string name="toast">ਪੌਪ-ਅੱਪ ਸੂਚਨਾ</string>
<string name="none">ਕੋਈ ਨਹੀਂ</string>
<string name="superuser_toggle_notification">ਸੂਚਨਾ</string>
<string name="superuser_toggle_revoke">ਅਧਿਕਾਰ ਵਾਪਸ ਲਓ</string>
<string name="superuser_policy_none">ਅਜੇ ਤੱਕ ਕਿਸੇ ਵੀ ਐਪ ਨੇ ਸੁਪਰਯੂਜ਼ਰ ਲਈ ਆਗਿਆ ਨਹੀਂ ਮੰਗੀ ਹੈ।</string>
<!--Logs-->
<string name="log_data_none">ਕੋਈ ਲੌਗਸ ਨਹੀਂ, ਆਪਣੀ ਸੁਪਰਯੂਜ਼ਰ ਸਮਰਥਿਤ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਹੋਰ ਵਰਤਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</string>
<string name="log_data_magisk_none">ਮੈਜਿਸਕ ਲੌਗਸ ਖਾਲੀ ਹਨ, ਇਹ ਅਜੀਬ ਹੈ।</string>
<string name="menuSaveLog">ਲੌਗ ਸੇਵ ਕਰੋ</string>
<string name="menuClearLog">ਲੌਗ ਸਾਫ ਕਰੋ</string>
<string name="logs_cleared">ਲੌਗ ਸਫਲਤਾਪੂਰਕ ਸਾਫ ਹੋ ਗਏ ਹਨ।</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">ਟੀਚਾ UID: %1$d</string>
<!--SafetyNet-->
<string name="safetynet_api_error">ਸੇਫਟੀਨੇਟ ਏਪੀਆਈ ਗਲਤੀ</string>
<string name="safetynet_res_invalid">ਜਵਾਬ ਅਵੈਧ ਹੈ</string>
<string name="safetynet_attest_success">ਸਫਲਤਾ!</string>
<string name="safetynet_attest_failure">ਤਸਦੀਕ ਅਸਫਲ!</string>
<string name="safetynet_attest_loading">ਸਿਰਫ ਇਕ ਸਕਿੰਟ…</string>
<string name="safetynet_attest_restart">ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ</string>
<!-- MagiskHide -->
<string name="show_system_app">ਸਿਸਟਮ ਐਪਸ ਦਿਖਾਓ</string>
<string name="show_os_app">OS ਐਪਲੀਕੇਸ਼ਨ ਦਿਖਾਓ</string>
<string name="hide_filter_hint">ਨਾਮ ਦੁਆਰਾ ਫਿਲਟਰ ਕਰੋ</string>
<string name="hide_scroll_up">ਉੱਪਰ ਸਕ੍ਰੌਲ ਕਰੋ</string>
<string name="hide_filters">ਫਿਲਟਰ</string>
<string name="hide_search">ਖੋਜੋ</string>
<!--Module -->
<string name="no_info_provided">(ਕੋਈ ਜਾਣਕਾਰੀ ਨਹੀਂ ਦਿੱਤੀ ਗਈ)</string>
<string name="reboot_userspace">ਸਾਫਟ ਰੀਬੂਟ</string>
<string name="reboot_recovery">ਰਿਕਵਰੀ ਰੀਬੂਟ</string>
<string name="reboot_bootloader">ਬੂਟਲੋਡਰ ਰੀਬੂਟ</string>
<string name="reboot_download">ਡਾਊਨਲੋਡ ਮੋਡ ਰੀਬੂਟ</string>
<string name="reboot_edl">EDL ਰੀਬੂਟ</string>
<string name="module_version_author"> %2$s ਦੇ ਦੁਆਰਾ %1$s</string>
<string name="module_section_pending">ਅਪਡੇਟਸ</string>
<string name="module_section_pending_action">ਸਾਰੇ ਅਪਡੇਟ ਕਰੋ</string>
<string name="module_state_remove">ਹਟਾਓ</string>
<string name="module_state_restore">ਰੀਸਟੋਰ ਕਰੋ</string>
<string name="module_action_install_external">ਸਟੋਰੇਜ ਤੋਂ ਇੰਸਟਾਲ ਕਰੋ</string>
<string name="update_available">ਅਪਡੇਟ ਉਪਲੱਬਧ ਹੈ</string>
<string name="module_installed">ਇੰਸਟਾਲਡ</string>
<string name="module_section_online">ਆਨਲਾਈਨ</string>
<string name="sorting_order">ਲੜੀਬੱਧ ਵਿਧੀ</string>
<!--Settings -->
<string name="settings_dark_mode_title">ਥੀਮ ਮੋਡ</string>
<string name="settings_dark_mode_message">ਕੋਈ ਥੀਮ ਚੁਣੋ ਜੋ ਤੁਹਾਡੀ ਸ਼ੈਲੀ ਦੇ ਅਨੁਕੂਲ ਹੋਵੇ!</string>
<string name="settings_dark_mode_light">ਹਮੇਸ਼ਾਂ ਚਿੱਟੇ ਰੰਗ ਦੀ</string>
<string name="settings_dark_mode_system">ਸਿਸਟਮ ਦੇ ਅਨੁਸਾਰ</string>
<string name="settings_dark_mode_dark">ਹਮੇਸ਼ਾ ਗਹਿਰੇ ਰੰਗ ਦੀ</string>
<string name="settings_download_path_title">ਡਾਊਨਲੋਡ ਮਾਰਗ</string>
<string name="settings_download_path_message">ਫਾਈਲਾਂ ਨੂੰ %1$s ਵਿੱਚ ਸੇਵ ਕੀਤਾ ਜਾਏਗਾ</string>
<string name="settings_clear_cache_title">ਰੈਪੋ ਕੈਚੇ ਸਾਫ਼ ਕਰੋ</string>
<string name="settings_clear_cache_summary">ਆਨਲਾਈਨਨ ਰਿਪੋਜ਼ ਲਈ ਕੈਸ਼ ਕੀਤੀ ਜਾਣਕਾਰੀ ਸਾਫ ਕਰੋ। ਇਹ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਆਨਲਾਈਨ ਤਾਜ਼ਾ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰਦਾ ਹੈ।</string>
<string name="settings_hide_manager_title">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਓਹਲੇ ਕਰੋ</string>
<string name="settings_hide_manager_summary">ਬੇਤਰਤੀਬੇ ਪੈਕੇਜ ਅਤੇ ਐਪ ਦੇ ਨਾਮਾਂ ਨਾਲ ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਰਿ੫ੇਕੇਜ ਕਰੋ</string>
<string name="settings_restore_manager_title">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਰੀਸਟੋਰ ਕਰੋ</string>
<string name="settings_restore_manager_summary">ਅਸਲੀ ਪੈਕੇਜ ਅਤੇ ਐਪਲੀਕੇਸ਼ ਦੇ ਨਾਮ ਨਾਲ ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਰੀਸਟੋਰ ਕਰੋ</string>
<string name="language">ਭਾਸ਼ਾ</string>
<string name="system_default">(ਸਿਸਟਮ ਡਿਫੌਲਟ)</string>
<string name="settings_check_update_title">ਚੈੱਕ ਅੱਪਡੇਟ</string>
<string name="settings_check_update_summary">ਸਮੇਂ-ਸਮੇਂ \'ਤੇ ਪਿਛੋਕੜ ਦੇ ਅਪਡੇਟਾਂ ਦੀ ਜਾਂਚ ਕਰੋ</string>
<string name="settings_update_channel_title">ਅਪਡੇਟ ਚੈਨਲ</string>
<string name="settings_update_stable">ਸਥਿਰ</string>
<string name="settings_update_beta">ਬੀਟਾ</string>
<string name="settings_update_custom">ਕਸਟਮ ਚੈਨਲ</string>
<string name="settings_update_custom_msg">ਇੱਕ ਕਸਟਮ URL ਦਾਖਲ ਕਰੋ</string>
<string name="settings_magiskhide_summary">ਵੱਖ ਵੱਖ ਕਿਸਮਾਂ ਦੀਆਂ ਖੋਜਾਂ ਤੋਂ ਬਚਣ ਲਈ ਮੈਜਿਸਕ ਨੂੰ ਓਹਲੇ ਕਰੋ</string>
<string name="settings_hosts_title">Systemless ਹੋਸਟ</string>
<string name="settings_hosts_summary">Adblock ਐਪਸ ਲਈ Systemless ਹੋਸਟ ਦੀ ਸਹਿਯੋਗ</string>
<string name="settings_hosts_toast">Systemless ਹੋਸਟ ਮੋਡੀਊਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ</string>
<string name="settings_app_name_hint">ਨਵਾਂ ਨਾਮ</string>
<string name="settings_app_name_helper">ਇਸ ਨਾਮ ਨਾਲ ਐਪ ਦੁਬਾਰਾ ਇੰਸਟਾਲ ਕੀਤਾ ਜਾਵੇਗਾ</string>
<string name="settings_app_name_error">ਗਲਤ ਫਾਰਮੈਟ</string>
<string name="settings_su_app_adb">ਐਪਸ ਅਤੇ ਐਡਬੀ</string>
<string name="settings_su_app">ਸਿਰਫ ਐਪਸ</string>
<string name="settings_su_adb">ਸਿਰਫ ਐਡਬੀ</string>
<string name="settings_su_disable">ਬੰਦ ਹੈ</string>
<string name="settings_su_request_10">10 ਸਕਿੰਟ</string>
<string name="settings_su_request_15">15 ਸਕਿੰਟ</string>
<string name="settings_su_request_20">20 ਸਕਿੰਟ</string>
<string name="settings_su_request_30">30 ਸਕਿੰਟ</string>
<string name="settings_su_request_45">45 ਸਕਿੰਟ</string>
<string name="settings_su_request_60">60 ਸਕਿੰਟ</string>
<string name="superuser_access">ਸੁਪਰਯੂਜ਼ਰ ਐਕਸੈਸ</string>
<string name="auto_response">ਆਟੋਮੈਟਿਕ ਜਵਾਬ</string>
<string name="request_timeout">ਬੇਨਤੀ ਦਾ ਸਮਾਂ ਸਮਾਪਤ</string>
<string name="superuser_notification">ਸੁਪਰਯੂਜ਼ਰ ਸੂਚਨਾ</string>
<string name="settings_su_reauth_title">ਅਪਗ੍ਰੇਡ ਹੋਣ ਤੋਂ ਬਾਅਦ ਪ੍ਰਮਾਣਿਕਤਾ</string>
<string name="settings_su_reauth_summary">ਇੱਕ ਐਪ ਦੇ ਅਪਡੇਟ ਹੋਣ ਤੋਂ ਬਾਅਦ ਸੁਪਰਯੂਜ਼ਰ ਆਗਿਆ ਪ੍ਰਮਾਣਿਤ ਕਰੋ</string>
<string name="settings_su_biometric_title">ਬਾਇਓਮੈਟ੍ਰਿਕ ਪ੍ਰਮਾਣਿਕਤਾ ਦਾ ਯੋਗ ਕਰੋ</string>
<string name="settings_su_biometric_summary">ਸੁਪਰਯੂਜ਼ਰ ਦੀ ਆਗਿਆ ਦੇਣ ਲਈ ਬਾਇਓਮੈਟ੍ਰਿਕ ਪ੍ਰਮਾਣੀਕਰਣ ਦੀ ਵਰਤੋਂ ਕਰੋ</string>
<string name="no_biometric">ਅਸਮਰਥਿਤ ਡਿਵਾਈਸ ਜਾਂ ਕੋਈ ਬਾਇਓਮੈਟ੍ਰਿਕ ਸੈਟਿੰਗ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ</string>
<string name="settings_customization">ਕਸਟਮਾਈਜੇਸ਼ਨ</string>
<string name="setting_add_shortcut_summary">ਐਪ ਨੂੰ ਲੁਕਾਉਣ ਤੋਂ ਬਾਅਦ ਨਾਮ ਅਤੇ ਆਈਕਾਨ ਨੂੰ ਪਛਾਣਨਾ ਮੁਸ਼ਕਲ ਹੈ, ਤਾਂ ਹੋਮ ਸਕ੍ਰੀਨ ਵਿਚ ਇਕ ਸੁੰਦਰ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰੋ</string>
<string name="settings_doh_title">DNS ਉੱਤੇ HTTPS</string>
<string name="settings_doh_description">ਕੁਝ ਦੇਸ਼ਾਂ ਵਿੱਚ ਚੱਲ ਰਹੇ DNS ਵਿਸ਼ਾਕਤਤਾ ਦਾ ਹੱਲ</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="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>
<!--Notifications-->
<string name="update_channel">ਮੈਜਿਸਕ ਅਪਡੇਟ</string>
<string name="progress_channel">ਤਰੱਕੀ ਦੀਆਂ ਸੂਚਨਾਵਾਂ</string>
<string name="download_complete">ਡਾਊਨਲੋਡ ਪੂਰਾ</string>
<string name="download_file_error">ਫਾਈਲ ਡਾਊਨਲੋਡ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ</string>
<string name="download_open_parent">ਮੁੱਢਲੇ ਫੋਲਡਰ ਵਿੱਚ ਦਿਖਾਓ</string>
<string name="download_open_self">ਫਾਈਲ ਦਿਖਾਓ</string>
<string name="magisk_update_title">ਮੈਜਿਸਕ ਅਪਡੇਟ ਉਪਲੱਬਧ!</string>
<string name="manager_update_title">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਲਈ ਅਪਡੇਟ ਉਪਲੱਬਧ ਹੈ!</string>
<!--Toasts, Dialogs-->
<string name="yes">ਹਾਂ</string>
<string name="no">ਨਹੀਂ</string>
<string name="repo_install_title">ਇੰਸਟਾਲ %1$s</string>
<string name="repo_install_msg">ਕੀ ਤੁਸੀਂ ਹੁਣੇ %1$s ਇੰਸਟਾਲ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="download">ਡਾਊਨਲੋਡ</string>
<string name="reboot">ਰੀਬੂਟ</string>
<string name="release_notes">ਰੀਲਿਜ਼ ਨੋਟਿਸ</string>
<string name="repo_cache_cleared">ਰਿਪੋ ਕੈਚੇ ਸਾਫ਼ ਕੀਤਾ</string>
<string name="flashing">ਫਲੈਸ਼ਿੰਗ …</string>
<string name="done">ਸਫਲ ਹੋਇਆ!</string>
<string name="failure">ਅਸਫਲ ਹੋਇਆ</string>
<string name="hide_manager_title">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਲੁਕਾਇਆ ਜਾ ਰਿਹਾ ਹੈ …</string>
<string name="hide_manager_fail_toast">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਓਹਲੇ ਕਰਨ ਵਿੱਚ ਅਸਫਲ</string>
<string name="restore_manager_fail_toast">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਰਿਸਟੋਰ ਕਰਨਾ ਵਿਫਲ ਹੋਇਆ</string>
<string name="open_link_failed_toast">ਲਿੰਕ ਖੋਲ੍ਹਣ ਲਈ ਕੋਈ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਮਿਲੀ</string>
<string name="complete_uninstall">ਪੂਰੀ ਤਰ੍ਹਾਂ ਅਣਇੰਸਟੌਲ ਕਰੋ</string>
<string name="restore_img">ਇਮੇਜ ਰਿਸਟੋਰ ਕਰੋ</string>
<string name="restore_img_msg">ਰਿਸਟੋਰ ਹੋ ਰਿਹਾ ਹੈ …</string>
<string name="restore_done">रिस्टोर ਸਫਲ ਹੋਇਆ!</string>
<string name="restore_fail">ਸਟਾਕ ਬੈਕਅਪ ਮੌਜੂਦ ਨਹੀਂ ਹੈ!</string>
<string name="proprietary_title">ਮਲਕੀਅਤ ਕੋਡ ਡਾਉਨਲੋਡ ਕਰੋ</string>
<string name="proprietary_notice">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਇੱਕ ਮੁਫਤ ਅਤੇ ਓਪਨ ਸੋਰਸ ਐਪ ਹੈ ਜੋ ਗੂਗਲ ਦੇ ਮਲਕੀਅਤ ਸੁਰੱਖਿਆ ਕੋਡ ਦੀ ਵਰਤੋਂ ਨਹੀਂ ਕਰਦਾ। ਕੀ ਤੁਸੀਂ ਸੁਰੱਖਿਆ ਨੂੰ ਵੇਖਣ ਲਈ ਮੈਸਿਕ ਮੈਨੇਜਰ ਨੂੰ ਇੱਕ ਐਕਸਟੈਂਸ਼ਨ ਡਾ ਡਾਊਨਲੋਡ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="setup_fail">ਸੈਟਅਪ ਅਸਫਲ ਹੋਇਆ</string>
<string name="env_fix_title">ਵਾਧੂ ਸੈਟਅਪ ਚਾਹੀਦਾ ਹੈ</string>
<string name="env_fix_msg">ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਤੇ ਮੈਜਿਸਕ ਨੂੰ ਸਹੀ ਤਰ੍ਹਾਂ ਕੰਮ ਕਰਨ ਲਈ ਵਾਧੂ ਸੈਟਅਪ ਦੀ ਲੋੜ ਹੈ। ਇਹ ਇੱਕ ਮੈਜਿਸਕ ਸੈਟਅਪ ਜ਼ਿਪ ਡਾਉਨਲੋਡ ਕਰੇਗਾ, ਕੀ ਤੁਸੀਂ ਅੱਗੇ ਵਧਣਾ ਚਾਹੋਗੇ?</string>
<string name="setup_msg">ਵਾਤਾਵਰਣ ਸੈਟਅਪ ਚੱਲ ਰਿਹਾ ਹੈ …</string>
<string name="authenticate">ਪ੍ਰਮਾਣਿਤ ਕਰੋ</string>
<string name="unsupport_magisk_title">ਗ਼ੈਰ ਮੈਜਿਸਕ ਵਰਜਨ</string>
<string name="unsupport_magisk_msg">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਦਾ ਇਹ ਵਰਜਨ ਮੈਜਿਸਕ ਵਰਜਨ %1$s ਤੋਂ ਘੱਟ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ।\n\n ਐਪ ਇਸ ਤਰ੍ਹਾਂ ਦਾ ਵਿਵਹਾਰ ਕਰੇਗੀ ਜਿਵੇਂ ਮੈਜਿਸਕ ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ, ਕਿਰਪਾ ਕਰਕੇ ਜਲਦੀ ਹੀ ਮੈਜਿਸਕ ਨੂੰ ਅਪਗ੍ਰੇਡ ਕਰੋ।</string>
<string name="external_rw_permission_denied">ਇਸ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਸਟੋਰੇਜ ਦੀ ਆਗਿਆ ਦਿਓ</string>
<string name="add_shortcut_title">ਹੋਮਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰੋ</string>
<string name="add_shortcut_msg">ਮੈਜਿਸਕ ਮੈਨੇਜਰ ਨੂੰ ਲੁਕਾਉਣ ਤੋਂ ਬਾਅਦ ਇਸਦੇ ਨਾਮ ਅਤੇ ਆਈਕਾਨ ਦੀ ਪਛਾਣ ਕਰਨਾ ਮੁਸ਼ਕਲ ਹੋ ਸਕਦਾ ਹੈ, ਕੀ ਤੁਸੀਂ ਹੋਮਸਕ੍ਰੀਨ ਤੇ ਇੱਕ ਵਧੀਆ ਲੁੱਕ ਸ਼ੌਰਟਕਟ ਸ਼ਾਮਲ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?</string>
<string name="app_not_found">ਇਸ ਐਕਸ਼ਨ ਨੂੰ ਸੰਭਾਲਣ ਲਈ ਕੋਈ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਮਿਲੀ</string>
</resources>

View File

@@ -22,7 +22,7 @@
<string name="status">Stare</string>
<string name="home_package">Pachet</string>
<string name="home_notice_content">Asigură-te întotdeauna că folosești aplicația open-source Magisk Manager. Managerul din surse necunoscute poate efectua acțiuni rău-intenționate.</string>
<string name="home_notice_content">Asigură-te întotdeauna că folosești aplicația open-source Magisk Manager. Managerul din surse necunoscute poate efectua acțiuni rău-intenționate!</string>
<string name="home_support_title">Sprijină-ne</string>
<string name="home_item_source">Sursă</string>
<string name="home_support_content">Magisk este și va fi întotdeauna gratuit și open-source. Cu toate acestea, ne poți arăta că îți pasă trimițând o mică donație.</string>
@@ -55,7 +55,8 @@
<string name="flash_screen_title">Instalare</string>
<!--Superuser-->
<string name="su_request_title">Solicitare de superutilizator</string>
<string name="su_request_title">Cerere de superutilizator</string>
<string name="touch_filtered_warning">Deoarece o aplicație ascunde o cerere de superutilizator, Magisk nu îți poate verifica răspunsul</string>
<string name="deny">Refuză</string>
<string name="prompt">Solicită</string>
<string name="grant">Acordă</string>
@@ -81,14 +82,14 @@
<string name="superuser_toggle_notification">Notificări</string>
<string name="superuser_toggle_revoke">Revocă</string>
<string name="superuser_policy_none">Nicio aplicație nu a solicitat încă permisiuni de superutilizator.</string>
<string name="superuser_policy_none">Nicio aplicație nu a cerut încă permisiuni de superutilizator.</string>
<!--Logs-->
<string name="log_data_none">Nu există jurnale, încearcă să folosești ceva mai mult aplicațiile cu acces de superutilizator.</string>
<string name="log_data_magisk_none">Jurnalele Magisk sunt goale, asta-i ciudat.</string>
<string name="log_data_none">Nu există jurnale, încearcă să folosești ceva mai mult aplicațiile cu acces de superutilizator</string>
<string name="log_data_magisk_none">Jurnalele Magisk sunt goale, asta-i ciudat</string>
<string name="menuSaveLog">Salvează jurnalul</string>
<string name="menuClearLog">Golește jurnalul acum</string>
<string name="logs_cleared">Jurnal golit cu succes.</string>
<string name="logs_cleared">Jurnal golit cu succes</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">UID țintă: %1$d</string>
@@ -100,15 +101,17 @@
<string name="safetynet_attest_loading">Așteaptă o clipă…</string>
<string name="safetynet_attest_restart">Încearcă din nou</string>
<!-- MagiskHide -->
<!--MagiskHide-->
<string name="show_system_app">Afișează aplicațiile de sistem</string>
<string name="show_os_app">Afișează aplicațiile SO-ului</string>
<string name="hide_filter_hint">Filtrează după nume</string>
<string name="hide_scroll_up">Derulează în sus</string>
<string name="hide_filters">Filtre</string>
<string name="hide_search">Căutare</string>
<!--Module -->
<!--Module-->
<string name="no_info_provided">(Nu sunt furnizate informații)</string>
<string name="reboot_userspace">Repornire software</string>
<string name="reboot_recovery">Repornește în modul recovery</string>
<string name="reboot_bootloader">Repornește în modul bootloader</string>
<string name="reboot_download">Repornește în modul download</string>
@@ -124,7 +127,7 @@
<string name="module_section_online">Online</string>
<string name="sorting_order">Ordine de sortare</string>
<!--Settings -->
<!--Settings-->
<string name="settings_dark_mode_title">Mod pentru temă</string>
<string name="settings_dark_mode_message">Selectează modul care ți se pliază cel mai bine stilului!</string>
<string name="settings_dark_mode_light">Mereu deschis</string>
@@ -133,7 +136,7 @@
<string name="settings_download_path_title">Cale de descărcare</string>
<string name="settings_download_path_message">Fișierele vor fi salvate în %1$s</string>
<string name="settings_clear_cache_title">Golește cache-ul depozitelor</string>
<string name="settings_clear_cache_summary">Golește informațiile memorate în cache pentru depozitele online. Acest lucru forțează actualizarea aplicației online.</string>
<string name="settings_clear_cache_summary">Golește informațiile memorate în cache pentru depozitele online. Acest lucru forțează actualizarea aplicației online</string>
<string name="settings_hide_manager_title">Ascunde Magisk Manager</string>
<string name="settings_hide_manager_summary">Reîmpachetează Magisk Manager cu numele aleatorii pentru pachet și aplicație</string>
<string name="settings_restore_manager_title">Restaurează Magisk Manager</string>
@@ -166,10 +169,12 @@
<string name="settings_su_request_60">60 de secunde</string>
<string name="superuser_access">Acces pentru superutilizator</string>
<string name="auto_response">Răspuns automat</string>
<string name="request_timeout">Expirare pentru solicitare</string>
<string name="request_timeout">Expirare pentru cerere</string>
<string name="superuser_notification">Notificare de superutilizator</string>
<string name="settings_su_reauth_title">Reautentificare după actualizare</string>
<string name="settings_su_reauth_summary">Reautentifică permisiunile pentru superutilizator după o actualizare a aplicației</string>
<string name="settings_su_tapjack_title">Activează protecția față de tapjacking</string>
<string name="settings_su_tapjack_summary">Caseta de dialog pentru solicitarea drepturilor de superutilizator nu va răspunde la input cât timp este ascunsă de orice altă fereastră sau suprapunere</string>
<string name="settings_su_biometric_title">Activează autentificarea biometrică</string>
<string name="settings_su_biometric_summary">Folosește autentificarea biometrică pentru a permite cereri de superutilizator</string>
<string name="no_biometric">Dispozitiv nesuportat sau nu sunt activate setări biometrice</string>
@@ -183,7 +188,7 @@
<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 să gestioneze accesul la root și să primească solicitări</string>
<string name="owner_manage_summary">Numai proprietarul poate să gestioneze accesul la root și să primească cereri</string>
<string name="user_indepenent_summary">Fiecare utilizator are propriile sale reguli separate pentru root</string>
<string name="mount_namespace_mode">Modul spațiului de nume pentru montare</string>
@@ -215,9 +220,10 @@
<string name="repo_cache_cleared">Cache-ul depozitelor golit</string>
<string name="flashing">Se scrie în memoria flash…</string>
<string name="done">Terminat!</string>
<string name="failure">Eșec</string>
<string name="failure">Eșec!</string>
<string name="hide_manager_title">Se ascunde Magisk Manager…</string>
<string name="hide_manager_fail_toast">Ascunderea Magisk Manager a eșuat.</string>
<string name="hide_manager_fail_toast">Ascunderea Magisk Manager a eșuat</string>
<string name="restore_manager_fail_toast">Restaurarea Magisk Manager a eșuat</string>
<string name="open_link_failed_toast">Nu a fost găsită nicio aplicație pentru a deschide linkul</string>
<string name="complete_uninstall">Finalizează dezinstalarea</string>
<string name="restore_img">Restaurează imagini</string>

View File

@@ -22,7 +22,7 @@
<string name="status">Stav</string>
<string name="home_package">Balíček</string>
<string name="home_notice_content">Vždy sa uistite, že používate Magisk Manager s otvoreným kódom. Správca z neznámeho zdroja môže vykonávať škodlivé akcie.</string>
<string name="home_notice_content">Vždy sa uistite, že používate Magisk Manager s otvoreným kódom. Správca z neznámeho zdroja môže vykonávať škodlivé akcie!</string>
<string name="home_support_title">Podporte nás</string>
<string name="home_item_source">Zdroj</string>
<string name="home_support_content">Magisk je a vždy bude slobodný a s otvoreným kódom. Môžete nám však ukázať, že vám na tom záleží zaslaním malého daru.</string>
@@ -44,7 +44,7 @@
<string name="install_next">Ďalej</string>
<string name="install_start">Poďme na to</string>
<string name="manager_download_install">Stlačte pre stiahnutie a inštaláciu</string>
<string name="download_zip_only">Len tiahnuť zip</string>
<string name="download_zip_only">Len stiahnuť zip</string>
<string name="direct_install">Priama inštalácia (Odporúča sa)</string>
<string name="install_inactive_slot">Inštalovať na neaktívny slot (Po OTA)</string>
<string name="install_inactive_slot_msg">Vaše zariadenie bude po reštarte PRINÚTENÉ nabootovať do aktuálne neaktívneho slotu!\nTúto voľbu použite iba po skončení OTA.\nPokračovať?</string>
@@ -85,11 +85,11 @@
<string name="superuser_policy_none">Žiadna aplikácia zatiaľ nepožiadala o povolenie Superužívateľa.</string>
<!--Logs-->
<string name="log_data_none">Nie sú žiadne záznamy, skúste nejakú appku vyžadujúcu práva Superužívateľa.</string>
<string name="log_data_magisk_none">Záznamy Magisku sú prázdne, to je divné.</string>
<string name="log_data_none">Nie sú žiadne záznamy, skúste nejakú appku vyžadujúcu práva Superužívateľa</string>
<string name="log_data_magisk_none">Záznamy Magisku sú prázdne, to je divné</string>
<string name="menuSaveLog">Uložiť záznam</string>
<string name="menuClearLog">Odstrániť záznam</string>
<string name="logs_cleared">Záznam úspešne odstránený.</string>
<string name="logs_cleared">Záznam úspešne odstránený</string>
<string name="pid">PID:%1$d</string>
<string name="target_uid">Cieľový UID: %1$d</string>
@@ -101,7 +101,7 @@
<string name="safetynet_attest_loading">Momentík ...</string>
<string name="safetynet_attest_restart">Skúste to znova</string>
<!-- MagiskHide -->
<!--MagiskHide-->
<string name="show_system_app">Zobraziť systémové aplikácie</string>
<string name="show_os_app">Zobraziť aplikácie OS</string>
<string name="hide_filter_hint">Filtrovať podľa názvu</string>
@@ -109,7 +109,7 @@
<string name="hide_filters">Filtre</string>
<string name="hide_search">Vyhľadávanie</string>
<!--Module Fragment-->
<!--Module-->
<string name="no_info_provided">(Nie sú k dispozícii žiadne informácie)</string>
<string name="reboot_userspace">Softvérový reštart</string>
<string name="reboot_recovery">Reštartovať do Recovery</string>
@@ -129,7 +129,7 @@
<!--Settings -->
<!--Settings-->
<string name="settings_dark_mode_title">Režim motívu</string>
<string name="settings_dark_mode_message">Vyberte režim, ktorý najlepšie vyhovuje vášmu štýlu!</string>
<string name="settings_dark_mode_light">Vždy svetlý</string>
@@ -222,7 +222,7 @@
<string name="repo_cache_cleared">Cache repo odstránená</string>
<string name="flashing">Flashovanie...</string>
<string name="done">Hotovo!</string>
<string name="failure">Zlyhalo</string>
<string name="failure">Zlyhalo!</string>
<string name="hide_manager_title">Skrývanie Magisk Managera…</string>
<string name="hide_manager_fail_toast">Skrytie Magisk Managera zlyhalo</string>
<string name="restore_manager_fail_toast">Obnovenie Magisk Managera zlyhalo</string>

View File

@@ -0,0 +1,238 @@
<resources>
<!--Sections-->
<string name="modules">Modulet</string>
<string name="superuser">Superpërdoruesi</string>
<string name="logs">Regjistrat</string>
<string name="settings">Cilësimet</string>
<string name="refresh">Rifresko të Dhënat Lokale</string>
<string name="install">Instalo</string>
<string name="section_home">Shtëpia</string>
<string name="section_theme">Temat</string>
<string name="safetynet">Rrjeti i Sigurisë</string>
<!--Home-->
<string name="no_connection">Nuk ka lidhje interneti</string>
<string name="app_changelog">Ndryshimet</string>
<string name="manager">Menaxheri</string>
<string name="loading">Po ngarkon…</string>
<string name="update">Përditëso</string>
<string name="not_available">N/A</string>
<string name="hide">Fshih</string>
<string name="status">Statusi</string>
<string name="home_package">Paketa</string>
<string name="home_notice_content">Gjithmonë sigurohuni që jeni duke përdorur Magisk Manager me burim të hapur. Magisk Manager i një burimi të panjohur mund të kryejë veprime të dëmshme!</string>
<string name="home_support_title">Na ndihmoni</string>
<string name="home_item_source">Burimi</string>
<string name="home_support_content">Magisk është, dhe gjithmonë do të jetë, falas dhe me burim të hapur. Megjithatë mund të na tregoni se ju interesoni duke dërguar një donacion të vogël.</string>
<string name="home_status_normal">Normale</string>
<string name="home_status_stub">Stub</string>
<string name="home_installed_version">E instaluar</string>
<string name="home_latest_version">Më e fundit</string>
<string name="invalid_update_channel">Kanal i pavlefshëm i azhurnimit</string>
<string name="uninstall_magisk_title">Çinstalo Magisk</string>
<string name="uninstall_magisk_msg">Të gjitha modulet do të çaktivizohen/hiqen! \n Rrënja do të hiqet! \n\n Të dhënat tuaja potencialisht të koduara nëse jo tashmë!</string>
<string name="home_check_safetynet">Kontrolloni Rrjetin e Sigurisë</string>
<!--Install-->
<string name="keep_force_encryption">Ruaj kriptimin me forcë</string>
<string name="keep_dm_verity">Ruaj AVB 2.0 /dm-vërtetësi</string>
<string name="recovery_mode">Modaliteti i rikuperimit</string>
<string name="install_options_title">Opsionet</string>
<string name="install_method_title">Metoda</string>
<string name="install_next">Tjetra</string>
<string name="install_start">Le të shkojmë</string>
<string name="manager_download_install">Shtypni për të shkarkuar dhe instaluar</string>
<string name="download_zip_only">Shkarkoni vetëm Zip</string>
<string name="direct_install">Instalimi i drejtpërdrejtë (rekomandohet)</string>
<string name="install_inactive_slot">Instalo në Slot Inaktive (Pas OTA)</string>
<string name="install_inactive_slot_msg">Pajisja juaj do të detyrohet të nisë në vendndodhjen aktuale joaktive pas një rindezjeje! \n Të përdorni vetëm këtë mundësi pasi të keni mbaruar OTA. \n Vazhdoni? </string>
<string name="setup_title">Konfigurimi shtesë</string>
<string name="select_patch_file">Zgjidhni dhe Patch një Skedar</string>
<string name="patch_file_msg">Zgjidhni një imazh të papërpunuar (* .img) ose një tarifë ODIN (* .tar)</string>
<string name="reboot_delay_toast">Rinisje pas 5 sekonda…</string>
<string name="flash_screen_title">Instalimi</string>
<!--Superuser-->
<string name="touch_filtered_warning">Meqenëse një aplikacion po errëson një kërkesë të superpërdoruesit, Magisk nuk mund të verifikojë përgjigjen tuaj</string>
<string name="deny">Moho</string>
<string name="prompt">Pyet</string>
<string name="grant">Lejo</string>
<string name="su_warning">Jep akses të plotë në pajisjen tuaj. \n Moho nëse nuk je i sigurt!</string>
<string name="forever">Gjithmonë</string>
<string name="once">Një herë</string>
<string name="tenmin">10 minuta</string>
<string name="twentymin">20 minuta</string>
<string name="thirtymin">30 minuta</string>
<string name="sixtymin">60 minuta</string>
<string name="su_allow_toast">%1$s iu dha e drejta e superpërdoruesit</string>
<string name="su_deny_toast">%1$s iu refuzuan të drejtat e Superpërdoruesit</string>
<string name="su_snack_grant">Jep të drejtën e superpërdoruesit prej %1$s</string>
<string name="su_snack_deny">Të drejtat e superpërdoruesit prej %1$s mohohen</string>
<string name="su_snack_notif_on">Njoftimet e %1$s janë aktivizuar</string>
<string name="su_snack_notif_off">Njoftimet e %1$s janë çaktivizuar</string>
<string name="su_snack_log_on">Regjistrimi i %1$s është aktivizuar</string>
<string name="su_snack_log_off">Regjistrimi i %1$s është çaktivizuar</string>
<string name="su_revoke_title">Anulohet?</string>
<string name="su_revoke_msg">Konfirmo të heqësh të drejtat e %1$s?</string>
<string name="toast">dolli</string>
<string name="none">Asnjë</string>
<string name="superuser_toggle_notification">Njoftimet</string>
<string name="superuser_toggle_revoke">Anulo</string>
<string name="superuser_policy_none">Asnjë aplikacion nuk ka kërkuar ende leje për superpërdoruesin.</string>
<!--Logs-->
<string name="log_data_none">Ju jeni pa regjistrime, provoni të përdorni më shumë aplikacionet tuaja të aktivizuara SU</string>
<string name="log_data_magisk_none">Regjistrat e Magisk janë bosh, kjo është e çuditshme</string>
<string name="menuSaveLog">Ruaj regjistrin</string>
<string name="menuClearLog">Pastro regjistrin tani</string>
<string name="logs_cleared">Regjistri u pastrua me sukses</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">UID i synuar: %1$d</string>
<!--SafetyNet-->
<string name="safetynet_api_error">Gabim API i SafetyNet</string>
<string name="safetynet_res_invalid">Përgjigjja është e pavlefshme </string>
<string name="safetynet_attest_success">Suksese!</string>
<string name="safetynet_attest_failure">Vërtetimi dështoi!</string>
<string name="safetynet_attest_loading">Prit një sekondë…</string>
<string name="safetynet_attest_restart">Provo përsëri</string>
<!--MagiskHide-->
<string name="show_system_app">Shfaq aplikacionet e sistemit</string>
<string name="show_os_app">Shfaq aplikacionet e sistemit operativ</string>
<string name="hide_filter_hint">Filtro me emër</string>
<string name="hide_scroll_up">Lëviz lart</string>
<string name="hide_filters">Filtrat</string>
<string name="hide_search">Kërko</string>
<!--Module-->
<string name="no_info_provided">(Nuk ofrohet informacion)</string>
<string name="reboot_userspace">Ristartim normal</string>
<string name="reboot_recovery">Ristartoni në recovery</string>
<string name="reboot_bootloader">Ristartoni në bootloader</string>
<string name="reboot_download">Ristartoni në download</string>
<string name="reboot_edl">Ristartoni në EDL</string>
<string name="module_version_author">%1$s nga %2$s</string>
<string name="module_state_remove">Hiq</string>
<string name="module_state_restore">Rivendos</string>
<string name="module_action_install_external">Instaloni nga hapësira ruajtëse</string>
<string name="update_available">Përditësimi i disponueshëm</string>
<string name="module_installed">@string/home_installed_version</string>
<string name="module_section_online">Në internet</string>
<string name="sorting_order">Renditja e Renditjes</string>
<!--Settings-->
<string name="settings_dark_mode_title">Modaliteti i temës</string>
<string name="settings_dark_mode_message">Zgjidhni mënyrën e cila i përshtatet më mirë stilit tuaj!</string>
<string name="settings_dark_mode_light">Gjithmonë e lehtë</string>
<string name="settings_dark_mode_system">Ndiqni sistemin</string>
<string name="settings_dark_mode_dark">Gjithmonë e errët</string>
<string name="settings_download_path_title">Shtegu i shkarkimit</string>
<string name="settings_download_path_message">Skedarët do të ruhen në %1$s</string>
<string name="settings_clear_cache_title">Pastro Cache të Repos</string>
<string name="settings_clear_cache_summary">Pastroni informacionin e memorizuar për repot në internet. Kjo e detyron aplikacionin të rifreskohet në internet</string>
<string name="settings_hide_manager_title">Fshih menaxherin e Magisk</string>
<string name="settings_hide_manager_summary">Ripaketimi Magisk Manager me paketa të rastësishme dhe emra të aplikacioneve</string>
<string name="settings_restore_manager_title">Rivendos menaxherin e Magisk</string>
<string name="settings_restore_manager_summary">Rivendos Magisk Manager me paketën origjinale dhe emrat e aplikacioneve</string>
<string name="language">Gjuha</string>
<string name="system_default">(Parazgjedhja e Sistemit)</string>
<string name="settings_check_update_title">Kontrolloni azhurnimet</string>
<string name="settings_check_update_summary">Kontrolloni periodikisht për azhurnime në sfond</string>
<string name="settings_update_channel_title">Azhurnoni Kanalin</string>
<string name="settings_update_stable">Qëndrueshëm</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Kanali i personalizuar</string>
<string name="settings_update_custom_msg">Vendos një URL të personalizuar</string>
<string name="settings_magiskhide_summary">Fshih Magisk nga forma të ndryshme të zbulimit</string>
<string name="settings_hosts_title">Pritës pa sistem</string>
<string name="settings_hosts_summary">Mbështetja e hostëve pa sistem për aplikacionet Adblock</string>
<string name="settings_hosts_toast">Moduli i pritur i sistemit pa sistem</string>
<string name="settings_app_name_hint">Emër i ri</string>
<string name="settings_app_name_helper">Aplikacioni do të ripaketohet në këtë emër</string>
<string name="settings_app_name_error">Formati i pavlefshëm</string>
<string name="settings_su_app_adb">Aplikacionet dhe ADB</string>
<string name="settings_su_app">Vetëm aplikacionet</string>
<string name="settings_su_adb">Vetëm ADB</string>
<string name="settings_su_disable">Çaktivizuar</string>
<string name="settings_su_request_10">10 Sekonda</string>
<string name="settings_su_request_15">15 Sekonda</string>
<string name="settings_su_request_20">20 Sekonda</string>
<string name="settings_su_request_30">30 Sekonda</string>
<string name="settings_su_request_45">45 Sekonda</string>
<string name="settings_su_request_60">60 Sekonda</string>
<string name="superuser_access">Hyrja në superpërdorues</string>
<string name="auto_response">Përgjigje Automatike</string>
<string name="request_timeout">Koha e kërkesës</string>
<string name="superuser_notification">Njoftimi i superpërdoruesit</string>
<string name="settings_su_reauth_title">Ridentifikoni pas azhurnimit</string>
<string name="settings_su_reauth_summary">Ridentifikoni lejet e superpërdoruesit pas azhurnimeve të një aplikacioni</string>
<string name="settings_su_tapjack_title">Aktivizo Mbrojtjen nga Tapjacking</string>
<string name="settings_su_tapjack_summary">Dialogu i menjëhershëm i superpërdoruesit nuk do ti përgjigjet hyrjes ndërsa errësohet nga ndonjë dritare tjetër ose mbivendosja</string>
<string name="settings_su_biometric_title">Aktivizo vërtetimin biometrik</string>
<string name="settings_su_biometric_summary">Përdorni vërtetimin biometrik për të lejuar kërkesat e superpërdoruesit</string>
<string name="no_biometric">Pajisja e pambështetur ose nuk janë aktivizuar cilësime biometrike</string>
<string name="settings_customization">Përshtatje</string>
<string name="setting_add_shortcut_summary">"Shtoni një shkurtore të bukur në ekranin kryesor në rast se emri dhe ikona janë të vështira për t'u njohur pasi të keni fshehur aplikacionin"</string>
<string name="settings_doh_title">DNS mbi HTTPS</string>
<string name="settings_doh_description">Helmimi i paqartë nga DNS në disa kombe</string>
<string name="multiuser_mode">Modaliteti i shumë përdoruesit</string>
<string name="settings_owner_only">Vetëm zotëruesi i pajisjes</string>
<string name="settings_owner_manage">Pronari i Pajisjes i Menaxhuar</string>
<string name="settings_user_independent">Përdorues i Pavarur</string>
<string name="user_indepenent_summary">Çdo përdorues ka rregullat e tij/saj të veçanta rrënjësore</string>
<string name="mount_namespace_mode">Modaliteti i hapësirës së emrave të malit</string>
<string name="settings_ns_global">Hapësira Globale e Emrave</string>
<string name="settings_ns_requester">Trashëgoni Hapësirën e Emrave</string>
<string name="settings_ns_isolate">Hapësira e izoluar e emrave</string>
<string name="global_summary">Të gjitha sesionet rrënjësore përdorin hapësirën globale të emrave të montimit</string>
<string name="requester_summary">Seancat rrënjësore do të trashëgojnë hapësirën e emrave të kërkuesit të tyre</string>
<string name="isolate_summary">Çdo sesion rrënjë do të ketë hapësirën e vet të izoluar të tij</string>
<!--Notifications-->
<string name="update_channel">Përditësimet e Magisk</string>
<string name="progress_channel">Njoftimet e Progresit</string>
<string name="download_complete">Shkarkimi përfundoi</string>
<string name="download_file_error">Gabim në shkarkimin e skedarit</string>
<string name="download_open_parent">Shfaq në dosjen mëmë</string>
<string name="magisk_update_title">Mundësohet azhurnimi i Magisk!</string>
<string name="manager_update_title">Ka perditësime të ri të Magisk Manager!</string>
<!--Toasts, Dialogs-->
<string name="yes">Po</string>
<string name="no">Jo</string>
<string name="repo_install_title">Instalo %1$s</string>
<string name="repo_install_msg">Dëshiron të instalosh %1$s tani?</string>
<string name="download">Shkarkim</string>
<string name="reboot">Rinis</string>
<string name="release_notes">Lëshoni shënime</string>
<string name="repo_cache_cleared">Depoja e repos u pastrua</string>
<string name="flashing">Ndezje…</string>
<string name="done">U krye!</string>
<string name="failure">Dështoi!</string>
<string name="hide_manager_title">Fshehja e Magisk manager…</string>
<string name="hide_manager_fail_toast">Fsheh Menaxherin e Magisk dështoi</string>
<string name="restore_manager_fail_toast">Rikthimi i menaxherin e Magisk dështoi</string>
<string name="open_link_failed_toast">Asnjë aplikacion nuk u gjet për të hapur lidhjen</string>
<string name="complete_uninstall">Çinstalimi i plotë</string>
<string name="restore_img">Rikthe Imazhet</string>
<string name="restore_img_msg">Rivendosja…</string>
<string name="restore_done">Restaurimi u krye!</string>
<string name="restore_fail">Rezervimi i aksioneve nuk ekziston!</string>
<string name="proprietary_title">Shkarkoni Kodin e Pronarit</string>
<string name="proprietary_notice">Magisk Manager është FOSS dhe nuk përmban kodin e pronarit të Google SecurityNet API. \n\n A do të lejoni që Magisk Manager të shkarkojë një shtesë (përmban GoogleApiClient) për kontrollet e SafetyNet?</string>
<string name="setup_fail">Konfigurimi dështoi</string>
<string name="env_fix_title">Kërkon Konfigurim Shtesë</string>
<string name="env_fix_msg">Pajisja juaj ka nevojë për konfigurim shtesë që Magisk të funksionojë siç duhet. Do të shkarkojë zip-in e konfigurimit të Magisk, doni të vazhdoni tani?</string>
<string name="setup_msg">Konfigurimi i mjedisit drejtues…</string>
<string name="authenticate">Vërteto</string>
<string name="unsupport_magisk_title">Versioni i pambështetur i Magisk</string>
<string name="unsupport_magisk_msg">Ky version i Magisk Manager nuk e mbështet versionin Magisk më të ulët se %1$s. \n\n Aplikimi do të sillet sikur nuk është instaluar asnjë Magisk, ju lutemi azhurnoni Magisk sa më shpejt të jetë e mundur.</string>
<string name="external_rw_permission_denied">Jep leje për ruajtje për të mundësuar këtë funksionalitet</string>
<string name="add_shortcut_title">Shto shkurtore në ekranin kryesor</string>
<string name="add_shortcut_msg">Pasi të keni fshehur Magisk Manager, emri dhe ikona e tij mund të bëhen të vështira për t\'u njohur. \n\n Dëshironi të shtoni një shkurtore të bukur në ekranin kryesor?</string>
<string name="app_not_found">Asnjë aplikacion nuk u gjet për të trajtuar këtë veprim</string>
</resources>

View File

@@ -1,11 +1,11 @@
<resources>
<!--Welcome Activity-->
<!--Sections-->
<string name="modules">Modüller</string>
<string name="superuser">Yetkili Kullanıcı</string>
<string name="logs">Günlük</string>
<string name="settings">Ayarlar</string>
<string name="refresh">Yerel Verileri Yenile</string>
<string name="refresh">Yerel verileri yenile</string>
<string name="install">Yükle</string>
<string name="section_home">Ana Ekran</string>
<string name="section_theme">Temalar</string>
@@ -14,7 +14,7 @@
<!--Home-->
<string name="no_connection">Bağlantı yok</string>
<string name="app_changelog">Değişiklikler</string>
<string name="manager">Yönetici</string>
<string name="manager">Manager</string>
<string name="loading">Yükleniyor…</string>
<string name="update">Güncelle</string>
<string name="not_available">N/A</string>
@@ -22,13 +22,13 @@
<string name="status">Durum</string>
<string name="home_package">Paket</string>
<string name="home_notice_content">Her zaman açık kaynaklı Magisk Manager kullandığınızdan emin olun. Kaynağı bilinmeyen yönetici uygulamaları kötü amaçlı eylemler gerçekleştirebilir.</string>
<string name="home_notice_content">Her zaman açık kaynaklı Magisk Manager kullandığınızdan emin olun. Kaynağı bilinmeyen Manager(yönetici) uygulamaları kötü amaçlı eylemler gerçekleştirebilirler!</string>
<string name="home_support_title">Bizi Destekleyin</string>
<string name="home_item_source">Kaynak</string>
<string name="home_support_content">Magisk özgür ve açık kaynaklıdır ve her zaman da öyle kalacak. Ancak küçük bir bağış göndererek bize önem verdiğinizi gösterebilirsiniz.</string>
<string name="home_support_content">Magisk özgür ve açık kaynaklıdır ve her zaman da öyle kalacaktır. Ancak küçük bir bağış göndererek bize önem verdiğinizi gösterebilirsiniz.</string>
<string name="home_status_normal">Normal</string>
<string name="home_status_stub">Stub</string>
<string name="home_installed_version">Yüklendi</string>
<string name="home_installed_version">Yüklü</string>
<string name="home_latest_version">Güncel</string>
<string name="invalid_update_channel">Geçersiz Güncelleme Kanalı</string>
<string name="uninstall_magisk_title">Magisk\'i kaldır</string>
@@ -36,7 +36,7 @@
<string name="home_check_safetynet">SafetyNet\'i kontrol et</string>
<!--Install-->
<string name="keep_force_encryption">Şifrelemeyi zorlamayı sürdür</string>
<string name="keep_force_encryption">Şifrelemeye zorlamayı sürdür</string>
<string name="keep_dm_verity">AVB 2.0/dm-verity\'i koru</string>
<string name="recovery_mode">Kurtarma Modu</string>
<string name="install_options_title">Seçenekler</string>
@@ -47,7 +47,7 @@
<string name="download_zip_only">Sadece Zip\'i indir</string>
<string name="direct_install">Doğrudan kurulum (Önerilen)</string>
<string name="install_inactive_slot">Aktif olmayan yuvaya yükle (OTA\'dan sonra)</string>
<string name="install_inactive_slot_msg">Cihazınız, yeniden başlatmanın ardından geçerli etkin olmayan yuvaya önyüklemeye ZORLANACAK!\nBu seçeneği yalnızca OTA bittikten sonra kullanın.\nDevam edilsin mi?</string>
<string name="install_inactive_slot_msg">Cihazınız, yeniden başlatmanın ardından geçerli etkin olmayan yuvaya ön yüklemeye ZORLANACAK!\nBu seçeneği yalnızca OTA bittikten sonra kullanın.\nDevam edilsin mi?</string>
<string name="setup_title">Ek kurulum</string>
<string name="select_patch_file">Dosya seçin ve yamalayın</string>
<string name="patch_file_msg">Bir raw imaj (*.img) veya ODIN tar dosyası (*.tar) seçin</string>
@@ -56,12 +56,13 @@
<!--Superuser-->
<string name="su_request_title">Yetkili Kullanıcı İsteği</string>
<string name="touch_filtered_warning">Çünkü bir uygulama yetkili kullanıcı isteğini engelliyor, Magisk senin yanıtını doğrulayamaz</string>
<string name="deny">Reddet</string>
<string name="prompt">Sor</string>
<string name="grant">İzin ver</string>
<string name="su_warning">Cihazınıza tam erişim izni verir.\nEmin değilseniz reddedin!</string>
<string name="forever">Daima</string>
<string name="once">Bir kere</string>
<string name="once">Bir kereliğine</string>
<string name="tenmin">10 dakika</string>
<string name="twentymin">20 dakika</string>
<string name="thirtymin">30 dakika</string>
@@ -81,14 +82,14 @@
<string name="superuser_toggle_notification">Bildirimler</string>
<string name="superuser_toggle_revoke">İptal et</string>
<string name="superuser_policy_none">Henüz hiçbir uygulama süper kullanıcı izni istemedi.</string>
<string name="superuser_policy_none">Henüz hiçbir uygulama yetkili kullanıcı izni istemedi.</string>
<!--Logs-->
<string name="log_data_none">Günlük boş, daha fazla uygulama için SU etkinleştirmeyi deneyin.</string>
<string name="log_data_magisk_none">Magisk günlükleri boş, bu garip.</string>
<string name="log_data_none">Günlüksüzsün, daha fazla Yetkili Kullanıcı İzni isteyen uygulama kullanmayı dene</string>
<string name="log_data_magisk_none">Magisk günlükleri boş, bu garip</string>
<string name="menuSaveLog">Günlüğü kaydet</string>
<string name="menuClearLog">Günlüğü temizle</string>
<string name="logs_cleared">Günlük başarıyla temizlendi.</string>
<string name="logs_cleared">Günlük başarıyla temizlendi</string>
<string name="pid">PID: %1$d</string>
<string name="target_uid">Hedef UID: %1$d</string>
@@ -96,41 +97,43 @@
<string name="safetynet_api_error">SafetyNet API Hatası</string>
<string name="safetynet_res_invalid">Yanıt geçersiz</string>
<string name="safetynet_attest_success">Başarılı!</string>
<string name="safetynet_attest_failure">Onaylama başarısız oldu!</string>
<string name="safetynet_attest_failure">Onaylama başarısız!</string>
<string name="safetynet_attest_loading">Sadece bir saniye…</string>
<string name="safetynet_attest_restart">Tekrar deneyiniz</string>
<string name="safetynet_attest_restart">Tekrar dene</string>
<!-- MagiskHide -->
<string name="show_system_app">Sistem uygulamalarını göster</string>
<!--MagiskHide-->
<string name="show_system_app">Sistem uyg. göster</string>
<string name="show_os_app">İşletim Sistemi uyg. göster</string>
<string name="hide_filter_hint">İsme göre filtrele</string>
<string name="hide_scroll_up">Yukarı kaydır</string>
<string name="hide_filters">Filtreler</string>
<string name="hide_search">Ara</string>
<!--Module Fragment-->
<string name="no_info_provided">(Hiçbir ıklama sağlanmadı)</string>
<!--Module-->
<string name="no_info_provided">(Hiçbir bilgi sağlanmadı)</string>
<string name="reboot_userspace">Hızlı yeniden başlat</string>
<string name="reboot_recovery">Kurtarma moduna yeniden başlat</string>
<string name="reboot_bootloader">Ön yükleyici moduna yeniden başlat</string>
<string name="reboot_download">Yükleme moduna yeniden başlat</string>
<string name="reboot_download">İndirme moduna yeniden başlat</string>
<string name="reboot_edl">EDL moduna yeniden başlat</string>
<string name="module_version_author">%1$s - %2$s</string>
<string name="module_section_pending">Güncellemeler</string>
<string name="module_section_pending_action">Tümünü güncelle</string>
<string name="module_state_remove">Kaldır</string>
<string name="module_state_restore">Geri yükle</string>
<string name="module_action_install_external">Depolama alanından yükle</string>
<string name="module_action_install_external">Dahili depolamadan yükle</string>
<string name="update_available">Güncelleme mevcut</string>
<string name="module_installed">@string/home_installed_version</string>
<string name="module_section_online">Çevrim içi</string>
<string name="module_section_online">Çevrim İçi</string>
<string name="sorting_order">Sıralama Düzeni</string>
<!--Settings -->
<string name="settings_dark_mode_title">Tema Modu</string>
<string name="settings_dark_mode_message">Stilinize en uygun modu seçin!</string>
<string name="settings_dark_mode_light">Her zaman aydınlık</string>
<string name="settings_dark_mode_system">Sistemi takip et</string>
<string name="settings_dark_mode_dark">Her zaman karanlık</string>
<string name="settings_download_path_title">İndirme Yolu</string>
<string name="settings_dark_mode_message">Stilinize en iyi uyan modu seçin!</string>
<string name="settings_dark_mode_light">Her Zaman Aydınlık</string>
<string name="settings_dark_mode_system">Sistemi Takip Et</string>
<string name="settings_dark_mode_dark">Her Zaman Karanlık</string>
<string name="settings_download_path_title">İndirme dizini</string>
<string name="settings_download_path_message">Dosyalar %1$s konumuna kaydedilecek</string>
<string name="settings_clear_cache_title">Depo Önbelleğini Temizle</string>
<string name="settings_clear_cache_summary">Çevrim içi depolar için önbellek bilgilerini temizle, uygulamayı çevrim içi yenilemeye zorla</string>
@@ -143,9 +146,9 @@
<string name="settings_check_update_title">Güncellemeleri Denetle</string>
<string name="settings_check_update_summary">Düzenli aralıklarla arka planda güncellemeleri denetle</string>
<string name="settings_update_channel_title">Güncelleme Kanalı</string>
<string name="settings_update_stable">Stabil(kararlı)</string>
<string name="settings_update_stable">Stabil</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Özel</string>
<string name="settings_update_custom">Özel Kanal</string>
<string name="settings_update_custom_msg">Özel bir URL ekleyin</string>
<string name="settings_magiskhide_summary">Magisk\'i çeşitli algılamalardan gizle</string>
<string name="settings_hosts_title">Sistemsiz host</string>
@@ -157,7 +160,7 @@
<string name="settings_su_app_adb">Uygulamalar ve ADB</string>
<string name="settings_su_app">Sadece uygulamalar</string>
<string name="settings_su_adb">Sadece ADB</string>
<string name="settings_su_disable">Devre dışı</string>
<string name="settings_su_disable">Devre Dışı</string>
<string name="settings_su_request_10">10 saniye</string>
<string name="settings_su_request_15">15 saniye</string>
<string name="settings_su_request_20">20 saniye</string>
@@ -170,13 +173,15 @@
<string name="superuser_notification">Yetkili Kullanıcı Bildirimi</string>
<string name="settings_su_reauth_title">Yükseltmeden sonra yeniden kimlik doğrula</string>
<string name="settings_su_reauth_summary">Uygulama yükseltmeleri sonrasında yetkili kullanıcı izinlerini yeniden doğrula</string>
<string name="settings_su_tapjack_title">Tapjacking Korumasını Aktifleştir</string>
<string name="settings_su_tapjack_summary">Yetkili Kullanıcı izin penceresi başka bir pencere veya arayüz tarafından engellenirken verilen yanıtlara tepki vermeyecektir</string>
<string name="settings_su_biometric_title">Biyometrik Kimlik Doğrulamayı Etkinleştir</string>
<string name="settings_su_biometric_summary">Superuser isteklerine izin vermek için biyometrik kimlik doğrulamayı kullanın</string>
<string name="no_biometric">Desteklenmeyen cihaz veya biyometrik ayar etkinleştirilmemiş</string>
<string name="settings_customization">Özelleştirme</string>
<string name="setting_add_shortcut_summary">Uygulamayı gizledikten sonra ismini ve simgesini tanımakta zorlanırsan ana ekrana güzel bir kısayol ekleyebilirsin</string>
<string name="settings_doh_title">HTTPS üzerinden DNS</string>
<string name="settings_doh_description">Bazı ülkelerdeki DNS zehirlenmesini çözmeye çalışır</string>
<string name="settings_doh_description">Bazı ülkelerdeki DNS zehirlenmesini çözmeye çalış</string>
<string name="multiuser_mode">Çoklu Kullanıcı Modu</string>
<string name="settings_owner_only">Yalnızca Cihaz Sahibi</string>
@@ -186,8 +191,8 @@
<string name="owner_manage_summary">Yalnızca cihaz sahibi kök erişimini yönetebilir ve izin isteklerini alabilir</string>
<string name="user_indepenent_summary">Her kullanıcının kendi ayrı kök erişimi kuralları vardır</string>
<string name="mount_namespace_mode">Ad Alanı Modunu Doldur</string>
<string name="settings_ns_global">Evrensel Ad Alanı</string>
<string name="mount_namespace_mode">Ad Alanı Modunu Bağla</string>
<string name="settings_ns_global">Global Ad Alanı</string>
<string name="settings_ns_requester">Devralınan Ad Alanı</string>
<string name="settings_ns_isolate">Ayrılmış Ad Alanı</string>
<string name="global_summary">Tüm kök oturumları genel bağlama ad alanını kullanır</string>
@@ -201,8 +206,8 @@
<string name="download_file_error">Dosya indirme hatası</string>
<string name="download_open_parent">Üst klasörde göster</string>
<string name="download_open_self">Dosyayı göster</string>
<string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string>
<string name="manager_update_title">Yeni Magisk Manager Güncellemesi Mevcut!</string>
<string name="magisk_update_title">Magisk Güncellemesi Mevcut!</string>
<string name="manager_update_title">Magisk Manager Güncellemesi Mevcut!</string>
<!--Toasts, Dialogs-->
<string name="yes">Evet</string>
@@ -217,25 +222,26 @@
<string name="done">Tamamlandı!</string>
<string name="failure">Başarısız</string>
<string name="hide_manager_title">Magisk Manager Gizleniyor…</string>
<string name="hide_manager_fail_toast">Magisk Manager\'ı Gizleme başarısız oldu.</string>
<string name="open_link_failed_toast">Bağlantıyı açabilecek uygulama bulunamadı.</string>
<string name="hide_manager_fail_toast">Magisk Manager\'ı gizleme başarısız</string>
<string name="restore_manager_fail_toast">Magisk Manager\'ı geri yükleme başarısız</string>
<string name="open_link_failed_toast">Bağlantıyı açabilecek bir uygulama bulunamadı</string>
<string name="complete_uninstall">Tamamen Kaldır</string>
<string name="restore_img">Önyükleme İmajını Geri Yükle</string>
<string name="restore_img">İmajları Geri Yükle</string>
<string name="restore_img_msg">Geri Yükleniyor…</string>
<string name="restore_done">Yenileme tamamlandı!</string>
<string name="restore_fail">Stok önyükleme yedeği yok!</string>
<string name="restore_done">Geri yükleme tamamlandı!</string>
<string name="restore_fail">Stock ön yükleme yedeği yok!</string>
<string name="proprietary_title">Sahipli Kodu İndirin</string>
<string name="proprietary_notice">Magisk Yöneticisi, FOSS(açık kaynaklı) olduğundan gerekli olan Google\'ın sahipli(kapalı kaynaklı) SafetyNet API kodunu içermez.\n\nMagisk Manager\'ın SafetyNet kontrolü için (GoogleApiClient içeren) bir uzantıyı indirmesine izin veriyor musunuz?</string>
<string name="proprietary_notice">Magisk Manager, FOSS(açık kaynaklı) olduğundan gerekli olan Google\'ın sahipli(kapalı kaynaklı) SafetyNet API kodunu içermez.\n\nMagisk Manager\'ın SafetyNet kontrolü için (GoogleApiClient içeren) bir uzantıyı indirmesine izin veriyor musunuz?</string>
<string name="setup_fail">Kurulum başarısız</string>
<string name="env_fix_title">Ek Kurulum Gerekli</string>
<string name="env_fix_msg">Cihazınızın Magisk\'in düzgün çalışması için ek kuruluma ihtiyacı var. Bu Magisk kurulum zip dosyasını indirecektir, şimdi devam etmek istiyor musunuz?</string>
<string name="setup_msg">Ortam kurulumu çalışıyor…</string>
<string name="authenticate">Kimlik doğrulaması</string>
<string name="setup_msg">Ortam kurulumu çalıştırılıyor…</string>
<string name="authenticate">Kimlik Doğrulaması</string>
<string name="unsupport_magisk_title">Desteklenmeyen Magisk Sürümü</string>
<string name="unsupport_magisk_msg">Magisk Manager\'ın bu sürümü, %1$s daha düşük Magisk versiyonlarını desteklememektedir.\n\nUygulama hiçbir Magisk kurulu değil gibi davranacak, lütfen en kısa zamanda Magisk\'i yükseltin.</string>
<string name="external_rw_permission_denied">Bu işlevi etkinleştirmek için depolama izni verin</string>
<string name="add_shortcut_title">Ana ekrana kısayol ekle</string>
<string name="add_shortcut_msg">Magisk Manager\'ı gizledikten sonra, ismini ve simgesini tanıması güç olabilir. Ana ekrana güzel bir kısayol eklemek ister misin??</string>
<string name="add_shortcut_msg">Magisk Manager\'ı gizledikten sonra, ismini ve simgesini tanıması zor olabilir. Ana ekrana güzel bir kısayol eklemek ister misin?</string>
<string name="app_not_found">Bu işlemi yapabilecek bir uygulama bulunamadı</string>
</resources>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SplashTheme" parent="SplashThemeBase">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V19.Theme.Splash.Light" parent="Base.V17.Theme.Splash.Light">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="Base.V19.Theme.Splash" parent="Base.V17.Theme.Splash">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V19.Theme.Splash.Light" />
<style name="Theme.Splash" parent="Base.V19.Theme.Splash" />
</resources>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Foundation.Compat">
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowTranslucentStatus">true</item>
</style>
</resources>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V21.Theme.Foundation.Light" parent="Base.V17.Theme.Foundation.Light">
<item name="android:statusBarColor">#38000000</item>
<item name="android:navigationBarColor">#38000000</item>
</style>
<style name="Base.V21.Theme.Foundation" parent="Base.V17.Theme.Foundation">
<item name="android:statusBarColor">#60000000</item>
<item name="android:navigationBarColor">#60000000</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V21.Theme.Foundation.Light" />
<style name="Theme.Foundation" parent="Base.V21.Theme.Foundation" />
<style name="Base.V21.Theme.Splash.Light" parent="Base.V19.Theme.Splash.Light">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<style name="Base.V21.Theme.Splash" parent="Base.V19.Theme.Splash">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">false</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V21.Theme.Splash.Light" />
<style name="Theme.Splash" parent="Base.V21.Theme.Splash" />
</resources>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V23.Theme.Foundation.Light" parent="Base.V21.Theme.Foundation.Light">
<item name="android:statusBarColor">#40bdbdbd</item>
<item name="android:windowLightStatusBar">true</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V23.Theme.Foundation.Light" />
<style name="Base.V23.Theme.Splash.Light" parent="Base.V21.Theme.Splash.Light">
<item name="android:windowLightStatusBar">false</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V23.Theme.Splash.Light" />
</resources>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V27.Theme.Foundation.Light" parent="Base.V23.Theme.Foundation.Light">
<item name="android:navigationBarColor">#e0fafafa</item>
<item name="android:navigationBarDividerColor">#1f000000</item>
<item name="android:windowLightNavigationBar">true</item>
</style>
<style name="Base.V27.Theme.Foundation" parent="Base.V21.Theme.Foundation">
<item name="android:navigationBarDividerColor">@android:color/transparent</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V27.Theme.Foundation.Light" />
<style name="Theme.Foundation" parent="Base.V27.Theme.Foundation" />
<style name="Base.V27.Theme.Splash.Light" parent="Base.V23.Theme.Splash.Light">
<item name="android:windowLightNavigationBar">false</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V27.Theme.Splash.Light" />
</resources>

View File

@@ -16,14 +16,6 @@
<item>@string/settings_su_app_adb</item>
</string-array>
<string-array name="value_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
</string-array>
<string-array name="request_timeout">
<item>@string/settings_su_request_10</item>
<item>@string/settings_su_request_15</item>

View File

@@ -19,4 +19,32 @@
<!--endregion-->
<declare-styleable name="WindowInsetsHelper">
<attr name="edgeToEdge" format="boolean"/>
<attr name="fitsSystemWindowsInsets" format="flags">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
<attr name="consumeSystemWindowsInsets" format="flags">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
<attr name="layout_fitsSystemWindowsInsets" format="flags">
<flag name="top" value="0x30" />
<flag name="bottom" value="0x50" />
<flag name="left" value="0x03" />
<flag name="right" value="0x05" />
<flag name="start" value="0x00800003" />
<flag name="end" value="0x00800005" />
</attr>
</declare-styleable>
</resources>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="recyclerScrollListener" type="id" />
<item name="coroutineScope" type="id"/>
<item name="coroutineScope" type="id" />
<item name="tag_rikka_material_WindowInsetsHelper" type="id"/>
<item name="tag_rikka_recyclerView_OverScrollIfContentScrollsListener" type="id"/>
</resources>

View File

@@ -1,20 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="SplashThemeBase" parent="android:Theme.DeviceDefault.NoActionBar">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="SplashTheme" parent="Theme.Splash.Light" />
<style name="SplashTheme" parent="SplashThemeBase" />
<style name="Foundation" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:windowBackground">?colorSurface</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<!--This should be overridden in v21 for transparency, etc-->
<style name="Foundation.Compat" />
<style name="Foundation" parent="Theme.Foundation.Light" />
<!--region Do not remove-->
<style name="Empty" />
@@ -28,7 +17,7 @@
<item name="android:textStyle">bold</item>
</style>
<style name="Foundation.Default" parent="Foundation.Compat">
<style name="Foundation.Default">
<item name="android:includeFontPadding">false</item>
<item name="actionBarSize">@dimen/internal_action_bar_size</item>
<item name="popupMenuStyle">@style/Foundation.PopupMenu</item>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Base.V17.Theme.Foundation.Light" parent="Theme.MaterialComponents.Light.NoActionBar">
<item name="android:windowBackground">?colorSurface</item>
<item name="android:windowContentOverlay">@null</item>
<item name="dialogTheme">@style/ThemeOverlay.Foundation.Dialog</item>
</style>
<style name="Base.V17.Theme.Foundation" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowBackground">?colorSurface</item>
<item name="android:windowContentOverlay">@null</item>
<item name="dialogTheme">@style/ThemeOverlay.Foundation.Dialog</item>
</style>
<style name="Theme.Foundation.Light" parent="Base.V17.Theme.Foundation.Light" />
<style name="Theme.Foundation" parent="Base.V17.Theme.Foundation" />
<style name="Base.V17.Theme.Splash.Light" parent="android:Theme.DeviceDefault.Light.NoActionBar">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="Base.V17.Theme.Splash" parent="android:Theme.DeviceDefault.NoActionBar">
<item name="android:windowBackground">@drawable/ic_splash_activity</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="Theme.Splash.Light" parent="Base.V17.Theme.Splash.Light" />
<style name="Theme.Splash" parent="Base.V17.Theme.Splash" />
<style name="Base.V17.ThemeOverlay.Foundation.Dialog" parent="ThemeOverlay.MaterialComponents.Dialog">
<item name="android:windowMinWidthMajor">@dimen/abc_dialog_min_width_major</item>
<item name="android:windowMinWidthMinor">@dimen/abc_dialog_min_width_minor</item>
</style>
<style name="ThemeOverlay.Foundation.Dialog" parent="Base.V17.ThemeOverlay.Foundation.Dialog" />
</resources>

View File

@@ -14,12 +14,12 @@ buildscript {
maven { url = uri("https://kotlin.bintray.com/kotlinx") }
}
val vNav = "2.3.1"
val vNav = "2.3.2"
extra["vNav"] = vNav
dependencies {
classpath("com.android.tools.build:gradle:4.1.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${vNav}")
// NOTE: Do not place your application dependencies here; they belong
@@ -27,7 +27,7 @@ buildscript {
}
}
tasks.register("clean",Delete::class){
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
@@ -110,12 +110,12 @@ subprojects {
buildTypes {
signingConfigs.getByName("config").also {
getByName("debug") {
// If keystore exists, sign the APK with custom signature
if (it.storeFile?.exists() == true)
signingConfig = it
signingConfig = if (it.storeFile?.exists() == true) it
else signingConfigs.getByName("debug")
}
getByName("release") {
signingConfig = it
signingConfig = if (it.storeFile?.exists() == true) it
else signingConfigs.getByName("debug")
}
}
}

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