Add boot image file patch

This commit is contained in:
topjohnwu 2017-08-31 03:07:33 +08:00
parent dbe6e5b3d7
commit db8fd2c913
9 changed files with 325 additions and 85 deletions

View File

@ -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;

View File

@ -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();
} }

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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!'"

View File

@ -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);
}
}

View File

@ -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);
} }
} }

View File

@ -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();

View File

@ -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>