mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 18:45:28 +00:00
Add flashing screen
This commit is contained in:
parent
f4097a372b
commit
2ea046cd80
@ -1,8 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.topjohnwu.magisk"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
package="com.topjohnwu.magisk">
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
@ -22,8 +21,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
android:exported="true"/>
|
android:exported="true" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".SplashActivity"
|
android:name=".SplashActivity"
|
||||||
android:configChanges="orientation|screenSize"
|
android:configChanges="orientation|screenSize"
|
||||||
@ -31,16 +29,22 @@
|
|||||||
android:theme="@style/SplashTheme">
|
android:theme="@style/SplashTheme">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".AboutActivity"
|
android:name=".AboutActivity"
|
||||||
android:theme="@style/AppTheme.Transparent"/>
|
android:theme="@style/AppTheme.Transparent" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:theme="@style/AppTheme.Transparent" />
|
android:theme="@style/AppTheme.Transparent" />
|
||||||
|
<activity
|
||||||
|
android:name=".FlashActivity"
|
||||||
|
android:screenOrientation="nosensor"
|
||||||
|
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||||
|
android:theme="@style/AppTheme.Transparent" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".superuser.RequestActivity"
|
android:name=".superuser.RequestActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
@ -54,29 +58,26 @@
|
|||||||
android:theme="@style/SuRequest" />
|
android:theme="@style/SuRequest" />
|
||||||
|
|
||||||
<receiver android:name=".superuser.SuReceiver" />
|
<receiver android:name=".superuser.SuReceiver" />
|
||||||
|
|
||||||
<receiver android:name=".receivers.BootReceiver">
|
<receiver android:name=".receivers.BootReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receivers.PackageReceiver">
|
<receiver android:name=".receivers.PackageReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.PACKAGE_REPLACED" />
|
||||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||||
|
|
||||||
<data android:scheme="package" />
|
<data android:scheme="package" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receivers.ManagerUpdate" />
|
<receiver android:name=".receivers.ManagerUpdate" />
|
||||||
|
|
||||||
<service android:name=".services.OnBootIntentService" />
|
<service android:name=".services.OnBootIntentService" />
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".services.UpdateCheckService"
|
android:name=".services.UpdateCheckService"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
android:exported="true"
|
||||||
android:exported="true" />
|
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="android.support.v4.content.FileProvider"
|
android:name="android.support.v4.content.FileProvider"
|
||||||
|
98
app/src/main/java/com/topjohnwu/magisk/FlashActivity.java
Normal file
98
app/src/main/java/com/topjohnwu/magisk/FlashActivity.java
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.asyncs.FlashZip;
|
||||||
|
import com.topjohnwu.magisk.components.Activity;
|
||||||
|
import com.topjohnwu.magisk.utils.AdaptiveList;
|
||||||
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
|
|
||||||
|
import butterknife.BindView;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.OnClick;
|
||||||
|
|
||||||
|
public class FlashActivity extends Activity {
|
||||||
|
|
||||||
|
@BindView(R.id.toolbar) Toolbar toolbar;
|
||||||
|
@BindView(R.id.flash_logs) RecyclerView flashLogs;
|
||||||
|
@BindView(R.id.button_panel) LinearLayout buttonPanel;
|
||||||
|
|
||||||
|
private AdaptiveList<String> rootShellOutput;
|
||||||
|
|
||||||
|
@OnClick(R.id.no_thanks)
|
||||||
|
public void dismiss() {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.reboot)
|
||||||
|
public void reboot() {
|
||||||
|
Shell.getRootShell(this).su_raw("reboot");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_flash);
|
||||||
|
ButterKnife.bind(this);
|
||||||
|
rootShellOutput = new AdaptiveList<>(flashLogs);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
ActionBar ab = getSupportActionBar();
|
||||||
|
if (ab != null) {
|
||||||
|
ab.setTitle(R.string.flashing);
|
||||||
|
}
|
||||||
|
setFloating();
|
||||||
|
|
||||||
|
flashLogs.setAdapter(new FlashLogAdapter());
|
||||||
|
|
||||||
|
// We must receive a Uri of the target zip
|
||||||
|
Uri uri = getIntent().getData();
|
||||||
|
|
||||||
|
new FlashZip(this, uri, rootShellOutput)
|
||||||
|
.setCallBack(() -> buttonPanel.setVisibility(View.VISIBLE))
|
||||||
|
.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
// Prevent user accidentally press back button
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FlashLogAdapter extends RecyclerView.Adapter<ViewHolder> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.list_item_flashlog, parent, false);
|
||||||
|
return new ViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
|
holder.text.setText(rootShellOutput.get(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return rootShellOutput.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
@BindView(R.id.textView) TextView text;
|
||||||
|
|
||||||
|
public ViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
ButterKnife.bind(this, itemView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -26,7 +26,7 @@ import android.widget.Spinner;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||||
import com.topjohnwu.magisk.asyncs.ProcessMagiskZip;
|
import com.topjohnwu.magisk.asyncs.ParallelTask;
|
||||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
||||||
import com.topjohnwu.magisk.components.Fragment;
|
import com.topjohnwu.magisk.components.Fragment;
|
||||||
import com.topjohnwu.magisk.components.SnackbarMaker;
|
import com.topjohnwu.magisk.components.SnackbarMaker;
|
||||||
@ -144,7 +144,13 @@ public class MagiskFragment extends Fragment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadDone(Uri uri, Context context) {
|
public void onDownloadDone(Uri uri, Context context) {
|
||||||
new ProcessMagiskZip(getActivity(), uri, boot, enc, verity).exec();
|
if (Shell.rootAccess()) {
|
||||||
|
new SetInstallFlags(boot, enc, verity)
|
||||||
|
.setCallBack(() -> startActivity(new Intent(context, FlashActivity.class).setData(uri)))
|
||||||
|
.exec(context);
|
||||||
|
} else {
|
||||||
|
Utils.showUriSnack(getActivity(), uri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
magiskManager.magiskLink,
|
magiskManager.magiskLink,
|
||||||
@ -160,6 +166,28 @@ public class MagiskFragment extends Fragment
|
|||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class SetInstallFlags extends ParallelTask<Context, Void, Void> {
|
||||||
|
|
||||||
|
private String boot;
|
||||||
|
private boolean enc, verity;
|
||||||
|
|
||||||
|
SetInstallFlags(String boot, boolean enc, boolean verity) {
|
||||||
|
this.boot = boot;
|
||||||
|
this.enc = enc;
|
||||||
|
this.verity = verity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Context... contexts) {
|
||||||
|
Shell.getRootShell(contexts[0]).su_raw("rm -f /dev/.magisk",
|
||||||
|
(boot != null) ? "echo \"BOOTIMAGE=" + boot + "\" >> /dev/.magisk" : "",
|
||||||
|
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
|
||||||
|
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OnClick(R.id.uninstall_button)
|
@OnClick(R.id.uninstall_button)
|
||||||
public void uninstall() {
|
public void uninstall() {
|
||||||
new AlertDialogBuilder(getActivity())
|
new AlertDialogBuilder(getActivity())
|
||||||
|
@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
@ -14,13 +13,11 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
import com.topjohnwu.magisk.adapters.ModulesAdapter;
|
||||||
import com.topjohnwu.magisk.asyncs.FlashZip;
|
|
||||||
import com.topjohnwu.magisk.asyncs.LoadModules;
|
import com.topjohnwu.magisk.asyncs.LoadModules;
|
||||||
import com.topjohnwu.magisk.components.Fragment;
|
import com.topjohnwu.magisk.components.Fragment;
|
||||||
import com.topjohnwu.magisk.module.Module;
|
import com.topjohnwu.magisk.module.Module;
|
||||||
import com.topjohnwu.magisk.utils.CallbackEvent;
|
import com.topjohnwu.magisk.utils.CallbackEvent;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -87,8 +84,9 @@ public class ModulesFragment extends Fragment implements CallbackEvent.Listener<
|
|||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
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
|
||||||
final Uri uri = data.getData();
|
Intent intent = new Intent(getActivity(), FlashActivity.class);
|
||||||
new FlashZip(getActivity(), uri).exec();
|
intent.setData(data.getData()).putExtra("ACTION", "flash");
|
||||||
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -162,14 +162,14 @@ public class SettingsActivity extends Activity {
|
|||||||
new AlertDialogBuilder(getActivity())
|
new AlertDialogBuilder(getActivity())
|
||||||
.setTitle(R.string.no_magisksu_title)
|
.setTitle(R.string.no_magisksu_title)
|
||||||
.setMessage(R.string.no_magisksu_msg)
|
.setMessage(R.string.no_magisksu_msg)
|
||||||
.setPositiveButton(R.string.understand, (dialog, which) -> new MagiskHide().enable())
|
.setPositiveButton(R.string.understand, (dialog, which) -> new MagiskHide(getActivity()).enable())
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.show();
|
.show();
|
||||||
} else {
|
} else {
|
||||||
new MagiskHide().enable();
|
new MagiskHide(getActivity()).enable();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
new MagiskHide().disable();
|
new MagiskHide(getActivity()).disable();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "hosts":
|
case "hosts":
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.topjohnwu.magisk.adapters;
|
package com.topjohnwu.magisk.adapters;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
@ -86,10 +87,10 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
holder.checkBox.setChecked(mHideList.contains(info.packageName));
|
holder.checkBox.setChecked(mHideList.contains(info.packageName));
|
||||||
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
holder.checkBox.setOnCheckedChangeListener((v, isChecked) -> {
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
new MagiskHide().add(info.packageName);
|
new MagiskHide((Activity) holder.itemView.getContext()).add(info.packageName);
|
||||||
mHideList.add(info.packageName);
|
mHideList.add(info.packageName);
|
||||||
} else {
|
} else {
|
||||||
new MagiskHide().rm(info.packageName);
|
new MagiskHide((Activity) holder.itemView.getContext()).rm(info.packageName);
|
||||||
mHideList.remove(info.packageName);
|
mHideList.remove(info.packageName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.widget.Toast;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.components.AlertDialogBuilder;
|
import com.topjohnwu.magisk.utils.AdaptiveList;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||||
|
|
||||||
@ -26,11 +24,12 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
private File mCachedFile, mScriptFile, mCheckFile;
|
private File mCachedFile, mScriptFile, mCheckFile;
|
||||||
|
|
||||||
private String mFilename;
|
private String mFilename;
|
||||||
private ProgressDialog progress;
|
private AdaptiveList<String> mList;
|
||||||
|
|
||||||
public FlashZip(Activity context, Uri uri) {
|
public FlashZip(Activity context, Uri uri, AdaptiveList<String> list) {
|
||||||
super(context);
|
super(context);
|
||||||
mUri = uri;
|
mUri = uri;
|
||||||
|
mList = list;
|
||||||
|
|
||||||
mCachedFile = new File(magiskManager.getCacheDir(), "install.zip");
|
mCachedFile = new File(magiskManager.getCacheDir(), "install.zip");
|
||||||
mScriptFile = new File(magiskManager.getCacheDir(), "/META-INF/com/google/android/update-binary");
|
mScriptFile = new File(magiskManager.getCacheDir(), "/META-INF/com/google/android/update-binary");
|
||||||
@ -40,13 +39,10 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
mFilename = Utils.getNameFromUri(magiskManager, mUri);
|
mFilename = Utils.getNameFromUri(magiskManager, mUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyToCache() throws Throwable {
|
private void copyToCache() throws Exception {
|
||||||
publishProgress(magiskManager.getString(R.string.copying_msg));
|
mList.add(magiskManager.getString(R.string.copying_msg));
|
||||||
|
|
||||||
if (mCachedFile.exists() && !mCachedFile.delete()) {
|
mCachedFile.delete();
|
||||||
Logger.error("FlashZip: Error while deleting already existing file");
|
|
||||||
throw new IOException();
|
|
||||||
}
|
|
||||||
try (
|
try (
|
||||||
InputStream in = magiskManager.getContentResolver().openInputStream(mUri);
|
InputStream in = magiskManager.getContentResolver().openInputStream(mUri);
|
||||||
OutputStream outputStream = new FileOutputStream(mCachedFile)
|
OutputStream outputStream = new FileOutputStream(mCachedFile)
|
||||||
@ -56,81 +52,64 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
if (in == null) throw new FileNotFoundException();
|
if (in == null) throw new FileNotFoundException();
|
||||||
while ((length = in.read(buffer)) > 0)
|
while ((length = in.read(buffer)) > 0)
|
||||||
outputStream.write(buffer, 0, length);
|
outputStream.write(buffer, 0, length);
|
||||||
|
|
||||||
Logger.dev("FlashZip: File created successfully - " + mCachedFile.getPath());
|
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
Logger.error("FlashZip: Invalid Uri");
|
mList.add("! Invalid Uri");
|
||||||
throw e;
|
throw e;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Logger.error("FlashZip: Error in creating file");
|
mList.add("! Cannot copy to cache");
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
List<String> ret;
|
List<String> ret = Utils.readFile(magiskManager.rootShell, mCheckFile.getPath());
|
||||||
ret = Utils.readFile(magiskManager.rootShell, mCheckFile.getPath());
|
|
||||||
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
return Utils.isValidShellResponse(ret) && ret.get(0).contains("#MAGISK");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cleanup(int ret) {
|
|
||||||
magiskManager.rootShell.su_raw(
|
|
||||||
"rm -rf " + mCachedFile.getParent() + "/*",
|
|
||||||
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
|
||||||
);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
progress = new ProgressDialog(activity);
|
// UI updates must run in the UI thread
|
||||||
progress.setTitle(R.string.zip_install_progress_title);
|
mList.setCallback(this::publishProgress);
|
||||||
progress.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onProgressUpdate(String... values) {
|
protected void onProgressUpdate(String... values) {
|
||||||
progress.setMessage(values[0]);
|
mList.updateView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Integer doInBackground(Void... voids) {
|
protected Integer doInBackground(Void... voids) {
|
||||||
Logger.dev("FlashZip Running... " + mFilename);
|
|
||||||
List<String> ret;
|
|
||||||
try {
|
try {
|
||||||
copyToCache();
|
copyToCache();
|
||||||
if (!unzipAndCheck()) return cleanup(0);
|
if (!unzipAndCheck()) return 0;
|
||||||
publishProgress(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
mList.add(magiskManager.getString(R.string.zip_install_progress_msg, mFilename));
|
||||||
ret = magiskManager.rootShell.su(
|
magiskManager.rootShell.su(mList,
|
||||||
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile,
|
"BOOTMODE=true sh " + mScriptFile + " dummy 1 " + mCachedFile +
|
||||||
"if [ $? -eq 0 ]; then echo true; else echo false; fi"
|
" && echo 'Success!' || echo 'Failed!'"
|
||||||
);
|
);
|
||||||
if (!Utils.isValidShellResponse(ret)) return -1;
|
if (TextUtils.equals(mList.get(mList.size() - 1), "Success!"))
|
||||||
Logger.dev("FlashZip: Console log:");
|
return 1;
|
||||||
for (String line : ret) {
|
} catch (Exception e) {
|
||||||
Logger.dev(line);
|
|
||||||
}
|
|
||||||
if (Boolean.parseBoolean(ret.get(ret.size() - 1)))
|
|
||||||
return cleanup(1);
|
|
||||||
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return cleanup(-1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -1 = error, manual install; 0 = invalid zip; 1 = success
|
// -1 = error, manual install; 0 = invalid zip; 1 = success
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Integer result) {
|
protected void onPostExecute(Integer result) {
|
||||||
progress.dismiss();
|
magiskManager.rootShell.su_raw(
|
||||||
|
"rm -rf " + mCachedFile.getParent() + "/*",
|
||||||
|
"rm -rf " + MagiskManager.TMP_FOLDER_PATH
|
||||||
|
);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case -1:
|
case -1:
|
||||||
Toast.makeText(magiskManager, magiskManager.getString(R.string.install_error), Toast.LENGTH_LONG).show();
|
mList.add(magiskManager.getString(R.string.install_error));
|
||||||
Utils.showUriSnack(activity, mUri);
|
Utils.showUriSnack(activity, mUri);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
Toast.makeText(magiskManager, magiskManager.getString(R.string.invalid_zip), Toast.LENGTH_LONG).show();
|
mList.add(magiskManager.getString(R.string.invalid_zip));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
onSuccess();
|
onSuccess();
|
||||||
@ -140,14 +119,6 @@ public class FlashZip extends ParallelTask<Void, String, Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void onSuccess() {
|
protected void onSuccess() {
|
||||||
magiskManager.updateCheckDone.trigger();
|
|
||||||
new LoadModules(activity).exec();
|
new LoadModules(activity).exec();
|
||||||
|
|
||||||
new AlertDialogBuilder(activity)
|
|
||||||
.setTitle(R.string.reboot_title)
|
|
||||||
.setMessage(R.string.reboot_msg)
|
|
||||||
.setPositiveButton(R.string.reboot, (dialogInterface, i) -> magiskManager.rootShell.su_raw("reboot"))
|
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ public class MagiskHide extends ParallelTask<Object, Void, Void> {
|
|||||||
|
|
||||||
private boolean isList = false;
|
private boolean isList = false;
|
||||||
|
|
||||||
public MagiskHide() {}
|
|
||||||
|
|
||||||
public MagiskHide(Activity context) {
|
public MagiskHide(Activity context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.net.Uri;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
|
|
||||||
public class ProcessMagiskZip extends ParallelTask<Void, Void, Boolean> {
|
|
||||||
|
|
||||||
private Uri mUri;
|
|
||||||
private ProgressDialog progressDialog;
|
|
||||||
private String mBoot;
|
|
||||||
private boolean mEnc, mVerity;
|
|
||||||
|
|
||||||
public ProcessMagiskZip(Activity context, Uri uri, String boot, boolean enc, boolean verity) {
|
|
||||||
super(context);
|
|
||||||
mUri = uri;
|
|
||||||
mBoot = boot;
|
|
||||||
mEnc = enc;
|
|
||||||
mVerity = verity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
progressDialog = ProgressDialog.show(activity,
|
|
||||||
activity.getString(R.string.zip_process_title),
|
|
||||||
activity.getString(R.string.zip_unzip_msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
if (Shell.rootAccess()) {
|
|
||||||
magiskManager.rootShell.su_raw("rm -f /dev/.magisk",
|
|
||||||
(mBoot != null) ? "echo \"BOOTIMAGE=" + mBoot + "\" >> /dev/.magisk" : "",
|
|
||||||
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(mEnc) + "\" >> /dev/.magisk",
|
|
||||||
"echo \"KEEPVERITY=" + String.valueOf(mVerity) + "\" >> /dev/.magisk"
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
if (result) {
|
|
||||||
new FlashZip(activity, mUri).exec();
|
|
||||||
} else {
|
|
||||||
Utils.showUriSnack(activity, mUri);
|
|
||||||
}
|
|
||||||
super.onPostExecute(result);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,9 +2,11 @@ package com.topjohnwu.magisk.asyncs;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.FlashActivity;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
@ -85,13 +87,12 @@ public class ProcessRepoZip extends ParallelTask<Void, Void, Boolean> {
|
|||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
if (result) {
|
if (result) {
|
||||||
if (Shell.rootAccess() && mInstall) {
|
if (Shell.rootAccess() && mInstall) {
|
||||||
new FlashZip(activity, mUri).exec();
|
magiskManager.startActivity(new Intent(magiskManager, FlashActivity.class).setData(mUri));
|
||||||
} else {
|
} else {
|
||||||
Utils.showUriSnack(activity, mUri);
|
Utils.showUriSnack(activity, mUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, R.string.process_error, Toast.LENGTH_LONG).show();
|
magiskManager.toast(R.string.process_error, Toast.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class AdaptiveList<E> extends ArrayList<E> {
|
||||||
|
|
||||||
|
private Runnable callback;
|
||||||
|
private RecyclerView mView;
|
||||||
|
|
||||||
|
public AdaptiveList(RecyclerView v) {
|
||||||
|
mView = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateView() {
|
||||||
|
mView.getAdapter().notifyDataSetChanged();
|
||||||
|
mView.scrollToPosition(mView.getAdapter().getItemCount() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallback(Runnable cb) {
|
||||||
|
callback = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(E e) {
|
||||||
|
boolean ret = super.add(e);
|
||||||
|
if (ret) {
|
||||||
|
if (callback == null) {
|
||||||
|
updateView();
|
||||||
|
} else {
|
||||||
|
callback.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -44,19 +44,19 @@ public class Utils {
|
|||||||
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
private static final int APK_UPDATE_NOTIFICATION_ID = 2;
|
||||||
|
|
||||||
public static boolean itemExist(Shell shell, String path) {
|
public static boolean itemExist(Shell shell, String path) {
|
||||||
String command = "if [ -e " + path + " ]; then echo true; else echo false; fi";
|
String command = "[ -e " + path + " ] && echo true || echo false";
|
||||||
List<String> ret = shell.su(command);
|
List<String> ret = shell.su(command);
|
||||||
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
return isValidShellResponse(ret) && Boolean.parseBoolean(ret.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createFile(Shell shell, String path) {
|
public static void createFile(Shell shell, String path) {
|
||||||
String folder = path.substring(0, path.lastIndexOf('/'));
|
String folder = path.substring(0, path.lastIndexOf('/'));
|
||||||
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null; if [ -f \"" + path + "\" ]; then echo true; else echo false; fi";
|
String command = "mkdir -p " + folder + " 2>/dev/null; touch " + path + " 2>/dev/null;";
|
||||||
shell.su_raw(command);
|
shell.su_raw(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeItem(Shell shell, String path) {
|
public static void removeItem(Shell shell, String path) {
|
||||||
String command = "rm -rf " + path + " 2>/dev/null; if [ -e " + path + " ]; then echo false; else echo true; fi";
|
String command = "rm -rf " + path + " 2>/dev/null";
|
||||||
shell.su_raw(command);
|
shell.su_raw(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
app/src/main/res/layout/activity_flash.xml
Normal file
56
app/src/main/res/layout/activity_flash.xml
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
tools:context="com.topjohnwu.magisk.FlashActivity">
|
||||||
|
|
||||||
|
<include layout="@layout/toolbar"/>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/flash_logs"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layoutManager="android.support.v7.widget.LinearLayoutManager">
|
||||||
|
|
||||||
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/button_panel"
|
||||||
|
style="?android:buttonStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:background="@android:color/darker_gray"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/no_thanks"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/close" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/reboot"
|
||||||
|
style="?android:borderlessButtonStyle"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="50dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/reboot" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
9
app/src/main/res/layout/list_item_flashlog.xml
Normal file
9
app/src/main/res/layout/list_item_flashlog.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/textView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="10sp" />
|
@ -133,6 +133,7 @@
|
|||||||
<string name="manager_update_title">New Magisk Manager Update Available!</string>
|
<string name="manager_update_title">New Magisk Manager Update Available!</string>
|
||||||
<string name="manager_download_install">Press to download and install</string>
|
<string name="manager_download_install">Press to download and install</string>
|
||||||
<string name="magisk_updates">Magisk Updates</string>
|
<string name="magisk_updates">Magisk Updates</string>
|
||||||
|
<string name="flashing">Flashing</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