Add boot image file patch
This commit is contained in:
parent
dbe6e5b3d7
commit
db8fd2c913
@ -1,5 +1,6 @@
|
|||||||
package com.topjohnwu.magisk;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
@ -8,12 +9,17 @@ import android.support.v7.widget.Toolbar;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.asyncs.FlashZip;
|
import com.topjohnwu.magisk.asyncs.FlashZip;
|
||||||
|
import com.topjohnwu.magisk.asyncs.PatchBootImage;
|
||||||
import com.topjohnwu.magisk.components.Activity;
|
import com.topjohnwu.magisk.components.Activity;
|
||||||
import com.topjohnwu.magisk.utils.AdaptiveList;
|
import com.topjohnwu.magisk.utils.AdaptiveList;
|
||||||
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
@ -21,11 +27,15 @@ import butterknife.OnClick;
|
|||||||
|
|
||||||
public class FlashActivity extends Activity {
|
public class FlashActivity extends Activity {
|
||||||
|
|
||||||
|
public static final String SET_ACTION = "action";
|
||||||
|
public static final String SET_BOOT_URI = "boot_uri";
|
||||||
|
public static final String FLASH_ZIP = "flash";
|
||||||
|
public static final String PATCH_BOOT = "patch";
|
||||||
|
|
||||||
@BindView(R.id.toolbar) Toolbar toolbar;
|
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||||
@BindView(R.id.flash_logs) RecyclerView flashLogs;
|
@BindView(R.id.flash_logs) RecyclerView flashLogs;
|
||||||
@BindView(R.id.button_panel) LinearLayout buttonPanel;
|
@BindView(R.id.button_panel) LinearLayout buttonPanel;
|
||||||
|
@BindView(R.id.reboot) Button reboot;
|
||||||
private AdaptiveList<String> rootShellOutput;
|
|
||||||
|
|
||||||
@OnClick(R.id.no_thanks)
|
@OnClick(R.id.no_thanks)
|
||||||
public void dismiss() {
|
public void dismiss() {
|
||||||
@ -42,22 +52,33 @@ public class FlashActivity extends Activity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_flash);
|
setContentView(R.layout.activity_flash);
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
rootShellOutput = new AdaptiveList<>(flashLogs);
|
AdaptiveList<String> rootShellOutput = new AdaptiveList<>(flashLogs);
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
ActionBar ab = getSupportActionBar();
|
ActionBar ab = getSupportActionBar();
|
||||||
if (ab != null) {
|
if (ab != null) {
|
||||||
ab.setTitle(R.string.flashing);
|
ab.setTitle(R.string.flashing);
|
||||||
}
|
}
|
||||||
setFloating();
|
setFloating();
|
||||||
|
if (!Shell.rootAccess())
|
||||||
|
reboot.setVisibility(View.GONE);
|
||||||
|
|
||||||
flashLogs.setAdapter(new FlashLogAdapter());
|
flashLogs.setAdapter(new FlashLogAdapter(rootShellOutput));
|
||||||
|
|
||||||
// We must receive a Uri of the target zip
|
// We must receive a Uri of the target zip
|
||||||
Uri uri = getIntent().getData();
|
Intent intent = getIntent();
|
||||||
|
Uri uri = intent.getData();
|
||||||
|
|
||||||
|
switch (getIntent().getStringExtra(SET_ACTION)) {
|
||||||
|
case FLASH_ZIP:
|
||||||
new FlashZip(this, uri, rootShellOutput)
|
new FlashZip(this, uri, rootShellOutput)
|
||||||
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
|
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
|
||||||
.exec();
|
.exec();
|
||||||
|
break;
|
||||||
|
case PATCH_BOOT:
|
||||||
|
new PatchBootImage(this, uri, intent.getParcelableExtra(SET_BOOT_URI), rootShellOutput)
|
||||||
|
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
|
||||||
|
.exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -65,7 +86,13 @@ public class FlashActivity extends Activity {
|
|||||||
// Prevent user accidentally press back button
|
// Prevent user accidentally press back button
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
|
private static class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||||
|
|
||||||
|
private List<String> mList;
|
||||||
|
|
||||||
|
FlashLogAdapter(List<String> list) {
|
||||||
|
mList = list;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
@ -76,16 +103,16 @@ public class FlashActivity extends Activity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
holder.text.setText(rootShellOutput.get(position));
|
holder.text.setText(mList.get(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return rootShellOutput.size();
|
return mList.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@BindView(R.id.textView) TextView text;
|
@BindView(R.id.textView) TextView text;
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.topjohnwu.magisk;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@ -49,15 +51,15 @@ import butterknife.Unbinder;
|
|||||||
public class MagiskFragment extends Fragment
|
public class MagiskFragment extends Fragment
|
||||||
implements Topic.Subscriber, SwipeRefreshLayout.OnRefreshListener, ExpandableView {
|
implements Topic.Subscriber, SwipeRefreshLayout.OnRefreshListener, ExpandableView {
|
||||||
|
|
||||||
public static final String SHOW_DIALOG = "dialog";
|
|
||||||
|
|
||||||
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
private static final String UNINSTALLER = "magisk_uninstaller.sh";
|
||||||
private static final String UTIL_FUNCTIONS= "util_functions.sh";
|
private static final String UTIL_FUNCTIONS= "util_functions.sh";
|
||||||
|
private static final int SELECT_BOOT_IMG = 3;
|
||||||
|
|
||||||
private Container expandableContainer = new Container();
|
private Container expandableContainer = new Container();
|
||||||
|
|
||||||
private MagiskManager magiskManager;
|
private MagiskManager magiskManager;
|
||||||
private Unbinder unbinder;
|
private Unbinder unbinder;
|
||||||
|
private static boolean shownDialog = false;
|
||||||
|
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
|
|
||||||
@ -108,6 +110,7 @@ public class MagiskFragment extends Fragment
|
|||||||
|
|
||||||
@OnClick(R.id.install_button)
|
@OnClick(R.id.install_button)
|
||||||
public void install() {
|
public void install() {
|
||||||
|
shownDialog = true;
|
||||||
String bootImage = null;
|
String bootImage = null;
|
||||||
if (Shell.rootAccess()) {
|
if (Shell.rootAccess()) {
|
||||||
if (magiskManager.bootBlock != null) {
|
if (magiskManager.bootBlock != null) {
|
||||||
@ -117,44 +120,73 @@ public class MagiskFragment extends Fragment
|
|||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
bootImage = magiskManager.blockList.get(idx - 1);
|
bootImage = magiskManager.blockList.get(idx - 1);
|
||||||
} else {
|
} else {
|
||||||
SnackbarMaker.make(getActivity(), R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
|
SnackbarMaker.make(getActivity(),
|
||||||
|
R.string.manual_boot_image, Snackbar.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final String boot = bootImage;
|
||||||
((NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
|
((NotificationManager) getActivity().getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
|
||||||
final String finalBootImage = bootImage;
|
|
||||||
String filename = "Magisk-v" + magiskManager.remoteMagiskVersionString + ".zip";
|
String filename = "Magisk-v" + magiskManager.remoteMagiskVersionString + ".zip";
|
||||||
new AlertDialogBuilder(getActivity())
|
new AlertDialogBuilder(getActivity())
|
||||||
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
.setTitle(getString(R.string.repo_install_title, getString(R.string.magisk)))
|
||||||
.setMessage(getString(R.string.repo_install_msg, filename))
|
.setMessage(getString(R.string.repo_install_msg, filename))
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setPositiveButton(Shell.rootAccess() ? R.string.install : R.string.download,
|
.setPositiveButton(
|
||||||
(d, i) ->
|
R.string.install,
|
||||||
Utils.dlAndReceive(
|
(d, i) -> {
|
||||||
getActivity(),
|
List<String> options = new ArrayList<>();
|
||||||
new DownloadReceiver() {
|
options.add(getString(R.string.download_zip_only));
|
||||||
private String boot = finalBootImage;
|
options.add(getString(R.string.patch_boot_file));
|
||||||
private boolean enc = keepEncChkbox.isChecked();
|
if (Shell.rootAccess()) {
|
||||||
private boolean verity = keepVerityChkbox.isChecked();
|
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:
|
||||||
|
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||||
|
intent.setType("*/*");
|
||||||
|
startActivityForResult(intent, SELECT_BOOT_IMG);
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
receiver = new DownloadReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadDone(Uri uri) {
|
public void onDownloadDone(Uri uri) {
|
||||||
if (Shell.rootAccess()) {
|
|
||||||
getShell().su_raw(
|
|
||||||
"rm -f /dev/.magisk",
|
|
||||||
"echo \"BOOTIMAGE=" + boot + "\" >> /dev/.magisk",
|
|
||||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
|
|
||||||
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
|
|
||||||
);
|
|
||||||
startActivity(new Intent(getActivity(), FlashActivity.class).setData(uri));
|
|
||||||
} else {
|
|
||||||
Utils.showUriSnack(getActivity(), uri);
|
Utils.showUriSnack(getActivity(), uri);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
receiver = new DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onDownloadDone(Uri uri) {
|
||||||
|
getShell().su_raw(
|
||||||
|
"echo \"BOOTIMAGE=" + boot + "\" > /dev/.magisk",
|
||||||
|
"echo \"KEEPFORCEENCRYPT=" + keepEncChkbox.isChecked() + "\" >> /dev/.magisk",
|
||||||
|
"echo \"KEEPVERITY=" + keepVerityChkbox.isChecked() + "\" >> /dev/.magisk"
|
||||||
|
);
|
||||||
|
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
||||||
|
intent.setData(uri).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
|
||||||
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Utils.dlAndReceive(
|
||||||
|
getActivity(),
|
||||||
|
receiver,
|
||||||
magiskManager.magiskLink,
|
magiskManager.magiskLink,
|
||||||
Utils.getLegalFilename(filename))
|
Utils.getLegalFilename(filename)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
).show();
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.setNeutralButton(R.string.release_notes, (d, i) -> {
|
.setNeutralButton(R.string.release_notes, (d, i) -> {
|
||||||
if (magiskManager.releaseNoteLink != null) {
|
if (magiskManager.releaseNoteLink != null) {
|
||||||
@ -172,7 +204,7 @@ public class MagiskFragment extends Fragment
|
|||||||
new AlertDialogBuilder(getActivity())
|
new AlertDialogBuilder(getActivity())
|
||||||
.setTitle(R.string.uninstall_magisk_title)
|
.setTitle(R.string.uninstall_magisk_title)
|
||||||
.setMessage(R.string.uninstall_magisk_msg)
|
.setMessage(R.string.uninstall_magisk_msg)
|
||||||
.setPositiveButton(R.string.yes, (dialogInterface, i) -> {
|
.setPositiveButton(R.string.yes, (d, i) -> {
|
||||||
try {
|
try {
|
||||||
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
InputStream in = magiskManager.getAssets().open(UNINSTALLER);
|
||||||
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
File uninstaller = new File(magiskManager.getCacheDir(), UNINSTALLER);
|
||||||
@ -254,6 +286,8 @@ public class MagiskFragment extends Fragment
|
|||||||
magiskManager.remoteMagiskVersionCode = -1;
|
magiskManager.remoteMagiskVersionCode = -1;
|
||||||
collapse();
|
collapse();
|
||||||
|
|
||||||
|
shownDialog = false;
|
||||||
|
|
||||||
// Trigger state check
|
// Trigger state check
|
||||||
if (Utils.checkNetworkStatus(magiskManager)) {
|
if (Utils.checkNetworkStatus(magiskManager)) {
|
||||||
new CheckUpdates(getActivity()).exec();
|
new CheckUpdates(getActivity()).exec();
|
||||||
@ -262,6 +296,28 @@ 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) {
|
||||||
|
// Get the URI of the selected file
|
||||||
|
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
||||||
|
intent.setData(uri)
|
||||||
|
.putExtra(FlashActivity.SET_BOOT_URI, data.getData())
|
||||||
|
.putExtra(FlashActivity.SET_ACTION, FlashActivity.PATCH_BOOT);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
magiskManager.magiskLink,
|
||||||
|
Utils.getLegalFilename("Magisk-v" + magiskManager.remoteMagiskVersionString + ".zip")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTopicPublished(Topic topic) {
|
public void onTopicPublished(Topic topic) {
|
||||||
if (topic == magiskManager.updateCheckDone) {
|
if (topic == magiskManager.updateCheckDone) {
|
||||||
@ -341,7 +397,7 @@ public class MagiskFragment extends Fragment
|
|||||||
rootStatusIcon.setColorFilter(color);
|
rootStatusIcon.setColorFilter(color);
|
||||||
|
|
||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
installText.setText(R.string.download);
|
installText.setText(R.string.install);
|
||||||
} else {
|
} else {
|
||||||
if (magiskManager.remoteMagiskVersionCode > magiskManager.magiskVersionCode) {
|
if (magiskManager.remoteMagiskVersionCode > magiskManager.magiskVersionCode) {
|
||||||
installText.setText(R.string.update);
|
installText.setText(R.string.update);
|
||||||
@ -384,7 +440,7 @@ public class MagiskFragment extends Fragment
|
|||||||
magiskUpdateProgress.setVisibility(View.GONE);
|
magiskUpdateProgress.setVisibility(View.GONE);
|
||||||
mSwipeRefreshLayout.setRefreshing(false);
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
|
|
||||||
if (magiskManager.remoteMagiskVersionCode > magiskManager.magiskVersionCode)
|
if (magiskManager.remoteMagiskVersionCode > magiskManager.magiskVersionCode && !shownDialog)
|
||||||
install();
|
install();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ public class ModulesFragment extends Fragment implements Topic.Subscriber {
|
|||||||
if (requestCode == FETCH_ZIP_CODE && resultCode == Activity.RESULT_OK && data != null) {
|
if (requestCode == FETCH_ZIP_CODE && resultCode == Activity.RESULT_OK && data != null) {
|
||||||
// Get the URI of the selected file
|
// Get the URI of the selected file
|
||||||
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
||||||
intent.setData(data.getData()).putExtra("ACTION", "flash");
|
intent.setData(data.getData()).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ public class SettingsActivity extends Activity implements Topic.Subscriber {
|
|||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
prefScreen.removePreference(magiskCategory);
|
prefScreen.removePreference(magiskCategory);
|
||||||
prefScreen.removePreference(suCategory);
|
prefScreen.removePreference(suCategory);
|
||||||
|
generalCatagory.removePreference(hideManager);
|
||||||
} else {
|
} else {
|
||||||
if (!magiskManager.isSuClient) {
|
if (!magiskManager.isSuClient) {
|
||||||
prefScreen.removePreference(suCategory);
|
prefScreen.removePreference(suCategory);
|
||||||
|
@ -18,7 +18,7 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FlashZip extends ParallelTask<Void, String, Integer> {
|
public class FlashZip extends ParallelTask<Void, Void, Integer> {
|
||||||
|
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
private File mCachedFile, mScriptFile, mCheckFile;
|
private File mCachedFile, mScriptFile, mCheckFile;
|
||||||
@ -40,7 +40,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean unzipAndCheck() throws Exception {
|
private boolean unzipAndCheck() throws Exception {
|
||||||
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android");
|
ZipUtils.unzip(mCachedFile, mCachedFile.getParentFile(), "META-INF/com/google/android", false);
|
||||||
List<String> ret = Utils.readFile(getShell(), mCheckFile.getPath());
|
List<String> ret = Utils.readFile(getShell(), mCheckFile.getPath());
|
||||||
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onProgressUpdate(String... values) {
|
protected void onProgressUpdate(Void... values) {
|
||||||
mList.updateView();
|
mList.updateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,18 +61,18 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
MagiskManager magiskManager = getMagiskManager();
|
MagiskManager magiskManager = getMagiskManager();
|
||||||
if (magiskManager == null) return -1;
|
if (magiskManager == null) return -1;
|
||||||
try {
|
try {
|
||||||
mList.add(magiskManager.getString(R.string.copying_msg));
|
mList.add("- Copying zip to temp directory");
|
||||||
|
|
||||||
mCachedFile.delete();
|
mCachedFile.delete();
|
||||||
try (
|
try (
|
||||||
InputStream in = magiskManager.getContentResolver().openInputStream(mUri);
|
InputStream in = magiskManager.getContentResolver().openInputStream(mUri);
|
||||||
OutputStream outputStream = new FileOutputStream(mCachedFile)
|
OutputStream out = new FileOutputStream(mCachedFile)
|
||||||
) {
|
) {
|
||||||
if (in == null) throw new FileNotFoundException();
|
if (in == null) throw new FileNotFoundException();
|
||||||
byte buffer[] = new byte[1024];
|
byte buffer[] = new byte[1024];
|
||||||
int length;
|
int length;
|
||||||
while ((length = in.read(buffer)) > 0)
|
while ((length = in.read(buffer)) > 0)
|
||||||
outputStream.write(buffer, 0, length);
|
out.write(buffer, 0, length);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
mList.add("! Invalid Uri");
|
mList.add("! Invalid Uri");
|
||||||
throw e;
|
throw e;
|
||||||
@ -81,7 +81,7 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
if (!unzipAndCheck()) return 0;
|
if (!unzipAndCheck()) return 0;
|
||||||
mList.add(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
mList.add("- Installing " + mFilename);
|
||||||
getShell().su(mList,
|
getShell().su(mList,
|
||||||
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile +
|
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile +
|
||||||
" && echo 'Success!' || echo 'Failed!'"
|
" && echo 'Success!' || echo 'Failed!'"
|
||||||
|
@ -0,0 +1,145 @@
|
|||||||
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
|
import com.topjohnwu.magisk.utils.AdaptiveList;
|
||||||
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PatchBootImage extends ParallelTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
|
private Uri mBootImg, mZip;
|
||||||
|
private AdaptiveList<String> mList;
|
||||||
|
private File dest;
|
||||||
|
|
||||||
|
public PatchBootImage(Activity context, Uri zip, Uri boot, AdaptiveList<String> list) {
|
||||||
|
super(context);
|
||||||
|
mBootImg = boot;
|
||||||
|
mList = list;
|
||||||
|
mZip = zip;
|
||||||
|
dest = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + "patched_boot.img");
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 magiskManager = getMagiskManager();
|
||||||
|
if (magiskManager == null) return false;
|
||||||
|
|
||||||
|
File install = new File(magiskManager.getApplicationInfo().dataDir, "install");
|
||||||
|
getShell().sh_raw("rm -rf " + install);
|
||||||
|
|
||||||
|
List<String> abis = Arrays.asList(Build.SUPPORTED_ABIS);
|
||||||
|
String arch;
|
||||||
|
if (abis.contains("x86_64")) arch = "x64";
|
||||||
|
else if (abis.contains("arm64-v8a")) arch = "arm64";
|
||||||
|
else if (abis.contains("x86")) arch = "x86";
|
||||||
|
else arch = "arm";
|
||||||
|
mList.add("- Device platform: " + arch);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Unzip files
|
||||||
|
mList.add("- Extracting files");
|
||||||
|
try (InputStream in = magiskManager.getContentResolver().openInputStream(mZip)) {
|
||||||
|
if (in == null) throw new FileNotFoundException();
|
||||||
|
BufferedInputStream buf = new BufferedInputStream(in);
|
||||||
|
buf.mark(Integer.MAX_VALUE);
|
||||||
|
ZipUtils.unzip(buf, install, arch, true);
|
||||||
|
buf.reset();
|
||||||
|
ZipUtils.unzip(buf, install, "common", true);
|
||||||
|
buf.reset();
|
||||||
|
ZipUtils.unzip(buf, install, "chromeos", false);
|
||||||
|
buf.reset();
|
||||||
|
ZipUtils.unzip(buf, install, "META-INF/com/google/android/update-binary", true);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
mList.add("! Invalid Uri");
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
mList.add("! Cannot unzip zip");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy boot image
|
||||||
|
File boot = new File(install, "boot.img");
|
||||||
|
try (
|
||||||
|
InputStream in = magiskManager.getContentResolver().openInputStream(mBootImg);
|
||||||
|
OutputStream out = new FileOutputStream(boot);
|
||||||
|
) {
|
||||||
|
if (in == null) throw new FileNotFoundException();
|
||||||
|
byte buffer[] = new byte[1024];
|
||||||
|
int length;
|
||||||
|
while ((length = in.read(buffer)) > 0)
|
||||||
|
out.write(buffer, 0, length);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
mList.add("! Invalid Uri");
|
||||||
|
throw e;
|
||||||
|
} catch (IOException e) {
|
||||||
|
mList.add("! Copy failed");
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
mList.add("- Use boot image: " + boot);
|
||||||
|
|
||||||
|
// Patch boot image
|
||||||
|
getShell().sh(mList,
|
||||||
|
"chmod -R 755 " + install,
|
||||||
|
"cd " + install,
|
||||||
|
"sh update-binary indep boot_patch.sh " + boot +
|
||||||
|
" && echo 'Success!' || echo 'Failed!'"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Move boot image
|
||||||
|
File source = new File(install, "new-boot.img");
|
||||||
|
dest.getParentFile().mkdirs();
|
||||||
|
getShell().sh_raw("mv " + source + " " + dest);
|
||||||
|
|
||||||
|
// Finals
|
||||||
|
getShell().sh_raw(
|
||||||
|
"mv bin/busybox busybox",
|
||||||
|
"rm -rf bin *.img update-binary");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Boolean result) {
|
||||||
|
if (result) {
|
||||||
|
mList.add("");
|
||||||
|
mList.add("*********************************");
|
||||||
|
mList.add(" Patched Boot Image is placed in ");
|
||||||
|
mList.add(" " + dest + " ");
|
||||||
|
mList.add("*********************************");
|
||||||
|
}
|
||||||
|
super.onPostExecute(result);
|
||||||
|
}
|
||||||
|
}
|
@ -94,12 +94,15 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
|
|||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
if (result) {
|
if (result) {
|
||||||
if (Shell.rootAccess() && mInstall) {
|
if (Shell.rootAccess() && mInstall) {
|
||||||
activity.startActivity(new Intent(activity, FlashActivity.class).setData(mUri));
|
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
||||||
|
intent.setData(mUri).putExtra(FlashActivity.SET_ACTION, FlashActivity.FLASH_ZIP);
|
||||||
|
activity.startActivity(intent);
|
||||||
} else {
|
} else {
|
||||||
Utils.showUriSnack(activity, mUri);
|
Utils.showUriSnack(activity, mUri);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Utils.getMagiskManager(activity).toast(R.string.process_error, Toast.LENGTH_LONG);
|
Utils.getMagiskManager(activity).toast(R.string.process_error, Toast.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
|
super.onPostExecute(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,34 +156,38 @@ public class ZipUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unzip(File file, File folder, String path) throws Exception {
|
public static void unzip(File zip, File folder, String path, boolean junkPath) throws Exception {
|
||||||
int count;
|
JarInputStream in = new JarInputStream(new FileInputStream(zip));
|
||||||
FileOutputStream out;
|
unzip(in, folder, path, junkPath);
|
||||||
File dest;
|
in.close();
|
||||||
InputStream is;
|
}
|
||||||
JarEntry entry;
|
|
||||||
|
public static void unzip(InputStream zip, File folder, String path, boolean junkPath) throws Exception {
|
||||||
byte data[] = new byte[4096];
|
byte data[] = new byte[4096];
|
||||||
try (JarFile zipfile = new JarFile(file)) {
|
try {
|
||||||
Enumeration<JarEntry> e = zipfile.entries();
|
JarInputStream zipfile = new JarInputStream(zip);
|
||||||
while(e.hasMoreElements()) {
|
JarEntry entry;
|
||||||
entry = e.nextElement();
|
while ((entry = zipfile.getNextJarEntry()) != null) {
|
||||||
if (!entry.getName().contains(path) || entry.isDirectory()){
|
if (!entry.getName().startsWith(path) || entry.isDirectory()){
|
||||||
// Ignore directories, only create files
|
// Ignore directories, only create files
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Logger.dev("ZipUtils: Extracting: " + entry);
|
String name;
|
||||||
is = zipfile.getInputStream(entry);
|
if (junkPath) {
|
||||||
dest = new File(folder, entry.getName());
|
name = entry.getName().substring(entry.getName().lastIndexOf('/') + 1);
|
||||||
if (dest.getParentFile().mkdirs()) {
|
} else {
|
||||||
dest.createNewFile();
|
name = entry.getName();
|
||||||
}
|
}
|
||||||
out = new FileOutputStream(dest);
|
Logger.dev("ZipUtils: Extracting: " + entry);
|
||||||
while ((count = is.read(data)) != -1) {
|
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);
|
out.write(data, 0, count);
|
||||||
}
|
}
|
||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
is.close();
|
|
||||||
}
|
}
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -138,6 +138,10 @@
|
|||||||
<string name="flashing">Flashing</string>
|
<string name="flashing">Flashing</string>
|
||||||
<string name="hide_manager_toast">Hiding Magisk Manager…</string>
|
<string name="hide_manager_toast">Hiding Magisk Manager…</string>
|
||||||
<string name="hide_manager_fail_toast">Hide Magisk Manager failed…</string>
|
<string name="hide_manager_fail_toast">Hide Magisk Manager failed…</string>
|
||||||
|
<string name="download_zip_only">Download Zip Only</string>
|
||||||
|
<string name="patch_boot_file">Patch Boot Image File</string>
|
||||||
|
<string name="direct_install">Direct Install (Recommend)</string>
|
||||||
|
<string name="select_method">Select Method</string>
|
||||||
|
|
||||||
<!--Settings Activity -->
|
<!--Settings Activity -->
|
||||||
<string name="settings_general_category">General</string>
|
<string name="settings_general_category">General</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user