mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-28 04:25:27 +00:00
parent
8eba05ed4a
commit
a3f0ef8e77
@ -6,6 +6,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -19,6 +20,7 @@ import android.widget.TextView;
|
||||
import com.topjohnwu.magisk.asyncs.ProcessMagiskZip;
|
||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||
import com.topjohnwu.magisk.components.Fragment;
|
||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||
import com.topjohnwu.magisk.utils.Shell;
|
||||
@ -34,6 +36,7 @@ import java.util.Locale;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class InstallFragment extends Fragment implements CallbackEvent.Listener<Void> {
|
||||
@ -41,108 +44,126 @@ public class InstallFragment extends Fragment implements CallbackEvent.Listener<
|
||||
|
||||
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||
|
||||
private Unbinder unbinder;
|
||||
@BindView(R.id.current_version_title) TextView currentVersionTitle;
|
||||
@BindView(R.id.install_title) TextView installTitle;
|
||||
@BindView(R.id.block_spinner) Spinner spinner;
|
||||
@BindView(R.id.detect_bootimage) Button detectButton;
|
||||
@BindView(R.id.flash_button) CardView flashButton;
|
||||
@BindView(R.id.install_button) CardView installButton;
|
||||
@BindView(R.id.install_text) TextView installText;
|
||||
@BindView(R.id.uninstall_button) CardView uninstallButton;
|
||||
@BindView(R.id.keep_force_enc) CheckBox keepEncChkbox;
|
||||
@BindView(R.id.keep_verity) CheckBox keepVerityChkbox;
|
||||
|
||||
@OnClick(R.id.detect_bootimage)
|
||||
public void toAutoDetect() {
|
||||
if (magiskManager.bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.install_button)
|
||||
public void install() {
|
||||
String bootImage = null;
|
||||
if (magiskManager.blockList != null) {
|
||||
int idx = spinner.getSelectedItemPosition();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
}
|
||||
} else {
|
||||
if (idx > 0) {
|
||||
bootImage = magiskManager.blockList.get(idx - 1);
|
||||
} else {
|
||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
final String finalBootImage = bootImage;
|
||||
String filename = "Magisk-v" + magiskManager.remoteMagiskVersion + ".zip";
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
|
||||
(dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = finalBootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
||||
}
|
||||
},
|
||||
magiskManager.magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
magiskManager.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(magiskManager.releaseNoteLink)));
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@OnClick(R.id.uninstall_button)
|
||||
public void uninstall() {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.uninstall_magisk_title)
|
||||
.setMessage(R.string.uninstall_magisk_msg)
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||
try {
|
||||
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
||||
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||
byte[] bytes = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(bytes)) != -1) {
|
||||
out.write(bytes, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
ProgressDialog progress = new ProgressDialog(getActivity());
|
||||
progress.setTitle(R.string.reboot);
|
||||
progress.show();
|
||||
new CountDownTimer(5000, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, millisUntilFinished / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||
Shell.su(true, "mv -f " + uninstaller + " /cache/" + UNINSTALLER,
|
||||
"reboot");
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private Unbinder unbinder;
|
||||
private MagiskManager magiskManager;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.fragment_install, container, false);
|
||||
unbinder = ButterKnife.bind(this, v);
|
||||
detectButton.setOnClickListener(v1 -> toAutoDetect());
|
||||
if (getApplication().magiskVersion < 0)
|
||||
magiskManager = getApplication();
|
||||
if (magiskManager.magiskVersion < 0) {
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, getString(R.string.version_none)));
|
||||
else
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, "v" + getApplication().magiskVersionString));
|
||||
installTitle.setText(getString(R.string.install_magisk_title, "v" + String.format(Locale.US, "%.1f", getApplication().remoteMagiskVersion)));
|
||||
flashButton.setOnClickListener(v1 -> {
|
||||
String bootImage;
|
||||
if (getApplication().bootBlock != null) {
|
||||
if (spinner.getSelectedItemPosition() > 0)
|
||||
bootImage = getApplication().blockList.get(spinner.getSelectedItemPosition() - 1);
|
||||
else
|
||||
bootImage = getApplication().bootBlock;
|
||||
} else {
|
||||
bootImage = getApplication().blockList.get(spinner.getSelectedItemPosition());
|
||||
}
|
||||
String filename = "Magisk-v" + getApplication().remoteMagiskVersion + ".zip";
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||
.setCancelable(true)
|
||||
.setPositiveButton(R.string.install, (dialogInterface, i) -> Utils.dlAndReceive(
|
||||
getActivity(),
|
||||
new DownloadReceiver() {
|
||||
private String boot = bootImage;
|
||||
private boolean enc = keepEncChkbox.isChecked();
|
||||
private boolean verity = keepVerityChkbox.isChecked();
|
||||
|
||||
@Override
|
||||
public void onDownloadDone(Uri uri) {
|
||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
||||
}
|
||||
},
|
||||
getApplication().magiskLink,
|
||||
Utils.getLegalFilename(filename)))
|
||||
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
|
||||
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getApplication().releaseNoteLink)));
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
});
|
||||
if (getApplication().magiskVersion < 10.3) {
|
||||
uninstallButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
uninstallButton.setOnClickListener(vi -> {
|
||||
new AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.uninstall_magisk_title)
|
||||
.setMessage(R.string.uninstall_magisk_msg)
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
||||
try {
|
||||
InputStream in = getActivity().getAssets().open(UNINSTALLER);
|
||||
File uninstaller = new File(getActivity().getCacheDir().getAbsolutePath() + "/" + UNINSTALLER);
|
||||
FileOutputStream out = new FileOutputStream(uninstaller);
|
||||
byte[] bytes = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(bytes)) != -1)
|
||||
out.write(bytes, 0, read);
|
||||
in.close();
|
||||
out.close();
|
||||
ProgressDialog progress = new ProgressDialog(getActivity());
|
||||
progress.setTitle(R.string.reboot);
|
||||
progress.show();
|
||||
new CountDownTimer(5000, 1000) {
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, millisUntilFinished / 1000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
progress.setMessage(getString(R.string.reboot_countdown, 0));
|
||||
Shell.su(true, "cp -af " + uninstaller + " /cache/" + UNINSTALLER,
|
||||
"reboot");
|
||||
}
|
||||
}.start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.show();
|
||||
});
|
||||
currentVersionTitle.setText(getString(R.string.current_magisk_title, "v" + magiskManager.magiskVersionString));
|
||||
}
|
||||
installTitle.setText(getString(R.string.install_magisk_title, "v" + String.format(Locale.US, "%.1f", magiskManager.remoteMagiskVersion)));
|
||||
|
||||
if (getApplication().blockDetectionDone.isTriggered) {
|
||||
updateUI();
|
||||
}
|
||||
updateUI();
|
||||
return v;
|
||||
}
|
||||
|
||||
@ -152,19 +173,33 @@ public class InstallFragment extends Fragment implements CallbackEvent.Listener<
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
List<String> items = new ArrayList<>(getApplication().blockList);
|
||||
if (getApplication().bootBlock != null)
|
||||
items.add(0, getString(R.string.auto_detect, getApplication().bootBlock));
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
toAutoDetect();
|
||||
}
|
||||
if (magiskManager.blockList == null || !Shell.rootAccess()) {
|
||||
uninstallButton.setVisibility(View.GONE);
|
||||
installText.setText(R.string.download);
|
||||
detectButton.setEnabled(false);
|
||||
keepEncChkbox.setEnabled(false);
|
||||
keepVerityChkbox.setEnabled(false);
|
||||
spinner.setEnabled(false);
|
||||
} else {
|
||||
uninstallButton.setVisibility(magiskManager.magiskVersion > 10.3 ? View.VISIBLE : View.GONE);
|
||||
installText.setText(R.string.download_install);
|
||||
detectButton.setEnabled(true);
|
||||
keepEncChkbox.setEnabled(true);
|
||||
keepVerityChkbox.setEnabled(true);
|
||||
spinner.setEnabled(true);
|
||||
|
||||
private void toAutoDetect() {
|
||||
if (getApplication().bootBlock != null) {
|
||||
spinner.setSelection(0);
|
||||
List<String> items = new ArrayList<>();
|
||||
if (magiskManager.bootBlock != null) {
|
||||
items.add(getString(R.string.auto_detect, magiskManager.bootBlock));
|
||||
} else {
|
||||
items.add(getString(R.string.cannot_auto_detect));
|
||||
}
|
||||
items.addAll(magiskManager.blockList);
|
||||
ArrayAdapter<String> adapter = new ArrayAdapter<>(getActivity(),
|
||||
android.R.layout.simple_spinner_item, items);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spinner.setAdapter(adapter);
|
||||
toAutoDetect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,12 +207,12 @@ public class InstallFragment extends Fragment implements CallbackEvent.Listener<
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
getActivity().setTitle(R.string.install);
|
||||
getApplication().blockDetectionDone.register(this);
|
||||
magiskManager.blockDetectionDone.register(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
getApplication().blockDetectionDone.unRegister(this);
|
||||
magiskManager.blockDetectionDone.unRegister(this);
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
|
@ -71,8 +71,9 @@ public class MagiskHideFragment extends Fragment implements CallbackEvent.Listen
|
||||
}
|
||||
};
|
||||
|
||||
if (getApplication().magiskHideDone.isTriggered)
|
||||
if (getApplication().magiskHideDone.isTriggered) {
|
||||
onTrigger(getApplication().magiskHideDone);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
@ -162,8 +162,9 @@ public class MagiskLogFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
|
||||
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Calendar now = Calendar.getInstance();
|
||||
String filename = String.format(
|
||||
@ -175,8 +176,9 @@ public class MagiskLogFragment extends Fragment {
|
||||
targetFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MagiskManager/" + filename);
|
||||
|
||||
if ((!targetFile.getParentFile().exists() && !targetFile.getParentFile().mkdirs())
|
||||
|| (targetFile.exists() && !targetFile.delete()))
|
||||
|| (targetFile.exists() && !targetFile.delete())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> in = Utils.readFile(MAGISK_LOG);
|
||||
|
||||
@ -214,10 +216,11 @@ public class MagiskLogFragment extends Fragment {
|
||||
break;
|
||||
case 2:
|
||||
bool = (boolean) o;
|
||||
if (bool)
|
||||
if (bool) {
|
||||
Toast.makeText(getActivity(), targetFile.toString(), Toast.LENGTH_LONG).show();
|
||||
else
|
||||
} else {
|
||||
Toast.makeText(getActivity(), getString(R.string.logs_save_failed), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -125,9 +125,9 @@ public class MagiskManager extends Application {
|
||||
}
|
||||
if (isSuClient) {
|
||||
ret = Shell.sh("getprop persist.sys.root_access");
|
||||
if (Utils.isValidShellResponse(ret))
|
||||
if (Utils.isValidShellResponse(ret)) {
|
||||
suAccessState = Integer.parseInt(ret.get(0));
|
||||
else {
|
||||
} else {
|
||||
Shell.su(true, "setprop persist.sys.root_access 3");
|
||||
suAccessState = 3;
|
||||
}
|
||||
@ -160,8 +160,9 @@ public class MagiskManager extends Application {
|
||||
magiskHideStarted = false;
|
||||
}
|
||||
|
||||
if (!magiskHide && magiskHideStarted)
|
||||
if (magiskHideStarted) {
|
||||
magiskHide = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -131,14 +131,16 @@ public class MainActivity extends Activity
|
||||
|
||||
private void checkHideSection() {
|
||||
Menu menu = navigationView.getMenu();
|
||||
if (Shell.rootAccess()) {
|
||||
menu.findItem(R.id.magiskhide).setVisible(
|
||||
getApplicationContext().magiskVersion >= 8 && prefs.getBoolean("magiskhide", false));
|
||||
menu.findItem(R.id.modules).setVisible(getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.downloads).setVisible(getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.log).setVisible(true);
|
||||
menu.findItem(R.id.superuser).setVisible(getApplicationContext().isSuClient);
|
||||
}
|
||||
menu.findItem(R.id.magiskhide).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 8
|
||||
&& prefs.getBoolean("magiskhide", false));
|
||||
menu.findItem(R.id.modules).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.downloads).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().magiskVersion >= 4);
|
||||
menu.findItem(R.id.log).setVisible(Shell.rootAccess());
|
||||
menu.findItem(R.id.superuser).setVisible(
|
||||
Shell.rootAccess() && getApplicationContext().isSuClient);
|
||||
menu.findItem(R.id.install).setVisible(getApplicationContext().remoteMagiskVersion > 0);
|
||||
}
|
||||
|
||||
@ -179,6 +181,7 @@ public class MainActivity extends Activity
|
||||
}
|
||||
|
||||
public void navigate(int itemId) {
|
||||
int bak = mDrawerItem;
|
||||
mDrawerItem = itemId;
|
||||
navigationView.setCheckedItem(itemId);
|
||||
switch (itemId) {
|
||||
@ -205,9 +208,11 @@ public class MainActivity extends Activity
|
||||
break;
|
||||
case R.id.settings:
|
||||
startActivity(new Intent(this, SettingsActivity.class));
|
||||
mDrawerItem = bak;
|
||||
break;
|
||||
case R.id.app_about:
|
||||
startActivity(new Intent(this, AboutActivity.class));
|
||||
mDrawerItem = bak;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -133,10 +133,11 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
|
||||
for (Repo repo : getApplication().repoMap.values()) {
|
||||
Module module = getApplication().moduleMap.get(repo.getId());
|
||||
if (module != null) {
|
||||
if (repo.getVersionCode() > module.getVersionCode())
|
||||
if (repo.getVersionCode() > module.getVersionCode()) {
|
||||
mUpdateRepos.add(repo);
|
||||
else
|
||||
} else {
|
||||
mInstalledRepos.add(repo);
|
||||
}
|
||||
} else {
|
||||
mOthersRepos.add(repo);
|
||||
}
|
||||
|
@ -112,10 +112,12 @@ public class SettingsActivity extends Activity {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
prefScreen.removePreference(suCategory);
|
||||
} else {
|
||||
if (!getApplication().isSuClient)
|
||||
if (!getApplication().isSuClient) {
|
||||
prefScreen.removePreference(suCategory);
|
||||
if (getApplication().magiskVersion < 11)
|
||||
}
|
||||
if (getApplication().magiskVersion < 11) {
|
||||
prefScreen.removePreference(magiskCategory);
|
||||
}
|
||||
if (getApplication().disabled) {
|
||||
busybox.setEnabled(false);
|
||||
magiskHide.setEnabled(false);
|
||||
@ -146,8 +148,8 @@ public class SettingsActivity extends Activity {
|
||||
enabled = prefs.getBoolean("dark_theme", false);
|
||||
if (getApplication().isDarkTheme != enabled) {
|
||||
getApplication().isDarkTheme = enabled;
|
||||
getActivity().finish();
|
||||
getApplication().reloadMainActivity.trigger();
|
||||
getActivity().recreate();
|
||||
}
|
||||
break;
|
||||
case "disable":
|
||||
@ -195,9 +197,12 @@ public class SettingsActivity extends Activity {
|
||||
.setPositiveButton(R.string.understand, (dialog, which) -> new MagiskHide().enable())
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
} else new MagiskHide().enable();
|
||||
} else
|
||||
} else {
|
||||
new MagiskHide().enable();
|
||||
}
|
||||
} else {
|
||||
new MagiskHide().disable();
|
||||
}
|
||||
break;
|
||||
case "hosts":
|
||||
enabled = prefs.getBoolean("hosts", false);
|
||||
|
@ -22,6 +22,7 @@ import com.topjohnwu.magisk.utils.Utils;
|
||||
import butterknife.BindColor;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
public class StatusFragment extends Fragment implements CallbackEvent.Listener<Void> {
|
||||
@ -53,7 +54,27 @@ public class StatusFragment extends Fragment implements CallbackEvent.Listener<V
|
||||
@BindColor(R.color.grey500) int colorNeutral;
|
||||
@BindColor(R.color.blue500) int colorInfo;
|
||||
@BindColor(android.R.color.transparent) int trans;
|
||||
int defaultColor;
|
||||
|
||||
@OnClick(R.id.safetyNet_container)
|
||||
public void safetyNet() {
|
||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||
safetyNetContainer.setBackgroundColor(trans);
|
||||
safetyNetIcon.setImageResource(0);
|
||||
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
||||
Utils.checkSafetyNet(getApplication());
|
||||
}
|
||||
|
||||
@OnClick(R.id.magisk_status_container)
|
||||
public void magisk() {
|
||||
((MainActivity) getActivity()).navigationView.setCheckedItem(R.id.install);
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
try {
|
||||
transaction.replace(R.id.content_frame, new InstallFragment(), "install").commit();
|
||||
} catch (IllegalStateException ignored) {}
|
||||
}
|
||||
|
||||
private int defaultColor;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@ -83,23 +104,6 @@ public class StatusFragment extends Fragment implements CallbackEvent.Listener<V
|
||||
new CheckUpdates(getActivity()).exec();
|
||||
});
|
||||
|
||||
safetyNetContainer.setOnClickListener(view -> {
|
||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||
safetyNetContainer.setBackgroundColor(trans);
|
||||
safetyNetIcon.setImageResource(0);
|
||||
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
||||
Utils.checkSafetyNet(getApplication());
|
||||
});
|
||||
|
||||
magiskStatusContainer.setOnClickListener(view -> {
|
||||
((MainActivity) getActivity()).navigationView.setCheckedItem(R.id.install);
|
||||
FragmentTransaction transaction = getFragmentManager().beginTransaction();
|
||||
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||
try {
|
||||
transaction.replace(R.id.content_frame, new InstallFragment(), "install").commit();
|
||||
} catch (IllegalStateException ignored) {}
|
||||
});
|
||||
|
||||
if (getApplication().magiskVersion < 0 && Shell.rootAccess() && !noDialog) {
|
||||
noDialog = true;
|
||||
new AlertDialogBuilder(getActivity())
|
||||
|
@ -109,7 +109,9 @@ public class SuLogAdapter {
|
||||
@Override
|
||||
public void onBindGroupViewHolder(LogGroupViewHolder holder, int flatPosition, ExpandableGroup group) {
|
||||
holder.date.setText(group.getTitle());
|
||||
if (isGroupExpanded(flatPosition)) holder.expand();
|
||||
if (isGroupExpanded(flatPosition)) {
|
||||
holder.expand();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,9 @@ public class GetBootBlocks extends SerialTask<Void, Void, Void> {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (Shell.rootAccess()) {
|
||||
magiskManager.blockList = Shell.su("ls /dev/block | grep mmc");
|
||||
if (magiskManager.bootBlock == null)
|
||||
magiskManager.bootBlock = Utils.detectBootImage();
|
||||
magiskManager.blockList = Shell.su("ls /dev/block | grep mmc");
|
||||
if (magiskManager.bootBlock == null) {
|
||||
magiskManager.bootBlock = Utils.detectBootImage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -22,8 +22,9 @@ public class LoadApps extends ParallelTask<Void, Void, Void> {
|
||||
List<ApplicationInfo> list = pm.getInstalledApplications(0);
|
||||
for (Iterator<ApplicationInfo> i = list.iterator(); i.hasNext(); ) {
|
||||
ApplicationInfo info = i.next();
|
||||
if (ApplicationAdapter.BLACKLIST.contains(info.packageName) || !info.enabled)
|
||||
if (ApplicationAdapter.BLACKLIST.contains(info.packageName) || !info.enabled) {
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
Collections.sort(list, (a, b) -> a.loadLabel(pm).toString().toLowerCase()
|
||||
.compareTo(b.loadLabel(pm).toString().toLowerCase()));
|
||||
|
@ -96,8 +96,9 @@ public class LoadRepos extends ParallelTask<Void, Void, Void> {
|
||||
Logger.dev("LoadRepos: Update cached repo " + id);
|
||||
repo.update(updatedDate);
|
||||
}
|
||||
if (repo.getId() != null)
|
||||
if (repo.getId() != null) {
|
||||
magiskManager.repoMap.put(id, repo);
|
||||
}
|
||||
} catch (BaseModule.CacheModException ignored) {}
|
||||
}
|
||||
|
||||
|
@ -21,15 +21,17 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
protected Void doInBackground(Object... params) {
|
||||
String command = (String) params[0];
|
||||
List<String> ret = Shell.su(MagiskManager.MAGISK_HIDE_PATH + command);
|
||||
if (isList)
|
||||
if (isList) {
|
||||
magiskManager.magiskHideList = ret;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void v) {
|
||||
if (isList)
|
||||
if (isList) {
|
||||
magiskManager.magiskHideDone.trigger();
|
||||
}
|
||||
}
|
||||
|
||||
public void add(CharSequence packageName) {
|
||||
@ -50,8 +52,7 @@ public class MagiskHide extends SerialTask<Object, Void, Void> {
|
||||
|
||||
public void list() {
|
||||
isList = true;
|
||||
if (magiskManager == null)
|
||||
return;
|
||||
if (magiskManager == null) return;
|
||||
exec("list");
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,8 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
ZipUtils.unzip(magiskManager.getContentResolver().openInputStream(mUri), tempdir);
|
||||
// Running in parallel mode, open new shell
|
||||
Shell.su(true,
|
||||
"echo \"BOOTIMAGE=/dev/block/" + mBoot + "\" > /dev/.magisk",
|
||||
"rm -f /dev/.magisk",
|
||||
(mBoot != null) ? "echo \"BOOTIMAGE=/dev/block/" + mBoot + "\" >> /dev/.magisk" : "",
|
||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk",
|
||||
"mkdir -p " + MagiskManager.TMP_FOLDER_PATH,
|
||||
@ -66,13 +67,14 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
progressDialog.dismiss();
|
||||
if (result)
|
||||
if (result) {
|
||||
new FlashZip(activity, mUri) {
|
||||
@Override
|
||||
protected boolean unzipAndCheck() throws Exception {
|
||||
// Don't need to check, as it is downloaded in correct form
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSuccess() {
|
||||
new SerialTask<Void, Void, Void>(activity) {
|
||||
@ -87,7 +89,8 @@ public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
||||
super.onSuccess();
|
||||
}
|
||||
}.exec();
|
||||
else
|
||||
} else {
|
||||
Utils.showUriSnack(activity, mUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,10 +103,11 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
|
||||
protected void onPostExecute(Boolean result) {
|
||||
progressDialog.dismiss();
|
||||
if (result) {
|
||||
if (Shell.rootAccess() && mInstall)
|
||||
if (Shell.rootAccess() && mInstall) {
|
||||
new FlashZip(activity, mUri).exec();
|
||||
else
|
||||
} else {
|
||||
Utils.showUriSnack(activity, mUri);
|
||||
}
|
||||
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.process_error, Toast.LENGTH_LONG).show();
|
||||
|
@ -93,8 +93,9 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
|
||||
positive.setText(text);
|
||||
positiveListener = listener;
|
||||
positive.setOnClickListener((v) -> {
|
||||
if (positiveListener != null)
|
||||
if (positiveListener != null) {
|
||||
positiveListener.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
return this;
|
||||
@ -112,8 +113,9 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
|
||||
negative.setText(text);
|
||||
negativeListener = listener;
|
||||
negative.setOnClickListener((v) -> {
|
||||
if (negativeListener != null)
|
||||
if (negativeListener != null) {
|
||||
negativeListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
return this;
|
||||
@ -131,8 +133,9 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
|
||||
neutral.setText(text);
|
||||
neutralListener = listener;
|
||||
neutral.setOnClickListener((v) -> {
|
||||
if (neutralListener != null)
|
||||
if (neutralListener != null) {
|
||||
neutralListener.onClick(dialog, DialogInterface.BUTTON_NEUTRAL);
|
||||
}
|
||||
dialog.dismiss();
|
||||
});
|
||||
return this;
|
||||
|
@ -3,7 +3,6 @@ package com.topjohnwu.magisk.components;
|
||||
import android.app.Activity;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -34,8 +33,7 @@ public class SnackbarMaker {
|
||||
|
||||
private static void setup(Snackbar snack) {
|
||||
TextView text = ButterKnife.findById(snack.getView(), android.support.design.R.id.snackbar_text);
|
||||
text.setMaxLines(2);
|
||||
text.setEllipsize(TextUtils.TruncateAt.START);
|
||||
text.setMaxLines(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,8 +40,9 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
public void addRepoMap(ValueSortedMap<String, Repo> map) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
Collection<Repo> list = map.values();
|
||||
for (Repo repo : list)
|
||||
for (Repo repo : list) {
|
||||
db.replace(TABLE_NAME, null, repo.getContentValues());
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
|
||||
@ -54,8 +55,9 @@ public class RepoDatabaseHelper extends SQLiteOpenHelper {
|
||||
public void removeRepo(ValueSortedMap<String, Repo> map) {
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
Collection<Repo> list = map.values();
|
||||
for (Repo repo : list)
|
||||
for (Repo repo : list) {
|
||||
db.delete(TABLE_NAME, "id=?", new String[] { repo.getId() });
|
||||
}
|
||||
db.close();
|
||||
}
|
||||
|
||||
|
@ -22,15 +22,18 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(uid INT, package_name TEXT, app_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
onUpgrade(db, 0, DATABASE_VER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 0) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " " +
|
||||
"(uid INT, package_name TEXT, app_name TEXT, policy INT, " +
|
||||
"until INT, logging INT, notification INT, " +
|
||||
"PRIMARY KEY(uid))");
|
||||
}
|
||||
// Currently new database, no upgrading
|
||||
}
|
||||
|
||||
@ -45,8 +48,9 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
|
||||
Policy policy = null;
|
||||
SQLiteDatabase db = getReadableDatabase();
|
||||
try (Cursor c = db.query(TABLE_NAME, null, "uid=?", new String[] { String.valueOf(uid) }, null, null, null)) {
|
||||
if (c.moveToNext())
|
||||
if (c.moveToNext()) {
|
||||
policy = new Policy(c);
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
return policy;
|
||||
|
@ -25,14 +25,17 @@ public class SuLogDatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
onUpgrade(db, 0, DATABASE_VER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion == 0) {
|
||||
db.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
|
||||
"from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " +
|
||||
"to_uid INT, action INT, time INT, command TEXT)");
|
||||
}
|
||||
// Currently new database, no upgrading
|
||||
}
|
||||
|
||||
@ -63,8 +66,9 @@ public class SuLogDatabaseHelper extends SQLiteOpenHelper {
|
||||
db.delete(TABLE_NAME, "time < ?", new String[] { String.valueOf(
|
||||
System.currentTimeMillis() / 1000 - magiskManager.suLogTimeout * 86400) });
|
||||
try (Cursor c = db.query(TABLE_NAME, null, selection, null, null, null, "time DESC")) {
|
||||
while (c.moveToNext())
|
||||
while (c.moveToNext()) {
|
||||
ret.add(new SuLogEntry(c));
|
||||
}
|
||||
}
|
||||
db.close();
|
||||
return ret;
|
||||
|
@ -21,8 +21,9 @@ public class Module extends BaseModule {
|
||||
setId(path.substring(sep + 1));
|
||||
}
|
||||
|
||||
if (getName() == null)
|
||||
if (getName() == null) {
|
||||
setName(getId());
|
||||
}
|
||||
|
||||
Logger.dev("Creating Module, id: " + getId());
|
||||
|
||||
|
@ -60,10 +60,6 @@ public class Repo extends BaseModule {
|
||||
return String.format(ZIP_URL, repoName);
|
||||
}
|
||||
|
||||
public String getLogUrl() {
|
||||
return String.format(FILE_URL, repoName, "changelog.txt");
|
||||
}
|
||||
|
||||
public String getManifestUrl() {
|
||||
return String.format(FILE_URL, repoName, "module.prop");
|
||||
}
|
||||
|
@ -38,10 +38,12 @@ public class SuReceiver extends BroadcastReceiver {
|
||||
|
||||
SuDatabaseHelper suDbHelper = new SuDatabaseHelper(context);
|
||||
policy = suDbHelper.getPolicy(fromUid);
|
||||
if (policy == null) try {
|
||||
policy = new Policy(fromUid, context.getPackageManager());
|
||||
} catch (Throwable throwable) {
|
||||
return;
|
||||
if (policy == null) {
|
||||
try {
|
||||
policy = new Policy(fromUid, context.getPackageManager());
|
||||
} catch (Throwable throwable) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
magiskManager.initSuConfigs();
|
||||
|
@ -76,8 +76,9 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
@Override
|
||||
public void onEvent(int fileEvent, String path) {
|
||||
if (fileEvent == FileObserver.DELETE_SELF) {
|
||||
if (event != null)
|
||||
if (event != null) {
|
||||
event.trigger();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@ -147,8 +148,9 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
public void onTrigger(CallbackEvent<Policy> event) {
|
||||
Policy policy = event.getResult();
|
||||
String response = "socket:DENY";
|
||||
if (policy != null &&policy.policy == Policy.ALLOW )
|
||||
if (policy != null &&policy.policy == Policy.ALLOW ) {
|
||||
response = "socket:ALLOW";
|
||||
}
|
||||
try {
|
||||
socket.getOutputStream().write((response).getBytes());
|
||||
} catch (Exception ignored) {}
|
||||
@ -176,7 +178,7 @@ public class SuRequestActivity extends Activity implements CallbackEvent.Listene
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
try{
|
||||
try {
|
||||
socket = new LocalSocket();
|
||||
socket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM));
|
||||
|
||||
|
@ -10,8 +10,9 @@ public class CallbackEvent<Result> {
|
||||
private Set<Listener<Result>> listeners;
|
||||
|
||||
public void register(Listener<Result> l) {
|
||||
if (listeners == null)
|
||||
if (listeners == null) {
|
||||
listeners = new HashSet<>();
|
||||
}
|
||||
listeners.add(l);
|
||||
}
|
||||
|
||||
@ -20,8 +21,9 @@ public class CallbackEvent<Result> {
|
||||
}
|
||||
|
||||
public void unRegister(Listener<Result> l) {
|
||||
if (listeners != null)
|
||||
if (listeners != null) {
|
||||
listeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
public void trigger() {
|
||||
@ -32,8 +34,9 @@ public class CallbackEvent<Result> {
|
||||
result = r;
|
||||
isTriggered = true;
|
||||
if (listeners != null) {
|
||||
for (Listener<Result> listener : listeners)
|
||||
for (Listener<Result> listener : listeners) {
|
||||
listener.onTrigger(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,11 +120,13 @@ public class Shell {
|
||||
StreamGobbler STDOUT;
|
||||
|
||||
// Create the default shell if not init
|
||||
if (!newShell && !isInit)
|
||||
if (!newShell && !isInit) {
|
||||
init();
|
||||
}
|
||||
|
||||
if (!newShell && !rootAccess())
|
||||
if (!newShell && !rootAccess()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (newShell) {
|
||||
res = Collections.synchronizedList(new ArrayList<String>());
|
||||
|
@ -114,8 +114,9 @@ public class Utils {
|
||||
"echo \"${BOOTIMAGE##*/}\""
|
||||
};
|
||||
List<String> ret = Shell.su(commands);
|
||||
if (isValidShellResponse(ret))
|
||||
if (isValidShellResponse(ret)) {
|
||||
return ret.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -77,10 +77,11 @@ public class WebService {
|
||||
StringBuilder result = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
if (first)
|
||||
if (first) {
|
||||
first = false;
|
||||
else
|
||||
} else {
|
||||
result.append("&");
|
||||
}
|
||||
|
||||
result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
|
||||
result.append("=");
|
||||
|
@ -112,14 +112,17 @@ public class ZipUtils {
|
||||
// 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())
|
||||
if (path.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// Don't include placeholder
|
||||
if (path.contains("system/placeholder"))
|
||||
if (path.contains("system/placeholder")) {
|
||||
continue;
|
||||
}
|
||||
dest.putNextEntry(new JarEntry(path));
|
||||
while((size = source.read(buffer, 0, 2048)) != -1)
|
||||
while((size = source.read(buffer, 0, 2048)) != -1) {
|
||||
dest.write(buffer, 0, size);
|
||||
}
|
||||
}
|
||||
source.close();
|
||||
dest.close();
|
||||
@ -149,17 +152,20 @@ public class ZipUtils {
|
||||
Enumeration<JarEntry> e = zipfile.entries();
|
||||
while(e.hasMoreElements()) {
|
||||
entry = e.nextElement();
|
||||
if (!entry.getName().contains(path) || entry.isDirectory())
|
||||
if (!entry.getName().contains(path) || entry.isDirectory()){
|
||||
// Ignore directories, only create files
|
||||
continue;
|
||||
}
|
||||
Logger.dev("ZipUtils: Extracting: " + entry);
|
||||
is = zipfile.getInputStream(entry);
|
||||
dest = new File(folder, entry.getName());
|
||||
if (dest.getParentFile().mkdirs())
|
||||
if (dest.getParentFile().mkdirs()) {
|
||||
dest.createNewFile();
|
||||
}
|
||||
out = new FileOutputStream(dest);
|
||||
while ((count = is.read(data, 0, 4096)) != -1)
|
||||
while ((count = is.read(data, 0, 4096)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
is.close();
|
||||
@ -178,16 +184,19 @@ public class ZipUtils {
|
||||
byte data[] = new byte[4096];
|
||||
try (JarInputStream zipfile = new JarInputStream(file)) {
|
||||
while((entry = zipfile.getNextJarEntry()) != null) {
|
||||
if (!entry.getName().contains(path) || entry.isDirectory())
|
||||
if (!entry.getName().contains(path) || entry.isDirectory()) {
|
||||
// Ignore directories, only create files
|
||||
continue;
|
||||
}
|
||||
Logger.dev("ZipUtils: Extracting: " + entry);
|
||||
dest = new File(folder, entry.getName());
|
||||
if (dest.getParentFile().mkdirs())
|
||||
if (dest.getParentFile().mkdirs()) {
|
||||
dest.createNewFile();
|
||||
}
|
||||
out = new FileOutputStream(dest);
|
||||
while ((count = zipfile.read(data, 0, 4096)) != -1)
|
||||
while ((count = zipfile.read(data, 0, 4096)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
@ -159,7 +159,7 @@
|
||||
</android.support.v7.widget.CardView>
|
||||
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/flash_button"
|
||||
android:id="@+id/install_button"
|
||||
android:layout_gravity="center"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
@ -192,7 +192,7 @@
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:text="@string/download_install"
|
||||
android:id="@+id/install_text"
|
||||
android:ems="10"
|
||||
android:gravity="center"
|
||||
android:layout_weight="1"
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="auto_detect">(自動) %1$s</string>
|
||||
<string name="boot_image_title">Boot 鏡像位置</string>
|
||||
<string name="boot_image_title">Boot 映像位置</string>
|
||||
<string name="detect_button">偵測</string>
|
||||
<string name="advanced_settings_title">高級設置</string>
|
||||
<string name="keep_force_encryption">保持強制加密</string>
|
||||
@ -181,13 +181,15 @@
|
||||
<string name="target_uid">目標 UID:\u0020</string>
|
||||
<string name="command">"指令: "</string>
|
||||
<string name="close">關閉</string>
|
||||
<string name="internal_storage">Zip 已被儲存到:[內部儲存空間]%1$s</string>
|
||||
<string name="internal_storage">Zip 已被儲存到:\n[內部儲存空間]%1$s</string>
|
||||
<string name="ok">好</string>
|
||||
<string name="process_error">處裡失敗</string>
|
||||
<string name="download">下載</string>
|
||||
<string name="zip_process_title">處理中</string>
|
||||
<string name="uninstall_magisk_title">解除安裝 Magisk</string>
|
||||
<string name="uninstall_magisk_msg">這將會刪除所有模組,MagiskSU,並有可能在目前未加密的情況下加密的的資料\n你確定要繼續嗎?</string>
|
||||
<string name="uninstall_magisk_msg">這將會刪除所有模組,MagiskSU,並有可能在目前資料未加密的情況下進行加密\n你確定要繼續嗎?</string>
|
||||
<string name="version_none">(無)</string>
|
||||
<string name="manual_boot_image">請手動選取 boot 映像位置</string>
|
||||
<string name="cannot_auto_detect">(無法自動偵測)</string>
|
||||
|
||||
</resources>
|
||||
|
@ -13,9 +13,6 @@
|
||||
<color name="blue500">#2196F3</color>
|
||||
<color name="yellow500">#FFC107</color>
|
||||
|
||||
<color name="dark_primary">#bf360c</color>
|
||||
<color name="dark_primary_dark">#000000</color>
|
||||
|
||||
<color name="dark_secondary_text">#dedede</color>
|
||||
|
||||
<color name="su_request_background">#e0e0e0</color>
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
<!--Install Fragment-->
|
||||
<string name="auto_detect">(Auto) %1$s</string>
|
||||
<string name="cannot_auto_detect">(Cannot auto detect)</string>
|
||||
<string name="boot_image_title">Boot Image Location</string>
|
||||
<string name="detect_button">Detect</string>
|
||||
<string name="advanced_settings_title">Advanced Settings</string>
|
||||
@ -124,6 +125,7 @@
|
||||
<string name="process_error">Process error</string>
|
||||
<string name="internal_storage">The zip is stored in:\n[Internal Storage]%1$s</string>
|
||||
<string name="zip_process_title">Processing</string>
|
||||
<string name="manual_boot_image">Please manually select a boot image!</string>
|
||||
|
||||
<!--Settings Activity -->
|
||||
<string name="settings_general_category">General</string>
|
||||
|
Loading…
Reference in New Issue
Block a user