Compare commits

...

76 Commits

Author SHA1 Message Date
topjohnwu
47ccf4b1f5 Bump version 2017-11-23 01:06:19 +08:00
topjohnwu
a356b21895 Prevent hiding Magisk Manager on old Magisk versions 2017-11-23 01:06:18 +08:00
dark-basic #DarkBasic BasicHD
614a36c888 Update strings.xml
New Lines added.
2017-11-23 00:12:23 +08:00
topjohnwu
f520fe36bd Update to use new paths 2017-11-22 14:03:15 +08:00
vvb2060
7273a1c34d Update zh-rCN translation 2017-11-21 21:49:40 +08:00
Oliver Cervera
dc45cbce37 Update Italians strings
All new strings translated + clean-up!
2017-11-21 21:49:28 +08:00
topjohnwu
708d8f75c0 Notify su db corruption 2017-11-21 02:21:37 +08:00
dark-basic #DarkBasic BasicHD
bd37d90228 Update strings.xml 2017-11-21 02:15:14 +08:00
topjohnwu
b1ad691464 Several small fixes 2017-11-21 02:15:13 +08:00
topjohnwu
f4e7baf31e Update snet.apk link 2017-11-21 00:43:13 +08:00
topjohnwu
c0e60c41f2 Update snet extension pack 2017-11-21 00:40:05 +08:00
topjohnwu
c8dad43e00 Fix boot patching 2017-11-21 00:34:25 +08:00
topjohnwu
a8f124704d Allow custom update channels 2017-11-20 03:09:08 +08:00
vvb2060
eed2816491 Update zh-rCN translation 2017-11-19 22:48:29 +08:00
linar10
a6334b3e35 Update strings.xml 2017-11-19 22:48:20 +08:00
topjohnwu
334beebfeb Not all devices work well with streaming 2017-11-19 06:17:31 +08:00
topjohnwu
13dad848bd Fix download progress bug for modules larger than 20MB 2017-11-18 14:17:26 +08:00
topjohnwu
e518f4cef8 Crash proof database: reset if error occurs 2017-11-18 05:17:06 +08:00
topjohnwu
c8fd5da2da Remove unused strings 2017-11-18 05:17:06 +08:00
topjohnwu
3a74729ecc Add saving logs feature for installation 2017-11-18 05:17:06 +08:00
topjohnwu
49c672ac4d Add STDERR support 2017-11-18 05:17:06 +08:00
topjohnwu
b570cb5b77 Extract external path 2017-11-18 05:17:06 +08:00
topjohnwu
97bf388471 Support new module specification 2017-11-18 05:17:05 +08:00
topjohnwu
1a32aaea6f Drawer rearrangement 2017-11-18 05:17:05 +08:00
topjohnwu
4635883dec Update to use adaptive icons 2017-11-18 03:56:34 +08:00
topjohnwu
3ba6db4a50 Update Trad. Chinese translation 2017-11-17 02:28:51 +08:00
Xorok
2f1de25747 Fix color of LogFragment menu items when using dark theme
I set the color directly in the ic_*.xml files instead of using android:iconTint in menu_log.xml (as seen in fragment_magisk.xml) because iconTint is API26+.
2017-11-17 02:14:13 +08:00
daveyannihilation
f60fd42ac0 Expose Flashing colours for themes 2017-11-17 02:03:35 +08:00
RoySchutte
ecc8f9c792 Update strings.xml 2017-11-17 01:45:05 +08:00
dark-basic #DarkBasic BasicHD
e295dfdcf7 Update strings.xml 2017-11-17 01:44:56 +08:00
Oliver Cervera
fc42c25390 Update IT translation for new strings
Updating Italian translation for new strings that have just been pushed.
2017-11-17 01:44:47 +08:00
topjohnwu
27d5858e06 Fix file selection for module install 2017-11-17 01:39:34 +08:00
Generator
e1ef732b60 update pt_PT translation 2017-11-15 05:44:13 +08:00
RoySchutte
9840b95c21 Update strings.xml 2017-11-15 05:44:05 +08:00
linar10
a6f8446d81 Update strings.xml 2017-11-15 05:43:56 +08:00
Oliver Cervera
c1c844c830 Update strings Italian
Urgent correction!
Many strings contain the following character
'
It needs a backslash \ typed in front, otherwise sentences are cut!
2017-11-15 05:43:46 +08:00
topjohnwu
389299afd1 Remove apps from hidelist if uninstalled 2017-11-15 05:36:57 +08:00
topjohnwu
826543a291 Fully support dtbo.img patching 2017-11-15 05:36:57 +08:00
topjohnwu
4ac83cfded Small UI improvement 2017-11-15 00:38:38 +08:00
topjohnwu
64c363ce53 Update repo download progress report 2017-11-09 02:12:55 +08:00
topjohnwu
cca4347bf9 Use handler instead of weird callbacks 2017-11-09 01:43:29 +08:00
topjohnwu
3ae3d4926a Small adjustments to UI 2017-11-09 01:11:50 +08:00
topjohnwu
36025d6d9f Use direct path 2017-11-09 00:03:37 +08:00
topjohnwu
e171362e3e Improve snet.apk downloading 2017-11-07 00:39:48 +08:00
topjohnwu
3e0bf2ae15 Bump version 2017-11-06 23:21:05 +08:00
dark-basic #DarkBasic BasicHD
07aa9f4b8b Update strings.xml
new lines added
2017-11-06 23:04:59 +08:00
Oliver Cervera
b2d9f3fc64 Update Italian IT strings 2017-11-06 23:04:46 +08:00
Taras Korzhak
5fb3e9167e Updated Ukrainian translation 2017-11-06 23:04:28 +08:00
topjohnwu
99c74b31be Improve dynamic permissions 2017-11-06 05:40:41 +08:00
topjohnwu
ce5b13824e Organize application initialization 2017-11-06 04:47:24 +08:00
topjohnwu
c39170c42e Organize constants 2017-11-06 04:41:23 +08:00
topjohnwu
fd19fbf300 Improve Magisk direct install 2017-11-04 04:01:58 +08:00
topjohnwu
166469827f Support new sha1 location 2017-11-03 05:02:14 +08:00
topjohnwu
a34ed538b6 Fix potential bug 2017-11-03 02:25:42 +08:00
topjohnwu
5f22d3e055 Support new xml binary format 2017-10-31 22:48:48 +08:00
topjohnwu
fdd700f3e5 Update boot signing in InstallMagisk 2017-10-31 16:31:58 +08:00
topjohnwu
adf930f126 Finalize bootsigner commandline 2017-10-31 02:55:50 +08:00
topjohnwu
05f41928cd Add boot signing 2017-10-30 03:45:22 +08:00
topjohnwu
2ee0829871 Fix strings.xml 2017-10-30 03:44:03 +08:00
Dmitry Val'd
743560825d Update RU translation
Added new lines from original + corrected mistakes of the previous version of translation
2017-10-29 19:05:22 +08:00
Antoine
e3d84ac349 Update french translation 2017-10-29 19:05:12 +08:00
Dino Dugandžija
266c832b30 Created Croatian translation
I've translated the Magisk Manager app strings.xml to Croatian language. If anything else is needed, please let me know.
2017-10-29 19:04:55 +08:00
topjohnwu
f5374a024e Improve dynamic loading snet package 2017-10-29 14:43:43 +08:00
topjohnwu
4956d826fb Fix UID stored in multiuser mode 2017-10-28 16:19:53 +08:00
topjohnwu
f5cc2af5d0 Repackage Magisk Manager for hiding 2017-10-28 16:19:53 +08:00
topjohnwu
5880d4a6ec Use global su database 2017-10-28 15:50:17 +08:00
topjohnwu
ae05dce958 Improve Shell and logging 2017-10-21 02:28:44 +08:00
topjohnwu
9ebe372a9a Simplify flash log screen 2017-10-21 02:28:44 +08:00
topjohnwu
e6e04cc5b3 Add reference ASAP 2017-10-16 11:51:34 +08:00
topjohnwu
12352510fd Fix strings 2017-10-16 11:47:07 +08:00
vvb2060
2b3d927937 Update zh-rCN translation 2017-10-16 11:11:27 +08:00
Madis
a8890740f5 Created Estonian translation
I translated Magisk Manager to Estonian with the help of an app called Stringlate.
2017-10-16 11:11:19 +08:00
dark-basic #DarkBasic BasicHD
f60d7ee54b Fix Strings.xml
Translation Mistakes corrected.
2017-10-16 11:11:10 +08:00
topjohnwu
896ca2ef6b Cleanup contexts 2017-10-16 00:54:48 +08:00
topjohnwu
c036f6d529 Cleanup Utils 2017-10-15 23:54:34 +08:00
topjohnwu
6f457c0c59 Refactor shell (again) 2017-10-15 23:02:44 +08:00
132 changed files with 3545 additions and 2842 deletions

View File

@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
compileSdkVersion 27
buildToolsVersion "27.0.1"
defaultConfig {
applicationId "com.topjohnwu.magisk"
minSdkVersion 21
targetSdkVersion 26
versionCode 57
versionName "5.4.0"
targetSdkVersion 27
versionCode 63
versionName "5.4.2"
ndk {
moduleName 'zipadjust'
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
@@ -45,20 +45,20 @@ android {
disable 'MissingTranslation'
}
}
repositories {
jcenter()
google()
maven { url "https://jitpack.io" }
maven { url "https://maven.google.com" }
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation project(':common')
implementation project(':jarsigner')
implementation 'com.android.support:recyclerview-v7:26.1.0'
implementation 'com.android.support:cardview-v7:26.1.0'
implementation 'com.android.support:design:26.1.0'
implementation 'com.android.support:support-v4:26.1.0'
implementation project(':crypto')
implementation 'com.android.support:recyclerview-v7:27.0.1'
implementation 'com.android.support:cardview-v7:27.0.1'
implementation 'com.android.support:design:27.0.1'
implementation 'com.android.support:support-v4:27.0.1'
implementation 'com.jakewharton:butterknife:8.8.1'
implementation 'com.atlassian.commonmark:commonmark:0.10.0'
implementation 'org.kamranzafar:jtar:2.3'

View File

@@ -14,6 +14,7 @@
android:name=".MagiskManager"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
@@ -73,6 +74,7 @@
</intent-filter>
</receiver>
<receiver android:name=".receivers.ManagerUpdate" />
<receiver android:name=".receivers.RebootReceiver" />
<service android:name=".services.OnBootIntentService" />
<service
@@ -93,7 +95,7 @@
<!-- Hardcode GMS version -->
<meta-data
android:name="com.google.android.gms.version"
android:value="11400000" />
android:value="11717000" />
</application>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -17,6 +17,7 @@ import android.widget.TextView;
import com.topjohnwu.magisk.components.AboutCardRow;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.utils.Const;
import java.io.IOException;
import java.io.InputStream;
@@ -27,10 +28,6 @@ import butterknife.ButterKnife;
public class AboutActivity extends Activity {
private static final String DONATION_URL = "https://www.paypal.me/topjohnwu";
private static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
private static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/MagiskManager";
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.app_version_info) AboutCardRow appVersionInfo;
@BindView(R.id.app_changelog) AboutCardRow appChangelog;
@@ -120,13 +117,13 @@ public class AboutActivity extends Activity {
}
appSourceCode.removeSummary();
appSourceCode.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(SOURCE_CODE_URL))));
appSourceCode.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.SOURCE_CODE_URL))));
supportThread.removeSummary();
supportThread.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(XDA_THREAD))));
supportThread.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.XDA_THREAD))));
donation.removeSummary();
donation.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(DONATION_URL))));
donation.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Const.Url.DONATION_URL))));
setFloating();
}

View File

@@ -4,22 +4,29 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.FlashZip;
import com.topjohnwu.magisk.asyncs.InstallMagisk;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.container.AdaptiveList;
import com.topjohnwu.magisk.container.CallbackList;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -27,28 +34,45 @@ import butterknife.OnClick;
public class FlashActivity extends Activity {
public static final String SET_ACTION = "action";
public static final String SET_BOOT = "boot";
public static final String SET_ENC = "enc";
public static final String SET_VERITY = "verity";
public static final String FLASH_ZIP = "flash";
public static final String PATCH_BOOT = "patch";
public static final String FLASH_MAGISK = "magisk";
@BindView(R.id.toolbar) Toolbar toolbar;
@BindView(R.id.flash_logs) RecyclerView flashLogs;
@BindView(R.id.button_panel) LinearLayout buttonPanel;
@BindView(R.id.reboot) Button reboot;
@BindView(R.id.txtLog) TextView flashLogs;
@BindView(R.id.button_panel) public LinearLayout buttonPanel;
@BindView(R.id.reboot) public Button reboot;
@BindView(R.id.scrollView) ScrollView sv;
private List<String> logs;
@OnClick(R.id.no_thanks)
public void dismiss() {
void dismiss() {
finish();
}
@OnClick(R.id.reboot)
public void reboot() {
getShell().su_raw("reboot");
void reboot() {
Shell.su_raw("/system/bin/reboot");
}
@OnClick(R.id.save_logs)
void saveLogs() {
Calendar now = Calendar.getInstance();
String filename = String.format(Locale.US,
"install_log_%04d%02d%02d_%02d:%02d:%02d.log",
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));
File logFile = new File(Const.EXTERNAL_PATH + "/logs", filename);
logFile.getParentFile().mkdirs();
try (FileWriter writer = new FileWriter(logFile)) {
for (String s : logs) {
writer.write(s);
writer.write('\n');
}
} catch (IOException e) {
e.printStackTrace();
return;
}
MagiskManager.toast(logFile.getPath(), Toast.LENGTH_LONG);
}
@Override
@@ -56,7 +80,6 @@ public class FlashActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash);
ButterKnife.bind(this);
AdaptiveList<String> rootShellOutput = new AdaptiveList<>(flashLogs);
setSupportActionBar(toolbar);
ActionBar ab = getSupportActionBar();
if (ab != null) {
@@ -67,45 +90,35 @@ public class FlashActivity extends Activity {
if (!Shell.rootAccess())
reboot.setVisibility(View.GONE);
flashLogs.setAdapter(new FlashLogAdapter(rootShellOutput));
logs = new ArrayList<>();
List<String> console = new CallbackList<String>() {
@Override
public synchronized void onAddElement(String e) {
logs.add(e);
flashLogs.setText(TextUtils.join("\n", this));
sv.postDelayed(() -> sv.fullScroll(ScrollView.FOCUS_DOWN), 10);
}
};
// We must receive a Uri of the target zip
Intent intent = getIntent();
Uri uri = intent.getData();
boolean keepEnc = intent.getBooleanExtra(SET_ENC, false);
boolean keepVerity = intent.getBooleanExtra(SET_VERITY, false);
boolean keepEnc = intent.getBooleanExtra(Const.Key.FLASH_SET_ENC, false);
boolean keepVerity = intent.getBooleanExtra(Const.Key.FLASH_SET_VERITY, false);
switch (getIntent().getStringExtra(SET_ACTION)) {
case FLASH_ZIP:
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
switch (intent.getStringExtra(Const.Key.FLASH_ACTION)) {
case Const.Value.FLASH_ZIP:
new FlashZip(this, uri, console, logs).exec();
break;
case Const.Value.PATCH_BOOT:
new InstallMagisk(this, console, logs, uri, keepEnc, keepVerity, (Uri) intent.getParcelableExtra(Const.Key.FLASH_SET_BOOT))
.exec();
break;
case PATCH_BOOT:
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, (Uri) intent.getParcelableExtra(SET_BOOT))
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
case Const.Value.FLASH_MAGISK:
new InstallMagisk(this, console, logs, uri, keepEnc, keepVerity, intent.getStringExtra(Const.Key.FLASH_SET_BOOT))
.exec();
break;
case FLASH_MAGISK:
String boot = intent.getStringExtra(SET_BOOT);
if (getMagiskManager().remoteMagiskVersionCode < 1370) {
// Use legacy installation method
getShell().su_raw(
"echo \"BOOTIMAGE=" + boot + "\" > /dev/.magisk",
"echo \"KEEPFORCEENCRYPT=" + keepEnc + "\" >> /dev/.magisk",
"echo \"KEEPVERITY=" + keepVerity + "\" >> /dev/.magisk"
);
new FlashZip(this, uri, rootShellOutput)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
} else {
// Use new installation method
new InstallMagisk(this, rootShellOutput, uri, keepEnc, keepVerity, boot)
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
.exec();
}
break;
}
}
@@ -113,41 +126,4 @@ public class FlashActivity extends Activity {
public void onBackPressed() {
// Prevent user accidentally press back button
}
private static class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
private List<String> mList;
FlashLogAdapter(List<String> list) {
mList = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_flashlog, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.text.setText(mList.get(position));
}
@Override
public int getItemCount() {
return mList.size();
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.textView) TextView text;
public ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}

View File

@@ -33,13 +33,10 @@ public class LogFragment extends Fragment {
TabFragmentAdapter adapter = new TabFragmentAdapter(getChildFragmentManager());
if (getApplication().isSuClient) {
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
tab.setupWithViewPager(viewPager);
tab.setVisibility(View.VISIBLE);
}
adapter.addTab(new SuLogFragment(), getString(R.string.superuser));
adapter.addTab(new MagiskLogFragment(), getString(R.string.magisk));
tab.setupWithViewPager(viewPager);
tab.setVisibility(View.VISIBLE);
viewPager.setAdapter(adapter);

View File

@@ -5,19 +5,16 @@ import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.asyncs.CheckSafetyNet;
@@ -25,14 +22,11 @@ import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.ExpandableView;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.ShowUI;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindColor;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -42,12 +36,13 @@ import butterknife.Unbinder;
public class MagiskFragment extends Fragment
implements Topic.Subscriber, SwipeRefreshLayout.OnRefreshListener, ExpandableView {
public static final int CAUSE_SERVICE_DISCONNECTED = 0x00001;
public static final int CAUSE_NETWORK_LOST = 0x00010;
public static final int RESPONSE_ERR = 0x00100;
private static final int CAUSE_SERVICE_DISCONNECTED = 0x01;
private static final int CAUSE_NETWORK_LOST = 0x02;
private static final int RESPONSE_ERR = 0x04;
private static final int CONNECTION_FAIL = 0x08;
public static final int BASIC_PASS = 0x01000;
public static final int CTS_PASS = 0x10000;
private static final int BASIC_PASS = 0x10;
private static final int CTS_PASS = 0x20;
private Container expandableContainer = new Container();
@@ -57,15 +52,12 @@ public class MagiskFragment extends Fragment
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.magisk_update_card) CardView magiskUpdateCard;
@BindView(R.id.magisk_update) RelativeLayout magiskUpdate;
@BindView(R.id.magisk_update_icon) ImageView magiskUpdateIcon;
@BindView(R.id.magisk_update_status) TextView magiskUpdateText;
@BindView(R.id.magisk_update_progress) ProgressBar magiskUpdateProgress;
@BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon;
@BindView(R.id.magisk_version) TextView magiskVersionText;
@BindView(R.id.root_status_icon) ImageView rootStatusIcon;
@BindView(R.id.root_status) TextView rootStatusText;
@BindView(R.id.safetyNet_card) CardView safetyNetCard;
@BindView(R.id.safetyNet_refresh) ImageView safetyNetRefreshIcon;
@@ -77,9 +69,6 @@ public class MagiskFragment extends Fragment
@BindView(R.id.basic_status_icon) ImageView basicStatusIcon;
@BindView(R.id.basic_status) TextView basicStatusText;
@BindView(R.id.bootimage_card) CardView bootImageCard;
@BindView(R.id.block_spinner) Spinner spinner;
@BindView(R.id.detect_bootimage) Button detectButton;
@BindView(R.id.install_option_card) CardView installOptionCard;
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
@@ -123,18 +112,18 @@ public class MagiskFragment extends Fragment
// Show Manager update first
if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
Utils.showManagerInstallDialog(getActivity());
ShowUI.managerInstallDialog(getActivity());
return;
}
((NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
Utils.showMagiskInstallDialog(this,
ShowUI.magiskInstallDialog(getActivity(),
keepEncChkbox.isChecked(), keepVerityChkbox.isChecked());
}
@OnClick(R.id.uninstall_button)
void uninstall() {
Utils.showUninstallDialog(this);
ShowUI.uninstallDialog(getActivity());
}
@Nullable
@@ -157,7 +146,7 @@ public class MagiskFragment extends Fragment
@Override
public void onRefresh() {
mm.getMagiskInfo();
mm.loadMagiskInfo();
updateUI();
magiskUpdateText.setText(R.string.checking_for_updates);
@@ -175,8 +164,8 @@ public class MagiskFragment extends Fragment
shownDialog = false;
// Trigger state check
if (Utils.checkNetworkStatus(mm)) {
new CheckUpdates(getActivity()).exec();
if (Utils.checkNetworkStatus()) {
new CheckUpdates().exec();
} else {
mSwipeRefreshLayout.setRefreshing(false);
}
@@ -207,35 +196,15 @@ public class MagiskFragment extends Fragment
return expandableContainer;
}
public String getSelectedBootImage() {
if (Shell.rootAccess()) {
if (mm.bootBlock != null) {
return mm.bootBlock;
} else {
int idx = spinner.getSelectedItemPosition();
if (idx > 0) {
return mm.blockList.get(idx - 1);
} else {
SnackbarMaker.make(getActivity(),
R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
return null;
}
}
} else {
return null;
}
}
private void updateUI() {
((MainActivity) getActivity()).checkHideSection();
boolean hasNetwork = Utils.checkNetworkStatus(getActivity());
boolean hasNetwork = Utils.checkNetworkStatus();
boolean hasRoot = Shell.rootAccess();
boolean isUpToDate = mm.magiskVersionCode > 1300;
magiskUpdateCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
magiskUpdate.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
safetyNetCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
bootImageCard.setVisibility(hasNetwork && hasRoot ? View.VISIBLE : View.GONE);
installOptionCard.setVisibility(hasNetwork ? View.VISIBLE : View.GONE);
uninstallButton.setVisibility(isUpToDate && hasRoot ? View.VISIBLE : View.GONE);
@@ -253,43 +222,6 @@ public class MagiskFragment extends Fragment
magiskStatusIcon.setImageResource(image);
magiskStatusIcon.setColorFilter(color);
switch (Shell.rootStatus) {
case 0:
color = colorBad;
image = R.drawable.ic_cancel;
rootStatusText.setText(R.string.not_rooted);
break;
case 1:
if (mm.suVersion != null) {
color = colorOK;
image = R.drawable.ic_check_circle;
rootStatusText.setText(mm.suVersion);
break;
}
case -1:
default:
color = colorNeutral;
image = R.drawable.ic_help;
rootStatusText.setText(R.string.root_error);
}
rootStatusIcon.setImageResource(image);
rootStatusIcon.setColorFilter(color);
List<String> items = new ArrayList<>();
if (mm.bootBlock != null) {
items.add(getString(R.string.auto_detect, mm.bootBlock));
spinner.setEnabled(false);
} else {
items.add(getString(R.string.cannot_auto_detect));
if (mm.blockList != null)
items.addAll(mm.blockList);
}
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
android.R.layout.simple_spinner_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
}
private void updateCheckUI() {
@@ -298,20 +230,20 @@ public class MagiskFragment extends Fragment
if (mm.remoteMagiskVersionCode < 0) {
color = colorNeutral;
image = R.drawable.ic_help;
magiskUpdateText.setText(R.string.cannot_check_updates);
magiskUpdateText.setText(R.string.invalid_update_channel);
installButton.setVisibility(View.GONE);
} else {
color = colorOK;
image = R.drawable.ic_check_circle;
magiskUpdateText.setText(getString(R.string.install_magisk_title, "v" + mm.remoteMagiskVersionString));
}
installButton.setVisibility(View.VISIBLE);
if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
installText.setText(getString(R.string.update, getString(R.string.app_name)));
} else if (mm.magiskVersionCode > 0 && mm.remoteMagiskVersionCode > mm.magiskVersionCode) {
installText.setText(getString(R.string.update, getString(R.string.magisk)));
} else {
installText.setText(R.string.install);
installButton.setVisibility(View.VISIBLE);
if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) {
installText.setText(getString(R.string.update, getString(R.string.app_name)));
} else if (mm.magiskVersionCode > 0 && mm.remoteMagiskVersionCode > mm.magiskVersionCode) {
installText.setText(getString(R.string.update, getString(R.string.magisk)));
} else {
installText.setText(R.string.install);
}
}
if (!shownDialog && (mm.remoteMagiskVersionCode > mm.magiskVersionCode
@@ -330,9 +262,7 @@ public class MagiskFragment extends Fragment
private void updateSafetyNetUI(int response) {
safetyNetProgress.setVisibility(View.GONE);
safetyNetRefreshIcon.setVisibility(View.VISIBLE);
if (response < 0) {
safetyNetStatusText.setText(R.string.safetyNet_api_error);
} else if ((response & 0x111) == 0) {
if ((response & 0x0F) == 0) {
safetyNetStatusText.setText(R.string.safetyNet_check_success);
boolean b;
@@ -357,9 +287,12 @@ public class MagiskFragment extends Fragment
resid = R.string.safetyNet_service_disconnected;
break;
case RESPONSE_ERR:
default:
resid = R.string.safetyNet_res_invalid;
break;
case CONNECTION_FAIL:
default:
resid = R.string.safetyNet_api_error;
break;
}
safetyNetStatusText.setText(resid);
}

View File

@@ -1,9 +1,7 @@
package com.topjohnwu.magisk;
import android.Manifest;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.text.TextUtils;
@@ -22,6 +20,7 @@ import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
@@ -29,6 +28,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -36,8 +36,6 @@ import butterknife.Unbinder;
public class MagiskLogFragment extends Fragment {
private static final String MAGISK_LOG = "/cache/magisk.log";
private Unbinder unbinder;
@BindView(R.id.txtLog) TextView txtLog;
@@ -110,30 +108,29 @@ public class MagiskLogFragment extends Fragment {
super(MagiskLogFragment.this.getActivity());
}
@SuppressLint("DefaultLocale")
@Override
protected Object doInBackground(Object... params) {
mode = (int) params[0];
switch (mode) {
case 0:
StringBuildingList logList = new StringBuildingList();
getShell().su(logList, "cat " + MAGISK_LOG);
return logList.toString();
Shell.su(logList, "cat " + Const.MAGISK_LOG + " | tail -n 1000");
return logList.getCharSequence();
case 1:
getShell().su_raw("echo -n > " + MAGISK_LOG);
Shell.su_raw("echo -n > " + Const.MAGISK_LOG);
SnackbarMaker.make(txtLog, R.string.logs_cleared, Snackbar.LENGTH_SHORT).show();
return "";
case 2:
Calendar now = Calendar.getInstance();
String filename = String.format(
"magisk_%s_%04d%02d%02d_%02d%02d%02d.log", "error",
String filename = String.format(Locale.US,
"magisk_log_%04d%02d%02d_%02d:%02d:%02d.log",
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));
targetFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
targetFile = new File(Const.EXTERNAL_PATH + "/logs", filename);
if ((!targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs())
|| (targetFile.exists() && !targetFile.delete())) {
@@ -142,7 +139,7 @@ public class MagiskLogFragment extends Fragment {
try (FileWriter out = new FileWriter(targetFile)) {
FileWritingList fileWritingList = new FileWritingList(out);
getShell().su(fileWritingList, "cat " + MAGISK_LOG);
Shell.su(fileWritingList, "cat " + Const.MAGISK_LOG);
} catch (IOException e) {
e.printStackTrace();
return false;
@@ -158,21 +155,21 @@ public class MagiskLogFragment extends Fragment {
switch (mode) {
case 0:
case 1:
String llog = (String) o;
CharSequence llog = (CharSequence) o;
progressBar.setVisibility(View.GONE);
if (TextUtils.isEmpty(llog))
txtLog.setText(R.string.log_is_empty);
else
txtLog.setText(llog);
svLog.post(() -> svLog.scrollTo(0, txtLog.getHeight()));
hsvLog.post(() -> hsvLog.scrollTo(0, 0));
svLog.postDelayed(() -> svLog.fullScroll(ScrollView.FOCUS_DOWN), 100);
hsvLog.postDelayed(() -> hsvLog.fullScroll(ScrollView.FOCUS_LEFT), 100);
break;
case 2:
boolean bool = (boolean) o;
if (bool) {
getMagiskManager().toast(targetFile.toString(), Toast.LENGTH_LONG);
MagiskManager.toast(targetFile.getPath(), Toast.LENGTH_LONG);
} else {
getMagiskManager().toast(R.string.logs_save_failed, Toast.LENGTH_LONG);
MagiskManager.toast(R.string.logs_save_failed, Toast.LENGTH_LONG);
}
break;
}
@@ -205,9 +202,8 @@ public class MagiskLogFragment extends Fragment {
return true;
}
@Override
public String toString() {
return builder.toString();
public CharSequence getCharSequence() {
return builder;
}
}

View File

@@ -1,56 +1,31 @@
package com.topjohnwu.magisk;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.DownloadBusybox;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.superuser.SuReceiver;
import com.topjohnwu.magisk.superuser.SuRequestActivity;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutionException;
public class MagiskManager extends Application {
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static final String MAGISK_HOST_FILE = "/magisk/.core/hosts";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_PATH = "/magisk";
public static final String INTENT_SECTION = "section";
public static final String INTENT_VERSION = "version";
public static final String INTENT_LINK = "link";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
public static final String DISABLE_INDICATION_PROP = "ro.magisk.disable";
public static final String NOTIFICATION_CHANNEL = "magisk_update_notice";
public static final String BUSYBOXPATH = "/dev/magisk/bin";
public static final int UPDATE_SERVICE_ID = 1;
// Global weak reference to self
private static WeakReference<MagiskManager> weakSelf;
// Topics
public final Topic magiskHideDone = new Topic();
@@ -62,6 +37,8 @@ public class MagiskManager extends Application {
public final Topic localeDone = new Topic();
// Info
public boolean hasInit = false;
public int userId;
public String magiskVersionString;
public int magiskVersionCode = -1;
public String remoteMagiskVersionString;
@@ -72,13 +49,11 @@ public class MagiskManager extends Application {
public int remoteManagerVersionCode = -1;
public String managerLink;
public String bootBlock = null;
public boolean isSuClient = false;
public String suVersion = null;
public boolean disabled;
public int snet_version;
public int updateServiceVersion;
// Data
public Map<String, Module> moduleMap;
public List<String> blockList;
public List<Locale> locales;
// Configurations
@@ -89,6 +64,7 @@ public class MagiskManager extends Application {
public boolean isDarkTheme;
public boolean updateNotification;
public boolean suReauth;
public boolean coreOnly;
public int suRequestTimeout;
public int suLogTimeout = 14;
public int suAccessState;
@@ -99,45 +75,41 @@ public class MagiskManager extends Application {
public String localeConfig;
public int updateChannel;
public String bootFormat;
public int snet_version;
public String customChannelUrl;
// Global resources
public SharedPreferences prefs;
public SuDatabaseHelper suDB;
public RepoDatabaseHelper repoDB;
public Shell shell;
public Runnable permissionGrantCallback = null;
private static Handler mHandler = new Handler();
private boolean started = false;
private static class LoadLocale extends ParallelTask<Void, Void, Void> {
LoadLocale(Context context) {
super(context);
}
@Override
protected Void doInBackground(Void... voids) {
getMagiskManager().locales = Utils.getAvailableLocale(getMagiskManager());
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
getMagiskManager().localeDone.publish();
}
public MagiskManager() {
weakSelf = new WeakReference<>(this);
}
@Override
public void onCreate() {
super.onCreate();
prefs = PreferenceManager.getDefaultSharedPreferences(this);
userId = getApplicationInfo().uid / 100000;
if (getDatabasePath(SuDatabaseHelper.DB_NAME).exists()) {
if (Utils.getDatabasePath(this, SuDatabaseHelper.DB_NAME).exists()) {
// Don't migrate yet, wait and check Magisk version
suDB = new SuDatabaseHelper(this);
} else {
suDB = new SuDatabaseHelper(Utils.getEncContext(this));
suDB = new SuDatabaseHelper();
}
// If detect original package, self destruct!
if (!getPackageName().equals(Const.ORIG_PKG_NAME)) {
try {
getPackageManager().getApplicationInfo(Const.ORIG_PKG_NAME, 0);
Shell.su(String.format(Locale.US, "pm uninstall --user %d %s", userId, getPackageName()));
return;
} catch (PackageManager.NameNotFoundException ignored) { /* Expected*/ }
}
repoDB = new RepoDatabaseHelper(this);
@@ -146,8 +118,12 @@ public class MagiskManager extends Application {
loadConfig();
}
public static MagiskManager get() {
return weakSelf.get();
}
public void setLocale() {
localeConfig = prefs.getString("locale", "");
localeConfig = prefs.getString(Const.Key.LOCALE, "");
if (localeConfig.isEmpty()) {
locale = defaultLocale;
} else {
@@ -160,139 +136,39 @@ public class MagiskManager extends Application {
}
public void loadConfig() {
isDarkTheme = prefs.getBoolean("dark_theme", false);
isDarkTheme = prefs.getBoolean(Const.Key.DARK_THEME, false);
// su
suRequestTimeout = Utils.getPrefsInt(prefs, "su_request_timeout", 10);
suResponseType = Utils.getPrefsInt(prefs, "su_auto_response", SuRequestActivity.PROMPT);
suNotificationType = Utils.getPrefsInt(prefs, "su_notification", SuReceiver.TOAST);
suReauth = prefs.getBoolean("su_reauth", false);
suAccessState = suDB.getSettings(SuDatabaseHelper.ROOT_ACCESS, SuDatabaseHelper.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = suDB.getSettings(SuDatabaseHelper.MULTIUSER_MODE, SuDatabaseHelper.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = suDB.getSettings(SuDatabaseHelper.MNT_NS, SuDatabaseHelper.NAMESPACE_MODE_REQUESTER);
suRequestTimeout = Utils.getPrefsInt(prefs, Const.Key.SU_REQUEST_TIMEOUT, Const.Value.timeoutList[2]);
suResponseType = Utils.getPrefsInt(prefs, Const.Key.SU_AUTO_RESPONSE, Const.Value.SU_PROMPT);
suNotificationType = Utils.getPrefsInt(prefs, Const.Key.SU_NOTIFICATION, Const.Value.NOTIFICATION_TOAST);
suReauth = prefs.getBoolean(Const.Key.SU_REAUTH, false);
suAccessState = suDB.getSettings(Const.Key.ROOT_ACCESS, Const.Value.ROOT_ACCESS_APPS_AND_ADB);
multiuserMode = suDB.getSettings(Const.Key.SU_MULTIUSER_MODE, Const.Value.MULTIUSER_MODE_OWNER_ONLY);
suNamespaceMode = suDB.getSettings(Const.Key.SU_MNT_NS, Const.Value.NAMESPACE_MODE_REQUESTER);
updateNotification = prefs.getBoolean("notification", true);
updateChannel = Utils.getPrefsInt(prefs, "update_channel", CheckUpdates.STABLE_CHANNEL);
bootFormat = prefs.getString("boot_format", ".img");
snet_version = prefs.getInt("snet_version", -1);
coreOnly = prefs.getBoolean(Const.Key.DISABLE, false);
updateNotification = prefs.getBoolean(Const.Key.UPDATE_NOTIFICATION, true);
updateChannel = Utils.getPrefsInt(prefs, Const.Key.UPDATE_CHANNEL, Const.Value.STABLE_CHANNEL);
bootFormat = prefs.getString(Const.Key.BOOT_FORMAT, ".img");
snet_version = prefs.getInt(Const.Key.SNET_VER, -1);
updateServiceVersion = prefs.getInt(Const.Key.UPDATE_SERVICE_VER, -1);
customChannelUrl = prefs.getString(Const.Key.CUSTOM_CHANNEL, "");
}
public void toast(String msg, int duration) {
mHandler.post(() -> Toast.makeText(this, msg, duration).show());
public static void toast(String msg, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), msg, duration).show());
}
public void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(this, resId, duration).show());
public static void toast(int resId, int duration) {
mHandler.post(() -> Toast.makeText(weakSelf.get(), resId, duration).show());
}
public void startup() {
if (started)
return;
started = true;
boolean hasNetwork = Utils.checkNetworkStatus(this);
getMagiskInfo();
// Check if we need to migrate suDB
if (getDatabasePath(SuDatabaseHelper.DB_NAME).exists() && Utils.useFDE(this)) {
if (magiskVersionCode >= 1410) {
suDB.close();
Context de = createDeviceProtectedStorageContext();
de.moveDatabaseFrom(this, SuDatabaseHelper.DB_NAME);
suDB = new SuDatabaseHelper(de);
}
}
new LoadLocale(this).exec();
// Root actions
if (Shell.rootAccess()) {
if (hasNetwork && !Utils.itemExist(shell, BUSYBOXPATH + "/busybox")) {
try {
// Force synchronous, make sure we have busybox to use
new DownloadBusybox(this).exec().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
try (InputStream in = getAssets().open(Utils.UTIL_FUNCTIONS)) {
shell.loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
shell.su_raw(
"export PATH=" + BUSYBOXPATH + ":$PATH",
"mount_partitions",
"BOOTIMAGE=",
"find_boot_image",
"migrate_boot_backup"
);
List<String> res = shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(res)) {
bootBlock = res.get(0);
} else {
blockList = shell.su("find /dev/block -type b | grep -vE 'dm|ram|loop'");
}
}
// Write back default values
prefs.edit()
.putBoolean("dark_theme", isDarkTheme)
.putBoolean("magiskhide", magiskHide)
.putBoolean("notification", updateNotification)
.putBoolean("hosts", Utils.itemExist(shell, MAGISK_HOST_FILE))
.putBoolean("disable", Utils.itemExist(shell, MAGISK_DISABLE_FILE))
.putBoolean("su_reauth", suReauth)
.putString("su_request_timeout", String.valueOf(suRequestTimeout))
.putString("su_auto_response", String.valueOf(suResponseType))
.putString("su_notification", String.valueOf(suNotificationType))
.putString("su_access", String.valueOf(suAccessState))
.putString("multiuser_mode", String.valueOf(multiuserMode))
.putString("mnt_ns", String.valueOf(suNamespaceMode))
.putString("update_channel", String.valueOf(updateChannel))
.putString("locale", localeConfig)
.putString("boot_format", bootFormat)
.apply();
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
LoadModules loadModuleTask = new LoadModules(this);
// Start update check job
if (hasNetwork) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo jobInfo = new JobInfo.Builder(UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(jobInfo);
loadModuleTask.setCallBack(() -> new UpdateRepos(this, false).exec());
}
// Fire asynctasks
loadModuleTask.exec();
}
public void getMagiskInfo() {
public void loadMagiskInfo() {
List<String> ret;
Shell.getShell(this);
ret = shell.sh("su -v");
if (Utils.isValidShellResponse(ret)) {
suVersion = ret.get(0);
isSuClient = suVersion.toUpperCase().contains("MAGISK");
}
ret = shell.sh("magisk -v");
ret = Shell.sh("magisk -v");
if (!Utils.isValidShellResponse(ret)) {
ret = shell.sh("getprop magisk.version");
ret = Shell.sh("getprop magisk.version");
if (Utils.isValidShellResponse(ret)) {
try {
magiskVersionString = ret.get(0);
@@ -301,21 +177,15 @@ public class MagiskManager extends Application {
}
} else {
magiskVersionString = ret.get(0).split(":")[0];
ret = shell.sh("magisk -V");
ret = Shell.sh("magisk -V");
try {
magiskVersionCode = Integer.parseInt(ret.get(0));
} catch (NumberFormatException ignored) {}
}
ret = shell.sh("getprop " + DISABLE_INDICATION_PROP);
try {
disabled = Utils.isValidShellResponse(ret) && Integer.parseInt(ret.get(0)) != 0;
} catch (NumberFormatException e) {
disabled = false;
}
if (magiskVersionCode > 1435) {
ret = shell.su("resetprop -p " + MAGISKHIDE_PROP);
ret = Shell.su("resetprop -p " + Const.MAGISKHIDE_PROP);
} else {
ret = shell.sh("getprop " + MAGISKHIDE_PROP);
ret = Shell.sh("getprop " + Const.MAGISKHIDE_PROP);
}
try {
magiskHide = !Utils.isValidShellResponse(ret) || Integer.parseInt(ret.get(0)) != 0;
@@ -323,4 +193,8 @@ public class MagiskManager extends Application {
magiskHide = true;
}
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
}
}

View File

@@ -6,6 +6,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
@@ -16,6 +17,7 @@ import android.view.MenuItem;
import android.view.View;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
@@ -38,11 +40,27 @@ public class MainActivity extends Activity
@Override
protected void onCreate(final Bundle savedInstanceState) {
getMagiskManager().startup();
prefs = getMagiskManager().prefs;
MagiskManager mm = getMagiskManager();
if (getMagiskManager().isDarkTheme) {
if (!mm.hasInit) {
Intent intent = new Intent(this, SplashActivity.class);
String section = getIntent().getStringExtra(Const.Key.OPEN_SECTION);
if (section != null) {
intent.putExtra(Const.Key.OPEN_SECTION, section);
}
startActivity(intent);
finish();
}
String perm = getIntent().getStringExtra(Const.Key.INTENT_PERM);
if (perm != null) {
ActivityCompat.requestPermissions(this, new String[] { perm }, 0);
}
prefs = mm.prefs;
if (mm.isDarkTheme) {
setTheme(R.style.AppTheme_Dark);
}
super.onCreate(savedInstanceState);
@@ -70,10 +88,9 @@ public class MainActivity extends Activity
toggle.syncState();
if (savedInstanceState == null)
navigate(getIntent().getStringExtra(MagiskManager.INTENT_SECTION));
navigate(getIntent().getStringExtra(Const.Key.OPEN_SECTION));
navigationView.setNavigationItemSelectedListener(this);
}
@Override
@@ -112,17 +129,18 @@ public class MainActivity extends Activity
}
public void checkHideSection() {
MagiskManager mm = getMagiskManager();
Menu menu = navigationView.getMenu();
menu.findItem(R.id.magiskhide).setVisible(
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 1300
&& prefs.getBoolean("magiskhide", false));
Shell.rootAccess() && mm.magiskVersionCode >= 1300
&& prefs.getBoolean(Const.Key.MAGISKHIDE, false));
menu.findItem(R.id.modules).setVisible(
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 0);
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus(this) &&
Shell.rootAccess() && getMagiskManager().magiskVersionCode >= 0);
Shell.rootAccess() && mm.magiskVersionCode >= 0);
menu.findItem(R.id.downloads).setVisible(Utils.checkNetworkStatus() &&
Shell.rootAccess() && mm.magiskVersionCode >= 0);
menu.setGroupVisible(R.id.second_group, !mm.coreOnly);
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
menu.findItem(R.id.superuser).setVisible(
Shell.rootAccess() && getMagiskManager().isSuClient);
menu.findItem(R.id.superuser).setVisible(Shell.rootAccess());
}
public void navigate(String item) {
@@ -176,7 +194,7 @@ public class MainActivity extends Activity
displayFragment(new ReposFragment(), "downloads", true);
break;
case R.id.magiskhide:
displayFragment(new MagiskHideFragment(), "magiskhide", true);
displayFragment(new MagiskHideFragment(), Const.Key.MAGISKHIDE, true);
break;
case R.id.log:
displayFragment(new LogFragment(), "log", false);

View File

@@ -16,6 +16,7 @@ import com.topjohnwu.magisk.adapters.ModulesAdapter;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
@@ -29,8 +30,6 @@ import butterknife.Unbinder;
public class ModulesFragment extends Fragment implements Topic.Subscriber {
private static final int FETCH_ZIP_CODE = 2;
private Unbinder unbinder;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@@ -40,7 +39,7 @@ public class ModulesFragment extends Fragment implements Topic.Subscriber {
Utils.runWithPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/zip");
startActivityForResult(intent, FETCH_ZIP_CODE);
startActivityForResult(intent, Const.ID.FETCH_ZIP);
});
}
@@ -54,7 +53,7 @@ public class ModulesFragment extends Fragment implements Topic.Subscriber {
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.GONE);
new LoadModules(getActivity()).exec();
new LoadModules().exec();
});
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@@ -86,10 +85,10 @@ public class ModulesFragment extends Fragment implements Topic.Subscriber {
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FETCH_ZIP_CODE && resultCode == Activity.RESULT_OK && data != null) {
if (requestCode == Const.ID.FETCH_ZIP && resultCode == Activity.RESULT_OK && data != null) {
// Get the URI of the selected file
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(data.getData()).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
intent.setData(data.getData()).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
startActivity(intent);
}
}

View File

@@ -47,7 +47,7 @@ public class ReposFragment extends Fragment implements Topic.Subscriber {
mSwipeRefreshLayout.setOnRefreshListener(() -> {
recyclerView.setVisibility(View.VISIBLE);
emptyRv.setVisibility(View.GONE);
new UpdateRepos(getActivity(), true).exec();
new UpdateRepos(true).exec();
});
getActivity().setTitle(R.string.downloads);

View File

@@ -8,17 +8,20 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.text.InputType;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.HideManager;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
@@ -71,8 +74,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
}
public static class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener,
Topic.Subscriber {
implements SharedPreferences.OnSharedPreferenceChangeListener, Topic.Subscriber {
private SharedPreferences prefs;
private PreferenceScreen prefScreen;
@@ -86,30 +88,59 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.app_settings);
prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
prefScreen = getPreferenceScreen();
mm = Utils.getMagiskManager(getActivity());
prefs = mm.prefs;
prefScreen = getPreferenceScreen();
generalCatagory = (PreferenceCategory) findPreference("general");
PreferenceCategory magiskCategory = (PreferenceCategory) findPreference("magisk");
PreferenceCategory suCategory = (PreferenceCategory) findPreference("superuser");
updateChannel = (ListPreference) findPreference("update_channel");
suAccess = (ListPreference) findPreference("su_access");
autoRes = (ListPreference) findPreference("su_auto_response");
requestTimeout = (ListPreference) findPreference("su_request_timeout");
suNotification = (ListPreference) findPreference("su_notification");
multiuserMode = (ListPreference) findPreference("multiuser_mode");
namespaceMode = (ListPreference) findPreference("mnt_ns");
SwitchPreference reauth = (SwitchPreference) findPreference("su_reauth");
Preference hideManager = findPreference("hide");
findPreference("clear").setOnPreferenceClickListener((pref) -> {
prefs.edit().remove(Const.Key.ETAG_KEY).apply();
mm.repoDB.clearRepo();
MagiskManager.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
return true;
});
updateChannel = (ListPreference) findPreference(Const.Key.UPDATE_CHANNEL);
suAccess = (ListPreference) findPreference(Const.Key.ROOT_ACCESS);
autoRes = (ListPreference) findPreference(Const.Key.SU_AUTO_RESPONSE);
requestTimeout = (ListPreference) findPreference(Const.Key.SU_REQUEST_TIMEOUT);
suNotification = (ListPreference) findPreference(Const.Key.SU_NOTIFICATION);
multiuserMode = (ListPreference) findPreference(Const.Key.SU_MULTIUSER_MODE);
namespaceMode = (ListPreference) findPreference(Const.Key.SU_MNT_NS);
SwitchPreference reauth = (SwitchPreference) findPreference(Const.Key.SU_REAUTH);
updateChannel.setOnPreferenceChangeListener((pref, o) -> {
mm.updateChannel = Integer.parseInt((String) o);
if (mm.updateChannel == Const.Value.CUSTOM_CHANNEL) {
LinearLayout layout = new LinearLayout(getActivity());
EditText url = new EditText(getActivity());
url.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
url.setText(mm.customChannelUrl);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(url);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) url.getLayoutParams();
params.setMargins(Utils.dpInPx(15), 0, Utils.dpInPx(15), 0);
new AlertDialogBuilder(getActivity())
.setTitle(R.string.settings_update_custom)
.setMessage(R.string.settings_update_custom_msg)
.setView(layout)
.setPositiveButton(R.string.ok, (d, i) -> {
prefs.edit().putString(Const.Key.CUSTOM_CHANNEL, url.getText().toString()).apply();
})
.setNegativeButton(R.string.close, null)
.show();
}
return true;
});
setSummary();
// Disable dangerous settings in user mode if selected owner manage
if (getActivity().getApplicationInfo().uid > 99999) {
if (mm.userId > 0) {
suCategory.removePreference(multiuserMode);
generalCatagory.removePreference(hideManager);
}
// Remove re-authentication option on Android O, it will not work
@@ -117,29 +148,23 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
suCategory.removePreference(reauth);
}
findPreference("clear").setOnPreferenceClickListener((pref) -> {
Utils.clearRepoCache(getActivity());
return true;
});
hideManager.setOnPreferenceClickListener((pref) -> {
Utils.runWithPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
() -> new HideManager(getActivity()).exec());
return true;
});
if (mm.getPackageName().equals(Const.ORIG_PKG_NAME) && mm.magiskVersionCode >= 1440) {
hideManager.setOnPreferenceClickListener((pref) -> {
Utils.runWithPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
() -> new HideManager().exec());
return true;
});
} else {
generalCatagory.removePreference(hideManager);
}
if (!Shell.rootAccess()) {
prefScreen.removePreference(magiskCategory);
prefScreen.removePreference(suCategory);
generalCatagory.removePreference(hideManager);
} else {
if (!mm.isSuClient) {
prefScreen.removePreference(suCategory);
}
if (mm.magiskVersionCode < 1300) {
prefScreen.removePreference(magiskCategory);
}
} else if (mm.magiskVersionCode < 1300) {
prefScreen.removePreference(magiskCategory);
}
}
@@ -160,7 +185,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
lp.setEntries(entries);
lp.setEntryValues(entryValues);
lp.setTitle(R.string.language);
lp.setKey("locale");
lp.setKey(Const.Key.LOCALE);
lp.setSummary(MagiskManager.locale.getDisplayName(MagiskManager.locale));
if (isNew) {
generalCatagory.addPreference(lp);
@@ -186,67 +211,62 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
boolean enabled;
switch (key) {
case "dark_theme":
enabled = prefs.getBoolean("dark_theme", false);
case Const.Key.DARK_THEME:
enabled = prefs.getBoolean(Const.Key.DARK_THEME, false);
if (mm.isDarkTheme != enabled) {
mm.reloadActivity.publish(false);
}
break;
case "disable":
enabled = prefs.getBoolean("disable", false);
case Const.Key.DISABLE:
enabled = prefs.getBoolean(Const.Key.DISABLE, false);
if (enabled) {
Utils.createFile(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
Utils.createFile(Const.MAGISK_DISABLE_FILE);
} else {
Utils.removeItem(getShell(), MagiskManager.MAGISK_DISABLE_FILE);
Utils.removeItem(Const.MAGISK_DISABLE_FILE);
}
Toast.makeText(getActivity(), R.string.settings_reboot_toast, Toast.LENGTH_LONG).show();
break;
case "magiskhide":
enabled = prefs.getBoolean("magiskhide", false);
case Const.Key.MAGISKHIDE:
enabled = prefs.getBoolean(Const.Key.MAGISKHIDE, false);
if (enabled) {
Utils.enableMagiskHide(getShell());
Shell.su_raw("magiskhide --enable");
} else {
Utils.disableMagiskHide(getShell());
Shell.su_raw("magiskhide --disable");
}
break;
case "hosts":
enabled = prefs.getBoolean("hosts", false);
case Const.Key.HOSTS:
enabled = prefs.getBoolean(Const.Key.HOSTS, false);
if (enabled) {
getShell().su_raw(
"cp -af /system/etc/hosts " + MagiskManager.MAGISK_HOST_FILE,
"mount -o bind " + MagiskManager.MAGISK_HOST_FILE + " /system/etc/hosts");
Shell.su_raw(
"cp -af /system/etc/hosts " + Const.MAGISK_HOST_FILE(),
"mount -o bind " + Const.MAGISK_HOST_FILE() + " /system/etc/hosts");
} else {
getShell().su_raw(
Shell.su_raw(
"umount -l /system/etc/hosts",
"rm -f " + MagiskManager.MAGISK_HOST_FILE);
"rm -f " + Const.MAGISK_HOST_FILE());
}
break;
case "su_access":
mm.suDB.setSettings(SuDatabaseHelper.ROOT_ACCESS, Utils.getPrefsInt(prefs, "su_access"));
case Const.Key.ROOT_ACCESS:
mm.suDB.setSettings(Const.Key.ROOT_ACCESS, Utils.getPrefsInt(prefs, Const.Key.ROOT_ACCESS));
break;
case "multiuser_mode":
mm.suDB.setSettings(SuDatabaseHelper.MULTIUSER_MODE, Utils.getPrefsInt(prefs, "multiuser_mode"));
case Const.Key.SU_MULTIUSER_MODE:
mm.suDB.setSettings(Const.Key.SU_MULTIUSER_MODE, Utils.getPrefsInt(prefs, Const.Key.SU_MULTIUSER_MODE));
break;
case "mnt_ns":
mm.suDB.setSettings(SuDatabaseHelper.MNT_NS, Utils.getPrefsInt(prefs, "mnt_ns"));
case Const.Key.SU_MNT_NS:
mm.suDB.setSettings(Const.Key.SU_MNT_NS, Utils.getPrefsInt(prefs, Const.Key.SU_MNT_NS));
break;
case "locale":
case Const.Key.LOCALE:
mm.setLocale();
mm.reloadActivity.publish(false);
break;
case "update_channel":
mm.updateChannel = Utils.getPrefsInt(prefs, "update_channel");
new CheckUpdates(mm, true).exec();
case Const.Key.UPDATE_CHANNEL:
new CheckUpdates().exec();
break;
}
mm.loadConfig();
setSummary();
}
private Shell getShell() {
return Shell.getShell(getActivity());
}
private void setSummary() {
updateChannel.setSummary(getResources()
.getStringArray(R.array.update_channel)[mm.updateChannel]);
@@ -257,7 +277,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
suNotification.setSummary(getResources()
.getStringArray(R.array.su_notification)[mm.suNotificationType]);
requestTimeout.setSummary(
getString(R.string.request_timeout_summary, prefs.getString("su_request_timeout", "10")));
getString(R.string.request_timeout_summary, prefs.getString(Const.Key.SU_REQUEST_TIMEOUT, "10")));
multiuserMode.setSummary(getResources()
.getStringArray(R.array.multiuser_summary)[mm.multiuserMode]);
namespaceMode.setSummary(getResources()
@@ -266,7 +286,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
@Override
public void onTopicPublished(Topic topic, Object result) {
setLocalePreference((ListPreference) findPreference("locale"));
setLocalePreference((ListPreference) findPreference(Const.Key.LOCALE));
}
@Override

View File

@@ -1,9 +1,27 @@
package com.topjohnwu.magisk;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.topjohnwu.magisk.asyncs.CheckUpdates;
import com.topjohnwu.magisk.asyncs.LoadModules;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.database.SuDatabaseHelper;
import com.topjohnwu.magisk.services.UpdateCheckService;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.util.List;
public class SplashActivity extends Activity {
@@ -11,14 +29,106 @@ public class SplashActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMagiskManager().startup();
MagiskManager mm = getMagiskManager();
// Dynamic detect all locales
new LoadLocale().exec();
// Create notification channel on Android O
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(Const.ID.NOTIFICATION_CHANNEL,
getString(R.string.magisk_updates), NotificationManager.IMPORTANCE_DEFAULT);
getSystemService(NotificationManager.class).createNotificationChannel(channel);
}
mm.loadMagiskInfo();
LoadModules loadModuleTask = new LoadModules();
if (Utils.checkNetworkStatus()) {
// Fire update check
new CheckUpdates().exec();
// Add repo update check
loadModuleTask.setCallBack(() -> new UpdateRepos(false).exec());
}
// Magisk working as expected
if (Shell.rootAccess() && mm.magiskVersionCode > 0) {
List<String> ret = Shell.su("echo \"$BOOTIMAGE\"");
if (Utils.isValidShellResponse(ret)) {
mm.bootBlock = ret.get(0);
}
// Setup suDB
SuDatabaseHelper.setupSuDB();
// Check alternative Magisk Manager
String pkg;
if (getPackageName().equals(Const.ORIG_PKG_NAME) &&
(pkg = mm.suDB.getStrings(Const.Key.SU_REQUESTER, null)) != null) {
Shell.su_raw("pm uninstall " + pkg);
mm.suDB.setStrings(Const.Key.SU_REQUESTER, null);
}
// Add update checking service
if (Const.Value.UPDATE_SERVICE_VER > mm.updateServiceVersion) {
ComponentName service = new ComponentName(this, UpdateCheckService.class);
JobInfo info = new JobInfo.Builder(Const.ID.UPDATE_SERVICE_ID, service)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.setPeriodic(8 * 60 * 60 * 1000)
.build();
((JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE)).schedule(info);
mm.updateServiceVersion = Const.Value.UPDATE_SERVICE_VER;
}
// Fire asynctasks
loadModuleTask.exec();
// Check dtbo status
Utils.patchDTBO();
}
// Write back default values
mm.prefs.edit()
.putBoolean(Const.Key.DARK_THEME, mm.isDarkTheme)
.putBoolean(Const.Key.MAGISKHIDE, mm.magiskHide)
.putBoolean(Const.Key.UPDATE_NOTIFICATION, mm.updateNotification)
.putBoolean(Const.Key.HOSTS, Utils.itemExist(Const.MAGISK_HOST_FILE()))
.putBoolean(Const.Key.DISABLE, Utils.itemExist(Const.MAGISK_DISABLE_FILE))
.putBoolean(Const.Key.SU_REAUTH, mm.suReauth)
.putString(Const.Key.SU_REQUEST_TIMEOUT, String.valueOf(mm.suRequestTimeout))
.putString(Const.Key.SU_AUTO_RESPONSE, String.valueOf(mm.suResponseType))
.putString(Const.Key.SU_NOTIFICATION, String.valueOf(mm.suNotificationType))
.putString(Const.Key.ROOT_ACCESS, String.valueOf(mm.suAccessState))
.putString(Const.Key.SU_MULTIUSER_MODE, String.valueOf(mm.multiuserMode))
.putString(Const.Key.SU_MNT_NS, String.valueOf(mm.suNamespaceMode))
.putString(Const.Key.UPDATE_CHANNEL, String.valueOf(mm.updateChannel))
.putString(Const.Key.LOCALE, mm.localeConfig)
.putString(Const.Key.BOOT_FORMAT, mm.bootFormat)
.putInt(Const.Key.UPDATE_SERVICE_VER, mm.updateServiceVersion)
.apply();
mm.hasInit = true;
Intent intent = new Intent(this, MainActivity.class);
String section = getIntent().getStringExtra(MagiskManager.INTENT_SECTION);
if (section != null) {
intent.putExtra(MagiskManager.INTENT_SECTION, section);
}
intent.putExtra(Const.Key.OPEN_SECTION, getIntent().getStringExtra(Const.Key.OPEN_SECTION));
intent.putExtra(Const.Key.INTENT_PERM, getIntent().getStringExtra(Const.Key.INTENT_PERM));
startActivity(intent);
finish();
}
static class LoadLocale extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
MagiskManager.get().locales = Utils.getAvailableLocale();
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
MagiskManager.get().localeDone.publish();
}
}
}

View File

@@ -5,6 +5,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -16,12 +17,12 @@ import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -31,23 +32,11 @@ import butterknife.ButterKnife;
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
public static final List<String> BLACKLIST = Arrays.asList(
"android",
"com.topjohnwu.magisk",
"com.google.android.gms"
);
private static final List<String> SNLIST = Arrays.asList(
"com.google.android.apps.walletnfcrel",
"com.nianticlabs.pokemongo"
);
private List<ApplicationInfo> mOriginalList, mList;
private List<String> mHideList;
private PackageManager pm;
private ApplicationFilter filter;
private Topic magiskHideDone;
private Shell shell;
public ApplicationAdapter(Context context) {
mOriginalList = mList = Collections.emptyList();
@@ -55,10 +44,13 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
filter = new ApplicationFilter();
pm = context.getPackageManager();
magiskHideDone = Utils.getMagiskManager(context).magiskHideDone;
shell = Shell.getShell(context);
new LoadApps().exec();
}
private boolean lowercaseContains(CharSequence string, CharSequence nonNullLowercaseSearch) {
return !TextUtils.isEmpty(string) && string.toString().toLowerCase().contains(nonNullLowercaseSearch);
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_app, parent, false);
@@ -77,7 +69,7 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
holder.itemView.setOnClickListener(null);
holder.checkBox.setOnCheckedChangeListener(null);
if (SNLIST.contains(info.packageName)) {
if (Const.SN_DEFAULTLIST.contains(info.packageName)) {
holder.checkBox.setChecked(true);
holder.checkBox.setEnabled(false);
holder.itemView.setOnClickListener(v ->
@@ -89,10 +81,10 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
holder.checkBox.setChecked(mHideList.contains(info.packageName));
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
if (isChecked) {
Utils.addMagiskHide(shell, info.packageName);
Shell.su_raw("magiskhide --add " + info.packageName);
mHideList.add(info.packageName);
} else {
Utils.rmMagiskHide(shell, info.packageName);
Shell.su_raw("magiskhide --rm " + info.packageName);
mHideList.remove(info.packageName);
}
});
@@ -135,8 +127,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
mList = new ArrayList<>();
String filter = constraint.toString().toLowerCase();
for (ApplicationInfo info : mOriginalList) {
if (Utils.lowercaseContains(info.loadLabel(pm), filter)
|| Utils.lowercaseContains(info.packageName, filter)) {
if (lowercaseContains(info.loadLabel(pm), filter)
|| lowercaseContains(info.packageName, filter)) {
mList.add(info);
}
}
@@ -157,13 +149,13 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
mOriginalList = pm.getInstalledApplications(0);
for (Iterator<ApplicationInfo> i = mOriginalList.iterator(); i.hasNext(); ) {
ApplicationInfo info = i.next();
if (ApplicationAdapter.BLACKLIST.contains(info.packageName) || !info.enabled) {
if (Const.SN_BLACKLIST.contains(info.packageName) || !info.enabled) {
i.remove();
}
}
Collections.sort(mOriginalList, (a, b) -> a.loadLabel(pm).toString().toLowerCase()
.compareTo(b.loadLabel(pm).toString().toLowerCase()));
mHideList = Utils.listMagiskHide(shell);
mHideList = Shell.su("magiskhide --ls");
return null;
}

View File

@@ -38,7 +38,6 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Context context = holder.itemView.getContext();
Shell rootShell = Shell.getShell(context);
final Module module = mList.get(position);
String version = module.getVersion();
@@ -56,10 +55,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
int snack;
if (isChecked) {
module.removeDisableFile(rootShell);
module.removeDisableFile();
snack = R.string.disable_file_removed;
} else {
module.createDisableFile(rootShell);
module.createDisableFile();
snack = R.string.disable_file_created;
}
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();
@@ -69,10 +68,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
boolean removed = module.willBeRemoved();
int snack;
if (removed) {
module.deleteRemoveFile(rootShell);
module.deleteRemoveFile();
snack = R.string.remove_file_deleted;
} else {
module.createRemoveFile(rootShell);
module.createRemoveFile();
snack = R.string.remove_file_created;
}
SnackbarMaker.make(holder.itemView, snack, Snackbar.LENGTH_SHORT).show();

View File

@@ -1,14 +1,18 @@
package com.topjohnwu.magisk.asyncs;
import android.support.v4.app.FragmentActivity;
import android.app.Activity;
import com.topjohnwu.jarsigner.ByteArrayStream;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Proxy;
import java.net.HttpURLConnection;
@@ -17,42 +21,36 @@ import dalvik.system.DexClassLoader;
public class CheckSafetyNet extends ParallelTask<Void, Void, Exception> {
public static final int SNET_VER = 2;
private static final String SNET_URL = "https://github.com/topjohnwu/MagiskManager/releases/download/v5.4.0/snet.apk";
private static final String PKG = "com.topjohnwu.snet";
private File dexPath;
private DexClassLoader loader;
public CheckSafetyNet(FragmentActivity activity) {
public CheckSafetyNet(Activity activity) {
super(activity);
dexPath = new File(activity.getCacheDir().getParent() + "/snet", "snet.apk");
}
@Override
protected void onPreExecute() {
MagiskManager mm = getMagiskManager();
if (mm.snet_version != CheckSafetyNet.SNET_VER) {
getShell().sh("rm -rf " + dexPath.getParent());
MagiskManager mm = MagiskManager.get();
if (mm.snet_version != Const.Value.SNET_VER) {
Shell.sh("rm -rf " + dexPath.getParent());
}
mm.snet_version = CheckSafetyNet.SNET_VER;
mm.prefs.edit().putInt("snet_version", CheckSafetyNet.SNET_VER).apply();
mm.snet_version = Const.Value.SNET_VER;
mm.prefs.edit().putInt(Const.Key.SNET_VER, Const.Value.SNET_VER).apply();
}
@Override
protected Exception doInBackground(Void... voids) {
try {
if (!dexPath.exists()) {
HttpURLConnection conn = WebService.request(SNET_URL, null);
ByteArrayStream bas = new ByteArrayStream();
bas.readFrom(conn.getInputStream());
conn.disconnect();
HttpURLConnection conn = WebService.request(Const.Url.SNET_URL, null);
dexPath.getParentFile().mkdir();
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(dexPath))) {
bas.writeTo(out);
out.flush();
try (
OutputStream out = new BufferedOutputStream(new FileOutputStream(dexPath));
InputStream in = new BufferedInputStream(conn.getInputStream())) {
Utils.inToOut(in, out);
}
conn.disconnect();
}
loader = new DexClassLoader(dexPath.toString(), dexPath.getParent(),
null, ClassLoader.getSystemClassLoader());
@@ -64,20 +62,21 @@ public class CheckSafetyNet extends ParallelTask<Void, Void, Exception> {
@Override
protected void onPostExecute(Exception err) {
MagiskManager mm = MagiskManager.get();
try {
if (err != null) throw err;
Class<?> helperClazz = loader.loadClass(PKG + ".SafetyNetHelper");
Class<?> callbackClazz = loader.loadClass(PKG + ".SafetyNetCallback");
Class<?> helperClazz = loader.loadClass(Const.SNET_PKG + ".SafetyNetHelper");
Class<?> callbackClazz = loader.loadClass(Const.SNET_PKG + ".SafetyNetCallback");
Object helper = helperClazz.getConstructors()[0].newInstance(
getActivity(), Proxy.newProxyInstance(
getActivity(), dexPath.getPath(), Proxy.newProxyInstance(
loader, new Class[] { callbackClazz }, (proxy, method, args) -> {
getMagiskManager().safetyNetDone.publish(false, args[0]);
mm.safetyNetDone.publish(false, args[0]);
return null;
}));
helperClazz.getMethod("attest").invoke(helper);
} catch (Exception e) {
e.printStackTrace();
getMagiskManager().safetyNetDone.publish(false, -1);
mm.safetyNetDone.publish(false, -1);
}
super.onPostExecute(err);
}

View File

@@ -1,10 +1,9 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import com.topjohnwu.magisk.BuildConfig;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.ShowUI;
import com.topjohnwu.magisk.utils.WebService;
import org.json.JSONException;
@@ -12,37 +11,30 @@ import org.json.JSONObject;
public class CheckUpdates extends ParallelTask<Void, Void, Void> {
public static final int STABLE_CHANNEL = 0;
public static final int BETA_CHANNEL = 1;
private boolean showNotification;
private static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/stable.json";
private static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/beta.json";
private boolean showNotification = false;
public CheckUpdates(Context context) {
super(context);
public CheckUpdates() {
this(false);
}
public CheckUpdates(Context context, boolean b) {
super(context);
public CheckUpdates(boolean b) {
showNotification = b;
}
@Override
protected Void doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return null;
String jsonStr;
MagiskManager mm = MagiskManager.get();
String jsonStr = "";
switch (mm.updateChannel) {
case STABLE_CHANNEL:
jsonStr = WebService.getString(STABLE_URL);
case Const.Value.STABLE_CHANNEL:
jsonStr = WebService.getString(Const.Url.STABLE_URL);
break;
case BETA_CHANNEL:
jsonStr = WebService.getString(BETA_URL);
case Const.Value.BETA_CHANNEL:
jsonStr = WebService.getString(Const.Url.BETA_URL);
break;
case Const.Value.CUSTOM_CHANNEL:
jsonStr = WebService.getString(mm.customChannelUrl);
break;
default:
jsonStr = null;
}
try {
JSONObject json = new JSONObject(jsonStr);
@@ -61,13 +53,12 @@ public class CheckUpdates extends ParallelTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void v) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
MagiskManager mm = MagiskManager.get();
if (showNotification && mm.updateNotification) {
if (BuildConfig.VERSION_CODE < mm.remoteManagerVersionCode) {
Utils.showManagerUpdateNotification(mm);
ShowUI.managerUpdateNotification();
} else if (mm.magiskVersionCode < mm.remoteMagiskVersionCode) {
Utils.showMagiskUpdateNotification(mm);
ShowUI.magiskUpdateNotification();
}
}
mm.updateCheckDone.publish();

View File

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

View File

@@ -3,10 +3,12 @@ package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.AdaptiveList;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
@@ -24,38 +26,27 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
private Uri mUri;
private File mCachedFile;
private AdaptiveList<String> mList;
private List<String> console, logs;
public FlashZip(Activity context, Uri uri, AdaptiveList<String> list) {
public FlashZip(Activity context, Uri uri, List<String> console, List<String> logs) {
super(context);
mUri = uri;
mList = list;
this.console = console;
this.logs = logs;
mCachedFile = new File(context.getCacheDir(), "install.zip");
}
private boolean unzipAndCheck() throws Exception {
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", true);
List<String> ret = Utils.readFile(getShell(), new File(mCachedFile.getParentFile(), "updater-script").getPath());
List<String> ret = Utils.readFile(new File(mCachedFile.getParentFile(), "updater-script").getPath());
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
}
@Override
protected void onPreExecute() {
// UI updates must run in the UI thread
mList.setCallback(this::publishProgress);
}
@Override
protected void onProgressUpdate(Void... values) {
mList.updateView();
}
@Override
protected Integer doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return -1;
MagiskManager mm = MagiskManager.get();
try {
mList.add("- Copying zip to temp directory");
console.add("- Copying zip to temp directory");
mCachedFile.delete();
try (
@@ -64,54 +55,54 @@ public class FlashZip extends ParallelTask<Void, Void, Integer> {
) {
if (in == null) throw new FileNotFoundException();
InputStream buf= new BufferedInputStream(in);
byte buffer[] = new byte[4096];
int length;
while ((length = buf.read(buffer)) > 0)
out.write(buffer, 0, length);
Utils.inToOut(buf, out);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
console.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Cannot copy to cache");
console.add("! Cannot copy to cache");
throw e;
}
if (!unzipAndCheck()) return 0;
mList.add("- Installing " + Utils.getNameFromUri(mm, mUri));
getShell().su(mList,
console.add("- Installing " + Utils.getNameFromUri(mm, mUri));
Shell.getShell().run(console, logs,
"cd " + mCachedFile.getParent(),
"BOOTMODE=true sh update-binary dummy 1 " + mCachedFile +
" && echo 'Success!' || echo 'Failed!'"
"BOOTMODE=true sh update-binary dummy 1 " + mCachedFile + " || echo 'Failed!'"
);
if (TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
return 1;
if (TextUtils.equals(console.get(console.size() - 1), "Failed!"))
return -1;
} catch (Exception e) {
e.printStackTrace();
return -1;
}
return -1;
console.add("- All done!");
return 1;
}
// -1 = error, manual install; 0 = invalid zip; 1 = success
@Override
protected void onPostExecute(Integer result) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
getShell().su_raw(
FlashActivity activity = (FlashActivity) getActivity();
Shell.su_raw(
"rm -rf " + mCachedFile.getParent(),
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
"rm -rf " + Const.TMP_FOLDER_PATH
);
switch (result) {
case -1:
mList.add(mm.getString(R.string.install_error));
console.add("! Installation failed");
Utils.showUriSnack(getActivity(), mUri);
break;
case 0:
mList.add(mm.getString(R.string.invalid_zip));
console.add("! This zip is not a Magisk Module!");
break;
case 1:
// Success
new LoadModules(mm).exec();
new LoadModules().exec();
break;
}
super.onPostExecute(result);
activity.reboot.setVisibility(result > 0 ? View.VISIBLE : View.GONE);
activity.buttonPanel.setVisibility(View.VISIBLE);
}
}

View File

@@ -1,114 +1,145 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.widget.Toast;
import com.topjohnwu.jarsigner.JarMap;
import com.topjohnwu.crypto.JarMap;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
import java.io.File;
import java.io.FileInputStream;
import java.security.SecureRandom;
import java.util.List;
import java.util.Locale;
import java.util.jar.JarEntry;
public class HideManager extends ParallelTask<Void, Void, Boolean> {
private static final String UNHIDE_APK = "unhide.apk";
private static final String ANDROID_MANIFEST = "AndroidManifest.xml";
private static final byte[] UNHIDE_PKG_NAME = "com.topjohnwu.unhide\0".getBytes();
private String genPackageName(String prefix, int length) {
StringBuilder builder = new StringBuilder(length);
builder.append(prefix);
length -= prefix.length();
SecureRandom random = new SecureRandom();
String base = "abcdefghijklmnopqrstuvwxyz";
String alpha = base + base.toUpperCase();
String full = alpha + "0123456789..........";
char next, prev = '\0';
for (int i = 0; i < length; ++i) {
if (prev == '.' || i == length - 1 || i == 0) {
next = alpha.charAt(random.nextInt(alpha.length()));
} else {
next = full.charAt(random.nextInt(full.length()));
}
builder.append(next);
prev = next;
}
return builder.toString();
}
public HideManager(Context context) {
super(context);
private int findOffset(byte buf[], byte pattern[]) {
int offset = -1;
for (int i = 0; i < buf.length - pattern.length; ++i) {
boolean match = true;
for (int j = 0; j < pattern.length; ++j) {
if (buf[i + j] != pattern[j]) {
match = false;
break;
}
}
if (match) {
offset = i;
break;
}
}
return offset;
}
/* It seems that AAPT sometimes generate another type of string format */
private boolean fallbackPatch(byte xml[], String from, String to) {
byte[] target = new byte[from.length() * 2 + 2];
for (int i = 0; i < from.length(); ++i) {
target[i * 2] = (byte) from.charAt(i);
}
int offset = findOffset(xml, target);
if (offset < 0)
return false;
byte[] dest = new byte[target.length - 2];
for (int i = 0; i < to.length(); ++i) {
dest[i * 2] = (byte) to.charAt(i);
}
System.arraycopy(dest, 0, xml, offset, dest.length);
return true;
}
private boolean findAndPatch(byte xml[], String from, String to) {
byte target[] = (from + '\0').getBytes();
int offset = findOffset(xml, target);
if (offset < 0)
return fallbackPatch(xml, from, to);
System.arraycopy(to.getBytes(), 0, xml, offset, to.length());
return true;
}
@Override
protected void onPreExecute() {
getMagiskManager().toast(R.string.hide_manager_toast, Toast.LENGTH_SHORT);
MagiskManager.toast(R.string.hide_manager_toast, Toast.LENGTH_SHORT);
MagiskManager.toast(R.string.hide_manager_toast2, Toast.LENGTH_LONG);
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return false;
MagiskManager mm = MagiskManager.get();
// Generate a new unhide app with random package name
File unhideAPK = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", "unhide.apk");
unhideAPK.getParentFile().mkdirs();
String pkg;
File repack = new File(Const.EXTERNAL_PATH, "repack.apk");
repack.getParentFile().mkdirs();
String pkg = genPackageName("com.", Const.ORIG_PKG_NAME.length());
try {
JarMap asset = new JarMap(mm.getAssets().open(UNHIDE_APK));
JarEntry je = new JarEntry(ANDROID_MANIFEST);
byte xml[] = asset.getRawData(je);
int offset = -1;
// Read whole APK into memory
JarMap apk = new JarMap(new FileInputStream(mm.getPackageCodePath()));
JarEntry je = new JarEntry(Const.ANDROID_MANIFEST);
byte xml[] = apk.getRawData(je);
// Linear search pattern offset
for (int i = 0; i < xml.length - UNHIDE_PKG_NAME.length; ++i) {
boolean match = true;
for (int j = 0; j < UNHIDE_PKG_NAME.length; ++j) {
if (xml[i + j] != UNHIDE_PKG_NAME[j]) {
match = false;
break;
}
}
if (match) {
offset = i;
break;
}
}
if (offset < 0)
if (!findAndPatch(xml, Const.ORIG_PKG_NAME, pkg))
return false;
if (!findAndPatch(xml, Const.ORIG_PKG_NAME + ".provider", pkg + ".provider"))
return false;
// Patch binary XML with new package name
pkg = Utils.genPackageName("com.", UNHIDE_PKG_NAME.length - 1);
System.arraycopy(pkg.getBytes(), 0, xml, offset, pkg.length());
asset.getOutputStream(je).write(xml);
// Write in changes
apk.getOutputStream(je).write(xml);
// Sign the APK
ZipUtils.signZip(mm, asset, unhideAPK, false);
ZipUtils.signZip(apk, repack, false);
} catch (Exception e) {
e.printStackTrace();
return false;
}
// Install the application
List<String> ret = getShell().su("pm install " + unhideAPK + ">/dev/null && echo true || echo false");
unhideAPK.delete();
List<String> ret = Shell.su(String.format(Locale.US,
"pm install --user %d %s >/dev/null && echo true || echo false",
mm.userId, repack));
repack.delete();
if (!Utils.isValidShellResponse(ret) || !Boolean.parseBoolean(ret.get(0)))
return false;
try {
// Allow the application to gain root by default
PackageManager pm = mm.getPackageManager();
int uid = pm.getApplicationInfo(pkg, 0).uid;
Policy policy = new Policy(uid, pm);
policy.policy = Policy.ALLOW;
policy.notification = false;
policy.logging = false;
mm.suDB.addPolicy(policy);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return false;
}
mm.suDB.setStrings(Const.Key.SU_REQUESTER, pkg);
Shell.su_raw(String.format(Locale.US, "pm uninstall --user %d %s", mm.userId, mm.getPackageName()));
// Hide myself!
getShell().su_raw("pm hide " + mm.getPackageName());
return true;
}
@Override
protected void onPostExecute(Boolean b) {
MagiskManager mm = getMagiskManager();
if (mm == null)
return;
if (!b) {
mm.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
MagiskManager.toast(R.string.hide_manager_fail_toast, Toast.LENGTH_LONG);
}
super.onPostExecute(b);
}

View File

@@ -1,14 +1,17 @@
package com.topjohnwu.magisk.asyncs;
import android.app.Activity;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import com.topjohnwu.crypto.SignBoot;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.container.AdaptiveList;
import com.topjohnwu.magisk.container.TarEntry;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.ZipUtils;
@@ -34,49 +37,42 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
private static final int DIRECT_MODE = 1;
private Uri mBootImg, mZip;
private AdaptiveList<String> mList;
private List<String> console, logs;
private String mBootLocation;
private boolean mKeepEnc, mKeepVerity;
private int mode;
private InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity) {
private InstallMagisk(Activity context, List<String> console, List<String> logs, Uri zip, boolean enc, boolean verity) {
super(context);
mList = list;
this.console = console;
this.logs = logs;
mZip = zip;
mKeepEnc = enc;
mKeepVerity = verity;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, Uri boot) {
this(context, list, zip, enc, verity);
public InstallMagisk(Activity context, List<String> console, List<String> logs, Uri zip, boolean enc, boolean verity, Uri boot) {
this(context, console, logs, zip, enc, verity);
mBootImg = boot;
mode = PATCH_MODE;
}
public InstallMagisk(Activity context, AdaptiveList<String> list, Uri zip, boolean enc, boolean verity, String boot) {
this(context, list, zip, enc, verity);
public InstallMagisk(Activity context, List<String> console, List<String> logs, Uri zip, boolean enc, boolean verity, String boot) {
this(context, console, logs, zip, enc, verity);
mBootLocation = boot;
mode = DIRECT_MODE;
}
@Override
protected void onPreExecute() {
// UI updates must run in the UI thread
mList.setCallback(this::publishProgress);
}
@Override
protected void onProgressUpdate(Void... values) {
mList.updateView();
}
@Override
protected Boolean doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return false;
MagiskManager mm = MagiskManager.get();
File install = new File(Utils.getEncContext(mm).getFilesDir().getParent(), "install");
getShell().sh_raw("rm -rf " + install);
File install = new File(
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ?
mm.createDeviceProtectedStorageContext() :
mm).getFilesDir().getParent()
, "install");
Shell.sh_raw("rm -rf " + install);
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
String arch;
@@ -84,11 +80,11 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
else if (abis.contains("arm64-v8a")) arch = "arm64";
else if (abis.contains("x86")) arch = "x86";
else arch = "arm";
mList.add("- Device platform: " + arch);
console.add("- Device platform: " + arch);
try {
// Unzip files
mList.add("- Extracting files");
console.add("- Extracting files");
try (InputStream in = mm.getContentResolver().openInputStream(mZip)) {
if (in == null) throw new FileNotFoundException();
BufferedInputStream buf = new BufferedInputStream(in);
@@ -100,18 +96,19 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
ZipUtils.unzip(buf, install, "chromeos/", false);
buf.reset();
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
buf.close();
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
console.add("! Invalid Uri");
throw e;
} catch (Exception e) {
mList.add("! Cannot unzip zip");
console.add("! Cannot unzip zip");
throw e;
}
File boot;
File boot = new File(install, "boot.img");
switch (mode) {
case PATCH_MODE:
boot = new File(install, "boot.img");
console.add("- Use boot image: " + boot);
// Copy boot image to local
try (
InputStream in = mm.getContentResolver().openInputStream(mBootImg);
@@ -133,89 +130,120 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
// Direct copy raw image
source = new BufferedInputStream(in);
}
byte buffer[] = new byte[1024];
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
Utils.inToOut(source, out);
} catch (FileNotFoundException e) {
mList.add("! Invalid Uri");
console.add("! Invalid Uri");
throw e;
} catch (IOException e) {
mList.add("! Copy failed");
console.add("! Copy failed");
throw e;
}
break;
case DIRECT_MODE:
boot = new File(mBootLocation);
console.add("- Use boot image: " + mBootLocation);
if (boot.createNewFile()) {
Shell.su("cat " + mBootLocation + " > " + boot);
} else {
console.add("! Dump boot image failed");
return false;
}
break;
default:
return false;
}
mList.add("- Use boot image: " + boot);
Shell shell;
if (mode == PATCH_MODE && Shell.rootAccess()) {
// Force non-root shell
shell = Shell.getShell("sh");
} else {
shell = getShell();
boolean isSigned;
try (InputStream in = new FileInputStream(boot)) {
isSigned = SignBoot.verifySignature(in, null);
if (isSigned) {
console.add("- Signed boot image detected");
}
} catch (Exception e) {
console.add("! Unable to check signature");
throw e;
}
// Force non-root shell
Shell shell;
if (Shell.rootAccess())
shell = new Shell("sh");
else
shell = Shell.getShell();
// Patch boot image
shell.sh(mList,
shell.run(console, logs,
"cd " + install,
"KEEPFORCEENCRYPT=" + mKeepEnc + " KEEPVERITY=" + mKeepVerity + " sh " +
"update-binary indep boot_patch.sh " + boot +
" && echo 'Success!' || echo 'Failed!'"
);
"update-binary indep boot_patch.sh " + boot + " || echo 'Failed!'");
if (!TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
if (TextUtils.equals(console.get(console.size() - 1), "Failed!"))
return false;
File patched_boot = new File(install, "new-boot.img");
mList.add("");
switch (mode) {
case PATCH_MODE:
File dest = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/patched_boot" + mm.bootFormat);
dest.getParentFile().mkdirs();
switch (mm.bootFormat) {
case ".img":
getShell().sh_raw("cp -f " + patched_boot + " " + dest);
break;
case ".img.tar":
TarOutputStream tar = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
tar.putNextEntry(new TarEntry(patched_boot, "boot.img"));
byte buffer[] = new byte[4096];
BufferedInputStream in = new BufferedInputStream(new FileInputStream(patched_boot));
int len;
while ((len = in.read(buffer)) != -1) {
tar.write(buffer, 0, len);
}
tar.flush();
tar.close();
in.close();
break;
}
mList.add("*********************************");
mList.add(" Patched Boot Image is placed in ");
mList.add(" " + dest + " ");
mList.add("*********************************");
break;
case DIRECT_MODE:
// Direct flash boot image
getShell().su(mList, "flash_boot_image " + patched_boot + " " + mBootLocation);
break;
default:
return false;
}
// Finals
getShell().sh_raw(
"cd " + install,
shell.run(null, null,
"mv -f new-boot.img ../",
"mv bin/busybox busybox",
"rm -rf bin *.img update-binary",
"cd /");
File patched_boot = new File(install.getParent(), "new-boot.img");
if (isSigned) {
console.add("- Signing boot image");
File signed = new File(install.getParent(), "signed.img");
AssetManager assets = mm.getAssets();
try (
InputStream in = new FileInputStream(patched_boot);
OutputStream out = new BufferedOutputStream(new FileOutputStream(signed));
InputStream keyIn = assets.open(Const.PRIVATE_KEY_NAME);
InputStream certIn = assets.open(Const.PUBLIC_KEY_NAME)
) {
SignBoot.doSignature("/boot", in, out, keyIn, certIn);
}
shell.run_raw(false, false, "mv -f " + signed + " " + patched_boot);
}
switch (mode) {
case PATCH_MODE:
File dest = new File(Const.EXTERNAL_PATH, "patched_boot" + mm.bootFormat);
dest.getParentFile().mkdirs();
OutputStream out;
switch (mm.bootFormat) {
case ".img.tar":
out = new TarOutputStream(new BufferedOutputStream(new FileOutputStream(dest)));
((TarOutputStream) out).putNextEntry(new TarEntry(patched_boot, "boot.img"));
break;
default:
case ".img":
out = new BufferedOutputStream(new FileOutputStream(dest));
break;
}
try (InputStream in = new BufferedInputStream(new FileInputStream(patched_boot))) {
Utils.inToOut(in, out);
out.close();
}
console.add("");
console.add("*********************************");
console.add(" Patched Boot Image is placed in ");
console.add(" " + dest + " ");
console.add("*********************************");
break;
case DIRECT_MODE:
// Direct flash boot image and patch dtbo if possible
Shell.getShell().run(console, logs,
"rm -rf /data/magisk/*",
"mkdir -p /data/magisk 2>/dev/null",
"mv -f " + install + "/* /data/magisk",
"rm -rf " + install,
"flash_boot_image " + patched_boot + " " + mBootLocation,
"patch_dtbo_image");
break;
default:
return false;
}
patched_boot.delete();
console.add("- All done!");
} catch (Exception e) {
e.printStackTrace();
return false;
@@ -225,6 +253,11 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
FlashActivity activity = (FlashActivity) getActivity();
if (!result) {
console.add("! Installation failed");
activity.reboot.setVisibility(View.GONE);
}
activity.buttonPanel.setVisibility(View.VISIBLE);
}
}

View File

@@ -1,26 +1,27 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.container.Module;
import com.topjohnwu.magisk.container.ValueSortedMap;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import java.util.List;
public class LoadModules extends ParallelTask<Void, Void, Void> {
public LoadModules(Context context) {
super(context);
private List<String> getModList() {
String command = "ls -d " + Const.MAGISK_PATH() + "/* | grep -v lost+found";
return Shell.su(command);
}
@Override
protected Void doInBackground(Void... voids) {
MagiskManager mm = getMagiskManager();
if (mm == null) return null;
MagiskManager mm = MagiskManager.get();
mm.moduleMap = new ValueSortedMap<>();
for (String path : Utils.getModList(getShell(), MagiskManager.MAGISK_PATH)) {
Module module = new Module(getShell(), path);
for (String path : getModList()) {
Module module = new Module(path);
mm.moduleMap.put(module.getId(), module);
}
@@ -29,9 +30,7 @@ public class LoadModules extends ParallelTask<Void, Void, Void> {
@Override
protected void onPostExecute(Void v) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.moduleLoadDone.publish();
MagiskManager.get().moduleLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -4,6 +4,7 @@ import android.app.Activity;
import android.support.v7.app.AlertDialog;
import android.webkit.WebView;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.WebService;
@@ -29,7 +30,7 @@ public class MarkDownWindow extends ParallelTask<Void, Void, String> {
Node doc = parser.parse(md);
return String.format(
"<link rel='stylesheet' type='text/css' href='file:///android_asset/%s.css'/> %s",
getMagiskManager().isDarkTheme ? "dark" : "light", renderer.render(doc));
MagiskManager.get().isDarkTheme ? "dark" : "light", renderer.render(doc));
}
@Override

View File

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

View File

@@ -5,13 +5,15 @@ import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.InputStreamWrapper;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebService;
@@ -37,43 +39,38 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
private String mLink;
private File mFile;
private int progress = 0, total = -1;
private static final int UPDATE_DL_PROG = 0;
private static final int SHOW_PROCESSING = 1;
private Handler mHandler;
public ProcessRepoZip(Activity context, String link, String filename, boolean install) {
super(context);
mLink = link;
mFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager", filename);
mFile = new File(Const.EXTERNAL_PATH, filename);
mInstall = install;
mHandler = new Handler();
}
private void removeTopFolder(InputStream in, File output) throws IOException {
JarInputStream source = new JarInputStream(in);
JarOutputStream dest = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output)));
private void removeTopFolder(File input, File output) throws IOException {
JarEntry entry;
String path;
int size;
byte buffer[] = new byte[4096];
while ((entry = source.getNextJarEntry()) != null) {
// Remove the top directory from the path
path = entry.getName().substring(entry.getName().indexOf("/") + 1);
// If it's the top folder, ignore it
if (path.isEmpty()) {
continue;
}
// Don't include placeholder
if (path.equals("system/placeholder")) {
continue;
}
dest.putNextEntry(new JarEntry(path));
while((size = source.read(buffer)) != -1) {
dest.write(buffer, 0, size);
try (
JarInputStream in = new JarInputStream(new BufferedInputStream(new FileInputStream(input)));
JarOutputStream out = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(output)))
) {
String path;
while ((entry = in.getNextJarEntry()) != null) {
// Remove the top directory from the path
path = entry.getName().substring(entry.getName().indexOf("/") + 1);
// If it's the top folder, ignore it
if (path.isEmpty()) {
continue;
}
// Don't include placeholder
if (path.equals("system/placeholder")) {
continue;
}
out.putNextEntry(new JarEntry(path));
Utils.inToOut(in, out);
}
}
source.close();
dest.close();
in.close();
}
@Override
@@ -83,28 +80,11 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
progressDialog = ProgressDialog.show(activity, activity.getString(R.string.zip_download_title), activity.getString(R.string.zip_download_msg, 0));
}
@Override
protected void onProgressUpdate(Object... values) {
int mode = (int) values[0];
switch (mode) {
case UPDATE_DL_PROG:
int add = (int) values[1];
progress += add;
progressDialog.setMessage(getActivity().getString(R.string.zip_download_msg, 100 * progress / total));
break;
case SHOW_PROCESSING:
progressDialog.setTitle(R.string.zip_process_title);
progressDialog.setMessage(getActivity().getString(R.string.zip_process_msg));
break;
}
}
@Override
protected Boolean doInBackground(Void... params) {
Activity activity = getActivity();
if (activity == null) return null;
try {
// Request zip from Internet
HttpURLConnection conn;
do {
@@ -117,37 +97,37 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
break;
} while (true);
InputStream in = new BufferedInputStream(new ProgressInputStream(conn.getInputStream()));
// Temp files
File temp1 = new File(activity.getCacheDir(), "1.zip");
File temp2 = new File(temp1.getParentFile(), "2.zip");
temp1.getParentFile().mkdir();
// First remove top folder in Github source zip, Web -> temp1
removeTopFolder(in, temp1);
conn.disconnect();
publishProgress(SHOW_PROCESSING);
// Then sign the zip for the first time, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, false);
// Adjust the zip to prevent unzip issues, temp2 -> temp1
ZipUtils.zipAdjust(temp2.getPath(), temp1.getPath());
// Finally, sign the whole zip file again, temp1 -> temp2
ZipUtils.signZip(activity, temp1, temp2, true);
// Write it to the target zip, temp2 -> file
try (OutputStream out = new BufferedOutputStream(new FileOutputStream(mFile));
InputStream source = new BufferedInputStream(new FileInputStream(temp2))
// First download the zip, Web -> temp1
try (
InputStream in = new BufferedInputStream(new ProgressInputStream(conn.getInputStream()));
OutputStream out = new BufferedOutputStream(new FileOutputStream(temp1))
) {
byte[] buffer = new byte[4096];
int length;
while ((length = source.read(buffer)) > 0)
out.write(buffer, 0, length);
Utils.inToOut(in, out);
in.close();
}
conn.disconnect();
mHandler.post(() -> {
progressDialog.setTitle(R.string.zip_process_title);
progressDialog.setMessage(getActivity().getString(R.string.zip_process_msg));
});
// First remove top folder in Github source zip, temp1 -> temp2
removeTopFolder(temp1, temp2);
// Then sign the zip for the first time, temp2 -> temp1
ZipUtils.signZip(temp2, temp1, false);
// Adjust the zip to prevent unzip issues, temp1 -> temp2
ZipUtils.zipAdjust(temp1.getPath(), temp2.getPath());
// Finally, sign the whole zip file again, temp2 -> target
ZipUtils.signZip(temp2, mFile, true);
// Delete temp files
temp1.delete();
@@ -165,17 +145,17 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
Activity activity = getActivity();
if (activity == null) return;
progressDialog.dismiss();
Uri uri = Uri.fromFile(mFile);
if (result) {
Uri uri = Uri.fromFile(mFile);
if (Shell.rootAccess() && mInstall) {
Intent intent = new Intent(getActivity(), FlashActivity.class);
intent.setData(uri).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
Intent intent = new Intent(activity, FlashActivity.class);
intent.setData(uri).putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_ZIP);
activity.startActivity(intent);
} else {
Utils.showUriSnack(activity, uri);
}
} else {
Utils.getMagiskManager(activity).toast(R.string.process_error, Toast.LENGTH_LONG);
MagiskManager.toast(R.string.process_error, Toast.LENGTH_LONG);
}
super.onPostExecute(result);
}
@@ -193,10 +173,18 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
super(in);
}
private void updateDlProgress(int step) {
progress += step;
progressDialog.setMessage(getActivity().getString(R.string.zip_download_msg, (int) (100 * (double) progress / total + 0.5)));
}
@Override
public synchronized int read() throws IOException {
publishProgress(UPDATE_DL_PROG, 1);
return super.read();
int b = super.read();
if (b > 0) {
mHandler.post(() -> updateDlProgress(1));
}
return b;
}
@Override
@@ -207,7 +195,9 @@ public class ProcessRepoZip extends ParallelTask<Void, Object, Boolean> {
@Override
public synchronized int read(@NonNull byte[] b, int off, int len) throws IOException {
int read = super.read(b, off, len);
publishProgress(UPDATE_DL_PROG, read);
if (read > 0) {
mHandler.post(() -> updateDlProgress(read));
}
return read;
}
}

View File

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

View File

@@ -1,6 +1,5 @@
package com.topjohnwu.magisk.asyncs;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
@@ -8,6 +7,7 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.ReposFragment;
import com.topjohnwu.magisk.container.Repo;
import com.topjohnwu.magisk.database.RepoDatabaseHelper;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.WebService;
@@ -27,12 +27,6 @@ import java.util.Map;
public class UpdateRepos extends ParallelTask<Void, Void, Void> {
private static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&page=%d";
public static final String ETAG_KEY = "ETag";
private static final String IF_NONE_MATCH = "If-None-Match";
private static final String LINK_KEY = "Link";
private static final int CHECK_ETAG = 0;
private static final int LOAD_NEXT = 1;
private static final int LOAD_PREV = 2;
@@ -44,16 +38,16 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
private int tasks = 0;
public UpdateRepos(Context context, boolean force) {
super(context);
prefs = getMagiskManager().prefs;
repoDB = getMagiskManager().repoDB;
getMagiskManager().repoLoadDone.hasPublished = false;
public UpdateRepos(boolean force) {
MagiskManager mm = MagiskManager.get();
prefs = mm.prefs;
repoDB = mm.repoDB;
mm.repoLoadDone.hasPublished = false;
// Legacy data cleanup
File old = new File(context.getApplicationInfo().dataDir + "/shared_prefs", "RepoMap.xml");
File old = new File(mm.getApplicationInfo().dataDir + "/shared_prefs", "RepoMap.xml");
if (old.exists() || prefs.getString("repomap", null) != null) {
old.delete();
prefs.edit().remove("version").remove("repomap").remove(ETAG_KEY).apply();
prefs.edit().remove("version").remove("repomap").remove(Const.Key.ETAG_KEY).apply();
repoDB.clearRepo();
}
forceUpdate = force;
@@ -112,8 +106,8 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
if (mode == CHECK_ETAG && page < etags.size()) {
etag = etags.get(page);
}
header.put(IF_NONE_MATCH, etag);
String url = String.format(Locale.US, REPO_URL, page + 1);
header.put(Const.Key.IF_NONE_MATCH, etag);
String url = String.format(Locale.US, Const.Url.REPO_URL, page + 1);
HttpURLConnection conn = WebService.request(url, header);
try {
@@ -130,11 +124,11 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
}
// Update ETAG
etag = header.get(ETAG_KEY);
etag = header.get(Const.Key.ETAG_KEY);
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
newEtags.add(etag);
String links = header.get(LINK_KEY);
String links = header.get(Const.Key.LINK_KEY);
if (links != null) {
for (String s : links.split(", ")) {
if (mode != LOAD_PREV && s.contains("next")) {
@@ -168,7 +162,7 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
etags = new ArrayList<>(Arrays.asList(prefs.getString(ETAG_KEY, "").split(",")));
etags = new ArrayList<>(Arrays.asList(prefs.getString(Const.Key.ETAG_KEY, "").split(",")));
cached = repoDB.getRepoIDList();
if (!loadPage(0, CHECK_ETAG)) {
@@ -205,15 +199,13 @@ public class UpdateRepos extends ParallelTask<Void, Void, Void> {
if (i != 0) etagBuilder.append(",");
etagBuilder.append(newEtags.get(i));
}
prefs.edit().putString(ETAG_KEY, etagBuilder.toString()).apply();
prefs.edit().putString(Const.Key.ETAG_KEY, etagBuilder.toString()).apply();
return null;
}
@Override
protected void onPostExecute(Void v) {
MagiskManager mm = getMagiskManager();
if (mm == null) return;
mm.repoLoadDone.publish();
MagiskManager.get().repoLoadDone.publish();
super.onPostExecute(v);
}
}

View File

@@ -1,8 +1,12 @@
package com.topjohnwu.magisk.components;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
@@ -10,12 +14,14 @@ import android.view.WindowManager;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
public class Activity extends AppCompatActivity {
private Runnable permissionGrantCallback;
private AssetManager mAssetManager = null;
private Resources mResources = null;
private ActivityResultListener activityResultListener;
public Activity() {
super();
@@ -42,26 +48,29 @@ public class Activity extends AppCompatActivity {
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
MagiskManager mm = getMagiskManager();
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (permissionGrantCallback != null) {
permissionGrantCallback.run();
if (mm.permissionGrantCallback != null) {
mm.permissionGrantCallback.run();
}
}
permissionGrantCallback = null;
mm.permissionGrantCallback = null;
}
public void setPermissionGrantCallback(Runnable callback) {
permissionGrantCallback = callback;
@Override
public AssetManager getAssets() {
return mAssetManager == null ? super.getAssets() : mAssetManager;
}
@Override
public Resources getResources() {
return mResources == null ? super.getResources() : mResources;
}
public MagiskManager getMagiskManager() {
return (MagiskManager) super.getApplicationContext();
}
public Shell getShell() {
return Shell.getShell(this);
}
protected void setFloating() {
boolean isTablet = getResources().getBoolean(R.bool.isTablet);
if (isTablet) {
@@ -76,4 +85,41 @@ public class Activity extends AppCompatActivity {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (activityResultListener != null)
activityResultListener.onActivityResult(requestCode, resultCode, data);
activityResultListener = null;
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, this::onActivityResult);
}
public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) {
activityResultListener = listener;
super.startActivityForResult(intent, requestCode);
}
@Keep
public void swapResources(String dexPath) {
mAssetManager = Utils.getAssets(dexPath);
if (mAssetManager == null)
return;
Resources res = super.getResources();
mResources = new Resources(mAssetManager, res.getDisplayMetrics(), res.getConfiguration());
mResources.newTheme().setTo(super.getTheme());
}
@Keep
public void restoreResources() {
mAssetManager = null;
mResources = null;
}
public interface ActivityResultListener {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
}

View File

@@ -3,22 +3,15 @@ package com.topjohnwu.magisk.components;
import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
public class Fragment extends android.support.v4.app.Fragment {
private ActivityResultListener activityResultListener;
public MagiskManager getApplication() {
return Utils.getMagiskManager(getActivity());
}
public Shell getShell() {
return Shell.getShell(getActivity());
}
@Override
public void onResume() {
super.onResume();
@@ -36,18 +29,11 @@ public class Fragment extends android.support.v4.app.Fragment {
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (activityResultListener != null)
activityResultListener.onActivityResult(requestCode, resultCode, data);
activityResultListener = null;
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, this::onActivityResult);
}
public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) {
activityResultListener = listener;
super.startActivityForResult(intent, requestCode);
}
public interface ActivityResultListener {
void onActivityResult(int requestCode, int resultCode, Intent data);
public void startActivityForResult(Intent intent, int requestCode, Activity.ActivityResultListener listener) {
((Activity) getActivity()).startActivityForResult(intent, requestCode, listener);
}
}

View File

@@ -1,36 +0,0 @@
package com.topjohnwu.magisk.container;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class AdaptiveList<E> extends ArrayList<E> {
private Runnable callback;
private RecyclerView mView;
public AdaptiveList(RecyclerView v) {
mView = v;
}
public void updateView() {
mView.getAdapter().notifyDataSetChanged();
mView.scrollToPosition(mView.getAdapter().getItemCount() - 1);
}
public void setCallback(Runnable cb) {
callback = cb;
}
public boolean add(E e) {
boolean ret = super.add(e);
if (ret) {
if (callback == null) {
updateView();
} else {
callback.run();
}
}
return ret;
}
}

View File

@@ -10,7 +10,7 @@ import java.util.List;
public abstract class BaseModule implements Comparable<BaseModule> {
private String mId = null, mName, mVersion, mAuthor, mDescription;
private int mVersionCode = -1, templateVersion = -1;
private int mVersionCode = -1, minMagiskVersion = -1;
protected BaseModule() {}
@@ -21,7 +21,7 @@ public abstract class BaseModule implements Comparable<BaseModule> {
mVersionCode = c.getInt(c.getColumnIndex("versionCode"));
mAuthor = c.getString(c.getColumnIndex("author"));
mDescription = c.getString(c.getColumnIndex("description"));
templateVersion = c.getInt(c.getColumnIndex("template"));
minMagiskVersion = c.getInt(c.getColumnIndex("minMagisk"));
}
public ContentValues getContentValues() {
@@ -32,7 +32,7 @@ public abstract class BaseModule implements Comparable<BaseModule> {
values.put("versionCode", mVersionCode);
values.put("author", mAuthor);
values.put("description", mDescription);
values.put("template", templateVersion);
values.put("minMagisk", minMagiskVersion);
return values;
}
@@ -67,8 +67,9 @@ public abstract class BaseModule implements Comparable<BaseModule> {
case "description":
mDescription = prop[1];
break;
case "minMagisk":
case "template":
templateVersion = Integer.parseInt(prop[1]);
minMagiskVersion = Integer.parseInt(prop[1]);
break;
default:
break;
@@ -108,8 +109,8 @@ public abstract class BaseModule implements Comparable<BaseModule> {
return mVersionCode;
}
public int getTemplateVersion() {
return templateVersion;
public int getMinMagiskVersion() {
return minMagiskVersion;
}
@Override

View File

@@ -0,0 +1,22 @@
package com.topjohnwu.magisk.container;
import android.os.Handler;
import java.util.ArrayList;
public abstract class CallbackList<E> extends ArrayList<E> {
private Handler handler;
protected CallbackList() {
handler = new Handler();
}
public abstract void onAddElement(E e);
public synchronized boolean add(E e) {
boolean ret = super.add(e);
handler.post(() -> onAddElement(e));
return ret;
}
}

View File

@@ -39,7 +39,7 @@ public class InputStreamWrapper extends InputStream {
@Override
public int read(@NonNull byte[] b) throws IOException {
return read(b, 0, b.length);
return in.read(b);
}
@Override
@@ -56,4 +56,19 @@ public class InputStreamWrapper extends InputStream {
public long skip(long n) throws IOException {
return in.skip(n);
}
@Override
public int hashCode() {
return in.hashCode();
}
@Override
public boolean equals(Object obj) {
return in.equals(obj);
}
@Override
public String toString() {
return in.toString();
}
}

View File

@@ -1,6 +1,5 @@
package com.topjohnwu.magisk.container;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
public class Module extends BaseModule {
@@ -8,10 +7,10 @@ public class Module extends BaseModule {
private String mRemoveFile, mDisableFile, mUpdateFile;
private boolean mEnable, mRemove, mUpdated;
public Module(Shell shell, String path) {
public Module(String path) {
try {
parseProps(Utils.readFile(shell, path + "/module.prop"));
parseProps(Utils.readFile(path + "/module.prop"));
} catch (NumberFormatException ignored) {}
mRemoveFile = path + "/remove";
@@ -27,33 +26,33 @@ public class Module extends BaseModule {
setName(getId());
}
mEnable = !Utils.itemExist(shell, mDisableFile);
mRemove = Utils.itemExist(shell, mRemoveFile);
mUpdated = Utils.itemExist(shell, mUpdateFile);
mEnable = !Utils.itemExist(mDisableFile);
mRemove = Utils.itemExist(mRemoveFile);
mUpdated = Utils.itemExist(mUpdateFile);
}
public void createDisableFile(Shell shell) {
public void createDisableFile() {
mEnable = false;
Utils.createFile(shell, mDisableFile);
Utils.createFile(mDisableFile);
}
public void removeDisableFile(Shell shell) {
public void removeDisableFile() {
mEnable = true;
Utils.removeItem(shell, mDisableFile);
Utils.removeItem(mDisableFile);
}
public boolean isEnabled() {
return mEnable;
}
public void createRemoveFile(Shell shell) {
public void createRemoveFile() {
mRemove = true;
Utils.createFile(shell, mRemoveFile);
Utils.createFile(mRemoveFile);
}
public void deleteRemoveFile(Shell shell) {
public void deleteRemoveFile() {
mRemove = false;
Utils.removeItem(shell, mRemoveFile);
Utils.removeItem(mRemoveFile);
}
public boolean willBeRemoved() {

View File

@@ -20,12 +20,11 @@ public class Policy implements Comparable<Policy>{
public Policy(int uid, PackageManager pm) throws PackageManager.NameNotFoundException {
String[] pkgs = pm.getPackagesForUid(uid);
if (pkgs != null && pkgs.length > 0) {
this.uid = uid;
packageName = pkgs[0];
info = pm.getApplicationInfo(packageName, 0);
appName = info.loadLabel(pm).toString();
} else throw new PackageManager.NameNotFoundException();
if (pkgs == null || pkgs.length == 0) throw new PackageManager.NameNotFoundException();
this.uid = uid % 100000;
packageName = pkgs[0];
info = pm.getApplicationInfo(packageName, 0);
appName = info.loadLabel(pm).toString();
}
public Policy(Cursor c, PackageManager pm) throws PackageManager.NameNotFoundException {

View File

@@ -3,17 +3,13 @@ package com.topjohnwu.magisk.container;
import android.content.ContentValues;
import android.database.Cursor;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.WebService;
import java.util.Date;
public class Repo extends BaseModule {
public static final int MIN_TEMPLATE_VER = 4;
private static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
private static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
private String repoName;
private Date mLastUpdate;
@@ -44,7 +40,7 @@ public class Repo extends BaseModule {
if (getVersionCode() < 0) {
throw new IllegalRepoException("Repo [" + repoName + "] does not contain versionCode");
}
if (getTemplateVersion() < MIN_TEMPLATE_VER) {
if (getMinMagiskVersion() < Const.Value.MIN_MODULE_VER) {
throw new IllegalRepoException("Repo [" + repoName + "] is outdated");
}
}
@@ -58,6 +54,7 @@ public class Repo extends BaseModule {
return false;
}
@Override
public ContentValues getContentValues() {
ContentValues values = super.getContentValues();
values.put("repo_name", repoName);
@@ -70,15 +67,15 @@ public class Repo extends BaseModule {
}
public String getZipUrl() {
return String.format(ZIP_URL, repoName);
return String.format(Const.Url.ZIP_URL, repoName);
}
public String getManifestUrl() {
return String.format(FILE_URL, repoName, "module.prop");
return String.format(Const.Url.FILE_URL, repoName, "module.prop");
}
public String getDetailUrl() {
return String.format(FILE_URL, repoName, "README.md");
return String.format(Const.Url.FILE_URL, repoName, "README.md");
}
public Date getLastUpdate() {

View File

@@ -7,6 +7,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.container.Repo;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import java.util.LinkedList;
@@ -14,7 +15,7 @@ import java.util.List;
public class RepoDatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VER = 2;
private static final int DATABASE_VER = 3;
private static final String TABLE_NAME = "repos";
private SQLiteDatabase mDb;
@@ -22,12 +23,12 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
public RepoDatabaseHelper(Context context) {
super(context, "repo.db", null, DATABASE_VER);
mDb = getWritableDatabase();
mm = Utils.getMagiskManager(context);
mDb = getWritableDatabase();
// Clear bad repos
mDb.delete(TABLE_NAME, "template<?",
new String[] { String.valueOf(Repo.MIN_TEMPLATE_VER) });
mDb.delete(TABLE_NAME, "minMagisk<?",
new String[] { String.valueOf(Const.Value.MIN_MODULE_VER) });
}
@Override
@@ -37,20 +38,29 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 0) {
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
"(id TEXT, name TEXT, version TEXT, versionCode INT, " +
"author TEXT, description TEXT, repo_name TEXT, last_update INT, " +
"PRIMARY KEY(id))");
oldVersion++;
}
if (oldVersion == 1) {
db.execSQL("ALTER TABLE " + TABLE_NAME + " ADD template INT");
oldVersion++;
try {
if (oldVersion < 3) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
"(id TEXT, name TEXT, version TEXT, versionCode INT, minMagisk INT, " +
"author TEXT, description TEXT, repo_name TEXT, last_update INT, " +
"PRIMARY KEY(id))");
mm.prefs.edit().remove(Const.Key.ETAG_KEY).apply();
oldVersion = 3;
}
} catch (Exception e) {
e.printStackTrace();
// Reset database
onDowngrade(db, DATABASE_VER, 0);
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, 0, DATABASE_VER);
}
public void clearRepo() {
mDb.delete(TABLE_NAME, null, null);
}
@@ -85,7 +95,7 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
}
public Cursor getRepoCursor() {
return mDb.query(TABLE_NAME, null, "template<=?",
return mDb.query(TABLE_NAME, null, "minMagisk<=?",
new String[] { String.valueOf(mm.magiskVersionCode) },
null, null, "name COLLATE NOCASE");
}

View File

@@ -7,11 +7,15 @@ import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
@@ -23,35 +27,87 @@ import java.util.List;
public class SuDatabaseHelper extends SQLiteOpenHelper {
public static final String ROOT_ACCESS = "root_access";
public static final int ROOT_ACCESS_DISABLED = 0;
public static final int ROOT_ACCESS_APPS_ONLY = 1;
public static final int ROOT_ACCESS_ADB_ONLY = 2;
public static final int ROOT_ACCESS_APPS_AND_ADB = 3;
public static final String MULTIUSER_MODE = "multiuser_mode";
public static final int MULTIUSER_MODE_OWNER_ONLY = 0;
public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
public static final int MULTIUSER_MODE_USER = 2;
public static final String MNT_NS = "mnt_ns";
public static final int NAMESPACE_MODE_GLOBAL = 0;
public static final int NAMESPACE_MODE_REQUESTER = 1;
public static final int NAMESPACE_MODE_ISOLATE = 2;
public static final String DB_NAME = "su.db";
private static final int DATABASE_VER = 3;
private static final int DATABASE_VER = 5;
private static final String POLICY_TABLE = "policies";
private static final String LOG_TABLE = "logs";
private static final String SETTINGS_TABLE = "settings";
private static final String STRINGS_TABLE = "strings";
private MagiskManager mm;
private static String GLOBAL_DB;
private Context mContext;
private PackageManager pm;
private SQLiteDatabase mDb;
private static Context preProcess() {
Context context;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Context ce = MagiskManager.get();
context = ce.createDeviceProtectedStorageContext();
File oldDB = Utils.getDatabasePath(ce, DB_NAME);
if (oldDB.exists()) {
// Migrate DB path
context.moveDatabaseFrom(ce, DB_NAME);
}
} else {
context = MagiskManager.get();
}
GLOBAL_DB = context.getFilesDir().getParentFile().getParent() + "/magisk.db";
File db = Utils.getDatabasePath(context, DB_NAME);
if (!db.exists() && Utils.itemExist(GLOBAL_DB)) {
// Migrate global DB to ours
db.getParentFile().mkdirs();
Shell.su(
"magisk --clone-attr " + context.getFilesDir() + " " + GLOBAL_DB,
"chmod 660 " + GLOBAL_DB,
"ln " + GLOBAL_DB + " " + db
);
}
return context;
}
public static void setupSuDB() {
MagiskManager mm = MagiskManager.get();
// Check if we need to migrate suDB
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mm.magiskVersionCode >= 1410 &&
Utils.getDatabasePath(mm, SuDatabaseHelper.DB_NAME).exists()) {
mm.suDB.close();
mm.suDB = new SuDatabaseHelper();
}
File suDbFile = mm.suDB.getDbFile();
if (!Utils.itemExist(GLOBAL_DB)) {
// Hard link our DB globally
Shell.su_raw("ln " + suDbFile + " " + GLOBAL_DB);
}
// Check if we are linked globally
List<String> ret = Shell.sh("ls -l " + suDbFile);
if (Utils.isValidShellResponse(ret)) {
try {
int links = Integer.parseInt(ret.get(0).trim().split("\\s+")[1]);
if (links < 2) {
mm.suDB.close();
suDbFile.delete();
new File(suDbFile + "-journal").delete();
mm.suDB = new SuDatabaseHelper();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public SuDatabaseHelper() {
this(preProcess());
}
public SuDatabaseHelper(Context context) {
super(context, DB_NAME, null, DATABASE_VER);
mm = Utils.getMagiskManager(context);
mContext = context;
pm = context.getPackageManager();
mDb = getWritableDatabase();
cleanup();
@@ -64,37 +120,72 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 0) {
createTables(db);
oldVersion = 2;
}
if (oldVersion == 1) {
// We're dropping column app_name, rename and re-construct table
db.execSQL("ALTER TABLE " + POLICY_TABLE + " RENAME TO " + POLICY_TABLE + "_old");
// Create the new tables
createTables(db);
// Migrate old data to new tables
db.execSQL(
"INSERT INTO " + POLICY_TABLE + " SELECT " +
"uid, package_name, policy, until, logging, notification " +
"FROM " + POLICY_TABLE + "_old");
db.execSQL("DROP TABLE " + POLICY_TABLE + "_old");
File oldDB = mm.getDatabasePath("sulog.db");
if (oldDB.exists()) {
migrateLegacyLogList(oldDB, db);
mm.deleteDatabase("sulog.db");
try {
if (oldVersion == 0) {
createTables(db);
oldVersion = 3;
}
++oldVersion;
}
if (oldVersion == 2) {
db.execSQL("UPDATE " + LOG_TABLE + " SET time=time*1000");
++oldVersion;
if (oldVersion == 1) {
// We're dropping column app_name, rename and re-construct table
db.execSQL("ALTER TABLE " + POLICY_TABLE + " RENAME TO " + POLICY_TABLE + "_old");
// Create the new tables
createTables(db);
// Migrate old data to new tables
db.execSQL(
"INSERT INTO " + POLICY_TABLE + " SELECT " +
"uid, package_name, policy, until, logging, notification " +
"FROM " + POLICY_TABLE + "_old");
db.execSQL("DROP TABLE " + POLICY_TABLE + "_old");
File oldDB = Utils.getDatabasePath(MagiskManager.get(), "sulog.db");
if (oldDB.exists()) {
migrateLegacyLogList(oldDB, db);
MagiskManager.get().deleteDatabase("sulog.db");
}
++oldVersion;
}
if (oldVersion == 2) {
db.execSQL("UPDATE " + LOG_TABLE + " SET time=time*1000");
++oldVersion;
}
if (oldVersion == 3) {
db.execSQL(
"CREATE TABLE IF NOT EXISTS " + STRINGS_TABLE + " " +
"(key TEXT, value TEXT, PRIMARY KEY(key))");
++oldVersion;
}
if (oldVersion == 4) {
db.execSQL("UPDATE " + POLICY_TABLE + " SET uid=uid%100000");
++oldVersion;
}
if (!Utils.itemExist(GLOBAL_DB)) {
// Hard link our DB globally
Shell.su_raw("ln " + getDbFile() + " " + GLOBAL_DB);
}
} catch (Exception e) {
e.printStackTrace();
onDowngrade(db, DATABASE_VER, 0);
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
MagiskManager.toast(R.string.su_db_corrupt, Toast.LENGTH_LONG);
// Remove everything, we do not support downgrade
db.execSQL("DROP TABLE IF EXISTS " + POLICY_TABLE);
db.execSQL("DROP TABLE IF EXISTS " + LOG_TABLE);
db.execSQL("DROP TABLE IF EXISTS " + SETTINGS_TABLE);
db.execSQL("DROP TABLE IF EXISTS " + STRINGS_TABLE);
onUpgrade(db, 0, DATABASE_VER);
}
public File getDbFile() {
return mContext.getDatabasePath(DB_NAME);
}
private void createTables(SQLiteDatabase db) {
// Policies
db.execSQL(
@@ -121,7 +212,7 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
new String[] { String.valueOf(System.currentTimeMillis() / 1000) });
// Clear outdated logs
mDb.delete(LOG_TABLE, "time < ?", new String[] { String.valueOf(
System.currentTimeMillis() - mm.suLogTimeout * 86400000) });
System.currentTimeMillis() - MagiskManager.get().suLogTimeout * 86400000) });
}
public void deletePolicy(Policy policy) {
@@ -138,7 +229,7 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
public Policy getPolicy(int uid) {
Policy policy = null;
try (Cursor c = mDb.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
try (Cursor c = mDb.query(POLICY_TABLE, null, "uid=?", new String[] { String.valueOf(uid % 100000) }, null, null, null)) {
if (c.moveToNext()) {
policy = new Policy(c, pm);
}
@@ -177,18 +268,6 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
while (c.moveToNext()) {
try {
Policy policy = new Policy(c, pm);
// The application changed UID for some reason, check user config
if (policy.info.uid != policy.uid) {
if (mm.suReauth) {
// Reauth required, remove from DB
deletePolicy(policy);
continue;
} else {
// No reauth, update to use the new UID
policy.uid = policy.info.uid;
updatePolicy(policy);
}
}
ret.add(policy);
} catch (PackageManager.NameNotFoundException e) {
// The app no longer exist, remove from DB
@@ -262,4 +341,25 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
}
return value;
}
public void setStrings(String key, String value) {
if (value == null) {
mDb.delete(STRINGS_TABLE, "key=?", new String[] { key });
} else {
ContentValues data = new ContentValues();
data.put("key", key);
data.put("value", value);
mDb.replace(STRINGS_TABLE, null, data);
}
}
public String getStrings(String key, String defaultValue) {
String value = defaultValue;
try (Cursor c = mDb.query(STRINGS_TABLE, null, "key=?",new String[] { key }, null, null, null)) {
if (c.moveToNext()) {
value = c.getString(c.getColumnIndex("value"));
}
}
return value;
}
}

View File

@@ -19,10 +19,7 @@ public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
// There is currently no need to start an IntentService onBoot
// startIntentService(context);
}
startIntentService(context);
}
}

View File

@@ -8,6 +8,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.widget.Toast;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
@@ -34,7 +35,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
onDownloadDone(uri);
break;
default:
Utils.getMagiskManager(context).toast(R.string.download_file_error, Toast.LENGTH_LONG);
MagiskManager.toast(R.string.download_file_error, Toast.LENGTH_LONG);
break;
}
context.unregisterReceiver(this);

View File

@@ -7,7 +7,7 @@ import android.net.Uri;
import android.os.Build;
import android.support.v4.content.FileProvider;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import java.io.File;
@@ -24,7 +24,7 @@ public class ManagerUpdate extends BroadcastReceiver {
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri content = FileProvider.getUriForFile(context,
"com.topjohnwu.magisk.provider", new File(uri.getPath()));
context.getPackageName() + ".provider", new File(uri.getPath()));
install.setData(content);
context.startActivity(install);
} else {
@@ -35,8 +35,8 @@ public class ManagerUpdate extends BroadcastReceiver {
}
}
},
intent.getStringExtra(MagiskManager.INTENT_LINK),
intent.getStringExtra(Const.Key.INTENT_SET_LINK),
Utils.getLegalFilename("MagiskManager-v" +
intent.getStringExtra(MagiskManager.INTENT_VERSION) + ".apk"));
intent.getStringExtra(Const.Key.INTENT_SET_VERSION) + ".apk"));
}
}

View File

@@ -5,35 +5,26 @@ import android.content.Context;
import android.content.Intent;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
public class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
MagiskManager mm = Utils.getMagiskManager(context);
String pkg = intent.getData().getEncodedSchemeSpecificPart();
Policy policy = magiskManager.suDB.getPolicy(pkg);
if (policy == null)
return;
switch (intent.getAction()) {
case Intent.ACTION_PACKAGE_REPLACED:
// This will only work pre-O
if (magiskManager.suReauth) {
magiskManager.suDB.deletePolicy(policy);
} else {
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
// Update the UID if available
if (uid > 0) {
policy.uid = uid % 100000;
}
magiskManager.suDB.updatePolicy(policy);
if (mm.suReauth) {
mm.suDB.deletePolicy(pkg);
}
break;
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
magiskManager.suDB.deletePolicy(policy);
mm.suDB.deletePolicy(pkg);
Shell.su_raw("magiskhide --rm " + pkg);
break;
}
}

View File

@@ -0,0 +1,14 @@
package com.topjohnwu.magisk.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.topjohnwu.magisk.utils.Shell;
public class RebootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Shell.su_raw("/system/bin/reboot");
}
}

View File

@@ -3,14 +3,16 @@ package com.topjohnwu.magisk.services;
import android.app.IntentService;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.NotificationCompat;
import android.support.v4.app.NotificationCompat;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;
public class OnBootIntentService extends IntentService {
private static final int ONBOOT_NOTIFICATION_ID = 3;
public OnBootIntentService() {
super("OnBootIntentService");
}
@@ -19,16 +21,28 @@ public class OnBootIntentService extends IntentService {
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, Const.ID.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle("onBoot")
.setContentText("Running onBoot operations...");
startForeground(ONBOOT_NOTIFICATION_ID, builder.build());
startForeground(Const.ID.ONBOOT_NOTIFICATION_ID, builder.build());
}
}
@Override
protected void onHandleIntent(Intent intent) {
// Currently nothing to do
/* Pixel 2 (XL) devices will need to patch dtbo.img.
* However, that is not possible if Magisk is installed by
* patching boot image with Magisk Manager and fastboot flash
* the boot image, since at that time we do not have root.
* Check for dtbo status every boot time, and prompt user
* to reboot if dtbo wasn't patched and patched by Magisk Manager.
* */
MagiskManager mm = Utils.getMagiskManager(this);
mm.loadMagiskInfo();
if (Shell.rootAccess()) {
Utils.patchDTBO();
}
}
}

View File

@@ -10,8 +10,8 @@ public class UpdateCheckService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
Utils.getMagiskManager(this).getMagiskInfo();
new CheckUpdates(this, true)
Utils.getMagiskManager(this).loadMagiskInfo();
new CheckUpdates(true)
.setCallBack(() -> jobFinished(params, false)).exec();
return true;
}

View File

@@ -11,33 +11,28 @@ import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.container.SuLogEntry;
import com.topjohnwu.magisk.utils.Const;
import com.topjohnwu.magisk.utils.Utils;
import java.util.Date;
public class SuReceiver extends BroadcastReceiver {
public static final int NO_NOTIFICATION = 0;
public static final int TOAST = 1;
private static final int NOTIFY_NORMAL_LOG = 0;
private static final int NOTIFY_USER_TOASTS = 1;
private static final int NOTIFY_USER_TO_OWNER = 2;
@Override
public void onReceive(Context context, Intent intent) {
int fromUid, toUid, pid, mode;
String command, action;
Policy policy;
MagiskManager magiskManager = (MagiskManager) context.getApplicationContext();
MagiskManager mm = Utils.getMagiskManager(context);
if (intent == null) return;
mode = intent.getIntExtra("mode", -1);
if (mode < 0) return;
if (mode == NOTIFY_USER_TO_OWNER) {
magiskManager.toast(R.string.multiuser_hint_owner_request, Toast.LENGTH_LONG);
if (mode == Const.Value.NOTIFY_USER_TO_OWNER) {
MagiskManager.toast(R.string.multiuser_hint_owner_request, Toast.LENGTH_LONG);
return;
}
@@ -48,7 +43,7 @@ public class SuReceiver extends BroadcastReceiver {
action = intent.getStringExtra("action");
if (action == null) return;
policy = magiskManager.suDB.getPolicy(fromUid);
policy = mm.suDB.getPolicy(fromUid);
if (policy == null) {
try {
policy = new Policy(fromUid, context.getPackageManager());
@@ -74,11 +69,11 @@ public class SuReceiver extends BroadcastReceiver {
return;
}
if (policy.notification && magiskManager.suNotificationType == TOAST) {
magiskManager.toast(message, Toast.LENGTH_SHORT);
if (policy.notification && mm.suNotificationType == Const.Value.NOTIFICATION_TOAST) {
MagiskManager.toast(message, Toast.LENGTH_SHORT);
}
if (mode == NOTIFY_NORMAL_LOG && policy.logging) {
if (mode == Const.Value.NOTIFY_NORMAL_LOG && policy.logging) {
toUid = intent.getIntExtra("to.uid", -1);
if (toUid < 0) return;
pid = intent.getIntExtra("pid", -1);
@@ -89,7 +84,7 @@ public class SuReceiver extends BroadcastReceiver {
log.fromPid = pid;
log.command = command;
log.date = new Date();
magiskManager.suDB.addLog(log);
mm.suDB.addLog(log);
}
}
}

View File

@@ -22,6 +22,7 @@ import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Activity;
import com.topjohnwu.magisk.container.Policy;
import com.topjohnwu.magisk.utils.Const;
import java.io.DataInputStream;
import java.io.IOException;
@@ -31,12 +32,6 @@ import butterknife.ButterKnife;
public class SuRequestActivity extends Activity {
public static final int PROMPT = 0;
public static final int AUTO_DENY = 1;
public static final int AUTO_ALLOW = 2;
private static final int[] timeoutList = {0, -1, 10, 20, 30, 60};
@BindView(R.id.su_popup) LinearLayout suPopup;
@BindView(R.id.timeout) Spinner timeout;
@BindView(R.id.app_icon) ImageView appIcon;
@@ -48,7 +43,7 @@ public class SuRequestActivity extends Activity {
private String socketPath;
private LocalSocket socket;
private PackageManager pm;
private MagiskManager magiskManager;
private MagiskManager mm;
private boolean hasTimeout;
private Policy policy;
@@ -60,7 +55,7 @@ public class SuRequestActivity extends Activity {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
pm = getPackageManager();
magiskManager = getMagiskManager();
mm = getMagiskManager();
Intent intent = getIntent();
socketPath = intent.getStringExtra("socket");
@@ -85,14 +80,14 @@ public class SuRequestActivity extends Activity {
}
private void showRequest() {
switch (magiskManager.suResponseType) {
case AUTO_DENY:
switch (mm.suResponseType) {
case Const.Value.SU_AUTO_DENY:
handleAction(Policy.DENY, 0);
return;
case AUTO_ALLOW:
case Const.Value.SU_AUTO_ALLOW:
handleAction(Policy.ALLOW, 0);
return;
case PROMPT:
case Const.Value.SU_PROMPT:
default:
}
@@ -114,7 +109,7 @@ public class SuRequestActivity extends Activity {
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
timeout.setAdapter(adapter);
timer = new CountDownTimer(magiskManager.suRequestTimeout * 1000, 1000) {
timer = new CountDownTimer(mm.suRequestTimeout * 1000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
deny_btn.setText(getString(R.string.deny_with_str, "(" + millisUntilFinished / 1000 + ")"));
@@ -169,14 +164,14 @@ public class SuRequestActivity extends Activity {
}
void handleAction(int action) {
handleAction(action, timeoutList[timeout.getSelectedItemPosition()]);
handleAction(action, Const.Value.timeoutList[timeout.getSelectedItemPosition()]);
}
void handleAction(int action, int time) {
policy.policy = action;
if (time >= 0) {
policy.until = (time == 0) ? 0 : (System.currentTimeMillis() / 1000 + time * 60);
magiskManager.suDB.addPolicy(policy);
mm.suDB.addPolicy(policy);
}
handleAction();
}
@@ -216,7 +211,7 @@ public class SuRequestActivity extends Activity {
}
int uid = payload.getAsInteger("uid");
policy = magiskManager.suDB.getPolicy(uid);
policy = mm.suDB.getPolicy(uid);
if (policy == null) {
policy = new Policy(uid, pm);
}

View File

@@ -0,0 +1,56 @@
package com.topjohnwu.magisk.utils;
import android.support.annotation.Keep;
import com.topjohnwu.crypto.SignBoot;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class BootSigner {
@Keep
public static void main(String[] args) throws Exception {
if (args.length > 0 && "-verify".equals(args[0])) {
String certPath = "";
if (args.length >= 3 && "-certificate".equals(args[1])) {
/* args[2] is the path to a public key certificate */
certPath = args[2];
}
/* args[1] is the path to a signed boot image */
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 keyIn, certIn;
if (args.length >= 3) {
keyIn = new FileInputStream(args[1]);
certIn = new FileInputStream(args[2]);
} else {
/* Use internal test keys */
JarFile apk = new JarFile(System.getProperty("java.class.path"));
JarEntry keyEntry = apk.getJarEntry("assets/" + Const.PRIVATE_KEY_NAME);
JarEntry sigEntry = apk.getJarEntry("assets/" + Const.PUBLIC_KEY_NAME);
keyIn = apk.getInputStream(keyEntry);
certIn = apk.getInputStream(sigEntry);
}
boolean success = SignBoot.doSignature("/boot", System.in, System.out, keyIn, certIn);
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 [pk8] [x509.pem]\n" +
" sign image, key and cert are optional\n"
);
}
}
}

View File

@@ -0,0 +1,161 @@
package com.topjohnwu.magisk.utils;
import android.os.Environment;
import java.io.File;
import java.util.Arrays;
import java.util.List;
public class Const {
public static final String DEBUG_TAG = "MagiskManager";
public static final String ORIG_PKG_NAME = "com.topjohnwu.magisk";
public static final String SNET_PKG = "com.topjohnwu.snet";
public static final String MAGISKHIDE_PROP = "persist.magisk.hide";
// APK content
public static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
public static final String PRIVATE_KEY_NAME = "private.key.pk8";
public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String UTIL_FUNCTIONS= "util_functions.sh";
public static final String ANDROID_MANIFEST = "AndroidManifest.xml";
// Paths
public static final String MAGISK_DISABLE_FILE = "/cache/.disable_magisk";
public static final String TMP_FOLDER_PATH = "/dev/tmp";
public static final String MAGISK_LOG = "/cache/magisk.log";
public static final File EXTERNAL_PATH = new File(Environment.getExternalStorageDirectory(), "MagiskManager");
public static String BUSYBOX_PATH() {
if (Utils.itemExist("/sbin/.core/busybox/busybox")) {
return "/sbin/.core/busybox";
} else {
return "/dev/magisk/bin";
}
}
public static String MAGISK_PATH() {
if (Utils.itemExist("/sbin/.core/img")) {
return "/sbin/.core/img";
} else if (Utils.itemExist("/dev/magisk/img")) {
return "/dev/magisk/img";
} else {
return "/magisk";
}
}
public static String MAGISK_HOST_FILE() {
return MAGISK_PATH() + "/.core/hosts";
}
/* A list of apps that should not be shown as hide-able */
public static final List<String> SN_BLACKLIST = Arrays.asList(
"android",
"com.topjohnwu.magisk",
"com.google.android.gms"
);
/* A list of apps that already uses SafetyNet
* They DO NOT need to be added to hide list */
public static final List<String> SN_DEFAULTLIST = Arrays.asList(
"com.google.android.apps.walletnfcrel",
"com.nianticlabs.pokemongo"
);
public static class ID {
public static final int UPDATE_SERVICE_ID = 1;
public static final int FETCH_ZIP = 2;
public static final int SELECT_BOOT = 3;
// notifications
public static final int MAGISK_UPDATE_NOTIFICATION_ID = 4;
public static final int APK_UPDATE_NOTIFICATION_ID = 5;
public static final int ONBOOT_NOTIFICATION_ID = 6;
public static final int DTBO_NOTIFICATION_ID = 7;
public static final String NOTIFICATION_CHANNEL = "magisk_notification";
}
public static class Url {
public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/stable.json";
public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/update/beta.json";
public static final String SNET_URL = "https://github.com/topjohnwu/MagiskManager/raw/c0e60c41f26744a86d90dfbd368a73c847db6b70/snet.apk";
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&page=%d";
public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
public static final String DONATION_URL = "https://www.paypal.me/topjohnwu";
public static final String XDA_THREAD = "http://forum.xda-developers.com/showthread.php?t=3432382";
public static final String SOURCE_CODE_URL = "https://github.com/topjohnwu/MagiskManager";
}
public static class Key {
// su
public static final String ROOT_ACCESS = "root_access";
public static final String SU_MULTIUSER_MODE = "multiuser_mode";
public static final String SU_MNT_NS = "mnt_ns";
public static final String SU_REQUESTER = "requester";
public static final String SU_REQUEST_TIMEOUT = "su_request_timeout";
public static final String SU_AUTO_RESPONSE = "su_auto_response";
public static final String SU_NOTIFICATION = "su_notification";
public static final String SU_REAUTH = "su_reauth";
// intents
public static final String OPEN_SECTION = "section";
public static final String INTENT_SET_VERSION = "version";
public static final String INTENT_SET_LINK = "link";
public static final String INTENT_PERM = "perm_dialog";
public static final String FLASH_ACTION = "action";
public static final String FLASH_SET_BOOT = "boot";
public static final String FLASH_SET_ENC = "enc";
public static final String FLASH_SET_VERITY = "verity";
// others
public static final String UPDATE_NOTIFICATION = "notification";
public static final String UPDATE_CHANNEL = "update_channel";
public static final String CUSTOM_CHANNEL = "custom_channel";
public static final String BOOT_FORMAT = "boot_format";
public static final String SNET_VER = "snet_version";
public static final String UPDATE_SERVICE_VER = "update_service_version";
public static final String MAGISKHIDE = "magiskhide";
public static final String HOSTS = "hosts";
public static final String DISABLE = "disable";
public static final String LOCALE = "locale";
public static final String DARK_THEME = "dark_theme";
public static final String ETAG_KEY = "ETag";
public static final String LINK_KEY = "Link";
public static final String IF_NONE_MATCH = "If-None-Match";
}
public static class Value {
public static final int STABLE_CHANNEL = 0;
public static final int BETA_CHANNEL = 1;
public static final int CUSTOM_CHANNEL = 2;
public static final int ROOT_ACCESS_DISABLED = 0;
public static final int ROOT_ACCESS_APPS_ONLY = 1;
public static final int ROOT_ACCESS_ADB_ONLY = 2;
public static final int ROOT_ACCESS_APPS_AND_ADB = 3;
public static final int MULTIUSER_MODE_OWNER_ONLY = 0;
public static final int MULTIUSER_MODE_OWNER_MANAGED = 1;
public static final int MULTIUSER_MODE_USER = 2;
public static final int NAMESPACE_MODE_GLOBAL = 0;
public static final int NAMESPACE_MODE_REQUESTER = 1;
public static final int NAMESPACE_MODE_ISOLATE = 2;
public static final int NO_NOTIFICATION = 0;
public static final int NOTIFICATION_TOAST = 1;
public static final int NOTIFY_NORMAL_LOG = 0;
public static final int NOTIFY_USER_TOASTS = 1;
public static final int NOTIFY_USER_TO_OWNER = 2;
public static final int SU_PROMPT = 0;
public static final int SU_AUTO_DENY = 1;
public static final int SU_AUTO_ALLOW = 2;
public static final String FLASH_ZIP = "flash";
public static final String PATCH_BOOT = "patch";
public static final String FLASH_MAGISK = "magisk";
public static final int[] timeoutList = {0, -1, 10, 20, 30, 60};
public static final int UPDATE_SERVICE_VER = 1;
public static final int SNET_VER = 4;
public static final int MIN_MODULE_VER = 1400;
}
}

View File

@@ -2,17 +2,14 @@ package com.topjohnwu.magisk.utils;
import android.util.Log;
import com.topjohnwu.magisk.MagiskManager;
import java.util.Locale;
public class Logger {
public static final String DEBUG_TAG = "MagiskManager";
private static final boolean SHELL_LOGGING = false;
public static void debug(String line) {
Log.d(DEBUG_TAG, "DEBUG: " + line);
Log.d(Const.DEBUG_TAG, "DEBUG: " + line);
}
public static void debug(String fmt, Object... args) {
@@ -20,20 +17,20 @@ public class Logger {
}
public static void error(String line) {
Log.e(DEBUG_TAG, "ERROR: " + line);
Log.e(Const.DEBUG_TAG, "ERROR: " + line);
}
public static void error(String fmt, Object... args) {
error(String.format(Locale.US, fmt, args));
}
public static void shell(String line) {
public static void shell(boolean in, String line) {
if (SHELL_LOGGING) {
Log.d(DEBUG_TAG, "SHELL: " + line);
Log.d(Const.DEBUG_TAG, (in ? "SHELLIN : " : "SHELLOUT: ") + line);
}
}
public static void shell(String fmt, Object... args) {
shell(String.format(Locale.US, fmt, args));
public static void shell(boolean in, String fmt, Object... args) {
shell(in, String.format(Locale.US, fmt, args));
}
}

View File

@@ -1,16 +1,14 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.text.TextUtils;
import com.topjohnwu.magisk.MagiskManager;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -21,192 +19,178 @@ import java.util.List;
public class Shell {
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted
public static int rootStatus;
// -2 = not initialized; -1 = no shell; 0 = non root shell; 1 = root shell
public static int status = -2;
private final Process shellProcess;
private final DataOutputStream STDIN;
private final DataInputStream STDOUT;
private final Process process;
private final OutputStream STDIN;
private final InputStream STDOUT;
private final InputStream STDERR;
private boolean isValid;
private void testRootShell(DataOutputStream in, DataInputStream out) throws IOException {
in.write(("id\n").getBytes("UTF-8"));
in.flush();
String s = new BufferedReader(new InputStreamReader(out)).readLine();
private static void testRootShell(Shell shell) throws IOException {
shell.STDIN.write(("id\n").getBytes("UTF-8"));
shell.STDIN.flush();
String s = new BufferedReader(new InputStreamReader(shell.STDOUT)).readLine();
if (TextUtils.isEmpty(s) || !s.contains("uid=0")) {
in.close();
out.close();
shell.STDIN.close();
shell.STDIN.close();
throw new IOException();
}
}
private Shell() {
rootStatus = 1;
Process process = null;
DataOutputStream in = null;
DataInputStream out = null;
try {
// Try getting global namespace
process = Runtime.getRuntime().exec("su --mount-master");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e) {
// Feature not implemented, normal root shell
try {
process = Runtime.getRuntime().exec("su");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
testRootShell(in, out);
} catch (IOException e1) {
rootStatus = 0;
}
}
if (!rootAccess()) {
// Try to gain non-root sh
try {
process = Runtime.getRuntime().exec("sh");
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
}
isValid = true;
shellProcess = process;
STDIN = in;
STDOUT = out;
sh_raw("umask 022");
}
private Shell(String command) {
Process process;
DataOutputStream in;
DataInputStream out;
try {
process = Runtime.getRuntime().exec(command);
in = new DataOutputStream(process.getOutputStream());
out = new DataInputStream(process.getInputStream());
} catch (IOException e) {
// Nothing works....
shellProcess = null;
STDIN = null;
STDOUT = null;
isValid = false;
return;
}
isValid = true;
shellProcess = process;
STDIN = in;
STDOUT = out;
public Shell(String command) throws IOException {
process = Runtime.getRuntime().exec(command);
STDIN = process.getOutputStream();
STDOUT = process.getInputStream();
STDERR = process.getErrorStream();
}
public static Shell getShell() {
return new Shell();
}
MagiskManager mm = MagiskManager.get();
boolean needNewShell = mm.shell == null;
public static Shell getShell(String command) {
return new Shell(command);
}
public static Shell getShell(Context context) {
MagiskManager magiskManager = Utils.getMagiskManager(context);
if (magiskManager.shell == null || !magiskManager.shell.isValid) {
// Get new shell if needed
magiskManager.shell = getShell();
if (!needNewShell) {
try {
mm.shell.process.exitValue();
// The process is dead
needNewShell = true;
} catch (IllegalThreadStateException ignored) {
// This should be the expected result
}
}
return magiskManager.shell;
if (needNewShell) {
status = 1;
try {
mm.shell = new Shell("su --mount-master");
testRootShell(mm.shell);
} catch (IOException e) {
// Mount master not implemented
try {
mm.shell = new Shell("su");
testRootShell(mm.shell);
} catch (IOException e1) {
// No root exists
status = 0;
try {
mm.shell = new Shell("sh");
} catch (IOException e2) {
status = -1;
return null;
}
}
}
if (rootAccess()) {
// Load utility shell scripts
try (InputStream in = mm.getAssets().open(Const.UTIL_FUNCTIONS)) {
mm.shell.loadInputStream(in);
} catch (IOException e) {
e.printStackTrace();
}
// Root shell initialization
String bbpath = Const.BUSYBOX_PATH();
mm.shell.run_raw(false, false,
"export PATH=" + bbpath + ":$PATH",
"mount_partitions",
"find_boot_image",
"migrate_boot_backup");
}
}
return mm.shell;
}
public static boolean rootAccess() {
return rootStatus > 0;
if (status == -2) getShell();
return status > 0;
}
public void loadInputStream(InputStream in) {
try {
int read;
byte[] bytes = new byte[4096];
while ((read = in.read(bytes)) != -1) {
STDIN.write(bytes, 0, read);
public void run(Collection<String> output, Collection<String> error, String... commands) {
StreamGobbler out, err;
synchronized (process) {
try {
out = new StreamGobbler(STDOUT, output);
err = new StreamGobbler(STDERR, error);
out.start();
err.start();
run_raw(output != null, error != null, commands);
STDIN.write("echo \'-shell-done-\'\necho \'-shell-done-\' >&2\n".getBytes("UTF-8"));
STDIN.flush();
try {
out.join();
err.join();
} catch (InterruptedException ignored) {}
} catch (IOException e) {
e.printStackTrace();
process.destroy();
}
STDIN.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public List<String> sh(String... commands) {
List<String> res = new ArrayList<>();
if (!isValid) return res;
sh(res, commands);
return res;
}
public void sh_raw(String... commands) {
sh_raw(false, commands);
}
public void sh_raw(boolean stdout, String... commands) {
if (!isValid) return;
synchronized (shellProcess) {
public void run_raw(boolean stdout, boolean stderr, String... commands) {
String suffix = "\n";
if (!stderr) suffix = " 2>/dev/null" + suffix;
if (!stdout) suffix = " >/dev/null" + suffix;
synchronized (process) {
try {
for (String command : commands) {
Logger.shell(command);
STDIN.write((command + (stdout ? "\n" : " >/dev/null\n")).getBytes("UTF-8"));
Logger.shell(true, command);
STDIN.write((command + suffix).getBytes("UTF-8"));
STDIN.flush();
}
} catch (IOException e) {
e.printStackTrace();
shellProcess.destroy();
isValid = false;
process.destroy();
}
}
}
public void sh(Collection<String> output, String... commands) {
if (!isValid) return;
try {
shellProcess.exitValue();
isValid = false;
return; // The process is dead, return
} catch (IllegalThreadStateException ignored) {
// This should be the expected result
}
synchronized (shellProcess) {
StreamGobbler out = new StreamGobbler(STDOUT, output);
out.start();
sh_raw(true, commands);
sh_raw(true, "echo \'-shell-done-\'");
try { out.join(); } catch (InterruptedException ignored) {}
public void loadInputStream(InputStream in) {
synchronized (process) {
try {
Utils.inToOut(in, STDIN);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public List<String> su(String... commands) {
public static List<String> sh(String... commands) {
List<String> res = new ArrayList<>();
sh(res, commands);
return res;
}
public static void sh(Collection<String> output, String... commands) {
Shell shell = getShell();
if (shell == null)
return;
shell.run(output, null, commands);
}
public static void sh_raw(String... commands) {
Shell shell = getShell();
if (shell == null)
return;
shell.run_raw(false, false, commands);
}
public static List<String> su(String... commands) {
if (!rootAccess()) return sh();
return sh(commands);
}
public void su_raw(String... commands) {
if (!rootAccess()) return;
sh_raw(commands);
}
public void su(Collection<String> output, String... commands) {
public static void su(Collection<String> output, String... commands) {
if (!rootAccess()) return;
sh(output, commands);
}
public static void su_raw(String... commands) {
if (!rootAccess()) return;
sh_raw(commands);
}
public static abstract class AbstractList<E> extends java.util.AbstractList<E> {
@Override

View File

@@ -0,0 +1,298 @@
package com.topjohnwu.magisk.utils;
import android.Manifest;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.asyncs.RestoreStockBoot;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import com.topjohnwu.magisk.receivers.RebootReceiver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class ShowUI {
public static void magiskUpdateNotification() {
MagiskManager mm = MagiskManager.get();
Intent intent = new Intent(mm, SplashActivity.class);
intent.putExtra(Const.Key.OPEN_SECTION, "magisk");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(mm.getString(R.string.magisk_update_title))
.setContentText(mm.getString(R.string.magisk_update_available, mm.remoteMagiskVersionString))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Const.ID.MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void managerUpdateNotification() {
MagiskManager mm = MagiskManager.get();
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(Const.Key.INTENT_SET_LINK, mm.managerLink);
intent.putExtra(Const.Key.INTENT_SET_VERSION, mm.remoteManagerVersionString);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
Const.ID.APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(mm.getString(R.string.manager_update_title))
.setContentText(mm.getString(R.string.manager_download_install))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Const.ID.APK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void dtboPatchedNotification() {
MagiskManager mm = MagiskManager.get();
Intent intent = new Intent(mm, RebootReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
Const.ID.DTBO_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, Const.ID.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(mm.getString(R.string.dtbo_patched_title))
.setContentText(mm.getString(R.string.dtbo_patched_reboot))
.setVibrate(new long[]{0, 100, 100, 100})
.addAction(R.drawable.ic_refresh, mm.getString(R.string.reboot), pendingIntent);
NotificationManager notificationManager =
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Const.ID.DTBO_NOTIFICATION_ID, builder.build());
}
public static void magiskInstallDialog(Activity activity, boolean enc, boolean verity) {
MagiskManager mm = Utils.getMagiskManager(activity);
String filename = Utils.getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip");
new AlertDialogBuilder(activity)
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.magisk)))
.setMessage(mm.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
List<String> options = new ArrayList<>();
options.add(mm.getString(R.string.download_zip_only));
options.add(mm.getString(R.string.patch_boot_file));
if (Shell.rootAccess()) {
options.add(mm.getString(R.string.direct_install));
}
List<String> res = Shell.su("echo $SLOT");
if (Utils.isValidShellResponse(res)) {
options.add(mm.getString(R.string.install_second_slot));
}
char[] slot = Utils.isValidShellResponse(res) ? res.get(0).toCharArray() : null;
new AlertDialog.Builder(activity)
.setTitle(R.string.select_method)
.setItems(
options.toArray(new String [0]),
(dialog, idx) -> {
String boot;
DownloadReceiver receiver = null;
switch (idx) {
case 1:
if (mm.remoteMagiskVersionCode < 1400) {
MagiskManager.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG);
return;
}
MagiskManager.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
((com.topjohnwu.magisk.components.Activity) activity)
.startActivityForResult(intent, Const.ID.SELECT_BOOT,
(requestCode, resultCode, data) -> {
if (requestCode == Const.ID.SELECT_BOOT
&& resultCode == Activity.RESULT_OK && data != null) {
Utils.dlAndReceive(
activity,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(Const.Key.FLASH_SET_BOOT, data.getData())
.putExtra(Const.Key.FLASH_SET_ENC, enc)
.putExtra(Const.Key.FLASH_SET_VERITY, verity)
.putExtra(Const.Key.FLASH_ACTION, Const.Value.PATCH_BOOT);
mm.startActivity(intent);
}
},
mm.magiskLink,
filename
);
}
});
return;
case 0:
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Utils.showUriSnack(activity, uri);
}
};
break;
case 2:
boot = mm.bootBlock;
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.putExtra(Const.Key.FLASH_SET_BOOT, boot)
.putExtra(Const.Key.FLASH_SET_ENC, enc)
.putExtra(Const.Key.FLASH_SET_VERITY, verity)
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_MAGISK);
activity.startActivity(intent);
}
};
break;
case 3:
assert (slot != null);
// Choose the other slot
if (slot[1] == 'a') slot[1] = 'b';
else slot[1] = 'a';
// Then find the boot image again
List<String> ret = Shell.su(
"SLOT=" + String.valueOf(slot),
"find_boot_image",
"echo \"$BOOTIMAGE\""
);
boot = Utils.isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null;
Shell.su_raw("mount_partitions");
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.putExtra(Const.Key.FLASH_SET_BOOT, boot)
.putExtra(Const.Key.FLASH_SET_ENC, enc)
.putExtra(Const.Key.FLASH_SET_VERITY, verity)
.putExtra(Const.Key.FLASH_ACTION, Const.Value.FLASH_MAGISK);
activity.startActivity(intent);
}
};
default:
}
Utils.dlAndReceive(
activity,
receiver,
mm.magiskLink,
filename
);
}
).show();
})
.setNeutralButton(R.string.release_notes, (d, i) -> {
if (mm.releaseNoteLink != null) {
Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink));
openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mm.startActivity(openLink);
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
public static void managerInstallDialog(Activity activity) {
MagiskManager mm = Utils.getMagiskManager(activity);
new AlertDialogBuilder(activity)
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.app_name)))
.setMessage(mm.getString(R.string.repo_install_msg,
Utils.getLegalFilename("MagiskManager-v" +
mm.remoteManagerVersionString + ".apk")))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
Utils.runWithPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(Const.Key.INTENT_SET_LINK, mm.managerLink);
intent.putExtra(Const.Key.INTENT_SET_VERSION, mm.remoteManagerVersionString);
mm.sendBroadcast(intent);
});
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
public static void uninstallDialog(Activity activity) {
MagiskManager mm = Utils.getMagiskManager(activity);
new AlertDialogBuilder(activity)
.setTitle(R.string.uninstall_magisk_title)
.setMessage(R.string.uninstall_magisk_msg)
.setPositiveButton(R.string.complete_uninstall, (d, i) -> {
try {
InputStream in = mm.getAssets().open(Const.UNINSTALLER);
File uninstaller = new File(mm.getCacheDir(), Const.UNINSTALLER);
FileOutputStream out = new FileOutputStream(uninstaller);
byte[] bytes = new byte[1024];
int read;
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.close();
in = mm.getAssets().open(Const.UTIL_FUNCTIONS);
File utils = new File(mm.getCacheDir(), Const.UTIL_FUNCTIONS);
out = new FileOutputStream(utils);
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.close();
Shell.su(
"cat " + uninstaller + " > /cache/" + Const.UNINSTALLER,
"cat " + utils + " > /data/magisk/" + Const.UTIL_FUNCTIONS
);
MagiskManager.toast(R.string.uninstall_toast, Toast.LENGTH_LONG);
Shell.su_raw(
"sleep 5",
"pm uninstall " + mm.getApplicationInfo().packageName
);
} catch (IOException e) {
e.printStackTrace();
}
})
.setNeutralButton(R.string.restore_stock_boot, (d, i) -> {
new RestoreStockBoot().exec();
})
.setNegativeButton(R.string.no_thanks, null)
.show();
}
}

View File

@@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Collections;
/**
* Modified by topjohnwu, based on Chainfire's libsuperuser
@@ -14,8 +15,8 @@ import java.util.Collection;
public class StreamGobbler extends Thread {
private BufferedReader reader = null;
private Collection<String> writer = null;
private BufferedReader reader;
private Collection<String> writer;
/**
* <p>StreamGobbler constructor</p>
@@ -24,17 +25,17 @@ public class StreamGobbler extends Thread {
* possible to prevent a deadlock from occurring, or Process.waitFor() never
* returning (as the buffer is full, pausing the native process)</p>
*
* @param inputStream InputStream to read from
* @param outputList {@literal List<String>} to write to, or null
* @param in InputStream to read from
* @param out {@literal List<String>} to write to, or null
*/
public StreamGobbler(InputStream inputStream, Collection<String> outputList) {
public StreamGobbler(InputStream in, Collection<String> out) {
try {
while (inputStream.available() != 0) {
inputStream.skip(inputStream.available());
while (in.available() != 0) {
in.skip(in.available());
}
} catch (IOException ignored) {}
reader = new BufferedReader(new InputStreamReader(inputStream));
writer = outputList;
reader = new BufferedReader(new InputStreamReader(in));
writer = out == null ? null : Collections.synchronizedCollection(out);
}
@Override
@@ -45,8 +46,8 @@ public class StreamGobbler extends Thread {
while ((line = reader.readLine()) != null) {
if (TextUtils.equals(line, "-shell-done-"))
return;
writer.add(line);
Logger.shell(line);
if (writer != null) writer.add(line);
Logger.shell(false, line);
}
} catch (IOException e) {
// reader probably closed, expected exit condition

View File

@@ -3,49 +3,35 @@ package com.topjohnwu.magisk.utils;
import android.Manifest;
import android.app.Activity;
import android.app.DownloadManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.widget.Toast;
import com.topjohnwu.magisk.FlashActivity;
import com.topjohnwu.magisk.MagiskFragment;
import com.topjohnwu.magisk.MagiskManager;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.SplashActivity;
import com.topjohnwu.magisk.asyncs.RestoreStockBoot;
import com.topjohnwu.magisk.asyncs.UpdateRepos;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.SnackbarMaker;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.receivers.ManagerUpdate;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.SecureRandom;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -54,39 +40,28 @@ import java.util.Locale;
public class Utils {
public static final int SELECT_BOOT_IMG = 3;
public static final String UNINSTALLER = "magisk_uninstaller.sh";
public static final String UTIL_FUNCTIONS= "util_functions.sh";
public static boolean isDownloading = false;
private static final int MAGISK_UPDATE_NOTIFICATION_ID = 1;
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
public static boolean itemExist(Shell shell, String path) {
public static boolean itemExist(String path) {
String command = "[ -e " + path + " ] && echo true || echo false";
List<String> ret = shell.su(command);
List<String> ret = Shell.su(command);
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
}
public static void createFile(Shell shell, String path) {
public static void createFile(String path) {
String folder = path.substring(0, path.lastIndexOf('/'));
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null;";
shell.su_raw(command);
Shell.su_raw(command);
}
public static void removeItem(Shell shell, String path) {
public static void removeItem(String path) {
String command = "rm -rf " + path + " 2>/dev/null";
shell.su_raw(command);
Shell.su_raw(command);
}
public static List<String> getModList(Shell shell, String path) {
String command = "ls -d " + path + "/* | grep -v lost+found";
return shell.su(command);
}
public static List<String> readFile(Shell shell, String path) {
public static List<String> readFile(String path) {
String command = "cat " + path + " | sed '$a\\ ' | sed '$d'";
return shell.su(command);
return Shell.su(command);
}
public static void dlAndReceive(Context context, DownloadReceiver receiver, String link, String filename) {
@@ -94,7 +69,7 @@ public class Utils {
return;
runWithPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE, () -> {
File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename);
File file = new File(Const.EXTERNAL_PATH, filename);
if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs())
|| (file.exists() && !file.delete())) {
@@ -123,10 +98,6 @@ public class Utils {
.replace("#", "").replace("@", "").replace("*", "");
}
public static boolean lowercaseContains(CharSequence string, CharSequence nonNullLowercaseSearch) {
return !TextUtils.isEmpty(string) && string.toString().toLowerCase().contains(nonNullLowercaseSearch);
}
public static boolean isValidShellResponse(List<String> list) {
if (list != null && list.size() != 0) {
// Check if all empty
@@ -149,13 +120,6 @@ public class Utils {
return (MagiskManager) context.getApplicationContext();
}
public static void clearRepoCache(Context context) {
MagiskManager mm = getMagiskManager(context);
mm.prefs.edit().remove(UpdateRepos.ETAG_KEY).apply();
mm.repoDB.clearRepo();
mm.toast(R.string.repo_cache_cleared, Toast.LENGTH_SHORT);
}
public static String getNameFromUri(Context context, Uri uri) {
String name = null;
try (Cursor c = context.getContentResolver().query(uri, null, null, null, null)) {
@@ -181,99 +145,43 @@ public class Utils {
.setAction(R.string.ok, (v)->{}).show();
}
public static boolean checkNetworkStatus(Context context) {
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
public static boolean checkNetworkStatus() {
ConnectivityManager manager = (ConnectivityManager)
MagiskManager.get().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
public static void showMagiskUpdateNotification(MagiskManager mm) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, MagiskManager.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(mm.getString(R.string.magisk_update_title))
.setContentText(mm.getString(R.string.magisk_update_available, mm.remoteMagiskVersionString))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true);
Intent intent = new Intent(mm, SplashActivity.class);
intent.putExtra(MagiskManager.INTENT_SECTION, "magisk");
TaskStackBuilder stackBuilder = TaskStackBuilder.create(mm);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent = stackBuilder.getPendingIntent(MAGISK_UPDATE_NOTIFICATION_ID,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MAGISK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void showManagerUpdateNotification(MagiskManager mm) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mm, MagiskManager.NOTIFICATION_CHANNEL);
builder.setSmallIcon(R.drawable.ic_magisk)
.setContentTitle(mm.getString(R.string.manager_update_title))
.setContentText(mm.getString(R.string.manager_download_install))
.setVibrate(new long[]{0, 100, 100, 100})
.setAutoCancel(true);
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(MagiskManager.INTENT_LINK, mm.managerLink);
intent.putExtra(MagiskManager.INTENT_VERSION, mm.remoteManagerVersionString);
PendingIntent pendingIntent = PendingIntent.getBroadcast(mm,
APK_UPDATE_NOTIFICATION_ID, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(APK_UPDATE_NOTIFICATION_ID, builder.build());
}
public static void enableMagiskHide(Shell shell) {
shell.su_raw("magiskhide --enable");
}
public static void disableMagiskHide(Shell shell) {
shell.su_raw("magiskhide --disable");
}
public static List<String> listMagiskHide(Shell shell) {
return shell.su("magiskhide --ls");
}
public static void addMagiskHide(Shell shell, String pkg) {
shell.su_raw("magiskhide --add " + pkg);
}
public static void rmMagiskHide(Shell shell, String pkg) {
shell.su_raw("magiskhide --rm " + pkg);
}
public static String getLocaleString(Context context, Locale locale, @StringRes int id) {
public static String getLocaleString(Locale locale, @StringRes int id) {
Context context = MagiskManager.get();
Configuration config = context.getResources().getConfiguration();
config.setLocale(locale);
Context localizedContext = context.createConfigurationContext(config);
return localizedContext.getString(id);
}
public static List<Locale> getAvailableLocale(Context context) {
public static List<Locale> getAvailableLocale() {
List<Locale> locales = new ArrayList<>();
HashSet<String> set = new HashSet<>();
Locale locale;
int compareId = R.string.download_file_error;
@StringRes int compareId = R.string.download_file_error;
// Add default locale
locales.add(Locale.ENGLISH);
set.add(getLocaleString(context, Locale.ENGLISH, compareId));
set.add(getLocaleString(Locale.ENGLISH, compareId));
// Add some special locales
locales.add(Locale.TAIWAN);
set.add(getLocaleString(context, Locale.TAIWAN, compareId));
set.add(getLocaleString(Locale.TAIWAN, compareId));
locale = new Locale("pt", "BR");
locales.add(locale);
set.add(getLocaleString(context, locale, compareId));
set.add(getLocaleString(locale, compareId));
// Other locales
for (String s : context.getAssets().getLocales()) {
for (String s : MagiskManager.get().getAssets().getLocales()) {
locale = Locale.forLanguageTag(s);
if (set.add(getLocaleString(context, locale, compareId))) {
if (set.add(getLocaleString(locale, compareId))) {
locales.add(locale);
}
}
@@ -283,252 +191,63 @@ public class Utils {
return locales;
}
public static String genPackageName(String prefix, int length) {
StringBuilder builder = new StringBuilder(length);
builder.append(prefix);
length -= prefix.length();
SecureRandom random = new SecureRandom();
String base = "abcdefghijklmnopqrstuvwxyz";
String alpha = base + base.toUpperCase();
String full = alpha + "0123456789..........";
char next, prev = '\0';
for (int i = 0; i < length; ++i) {
if (prev == '.' || i == length - 1 || i == 0) {
next = alpha.charAt(random.nextInt(alpha.length()));
} else {
next = full.charAt(random.nextInt(full.length()));
}
builder.append(next);
prev = next;
}
return builder.toString();
}
public static void runWithPermission(Context context, String permission, Runnable callback) {
if (ContextCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
// Passed in context should be an activity if not granted, need to show dialog!
if (!(context instanceof com.topjohnwu.magisk.components.Activity))
return;
com.topjohnwu.magisk.components.Activity activity = (com.topjohnwu.magisk.components.Activity) context;
activity.setPermissionGrantCallback(callback);
ActivityCompat.requestPermissions(activity, new String[] { permission }, 0);
Utils.getMagiskManager(context).setPermissionGrantCallback(callback);
if (!(context instanceof com.topjohnwu.magisk.components.Activity)) {
// Start activity to show dialog
Intent intent = new Intent(context, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Const.Key.INTENT_PERM, permission);
context.startActivity(intent);
} else {
ActivityCompat.requestPermissions((Activity) context, new String[] { permission }, 0);
}
} else {
callback.run();
}
}
public static void showMagiskInstallDialog(MagiskFragment fragment, boolean enc, boolean verity) {
MagiskManager mm = getMagiskManager(fragment.getActivity());
String filename = getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip");
new AlertDialogBuilder(fragment.getActivity())
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.magisk)))
.setMessage(mm.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
List<String> options = new ArrayList<>();
options.add(mm.getString(R.string.download_zip_only));
options.add(mm.getString(R.string.patch_boot_file));
if (Shell.rootAccess()) {
options.add(mm.getString(R.string.direct_install));
}
List<String> res = Shell.getShell(mm).su("echo $SLOT");
if (isValidShellResponse(res)) {
options.add(mm.getString(R.string.install_second_slot));
}
char[] slot = isValidShellResponse(res) ? res.get(0).toCharArray() : null;
new AlertDialog.Builder(fragment.getActivity())
.setTitle(R.string.select_method)
.setItems(
options.toArray(new String [0]),
(dialog, idx) -> {
String boot;
DownloadReceiver receiver = null;
switch (idx) {
case 1:
if (mm.remoteMagiskVersionCode < 1400) {
mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG);
return;
}
mm.toast(R.string.boot_file_patch_msg, Toast.LENGTH_LONG);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
fragment.startActivityForResult(intent, SELECT_BOOT_IMG,
(requestCode, resultCode, data) -> {
if (requestCode == SELECT_BOOT_IMG
&& resultCode == Activity.RESULT_OK && data != null) {
dlAndReceive(
fragment.getActivity(),
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, data.getData())
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT);
mm.startActivity(intent);
}
},
mm.magiskLink,
filename
);
}
});
return;
case 0:
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
showUriSnack(fragment.getActivity(), uri);
}
};
break;
case 2:
boot = fragment.getSelectedBootImage();
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, boot)
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
mm.startActivity(intent);
}
};
break;
case 3:
assert (slot != null);
// Choose the other slot
if (slot[1] == 'a') slot[1] = 'b';
else slot[1] = 'a';
// Then find the boot image again
List<String> ret = Shell.getShell(mm).su(
"BOOTIMAGE=",
"SLOT=" + String.valueOf(slot),
"find_boot_image",
"echo \"$BOOTIMAGE\""
);
boot = isValidShellResponse(ret) ? ret.get(ret.size() - 1) : null;
Shell.getShell(mm).su_raw("mount_partitions");
if (boot == null)
return;
receiver = new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
Intent intent = new Intent(mm, FlashActivity.class);
intent.setData(uri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(FlashActivity.SET_BOOT, boot)
.putExtra(FlashActivity.SET_ENC, enc)
.putExtra(FlashActivity.SET_VERITY, verity)
.putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK);
mm.startActivity(intent);
}
};
default:
}
Utils.dlAndReceive(
fragment.getActivity(),
receiver,
mm.magiskLink,
filename
);
}
).show();
})
.setNeutralButton(R.string.release_notes, (d, i) -> {
if (mm.releaseNoteLink != null) {
Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink));
openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mm.startActivity(openLink);
}
})
.setNegativeButton(R.string.no_thanks, null)
.show();
public static File getDatabasePath(Context context, String dbName) {
return new File(context.getFilesDir().getParent() + "/databases", dbName);
}
public static void showManagerInstallDialog(Activity activity) {
MagiskManager mm = Utils.getMagiskManager(activity);
new AlertDialogBuilder(activity)
.setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.app_name)))
.setMessage(mm.getString(R.string.repo_install_msg,
Utils.getLegalFilename("MagiskManager-v" +
mm.remoteManagerVersionString + ".apk")))
.setCancelable(true)
.setPositiveButton(R.string.install, (d, i) -> {
Intent intent = new Intent(mm, ManagerUpdate.class);
intent.putExtra(MagiskManager.INTENT_LINK, mm.managerLink);
intent.putExtra(MagiskManager.INTENT_VERSION, mm.remoteManagerVersionString);
mm.sendBroadcast(intent);
})
.setNegativeButton(R.string.no_thanks, null)
.show();
public static AssetManager getAssets(String apk) {
try {
AssetManager asset = AssetManager.class.newInstance();
AssetManager.class.getMethod("addAssetPath", String.class).invoke(asset, apk);
return asset;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void showUninstallDialog(MagiskFragment fragment) {
MagiskManager mm = Utils.getMagiskManager(fragment.getActivity());
new AlertDialogBuilder(fragment.getActivity())
.setTitle(R.string.uninstall_magisk_title)
.setMessage(R.string.uninstall_magisk_msg)
.setPositiveButton(R.string.complete_uninstall, (d, i) -> {
try {
InputStream in = mm.getAssets().open(UNINSTALLER);
File uninstaller = new File(mm.getCacheDir(), UNINSTALLER);
FileOutputStream out = new FileOutputStream(uninstaller);
byte[] bytes = new byte[1024];
int read;
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.close();
in = mm.getAssets().open(UTIL_FUNCTIONS);
File utils = new File(mm.getCacheDir(), UTIL_FUNCTIONS);
out = new FileOutputStream(utils);
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.close();
Shell.getShell(mm).su(
"cat " + uninstaller + " > /cache/" + UNINSTALLER,
"cat " + utils + " > /data/magisk/" + UTIL_FUNCTIONS
);
mm.toast(R.string.uninstall_toast, Toast.LENGTH_LONG);
Shell.getShell(mm).su_raw(
"sleep 5",
"pm uninstall " + mm.getApplicationInfo().packageName
);
} catch (IOException e) {
e.printStackTrace();
}
})
.setNeutralButton(R.string.restore_stock_boot, (d, i) -> {
String boot = fragment.getSelectedBootImage();
if (boot == null) return;
new RestoreStockBoot(mm, boot).exec();
})
.setNegativeButton(R.string.no_thanks, null)
.show();
public static int inToOut(InputStream in, OutputStream out) throws IOException {
int read, total = 0;
byte buffer[] = new byte[4096];
while ((read = in.read(buffer)) > 0) {
out.write(buffer, 0, read);
total += read;
}
out.flush();
return total;
}
public static boolean useFDE(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& context.getSystemService(DevicePolicyManager.class).getStorageEncryptionStatus()
== DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
public static void patchDTBO() {
if (MagiskManager.get().magiskVersionCode >= 1446) {
List<String> ret = Shell.su("patch_dtbo_image && echo true || echo false");
if (Utils.isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(ret.size() - 1))) {
ShowUI.dtboPatchedNotification();
}
}
}
public static Context getEncContext(Context context) {
if (useFDE(context))
return context.createDeviceProtectedStorageContext();
else
return context;
public static int dpInPx(int dp) {
Context context = MagiskManager.get();
float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5);
}
}

View File

@@ -1,10 +1,10 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.content.res.AssetManager;
import com.topjohnwu.jarsigner.JarMap;
import com.topjohnwu.jarsigner.SignAPK;
import com.topjohnwu.crypto.JarMap;
import com.topjohnwu.crypto.SignAPK;
import com.topjohnwu.magisk.MagiskManager;
import java.io.BufferedInputStream;
import java.io.File;
@@ -15,9 +15,6 @@ import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
public class ZipUtils {
// File name in assets
private static final String PUBLIC_KEY_NAME = "public.certificate.x509.pem";
private static final String PRIVATE_KEY_NAME = "private.key.pk8";
static {
System.loadLibrary("zipadjust");
@@ -32,7 +29,6 @@ public class ZipUtils {
}
public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception {
byte data[] = new byte[4096];
try {
JarInputStream zipfile = new JarInputStream(zip);
JarEntry entry;
@@ -49,13 +45,9 @@ public class ZipUtils {
}
File dest = new File(folder, name);
dest.getParentFile().mkdirs();
FileOutputStream out = new FileOutputStream(dest);
int count;
while ((count = zipfile.read(data)) != -1) {
out.write(data, 0, count);
try (FileOutputStream out = new FileOutputStream(dest)) {
Utils.inToOut(zipfile, out);
}
out.flush();
out.close();
}
} catch(Exception e) {
e.printStackTrace();
@@ -63,18 +55,18 @@ public class ZipUtils {
}
}
public static void signZip(Context context, InputStream is, File output, boolean minSign) throws Exception {
signZip(context, new JarMap(is, false), output, minSign);
public static void signZip(InputStream is, File output, boolean minSign) throws Exception {
signZip(new JarMap(is, false), output, minSign);
}
public static void signZip(Context context, File input, File output, boolean minSign) throws Exception {
signZip(context, new JarMap(input, false), output, minSign);
public static void signZip(File input, File output, boolean minSign) throws Exception {
signZip(new JarMap(input, false), output, minSign);
}
public static void signZip(Context context, JarMap input, File output, boolean minSign) throws Exception {
AssetManager assets = context.getAssets();
public static void signZip(JarMap input, File output, boolean minSign) throws Exception {
AssetManager assets = MagiskManager.get().getAssets();
SignAPK.signZip(
assets.open(PUBLIC_KEY_NAME), assets.open(PRIVATE_KEY_NAME),
assets.open(Const.PUBLIC_KEY_NAME), assets.open(Const.PRIVATE_KEY_NAME),
input, output, minSign);
}
}

View File

@@ -4,6 +4,6 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#000"
android:fillColor="?attr/imageColorTint"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@@ -0,0 +1,85 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="3842.2534"
android:viewportHeight="3842.2534">
<group android:translateX="557.1268"
android:translateY="557.1268">
<path
android:pathData="M665,874"
android:strokeColor="#626262"
android:fillColor="#c3afe5"
android:strokeWidth="3"/>
<path
android:pathData="M1263,1244c-238.9,170.6 -487.1,149.8 -601,-221c-20.2,-65.8 -63.9,478 186,584c74.2,31.5 34.8,-78.8 167,-179c74.5,-56.5 294.6,-217.3 248,-184z"
android:fillColor="#fbbcc9"/>
<path
android:pathData="M1231,1679c-64.6,63.2 -78.9,85.3 -162,158c-119.8,104.9 -241,-42 -223,-12c107.9,179.8 389.1,481.3 376,406c-26,-148.8 -46,-225 -28,-364c12.8,-99.3 58.8,-209.3 37,-188z"
android:fillColor="#ffffff"/>
<path
android:pathData="M1538,1856c18,139 -2,215.2 -28,364c-13.1,75.3 268.1,-226.3 376,-406c18,-30 -103.2,116.9 -223,12c-83.1,-72.7 -97.4,-94.8 -162,-158c-21.8,-21.3 24.2,88.7 37,188z"
android:fillColor="#ffffff"/>
<path
android:pathData="M1322,1731"
android:fillColor="#ff6e40"/>
<path
android:pathData="M1031,1974"
android:fillColor="#3747a9"/>
<path
android:pathData="M1148,1590"
android:fillColor="#f9e398"/>
<path
android:pathData="M1195,1193c-36.8,-163.5 -422.2,-66 -524,-325c-22.7,-57.7 30.6,415.1 319,427c139.7,5.8 212.2,-69.9 205,-102z"
android:fillColor="#3747a9"/>
<path
android:pathData="M1125,798c-5.7,-129.6 -56,-350 -116,-344c-60,6 -211.7,96.5 -184,134c146.9,198.9 237.2,380.7 407,520c22.8,18.7 -101.8,-191.6 -107,-310z"
android:fillColor="#ffffff"/>
<path
android:pathData="M1294,1332l-62,-70"
android:fillColor="#e4007e"/>
<path
android:pathData="M694,1134"
android:fillColor="#e4007e"/>
<path
android:pathData="M959,906c-96.4,-102 -170,-306 -170,-306c0,0 -104.8,125.6 -97,192c10.5,89.2 104.6,173.6 230,208c134.2,36.8 291,121 291,121c-188.9,-119 -149,-104 -254,-215z"
android:fillColor="#ff6e40"/>
<path
android:pathData="M1330,1364c26,10.2 14.6,-538.8 26.6,-685.8c12,-146.9 -77.7,-237.2 -110.6,-264.2c-33,-27 -96.1,-6.4 -172,19c85.9,58.9 129,129 141,225c-18,221.9 101,330 115,706z"
android:fillColor="#ffb327"/>
<path
android:pathData="M1229.3,1429.8c-131.5,37.9 -182.5,220.5 -315.2,243.1c-27.4,4.7 -58.3,12.9 -94.3,11.2c-67.3,-3.2 -152.4,-41.3 -266.1,-202.6c-33.6,-47.7 83.4,307.1 377,311.5c215,3.2 240.1,-210.5 383.4,-217c51.7,-2.3 55,-101 55,-101c0,0 -61.8,-67.6 -139.7,-45.2z"
android:fillColor="#303030"/>
<path
android:pathData="M1507.7,1430.8c131.5,37.9 182.5,220.5 315.2,243.1c27.4,4.7 58.3,12.9 94.3,11.2c67.3,-3.2 152.4,-41.3 266.1,-202.6c33.6,-47.7 -83.4,307.1 -377,311.5c-215,3.2 -240.1,-210.5 -383.4,-217c-51.7,-2.3 -55,-101 -55,-101c0,0 61.8,-67.6 139.7,-45.2z"
android:fillColor="#303030"/>
<path
android:pathData="M761,1626"
android:fillColor="#ffb327"/>
<path
android:pathData="M1721,1428c132.2,100.2 92.8,210.5 167,179c249.9,-106 206.2,-649.8 186,-584c-113.9,370.8 -362.1,391.5 -601,221c-46.7,-33.3 173.5,127.5 248,184z"
android:fillColor="#fbbcc9"/>
<path
android:pathData="M1268.6,1665c0,0 13.5,80.5 -3,258c-20.7,222.5 84.8,576 84.8,576c0,0 143.8,-354.2 118.7,-583c-20.6,-188.1 9.3,-253.8 3,-245c-110.5,152.6 -203.5,-6 -203.5,-6z"
android:fillColor="#303030"/>
<path
android:pathData="M1746,1295c288.4,-11.9 341.7,-484.7 319,-427c-101.8,259 -487.2,161.5 -524,325c-7.2,32.1 65.3,107.8 205,102z"
android:fillColor="#3747a9"/>
<path
android:pathData="M1504,1108c169.8,-139.3 260.1,-321 407,-520c27.7,-37.5 -124,-128 -184,-134c-60,-6 -110.3,214.4 -116,344c-5.2,118.4 -129.8,328.7 -107,310z"
android:fillColor="#ffffff"/>
<path
android:pathData="M1504,1262l-62,70"
android:fillColor="#e4007e"/>
<path
android:pathData="M1523,1121c0,0 156.8,-84.3 291,-121c125.4,-34.3 219.5,-118.8 230,-208c7.8,-66.4 -97,-192 -97,-192c0,0 -73.6,204 -170,306c-105,111 -65.1,96 -254,215z"
android:fillColor="#ff6e40"/>
<path
android:pathData="M1521,658c12,-96 55.1,-166.1 141,-225c-75.9,-25.4 -139,-46 -172,-19c-33,27 -122.6,117.3 -110.6,264.2c12,146.9 0.7,695.9 26.6,685.8c14,-376 133,-484.1 115,-706z"
android:fillColor="#ffb327"/>
<path
android:pathData="M998,2109"
android:strokeColor="#626262"
android:fillColor="#00000000"
android:strokeWidth="3"/>
</group>
</vector>

View File

@@ -4,6 +4,6 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="?attr/imageColorTint"
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
</vector>

View File

@@ -4,6 +4,6 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:fillColor="?attr/imageColorTint"
android:pathData="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>

View File

@@ -3,27 +3,34 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="@android:color/black"
android:background="@color/flashing_background_color"
tools:context="com.topjohnwu.magisk.FlashActivity">
<include layout="@layout/toolbar"/>
<HorizontalScrollView
<ScrollView
android:id="@+id/scrollView"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<android.support.v7.widget.RecyclerView
android:id="@+id/flash_logs"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layoutManager="android.support.v7.widget.LinearLayoutManager">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
<TextView
android:id="@+id/txtLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:padding="8dp"
android:textColor="@android:color/white"
android:textSize="10sp" />
</HorizontalScrollView>
</HorizontalScrollView>
</ScrollView>
<LinearLayout
android:id="@+id/button_panel"
@@ -31,7 +38,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="@android:color/darker_gray"
android:background="@color/button_panel_background_color"
android:orientation="horizontal"
android:visibility="gone">
@@ -43,6 +50,14 @@
android:layout_weight="1"
android:text="@string/close" />
<Button
android:id="@+id/save_logs"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:text="@string/menuSaveLog" />
<Button
android:id="@+id/reboot"
style="?android:borderlessButtonStyle"

View File

@@ -9,26 +9,19 @@
android:id="@+id/message_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:paddingBottom="12dip"
android:paddingEnd="20dip"
android:paddingStart="20dip"
android:paddingTop="12dip">
<ScrollView
<TextView
android:id="@+id/message"
style="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:overScrollMode="ifContentScrolls"
android:paddingBottom="12dip"
android:paddingEnd="20dip"
android:paddingStart="20dip"
android:paddingTop="12dip">
<TextView
android:id="@+id/message"
style="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dip" />
</ScrollView>
android:padding="5dip" />
</LinearLayout>

View File

@@ -21,7 +21,6 @@
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="@+id/magisk_update_card"
style="?attr/cardStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -32,65 +31,54 @@
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/magisk_update_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_margin="15dp"
android:layout_toStartOf="@+id/magisk_update_status"
android:src="@drawable/ic_refresh"
android:visibility="gone" />
<ProgressBar
android:id="@+id/magisk_update_progress"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_margin="15dp"
android:layout_toStartOf="@+id/magisk_update_status" />
<TextView
android:id="@+id/magisk_update_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:minWidth="225dp"
android:padding="6dp"
android:text="@string/checking_for_updates"
android:textStyle="bold" />
</RelativeLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
style="?attr/cardStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:paddingBottom="7dp"
android:paddingTop="7dp">
<RelativeLayout
android:id="@+id/magisk_update"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp">
<ImageView
android:id="@+id/magisk_update_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/magisk_update_status"
android:visibility="gone" />
<ProgressBar
android:id="@+id/magisk_update_progress"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/magisk_update_status" />
<TextView
android:id="@+id/magisk_update_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:minWidth="225dp"
android:padding="6dp"
android:text="@string/checking_for_updates"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginTop="15dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
@@ -98,8 +86,6 @@
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
android:layout_marginStart="15dp"
android:layout_toStartOf="@+id/magisk_version" />
<TextView
@@ -116,35 +102,6 @@
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="15dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/root_status_icon"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
android:layout_marginStart="15dp"
android:layout_toStartOf="@+id/root_status" />
<TextView
android:id="@+id/root_status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:minWidth="225dp"
android:padding="6dp"
android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
@@ -178,8 +135,7 @@
android:layout_centerVertical="true"
android:layout_margin="15dp"
android:layout_toStartOf="@+id/safetyNet_status"
android:src="@drawable/ic_refresh"
android:tint="?attr/imageColorTint" />
android:src="@drawable/ic_refresh" />
<ProgressBar
android:id="@+id/safetyNet_check_progress"
@@ -267,61 +223,6 @@
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/bootimage_card"
style="?attr/cardStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="4dp"
android:layout_marginEnd="5dp"
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="15dp"
android:layout_marginTop="15dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingBottom="10dp"
android:text="@string/boot_image_title"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="25dp"
android:layout_marginStart="25dp"
android:minHeight="35dp"
android:orientation="horizontal">
<Spinner
android:id="@+id/block_spinner"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:id="@+id/detect_bootimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/detect_button"
android:visibility="gone" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/install_option_card"
style="?attr/cardStyle"
@@ -382,33 +283,36 @@
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
android:visibility="gone"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation">
<LinearLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="5dp"
android:layout_marginEnd="25dp"
android:layout_marginStart="25dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:layout_marginEnd="40dp"
android:layout_marginStart="40dp"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:layout_height="50dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginEnd="5dp"
android:layout_weight="0"
app:srcCompat="@mipmap/ic_launcher" />
app:srcCompat="@mipmap/ic_launcher_round" />
<TextView
android:id="@+id/install_text"
android:layout_width="match_parent"
android:layout_width="180dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:ems="10"
android:fontFamily="sans-serif"
android:gravity="center"
@@ -417,15 +321,7 @@
android:textSize="20sp"
android:textStyle="bold" />
<FrameLayout
android:layout_width="50dp"
android:layout_height="match_parent"
android:layout_marginStart="5dp"
android:layout_weight="0">
</FrameLayout>
</LinearLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
@@ -442,7 +338,8 @@
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="@dimen/card_corner_radius"
app:cardElevation="@dimen/card_elevation">
app:cardElevation="@dimen/card_elevation"
android:focusable="true">
<TextView
android:layout_width="match_parent"

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:textColor="@android:color/white"
android:textSize="10sp" />

View File

@@ -15,6 +15,10 @@
android:icon="@drawable/ic_superuser"
android:title="@string/superuser"
android:visible="false"/>
<item
android:id="@+id/magiskhide"
android:icon="@drawable/ic_autoroot"
android:title="@string/magiskhide" />
</group>
@@ -32,32 +36,28 @@
android:icon="@drawable/ic_cloud_download"
android:title="@string/downloads"/>
<item
android:id="@+id/magiskhide"
android:icon="@drawable/ic_autoroot"
android:title="@string/magiskhide"/>
</group>
<group
android:checkableBehavior="single"
android:id="@+id/third_group">
<item
android:id="@+id/log"
android:icon="@drawable/ic_bug_report"
android:title="@string/log"/>
</group>
<group
android:checkableBehavior="none"
android:id="@+id/third_group">
android:title="@string/log" />
<item
android:checkable="false"
android:id="@+id/settings"
android:icon="@drawable/ic_settings"
android:title="@string/settings"/>
<item
android:checkable="false"
android:id="@+id/app_about"
android:icon="@drawable/ic_info_outline"
android:title="@string/about"/>
</group>
</menu>
</menu>

View File

@@ -5,7 +5,7 @@
<item
android:id="@+id/menu_save"
android:icon="@drawable/ic_save"
android:title="@string/menuSaveToSd"
android:title="@string/menuSaveLog"
app:showAsAction="ifRoom"/>
<item

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -14,9 +14,6 @@
<string name="checking_for_updates">البحث عن تحديثات…</string>
<string name="magisk_update_available">Magisk v%1$s متاح!</string>
<string name="cannot_check_updates">لا يمكن التحقق من التحديثات، لا يوجد إنترنت؟</string>
<string name="root_error">مروت لكن لا يوجد إذن الروت، غير مسموح به؟</string>
<string name="not_rooted">غير مروت</string>
<string name="safetyNet_check_text">انقر لبدء فحص SafetyNet</string>
<string name="checking_safetyNet_status">التحقق من حالة SafetyNet…</string>
<string name="safetyNet_check_success">نجح فحص SafetyNet</string>
@@ -25,10 +22,6 @@
<string name="safetyNet_res_invalid">الاستجابة غير صالحه</string>
<!--Install Fragment-->
<string name="auto_detect">(تلقائي) %1$s</string>
<string name="cannot_auto_detect">(لا يمكن الكشف التلقائي)</string>
<string name="boot_image_title">موقع ملف الإقلاع</string>
<string name="detect_button">تحقق</string>
<string name="advanced_settings_title">إعدادات متقدمة</string>
<string name="keep_force_encryption">الحفاظ علي قوه التشفير</string>
<string name="keep_dm_verity">إبقاء dm-verity</string>
@@ -53,7 +46,6 @@
<string name="not_installed">غير مثبت</string>
<!--Log Fragment-->
<string name="menuSaveToSd">حفظ إلى بطاقة ذاكرة SD</string>
<string name="menuReload">إعادة تحميل</string>
<string name="menuClearLog">حذف السجل الآن</string>
<string name="logs_cleared">تم حذف السجل بنجاح</string>
@@ -82,8 +74,6 @@
<string name="repo_install_msg">هل تريد تثبيت %1$s ?</string>
<string name="download">التنزيل</string>
<string name="download_file_error">خطأ تنزيل الملف</string>
<string name="install_error">خطأ في التثبيت!</string>
<string name="invalid_zip">الملف المضغوط ليس إضافة Magisk!!</string>
<string name="reboot">إعادة التشغيل</string>
<string name="zip_process_msg">معالجة الملف المضغوط …</string>
<string name="downloading_toast">جاري التنزيل %1$s</string>
@@ -95,7 +85,6 @@
<string name="process_error">خطأ في العملية</string>
<string name="internal_storage">يتم تخزين الملف المضغوط في:\n[التخزين الداخلي]%1$s</string>
<string name="zip_process_title">معالجة</string>
<string name="manual_boot_image">يرجى تحديد ملف الإقلاع يدوياً!</string>
<!--Settings Activity -->
<string name="settings_general_category">عام</string>

View File

@@ -14,22 +14,15 @@
<string name="checking_for_updates">Kontrola aktualizací…</string>
<string name="magisk_update_available">Magisk v%1$s je dostupný!</string>
<string name="cannot_check_updates">Nelze zkontrolovat aktualizace. Jste připojeni k Internetu?</string>
<string name="root_error">Zařízení s rootem ale chybí root povolení, máte jej zpřístupněno?</string>
<string name="not_rooted">Nemáte root</string>
<string name="safetyNet_check_text">Kliknutím zahájíte SafetyNet kontrolu</string>
<string name="checking_safetyNet_status">Kontrola stavu SafetyNet…</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Nelze zjistit automaticky)</string>
<string name="boot_image_title">Umístění Boot Image</string>
<string name="detect_button">Zjistit</string>
<string name="advanced_settings_title">Pokročilá Nastavení</string>
<string name="keep_force_encryption">Udržet "force encryption"</string>
<string name="keep_dm_verity">Udržet dm-verity</string>
<string name="current_magisk_title">Nainstalovaná verze Magisk: %1$s</string>
<string name="install_magisk_title">Poslední verze Magisk: %1$s</string>
<string name="current_magisk_title">Nainstalovaná verze: %1$s</string>
<string name="install_magisk_title">Poslední verze: %1$s</string>
<string name="uninstall">Odinstalovat</string>
<string name="uninstall_magisk_title">Odinstalovat Magisk</string>
@@ -49,7 +42,7 @@
<string name="not_installed">Nenainstalováno</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Uložit na SD</string>
<string name="menuSaveLog">Uložit log</string>
<string name="menuReload">Aktualizovat</string>
<string name="menuClearLog">Smazat Log</string>
<string name="logs_cleared">Log byl smazán</string>
@@ -78,8 +71,6 @@
<string name="repo_install_msg">Chcete nainstalovat %1$s ?</string>
<string name="download">Stáhnout</string>
<string name="download_file_error">Chyba při Stahování souboru</string>
<string name="install_error">Chyba při Instalaci!</string>
<string name="invalid_zip">Soubor zip není Magisk Modul!!</string>
<string name="reboot">Restart</string>
<string name="zip_process_msg">Zpracování zip souboru …</string>
<string name="downloading_toast">Stahování %1$s</string>
@@ -91,7 +82,6 @@
<string name="process_error">Chyba při Zpracování</string>
<string name="internal_storage">Zip je uchován v:\n[Interním Úložišti]%1$s</string>
<string name="zip_process_title">Zpracování</string>
<string name="manual_boot_image">Ručně vyberte boot image!</string>
<!--Settings Activity -->
<string name="settings_general_category">Obecné</string>

View File

@@ -17,9 +17,6 @@
<string name="checking_for_updates">Suche nach Updates…</string>
<string name="magisk_update_available">Magisk %1$s ist verfügbar!</string>
<string name="cannot_check_updates">Updatesuche fehlgeschlagen.\nIst eine Internetverbindung verfügbar?</string>
<string name="root_error">Gerootet, aber keine root-Rechte. Wurde der root-Zugriff verweigert?</string>
<string name="not_rooted">Nicht gerootet</string>
<string name="safetyNet_check_text">SafetyNet-Status abfragen</string>
<string name="checking_safetyNet_status">Prüfe SafetyNet-Status…</string>
<string name="safetyNet_check_success">SafetyNet-Test erfolgreich</string>
@@ -28,15 +25,11 @@
<string name="safetyNet_res_invalid">Die Antwort ist ungültig</string>
<!--Install Fragment-->
<string name="auto_detect">%1$s (autom.)</string>
<string name="cannot_auto_detect">(Erkennung nicht möglich)</string>
<string name="boot_image_title">Boot-Image-Pfad</string>
<string name="detect_button">Automatisch</string>
<string name="advanced_settings_title">Erweiterte Optionen</string>
<string name="keep_force_encryption">\"force encryption\" beibehalten</string>
<string name="keep_dm_verity">\"dm-verity\"-Test beibehalten</string>
<string name="current_magisk_title">Installierte Magisk-Version: %1$s</string>
<string name="install_magisk_title">Neueste Magisk-Version: %1$s</string>
<string name="current_magisk_title">Installierte Version: %1$s</string>
<string name="install_magisk_title">Neueste Version: %1$s</string>
<string name="uninstall">Deinstallieren</string>
<string name="uninstall_magisk_title">Magisk deinstallieren</string>
@@ -56,7 +49,7 @@
<string name="not_installed">Nicht installiert</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Log auf SD-Karte speichern</string>
<string name="menuSaveLog">Log auf speichern</string>
<string name="menuReload">Log erneut laden</string>
<string name="menuClearLog">Log löschen</string>
<string name="logs_cleared">Log gelöscht</string>
@@ -85,8 +78,6 @@
<string name="repo_install_msg">Möchtest du %1$s installieren?</string>
<string name="download">Herunterladen</string>
<string name="download_file_error">Fehler beim Herunterladen der Datei</string>
<string name="install_error">Fehler bei der Installation!</string>
<string name="invalid_zip">Die Zip-Datei ist kein Magisk-Modul!</string>
<string name="reboot">Neustart</string>
<string name="downloading_toast">Herunterladen von %1$s</string>
<string name="magisk_update_title">Neues Magisk-Update verfügbar!</string>
@@ -100,7 +91,6 @@
<string name="zip_download_msg">Lade Zip-Datei herunter (%1$d%%) …</string>
<string name="zip_process_title">Verarbeite</string>
<string name="zip_process_msg">Verarbeite Zip-Datei…</string>
<string name="manual_boot_image">Bitte Boot-Image auswählen!</string>
<string name="manager_update_title">Update für Magisk Manager verfügbar!</string>
<string name="manager_download_install">Herunterladen und installieren</string>
<string name="magisk_updates">Magisk Updates</string>
@@ -122,7 +112,6 @@
<string name="settings_clear_cache_title">Repo-Cache löschen</string>
<string name="settings_clear_cache_summary">Löscht die zwischengespeicherten Informationen der Online-Repos. Erzwingt eine Aktualisierung</string>
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
<string name="settings_hide_manager_summary">Magisk Manager temporär verbergen.\nDies installiert eine neue App namens \"Unhide Magisk Manager\"</string>
<string name="language">Sprache</string>
<string name="system_default">(Systemstandard)</string>
<string name="settings_update">Update-Einstellungen</string>

View File

@@ -1,200 +1,189 @@
<resources>
<!--Welcome Activity-->
<string name="modules">Ενότητες</string>
<string name="downloads">Λήψεις</string>
<string name="superuser">Υπερχρήστης</string>
<string name="log">Aρχείο Kαταγραφής</string>
<string name="settings">Ρυθμίσεις</string>
<string name="install">Εγκατάσταση</string>
<!--Status Fragment-->
<string name="magisk_version_error">Το Magisk δεν είναι εγκατεστημένο</string>
<string name="checking_for_updates">Έλεγχος για ενημερώσεις…</string>
<string name="magisk_update_available">Το Magisk v%1$s είναι διαθέσιμο!</string>
<string name="cannot_check_updates">Αδυναμία ελέγχου για ενημερώσεις, δεν έχει internet;</string>
<string name="root_error">Υπάρχει root αλλά όχι άδεια για root, δεν επιτρέπεται;</string>
<string name="not_rooted">Δεν υπάρχει root</string>
<string name="safetyNet_check_text">Πατήστε για έλεγχο του SafetyNet</string>
<string name="checking_safetyNet_status">Έλεγχος κατάστασης SafetyNet…</string>
<string name="safetyNet_check_success">Ο Έλεγχος του SafetyNet Ήταν Επιτυχής</string>
<string name="safetyNet_network_loss">Αδυναμία σύνδεσης στο δίκτυο</string>
<string name="safetyNet_service_disconnected">Η υπηρεσία τερματίστηκε</string>
<string name="safetyNet_res_invalid">Η απόκριση είναι άκυρη</string>
<!--Install Fragment-->
<string name="auto_detect">(Αυτόματα) %1$s</string>
<string name="cannot_auto_detect">(Αδυναμία αυτόματης εύρεσης)</string>
<string name="boot_image_title">Τοποθεσία Εικόνας Boot</string>
<string name="detect_button">Εύρεση</string>
<string name="advanced_settings_title">Προηγμένες ρυθμίσεις</string>
<string name="keep_force_encryption">Διατήρηση επιβεβλημένης κρυπτογράφησης</string>
<string name="keep_dm_verity">Διατήρηση dm-verity</string>
<string name="current_magisk_title">Εγκατεστημένη έκδοση Magisk: %1$s</string>
<string name="install_magisk_title">Τελευταία έκδοση Magisk: %1$s</string>
<string name="uninstall">Απεγκατάσταση</string>
<string name="uninstall_magisk_title">Απεγκατάσταση Magisk</string>
<string name="update">Ενημέρωση %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Δεν δόθηκαν πληροφορίες)</string>
<string name="no_modules_found">Δεν βρέθηκαν ενότητες</string>
<string name="update_file_created">Η ενότητα θα ενημερωθεί στην επόμενη επανεκκίνηση</string>
<string name="remove_file_created">Η ενότητα θα αφαιρεθεί στην επόμενη επανεκκίνηση</string>
<string name="remove_file_deleted">Η ενότητα δεν θα αφαιρεθεί στην επόμενη επανεκκίνηση</string>
<string name="disable_file_created">Η ενότητα θα απενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="disable_file_removed">Η ενότητα θα ενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="author">Δημιουργήθηκε από τον/την %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
<string name="installed">Εγκαταστάθηκε</string>
<string name="not_installed">Μη εγκατεστημένη</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Αποθήκευση σε SD</string>
<string name="menuReload">Επαναφόρτωση</string>
<string name="menuClearLog">Εκκαθάριση αρχείου καταγραφής τώρα</string>
<string name="logs_cleared">Το αρχείο καταγραφής εκκαθαρίστηκε επιτυχώς</string>
<string name="log_is_empty">Το αρχείο καταγραφής είναι κενό</string>
<string name="logs_save_failed">Αποτυχία αποθήκευσης αρχείου καταγραφής στην κάρτα SD:</string>
<!--About Activity-->
<string name="about">Περί</string>
<string name="app_developers">Κύριοι προγραμματιστές</string>
<string name="app_developers_"><![CDATA[Η εφαρμογή δημιουργήθηκε από τον <a href="https://github.com/topjohnwu">topjohnwu</a> σε συνεργασία με <a href="https://github.com/d8ahazard">Digitalhigh</a> και <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Καταγραφή αλλαγών εφαρμογής</string>
<string name="translators">JpegXguy</string>
<string name="app_version">Έκδοση εφαρμογής</string>
<string name="app_source_code">Πηγαίος κώδικας</string>
<string name="donation">Δωρεά</string>
<string name="app_translators">Μεταφραστές εφαρμογής</string>
<string name="support_thread">Νήμα υποστήριξης</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Η λειτουργία αυτή δεν θα δουλέψει χωρίς την άδεια εγγραφής στον εξωτερικό χώρο αποθηκεύσης.</string>
<string name="no_thanks">Όχι ευχαριστώ</string>
<string name="yes">Ναι</string>
<string name="ok">OK</string>
<string name="close">Κλείσιμο</string>
<string name="repo_install_title">Εγκατάσταση %1$s</string>
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
<string name="download">Λήψη</string>
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
<string name="install_error">Σφάλμα εγκατάστασης!</string>
<string name="invalid_zip">Αυτό το zip δεν είναι Ενότητα Magisk!!</string>
<string name="reboot">Επανεκκίνηση</string>
<string name="zip_process_msg">Επεξεργασία αρχείου zip …</string>
<string name="downloading_toast">Κατέβασμα %1$s</string>
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
<string name="settings_reboot_toast">Επανεκκίνηση για εφαρμογή ρυθμίσεων</string>
<string name="release_notes">Σημειώσεις έκδοσης</string>
<string name="repo_cache_cleared">Η Repo cache καθαρίστηκε</string>
<string name="safetyNet_hide_notice">Αυτή η εφαρμογή χρησιμοποιεί SafetyNet\nΉδη διαχειρίζεται από το MagiskHide από προεπιλογή</string>
<string name="process_error">Σφάλμα διαδικασίας</string>
<string name="internal_storage">Το zip είναι αποθηκευμένο σε:\n[Εσωτερική μνήμη]%1$s</string>
<string name="zip_process_title">Επεξεργασία</string>
<string name="manual_boot_image">Παρακαλώ επιλέξτε χειροκίνητα μια εικόνα boot!</string>
<string name="manager_update_title">Νέα Ενημέρωση Magisk Manager Διαθέσιμη!</string>
<string name="manager_download_install">Πιέστε για λήψη και εγκατάσταση</string>
<string name="magisk_updates">Ενημερώσεις Magisk</string>
<string name="flashing">Γίνεται Flash</string>
<string name="hide_manager_toast">Κρύβοντας το Magisk Manager…</string>
<string name="hide_manager_fail_toast">Το κρύψιμο Magisk Manager απέτυχε…</string>
<string name="download_zip_only">Λήψη Zip Μόνο</string>
<string name="patch_boot_file">Εφαρμογή Patch στο Αρχείο Εικόνας Boot</string>
<string name="direct_install">Απευθείας Εγκατάσταση (Προτείνεται)</string>
<string name="select_method">Επιλογή Μεθόδου</string>
<!--Settings Activity -->
<string name="settings_general_category">Γενικά</string>
<string name="settings_dark_theme_title">Σκούρο θέμα</string>
<string name="settings_dark_theme_summary">Ενεργοποίηση σκούρου θέματος</string>
<string name="settings_notification_title">Ειδοποίηση Ενημέρωσης</string>
<string name="settings_notification_summary">Εμφάνιση ειδοποιήσεων ενημέρωσης όταν είναι διαθέσιμη νέα έκδοση</string>
<string name="settings_clear_cache_title">Εκκαθάριση προσωρινής μνήμης αποθετηρίων</string>
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για απευθείας συνδεδεμένα αποθετήρια, αναγκάζει την εφαρμογή να κάνει ανανέωση σε απευθείας σύνδεση</string>
<string name="settings_hide_manager_title">Κρύψιμο Magisk Manager</string>
<string name="settings_hide_manager_summary">Προσωρινό κρύψιμο του Magisk Manager.\nΑυτό θα εγκαταστήσει μια νέα εφαρμογή με το όνομα \"Unhide Magisk Manager\"</string>
<string name="language">Γλώσσα</string>
<string name="system_default">(Προεπιλογή Συστήματος)</string>
<string name="settings_update">Ρυθμίσεις Ενημερώσεων</string>
<string name="settings_update_channel_title">Κανάλι Ενημερώσεων</string>
<string name="settings_update_stable">Σταθερή</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Μορφή Τροποποιημένης Εικόνας Boot</string>
<string name="settings_boot_format_summary">Επιλέξτε τη μορφή της εξαγόμενης εικόνας boot μετά το patch.\nΕπιλέξτε .img για flash μέσω λειτουργίας fastboot/download· επιλέξτε .img.tar για flash μέσω ODIN.</string>
<string name="settings_core_only_title">Magisk Λειτουργία Πυρήνα Μόνο</string>
<string name="settings_core_only_summary">Ενεργοποίηση μόνο των λειτουργιών πυρήνα, καμία από τις ενότητες δεν θα ενεργοποιηθεί. Τα MagiskSU, MagiskHide, και systemless hosts θα παραμείνουν ενεργά</string>
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
<string name="settings_su_app_adb">Εφαρμογές και ADB</string>
<string name="settings_su_app">Εφαρμογές μόνο</string>
<string name="settings_su_adb">ADB μόνο</string>
<string name="settings_su_disable">Απενεργοποιημένο</string>
<string name="settings_su_request_10">10 δευτερόλεπτα</string>
<string name="settings_su_request_20">20 δευτερόλεπτα</string>
<string name="settings_su_request_30">30 δευτερόλεπτα</string>
<string name="settings_su_request_60">60 δευτερόλεπτα</string>
<string name="superuser_access">Πρόσβαση Υπερχρήστη</string>
<string name="auto_response">Αυτόματη Απόκριση</string>
<string name="request_timeout">Χρονικό όριο Αιτήματος</string>
<string name="superuser_notification">Ειδοποίηση Υπερχρήστη</string>
<string name="request_timeout_summary">%1$s δευτερόλεπτα</string>
<string name="settings_su_reauth_title">Επαναπιστοποίηση μετά από αναβάθμιση</string>
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
<string name="multiuser_mode">Λειτουργία Πολλών Χρηστών</string>
<string name="settings_owner_only">Μόνο Ιδιοκτήτης Συσκευής</string>
<string name="settings_owner_manage">Διαχειριζόμενη από τον Ιδιοκτήτη</string>
<string name="settings_user_independent">Ανεξάρτητη από τον χρήστη</string>
<string name="owner_only_summary">Μόνο ο ιδιοκτήτης έχει πρόσβαση root</string>
<string name="owner_manage_summary">Μόνο ο ιδιοκτήτης μπορεί να διαχειριστεί την πρόσβαση root και να δεχτεί προτροπές αίτημάτων</string>
<string name="user_indepenent_summary">Κάθε χρήστης έχει τους δικούς του ξεχωριστούς κανόνες root</string>
<string name="multiuser_hint_owner_request">Ένα αίτημα έχει σταλεί στον ιδιοκτήτη της συσκευής. Παρακαλώ αλλάξτε σε ιδιοκτήτη και δώστε την άδεια</string>
<string name="mount_namespace_mode">Λειτουργία προσάρτησης χώρου ονομάτων</string>
<string name="settings_ns_global">Καθολικός Χώρος Ονομάτων</string>
<string name="settings_ns_requester">Κληρονόμησε Χώρο Ονομάτων</string>
<string name="settings_ns_isolate">Απομονωμένος Χώρος Ονομάτων</string>
<string name="global_summary">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
<!--Superuser-->
<string name="su_request_title">Αίτημα υπερχρήστη</string>
<string name="deny_with_str">Άρνηση%1$s</string>
<string name="deny">Άρνηση</string>
<string name="prompt">Προτροπή</string>
<string name="grant">Απόδοχη</string>
<string name="su_warning">Δίνει πλήρη πρόσβαση στη συσκευή σας.\nΑρνηθείτε αν δεν είστε σίγουρος/η!</string>
<string name="forever">Πάντα</string>
<string name="once">Μία φορά</string>
<string name="tenmin">10 λεπτά</string>
<string name="twentymin">20 λεπτά</string>
<string name="thirtymin">30 λεπτά</string>
<string name="sixtymin">60 λεπτά</string>
<string name="su_allow_toast">Παραχωρήθηκαν δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_deny_toast">Απορρίφθηκαν τα δικαιώματα υπερχρήστη του %1$s</string>
<string name="no_apps_found">Δεν βρέθηκαν εφαρμογές</string>
<string name="su_snack_grant">Παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_snack_deny">Δεν παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_snack_notif_on">Οι ειδοποιήσεις του %1$s είναι ενεργοποιημένες</string>
<string name="su_snack_notif_off">Οι ειδοποιήσεις του %1$s είναι απενεργοποιημένες</string>
<string name="su_snack_log_on">Η καταγραφή του %1$s είναι ενεργοποιημένη</string>
<string name="su_snack_log_off">Η καταγραφή του %1$s είναι απενεργοποιημένη</string>
<string name="su_snack_revoke">Τα δικαιώματα του %1$s ανακαλούνται</string>
<string name="su_revoke_title">Ανάκληση;</string>
<string name="su_revoke_msg">Επιβεβαίωση για ανάκληση δικαιωμάτων %1$s;</string>
<string name="toast">Toast</string>
<string name="none">Κανένα</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">UID Στόχος:\u0020</string>
<string name="command">Εντολή:\u0020</string>
</resources>
<resources>
<!--Welcome Activity-->
<string name="modules">Ενότητες</string>
<string name="downloads">Λήψεις</string>
<string name="superuser">Υπερχρήστης</string>
<string name="log">Aρχείο Kαταγραφής</string>
<string name="settings">Ρυθμίσεις</string>
<string name="install">Εγκατάσταση</string>
<!--Status Fragment-->
<string name="magisk_version_error">Το Magisk δεν είναι εγκατεστημένο</string>
<string name="checking_for_updates">Έλεγχος για ενημερώσεις…</string>
<string name="magisk_update_available">Το Magisk v%1$s είναι διαθέσιμο!</string>
<string name="safetyNet_check_text">Πατήστε για έλεγχο του SafetyNet</string>
<string name="checking_safetyNet_status">Έλεγχος κατάστασης SafetyNet…</string>
<string name="safetyNet_check_success">Ο Έλεγχος του SafetyNet Ήταν Επιτυχής</string>
<string name="safetyNet_network_loss">Αδυναμία σύνδεσης στο δίκτυο</string>
<string name="safetyNet_service_disconnected">Η υπηρεσία τερματίστηκε</string>
<string name="safetyNet_res_invalid">Η απόκριση είναι άκυρη</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Προηγμένες ρυθμίσεις</string>
<string name="keep_force_encryption">Διατήρηση επιβεβλημένης κρυπτογράφησης</string>
<string name="keep_dm_verity">Διατήρηση dm-verity</string>
<string name="current_magisk_title">Εγκατεστημένη έκδοση: %1$s</string>
<string name="install_magisk_title">Τελευταία έκδοση: %1$s</string>
<string name="uninstall">Απεγκατάσταση</string>
<string name="uninstall_magisk_title">Απεγκατάσταση Magisk</string>
<string name="update">Ενημέρωση %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Δεν δόθηκαν πληροφορίες)</string>
<string name="no_modules_found">Δεν βρέθηκαν ενότητες</string>
<string name="update_file_created">Η ενότητα θα ενημερωθεί στην επόμενη επανεκκίνηση</string>
<string name="remove_file_created">Η ενότητα θα αφαιρεθεί στην επόμενη επανεκκίνηση</string>
<string name="remove_file_deleted">Η ενότητα δεν θα αφαιρεθεί στην επόμενη επανεκκίνηση</string>
<string name="disable_file_created">Η ενότητα θα απενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="disable_file_removed">Η ενότητα θα ενεργοποιηθεί στην επόμενη επανεκκίνηση</string>
<string name="author">Δημιουργήθηκε από τον/την %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Διαθέσιμη Ενημέρωση</string>
<string name="installed">Εγκαταστάθηκε</string>
<string name="not_installed">Μη εγκατεστημένη</string>
<!--Log Fragment-->
<string name="menuSaveLog">"Αποθήκευση καταγραφής "</string>
<string name="menuReload">Επαναφόρτωση</string>
<string name="menuClearLog">Εκκαθάριση αρχείου καταγραφής τώρα</string>
<string name="logs_cleared">Το αρχείο καταγραφής εκκαθαρίστηκε επιτυχώς</string>
<string name="log_is_empty">Το αρχείο καταγραφής είναι κενό</string>
<string name="logs_save_failed">Αποτυχία αποθήκευσης αρχείου καταγραφής στην κάρτα SD:</string>
<!--About Activity-->
<string name="about">Περί</string>
<string name="app_developers">Κύριοι προγραμματιστές</string>
<string name="app_developers_"><![CDATA[Η εφαρμογή δημιουργήθηκε από τον <a href="https://github.com/topjohnwu">topjohnwu</a> σε συνεργασία με <a href="https://github.com/d8ahazard">Digitalhigh</a> και <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Καταγραφή αλλαγών εφαρμογής</string>
<string name="translators">JpegXguy</string>
<string name="app_version">Έκδοση εφαρμογής</string>
<string name="app_source_code">Πηγαίος κώδικας</string>
<string name="donation">Δωρεά</string>
<string name="app_translators">Μεταφραστές εφαρμογής</string>
<string name="support_thread">Νήμα υποστήριξης</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Η λειτουργία αυτή δεν θα δουλέψει χωρίς την άδεια εγγραφής στον εξωτερικό χώρο αποθηκεύσης.</string>
<string name="no_thanks">Όχι ευχαριστώ</string>
<string name="yes">Ναι</string>
<string name="ok">OK</string>
<string name="close">Κλείσιμο</string>
<string name="repo_install_title">Εγκατάσταση %1$s</string>
<string name="repo_install_msg">Θέλετε να εγκαταστήσετε το %1$s τώρα;</string>
<string name="download">Λήψη</string>
<string name="download_file_error">Σφάλμα στη λήψη του αρχείου</string>
<string name="reboot">Επανεκκίνηση</string>
<string name="zip_process_msg">Επεξεργασία αρχείου zip …</string>
<string name="downloading_toast">Κατέβασμα %1$s</string>
<string name="magisk_update_title">Νέα Ενημέρωση Magisk Διαθέσιμη!</string>
<string name="settings_reboot_toast">Επανεκκίνηση για εφαρμογή ρυθμίσεων</string>
<string name="release_notes">Σημειώσεις έκδοσης</string>
<string name="repo_cache_cleared">Η Repo cache καθαρίστηκε</string>
<string name="safetyNet_hide_notice">Αυτή η εφαρμογή χρησιμοποιεί SafetyNet\nΉδη διαχειρίζεται από το MagiskHide από προεπιλογή</string>
<string name="process_error">Σφάλμα διαδικασίας</string>
<string name="internal_storage">Το zip είναι αποθηκευμένο σε:\n[Εσωτερική μνήμη]%1$s</string>
<string name="zip_process_title">Επεξεργασία</string>
<string name="manager_update_title">Νέα Ενημέρωση Magisk Manager Διαθέσιμη!</string>
<string name="manager_download_install">Πιέστε για λήψη και εγκατάσταση</string>
<string name="magisk_updates">Ενημερώσεις Magisk</string>
<string name="flashing">Γίνεται Flash</string>
<string name="hide_manager_toast">Κρύβοντας το Magisk Manager…</string>
<string name="hide_manager_fail_toast">Το κρύψιμο Magisk Manager απέτυχε…</string>
<string name="download_zip_only">Λήψη Zip Μόνο</string>
<string name="patch_boot_file">Εφαρμογή Patch στο Αρχείο Εικόνας Boot</string>
<string name="direct_install">Απευθείας Εγκατάσταση (Προτείνεται)</string>
<string name="select_method">Επιλογή Μεθόδου</string>
<!--Settings Activity -->
<string name="settings_general_category">Γενικά</string>
<string name="settings_dark_theme_title">Σκούρο θέμα</string>
<string name="settings_dark_theme_summary">Ενεργοποίηση σκούρου θέματος</string>
<string name="settings_notification_title">Ειδοποίηση Ενημέρωσης</string>
<string name="settings_notification_summary">Εμφάνιση ειδοποιήσεων ενημέρωσης όταν είναι διαθέσιμη νέα έκδοση</string>
<string name="settings_clear_cache_title">Εκκαθάριση προσωρινής μνήμης αποθετηρίων</string>
<string name="settings_clear_cache_summary">Καθαρίζει τις κρυφές πληροφορίες για απευθείας συνδεδεμένα αποθετήρια, αναγκάζει την εφαρμογή να κάνει ανανέωση σε απευθείας σύνδεση</string>
<string name="settings_hide_manager_title">Κρύψιμο Magisk Manager</string>
<string name="language">Γλώσσα</string>
<string name="system_default">(Προεπιλογή Συστήματος)</string>
<string name="settings_update">Ρυθμίσεις Ενημερώσεων</string>
<string name="settings_update_channel_title">Κανάλι Ενημερώσεων</string>
<string name="settings_update_stable">Σταθερή</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Μορφή Τροποποιημένης Εικόνας Boot</string>
<string name="settings_boot_format_summary">Επιλέξτε τη μορφή της εξαγόμενης εικόνας boot μετά το patch.\nΕπιλέξτε .img για flash μέσω λειτουργίας fastboot/download· επιλέξτε .img.tar για flash μέσω ODIN.</string>
<string name="settings_core_only_title">Magisk Λειτουργία Πυρήνα Μόνο</string>
<string name="settings_core_only_summary">Ενεργοποίηση μόνο των λειτουργιών πυρήνα, καμία από τις ενότητες δεν θα ενεργοποιηθεί. Τα MagiskSU, MagiskHide, και systemless hosts θα παραμείνουν ενεργά</string>
<string name="settings_magiskhide_summary">Κρύβει το Magisk από διάφορες ανιχνεύσεις</string>
<string name="settings_hosts_title">Systemless hosts</string>
<string name="settings_hosts_summary">Υποστήριξη Systemless hosts για εφαρμογές Adblock</string>
<string name="settings_su_app_adb">Εφαρμογές και ADB</string>
<string name="settings_su_app">Εφαρμογές μόνο</string>
<string name="settings_su_adb">ADB μόνο</string>
<string name="settings_su_disable">Απενεργοποιημένο</string>
<string name="settings_su_request_10">10 δευτερόλεπτα</string>
<string name="settings_su_request_20">20 δευτερόλεπτα</string>
<string name="settings_su_request_30">30 δευτερόλεπτα</string>
<string name="settings_su_request_60">60 δευτερόλεπτα</string>
<string name="superuser_access">Πρόσβαση Υπερχρήστη</string>
<string name="auto_response">Αυτόματη Απόκριση</string>
<string name="request_timeout">Χρονικό όριο Αιτήματος</string>
<string name="superuser_notification">Ειδοποίηση Υπερχρήστη</string>
<string name="request_timeout_summary">%1$s δευτερόλεπτα</string>
<string name="settings_su_reauth_title">Επαναπιστοποίηση μετά από αναβάθμιση</string>
<string name="settings_su_reauth_summary">Επαναπιστοποίηση αδειών υπερχρήστη μετά την αναβάθμιση μίας εφαρμογής</string>
<string name="multiuser_mode">Λειτουργία Πολλών Χρηστών</string>
<string name="settings_owner_only">Μόνο Ιδιοκτήτης Συσκευής</string>
<string name="settings_owner_manage">Διαχειριζόμενη από τον Ιδιοκτήτη</string>
<string name="settings_user_independent">Ανεξάρτητη από τον χρήστη</string>
<string name="owner_only_summary">Μόνο ο ιδιοκτήτης έχει πρόσβαση root</string>
<string name="owner_manage_summary">Μόνο ο ιδιοκτήτης μπορεί να διαχειριστεί την πρόσβαση root και να δεχτεί προτροπές αίτημάτων</string>
<string name="user_indepenent_summary">Κάθε χρήστης έχει τους δικούς του ξεχωριστούς κανόνες root</string>
<string name="multiuser_hint_owner_request">Ένα αίτημα έχει σταλεί στον ιδιοκτήτη της συσκευής. Παρακαλώ αλλάξτε σε ιδιοκτήτη και δώστε την άδεια</string>
<string name="mount_namespace_mode">Λειτουργία προσάρτησης χώρου ονομάτων</string>
<string name="settings_ns_global">Καθολικός Χώρος Ονομάτων</string>
<string name="settings_ns_requester">Κληρονόμησε Χώρο Ονομάτων</string>
<string name="settings_ns_isolate">Απομονωμένος Χώρος Ονομάτων</string>
<string name="global_summary">Όλες οι συνεδρίες root χρησιμοποιούν τον καθολικό χώρο oνομάτων προσάρτησης</string>
<string name="requester_summary">Οι συνεδρίες root θα κληρονομούν το χώρο ονομάτων του αιτούντα τους</string>
<string name="isolate_summary">Κάθε συνεδρία root θα έχει το δικό της απομονωμένο χώρο ονομάτων</string>
<!--Superuser-->
<string name="su_request_title">Αίτημα υπερχρήστη</string>
<string name="deny_with_str">Άρνηση%1$s</string>
<string name="deny">Άρνηση</string>
<string name="prompt">Προτροπή</string>
<string name="grant">Απόδοχη</string>
<string name="su_warning">Δίνει πλήρη πρόσβαση στη συσκευή σας.\nΑρνηθείτε αν δεν είστε σίγουρος/η!</string>
<string name="forever">Πάντα</string>
<string name="once">Μία φορά</string>
<string name="tenmin">10 λεπτά</string>
<string name="twentymin">20 λεπτά</string>
<string name="thirtymin">30 λεπτά</string>
<string name="sixtymin">60 λεπτά</string>
<string name="su_allow_toast">Παραχωρήθηκαν δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_deny_toast">Απορρίφθηκαν τα δικαιώματα υπερχρήστη του %1$s</string>
<string name="no_apps_found">Δεν βρέθηκαν εφαρμογές</string>
<string name="su_snack_grant">Παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_snack_deny">Δεν παραχορούνται δικαιώματα υπερχρήστη στο %1$s</string>
<string name="su_snack_notif_on">Οι ειδοποιήσεις του %1$s είναι ενεργοποιημένες</string>
<string name="su_snack_notif_off">Οι ειδοποιήσεις του %1$s είναι απενεργοποιημένες</string>
<string name="su_snack_log_on">Η καταγραφή του %1$s είναι ενεργοποιημένη</string>
<string name="su_snack_log_off">Η καταγραφή του %1$s είναι απενεργοποιημένη</string>
<string name="su_snack_revoke">Τα δικαιώματα του %1$s ανακαλούνται</string>
<string name="su_revoke_title">Ανάκληση;</string>
<string name="su_revoke_msg">Επιβεβαίωση για ανάκληση δικαιωμάτων %1$s;</string>
<string name="toast">Toast</string>
<string name="none">Κανένα</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">UID Στόχος:\u0020</string>
<string name="command">Εντολή:\u0020</string>
</resources>

View File

@@ -14,9 +14,7 @@
<string name="checking_for_updates">Comprobando actualizaciones…</string>
<string name="magisk_update_available">¡Disponible Magisk v%1$s!</string>
<string name="cannot_check_updates">No se pueden comprobar actualizaciones ¿No tiene internet?</string>
<string name="root_error">Rooteado pero sin permiso root, ¿No lo permitiste?</string>
<string name="not_rooted">No rooteado</string>
<string name="invalid_update_channel">Canal de actualización inválido</string>
<string name="safetyNet_check_text">Toque para empezar la comprobación de SafetyNet</string>
<string name="checking_safetyNet_status">Comprobando estado de SafetyNet…</string>
<string name="safetyNet_check_success">La comprobación de SafetyNet fue exitosa</string>
@@ -26,15 +24,11 @@
<string name="safetyNet_res_invalid">La respuesta no es válida</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(No se puede detectar automáticamente)</string>
<string name="boot_image_title">Ubicación de la imagen boot</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Ajustes avanzados</string>
<string name="keep_force_encryption">Mantener cifrado forzado</string>
<string name="keep_dm_verity">Mantener dm-verity</string>
<string name="current_magisk_title">Versión de Magisk instalada: %1$s</string>
<string name="install_magisk_title">Última versión de Magisk: %1$s</string>
<string name="current_magisk_title">Versión instalada: %1$s</string>
<string name="install_magisk_title">Última versión: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="uninstall_magisk_msg">Todos los módulos serán desactivados / eliminados. El acceso Root se eliminará y, posiblemente, encriptará los datos si los datos no están cifrados actualmente.</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
@@ -56,7 +50,7 @@
<string name="not_installed">No Instalado</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Guardar en la SD</string>
<string name="menuSaveLog">Guardar registro</string>
<string name="menuReload">Recargar</string>
<string name="menuClearLog">Limpiar registro ahora</string>
<string name="logs_cleared">Registro limpiado correctamente</string>
@@ -85,8 +79,6 @@
<string name="repo_install_msg">¿Quieres instalar %1$s ahora?</string>
<string name="download">Descargar</string>
<string name="download_file_error">Error descargando archivo</string>
<string name="install_error">¡Error en la instalación!</string>
<string name="invalid_zip">¡El zip no es un módulo Magisk!</string>
<string name="reboot">Reiniciar</string>
<string name="zip_process_msg">Procesando archivo zip …</string>
<string name="downloading_toast">Descargando %1$s</string>
@@ -100,12 +92,14 @@
<string name="zip_download_title">Descargando</string>
<string name="zip_download_msg">Descargando el archivo zip (%1$d%%) …</string>
<string name="zip_process_title">Procesando</string>
<string name="manual_boot_image">¡Selecciona manualmente una imagen boot!</string>
<string name="manager_update_title">Nueva actualización de Magisk Manager disponible!</string>
<string name="manager_download_install">Pulse para descargar e instalar</string>
<string name="dtbo_patched_title">DTBO fue parchado!</string>
<string name="dtbo_patched_reboot">Magisk Manager ha parcheado dtbo.img, por favor reinicia</string>
<string name="magisk_updates">Actualización de Magisk</string>
<string name="flashing">Flasheando</string>
<string name="hide_manager_toast">Ocultando Magisk Manager...</string>
<string name="hide_manager_toast2">Esto podría tomar un tiempo...</string>
<string name="hide_manager_fail_toast">La Ocultación de Magisk Manager ha fallado…</string>
<string name="download_zip_only">Descargar sólo el archivo ZIP</string>
<string name="patch_boot_file">Parcheo de la imagen boot</string>
@@ -120,8 +114,8 @@
<string name="restore_fail">¡El respaldo de la imagen boot Stock no existe!</string>
<string name="uninstall_toast">Desinstalación de Magisk Manager en 5 segundos, por favor después reinicie manualmente </string>
<string name="proprietary_title">Descargar Código Propietario</string>
<string name="proprietary_notice">Magisk Manager es un Software Libre por lo que no contiene el código API de SafetyNet (Código Propietario de Google).\n\n ¿Puede permitir que Magisk Manager descargue una extensión (contiene el GoogleApiClient) para los cheques de SafetyNet?</string>
<string name="proprietary_notice">Magisk Manager es un Software Libre por lo que no contiene el código API de SafetyNet (Código Propietario de Google).\n\n ¿Puede permitir que Magisk Manager descargue una extensión (contiene el GoogleApiClient) para la comprobación de SafetyNet?</string>
<string name="su_db_corrupt">La base de datos SU está dañada, se creará nueva base de datos</string>
<!--Settings Activity -->
<string name="settings_general_category">General</string>
@@ -132,13 +126,15 @@
<string name="settings_clear_cache_title">Limpiar caché del repositorio</string>
<string name="settings_clear_cache_summary">Limpiar la información en caché para los repositorios en línea, fuerza a la aplicación a actualizar en línea</string>
<string name="settings_hide_manager_title">Ocultar Magisk Manager</string>
<string name="settings_hide_manager_summary">Ocultar temporalmente Magisk Manager.\nEsto instalará una nueva aplicación llamada \"Unhide Magisk Manager\"</string>
<string name="settings_hide_manager_summary">Re-empaquetar Magisk Manager con un nombre de paquete al azar</string>
<string name="language">Idioma</string>
<string name="system_default">(Idioma del sistema)</string>
<string name="settings_update">Ajustes de Actualización</string>
<string name="settings_update_channel_title">Canal de Actualización</string>
<string name="settings_update_stable">Estable</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Personalizado</string>
<string name="settings_update_custom_msg">Insertar una URL personalizada</string>
<string name="settings_boot_format_title">Parchear imagen boot por tipo de formato</string>
<string name="settings_boot_format_summary">Seleccionar el formato de salida para parchear la imagen boot.\nEscoja .img para flashear mediante fastboot/download mode; escoja .img.tar para flashear con ODIN.</string>

View File

@@ -0,0 +1,211 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moodulid</string>
<string name="downloads">Allalaadimised</string>
<string name="superuser">Superkasutaja</string>
<string name="log">Logi</string>
<string name="settings">Seaded</string>
<string name="install">Installi</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk pole installitud</string>
<string name="checking_for_updates">Kontrollin uuendusi...</string>
<string name="magisk_update_available">Magisk v%1$s on saadaval!</string>
<string name="safetyNet_check_text">Koputa, et alustada SafetyNet\'i kontrolli</string>
<string name="checking_safetyNet_status">Kontrollin SafetyNet\'i olekut...</string>
<string name="safetyNet_check_success">SafetyNet\'i kontroll edukas</string>
<string name="safetyNet_api_error">SafetyNet\'i API viga</string>
<string name="safetyNet_network_loss">Võrguühendus puudub</string>
<string name="safetyNet_service_disconnected">Teenus on sundsuletud</string>
<string name="safetyNet_res_invalid">Vastus on sobimatu</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Täpsemad seaded</string>
<string name="keep_force_encryption">Säilita sunnitud krüpteering</string>
<string name="keep_dm_verity">Säilita dm-verity</string>
<string name="current_magisk_title">Installitud versioon: %1$s</string>
<string name="install_magisk_title">Viimane versioon: %1$s</string>
<string name="uninstall">Eemalda</string>
<string name="uninstall_magisk_title">Eemalda Magisk</string>
<string name="uninstall_magisk_msg">Kõik moodulid keelatakse/eemaldatakse. Juurkasutaja eemaldatakse ning potensiaalselt krüptitakse su andmed, kui need ei ole hetkel krüpteeritud</string>
<string name="update">Uuenda %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Info puudub)</string>
<string name="no_modules_found">Mooduleid ei leitud</string>
<string name="update_file_created">Moodul uuendatakse järgmisel taaskäivitusel</string>
<string name="remove_file_created">Moodul eemaldatakse järgmisel taaskäivitusel</string>
<string name="remove_file_deleted">Moodulit ei eemaldata järgmisel taaskäivitusel</string>
<string name="disable_file_created">Moodul keelatakse järgmisel taaskäivitusel</string>
<string name="disable_file_removed">Moodul lubatakse järgmisel taaskäivitusel</string>
<string name="author">Loodud %1$s poolt</string>
<!--Repo Fragment-->
<string name="update_available">Uuendus saadaval</string>
<string name="installed">Installitud</string>
<string name="not_installed">Pole installitud</string>
<!--Log Fragment-->
<string name="menuSaveLog">Salvesta logi</string>
<string name="menuReload">Laadi uuesti</string>
<string name="menuClearLog">Tühjenda logi nüüd</string>
<string name="logs_cleared">Logi edukalt tühjendatud</string>
<string name="log_is_empty">Logi on tühi</string>
<string name="logs_save_failed">Logi ei saanud SD-kaardile kirjutada:</string>
<!--About Activity-->
<string name="about">Teave</string>
<string name="app_developers">Põhilised arendajad</string>
<string name="app_developers_"><![CDATA[Rakendus on loodud <a href="https://github.com/topjohnwu">topjohnwu</a> poolt, koostöös <a href="https://github.com/d8ahazard">Digitalhigh</a> ja <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Rakenduse muutuste logi</string>
<string name="translators" />
<string name="app_version">Rakenduse versioon</string>
<string name="app_source_code">Lähtekood</string>
<string name="donation">Annetus</string>
<string name="app_translators">Rakenduse tõlkijad</string>
<string name="support_thread">Foorumi tugiteema</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">See funktsioon ei tööta ilma välismälule kirjutamise õiguseta.</string>
<string name="no_thanks">Tänan ei</string>
<string name="yes">Jah</string>
<string name="ok">OK</string>
<string name="close">Sulge</string>
<string name="repo_install_title">Installi %1$s</string>
<string name="repo_install_msg">Kas soovid kohe installida %1$s?</string>
<string name="download">Allalaadimine</string>
<string name="download_file_error">Faili allalaadimisel esines viga</string>
<string name="reboot">Taaskäivita</string>
<string name="downloading_toast">Laadin %1$s alla</string>
<string name="magisk_update_title">Saadaval uus Magisk\'i uuendus!</string>
<string name="settings_reboot_toast">Taaskäivita seadete rakendamiseks</string>
<string name="release_notes">Väljalaskemärkmed</string>
<string name="repo_cache_cleared">Hoidla vahemälu tühjendatud</string>
<string name="safetyNet_hide_notice">See rakendus kasutab SafetyNet\'i\n
Juba vaikimisi hallatud MagiskHide poolt</string>
<string name="process_error">Protsessi viga</string>
<string name="internal_storage">ZIP on salvestatud:\n
[Sisemälu]%1$s</string>
<string name="zip_download_title">Laadin alla</string>
<string name="zip_download_msg">Laadin ZIP-faili alla (%1$d%%)...</string>
<string name="zip_process_title">Töötlen</string>
<string name="zip_process_msg">Töötlen ZIP-faili...</string>
<string name="manager_update_title">Saadaval uus Magisk Manager uuendus!</string>
<string name="manager_download_install">Vajuta allalaadimiseks ja installimiseks</string>
<string name="magisk_updates">Magisk\'i uuendused</string>
<string name="flashing">Välgutamine</string>
<string name="hide_manager_toast">Peidan Magisk Manager\'i...</string>
<string name="hide_manager_fail_toast">Magisk Manager\'i peitmine ebaõnnestus...</string>
<string name="download_zip_only">Laadi ainult ZIP alla</string>
<string name="patch_boot_file">Paika käivituspildi fail</string>
<string name="direct_install">Otsene install (soovitatud)</string>
<string name="install_second_slot">Installi teise lahtrisse (pärast üle õhu uuendust)</string>
<string name="select_method">Vali meetod</string>
<string name="no_boot_file_patch_support">Magisk\'i sihtversioon ei toeta käivituspildi faili paikamist</string>
<string name="boot_file_patch_msg">Vali originaalne käivituspildi väljastus .img või .img.tar vormingus</string>
<string name="complete_uninstall">Täielik eemaldus</string>
<string name="restore_stock_boot">Taasta originaalne käivitus</string>
<string name="restore_done">Taastus valmis!</string>
<string name="restore_fail">Originaalne varundus puudub!</string>
<string name="uninstall_toast">Eemaldan Magisk Manager\'i 5 sekundi pärast, palun tee peale seda käsitsi taaskäivitus</string>
<string name="proprietary_title">Laadi alla suletud koodi</string>
<string name="proprietary_notice">Magisk Manager on vaba ja avatud lähtekoodiga, seega ei sisalda Google\'i suletud SafetyNet\'i API koodi.\n
\n
Kas lubad Magisk Manager\'il SafetyNet\'i kontrollide jaoks laadida alla laiendus (mis sisaldab GoogleApiClient\'i)?</string>
<!--Settings Activity -->
<string name="settings_general_category">Üldine</string>
<string name="settings_dark_theme_title">Tume teema</string>
<string name="settings_dark_theme_summary">Luba tume teema</string>
<string name="settings_notification_title">Uuendusteade</string>
<string name="settings_notification_summary">Kuva uuendusteateid, kui uus versioon on saadaval</string>
<string name="settings_clear_cache_title">Tühjenda hoidla vahemälu</string>
<string name="settings_clear_cache_summary">Tühjenda võrgus olevate hoidlate vahemälus olev teave, sunnib rakendust võrgust värskendama</string>
<string name="settings_hide_manager_title">Peida Magisk Manager</string>
<string name="language">Keel</string>
<string name="system_default">(Süsteemi vaikesäte)</string>
<string name="settings_update">Uuenda seadeid</string>
<string name="settings_update_channel_title">Uuenduskanal</string>
<string name="settings_update_stable">Stabiilne</string>
<string name="settings_update_beta">Beeta</string>
<string name="settings_boot_format_title">Paigatud käivitusväljundi vorming</string>
<string name="settings_boot_format_summary">Vali väljutatava paigatud käivituspildi vorming.\n
Vali .img, mida välgutada fastboot/allalaadimisrežiimi kaudu; vali .img.tar, mida välgutada ODIN\'i kaudu.</string>
<string name="settings_core_only_title">Magisk\'i ainult tuuma režiim</string>
<string name="settings_core_only_summary">Luba ainult põhifunktsioonid, kõiki mooduleid ei laadita. MagiskSU, MagiskHide ja süsteemivaba hosts siiski lubatakse</string>
<string name="settings_magiskhide_summary">Peida Magisk erinevate tuvastuste eest</string>
<string name="settings_hosts_title">Süsteemivaba hosts</string>
<string name="settings_hosts_summary">Süsteemivaba hosts-tugi reklaamiblokeerijatest rakendustele</string>
<string name="settings_su_app_adb">Rakendused ja ADB</string>
<string name="settings_su_app">Ainult rakendused</string>
<string name="settings_su_adb">Ainult ADB</string>
<string name="settings_su_disable">Keelatud</string>
<string name="settings_su_request_10">10 sekundit</string>
<string name="settings_su_request_20">20 sekundit</string>
<string name="settings_su_request_30">30 sekundit</string>
<string name="settings_su_request_60">60 sekundit</string>
<string name="superuser_access">Superkasutaja ligipääs</string>
<string name="auto_response">Automaatne vastus</string>
<string name="request_timeout">Taotluse ajalõpp</string>
<string name="superuser_notification">Superkasutaja teade</string>
<string name="request_timeout_summary">%1$s sekundit</string>
<string name="settings_su_reauth_title">Taas-autendi peale uuendust</string>
<string name="settings_su_reauth_summary">Taas-autendi superkasutaja õigused peale rakenduse uuendust</string>
<string name="multiuser_mode">Mitmikkasutaja režiim</string>
<string name="settings_owner_only">Ainult seadme omanik</string>
<string name="settings_owner_manage">Seadme omaniku hallatud</string>
<string name="settings_user_independent">Kasutajast sõltumatu</string>
<string name="owner_only_summary">Ainult omanikul on juurkasutaja õigused</string>
<string name="owner_manage_summary">Ainult omanik saab hallata juurkasutaja ligipääsu ja saada taotlusküsimusi</string>
<string name="user_indepenent_summary">Igal kasutajal on oma isiklikud juurkasutaja reeglid</string>
<string name="multiuser_hint_owner_request">Taotlus on saadetud seadme omanikule. Palun lülitu omanikule ja anna luba</string>
<string name="mount_namespace_mode">Nimeruumi monteerimisrežiim</string>
<string name="settings_ns_global">Globaalne nimeruum</string>
<string name="settings_ns_requester">Võta nimeruum üle</string>
<string name="settings_ns_isolate">Isoleeritud nimeruum</string>
<string name="global_summary">Kõik juurkasutaja sessioonid kasutavad globaalset monteerimise nimeruumi</string>
<string name="requester_summary">Juurkasutaja sessioonid võtavad üle selle taotleja nimeruumi</string>
<string name="isolate_summary">Iga juurkasutaja sessioon saab oma isoleeritud nimeruumi</string>
<!--Superuser-->
<string name="su_request_title">Superkasutaja taotlus</string>
<string name="deny_with_str">Keela %1$s</string>
<string name="deny">Keela</string>
<string name="prompt">Küsi</string>
<string name="grant">Luba</string>
<string name="su_warning">Annab täieliku ligipääsu sinu seadmele.\n
Keela, kui pole kindel!</string>
<string name="forever">Igavesti</string>
<string name="once">Üks kord</string>
<string name="tenmin">10 min</string>
<string name="twentymin">20 min</string>
<string name="thirtymin">30 min</string>
<string name="sixtymin">60 min</string>
<string name="su_allow_toast">%1$s anti superkasutaja õigused</string>
<string name="su_deny_toast">%1$s keelati superkasutaja õigused</string>
<string name="no_apps_found">Rakendusi ei leitud</string>
<string name="su_snack_grant">%1$s superkasutaja õigused on antud</string>
<string name="su_snack_deny">%1$s superkasutaja õigused on keelatud</string>
<string name="su_snack_notif_on">%1$s teated on lubatud</string>
<string name="su_snack_notif_off">%1$s teated on keelatud</string>
<string name="su_snack_log_on">%1$s logimine on lubatud</string>
<string name="su_snack_log_off">%1$s logimine on keelatud</string>
<string name="su_snack_revoke">%1$s õigused on eemaldatud</string>
<string name="su_revoke_title">Eemaldad?</string>
<string name="su_revoke_msg">Kinnitad %1$s õiguste eemaldamise?</string>
<string name="toast">Hüpik</string>
<string name="none">Puudub</string>
<!--Superuser logs-->
<string name="pid">PID:\\u0020</string>
<string name="target_uid">Siht-UID:\\u0020</string>
<string name="command">Käsklus:\\u0020</string>
</resources>

View File

@@ -1,5 +1,4 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Modules</string>
<string name="downloads">Téléchargements</string>
@@ -11,28 +10,22 @@
<string name="magisk_version_error">Magisk non installé</string>
<string name="checking_for_updates">Vérification de mises à jour…</string>
<string name="magisk_update_available">Magisk v%1$s disponible !</string>
<string name="cannot_check_updates">Impossible de vérifier les mises à jour, pas d\'Internet ?</string>
<string name="root_error">Rooté mais aucune permission root, non autorisée ?</string>
<string name="not_rooted">Non rooté</string>
<string name="safetyNet_check_text">Appuyer pour lancer le contrôle SafetyNet</string>
<string name="checking_safetyNet_status">Vérification de l\'état de SafetyNet…</string>
<string name="safetyNet_check_success">Contrôle SafetyNet passé avec succès</string>
<string name="safetyNet_network_loss">Connexion réseau indisponible unavailable</string>
<string name="safetyNet_api_error">Erreur d\'API SafetyNet</string>
<string name="safetyNet_network_loss">Connexion réseau indisponible</string>
<string name="safetyNet_service_disconnected">Le service a été tué</string>
<string name="safetyNet_res_invalid">La réponse est invalide</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Auto détection impossible)</string>
<string name="boot_image_title">Emplacement de l\'image Boot</string>
<string name="detect_button">Détection</string>
<string name="advanced_settings_title">Paramètres avancés</string>
<string name="keep_force_encryption">Garder le chiffrement forcé</string>
<string name="keep_dm_verity">Garder dm-verity</string>
<string name="current_magisk_title">Version Magisk Installée : %1$s</string>
<string name="install_magisk_title">Dernière Version Magisk : %1$s</string>
<string name="current_magisk_title">Version installée : %1$s</string>
<string name="install_magisk_title">Dernière Magisk : %1$s</string>
<string name="uninstall">Désinstaller</string>
<string name="uninstall_magisk_title">Désinstaller Magisk</string>
<string name="uninstall_magisk_msg">Tous les modules seront désactivés/effacés. Le root sera enlevé et vos données seront potentiellement chiffrées si ce n\'est actuellement pas le cas</string>
<string name="uninstall_magisk_msg">Tous les modules seront désactivés/effacés. Le root sera enlevé et vos données seront potentiellement chiffrées si elles ne le sont pas actuellement</string>
<string name="update">Mise à jour %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Aucune information transmise)</string>
@@ -48,7 +41,7 @@
<string name="installed">Installé</string>
<string name="not_installed">Non installé</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Enregistrer sur SD</string>
<string name="menuSaveLog">Enregistrer journal</string>
<string name="menuReload">Actualiser</string>
<string name="menuClearLog">Effacer le journal maintenant</string>
<string name="logs_cleared">Journal effacé avec succès</string>
@@ -59,12 +52,12 @@
<string name="app_developers">Principaux développeurs</string>
<string name="app_developers_"><![CDATA[Appli créée par <a href="https://github.com/topjohnwu">topjohnwu</a> en collaboration avec <a href="https://github.com/d8ahazard">Digitalhigh</a> et <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Modifications de l\'application</string>
<string name="translators" />
<string name="translators">Primokorn, Naboleo, tonymanou</string>
<string name="app_version">Version de l\'application</string>
<string name="app_source_code">Code source</string>
<string name="donation">Dons</string>
<string name="app_translators">Traducteurs de l\'application</string>
<string name="support_thread">Sujet pour support</string>
<string name="support_thread">Fil de discussion pour support</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Cette fonctionnalité ne marchera pas sans la permission d\'écriture sur le stockage externe.</string>
<string name="no_thanks">Non merci</string>
@@ -72,11 +65,9 @@
<string name="ok">OK</string>
<string name="close">Fermer</string>
<string name="repo_install_title">Installer %1$s</string>
<string name="repo_install_msg">Voulez-vous installer %1$s ?</string>
<string name="repo_install_msg">Voulez-vous installer %1$s maintenant ?</string>
<string name="download">Télécharger</string>
<string name="download_file_error">Erreur de téléchargement du fichier</string>
<string name="install_error">Échec de l\'installation !</string>
<string name="invalid_zip">Ce zip n\'est pas un Module Magisk !!</string>
<string name="reboot">Redémarrer</string>
<string name="zip_process_msg">Exécution du fichier zip…</string>
<string name="downloading_toast">Téléchargement %1$s</string>
@@ -85,27 +76,31 @@
<string name="release_notes">Notes de version</string>
<string name="repo_cache_cleared">Cache du dépôt effacé</string>
<string name="safetyNet_hide_notice">Cette application utilise SafetyNet\nDéjà pris en charge par MagiskHide par défaut</string>
<string name="process_error">Erreur d\'exécution</string>
<string name="internal_storage">Le zip est stocké dans :\n[Internal Storage]%1$s</string>
<string name="zip_process_title">Exécution</string>
<string name="manual_boot_image">Veuillez sélectionner l\'image boot manuellement !</string>
<string name="zip_download_title">Téléchargement</string>
<string name="zip_download_msg">Téléchargement du fichier zip (%1$d%%) ...</string>
<string name="manager_update_title">Nouvelle mise à jour Magisk Manager disponible !</string>
<string name="process_error">Erreur de traitement</string>
<string name="internal_storage">Le zip est stocké dans :\n[Stockage interne]%1$s</string>
<string name="zip_process_title">Traitement</string>
<string name="zip_download_title">Téléchargement</string>
<string name="zip_download_msg">Téléchargement du fichier zip (%1$d%%)…</string>
<string name="manager_update_title">Nouvelle mise à jour de Magisk Manager disponible !</string>
<string name="manager_download_install">Appuyez pour télécharger et installer</string>
<string name="magisk_updates">Mises à jour Magisk</string>
<string name="flashing">Flash en-cours</string>
<string name="flashing">Flashage en cours</string>
<string name="hide_manager_toast">Masquage de Magisk Manager…</string>
<string name="hide_manager_fail_toast">Échec du masquage de Magisk Manager...</string>
<string name="hide_manager_fail_toast">Échec du masquage de Magisk Manager</string>
<string name="download_zip_only">Télécharger uniquement le zip</string>
<string name="patch_boot_file">Patcher le fichier image Boot</string>
<string name="direct_install">Installation directe (recommandée)</string>
<string name="install_second_slot">Intaller sur le second slot (après une OTA)</string>
<string name="select_method">Choisir une méthode</string>
<string name="no_boot_file_patch_support">La version cible de Magisk ne supporte pas la modification du fichier image Boot</string>
<string name="boot_file_patch_msg">Sélectionnez l\'image Boot stock au format .img ou .img.tar</string>
<string name="complete_uninstall">Désinstaller complètement</string>
<string name="restore_stock_boot">Restaurer le Boot stock</string>
<string name="restore_done">Restauration effectuée !</string>
<string name="restore_fail">Pas de sauvegarde stock disponible !</string>
<string name="uninstall_toast">Désinstallation de Magisk Manager dans 5 secondes, n\'oubliez pas de redémarrer par la suite</string>
<string name="proprietary_title">Télécharger le code propriétaire</string>
<string name="proprietary_notice">Magisk Manager est un logiciel FOSS et ne contient donc pas le code propriétaire de l\'API SafetyNet de Google. Autorisez-vous Magisk Manager à télécharger une extension (qui contient GoogleApiClient) afin de tester SafetyNet ?</string>
<!--Settings Activity -->
<string name="settings_general_category">Général</string>
<string name="settings_dark_theme_title">Thème sombre</string>
@@ -113,7 +108,7 @@
<string name="settings_notification_title">Notification de mise à jour</string>
<string name="settings_notification_summary">Afficher des notifications de mises à jour quand une nouvelle version est disponible</string>
<string name="settings_clear_cache_title">Effacer le cache du dépôt</string>
<string name="settings_clear_cache_summary">Effacer les informations en cache des dépôts en ligne, pour forcer une actualisation de l\'application</string>
<string name="settings_clear_cache_summary">Effacer les informations en cache des dépôts distants, pour forcer une actualisation de l\'application</string>
<string name="settings_core_only_title">Mode Magisk Core uniquement</string>
<string name="settings_core_only_summary">Activer uniquement les fonctionnalités de base, tous les modules ne seront pas chargés. MagiskSU, MagiskHide et les hosts systemless restent activés</string>
<string name="settings_magiskhide_summary">Masquer Magisk de diverses détections</string>
@@ -133,8 +128,7 @@
<string name="superuser_notification">Notification Superuser</string>
<string name="request_timeout_summary">%1$s secondes</string>
<string name="settings_hide_manager_title">Masquer Magisk Manager</string>
<string name="settings_hide_manager_summary">Masquer temporairement Magisk Manager.\nCeci installera une nouvelle appli appelée \"Unhide Magisk Manager\"</string>
<string name="language">Langue</string>
<string name="language">Langue</string>
<string name="system_default">(Selon système)</string>
<string name="settings_update">Paramètres de mises à jour</string>
<string name="settings_update_channel_title">Canal de mise à jour</string>
@@ -188,6 +182,6 @@
<string name="none">Aucun</string>
<!--Superuser logs-->
<string name="pid">PID :\u0020</string>
<string name="target_uid">Cible UID:\u0020</string>
<string name="target_uid">UID cible :\\u0020</string>
<string name="command">Commande :\u0020</string>
</resources>

View File

@@ -0,0 +1,206 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moduli</string>
<string name="downloads">Preuzimanja</string>
<string name="superuser">Superuser</string>
<string name="log">Zapisnik događaja</string>
<string name="settings">Postavke</string>
<string name="install">Instaliranje</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk nije instaliran</string>
<string name="checking_for_updates">Provjera ažuriranja...</string>
<string name="magisk_update_available">Dostupna je Maigsk inačica v%1$s!</string>
<string name="safetyNet_check_text">Dodirni za SafetyNet provjeru</string>
<string name="checking_safetyNet_status">Provjera SafetyNet statusa</string>
<string name="safetyNet_check_success">SafetyNet provjera uspješna</string>
<string name="safetyNet_api_error">SafetyNet API greška</string>
<string name="safetyNet_network_loss">Mrežna veza nije dostupna</string>
<string name="safetyNet_service_disconnected">Usluga je ubijena</string>
<string name="safetyNet_res_invalid">Odgovor je nevažeći</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Napredne postavke</string>
<string name="keep_force_encryption">Zadrži prisilno šifirannje</string>
<string name="keep_dm_verity">Zadrži dm-istinitost</string>
<string name="current_magisk_title">Instalirana inačica: %1$s</string>
<string name="install_magisk_title">Najnovija inačica: %1$s</string>
<string name="uninstall">Deinstaliraj</string>
<string name="uninstall_magisk_title">Deinstaliraj Magisk</string>
<string name="uninstall_magisk_msg">Svi moduli će biti onemogućeni/uklonjeni. Root će biti uklonjen i potencijalno šifrirati vaše podatke, ukoliko vaši podaci trenutačno nisu šifrirani</string>
<string name="update">Ažuriraj %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nema podataka)</string>
<string name="no_modules_found">Nijedan modul nije pronađen</string>
<string name="update_file_created">Modul će se ažurirati pri sljedećem ponovnom pokretanju</string>
<string name="remove_file_created">Modul će biti uklonjen pri sljedećem ponovnom pokretanju</string>
<string name="remove_file_deleted">Modul neće biti uklonjen pri sljedećem ponovnom pokretanju</string>
<string name="disable_file_created">Modul će biti onemogućen pri sljedećem ponovnom pokretanju</string>
<string name="disable_file_removed">Modul će biti omogućen pri sljedećem ponovnom pokretanju</string>
<string name="author">Napravio %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Ažuriranje dostupno</string>
<string name="installed">Instalirano</string>
<string name="not_installed">Nije instalirano</string>
<!--Log Fragment-->
<string name="menuSaveLog">"Spremi zapisnik "</string>
<string name="menuReload">Ponovno učitaj</string>
<string name="menuClearLog">Očisti zapisnik sada</string>
<string name="logs_cleared">Zapisnik je uspješno izbrisan</string>
<string name="log_is_empty">Zapisnik je prazan</string>
<string name="logs_save_failed">Nije moguće napisati zapisnik na SD karticu:</string>
<!--About Activity-->
<string name="about">O aplikaciji</string>
<string name="app_developers">Glavni razvojni programeri</string>
<string name="app_developers_"><![CDATA[Aplikaciju izradio <a href="https://github.com/topjohnwu">topjohnwu</a> u suradnji s <a href="https://github.com/d8ahazard">Digitalhigh</a> i <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Popis izmjena aplikacije</string>
<string name="translators" />
<string name="app_version">Verzija aplikacije</string>
<string name="app_source_code">Izvorni kod</string>
<string name="donation">Donacija</string>
<string name="app_translators">Prevoditelji aplikacije</string>
<string name="support_thread">Tema podrške</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Ova značajka neće raditi bez dopuštenja za korištenje vanjske pohrane.</string>
<string name="no_thanks">Ne hvala</string>
<string name="yes">Da</string>
<string name="ok">OK</string>
<string name="close">Zatvori</string>
<string name="repo_install_title">Instaliraj %1$s</string>
<string name="repo_install_msg">Da li želiš instalirati %1$s sada?</string>
<string name="download">Preuzmi</string>
<string name="download_file_error">Pogreška prilikom preuzimanja datoteke</string>
<string name="reboot">Ponovno podizanje sustava</string>
<string name="downloading_toast">Preuzimanje %1$s</string>
<string name="magisk_update_title">Dostupno je novo Magisk ažuriranje!</string>
<string name="settings_reboot_toast">Ponovno pokrenite kako biste primjenili postavke</string>
<string name="release_notes">Bilješke o izdavanju aplikacije</string>
<string name="repo_cache_cleared">Predmemorija repozitorija izbrisana</string>
<string name="safetyNet_hide_notice">Ova aplikacija upotrebljava SafetyNet\nRiješeno pomoću MagiskHide prema zadanim postavkama</string>
<string name="process_error">Pogreška u procesu</string>
<string name="internal_storage">Zip je pohranjen u:\n[Unutarnja pohrana]%1$s</string>
<string name="zip_download_title">Preuzimanje</string>
<string name="zip_download_msg">Preuzimanje zip datoteke (%1$d%%) …</string>
<string name="zip_process_title">Obrada</string>
<string name="zip_process_msg">Obrada zip datoteke …</string>
<string name="manager_update_title">Dostupno je novo ažuriranje Magisk Manager aplikacije!</string>
<string name="manager_download_install">Pritisnite za preuzimanje i instalaciju</string>
<string name="magisk_updates">Magisk ažuriranja</string>
<string name="flashing">Apliciranje</string>
<string name="hide_manager_toast">Skrivanje Magisk Manager aplikacije…</string>
<string name="hide_manager_fail_toast">Skrivanje Magisk Manager nije uspjelo</string>
<string name="download_zip_only">Preuzmi samo zip</string>
<string name="patch_boot_file">Zakrpa datoteke za podizanje sustava</string>
<string name="direct_install">Izravna instalacija (preporuča se)</string>
<string name="install_second_slot">Instalirajte na drugo mjesto (nakon OTA-e)</string>
<string name="select_method">Odaberite metodu</string>
<string name="no_boot_file_patch_support">Ciljana verzija Magiska ne podržava zakrpu datoteke za podizanje sustava</string>
<string name="boot_file_patch_msg">Odaberite standardnu datoteku za podizanje sustava u .img ili .img.tar formatu</string>
<string name="complete_uninstall">Potpuna deinstalacija</string>
<string name="restore_stock_boot">Obnovi standardnu datoteku za podizanje sustava</string>
<string name="restore_done">Obnova je dovršena!</string>
<string name="restore_fail">Stock backup does not exist!</string>
<string name="uninstall_toast">Deinstaliranje Magisk Manager aplikacije unutar 5 sekundi, molimo ponovno pokrenite uređaj nakon toga</string>
<string name="proprietary_title">Preuzmite vlasnički kod</string>
<string name="proprietary_notice">Magisk Manager je FOSS aplikacija te ne sadrži Googleov SafetyNet API kod.\n\nDopuštate li Magisk Manager aplikaciji da preuzme proširenje (sadrži GoogleApiClient) za SafetyNet provjere?</string>
<!--Settings Activity -->
<string name="settings_general_category">Općenito</string>
<string name="settings_dark_theme_title">Tamna tema</string>
<string name="settings_dark_theme_summary">Omogući tamnu temu</string>
<string name="settings_notification_title">Obavijest o ažuriranju</string>
<string name="settings_notification_summary">Prikaži obavijest o ažuriranju kada je dostupna nova verzija</string>
<string name="settings_clear_cache_title">Izbriši predmemoriju repozitorija</string>
<string name="settings_clear_cache_summary">Izbrišite predmemorirane informacije za online repozitorij, prisiljavajući aplikaciju da se osvježi online</string>
<string name="settings_hide_manager_title">Sakrij Magisk Manager</string>
<string name="settings_hide_manager_summary">Privremeno sakrij Magisk Manager.\nTo će instalirati novu aplikaciju pod nazivom \"Otkrij Magisk Manager\"</string>
<string name="language">Jezik</string>
<string name="system_default">(Zadana postavka sustava)</string>
<string name="settings_update">Ažuriraj postavke</string>
<string name="settings_update_channel_title">Kanal ažuriranja</string>
<string name="settings_update_stable">Stabilno</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Izlazni format datoteke za podizanje sustava nakon zakrpe</string>
<string name="settings_boot_format_summary">Odaberite izlazni format datoteke za podizanje sustava nakon zakrpe.\nOdaberite .img da biste aplicirali putem brzog pokretanja(fastboota)/preuzimanja(downloada); odaberite .img.tar da biste aplicirali putem ODIN-a.</string>
<string name="settings_core_only_title">Samo Magisk Core način rada</string>
<string name="settings_core_only_summary">Omogućite samo osnovne značajke, svi se moduli neće učitati. MagiskSU, MagiskHide i systemless hostovi će i dalje biti omogućeni</string>
<string name="settings_magiskhide_summary">Sakrij Magisk od raznih detekcija</string>
<string name="settings_hosts_title">Systemless hostovi</string>
<string name="settings_hosts_summary">Systemless hostovi podržavaju Adblock aplikacije</string>
<string name="settings_su_app_adb">Aplikacije and ADB</string>
<string name="settings_su_app">Samo aplikacije</string>
<string name="settings_su_adb">Samo ADB</string>
<string name="settings_su_disable">Onemogućeno</string>
<string name="settings_su_request_10">10 sekundi</string>
<string name="settings_su_request_20">20 sekundi</string>
<string name="settings_su_request_30">30 sekundi</string>
<string name="settings_su_request_60">60 sekundi</string>
<string name="superuser_access">Superuser pristup</string>
<string name="auto_response">Automatski odgovor</string>
<string name="request_timeout">Vremensko ograničenje zahtjeva</string>
<string name="superuser_notification">Superuser obavijest</string>
<string name="request_timeout_summary">%1$s sekundi</string>
<string name="settings_su_reauth_title">Ponovno provjerite autentičnost nakon ažuriranja</string>
<string name="settings_su_reauth_summary">Ponovno provjerite autentičnost Superuser dopuštenja nakon ažuriranja aplikacije</string>
<string name="multiuser_mode">Višekorisnički način rada</string>
<string name="settings_owner_only">Samo vlasnik uređaja</string>
<string name="settings_owner_manage">Upravljano od strane vlasnika uređaja</string>
<string name="settings_user_independent">Neovisno o korisniku</string>
<string name="owner_only_summary">Samo vlasnik ima root pristup</string>
<string name="owner_manage_summary">Samo vlasnik može upravljati root pristupom i primati zahtjeve za root pristup</string>
<string name="user_indepenent_summary">Svaki korisnik ima vlastita root pravila</string>
<string name="multiuser_hint_owner_request">Zahtjev je poslan vlasniku uređaja. Prebacite se na vlasnika i odobrite dopuštenje</string>
<string name="mount_namespace_mode">Postavljanje imenskog prostora</string>
<string name="settings_ns_global">Globalni imenski prostor</string>
<string name="settings_ns_requester">Naslijedit imenski prostor</string>
<string name="settings_ns_isolate">Izolirani imenski prostor</string>
<string name="global_summary">Sve root sesije koriste globalni imenski prostor</string>
<string name="requester_summary">Root sesije će nasljediti imenski prostor tražitelja</string>
<string name="isolate_summary">Svaka root sesija ima svoj vlastiti imenski prostor</string>
<!--Superuser-->
<string name="su_request_title">Superuser zahtjev</string>
<string name="deny_with_str">Odbij%1$s</string>
<string name="deny">Odbij</string>
<string name="prompt">Upitaj</string>
<string name="grant">Odobri</string>
<string name="su_warning">Omogućuje potpuni pristup vašem uređaju.\nOdbijte ako niste sigurni!</string>
<string name="forever">Zauvijek</string>
<string name="once">Jednom</string>
<string name="tenmin">10 min</string>
<string name="twentymin">20 min</string>
<string name="thirtymin">30 min</string>
<string name="sixtymin">60 min</string>
<string name="su_allow_toast">%1$s su dodijeljena Superuser prava</string>
<string name="su_deny_toast">%1$s su odbijena Superuser prava</string>
<string name="no_apps_found">Nisu pronađene aplikacije</string>
<string name="su_snack_grant">Superuser prava su dodijeljena za %1$s</string>
<string name="su_snack_deny">Superuser prava su odbijena za %1$s</string>
<string name="su_snack_notif_on">Obavijesti za %1$s su odobrene</string>
<string name="su_snack_notif_off">Obavijesti za %1$s su odbijene</string>
<string name="su_snack_log_on">Zapisnik događaja omogućen je za %1$s</string>
<string name="su_snack_log_off">Zapisnik događaja onemogućen je za %1$s</string>
<string name="su_snack_revoke">Opozvana su prava za %1$s</string>
<string name="su_revoke_title">Opozvati?</string>
<string name="su_revoke_msg">Potvrdite da biste opozvali prava za %1$s?</string>
<string name="toast">Pop-up</string>
<string name="none">Nijedan</string>
<!--Superuser logs-->
<string name="pid">PID:\u0020</string>
<string name="target_uid">Ciljani UID:\u0020</string>
<string name="command">Naredba:\u0020</string>
</resources>

View File

@@ -1,6 +1,6 @@
<resources>
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Moduli</string>
<string name="downloads">Download</string>
@@ -11,40 +11,36 @@
<!--Status Fragment-->
<string name="magisk_version_error">Magisk non installato</string>
<string name="checking_for_updates">Controllo aggiornamenti…</string>
<string name="magisk_update_available">È disponibile Magisk v%1$s!</string>
<string name="cannot_check_updates">Impossibile controllare aggiornamenti</string>
<string name="root_error">Rootato ma senza permessi. Non sei autorizzato?</string>
<string name="not_rooted">Non rootato</string>
<string name="safetyNet_check_text">Tocca per avviare controllo SafetyNet</string>
<string name="checking_safetyNet_status">Controllo stato SafetyNet</string>
<string name="safetyNet_check_success">Controllo SafetyNet OK</string>
<string name="safetyNet_network_loss">persa conenssioen di rete</string>
<string name="safetyNet_service_disconnected">Ils ervizio è stato terminato</string>
<string name="invalid_update_channel">Canale di aggiornamento non valido</string>
<string name="safetyNet_check_text">Tocca per controllare SafetyNet</string>
<string name="checking_safetyNet_status">Controllo stato di SafetyNet</string>
<string name="safetyNet_check_success">Controllo di SafetyNet OK</string>
<string name="safetyNet_api_error">Errore API di SafetyNet</string>
<string name="safetyNet_network_loss">Connessione di rete persa</string>
<string name="safetyNet_service_disconnected">Il servizio è stato terminato</string>
<string name="safetyNet_res_invalid">La risposta non è valida</string>
<!--Install Fragment-->
<string name="auto_detect">%1$s (auto)</string>
<string name="cannot_auto_detect">(impossibile rilevare automaticamente)</string>
<string name="boot_image_title">Percorso immagine boot</string>
<string name="detect_button">Rileva</string>
<string name="advanced_settings_title">Impostazioni avanzate</string>
<string name="keep_force_encryption">Mantieni crittografia forzata</string>
<string name="keep_force_encryption">Mantieni la crittografia forzata</string>
<string name="keep_dm_verity">Mantieni dm-verity</string>
<string name="current_magisk_title">Versione Magisk installata: %1$s</string>
<string name="install_magisk_title">Versione Magisk aggiornata: %1$s</string>
<string name="current_magisk_title">Versione di installata: %1$s</string>
<string name="install_magisk_title">Ultima versione di: %1$s</string>
<string name="uninstall">Disinstalla</string>
<string name="uninstall_magisk_title">Disinstalla Magisk</string>
<string name="uninstall_magisk_msg">Tutti i moduli verranno disabilitati/rimossi. Il root verrà rimosso e se il dispositivo non è crittografato è possibile che vengano crittografati tutti i dati</string>
<string name="update">Aggiorna %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(nessuna informazione)</string>
<string name="no_info_provided">(Nessuna informazione)</string>
<string name="no_modules_found">Nessun modulo trovato</string>
<string name="update_file_created">Il modulo sarà aggiornato al prossimo riavvio</string>
<string name="remove_file_created">Il modulo sarà rimosso al prossimo riavvio</string>
<string name="remove_file_deleted">Il modulo non sarà rimosso al prossimo riavvio</string>
<string name="disable_file_created">Il modulo sarà disattivato al prossimo riavvio</string>
<string name="disable_file_created">Il modulo sarà disabilitato al prossimo riavvio</string>
<string name="disable_file_removed">Il modulo sarà abilitato al prossimo riavvio</string>
<string name="author">Creato da: %1$s</string>
@@ -54,9 +50,9 @@
<string name="not_installed">Non installato</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Salva nella SD</string>
<string name="menuSaveLog">Salva registro eventi</string>
<string name="menuReload">Ricarica</string>
<string name="menuClearLog">Azzera registro eventi</string>
<string name="menuClearLog">Pulisci registro eventi</string>
<string name="logs_cleared">Registro eventi creato correttamente</string>
<string name="log_is_empty">Il registro eventi è vuoto</string>
<string name="logs_save_failed">Impossibile scrivere registro eventi nella SD</string>
@@ -66,7 +62,7 @@
<string name="app_developers">Sviluppatori</string>
<string name="app_developers_"><![CDATA[App creata da <a href="https://github.com/topjohnwu">topjohnwu</a> in collaborazione con <a href="https://github.com/d8ahazard">Digitalhigh</a> e <a href="https://github.com/dvdandroid">Dvdandroid</a>.]]></string>
<string name="app_changelog">Novità</string>
<string name="translators">Fabb2303 - bovirus</string>
<string name="translators">Auanasgheps | Fabb2303 | bovirus</string>
<string name="app_version">Versione app</string>
<string name="app_source_code">Codice sorgente</string>
<string name="donation">Dona</string>
@@ -74,8 +70,8 @@
<string name="support_thread">Supporto app</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">Questa funzione non sarà operativa senza il permesso di scrittura nella memoria di archiviazione esterna</string>
<string name="no_thanks">No grazie</string>
<string name="permissionNotGranted">Questa funzione non sarà operativa senza il permesso di scrittura nella memoria di archiviazione esterna.</string>
<string name="no_thanks">No, grazie</string>
<string name="yes"></string>
<string name="ok">OK</string>
<string name="close">Chiudi</string>
@@ -83,40 +79,70 @@
<string name="repo_install_msg">Vuoi installare %1$s ?</string>
<string name="download">Download</string>
<string name="download_file_error">Errore nel download del file</string>
<string name="install_error">Errore di installazione!</string>
<string name="invalid_zip">Lo ZIP non è un modulo Magisk!!</string>
<string name="reboot">Riavvia</string>
<string name="zip_process_msg">Elaborazione file ZIP…</string>
<string name="downloading_toast">Download di %1$s</string>
<string name="magisk_update_title">Disponibile nuovo aggiornamento Magisk!</string>
<string name="magisk_update_title">Disponibile un nuovo aggiornamento di Magisk!</string>
<string name="settings_reboot_toast">Riavvia per applicare</string>
<string name="release_notes">Note di rilascio</string>
<string name="repo_cache_cleared">Cache reposititory azzerata</string>
<string name="repo_cache_cleared">La cache delle repository è stata pulita</string>
<string name="safetyNet_hide_notice">Quest\'app usa SafetyNet\ned è già gestita da MagiskHide</string>
<string name="process_error">Errore di elaborazione</string>
<string name="internal_storage">Lo ZIP si trova in:\n[memoria interna]%1$s</string>
<string name="zip_process_title">Elaborazione</string>
<string name="manual_boot_image">Seleziona manualmente l\'immagine di boot!</string>
<string name="internal_storage">Il file zip si trova in:\n[memoria interna]%1$s</string>
<string name="zip_download_title">Download in corso</string>
<string name="zip_download_msg">Download del file zip (%1$d%%) …</string>
<string name="zip_process_title">Elaborazione</string>
<string name="zip_process_msg">Elaborazione del file zip…</string>
<string name="manager_update_title">Nuovo aggiornamento di Magisk Manager disponibile!</string>
<string name="manager_download_install">Premere per scaricare e installare</string>
<string name="magisk_updates">Aggiornamenti Magisk</string>
<string name="flashing">Flashando</string>
<string name="dtbo_patched_title">DTBO è stato aggiornato!</string>
<string name="dtbo_patched_reboot">Magisk Manager ha aggiornato dtbo.img, riavvia per completare</string>
<string name="magisk_updates">Aggiornamento Magisk</string>
<string name="flashing">Flash in corso…</string>
<string name="hide_manager_toast">Nascondendo Magisk Manager…</string>
<string name="hide_manager_toast2">Potrebbe volerci un po\'…</string>
<string name="hide_manager_fail_toast">Non è stato possibile nascondere Magisk Manager</string>
<string name="download_zip_only">Scarica solo il file zip</string>
<string name="patch_boot_file">Aggiorna l\'immagine di boot</string>
<string name="direct_install">Installazione diretta (raccomandata)</string>
<string name="install_second_slot">Installa nel secondo slot (dopo OTA)</string>
<string name="select_method">Seleziona un metodo</string>
<string name="no_boot_file_patch_support">La versione Magisk di destinazione non supporta l\'aggiornamento dell\'immagine di boot</string>
<string name="boot_file_patch_msg">Seleziona l\'immagine originale di boot in formato .img o img.tar</string>
<string name="complete_uninstall">Completa disinstallazione</string>
<string name="restore_stock_boot">Ripristina l\'immagine originale di boot</string>
<string name="restore_done">Ripristino completato!</string>
<string name="restore_fail">Non esiste un\'immagine originale di boot!</string>
<string name="uninstall_toast">Disinstallazione di Magisk Manager in 5 secondi, riavvia manualmente per completare</string>
<string name="proprietary_title">Scarica codice proprietario</string>
<string name="proprietary_notice">Magisk Manager è FOSS, quindi non contiene il codice proprietario delle API Google SafetyNet.\n\nVuoi permettere il download di un\'estensione (che contiene GoogleApiClient) per controllare lo stato di SafetyNet?</string>
<string name="su_db_corrupt">Il database SU è corrotto, un nuovo DB verrà ricreato</string>
<!--Settings Activity -->
<string name="settings_general_category">Generale</string>
<string name="settings_dark_theme_title">Tema scuro</string>
<string name="settings_dark_theme_summary">Abilita tema scuro</string>
<string name="settings_dark_theme_summary">Abilita il tema scuro</string>
<string name="settings_notification_title">Notifica aggiornamenti</string>
<string name="settings_notification_summary">Visualizza notifica quando sono diponibili aggiornamenti</string>
<string name="settings_clear_cache_title">Azzera cache repository</string>
<string name="settings_clear_cache_summary">Azzera le informazioni nella cache per i repository online, e forza l\'aggiornamento online dell\'app</string>
<string name="settings_core_only_title">Solo modo core Magisk</string>
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Non tutti i moduli verranno caricati. MagiskSU, MagiskHide, e host systemless rimarranno abilitati</string>
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
<string name="settings_hosts_title">Host systemless</string>
<string name="settings_hosts_summary">Supporto host systemless per app blocco pubblicità</string>
<string name="settings_notification_summary">Mostra una notifica quando sono disponibili aggiornamenti</string>
<string name="settings_clear_cache_title">Pulisci cache repository</string>
<string name="settings_clear_cache_summary">Pulisci la cache delle repository e forza l\'aggiornamento online dell\'app</string>
<string name="settings_hide_manager_title">Nascondi Magisk Manager</string>
<string name="settings_hide_manager_summary">Reinstalla Magisk Manager con un nome del pacchetto casuale</string>
<string name="language">Lingua</string>
<string name="system_default">(Predefinito)</string>
<string name="settings_update">Impostazioni di aggiornamento</string>
<string name="settings_update_channel_title">Canale di aggiornamento</string>
<string name="settings_update_stable">Stabile</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_update_custom">Personalizzato</string>
+ <string name="settings_update_custom_msg">Inserisci un URL personalizzato</string>
<string name="settings_boot_format_title">Formato dell\'immagine di boot aggiornata</string>
<string name="settings_boot_format_summary">Seleziona il formato nel quale l\'immagine di boot verrà salvata. .\nSeleziona .img per il flash in fastboot/download mode; Seleziona .img.tar per il flash con Odin.</string>
<string name="settings_core_only_title">Modalità Magisk Core</string>
<string name="settings_core_only_summary">Abilita solo le funzioni principali. Nessun modulo verrà caricato. MagiskSU, MagiskHide e host systemless rimarranno abilitati</string>
<string name="settings_magiskhide_summary">Nasconde Magisk da numerose rilevazioni</string>
<string name="settings_hosts_title">Host systemless</string>
<string name="settings_hosts_summary">Supporto a host systemless per le app che bloccano le pubblicità</string>
<string name="settings_su_app_adb">App e ADB</string>
<string name="settings_su_app">Solo app</string>
<string name="settings_su_adb">Solo ADB</string>
@@ -126,27 +152,35 @@
<string name="settings_su_request_30">30 secondi</string>
<string name="settings_su_request_60">60 secondi</string>
<string name="superuser_access">Accesso Superuser</string>
<string name="auto_response">Risposta automatica</string>
<string name="auto_response">Accesso predefinito</string>
<string name="request_timeout">Timeout richiesta</string>
<string name="superuser_notification">Notifica Superuser</string>
<string name="request_timeout_summary">%1$s secondi</string>
<string name="settings_su_reauth_title">Ri-autentifica dopo aggiornamento</string>
<string name="settings_su_reauth_summary">Ri-autentifica permessi superuser dopo aggiornamento applicazione</string>
<string name="multiuser_mode">Modo multiutente</string>
<string name="settings_owner_only">Solo proprietario dispositivo</string>
<string name="settings_owner_manage">gestito da propietario utente</string>
<string name="settings_user_independent">Utente indipendente</string>
<string name="owner_only_summary">Solo proprietario che ha accesso root</string>
<string name="owner_manage_summary">Solo il propietario può gestire accesso root e ricevere richieste</string>
<string name="settings_su_reauth_title">Ri-autentica dopo un aggiornamento</string>
<string name="settings_su_reauth_summary">Ri-autentica permessi Superuser dopo aggiornamento applicazione</string>
<string name="multiuser_mode">Modalità multiutente</string>
<string name="settings_owner_only">Solo proprietario del dispositivo</string>
<string name="settings_owner_manage">Gestito dal proprietario utente</string>
<string name="settings_user_independent">Utente indipendente</string>
<string name="owner_only_summary">Solo il proprietario ha i permessi di root</string>
<string name="owner_manage_summary">Solo il proprietario può gestire accesso root e ricevere richieste</string>
<string name="user_indepenent_summary">Ogni utente ha le sue regole di root separate</string>
<string name="multiuser_hint_owner_request">Una richiestà è stata inviata al propietario dipositivo. Accedi come propietario dispositivo e concedi i permessi.</string>
<string name="multiuser_hint_owner_request">Una richiesta è stata inviata al proprietario del dispositivo. Accedi come proprietario dispositivo e concedi i permessi.</string>
<string name="mount_namespace_mode">Modalità mount Namespace</string>
<string name="settings_ns_global">Namespace globale</string>
<string name="settings_ns_requester">Namespace ereditato</string>
<string name="settings_ns_isolate">Namespace isolato</string>
<string name="global_summary">Tutte le sessioni di root erediteranno il Namespace globale</string>
<string name="requester_summary">Le sessioni di root erediteranno il Namespace del loro richiedente</string>
<string name="isolate_summary">Ogni sessione di root avrà il suo Namespace isolato</string>
<!--Superuser-->
<string name="su_request_title">Richiesta Superuser</string>
<string name="deny_with_str">Nega %1$s</string>
<string name="deny">Nega</string>
<string name="prompt">Richiedi</string>
<string name="prompt">Chiedi</string>
<string name="grant">Concedi</string>
<string name="su_warning">Concede il pieno accesso al dispositivo.\nNega se non sei sicuro</string>
<string name="forever">Sempre</string>
@@ -155,15 +189,15 @@
<string name="twentymin">20 minuti</string>
<string name="thirtymin">30 minuti</string>
<string name="sixtymin">60 minuti</string>
<string name="su_allow_toast">%1$s HA ottenuto i permessi Superuser</string>
<string name="su_deny_toast">%1$s NON ha ottenuto i permessi Superuser</string>
<string name="su_allow_toast">%1$s ha ottenuto i permessi Superuser</string>
<string name="su_deny_toast">%1$s non ha ottenuto i permessi Superuser</string>
<string name="no_apps_found">Nessuna app trovata</string>
<string name="su_snack_grant"> %1$s HA ottenuto i permessi Superuser</string>
<string name="su_snack_deny"> %1$s NON ha ottenuto i permessi Superuser</string>
<string name="su_snack_grant"> %1$s ha ottenuto i permessi Superuser</string>
<string name="su_snack_deny"> %1$s non ha ottenuto i permessi Superuser</string>
<string name="su_snack_notif_on">Notifiche per %1$s abilitate</string>
<string name="su_snack_notif_off">Notifiche per %1$s disabilitate</string>
<string name="su_snack_log_on">Registro eventi abilitato per %1$s</string>
<string name="su_snack_log_off">Registro eventi NON abilitato per %1$s</string>
<string name="su_snack_log_off">Registro eventi non abilitato per %1$s</string>
<string name="su_snack_revoke">I diritti di %1$s sono stati revocati</string>
<string name="su_revoke_title">Revocare?</string>
<string name="su_revoke_msg">Confermi la revoca dei diritti di %1$s?</string>

View File

@@ -14,22 +14,15 @@
<string name="checking_for_updates">更新を確認中...</string>
<string name="magisk_update_available">Magisk v%1$s が利用可能です!</string>
<string name="cannot_check_updates">更新を確認できませんでした。インターネットに接続されていますか?</string>
<string name="root_error">Root化はされていますが権限がありません。拒否していませんか</string>
<string name="not_rooted">Root化されていません</string>
<string name="safetyNet_check_text">タップしてSafetyNetチェックを開始</string>
<string name="checking_safetyNet_status">SafetyNet Statusをチェック中…</string>
<!--Install Fragment-->
<string name="auto_detect">(自動) %1$s</string>
<string name="cannot_auto_detect">(自動検出に失敗)</string>
<string name="boot_image_title">Bootイメージの位置</string>
<string name="detect_button">検出</string>
<string name="advanced_settings_title">高度な設定</string>
<string name="keep_force_encryption">強制的な暗号化を維持する</string>
<string name="keep_dm_verity">dm-verityを維持する</string>
<string name="current_magisk_title">インストール済のMagisk: %1$s</string>
<string name="install_magisk_title">最新のMagisk: %1$s</string>
<string name="current_magisk_title">インストール済: %1$s</string>
<string name="install_magisk_title">最新: %1$s</string>
<string name="uninstall">アンインストール</string>
<string name="uninstall_magisk_title">Magiskをアンインストールします</string>
@@ -49,7 +42,7 @@
<string name="not_installed">未インストール</string>
<!--Log Fragment-->
<string name="menuSaveToSd">SDカードに保存</string>
<string name="menuSaveLog">ログ保存</string>
<string name="menuReload">リロード</string>
<string name="menuClearLog">ログを消去する</string>
<string name="logs_cleared">ログは正常にクリアされました</string>
@@ -78,8 +71,6 @@
<string name="repo_install_msg">%1$s をインストールしますか?</string>
<string name="download">ダウンロード</string>
<string name="download_file_error">ダウンロード中にエラーが発生しました</string>
<string name="install_error">インストールエラー!</string>
<string name="invalid_zip">このzipはMagiskモジュールではありません</string>
<string name="reboot">再起動</string>
<string name="zip_process_msg">zipファイルの処理中…</string>
<string name="downloading_toast">%1$s をダウンロード中</string>
@@ -91,7 +82,6 @@
<string name="process_error">プロセスエラー</string>
<string name="internal_storage">zipは:\n[Internal Storage]%1$sに保存されます</string>
<string name="zip_process_title">処理</string>
<string name="manual_boot_image">ブートイメージを手動で選択してください!</string>
<!--Settings Activity -->
<string name="settings_general_category">一般</string>

View File

@@ -14,22 +14,15 @@
<string name="checking_for_updates">업데이트 확인 중…</string>
<string name="magisk_update_available">Magisk v%1$s 사용 가능!</string>
<string name="cannot_check_updates">업데이트를 확인할 수 없음. 인터넷 연결을 확인하세요.</string>
<string name="root_error">루팅은 되어 있으나 루트 권한을 얻을 수 없음. 루트 권한 허용 상태를 확인하세요.</string>
<string name="not_rooted">루팅이 되어 있지 않음</string>
<string name="safetyNet_check_text">SafetyNet 체크를 시작하려면 누르기</string>
<string name="checking_safetyNet_status">SafetyNet 상태 확인 중…</string>
<!--Install Fragment-->
<string name="auto_detect">(자동) %1$s</string>
<string name="cannot_auto_detect">(자동 감지 실패)</string>
<string name="boot_image_title">부트 이미지 위치</string>
<string name="detect_button">감지</string>
<string name="advanced_settings_title">고급 설정</string>
<string name="keep_force_encryption">강제 암호화 유지</string>
<string name="keep_dm_verity">dm-verity 유지</string>
<string name="current_magisk_title">설치된 Magisk 버전: %1$s</string>
<string name="install_magisk_title">최신 Magisk 버전: %1$s</string>
<string name="current_magisk_title">설치된버전: %1$s</string>
<string name="install_magisk_title">최신버전: %1$s</string>
<string name="uninstall">제거</string>
<string name="uninstall_magisk_title">Magisk 제거</string>
@@ -49,7 +42,7 @@
<string name="not_installed">설치되지 않음</string>
<!--Log Fragment-->
<string name="menuSaveToSd">SD 카드에 저장</string>
<string name="menuSaveLog">저장 로그</string>
<string name="menuReload">다시 불러오기</string>
<string name="menuClearLog">지금 로그 비우기</string>
<string name="logs_cleared">로그가 성공적으로 비워짐</string>
@@ -77,8 +70,6 @@
<string name="repo_install_title">%1$s 설치</string>
<string name="repo_install_msg">정말 %1$s을(를) 설치하시겠습니까?</string>
<string name="download_file_error">파일 다운로드 오류</string>
<string name="install_error">설치 오류!</string>
<string name="invalid_zip">이 zip 파일은 Magisk 모듈이 아닙니다!!</string>
<string name="reboot">다시 시작</string>
<string name="zip_process_msg">zip 파일 처리 중…</string>
<string name="downloading_toast">%1$s 다운로드 중</string>
@@ -90,7 +81,6 @@
<string name="process_error">처리 오류</string>
<string name="internal_storage">zip 파일이 다음 위치에 저장됨:\n[내부 저장소]%1$s</string>
<string name="zip_process_title">처리 중</string>
<string name="manual_boot_image">부트 이미지를 직접 선택해 주세요!</string>
<!--Settings Activity -->
<string name="settings_general_category">일반</string>

View File

@@ -14,26 +14,20 @@
<string name="checking_for_updates">Controleren op updates…</string>
<string name="magisk_update_available">Magisk v%1$s beschikbaar!</string>
<string name="cannot_check_updates">Kan niet controleren op updates. Geen internet?</string>
<string name="root_error">Geroot, maar geen root-permissie. Niet toegestaan?</string>
<string name="not_rooted">Niet geroot</string>
<string name="safetyNet_check_text">Tik om SafetyNet controle te starten</string>
<string name="checking_safetyNet_status">SafetyNet status controleren…</string>
<string name="safetyNet_check_success">SafetyNet controle succesvol</string>
<string name="safetyNet_api_error">SafetyNet API fout</string>
<string name="safetyNet_network_loss">Netwerkverbinding verloren</string>
<string name="safetyNet_service_disconnected">Service is beëindigd</string>
<string name="safetyNet_res_invalid">Reactie is ongeldig</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Kan niet auto-detecteren)</string>
<string name="boot_image_title">Boot image locatie</string>
<string name="detect_button">Detecteren</string>
<string name="advanced_settings_title">Geavanceerde instellingen</string>
<string name="keep_force_encryption">Behoud afgedwongen versleuteling</string>
<string name="keep_dm_verity">Behoud dm-verity</string>
<string name="current_magisk_title">Geïnstalleerde Magisk versie: %1$s</string>
<string name="install_magisk_title">Recentste Magisk versie: %1$s</string>
<string name="current_magisk_title">Geïnstalleerde versie: %1$s</string>
<string name="install_magisk_title">Recentste versie: %1$s</string>
<string name="uninstall">Deïnstalleren</string>
<string name="uninstall_magisk_title">Magisk deïnstalleren</string>
<string name="uninstall_magisk_msg">Alle modules worden uitgeschakeld/verwijderd. Root wordt verwijderd, en je data wordt mogelijk versleuteld als deze dat momenteel niet is</string>
@@ -55,7 +49,7 @@
<string name="not_installed">Niet geïnstalleerd</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Opslaan op SD-kaart</string>
<string name="menuSaveLog">Opslaan log</string>
<string name="menuReload">Herladen</string>
<string name="menuClearLog">Log nu wissen</string>
<string name="logs_cleared">Log succesvol gewist</string>
@@ -84,8 +78,6 @@
<string name="repo_install_msg">Zeker weten %1$s installeren?</string>
<string name="download">Downloaden</string>
<string name="download_file_error">Fout tijdens downloaden</string>
<string name="install_error">Installatiefout!</string>
<string name="invalid_zip">De zip is geen Magisk module!</string>
<string name="reboot">Herstarten</string>
<string name="downloading_toast">%1$s downloaden</string>
<string name="magisk_update_title">Nieuwe Magisk update beschikbaar!</string>
@@ -99,13 +91,13 @@
<string name="zip_download_msg">Zip-bestand downloaden (%1$d%%) …</string>
<string name="zip_process_title">Verwerken</string>
<string name="zip_process_msg">Zip-bestand verwerken…</string>
<string name="manual_boot_image">Gelieve handmatig een boot image te selecteren!</string>
<string name="manager_update_title">Nieuwe Magisk Manager update beschikbaar!</string>
<string name="manager_download_install">Tik om te downloaden en installeren</string>
<string name="magisk_updates">Magisk updates</string>
<string name="flashing">Flashen</string>
<string name="hide_manager_toast">Magisk Manager verbergen…</string>
<string name="hide_manager_fail_toast">Magisk Manager verbergen mislukt…</string>
<string name="hide_manager_toast2">Dit kan even duren…</string>
<string name="download_zip_only">Alleen zip downloaden</string>
<string name="patch_boot_file">Boot image-bestand patchen</string>
<string name="direct_install">Direct installeren (aangeraden)</string>
@@ -118,6 +110,8 @@
<string name="restore_done">Herstel voltooid!</string>
<string name="restore_fail">Originele back-up bestaat niet!</string>
<string name="uninstall_toast">Magisk Manager wordt over 5 seconden verwijderd, hierna handmatig herstarten aub</string>
<string name="proprietary_title">Google\'s code downloaden</string>
<string name="proprietary_notice">Magisk Manager is FOSS, dus bevat geen SafetyNet API code van Google.\n\nSta je Magisk Manager toe om een extensie te downloaden (bevat GoogleApiClient) voor SafetyNet controles?</string>
<!--Settings Activity -->
<string name="settings_general_category">Algemeen</string>
@@ -128,7 +122,7 @@
<string name="settings_clear_cache_title">Opslagcache wissen</string>
<string name="settings_clear_cache_summary">Wis de gecachte informatie voor online opslagplaatsen. Dit dwingt de app om online te verversen</string>
<string name="settings_hide_manager_title">Magisk Manager verbergen</string>
<string name="settings_hide_manager_summary">Magisk Manager tijdelijk verbergen.\nDit installeert een nieuwe app genaamd \"Unhide Magisk Manager\"</string>
<string name="settings_hide_manager_summary">Magisk Manager opnieuw inpakken met een willekeurige pakketnaam</string>
<string name="language">Taal</string>
<string name="system_default">(Systeem standaard)</string>
<string name="settings_update">Instellingen bijwerken</string>
@@ -137,7 +131,6 @@
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Gepatchte boot uitvoerformaat</string>
<string name="settings_boot_format_summary">Kies het formaat van de boot image uitvoer.\nKies .img om via fastboot/downloadmodus te flashen; kies .img.tar om via ODIN te flashen.</string>
<string name="settings_core_only_title">Magisk basismodus</string>
<string name="settings_core_only_summary">Alleen kernfuncties inschakelen. Alle modules worden niet geladen. MagiskSU, MagiskHide, en systeemloze hosts blijven ingeschakeld</string>
<string name="settings_magiskhide_summary">Magisk van verschillende detecties verbergen</string>
@@ -183,7 +176,7 @@
<string name="deny">Weigeren</string>
<string name="prompt">Prompt</string>
<string name="grant">Toestaan</string>
<string name="su_warning">Verleent volledige toegang aan je apparaat.\nWeigeren als je het niet zeker weet!</string>
<string name="su_warning">Verleent volledige toegang tot je apparaat.\nWeigeren als je het niet zeker weet!</string>
<string name="forever">Altijd</string>
<string name="once">Eénmalig</string>
<string name="tenmin">10 min</string>

View File

@@ -17,26 +17,20 @@
<string name="checking_for_updates">Sprawdzanie aktualizacji…</string>
<string name="magisk_update_available">Magisk v%1$s dostępny!</string>
<string name="cannot_check_updates">Nie można sprawdzić dostępności aktualizacji, brak internetu</string>
<string name="root_error">Root dostępny, ale dostęp nie przyznany</string>
<string name="not_rooted">Brak Roota</string>
<string name="safetyNet_check_text">Dotknij aby sprawdzić SafetyNet</string>
<string name="checking_safetyNet_status">Sprawdzanie statusu SafetyNet…</string>
<string name="safetyNet_check_success">Sprawdzanie SafetyNet z Powodzeniem</string>
<string name="safetyNet_network_loss">Brak połączenia z internetem</string>
<string name="safetyNet_api_error">Bład SafetyNet API</string>
<string name="safetyNet_network_loss">Brak połączenia z internetem</string>
<string name="safetyNet_service_disconnected">Usługa została zamknięta</string>
<string name="safetyNet_res_invalid">Usługa nie odpowiada</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Nie można automatycznie wykryć)</string>
<string name="boot_image_title">Lokalizacja Boot Image</string>
<string name="detect_button">Wykryj</string>
<string name="advanced_settings_title">Zaawansowane Ustawienia</string>
<string name="keep_force_encryption">Keep force encryption</string>
<string name="keep_dm_verity">Keep dm-verity</string>
<string name="current_magisk_title">Zainstalowana Wersja Magisk: %1$s</string>
<string name="install_magisk_title">Ostatnia Wersja Magisk: %1$s</string>
<string name="current_magisk_title">Zainstalowana Wersja: %1$s</string>
<string name="install_magisk_title">Ostatnia Wersja: %1$s</string>
<string name="uninstall">Odinstaluj</string>
<string name="uninstall_magisk_title">Odinstaluj Magisk</string>
<string name="uninstall_magisk_msg">Wszystkie moduły będą wyłączone/usunięte.Root zostanie usunięty i przywrócone szyfrowanie danych, jeśli nie są te dane obecnie szyfrowane</string>
@@ -58,7 +52,7 @@
<string name="not_installed">Nie zainstalowany</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Zapisz na SD</string>
<string name="menuSaveLog">Zapisz log</string>
<string name="menuReload">Załaduj ponownie</string>
<string name="menuClearLog">Wyczyść Log</string>
<string name="logs_cleared">Log wyczyszczony</string>
@@ -87,8 +81,6 @@
<string name="repo_install_msg">Czy chcesz zainstalować %1$s ?</string>
<string name="download">Pobierz</string>
<string name="download_file_error">Błąd pobierania pliku</string>
<string name="install_error">Błąd instalacji!</string>
<string name="invalid_zip">Ten zip nie jest Modułem Magisk!!</string>
<string name="reboot">Restart</string>
<string name="downloading_toast">Pobieranie %1$s</string>
<string name="magisk_update_title">Nowa Wersja Magisk Dostępna!</string>
@@ -102,13 +94,15 @@
<string name="zip_download_msg">Pobieranie pliku zip (%1$d%%) …</string>
<string name="zip_process_title">Przetwarzanie</string>
<string name="zip_process_msg">Przetwarzanie pliku zip …</string>
<string name="manual_boot_image">Proszę ręcznie wybrać boot image!</string>
<string name="manager_update_title">Nowa Wersja Magisk Manager Jest Dostępna!</string>
<string name="manager_download_install">Naciśnij aby pobrać i zainstalować</string>
<string name="dtbo_patched_title">DTBO został wgrany!</string>
<string name="dtbo_patched_reboot">Magisk Manager wgrał dtbo.img, uruchom ponownie</string>
<string name="magisk_updates">Aktualizacja Magisk</string>
<string name="flashing">Flashowanie</string>
<string name="hide_manager_toast">Ukryj Magisk Manager…</string>
<string name="hide_manager_fail_toast">Błąd ukrycia Magisk Manager</string>
<string name="hide_manager_toast2">To może chwilę potrwać…</string>
<string name="hide_manager_fail_toast">Błąd Menadżera Hide Magisk</string>
<string name="download_zip_only">Pobierz Tylko Zip</string>
<string name="patch_boot_file">Patchowanie Pliku Boot Image</string>
<string name="direct_install">Bezpośrednia instalacja (Zalecane)</string>
@@ -118,11 +112,13 @@
<string name="boot_file_patch_msg">Wybierz stock boot image w formacie .img lub .img.tar</string>
<string name="complete_uninstall">Odinstalowywanie Zakończone</string>
<string name="restore_stock_boot">Przywróć Stockowy Boot</string>
<string name="restore_done">Przywracanie zakonczone!</string>
<string name="restore_done">Przywracanie zakończone!</string>
<string name="restore_fail">Stock backup nie istnieje!</string>
<string name="uninstall_toast">Odinstalowanie Magisk Manager w ciągu 5 sekund, proszę następnie ręcznie ponownie uruchomić urządzenie</string>
<!--Settings Activity -->
<string name="proprietary_title">Pobierz Własny Kod</string>
<string name="proprietary_notice">Magisk Manager to FOSS, więc nie zawiera zastrzeżonego kodu API SafetyNet. \n\nCzy zezwolić Magisk Managerowi na pobranie rozszerzenia (zawierającego GoogleApiClient) do sprawdzeń SafetyNet?</string>
<!--Settings Activity -->
<string name="settings_general_category">Ogólne</string>
<string name="settings_dark_theme_title">Ciemny Motyw</string>
<string name="settings_dark_theme_summary">Włącz ciemny motyw</string>
@@ -131,17 +127,16 @@
<string name="settings_clear_cache_title">Wyczyść Pamięć Repozytorium</string>
<string name="settings_clear_cache_summary">Wymusza na aplikacji odświeżenie online repozytorium</string>
<string name="settings_hide_manager_title">Ukryj Magisk Manager</string>
<string name="settings_hide_manager_summary">Tymczasowo ukryj Magisk Manager.\nSpowoduje to zainstalowanie nowej aplikacji o nazwie \"Pokaż Magisk Manager\"</string>
<string name="language">Język</string>
<string name="settings_hide_manager_summary">Przepakowanie Magisk Manager z losową nazwą pakietu</string>
<string name="language">Język</string>
<string name="system_default">(Domyślny Systemu)</string>
<string name="settings_update">Aktualizacja Ustawień</string>
<string name="settings_update_channel_title">Aktualizacja Kanału</string>
<string name="settings_update_stable">Stabilna</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_boot_format_title">Poprawiony format wyjścia rozruchowego</string>
<string name="settings_boot_format_summary">Wybierz format wyjściowy pliku boot image.\nWybierz .img do programu za pośrednictwem fastboot/download mode; wybierz .img.tar za pomocą ODINA.</string>
<string name="settings_core_only_title">Tylko Tryb Rdzeni Magisk</string>
<string name="settings_boot_format_title">Poprawny format wyjścia rozruchowego</string>
<string name="settings_boot_format_summary">Wybierz format pliku boot image.\nWybierz .img dla wgrywania poprzez Fastboot/Download Mode; wybierz .img.tar dla ODINA.</string>
<string name="settings_core_only_title">Tylko Tryb Rdzeni Magisk</string>
<string name="settings_core_only_summary">Włącz tylko podstawowe funkcje, wszystkie moduły nie zostaną załadowane. MagiskSU, MagiskHide i systemless hosts nadal będą włączone</string>
<string name="settings_magiskhide_summary">Włącz Hide Magisk dla wykrytych aplikacji</string>
<string name="settings_hosts_title">Włącz systemless hosts</string>
@@ -172,7 +167,7 @@
<string name="user_indepenent_summary">Każdy użytkownik ma swoje własne odrębne ustawienia dostępu</string>
<string name="multiuser_hint_owner_request">Żądanie zostało wysłane do właściciela urządzenia. Proszę przejść do właściciela i udzielić pozwolenia</string>
<string name="mount_namespace_mode">Montuj Tryb Nazw</string>
<string name="mount_namespace_mode">Montuj Tryb Odstępu Nazw</string>
<string name="settings_ns_global">Globalna Nazwa</string>
<string name="settings_ns_requester">Dziedziczenie Nazw</string>
<string name="settings_ns_isolate">Izolacja Nazw</string>

View File

@@ -17,9 +17,6 @@
<string name="checking_for_updates">Checando por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="cannot_check_updates">Não é possível verificar se há atualizações</string>
<string name="root_error">Rooteado mas sem permissão de root, o acesso foi permitido?</string>
<string name="not_rooted">Sem root</string>
<string name="safetyNet_check_text">Pressione para checar o SafetyNet</string>
<string name="checking_safetyNet_status">Verificando status do SafetyNet…</string>
<string name="safetyNet_check_success">SafetyNet verificado</string>
@@ -29,15 +26,11 @@
<string name="safetyNet_res_invalid">A resposta é inválida</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Não foi auto detectado)</string>
<string name="boot_image_title">Local da Boot Image</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Configurações avançadas</string>
<string name="keep_force_encryption">Keep force encryption</string>
<string name="keep_dm_verity">Keep dm-verity</string>
<string name="current_magisk_title">Versão instalada do Magisk: %1$s</string>
<string name="install_magisk_title">Última versão do Magisk: %1$s</string>
<string name="current_magisk_title">Versão instalada: %1$s</string>
<string name="install_magisk_title">Última versão: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="uninstall_magisk_msg">Todos os modulos magisk será desativado/removido. O root será removido, e possivelmente a encriptação de seus dados se seus dados não foram encriptado.</string>
@@ -59,7 +52,7 @@
<string name="not_installed">Não Instalado</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Salvar no SD</string>
<string name="menuSaveLog">Salvar registro</string>
<string name="menuReload">Recarregar</string>
<string name="menuClearLog">Limpar registro agora</string>
<string name="logs_cleared">Registro limpado com sucesso</string>
@@ -88,8 +81,6 @@
<string name="repo_install_msg">Você deseja instalar%1$s ?</string>
<string name="download">Baixar</string>
<string name="download_file_error">Erro ao baixar o arquivo</string>
<string name="install_error">Erro na instalação!</string>
<string name="invalid_zip">O zip não é um Módulo Magisk!!</string>
<string name="reboot">Reiniciar</string>
<string name="downloading_toast">Baixando %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
@@ -103,8 +94,7 @@
<string name="zip_download_msg">Baixando o arquivo zip (%1$d%%) …</string>
<string name="zip_process_title">Processando</string>
<string name="zip_process_msg">Processando arquivo zip …</string>
<string name="manual_boot_image">Por Favor, selecione manualmente a Boot Image</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="manager_download_install">Pressione para baixar e instalar</string>
<string name="magisk_updates">Atualizações do Magisk</string>
<string name="flashing">Flasheando</string>
@@ -134,7 +124,6 @@
<string name="settings_clear_cache_title">Limpar Repo Cache</string>
<string name="settings_clear_cache_summary">Limpe as informações armazenadas em cache para repos. online, forçando o aplicativo a atualizar online</string>
<string name="settings_hide_manager_title">Ocultar Magisk Manager</string>
<string name="settings_hide_manager_summary">Oculta temporariamente o Magisk Manager.\nIsso irá instalar um novo aplicativo chamado \"Unhide Magisk Manager\"</string>
<string name="language">Linguagem</string>
<string name="system_default">(Padrão do Sistema)</string>
<string name="settings_update">Atualizar Configurações</string>

View File

@@ -2,41 +2,35 @@
<!--Universal-->
<!--Welcome Activity-->
<string name="modules">Módulos</string>
<string name="modules">Módulos</string>
<string name="downloads">Transferir</string>
<string name="superuser">Super-Utilizador</string>
<string name="superuser">root</string>
<string name="log">Registo</string>
<string name="settings">Definições</string>
<string name="install">Instalar</string>
<string name="install">Instalar</string>
<!--Status Fragment-->
<string name="magisk_version_error">Magisk não instalado</string>
<string name="magisk_version_error">Magisk não instalado</string>
<string name="checking_for_updates">A procurar por atualizações…</string>
<string name="magisk_update_available">Magisk v%1$s disponível!</string>
<string name="cannot_check_updates">Não foi possível verificar atualizações, sem internet?</string>
<string name="root_error">Com root mas sem permissão de root, o acesso foi permitido?</string>
<string name="not_rooted">Sem root</string>
<string name="safetyNet_check_text">Pressione para verificar SafetyNet</string>
<string name="checking_safetyNet_status">A verificar o estado do SafetyNet…</string>
<string name="safetyNet_check_success">SafetyNet verificado com sucesso</string>
<string name="safetyNet_network_loss">Perda de ligação</string>
<string name="safetyNet_api_error">Erro na API SafetyNet</string>
<string name="safetyNet_network_loss">Perda de ligação</string>
<string name="safetyNet_service_disconnected">Serviço foi interrompido</string>
<string name="safetyNet_res_invalid">A resposta é inválida</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Não foi auto detetado)</string>
<string name="boot_image_title">Local da Imagem de Arranque</string>
<string name="detect_button">Detectar</string>
<string name="advanced_settings_title">Definições avançadas</string>
<!--Install Fragment-->
<string name="advanced_settings_title">Definições avançadas</string>
<string name="keep_force_encryption">Manter encriptação forçada</string>
<string name="keep_dm_verity">Manter dm-verity</string>
<string name="current_magisk_title">Versão instalada do Magisk: %1$s</string>
<string name="install_magisk_title">Última versão do Magisk: %1$s</string>
<string name="current_magisk_title">Versão instalada: %1$s</string>
<string name="install_magisk_title">Última versão: %1$s</string>
<string name="uninstall">Desinstalar</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="update">Atualizar %1$s</string>
<string name="uninstall_magisk_title">Desinstalar Magisk</string>
<string name="update">Atualizar %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Nenhuma informação fornecida)</string>
@@ -48,13 +42,13 @@
<string name="disable_file_removed">Módulo será ativado depois de reiniciar</string>
<string name="author">Criado por %1$s</string>
<!--Repo Fragment-->
<!--Repo Fragment-->
<string name="update_available">Atualização disponível</string>
<string name="installed">Instalado</string>
<string name="not_installed">Não Instalado</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Gravar no SD</string>
<string name="menuSaveLog">Gravar registo</string>
<string name="menuReload">Recarregar</string>
<string name="menuClearLog">Limpar registo agora</string>
<string name="logs_cleared">Registo limpo com sucesso</string>
@@ -80,28 +74,35 @@
<string name="close">Fechar</string>
<string name="repo_install_title">Instalar %1$s</string>
<string name="repo_install_msg">Deseja instalar%1$s agora?</string>
<string name="download">Transferir</string>
<string name="download_file_error">Erro ao transferir ficheiro</string>
<string name="install_error">Erro na instalação!</string>
<string name="invalid_zip">Este zip não é um Módulo Magisk!!</string>
<string name="download">Transferir</string>
<string name="download_file_error">Erro ao transferir ficheiro</string>
<string name="reboot">Reiniciar</string>
<string name="zip_process_msg">A processar ficheiro zip …</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="downloading_toast">A transferir %1$s</string>
<string name="magisk_update_title">Nova atualização do Magisk disponível!</string>
<string name="settings_reboot_toast">Reinicie para aplicar definições</string>
<string name="release_notes">Notas da atualização</string>
<string name="repo_cache_cleared">Cache do repositório apagado</string>
<string name="safetyNet_hide_notice">Esta aplicação usa SafetyNet
\nJá manipulado pelo MagiskHide por padrão</string>
<string name="process_error">Erro no processo</string>
<string name="process_error">Erro no processo</string>
<string name="internal_storage">O zip foi guardado em:
\n[Armazenamento interno]%1$s</string>
<string name="zip_download_msg">A transferir ficheiro zip (%1$d%%) …</string>
<string name="zip_process_title">A processar</string>
<string name="manual_boot_image">Por Favor, selecione manualmente a imagem de Arranque</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="zip_process_msg">A processar ficheiro zip …</string>
<string name="manager_update_title">Nova atualização do Magisk Manager disponível!</string>
<string name="manager_download_install">Pressione para transferir e instalar</string>
<string name="magisk_updates">Atualizações do Magisk</string>
<string name="flashing">A instalar</string>
<string name="hide_manager_toast">A esconder Magisk Manager…</string>
<string name="hide_manager_toast2">Isto pode demorar algum tempo...</string>
<string name="hide_manager_fail_toast">Falha ao esconder Magisk Manager…</string>
<string name="download_zip_only">Transferir Apenas Ficheiro Zip</string>
<string name="patch_boot_file">Patch a Imagem de Arranque</string>
<string name="direct_install">Instalar Diretamente (Recomendado)</string>
<string name="select_method">Selecionar Método</string>
<string name="complete_uninstall">Desinstalação Completa</string>
<string name="restore_done">Restauração feita!</string>
<!--Settings Activity -->
<string name="settings_general_category">Geral</string>
@@ -111,13 +112,15 @@
<string name="settings_notification_summary">Mostrar notificações de atualização quando a nova versão estiver disponível</string>
<string name="settings_clear_cache_title">Apagar Cache de Repositório</string>
<string name="settings_clear_cache_summary">Apaga a informação cache de repositórios online. online, forçando a aplicação a atualizar online</string>
<string name="settings_hide_manager_title">Esconder Magisk Manager</string>
<string name="language">Língua</string>
<string name="system_default">(Padrão do Sistema)</string>
<string name="settings_update_stable">Estável</string>
<string name="settings_update_beta">Beta</string>
<string name="settings_core_only_title">Magisk somente em Modo Core</string>
<string name="settings_core_only_summary">Ativar somente funcionalidades principais, todos os módulos não serão carregados. MagiskSU, MagiskHide, e systemless hosts ainda estará ativado</string>
<string name="settings_magiskhide_summary">Oculta Magisk de várias deteções</string>
<string name="settings_hosts_title">Ativar systemless hosts</string>
<string name="settings_hosts_title">Ativar systemless hosts</string>
<string name="settings_hosts_summary">Suporte de systemless para aplicações Adblock</string>
<string name="settings_su_app_adb">Aplicações e ADB</string>
@@ -128,13 +131,13 @@
<string name="settings_su_request_20">20 segundos</string>
<string name="settings_su_request_30">30 segundos</string>
<string name="settings_su_request_60">60 segundos</string>
<string name="superuser_access">Acesso de Super-Utilizador</string>
<string name="superuser_access">Acesso de root</string>
<string name="auto_response">Resposta Automática</string>
<string name="request_timeout">Tempo limite de solicitação</string>
<string name="superuser_notification">Notificação de Super-Utilizador</string>
<string name="superuser_notification">Notificação de root</string>
<string name="request_timeout_summary">%1$s segundos</string>
<string name="settings_su_reauth_title">Autenticar novamente após atualizar</string>
<string name="settings_su_reauth_summary">Autenticar novamente permissões de Super-Utilizador após atualizar aplicações</string>
<string name="settings_su_reauth_summary">Autenticar novamente permissões de root após atualizar aplicações</string>
<string name="multiuser_mode">Modo Multi-Utilizador</string>
<string name="settings_owner_only">Apenas Proprietário de Dispositivo</string>
@@ -153,8 +156,8 @@
<string name="requester_summary">As sessões de root herdarão a identificação do seu solicitante</string>
<string name="isolate_summary">Cada sessão root terá sua própria identificação isolada</string>
<!--Superuser-->
<string name="su_request_title">Pedido de Super-Utilizador</string>
<!--Superuser-->
<string name="su_request_title">Pedido de root</string>
<string name="deny_with_str">Negar%1$s</string>
<string name="deny">Negar</string>
<string name="prompt">Perguntar</string>
@@ -167,11 +170,11 @@
<string name="twentymin">20 minutos</string>
<string name="thirtymin">30 minutos</string>
<string name="sixtymin">60 minutos</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de Super-Utilizador</string>
<string name="su_deny_toast">%1$s foi negado o acesso de Super-Utilizador</string>
<string name="su_allow_toast">%1$s foi permitido o acesso de root</string>
<string name="su_deny_toast">%1$s foi negado o acesso de root</string>
<string name="no_apps_found">Não foram encontrados aplicações</string>
<string name="su_snack_grant">Acesso de Super-Utilizador a %1$s foi permitido</string>
<string name="su_snack_deny">Acesso de Super-Utilizador a %1$s foi negado</string>
<string name="su_snack_grant">Acesso de root a %1$s foi permitido</string>
<string name="su_snack_deny">Acesso de root a %1$s foi negado</string>
<string name="su_snack_notif_on">Notificações de %1$s está ativado</string>
<string name="su_snack_notif_off">Notificações da %1$s está desativado</string>
<string name="su_snack_log_on">Registo de %1$s está ativado</string>

View File

@@ -12,22 +12,15 @@
<string name="checking_for_updates">Verificare actualizări…</string>
<string name="magisk_update_available">Magisk v%1$s disponibil!</string>
<string name="cannot_check_updates">Nu se pot verifica actualizările, nu este internet?</string>
<string name="root_error">Root obţinut, dar fără permisiune root, nu este permis?</string>
<string name="not_rooted">Nu este obţinut root</string>
<string name="safetyNet_check_text">Verificare SafetyNet</string>
<string name="checking_safetyNet_status">Verificarea stării SafetyNet…</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Nu se poate detecta automat)</string>
<string name="boot_image_title">Locaţie imagine Boot</string>
<string name="detect_button">Detectare</string>
<string name="advanced_settings_title">Setări avansate</string>
<string name="keep_force_encryption">Păstrare criptare forţată</string>
<string name="keep_dm_verity">Păstrare dm-verity</string>
<string name="current_magisk_title">Versiune Magisk instalată: %1$s</string>
<string name="install_magisk_title">Ultima versiune Magisk: %1$s</string>
<string name="current_magisk_title">Versiune instalată: %1$s</string>
<string name="install_magisk_title">Ultima versiune: %1$s</string>
<string name="uninstall">Dezinstalare</string>
<string name="uninstall_magisk_title">Dezinstalare Magisk</string>
<string name="update">Actualizare %1$s</string>
@@ -49,7 +42,7 @@
<string name="not_installed">Nu este instalat</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Salvare pe cardul SD</string>
<string name="menuSaveLog">Salvare jurnal</string>
<string name="menuReload">Reîncărcare</string>
<string name="menuClearLog">Șterge jurnal acum</string>
<string name="logs_cleared">Jurnal şters</string>
@@ -78,8 +71,6 @@
<string name="repo_install_msg">Instalaţi %1$s?</string>
<string name="download">Descărcare</string>
<string name="download_file_error">Eroare la descărcarea fișierului</string>
<string name="install_error">Eroare de instalare!</string>
<string name="invalid_zip">Zip-ul nu este un modul Magisk!</string>
<string name="reboot">Repornire</string>
<string name="zip_process_msg">Procesare fişierului zip…</string>
<string name="downloading_toast">Descărcare %1$s</string>
@@ -91,7 +82,6 @@
<string name="process_error">Eroare de proces</string>
<string name="internal_storage">Zip stocat în:\n[Stocare internă]%1$s</string>
<string name="zip_process_title">Procesare</string>
<string name="manual_boot_image">Selectați manual o imagine de boot!</string>
<string name="manager_update_title">O nouă actualizare pentru Magisk Manager este disponibilă!</string>
<string name="manager_download_install">Apăsați pentru a descărca și instala</string>
<string name="magisk_updates">Actualizări Magisk</string>
@@ -108,7 +98,6 @@
<string name="settings_clear_cache_title">Eliminare cache</string>
<string name="settings_clear_cache_summary">Ștergeți informațiile memorate în cache, forțează actualizarea aplicației online</string>
<string name="settings_hide_manager_title">Ascundeţi Magisk Manager</string>
<string name="settings_hide_manager_summary">Ascundeţi temporar Magisk Manager.\nAceasta va instala o nouă aplicație numită \"Unhide Magisk Manager\"</string>
<string name="language">Limbă</string>
<string name="system_default">(Implicit)</string>

View File

@@ -14,9 +14,6 @@
<string name="checking_for_updates">Проверка обновлений…</string>
<string name="magisk_update_available">Доступен Magisk v%1$s!</string>
<string name="cannot_check_updates">Невозможно проверить наличие обновлений</string>
<string name="root_error">Root присутствует, но отсутствует разрешение</string>
<string name="not_rooted">Root отсутствует</string>
<string name="safetyNet_check_text">Проверить статус SafetyNet</string>
<string name="checking_safetyNet_status">Проверка статуса SafetyNet…</string>
<string name="safetyNet_check_success">Проверка SafetyNet пройдена</string>
@@ -26,15 +23,11 @@
<string name="safetyNet_res_invalid">Некорректный ответ</string>
<!--Install Fragment-->
<string name="auto_detect">(Авто) %1$s</string>
<string name="cannot_auto_detect">(Автоопределение невозможно)</string>
<string name="boot_image_title">Расположение boot-образа</string>
<string name="detect_button">Определить</string>
<string name="advanced_settings_title">Расширенные настройки</string>
<string name="keep_force_encryption">Оставить принуд. шифрование</string>
<string name="keep_dm_verity">Оставить dm-verity</string>
<string name="current_magisk_title">Текущая версия Magisk: %1$s</string>
<string name="install_magisk_title">Последняя версия Magisk: %1$s</string>
<string name="current_magisk_title">Текущая версия: %1$s</string>
<string name="install_magisk_title">Последняя версия: %1$s</string>
<string name="uninstall">Удалить</string>
<string name="uninstall_magisk_title">Удалить Magisk</string>
<string name="uninstall_magisk_msg">Все модули были отключены либо удалены. Root-доступ будет удален, данные зашифруются, если до сих пор не были зашифрованы</string>
@@ -56,7 +49,7 @@
<string name="not_installed">Не установлен</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Сохранить на карту памяти</string>
<string name="menuSaveLog">"Сохранить историю "</string>
<string name="menuReload">Обновить</string>
<string name="menuClearLog">Очистить историю сейчас</string>
<string name="logs_cleared">История успешно очищена</string>
@@ -85,8 +78,6 @@
<string name="repo_install_msg">Желаете установить %1$s ?</string>
<string name="download">Скачать</string>
<string name="download_file_error">Ошибка скачивания файла</string>
<string name="install_error">Ошибка во время установки!</string>
<string name="invalid_zip">В архив отсутствует модуль Magisk!</string>
<string name="reboot">Перезагрузка</string>
<string name="downloading_toast">Скачивание %1$s</string>
<string name="magisk_update_title">Доступно новое обновление Magisk!</string>
@@ -100,12 +91,12 @@
<string name="zip_download_msg">Загрузка архива (%1$d%%) …</string>
<string name="zip_process_title">Обработка</string>
<string name="zip_process_msg">Обработка архива…</string>
<string name="manual_boot_image">Пожалуйста, выберите вручную boot-образ!</string>
<string name="manager_update_title">Доступно новое обновление менеджера Magisk!</string>
<string name="manager_download_install">Нажмите, чтобы скачать и установить</string>
<string name="magisk_updates">Обновления Magisk</string>
<string name="flashing">Прошивка…</string>
<string name="hide_manager_toast">Скрытие Менеджера Magisk…</string>
<string name="hide_manager_toast2">Может занять некоторое время…</string>
<string name="hide_manager_fail_toast">Скрытие Менеджера Magisk неудачно…</string>
<string name="download_zip_only">Загрузка только архива</string>
<string name="patch_boot_file">Пропатчить boot-образ</string>
@@ -129,9 +120,9 @@
<string name="settings_notification_title">Уведомление об обновлении</string>
<string name="settings_notification_summary">Показывать уведомления об обновлении, когда доступна новая версия</string>
<string name="settings_clear_cache_title">Очистка кеша</string>
<string name="settings_clear_cache_summary">Очистить сохранённую информацию о сетевых репозиториях, заставляя приложение принудительно обновляться через Интернете</string>
<string name="settings_clear_cache_summary">Очистить сохранённую информацию о сетевых репозиториях, заставляя приложение принудительно обновляться через Интернет</string>
<string name="settings_hide_manager_title">Скрыть Менеджер Magisk</string>
<string name="settings_hide_manager_summary">Временно скрывает Менеджер Magisk.\nБудет установлено новое приложение, называется \"Unhide Magisk Manager\"</string>
<string name="settings_hide_manager_summary">Пересобрать менеджер Magisk с случайным именем пакета</string>
<string name="language">Язык</string>
<string name="system_default">По умолчанию (системный)</string>
<string name="settings_update">Настройки обновления</string>

View File

@@ -14,9 +14,6 @@
<string name="checking_for_updates">Söker efter uppdateringar…</string>
<string name="magisk_update_available">Magisk v%1$s tillgänglig!</string>
<string name="cannot_check_updates">Kan inte söka efter uppdateringar, inget internet?</string>
<string name="root_error">Rootad men inga root-rättigheter, inte tillåtet?</string>
<string name="not_rooted">Inte rootad</string>
<string name="safetyNet_check_text">Tryck för att starta SafetyNet-kontroll</string>
<string name="checking_safetyNet_status">Kontrollerar SafetyNet-status…</string>
<string name="safetyNet_check_success">SafetyNet-kontroll lyckades</string>
@@ -25,15 +22,11 @@
<string name="safetyNet_res_invalid">Svaret är ogiltigt</string>
<!--Install Fragment-->
<string name="auto_detect">(Auto) %1$s</string>
<string name="cannot_auto_detect">(Det går inte att auto-detektera)</string>
<string name="boot_image_title">Boot-image plats</string>
<string name="detect_button">Detektera</string>
<string name="advanced_settings_title">Advancerade inställningar</string>
<string name="keep_force_encryption">Fortsätt tvinga kryptering</string>
<string name="keep_dm_verity">Behåll dm-verity</string>
<string name="current_magisk_title">Installerad Magisk: %1$s</string>
<string name="install_magisk_title">Senaste Magisk: %1$s</string>
<string name="current_magisk_title">Installerad: %1$s</string>
<string name="install_magisk_title">Senaste: %1$s</string>
<string name="uninstall">Avinstallera</string>
<string name="uninstall_magisk_title">Avinstallera Magisk</string>
<string name="update">Uppdatera %1$s</string>
@@ -54,7 +47,7 @@
<string name="not_installed">Inte installerad</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Spara till SD-kort</string>
<string name="menuSaveLog">Spara loggen</string>
<string name="menuReload">Uppdatera</string>
<string name="menuClearLog">Rensa loggen</string>
<string name="logs_cleared">Loggen rensad</string>
@@ -83,8 +76,6 @@
<string name="repo_install_msg">Vill du installera %1$s ?</string>
<string name="download">Ladda ner</string>
<string name="download_file_error">Fel vid nerladdning av fil</string>
<string name="install_error">Installation error!</string>
<string name="invalid_zip">ZIP-filen är inte en modul till Magisk!</string>
<string name="reboot">Starta om</string>
<string name="zip_process_msg">Bearbetar ZIP-filen …</string>
<string name="downloading_toast">Laddar ner %1$s</string>
@@ -96,7 +87,6 @@
<string name="process_error">Processfel</string>
<string name="internal_storage">ZIP-filen är sparad i:\n[Internal Storage]%1$s</string>
<string name="zip_process_title">Arbetar</string>
<string name="manual_boot_image">Välj manuellt en boot-image!</string>
<string name="manager_update_title">En uppdatering av Magisk maneger finns tillgänglig!</string>
<string name="manager_download_install">Tryck för att ladda ner och installera</string>
<string name="magisk_updates">Magiska uppdateringar</string>

View File

@@ -13,9 +13,6 @@
<string name="checking_for_updates">Güncelleştirmeler denetleniyor…</string>
<string name="magisk_update_available">Magisk v%1$s mevcut!</string>
<string name="cannot_check_updates">Güncelleştirmeler denetlenemiyor, İnternet bağlantınız yok mu?</string>
<string name="root_error">Kök erişimli ama kök erişimi izni yok, izin verilmedi mi?</string>
<string name="not_rooted">Kök erişimli değil</string>
<string name="safetyNet_check_text">SafetyNet kontrolünü başlatmak için dokunun</string>
<string name="checking_safetyNet_status">SafetyNet durumu kontrol ediliyor…</string>
<string name="safetyNet_check_success">SafetyNet Kontrolü Başarılı</string>
@@ -24,15 +21,11 @@
<string name="safetyNet_res_invalid">Yanıt geçersiz</string>
<!--Install Fragment-->
<string name="auto_detect">(Otomatik) %1$s</string>
<string name="cannot_auto_detect">(Otomatik algılanamıyor)</string>
<string name="boot_image_title">Önyükleme İmajı Konumu</string>
<string name="detect_button">Algıla</string>
<string name="advanced_settings_title">Gelişmiş Ayarlar</string>
<string name="keep_force_encryption">Şifrelemeyi zorlamayı sürdür</string>
<string name="keep_dm_verity">"Dm-verity\'yi koru"</string>
<string name="current_magisk_title">Yüklenmiş Magisk Sürümü: %1$s</string>
<string name="install_magisk_title">Son Magisk Sürümü: %1$s</string>
<string name="current_magisk_title">Yüklenmiş Sürümü: %1$s</string>
<string name="install_magisk_title">Son Sürümü: %1$s</string>
<string name="uninstall">Kaldır</string>
<string name="uninstall_magisk_title">"Magisk\'i kaldır"</string>
<string name="uninstall_magisk_msg">Tüm modüller devre dışı bırakılacak/kaldırılacaktır. Kök erişimi kaldırılacak ve verileriniz şu anda şifrelenmemişse potansiyel olarak verilerinizi şifrelenecek</string>
@@ -54,7 +47,7 @@
<string name="not_installed">Yüklenmemiş</string>
<!--Log Fragment-->
<string name="menuSaveToSd">"SD Kart\'a kaydet"</string>
<string name="menuSaveLog">Günlüğü kaydet</string>
<string name="menuReload">Yenile</string>
<string name="menuClearLog">Günlüğü temizle</string>
<string name="logs_cleared">Günlük başarıyla temizlendi</string>
@@ -83,8 +76,6 @@
<string name="repo_install_msg">%1$s yüklensin mi?</string>
<string name="download">İndir</string>
<string name="download_file_error">Dosya indirme hatası</string>
<string name="install_error">Yükleme hatası!</string>
<string name="invalid_zip">Zip Magisk Modülü değil!!</string>
<string name="reboot">Yeniden başlat</string>
<string name="downloading_toast">%1$s indiriliyor</string>
<string name="magisk_update_title">Yeni Magisk Güncellemesi Mevcut!</string>
@@ -98,7 +89,6 @@
<string name="zip_download_msg">Zip dosyası indiriliyor (%1$d%%) …</string>
<string name="zip_process_title">İşleniyor</string>
<string name="zip_process_msg">Zip dosyası işleniyor …</string>
<string name="manual_boot_image">Lütfen elle bir boot imajı seçin!</string>
<string name="manager_update_title">Yeni Magisk Manager Güncellemesi Mevcut!</string>
<string name="manager_download_install">İndirmek ve yüklemek için dokunun</string>
<string name="magisk_updates">Magisk Güncellemeleri</string>
@@ -125,7 +115,6 @@
<string name="settings_clear_cache_title">Repo Önbelleğini Temizle</string>
<string name="settings_clear_cache_summary">Çevrimiçi repolar için önbellek bilgilerini temizle, uygulamayı çevrimiçi yenilemeye zorla</string>
<string name="settings_hide_manager_title">Magisk Manager\'ı Gizle</string>
<string name="settings_hide_manager_summary">Magisk Manager\'ı geçici olarak gizle.\nBu, \"Unhide Magisk Manager\" adlı yeni bir uygulama yükleyecektir.</string>
<string name="language">Dil</string>
<string name="system_default">(Sistem Varsayılanı)</string>
<string name="settings_update">Güncelleme Ayarları</string>

View File

@@ -6,8 +6,6 @@
<string name="superuser">Суперкористувач</string>
<string name="log">Логи</string>
<string name="settings">Налаштування</string>
<!--Status Fragment-->
<string name="install">Встановлення</string>
<!--Status Fragment-->
@@ -15,29 +13,24 @@
<string name="checking_for_updates">Перевірка оновлень…</string>
<string name="magisk_update_available">Доступно Magisk v%1$s!</string>
<string name="cannot_check_updates">Неможливо перевірити наявність оновлень</string>
<string name="root_error">Root присутній, але немає дозволу</string>
<string name="not_rooted">Root відсутній</string>
<string name="safetyNet_check_text">Перевірити статус SafetyNet</string>
<string name="checking_safetyNet_status">Перевірка статусу SafetyNet…</string>
<string name="safetyNet_check_success">Перевірку SafetyNet завершено</string>
<string name="safetyNet_api_error">Помилка в API SafetyNet</string>
<string name="safetyNet_network_loss">Підключення до інтернету втрачено</string>
<string name="safetyNet_service_disconnected">Службу зупинено</string>
<string name="safetyNet_res_invalid">Невірна відповідь</string>
<!--Install Fragment-->
<string name="auto_detect">(Авто) %1$s</string>
<string name="cannot_auto_detect">(Автовизначення неможливе)</string>
<string name="boot_image_title">Розташування boot-образу</string>
<string name="detect_button">Визначити</string>
<string name="advanced_settings_title">Розширені налаштування</string>
<string name="keep_force_encryption">Залишити примусове шифрування</string>
<string name="keep_dm_verity">Залишити dm-verity</string>
<string name="current_magisk_title">Поточна версія Magisk: %1$s</string>
<string name="install_magisk_title">Найновіша версія Magisk: %1$s</string>
<string name="current_magisk_title">Поточна версія: %1$s</string>
<string name="install_magisk_title">Найновіша версія: %1$s</string>
<string name="uninstall">Видалити</string>
<string name="uninstall_magisk_title">Видалити Magisk</string>
<string name="uninstall_magisk_msg">Ця дія призведе до видалення всіх модулів, MagiskSU, і може зашифрувати дані, якщо вони не зашифровані.\nВпевнені, що бажаєте продовжити?</string>
<string name="update">Оновити %1$s</string>
<!--Module Fragment-->
<string name="no_info_provided">(Немає наданої інформації)</string>
@@ -48,7 +41,6 @@
<string name="disable_file_created">Модуль вимкнеться при перезавантаженні</string>
<string name="disable_file_removed">Модуль увімкнеться при перезавантаженні</string>
<string name="author">Автор: %1$s</string>
<string name="update">Оновити %1$s</string>
<!--Repo Fragment-->
<string name="update_available">Доступне оновлення</string>
@@ -56,7 +48,7 @@
<string name="not_installed">Не встановлено</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Зберегти на карту пам\'яті</string>
<string name="menuSaveLog">Зберегти логи</string>
<string name="menuReload">Оновити</string>
<string name="menuClearLog">Очистити логи</string>
<string name="logs_cleared">Логи очищено</string>
@@ -85,39 +77,41 @@
<string name="repo_install_msg">Бажаєте встановити %1$s ?</string>
<string name="download">Завантажити</string>
<string name="download_file_error">Помилка завантаження файлу</string>
<string name="install_error">Помилка під час встановлення</string>
<string name="invalid_zip">В архіві відсутній модуль Magisk!</string>
<string name="reboot">Перезавантаження</string>
<string name="zip_process_msg">Опрацювання архіву …</string>
<string name="downloading_toast">Завантаження %1$s</string>
<string name="magisk_update_title">Доступне оновлення Magisk!</string>
<string name="settings_reboot_toast">Для застосування змін перезавантажте пристрій</string>
<string name="release_notes">Особливості версії</string>
<string name="repo_cache_cleared">Кеш репозиторію очищено</string>
<string name="safetyNet_hide_notice">Ця програма використовує SafetyNet.\nВже опрацьовано MagiskHide за замовчуванням</string>
<string name="zip_download_title">Завантаження</string>
<string name="zip_download_msg">Завантаження zip файлу (%1$d%%) …</string>
<string name="process_error">Помилка опрацювання</string>
<string name="internal_storage">Архів розташований:\n[Внутрішнє Сховище]%1$s</string>
<string name="zip_download_title">Завантаження</string>
<string name="zip_download_msg">Завантаження zip файлу (%1$d%%) …</string>
<string name="zip_process_title">Опрацювання</string>
<string name="manual_boot_image">Будь ласка, виберіть boot-образ!</string>
<string name="zip_process_msg">Опрацювання архіву …</string>
<string name="manager_update_title">Доступне оновлення Magisk Manager!</string>
<string name="manager_download_install">Натисніть, щоб завантажити і встановити</string>
<string name="magisk_updates">Оновлення Magisk</string>
<string name="flashing">Прошивання</string>
<string name="hide_manager_toast">Приховування Magisk Manager…</string>
<string name="hide_manager_toast2">Це може зайняти деякий час…</string>
<string name="hide_manager_fail_toast">Не вдалося приховати Magisk Manager…</string>
<string name="download_zip_only">Тільки завантажити</string>
<string name="patch_boot_file">Пропатчити boot образ</string>
<string name="direct_install">Пряме встановлення (рекомендовано)</string>
<string name="install_second_slot">Встановити в Другий Слот (після OTA)</string>
<string name="select_method">Виберіть спосіб</string>
<string name="no_boot_file_patch_support">Цільова версія Magisk не підтримує пропатчування boot образу</string>
<string name="boot_file_patch_msg">Виберіть дамп заводського boot образу в форматі .img чи .img.tar</string>
<string name="boot_file_patch_msg">Виберіть оригінальний дамп boot образу в форматі .img чи .img.tar</string>
<string name="complete_uninstall">Видалення виконано</string>
<string name="restore_stock_boot">Відновити заводський образ</string>
<string name="restore_stock_boot">Відновити оригінальний образ</string>
<string name="restore_done">Відновлення завершено!</string>
<string name="restore_fail">Немає резервної копії заводського boot образу</string>
<string name="restore_fail">Немає резервної копії оригінального boot образу</string>
<string name="uninstall_toast">Видалення Менеджера Magisk протягом 5 секунд, потім, будь ласка, вручну перезавантажте</string>
<string name="proprietary_title">Завантажити пропрієтарний код</string>
<string name="proprietary_notice">Менеджер Magisk - це безкоштовний додаток з відкритим вихідним кодом, тому він не містить пропрієтарний код API SafetyNet від компанії Google.\n\nДозволити Менеджеру Magisk завантажити розширення (яке містить GoogleApiClient) для перевірки SafetyNet?</string>
<!--Settings Activity -->
<string name="settings_general_category">Основні</string>
<string name="settings_dark_theme_title">Темна тема</string>
@@ -127,7 +121,7 @@
<string name="settings_clear_cache_title">Очищення кешу</string>
<string name="settings_clear_cache_summary">Очистити збережену інформацію про мережеві репозиторії, змушуючи програму примусово оновлюватися через Інтернет</string>
<string name="settings_hide_manager_title">Приховати Magisk Manager</string>
<string name="settings_hide_manager_summary">Тимчасово приховати Magisk Manager.\nЦя дія встановить новий додаток \"Unhide Magisk Manager\"</string>
<string name="settings_hide_manager_summary">Перезібрати Менеджер Magisk з випадковим іменем пакету</string>
<string name="language">Мова</string>
<string name="system_default">Стандартна (системна)</string>
<string name="settings_update">Оновити налаштування</string>
@@ -136,7 +130,6 @@
<string name="settings_update_beta">Бета реліз</string>
<string name="settings_boot_format_title">Формат пропатченого образу</string>
<string name="settings_boot_format_summary">Виберіть формат вихідного пропатченого boot образу.\n.img - для прошивання через fastboot/download режим;\n.img.tar - для прошивання через ODIN.</string>
<string name="settings_core_only_title">Режим ядра Magisk</string>
<string name="settings_core_only_summary">Увімкнути тільки можливості ядра, всі модулі не будуть активними. MagiskSU, MagiskHide і позасистемні хости залишуться увімкненими</string>
<string name="settings_magiskhide_summary">Приховати Magisk від різних перевірок</string>

View File

@@ -14,22 +14,15 @@
<string name="checking_for_updates">Đang kiểm tra cập nhật…</string>
<string name="magisk_update_available">Magisk v%1$s available!</string>
<string name="cannot_check_updates">Không thể kiểm tra cập nhật, không có Internet?</string>
<string name="root_error">Đã root nhưng không có quyền root, chưa được cho phép?</string>
<string name="not_rooted">Chưa root</string>
<string name="safetyNet_check_text">Chạm để bắt đầu kiểm tra SafetyNet</string>
<string name="checking_safetyNet_status">Đang kiểm tra trạng thái SafetyNet…</string>
<!--Install Fragment-->
<string name="auto_detect">(Tự động) %1$s</string>
<string name="cannot_auto_detect">(Không thể tự phát hiện)</string>
<string name="boot_image_title">Vị trí ảnh khởi động</string>
<string name="detect_button">Tìm</string>
<string name="advanced_settings_title">Thiết lập nâng cao</string>
<string name="keep_force_encryption">Giữ bắt buộc mã hoá</string>
<string name="keep_dm_verity">Giữ dm-verity</string>
<string name="current_magisk_title">Đã cài đặt Magisk phiên bản: %1$s</string>
<string name="install_magisk_title">Phiên bản Magisk mới nhất: %1$s</string>
<string name="current_magisk_title">Đã cài đặt phiên bản: %1$s</string>
<string name="install_magisk_title">Phiên bản mới nhất: %1$s</string>
<string name="uninstall">Gỡ bỏ</string>
<string name="uninstall_magisk_title">Gỡ bỏ Magisk</string>
@@ -49,7 +42,7 @@
<string name="not_installed">Chưa được cài đặt</string>
<!--Log Fragment-->
<string name="menuSaveToSd">Lưu vào thẻ nhớ</string>
<string name="menuSaveLog">Lưu nhật ký</string>
<string name="menuReload">Tải lại</string>
<string name="menuClearLog">Xoá nhật ký ngay</string>
<string name="logs_cleared">Đã xoá nhật ký thành công</string>
@@ -78,8 +71,6 @@
<string name="repo_install_msg">Bạn muốn cài đặt %1$s ?</string>
<string name="download">Tải xuống</string>
<string name="download_file_error">Lỗi tải tập tin</string>
<string name="install_error">Lỗi cài đặt!</string>
<string name="invalid_zip">Tập tin zip không phải mô-đun Magisk!!</string>
<string name="reboot">Khởi động lại</string>
<string name="zip_process_msg">Đang xử lý tập tin zip …</string>
<string name="downloading_toast">Đang tải xuống %1$s</string>
@@ -91,7 +82,6 @@
<string name="process_error">Lỗi xử lý</string>
<string name="internal_storage">Tập tin zip được lưu vào:\n[Bộ nhớ trong]%1$s</string>
<string name="zip_process_title">Đang xử lý</string>
<string name="manual_boot_image">Hãy tự chọn một ảnh khởi động!</string>
<!--Settings Activity -->
<string name="settings_general_category">Chung</string>

View File

@@ -11,31 +11,26 @@
<!--Status Fragment-->
<string name="magisk_version_error">未安装 Magisk</string>
<string name="checking_for_updates">正在检查更新…</string>
<string name="magisk_update_available">Magisk 可更新到 v%1$s</string>
<string name="cannot_check_updates">无法检查更新,没有网络连接?</string>
<string name="root_error">已 ROOT 但没有 ROOT 权限,未授予权限?</string>
<string name="not_rooted">未 ROOT</string>
<string name="invalid_update_channel">无效的更新通道</string>
<string name="safetyNet_check_text">点击启动 SafetyNet 检查</string>
<string name="checking_safetyNet_status">正在检查 SafetyNet 状态…</string>
<string name="safetyNet_check_success">SafetyNet 检查成功</string>
<string name="safetyNet_api_error">SafetyNet API 错误</string>
<string name="safetyNet_network_loss">网络连接不可用</string>
<string name="safetyNet_service_disconnected">服务已被取消</string>
<string name="safetyNet_res_invalid">回传值无效</string>
<!--Install Fragment-->
<string name="auto_detect">(自动) %1$s</string>
<string name="cannot_auto_detect">(无法自动检测)</string>
<string name="boot_image_title">Boot 镜像位置</string>
<string name="detect_button">检测</string>
<string name="advanced_settings_title">高级设置</string>
<string name="keep_force_encryption">保持强制加密</string>
<string name="keep_dm_verity">保留 dm-verity</string>
<string name="current_magisk_title">已安装 Magisk 版本:%1$s</string>
<string name="install_magisk_title">最新的 Magisk 版本:%1$s</string>
<string name="current_magisk_title">已安装版本:%1$s</string>
<string name="install_magisk_title">最新的版本:%1$s</string>
<string name="uninstall">卸载</string>
<string name="uninstall_magisk_title">卸载 Magisk</string>
<string name="uninstall_magisk_msg">所有模块将会被停用 / 删除。root会被移除并有可能在目前数据未加密的情况下被加密</string>
<string name="update">更新 %1$s</string>
<!--Module Fragment-->
@@ -54,19 +49,19 @@
<string name="not_installed">未安装</string>
<!--Log Fragment-->
<string name="menuSaveToSd">保存到 SD 卡</string>
<string name="menuReload">重载</string>
<string name="menuSaveLog">保存日志</string>
<string name="menuReload">刷新</string>
<string name="menuClearLog">清除日志</string>
<string name="logs_cleared">日志已成功清除</string>
<string name="log_is_empty">日志为空</string>
<string name="logs_save_failed">无法将日志写入 SD 卡</string>
<string name="logs_save_failed">无法将日志写入内置存储</string>
<!--About Activity-->
<string name="about">关于</string>
<string name="app_developers">主要开发者</string>
<string name="app_developers_"><![CDATA[此应用由 <a href="https://github.com/topjohnwu">topjohnwu</a> 与 <a href="https://github.com/d8ahazard">Digitalhigh</a> 和 <a href="https://github.com/dvdandroid">Dvdandroid</a> 合作开发。]]></string>
<string name="app_changelog">应用更新日志</string>
<string name="translators">gh2923</string>
<string name="translators">gh2923, vvb2060</string>
<string name="app_version">应用版本</string>
<string name="app_source_code">源代码</string>
<string name="donation">捐赠</string>
@@ -74,19 +69,16 @@
<string name="support_thread">支持主题</string>
<!--Toasts, Dialogs-->
<string name="permissionNotGranted">未授予写入置存储权限,此功能无法正常工作。</string>
<string name="permissionNotGranted">未授予写入置存储权限,此功能无法正常工作。</string>
<string name="no_thanks">不,谢谢</string>
<string name="yes"></string>
<string name="ok">确定</string>
<string name="ok"></string>
<string name="close">关闭</string>
<string name="repo_install_title">安装 %1$s</string>
<string name="repo_install_msg">你想要立即安装 %1$s 吗?</string>
<string name="download">下载</string>
<string name="download_file_error">下载文件时出错</string>
<string name="install_error">安装出错!</string>
<string name="invalid_zip">此 zip 文件不是 Magisk 模块!!</string>
<string name="reboot">重启</string>
<string name="zip_process_msg">正在处理 zip 文件 …</string>
<string name="downloading_toast">正在下载 %1$s</string>
<string name="magisk_update_title">Magisk 可更新!</string>
<string name="settings_reboot_toast">重启以应用设置</string>
@@ -94,36 +86,56 @@
<string name="repo_cache_cleared">资源库缓存已清除</string>
<string name="safetyNet_hide_notice">此应用使用了 SafetyNet\n已默认由 MagiskHide 处理</string>
<string name="process_error">处理失败</string>
<string name="internal_storage">Zip 已被储存到:\n[内部存储]%1$s</string>
<string name="internal_storage">Zip 已被储存到:\n[内部存储空间]%1$s</string>
<string name="zip_download_title">正在下载</string>
<string name="zip_download_msg">正在下载 Zip 文件(%1$d%%)…</string>
<string name="zip_process_title">正在处理</string>
<string name="manual_boot_image">请手动选择 Boot 镜像位置!</string>
<string name="zip_process_msg">正在处理 zip 文件…</string>
<string name="manager_update_title">Magisk Manager 有更新!</string>
<string name="manager_download_install">点击以下载并安装</string>
<string name="dtbo_patched_title">已修补 DTBO!</string>
<string name="dtbo_patched_reboot">Magisk Manager 为 dtbo 分区进行了修补,请立即重新启动</string>
<string name="magisk_updates">Magisk 更新</string>
<string name="flashing">正在刷入</string>
<string name="hide_manager_toast">正在隐藏 Magisk Manager…</string>
<string name="hide_manager_toast2">这可能需要一点时间…</string>
<string name="hide_manager_fail_toast">隐藏 Magisk Manager 失败…</string>
<string name="download_zip_only">仅下载 Zip</string>
<string name="patch_boot_file"> Boot 镜像文件打补丁</string>
<string name="patch_boot_file">修补 Boot 镜像文件</string>
<string name="direct_install">直接安装(推荐)</string>
<string name="select_method">选择方法</string>
<string name="install_second_slot">安装到第二分区安装完OTA后</string>
<string name="select_method">选择安装方法</string>
<string name="no_boot_file_patch_support">目标安装版本不支持修补 Boot 镜像文件</string>
<string name="boot_file_patch_msg">选择原厂 Boot 镜像备份;支持 .img 以及 .img.tar 格式</string>
<string name="complete_uninstall">完全卸载</string>
<string name="restore_stock_boot">还原原厂 Boot 镜像</string>
<string name="restore_done">还原完成!</string>
<string name="restore_fail">原厂 Boot 镜像备份不存在!</string>
<string name="uninstall_toast">将在 5 秒内卸载 Magisk Manager接下来请手动重新启动</string>
<string name="proprietary_title">下载专有代码</string>
<string name="proprietary_notice">Magisk Manager 是一个 100% 开源的应用,因此不会包含 Google 专有的 SafetyNet API 代码。\n\n你允许 Magisk Manager 下载一个扩展(包含 GoogleApiClient用于 SafetyNet 检查吗?</string>
<string name="su_db_corrupt">SU 数据库已损坏,将重新创建数据库</string>
<!--Settings Activity -->
<string name="settings_general_category">常规</string>
<string name="settings_dark_theme_title">深色主题</string>
<string name="settings_dark_theme_summary">使用深色主题</string>
<string name="settings_notification_title">更新通知</string>
<string name="settings_notification_summary">当有新版本可用时显示更新通知</string>
<string name="settings_clear_cache_title">清除资源库缓存</string>
<string name="settings_clear_cache_summary">清除已缓存的在线资源库信息,强制刷新在线数据</string>
<string name="settings_notification_summary">当有新版本时显示更新通知</string>
<string name="settings_clear_cache_title">清除库缓存</string>
<string name="settings_clear_cache_summary">清除已缓存的在线库信息,强制刷新在线数据</string>
<string name="settings_hide_manager_title">隐藏 Magisk Manager</string>
<string name="settings_hide_manager_summary">临时隐藏 Magisk Manager。\n此功能将会安装一个名为“Unhide Magisk Manager取消隐藏 Magisk Manager”的新应用。</string>
<string name="settings_hide_manager_summary">用随机包名重新安装 Magisk Manager</string>
<string name="language">语言</string>
<string name="system_default">(系统默认)</string>
<string name="settings_update">更新设定</string>
<string name="settings_update_channel_title">更新通道</string>
<string name="settings_update_stable">稳定版</string>
<string name="settings_update_beta">测试版</string>
<string name="settings_update_custom">自定义</string>
<string name="settings_update_custom_msg">请输入自定义网址</string>
<string name="settings_boot_format_title">已修补的 Boot 镜像输出格式</string>
<string name="settings_boot_format_summary">选择已修补的 Boot 镜像文件输出格式\n若要通过 fastboot/download 模式刷入,请选择 .img 格式;若要通过 Odin 刷入,则选择 .img.tar\n</string>
<string name="settings_core_only_title">Magisk 核心功能模式</string>
<string name="settings_core_only_summary">仅启用核心功能所有模块将不会被载入。MagiskSU、MagiskHide 和 systemless hosts 仍会持续运作</string>
<string name="settings_magiskhide_summary">隐藏 Magisk 使其不被多种方法检测到</string>
@@ -144,7 +156,7 @@
<string name="superuser_notification">超级用户通知</string>
<string name="request_timeout_summary">%1$s 秒</string>
<string name="settings_su_reauth_title">更新后重新认证</string>
<string name="settings_su_reauth_summary">应用程序更新后重新认证超级用户</string>
<string name="settings_su_reauth_summary">应用更新后重新认证超级用户权</string>
<string name="multiuser_mode">多用户模式</string>
<string name="settings_owner_only">仅设备所有者</string>

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