From 2ee22fd374cbc685d628ed7f5f850f1e3deb6aa2 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 5 Sep 2017 17:43:13 +0800 Subject: [PATCH] Add restore stock image feature --- .../com/topjohnwu/magisk/MagiskFragment.java | 222 +++--------------- .../magisk/adapters/PolicyAdapter.java | 3 +- .../magisk/adapters/ReposAdapter.java | 2 +- .../magisk/asyncs/RestoreStockBoot.java | 40 ++++ .../magisk/components/AlertDialogBuilder.java | 6 +- .../topjohnwu/magisk/components/Fragment.java | 20 ++ .../com/topjohnwu/magisk/utils/Utils.java | 193 ++++++++++++++- app/src/main/res/layout/fragment_magisk.xml | 4 +- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-ko/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt-rPT/strings.xml | 2 - app/src/main/res/values-ro/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values-sv/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 1 - app/src/main/res/values-uk/strings.xml | 1 - app/src/main/res/values-vi/strings.xml | 1 - app/src/main/res/values-zh-rCN/strings.xml | 1 - app/src/main/res/values-zh-rTW/strings.xml | 6 +- app/src/main/res/values/strings.xml | 6 +- 30 files changed, 296 insertions(+), 227 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java index a0269cadb..d7233e6f9 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java @@ -1,14 +1,8 @@ package com.topjohnwu.magisk; -import android.app.Activity; -import android.app.AlertDialog; import android.app.NotificationManager; -import android.app.ProgressDialog; import android.content.Context; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; -import android.os.CountDownTimer; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.widget.SwipeRefreshLayout; @@ -24,23 +18,15 @@ import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.TextView; -import android.widget.Toast; import com.topjohnwu.magisk.asyncs.CheckUpdates; -import com.topjohnwu.magisk.components.AlertDialogBuilder; import com.topjohnwu.magisk.components.ExpandableView; import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.SnackbarMaker; -import com.topjohnwu.magisk.receivers.DownloadReceiver; -import com.topjohnwu.magisk.receivers.ManagerUpdate; import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Utils; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; import java.util.ArrayList; import java.util.List; @@ -53,10 +39,6 @@ import butterknife.Unbinder; public class MagiskFragment extends Fragment implements Topic.Subscriber, SwipeRefreshLayout.OnRefreshListener, ExpandableView { - private static final String UNINSTALLER = "magisk_uninstaller.sh"; - private static final String UTIL_FUNCTIONS= "util_functions.sh"; - private static final int SELECT_BOOT_IMG = 3; - private Container expandableContainer = new Container(); private MagiskManager mm; @@ -102,7 +84,7 @@ public class MagiskFragment extends Fragment @BindColor(R.color.blue500) int colorInfo; @OnClick(R.id.safetyNet_title) - public void safetyNet() { + void safetyNet() { safetyNetProgress.setVisibility(View.VISIBLE); safetyNetRefreshIcon.setVisibility(View.GONE); safetyNetStatusText.setText(R.string.checking_safetyNet_status); @@ -111,169 +93,23 @@ public class MagiskFragment extends Fragment } @OnClick(R.id.install_button) - public void install() { + void install() { shownDialog = true; // Show Manager update first if (mm.remoteManagerVersionCode > BuildConfig.VERSION_CODE) { - new AlertDialogBuilder(getActivity()) - .setTitle(getString(R.string.repo_install_title, getString(R.string.app_name))) - .setMessage(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); - getActivity().sendBroadcast(intent); - }) - .setNegativeButton(R.string.no_thanks, null) - .show(); + Utils.showManagerInstallDialog(getActivity()); return; } - String bootImage = null; - if (Shell.rootAccess()) { - if (mm.bootBlock != null) { - bootImage = mm.bootBlock; - } else { - int idx = spinner.getSelectedItemPosition(); - if (idx > 0) { - bootImage = mm.blockList.get(idx - 1); - } else { - SnackbarMaker.make(getActivity(), - R.string.manual_boot_image, Snackbar.LENGTH_LONG).show(); - return; - } - } - } - final String boot = bootImage; - ((NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll(); - String filename = "Magisk-v" + mm.remoteMagiskVersionString + ".zip"; - new AlertDialogBuilder(getActivity()) - .setTitle(getString(R.string.repo_install_title, getString(R.string.magisk))) - .setMessage(getString(R.string.repo_install_msg, filename)) - .setCancelable(true) - .setPositiveButton( - R.string.install, - (d, i) -> { - List options = new ArrayList<>(); - options.add(getString(R.string.download_zip_only)); - options.add(getString(R.string.patch_boot_file)); - if (Shell.rootAccess()) { - options.add(getString(R.string.direct_install)); - } - new AlertDialog.Builder(getActivity()) - .setTitle(R.string.select_method) - .setItems( - options.toArray(new String [0]), - (dialog, idx) -> { - DownloadReceiver receiver = null; - switch (idx) { - case 1: - if (mm.remoteMagiskVersionCode < 1370) { - mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG); - return; - } - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("*/*"); - startActivityForResult(intent, SELECT_BOOT_IMG); - return; - case 0: - receiver = new DownloadReceiver() { - @Override - public void onDownloadDone(Uri uri) { - Utils.showUriSnack(getActivity(), uri); - } - }; - break; - case 2: - receiver = new DownloadReceiver() { - @Override - public void onDownloadDone(Uri uri) { - Intent intent = new Intent(getActivity(), FlashActivity.class); - intent.setData(uri) - .putExtra(FlashActivity.SET_BOOT, boot) - .putExtra(FlashActivity.SET_ENC, keepEncChkbox.isChecked()) - .putExtra(FlashActivity.SET_VERITY, keepVerityChkbox.isChecked()) - .putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_MAGISK); - startActivity(intent); - } - }; - break; - } - Utils.dlAndReceive( - getActivity(), - receiver, - mm.magiskLink, - Utils.getLegalFilename(filename) - ); - } - ).show(); - } - ) - .setNeutralButton(R.string.release_notes, (d, i) -> { - if (mm.releaseNoteLink != null) { - Intent openReleaseNoteLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink)); - openReleaseNoteLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mm.startActivity(openReleaseNoteLink); - } - }) - .setNegativeButton(R.string.no_thanks, null) - .show(); + ((NotificationManager) mm.getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll(); + Utils.showMagiskInstallDialog(this, + keepEncChkbox.isChecked(), keepVerityChkbox.isChecked()); } @OnClick(R.id.uninstall_button) - public void uninstall() { - new AlertDialogBuilder(getActivity()) - .setTitle(R.string.uninstall_magisk_title) - .setMessage(R.string.uninstall_magisk_msg) - .setPositiveButton(R.string.yes, (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(); - 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)); - getShell().su_raw( - "mv -f " + uninstaller + " /cache/" + UNINSTALLER, - "mv -f " + utils + " /data/magisk/" + UTIL_FUNCTIONS, - "reboot" - ); - } - }.start(); - } catch (IOException e) { - e.printStackTrace(); - } - }) - .setNegativeButton(R.string.no_thanks, null) - .show(); + void uninstall() { + Utils.showUninstallDialog(this); } @Nullable @@ -321,29 +157,6 @@ public class MagiskFragment extends Fragment } } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == SELECT_BOOT_IMG && resultCode == Activity.RESULT_OK && data != null) { - Utils.dlAndReceive( - getActivity(), - new DownloadReceiver() { - @Override - public void onDownloadDone(Uri uri) { - Intent intent = new Intent(getActivity(), FlashActivity.class); - intent.setData(uri) - .putExtra(FlashActivity.SET_BOOT, data.getData()) - .putExtra(FlashActivity.SET_ENC, keepEncChkbox.isChecked()) - .putExtra(FlashActivity.SET_VERITY, keepVerityChkbox.isChecked()) - .putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT); - startActivity(intent); - } - }, - mm.magiskLink, - Utils.getLegalFilename("Magisk-v" + mm.remoteMagiskVersionString + ".zip") - ); - } - } - @Override public void onTopicPublished(Topic topic) { if (topic == mm.updateCheckDone) { @@ -369,6 +182,25 @@ 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(); diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java index bdf092fd7..d006b1122 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/PolicyAdapter.java @@ -1,5 +1,6 @@ package com.topjohnwu.magisk.adapters; +import android.app.Activity; import android.content.pm.PackageManager; import android.support.design.widget.Snackbar; import android.support.v7.widget.RecyclerView; @@ -92,7 +93,7 @@ public class PolicyAdapter extends RecyclerView.Adapter new AlertDialogBuilder(v.getContext()) + holder.delete.setOnClickListener(v -> new AlertDialogBuilder((Activity) v.getContext()) .setTitle(R.string.su_revoke_title) .setMessage(v.getContext().getString(R.string.su_revoke_msg, policy.appName)) .setPositiveButton(R.string.yes, (dialog, which) -> { diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java index a9b92b6e1..08b749604 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java @@ -100,7 +100,7 @@ public class ReposAdapter extends SectionedAdapter { String filename = repo.getName() + "-" + repo.getVersion() + ".zip"; - new AlertDialogBuilder(context) + new AlertDialogBuilder((Activity) context) .setTitle(context.getString(R.string.repo_install_title, repo.getName())) .setMessage(context.getString(R.string.repo_install_msg, filename)) .setCancelable(true) diff --git a/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java b/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java new file mode 100644 index 000000000..d3a0b9406 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/asyncs/RestoreStockBoot.java @@ -0,0 +1,40 @@ +package com.topjohnwu.magisk.asyncs; + +import android.content.Context; +import android.widget.Toast; + +import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.utils.Utils; + +import java.util.List; + +public class RestoreStockBoot extends ParallelTask { + + private String mBoot; + + public RestoreStockBoot(Context context, String boot) { + super(context); + mBoot = boot; + } + + @Override + protected Boolean doInBackground(Void... voids) { + List 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("gzip -d < " + stock_boot + " | cat - /dev/zero | dd of=" + mBoot + " bs=4096"); + return true; + } + + @Override + protected void onPostExecute(Boolean result) { + if (result) { + getMagiskManager().toast(R.string.restore_done, Toast.LENGTH_SHORT); + } else { + getMagiskManager().toast(R.string.restore_fail, Toast.LENGTH_LONG); + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/components/AlertDialogBuilder.java b/app/src/main/java/com/topjohnwu/magisk/components/AlertDialogBuilder.java index a94f27a68..0c72a6ce1 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/AlertDialogBuilder.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/AlertDialogBuilder.java @@ -1,6 +1,6 @@ package com.topjohnwu.magisk.components; -import android.content.Context; +import android.app.Activity; import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -37,12 +37,12 @@ public class AlertDialogBuilder extends AlertDialog.Builder { private AlertDialog dialog; - public AlertDialogBuilder(@NonNull Context context) { + public AlertDialogBuilder(@NonNull Activity context) { super(context); setup(); } - public AlertDialogBuilder(@NonNull Context context, @StyleRes int themeResId) { + public AlertDialogBuilder(@NonNull Activity context, @StyleRes int themeResId) { super(context, themeResId); setup(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java b/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java index 494ae5637..7c2ef198d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/components/Fragment.java @@ -1,5 +1,7 @@ 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; @@ -7,6 +9,8 @@ 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()); } @@ -30,4 +34,20 @@ public class Fragment extends android.support.v4.app.Fragment { } super.onPause(); } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (activityResultListener != null) + activityResultListener.onActivityResult(requestCode, resultCode, data); + activityResultListener = null; + } + + public void startActivityForResult(Intent intent, int requestCode, ActivityResultListener listener) { + activityResultListener = listener; + super.startActivityForResult(intent, requestCode); + } + + public interface ActivityResultListener { + void onActivityResult(int requestCode, int resultCode, Intent data); + } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index a3e054f11..69e2c9441 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -5,6 +5,7 @@ import android.app.Activity; import android.app.DownloadManager; import android.app.NotificationManager; import android.app.PendingIntent; +import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -15,6 +16,7 @@ import android.database.Cursor; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; +import android.os.CountDownTimer; import android.os.Environment; import android.provider.OpenableColumns; import android.support.annotation.StringRes; @@ -24,18 +26,26 @@ import android.support.v4.app.FragmentActivity; 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.util.ArrayList; import java.util.Collections; @@ -45,6 +55,9 @@ 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; @@ -185,7 +198,7 @@ public class Utils { return networkInfo != null && networkInfo.isConnected(); } - public static void showMagiskUpdate(MagiskManager mm) { + 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)) @@ -205,7 +218,7 @@ public class Utils { notificationManager.notify(MAGISK_UPDATE_NOTIFICATION_ID, builder.build()); } - public static void showManagerUpdate(MagiskManager mm) { + 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)) @@ -314,4 +327,180 @@ public class Utils { 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 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)); + } + new AlertDialog.Builder(fragment.getActivity()) + .setTitle(R.string.select_method) + .setItems( + options.toArray(new String [0]), + (dialog, idx) -> { + DownloadReceiver receiver = null; + switch (idx) { + case 1: + if (mm.remoteMagiskVersionCode < 1370) { + mm.toast(R.string.no_boot_file_patch_support, Toast.LENGTH_LONG); + return; + } + 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: + final String 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; + } + Utils.dlAndReceive( + mm, + receiver, + mm.magiskLink, + filename + ); + } + ).show(); + }) + .setNeutralButton(R.string.release_notes, (d, i) -> { + if (mm.releaseNoteLink != null) { + Intent openLink = new Intent(Intent.ACTION_VIEW, Uri.parse(mm.releaseNoteLink)); + openLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mm.startActivity(openLink); + } + }) + .setNegativeButton(R.string.no_thanks, null) + .show(); + } + + public static void showManagerInstallDialog(Activity activity) { + MagiskManager mm = Utils.getMagiskManager(activity); + new AlertDialogBuilder(activity) + .setTitle(mm.getString(R.string.repo_install_title, mm.getString(R.string.app_name))) + .setMessage(mm.getString(R.string.repo_install_msg, + Utils.getLegalFilename("MagiskManager-v" + + mm.remoteManagerVersionString + ".apk"))) + .setCancelable(true) + .setPositiveButton(R.string.install, (d, i) -> { + Intent intent = new Intent(mm, ManagerUpdate.class); + intent.putExtra(MagiskManager.INTENT_LINK, mm.managerLink); + intent.putExtra(MagiskManager.INTENT_VERSION, mm.remoteManagerVersionString); + mm.sendBroadcast(intent); + }) + .setNegativeButton(R.string.no_thanks, null) + .show(); + } + + public static void showUninstallDialog(MagiskFragment fragment) { + MagiskManager mm = Utils.getMagiskManager(fragment.getActivity()); + new AlertDialogBuilder(fragment.getActivity()) + .setTitle(R.string.uninstall_magisk_title) + .setMessage(R.string.uninstall_magisk_msg) + .setPositiveButton(R.string.complete_uninstall, (d, i) -> { + try { + InputStream in = mm.getAssets().open(UNINSTALLER); + File uninstaller = new File(mm.getCacheDir(), UNINSTALLER); + FileOutputStream out = new FileOutputStream(uninstaller); + byte[] bytes = new byte[1024]; + int read; + while ((read = in.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + in.close(); + out.close(); + in = mm.getAssets().open(UTIL_FUNCTIONS); + File utils = new File(mm.getCacheDir(), UTIL_FUNCTIONS); + out = new FileOutputStream(utils); + while ((read = in.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + in.close(); + out.close(); + ProgressDialog progress = new ProgressDialog(fragment.getActivity()); + progress.setTitle(R.string.reboot); + progress.show(); + new CountDownTimer(5000, 1000) { + @Override + public void onTick(long millisUntilFinished) { + progress.setMessage(mm.getString(R.string.reboot_countdown, + millisUntilFinished / 1000)); + } + + @Override + public void onFinish() { + progress.setMessage(mm.getString(R.string.reboot_countdown, 0)); + Shell.getShell(mm).su_raw( + "mv -f " + uninstaller + " /cache/" + UNINSTALLER, + "mv -f " + utils + " /data/magisk/" + UTIL_FUNCTIONS, + "reboot" + ); + } + }.start(); + } 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(); + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_magisk.xml b/app/src/main/res/layout/fragment_magisk.xml index aade9985e..92bf74f45 100644 --- a/app/src/main/res/layout/fragment_magisk.xml +++ b/app/src/main/res/layout/fragment_magisk.xml @@ -399,7 +399,7 @@ android:id="@+id/imageView" android:layout_width="50dp" android:layout_height="wrap_content" - android:layout_marginEnd="20dp" + android:layout_marginEnd="5dp" android:layout_weight="0" app:srcCompat="@mipmap/ic_launcher" /> @@ -419,7 +419,7 @@ diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 8a9422ecd..aeb112066 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -38,7 +38,6 @@ إلغاء التثبيت إعادة التشغيل في %1$d إلغاء تثبيت Magisk - سيؤدي هذا إلى إزالة جميع الإضافات، MagiskSU، وربما تشفير البيانات الخاصة بك إذا لم يتم تشفيرها\nهل أنت متأكد من الاستمرار؟ (لم يتم توفير أي معلومات) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 77109feb3..3be66b69f 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -34,7 +34,6 @@ Odinstalovat Restart za %1$d Odinstalovat Magisk - Tímto odstraníte veškeré moduly, MagiskSU a potencionálně zašifrujete svá data pokud ještě nejsou\nOpravdu chcete pokračovat? (Žádné info) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 6cc8fcf2e..aaea1b6a9 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -41,7 +41,6 @@ Deinstallieren Neustart in %1$d Magisk deinstallieren - Dies entfernt alle Module, MagiskSU und verschlüsselt unter Umständen deine Daten, falls nicht bereits verschlüsselt.\nMöchtest du wirklich fortfahren? (Nichts angegeben) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index b90d75784..dfbe89318 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -36,7 +36,6 @@ Απεγκατάσταση Επανεκκίνηση σε %1$d Απεγκατάσταση Magisk - Αυτό θα αφαιρέσει όλες τις ενότητες, το MagiskSU και πιθανόν να κρυπτογραφήσει τα δεδομένα σας αν δεν είναι κρυπτογραφυμένα\nΕίστε σίγουρος/η ότι θέλετε να συνεχίσετε; Ενημέρωση %1$s diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e01b06f4f..ad4500f0c 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -38,7 +38,6 @@ Desinstalar Reiniciando en %1$d Desinstalar Magisk - Esto eliminará todos los módulos, MagiskSU, y potencialmente puede cifrar sus datos si no está encriptada\nEstas seguro de continuar? Actualización %1$s diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 679513bba..fa15bb9fe 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -30,7 +30,6 @@ Désinstaller Redémarrage dans %1$d Désinstaller Magisk - Cela va supprimer tous les modules, MagiskSU et éventuellement chiffrer vos données si vous n\'êtes pas chiffré\nÊtes-vous sûr de vouloir continuer ? (Aucune information transmise) Aucun module trouvé diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 425be444c..962125911 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -38,7 +38,6 @@ Disinstalla Riavvio tra %1$d Disinstalla Magisk - Questo rimuoverà tutti i moduli, MagiskSU, e potenzialmente crittograferà i dati, se non crittografati/nVuoi continuare? Aggiorna %1$s diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 92017298f..da75be5c2 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -34,7 +34,6 @@ アンインストール %1$dで再起動します Magiskをアンインストールします - これにより、すべてのモジュールとMagiskSUを削除します。暗号化されていないデータが暗号化される可能性があります。\ n続行しますか? (情報がありません) diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 304808a30..d2c2ad927 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -34,7 +34,6 @@ 제거 %1$d초 안에 다시 시작됨 Magisk 제거 - 모든 모듈과 MagiskSU를 제거합니다. 또한 데이터가 암호화되어 있지 않은 경우 암호화될 가능성이 있습니다.\n정말 계속하시겠습니까? (제공된 정보 없음) diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 6b87475a1..f7969c584 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -38,7 +38,6 @@ Deïnstalleren Herstarten in %1$d Magisk deïnstalleren - Dit verwijdert alle modules, MagiskSU, en versleutelt mogelijk alle niet-versleutelde data\nZeker weten voortzetten? Bijwerken %1$s diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index a3241b6c7..abcd8c75a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -41,7 +41,6 @@ Odinstaluj Restartuj do %1$d Odinstaluj Magisk - Spowoduje to usunięcie wszystkich modułów, MagiskSU i potencjalnie szyfrowanie danych jeśli nie były szyfrowane \ nCzy na pewno kontynuować? Aktualizacja %1$s diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 9a698984d..cbb9f6f53 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -41,7 +41,6 @@ Desinstalar Reiniciando em %1$d Desinstalar Magisk - Isso removerá todos os módulos, MagiskSU, e Potencialmente criptografar seus dados se não criptografados\nVocê deseja continuar? (Nenhuma informação fornecida) diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 52d706e0b..1b7bfbd5d 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -38,8 +38,6 @@ Desinstalar A reiniciar em %1$d Desinstalar Magisk -Isso irá remover todos os módulos, MagiskSU, e Potencialmente encriptar seus dados se estiverem encriptados -\nDeseja continuar? Atualizar %1$s diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 3dd31a425..59e904cfc 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -32,7 +32,6 @@ Dezinstalare Repornire în %1$d Dezinstalare Magisk - Aceasta va elimina toate modulele, MagiskSU, şi potențial să cripteze datele, dacă nu sunt criptate\nContinuaţi? Actualizare %1$s diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ae09895c8..45e502bbb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -38,7 +38,6 @@ Удалить Перезагрузка через %1$d Удалить Magisk - Данное действие приведет к удалению всех модулей, MagiskSU, и может зашифровать данные, если они не зашифрованы.\nУверены, что желаете продолжить? Обновить %1$s diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 6784fd387..0a1217373 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -38,7 +38,6 @@ Avinstallera Omstart om %1$d Avinstallera Magisk - Detta kommer att ta bort alla moduler, MagiskSU, och potentiellt kryptera din data om inte krypterad\nÄr det säker du vill fortsätta? Uppdatera %1$s diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index f3aecc85b..ab9b9f4b8 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -37,7 +37,6 @@ Kaldır %1$d saniye içinde yeniden başlatılacak "Magisk\'i kaldır" - "Bu, tüm modülleri, MagiskSU\'yu kaldıracak ve şifrelenmemişse verilerinizi potansiyel olarak şifreleyecektir\nDevam etmek istediğinize emin misiniz?" Güncelle %1$s diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 827552fd7..f77b07089 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -37,7 +37,6 @@ Видалити Перезавантаження через %1$d Видалити Magisk - Ця дія призведе до видалення всіх модулів, MagiskSU, і може зашифрувати дані, якщо вони не зашифровані.\nВпевнені, що бажаєте продовжити? Оновити %1$s diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index de3205e9d..221cb1b6a 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -34,7 +34,6 @@ Gỡ bỏ Khởi động lại trong %1$d Gỡ bỏ Magisk - Việc này sẽ xoá tất cả các mô-đun, MagiskSU và có khả năng sẽ mã hoá dữ liệu nếu chưa được mã hoá\nBạn chắc muốn tiếp tục? (Không có thông tin được cung cấp) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 52507ecf8..64b190733 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -38,7 +38,6 @@ 卸载 将在 %1$d 后重启 卸载 Magisk - 将会删除所有模块及 MagiskSU,并有可能在目前未加密的情况下加密你的数据\n你确定要继续吗? 更新 %1$s diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 33e45cd50..14d995105 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -157,7 +157,7 @@ 下載 處理中 解除安裝 Magisk - 這將會刪除所有模組,MagiskSU,並有可能在目前資料未加密的情況下進行加密\n你確定要繼續嗎? + 所有模組將會被停用 / 刪除。root會被移除,並有可能在目前資料未加密的情況下被加密 請手動選取 boot 映像位置 (無法自動偵測) 有更新的時候顯示通知 @@ -208,5 +208,9 @@ 正在下載 正在下載 Zip 文件 … 選擇已補丁 Boot 映像文件輸出格式\n若要透過 fastboot/download 模式刷入,請選擇 .img 格式;若要透過 ODIN 刷入,則選擇 .img.tar\n + 完全解除安裝 + 還原原廠 boot 映像 + 還原完成! + 原廠 boot 映像備份不存在! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b3f8fd107..bc5079604 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -41,7 +41,7 @@ Uninstall Rebooting in %1$d Uninstall Magisk - This will remove all modules, MagiskSU, and potentially encrypt your data if not encrypted\nAre you sure to continue? + All modules will be disabled/removed. Root will be removed, and potentially encrypt your data if your data is not currently encrypted Update %1$s @@ -116,6 +116,10 @@ Direct Install (Recommend) Select Method Target Magisk version doesn\'t support boot image file patching + Complete Uninstall + Restore Stock Boot + Restoration done! + Stock backup does not exist! General