Update FlashZip to use Uri

This commit is contained in:
topjohnwu 2016-09-27 15:51:38 +08:00
parent 7511df61b3
commit 441e603bc0
9 changed files with 160 additions and 504 deletions

View File

@ -24,7 +24,7 @@
tools:ignore="AllowBackup,GoogleAppIndexingWarning"> tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<service <service
android:name=".services.MonitorService" android:name=".services.MonitorService"
android:label="@string/accessibility_service_name" android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter> <intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" /> <action android:name="android.accessibilityservice.AccessibilityService" />

View File

@ -4,6 +4,7 @@ import android.app.Fragment;
import android.content.Intent; import android.content.Intent;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
@ -138,8 +139,8 @@ public class MagiskFragment extends Fragment {
getActivity(), getActivity(),
new DownloadReceiver(getString(R.string.magisk)) { new DownloadReceiver(getString(R.string.magisk)) {
@Override @Override
public void task(File file) { public void task(Uri uri) {
new Async.FlashZIP(mContext, mName, file.getPath()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
} }
}, },
Utils.magiskLink, "latest_magisk.zip")) Utils.magiskLink, "latest_magisk.zip"))
@ -164,10 +165,10 @@ public class MagiskFragment extends Fragment {
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(getActivity(), .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(getActivity(),
new DownloadReceiver() { new DownloadReceiver() {
@Override @Override
public void task(File file) { public void task(Uri uri) {
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE); Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setData(FileProvider.getUriForFile(mContext, "com.topjohnwu.magisk.provider", file)); install.setData(uri);
mContext.startActivity(install); mContext.startActivity(install);
} }
}, },

View File

@ -5,6 +5,7 @@ import android.animation.ValueAnimator;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
@ -38,29 +39,17 @@ import butterknife.ButterKnife;
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> { public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
//@BindView(R.id.expand_layout) LinearLayout expandedLayout;
private final List<Module> mList; private final List<Module> mList;
private final List<Module> mListToUpdate = new ArrayList<>();
List<Boolean> mExpandedList;
@BindView(R.id.expand_layout)
LinearLayout expandedLayout;
private View viewMain; private View viewMain;
private Context context; private Context context;
private final Utils.ItemClickListener chboxListener; private final Utils.ItemClickListener chboxListener;
private final Utils.ItemClickListener deleteBtnListener; private final Utils.ItemClickListener deleteBtnListener;
private final Utils.ItemClickListener unDeleteBtnListener; private final Utils.ItemClickListener unDeleteBtnListener;
private boolean alertUpdate, ignoreAlertUpdate;
public ModulesAdapter(List<Module> list, Utils.ItemClickListener chboxListener, Utils.ItemClickListener deleteBtnListener, Utils.ItemClickListener undeleteBtnListener) { public ModulesAdapter(List<Module> list, Utils.ItemClickListener chboxListener, Utils.ItemClickListener deleteBtnListener, Utils.ItemClickListener undeleteBtnListener) {
alertUpdate = false;
this.mList = list; this.mList = list;
mExpandedList = new ArrayList<>(mList.size());
for (int i = 0; i < mList.size(); i++) {
mExpandedList.add(false);
if (mList.get(i).isUpdateAvailable()) {
alertUpdate = true;
mListToUpdate.add(mList.get(i));
}
}
this.chboxListener = chboxListener; this.chboxListener = chboxListener;
this.deleteBtnListener = deleteBtnListener; this.deleteBtnListener = deleteBtnListener;
this.unDeleteBtnListener = undeleteBtnListener; this.unDeleteBtnListener = undeleteBtnListener;
@ -78,85 +67,24 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
public void onBindViewHolder(final ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
final Module module = mList.get(position); final Module module = mList.get(position);
Log.d("Magisk", "ModulesAdapter: Trying set up bindview from list pos " + position + " and " + module.getName()); Log.d("Magisk", "ModulesAdapter: Trying set up bindview from list pos " + position + " and " + module.getName());
Log.d("Magisk", "ModulesFragment: Log ID is " + module.getmLogUrl()); if (module.isCache()) {
if (module.isCache())
holder.title.setText("[Cache] " + module.getName()); holder.title.setText("[Cache] " + module.getName());
else } else {
holder.title.setText(module.getName()); holder.title.setText(module.getName());
holder.versionName.setText(module.getVersion());
holder.description.setText(module.getDescription());
holder.author.setText(module.getAuthor());
String logUrl = module.getmLogUrl();
String supportUrl = module.getSupportUrl();
String donateUrl = module.getDonateUrl();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (prefs.contains("ignoreUpdateAlerts")) {
ignoreAlertUpdate = prefs.getBoolean("ignoreUpdateAlerts", false);
} }
if (prefs.contains("repo-canUpdate_" + module.getId())) { String author = module.getAuthor();
if (prefs.getBoolean("repo-canUpdate_" + module.getId(), false)) { String versionName = module.getVersion();
holder.updateStatus.setText(R.string.module_update_available); String description = module.getDescription();
holder.updateStatus.setVisibility(View.VISIBLE); if (versionName != null) {
} else { holder.versionName.setText(versionName);
holder.updateStatus.setVisibility(View.GONE); }
if (author != null) {
holder.author.setText(context.getString(R.string.author, author));
}
if (description != null) {
holder.description.setText(description);
} }
if (alertUpdate && !ignoreAlertUpdate) {
Iterator<Module> iterRepo = mListToUpdate.iterator();
while (iterRepo.hasNext()) {
Module mModule = iterRepo.next();
DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
DownloadReceiver receiver = new DownloadReceiver() {
@Override
public void task(File file) {
Log.d("Magisk", "Task firing");
new Async.FlashZIP(context, mModule.getId(), file.toString()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
};
String filename = mModule.getId().replace(" ", "") + ".zip";
Utils.downloadAndReceive(context, receiver, mModule.getmZipUrl(), filename);
break;
case DialogInterface.BUTTON_NEGATIVE:
ignoreAlertUpdate = true;
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean("ignoreUpdateAlerts", ignoreAlertUpdate);
editor.apply();
break;
}
};
AlertDialog.Builder builder;
String theme = PreferenceManager.getDefaultSharedPreferences(context).getString("theme", "");
if (theme.equals("Dark")) {
builder = new AlertDialog.Builder(context,R.style.AlertDialog_dh);
} else {
builder = new AlertDialog.Builder(context);
}
builder.setMessage("An update is available for " + mModule.getName() + ". Would you like to install it?").setPositiveButton("Yes", dialogClickListener)
.setNegativeButton("No", dialogClickListener).show();
mListToUpdate.remove(mModule);
}
}
}
View.OnClickListener oCl = view -> {
if (view.getId() == holder.changeLog.getId()) {
new WebWindow("Changelog", module.getmLogUrl(), context);
}
if (view.getId() == holder.authorLink.getId()) {
new WebWindow("Donate", module.getDonateUrl(), context);
}
if (view.getId() == holder.supportLink.getId()) {
new WebWindow("Support", module.getSupportUrl(), context);
}
};
holder.authorLink.setOnClickListener(oCl);
holder.changeLog.setOnClickListener(oCl);
holder.supportLink.setOnClickListener(oCl);
holder.checkBox.setChecked(module.isEnabled()); holder.checkBox.setChecked(module.isEnabled());
holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> chboxListener.onItemClick(compoundButton, holder.getAdapterPosition())); holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> chboxListener.onItemClick(compoundButton, holder.getAdapterPosition()));
@ -190,33 +118,14 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
class ViewHolder extends RecyclerView.ViewHolder { class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.title) @BindView(R.id.title) TextView title;
TextView title; @BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description;
@BindView(R.id.version_name) @BindView(R.id.warning) TextView warning;
TextView versionName; @BindView(R.id.checkbox) CheckBox checkBox;
@BindView(R.id.description) @BindView(R.id.author) TextView author;
TextView description; // @BindView(R.id.updateStatus) TextView updateStatus;
@BindView(R.id.warning) @BindView(R.id.delete) ImageView delete;
TextView warning;
@BindView(R.id.checkbox)
CheckBox checkBox;
@BindView(R.id.author)
TextView author;
@BindView(R.id.updateStatus)
TextView updateStatus;
@BindView(R.id.delete)
ImageView delete;
@BindView(R.id.changeLog)
ImageView changeLog;
@BindView(R.id.authorLink)
ImageView authorLink;
@BindView(R.id.supportLink)
ImageView supportLink;
@BindView(R.id.expand_layout)
LinearLayout expandLayout;
private ValueAnimator mAnimator;
private int mMeasuredHeight;
public ViewHolder(View itemView) { public ViewHolder(View itemView) {
super(itemView); super(itemView);
@ -225,91 +134,10 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
DisplayMetrics dimension = new DisplayMetrics(); DisplayMetrics dimension = new DisplayMetrics();
windowmanager.getDefaultDisplay().getMetrics(dimension); windowmanager.getDefaultDisplay().getMetrics(dimension);
expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
expandLayout.setVisibility(View.GONE);
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
expandLayout.measure(widthSpec, heightSpec);
mAnimator = slideAnimator(0, expandLayout.getMeasuredHeight());
return true;
}
});
viewMain.setOnClickListener(view -> {
int position = getAdapterPosition();
Log.d("Magisk", "ReposFragment: CLICK. " + position + " and " + mExpandedList.get(position));
if (mExpandedList.get(position)) {
collapse(expandLayout);
} else {
expand(expandLayout);
}
mExpandedList.set(position, !mExpandedList.get(position));
});
if (!Shell.rootAccess()) { if (!Shell.rootAccess()) {
checkBox.setEnabled(false); checkBox.setEnabled(false);
delete.setEnabled(false); delete.setEnabled(false);
} }
} }
private void expand(View view) {
// set Visible
Log.d("Magisk", "ReposFragment: Expand anim called " + mMeasuredHeight + " and " + view.getId());
view.setVisibility(View.VISIBLE);
mAnimator.start();
}
private void collapse(View view) {
int finalHeight = view.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
Log.d("Magisk", "ReposFragment: Collapse anim called " + finalHeight + " and " + view.getId());
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
// Height=0, but it set visibility to GONE
view.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
mAnimator.start();
}
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
// Update Height
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = expandLayout
.getLayoutParams();
layoutParams.height = value;
expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
} }
} }

View File

@ -6,6 +6,7 @@ import android.animation.ValueAnimator;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
@ -147,9 +148,8 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
DownloadReceiver receiver = new DownloadReceiver() { DownloadReceiver receiver = new DownloadReceiver() {
@Override @Override
public void task(File file) { public void task(Uri uri) {
Log.d("Magisk", "Task firing"); new Async.FlashZIP(context, uri, repo.getName() + "-v" + repo.getVersion());
new Async.FlashZIP(context, repo.getId(), file.toString()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
} }
}; };
String filename = repo.getId().replace(" ", "") + ".zip"; String filename = repo.getId().replace(" ", "") + ".zip";

View File

@ -1,11 +1,5 @@
package com.topjohnwu.magisk.module; package com.topjohnwu.magisk.module;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Logger; import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.Utils;
@ -13,13 +7,10 @@ public class Module extends BaseModule {
private String mRemoveFile; private String mRemoveFile;
private String mDisableFile; private String mDisableFile;
private String mZipUrl, mLogUrl;
private boolean mEnable, mRemove, mUpdateAvailable = false; private boolean mEnable, mRemove, mUpdateAvailable = false;
public Module(Context context, String path) { public Module(String path) {
super();
parseProps(Utils.readFile(path + "/module.prop")); parseProps(Utils.readFile(path + "/module.prop"));
mRemoveFile = path + "/remove"; mRemoveFile = path + "/remove";
@ -33,13 +24,7 @@ public class Module extends BaseModule {
if (mName == null) if (mName == null)
mName = mId; mName = mId;
if (mDescription == null) Logger.dh("Creating Module, id: " + mId);
mDescription = context.getString(R.string.no_info_provided);
if (mVersion == null)
mVersion = context.getString(R.string.no_info_provided);
Logger.dh("Module id: " + mId);
mEnable = !Utils.itemExist(mDisableFile); mEnable = !Utils.itemExist(mDisableFile);
mRemove = Utils.itemExist(mRemoveFile); mRemove = Utils.itemExist(mRemoveFile);
@ -52,12 +37,11 @@ public class Module extends BaseModule {
repo.setInstalled(); repo.setInstalled();
if (repo.getVersionCode() > mVersionCode) { if (repo.getVersionCode() > mVersionCode) {
repo.setUpdate(); repo.setUpdate();
mUpdateAvailable = true;
} }
} }
} }
public String getmLogUrl() {return mLogUrl; }
public void createDisableFile() { public void createDisableFile() {
mEnable = !Utils.createFile(mDisableFile); mEnable = !Utils.createFile(mDisableFile);
} }
@ -82,8 +66,6 @@ public class Module extends BaseModule {
return mRemove; return mRemove;
} }
public String getmZipUrl() { return mZipUrl; }
public boolean isUpdateAvailable() { return mUpdateAvailable; } public boolean isUpdateAvailable() { return mUpdateAvailable; }
} }

View File

@ -38,8 +38,8 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
int status = c.getInt(columnIndex); int status = c.getInt(columnIndex);
switch (status) { switch (status) {
case DownloadManager.STATUS_SUCCESSFUL: case DownloadManager.STATUS_SUCCESSFUL:
File file = new File(Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))).getPath()); Uri uri = Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
task(file); task(uri);
break; break;
default: default:
Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show();
@ -54,5 +54,5 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
downloadID = id; downloadID = id;
} }
public abstract void task(File file); public void task(Uri uri) {}
} }

View File

@ -3,9 +3,12 @@ package com.topjohnwu.magisk.utils;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Environment;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.renderscript.ScriptGroup;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
@ -73,21 +76,10 @@ public class Async {
@Override @Override
protected Void doInBackground(Void... voids) { protected Void doInBackground(Void... voids) {
String jsonStr = WebRequest.makeWebServiceCall(Utils.UPDATE_JSON, WebRequest.GET);
try { try {
HttpURLConnection c = (HttpURLConnection) new URL(Utils.UPDATE_JSON).openConnection(); JSONObject json = new JSONObject(jsonStr);
c.setRequestMethod("GET");
c.setInstanceFollowRedirects(false);
c.setDoOutput(false);
c.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
JSONObject json = new JSONObject(sb.toString());
JSONObject magisk = json.getJSONObject("magisk"); JSONObject magisk = json.getJSONObject("magisk");
JSONObject app = json.getJSONObject("app"); JSONObject app = json.getJSONObject("app");
JSONObject root = json.getJSONObject("root"); JSONObject root = json.getJSONObject("root");
@ -102,9 +94,7 @@ public class Async {
Utils.phhLink = root.getString("phh"); Utils.phhLink = root.getString("phh");
Utils.supersuLink = root.getString("supersu"); Utils.supersuLink = root.getString("supersu");
} catch (JSONException ignored) {}
} catch (IOException | JSONException ignored) {
}
return null; return null;
} }
@ -116,87 +106,16 @@ public class Async {
.setTitle(R.string.no_magisk_title) .setTitle(R.string.no_magisk_title)
.setMessage(R.string.no_magisk_msg) .setMessage(R.string.no_magisk_msg)
.setCancelable(true) .setCancelable(true)
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> new AlertDialog.Builder(mContext) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(
.setTitle(R.string.root_method_title)
.setItems(new String[]{mContext.getString(R.string.phh), mContext.getString(R.string.supersu)}, (dialogInterface1, root) -> {
DownloadReceiver rootReceiver;
String link, filename;
switch (root) {
case 0:
link = Utils.phhLink;
filename = "phhsu.zip";
rootReceiver = new DownloadReceiver(mContext.getString(R.string.phh)) {
@Override
public void task(File file) {
new FlashZIP(mContext, mName, file.getPath()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
};
break;
case 1:
link = Utils.supersuLink;
filename = "supersu.zip";
rootReceiver = new DownloadReceiver(mContext.getString(R.string.supersu)) {
@Override
public void task(File file) {
new FlashZIP(mContext, mName, file.getPath()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
};
break;
default:
rootReceiver = null;
link = filename = null;
}
DownloadReceiver magiskReceiver = new DownloadReceiver(mContext.getString(R.string.magisk)) {
@Override
public void task(File file) {
Context temp = mContext;
new FlashZIP(mContext, mName, file.getPath()) {
@Override
protected void done() {
Utils.downloadAndReceive(temp, rootReceiver, link, filename);
}
}.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
};
Utils.downloadAndReceive(mContext, magiskReceiver, Utils.magiskLink, "latest_magisk.zip");
})
.show())
.setNegativeButton(R.string.no_thanks, null)
.show();
} else if (Shell.rootStatus == 2) {
new AlertDialog.Builder(mContext)
.setTitle(R.string.root_system)
.setMessage(R.string.root_system_msg)
.setCancelable(true)
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> new AlertDialog.Builder(mContext)
.setTitle(R.string.root_method_title)
.setItems(new String[]{mContext.getString(R.string.phh), mContext.getString(R.string.supersu)}, (dialogInterface1, root) -> {
switch (root) {
case 0:
Utils.downloadAndReceive(
mContext, mContext,
new DownloadReceiver(mContext.getString(R.string.phh)) { new DownloadReceiver(mContext.getString(R.string.magisk)) {
@Override @Override
public void task(File file) { public void task(Uri uri) {
new FlashZIP(mContext, mName, file.getPath()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); new FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
} }
}, },
Utils.phhLink, "phhsu.zip"); Utils.magiskLink,
break; "latest_magisk.zip"))
case 1:
Utils.downloadAndReceive(
mContext,
new DownloadReceiver(mContext.getString(R.string.supersu)) {
@Override
public void task(File file) {
new FlashZIP(mContext, mName, file.getPath()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
},
Utils.supersuLink, "supersu.zip");
break;
}
})
.show())
.setNegativeButton(R.string.no_thanks, null) .setNegativeButton(R.string.no_thanks, null)
.show(); .show();
} }
@ -220,12 +139,12 @@ public class Async {
for (String mod : magisk) { for (String mod : magisk) {
Logger.dh("Adding modules from " + mod); Logger.dh("Adding modules from " + mod);
ModulesFragment.listModules.add(new Module(mContext, mod)); ModulesFragment.listModules.add(new Module(mod));
} }
for (String mod : magiskCache) { for (String mod : magiskCache) {
Logger.dh("Adding cache modules from " + mod); Logger.dh("Adding cache modules from " + mod);
Module cacheMod = new Module(mContext, mod); Module cacheMod = new Module(mod);
// Prevent people forgot to change module.prop // Prevent people forgot to change module.prop
cacheMod.setCache(); cacheMod.setCache();
ModulesFragment.listModules.add(cacheMod); ModulesFragment.listModules.add(cacheMod);
@ -264,61 +183,29 @@ public class Async {
private String mPath, mName; private String mPath, mName;
private Uri mUri; private Uri mUri;
private ProgressDialog progress; private ProgressDialog progress;
private File mFile; private File mFile, sdFile;
private Context mContext; private Context mContext;
private List<String> ret; private List<String> ret;
private boolean deleteFileAfter; private boolean copyToSD;
public FlashZIP(Context context, String name, String path) { public FlashZIP(Context context, Uri uri, String name) {
mContext = context; mContext = context;
mUri = uri;
mName = name; mName = name;
mPath = path; copyToSD = true;
deleteFileAfter = false;
} }
public FlashZIP(Context context, Uri uRi) { public FlashZIP(Context context, Uri uri) {
mContext = context; mContext = context;
mUri = uRi; mUri = uri;
deleteFileAfter = true; mName = uri.getLastPathSegment();
copyToSD = false;
String file;
FileInfo fileInfo = FileUtils.getFileInfo(context, mUri);
Logger.dh("Utils: FlashZip Running, " + fileInfo.getPath());
String filename = fileInfo.getPath();
String idStr = filename.substring(filename.lastIndexOf('/') + 1);
if (!idStr.contains(".zip")) {
Logger.dh("Async: Improper name, cancelling " + idStr);
this.cancel(true);
progress.cancel();
}
file = mContext.getFilesDir() + "/" + idStr;
ContentResolver contentResolver = mContext.getContentResolver();
//contentResolver.takePersistableUriPermission(mUri, flags);
try {
InputStream in = contentResolver.openInputStream(mUri);
Log.d("Magisk", "Firing inputStream");
mFile = createFileFromInputStream(in, file);
if (mFile != null) {
mPath = mFile.getPath();
Logger.dh("Async: Mpath is " + mPath);
} else {
Log.e("Magisk", "Async: error creating file " + mUri.getPath());
this.cancel(true);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} }
// TODO handle non-primary volumes private static void createFileFromInputStream(InputStream inputStream, File f) throws IOException {
if (f.exists() && !f.delete()) {
throw new IOException();
} }
private static File createFileFromInputStream(InputStream inputStream, String fileName) {
try {
File f = new File(fileName);
f.setWritable(true, false); f.setWritable(true, false);
OutputStream outputStream = new FileOutputStream(f); OutputStream outputStream = new FileOutputStream(f);
byte buffer[] = new byte[1024]; byte buffer[] = new byte[1024];
@ -329,61 +216,74 @@ public class Async {
} }
outputStream.close(); outputStream.close();
inputStream.close(); Logger.dh("FlashZip: File created successfully - " + f.getPath());
Logger.dh("Async: File created successfully - " + f.getPath());
return f;
} catch (IOException e) {
System.out.println("error in creating a file");
e.printStackTrace();
}
return null;
} }
@Override @Override
protected void onPreExecute() { protected void onPreExecute() {
super.onPreExecute(); super.onPreExecute();
progress = ProgressDialog.show(mContext, mContext.getString(R.string.zip_install_progress_title), mContext.getString(R.string.zip_install_progress_msg, mName)); progress = ProgressDialog.show(mContext, mContext.getString(R.string.zip_install_progress_title), mContext.getString(R.string.zip_install_progress_msg, mName));
} }
@Override @Override
protected Boolean doInBackground(Void... voids) { protected Boolean doInBackground(Void... voids) {
if (mPath == null) { Logger.dh("FlashZip Running... " + mName);
Log.e("Magisk", "Utils: Error, flashZIP called without a valid zip file to flash."); InputStream in;
try {
try {
in = mContext.getContentResolver().openInputStream(mUri);
mFile = new File(mContext.getFilesDir().getAbsolutePath() + "/install.zip");
createFileFromInputStream(in, mFile);
} catch (FileNotFoundException e) {
Log.e("Magisk", "FlashZip: Invalid Uri");
throw e;
} catch (IOException e) {
Log.e("Magisk", "FlashZip: Error in creating file");
throw e;
}
} catch (Throwable e) {
this.cancel(true); this.cancel(true);
progress.cancel(); progress.cancel();
e.printStackTrace();
return false; return false;
} }
if (!Shell.rootAccess()) { if (Shell.rootAccess()) {
return false;
} else {
ret = Shell.su( ret = Shell.su(
"rm -rf /data/tmp", "unzip -o " + mFile.getPath() + " META-INF/com/google/android/* -d " + mFile.getParent(),
"mkdir -p /data/tmp", "BOOTMODE=true sh " + mFile.getParent() + "/META-INF/com/google/android/update-binary dummy 1 "+ mFile.getPath(),
"cp -af " + mPath + " /data/tmp/install.zip",
"unzip -o /data/tmp/install.zip META-INF/com/google/android/* -d /data/tmp",
"BOOTMODE=true sh /data/tmp/META-INF/com/google/android/update-binary dummy 1 /data/tmp/install.zip",
"if [ $? -eq 0 ]; then echo true; else echo false; fi" "if [ $? -eq 0 ]; then echo true; else echo false; fi"
); );
Logger.dh("Async: ret is " + ret); Logger.dh("FlashZip: Console log:\n" + ret);
return ret != null && Boolean.parseBoolean(ret.get(ret.size() - 1));
} }
// Copy the file to sdcard
if (copyToSD) {
try {
sdFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + (mName.contains(".zip") ? mName : mName + ".zip"));
if ((!sdFile.getParentFile().exists() && !sdFile.getParentFile().mkdirs()) || (sdFile.exists() && !sdFile.delete())) {
throw new IOException();
}
createFileFromInputStream(in, sdFile);
assert in != null;
in.close();
} catch (IOException e) {
Log.e("Magisk", "FlashZip: Unable to copy to sdcard");
e.printStackTrace();
}
}
mFile.delete();
return ret == null || !Boolean.parseBoolean(ret.get(ret.size() - 1));
} }
@Override @Override
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
super.onPostExecute(result); super.onPostExecute(result);
//Shell.su("rm -rf /data/tmp");
if (deleteFileAfter) {
Shell.su("rm -rf " + mPath);
Log.d("Magisk", "Utils: Deleting file " + mPath);
}
progress.dismiss(); progress.dismiss();
if (!result) { if (!result) {
if (sdFile == null) {
Toast.makeText(mContext, mContext.getString(R.string.install_error), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(mContext, mContext.getString(R.string.manual_install, mPath), Toast.LENGTH_LONG).show(); Toast.makeText(mContext, mContext.getString(R.string.manual_install, mPath), Toast.LENGTH_LONG).show();
}
return; return;
} }
done(); done();
@ -400,7 +300,7 @@ public class Async {
builder builder
.setTitle(R.string.reboot_title) .setTitle(R.string.reboot_title)
.setMessage(R.string.reboot_msg) .setMessage(R.string.reboot_msg)
.setPositiveButton(R.string.reboot, (dialogInterface1, i) -> Shell.su("reboot")) .setPositiveButton(R.string.reboot, (dialogInterface1, i) -> Shell.su("sh -c reboot"))
.setNegativeButton(R.string.no_thanks, null) .setNegativeButton(R.string.no_thanks, null)
.show(); .show();
} }

View File

@ -41,18 +41,51 @@
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_below="@id/title" android:layout_below="@id/title"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/no_info_provided"
android:textColor="@android:color/tertiary_text_dark" android:textColor="@android:color/tertiary_text_dark"
android:textIsSelectable="false" android:textIsSelectable="false"
android:textStyle="bold|italic"/> android:textStyle="bold|italic"/>
<TextView
android:id="@+id/author"
android:layout_width="@dimen/card_textview_width"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="@id/version_name"
android:text="@string/no_info_provided"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@android:color/tertiary_text_dark"
android:textIsSelectable="false"
android:textStyle="bold|italic"/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/author"
android:layout_gravity="center_vertical"
android:text="@string/no_info_provided"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textIsSelectable="false"/>
<TextView
android:id="@+id/warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/description"
android:layout_gravity="center_vertical"
android:text="@string/remove_file_created"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/red500"
android:visibility="gone"/>
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@+id/expand_layout"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingTop="15dp"> android:paddingTop="20dp">
<CheckBox <CheckBox
@ -90,95 +123,6 @@
<!--android:layout_alignBaseline="@id/title"--> <!--android:layout_alignBaseline="@id/title"-->
<!--android:layout_alignParentEnd="true"--> <!--android:layout_alignParentEnd="true"-->
<!--/>--> <!--/>-->
<TextView
android:id="@+id/description"
android:layout_width="@dimen/card_textview_width"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="@id/version_name"
android:layout_gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textIsSelectable="false"/>
<TextView
android:id="@+id/warning"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/description"
android:layout_gravity="center_vertical"
android:text="@string/remove_file_created"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/red500"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/expand_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="@id/description"
android:minHeight="70dp"
android:orientation="vertical"
>
<TextView
android:id="@+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@android:color/tertiary_text_dark"
android:textIsSelectable="false"
android:textStyle="bold|italic"/>
<TextView
android:id="@+id/updateStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="20dip"
android:gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textIsSelectable="false"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dip"
android:layout_gravity="center"
android:layout_marginBottom="0dip"
android:orientation="horizontal">
<ImageView
android:id="@+id/changeLog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/card_imageview_margin"
android:layout_marginStart="@dimen/card_imageview_margin"
android:background="@drawable/ic_changelog"
android:backgroundTint="@color/icon_grey"/>
<ImageView
android:id="@+id/authorLink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/card_imageview_margin"
android:layout_marginStart="@dimen/card_imageview_margin"
android:background="@drawable/ic_author"
android:backgroundTint="@color/icon_grey"/>
<ImageView
android:id="@+id/supportLink"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/card_imageview_margin"
android:layout_marginStart="@dimen/card_imageview_margin"
android:background="@drawable/ic_support"
android:backgroundTint="@color/icon_grey"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -54,7 +54,7 @@
<string name="remove_file_deleted">Module will not be removed at next reboot</string> <string name="remove_file_deleted">Module will not be removed at next reboot</string>
<string name="disable_file_created">Module will be disabled at next reboot</string> <string name="disable_file_created">Module will be disabled at next reboot</string>
<string name="disable_file_removed">Module will be enabled at next reboot</string> <string name="disable_file_removed">Module will be enabled at next reboot</string>
<string name="author">Created by </string> <string name="author">Created by %1$s</string>
<!--Log Fragment--> <!--Log Fragment-->
<string name="menuSaveToSd">Save to SD</string> <string name="menuSaveToSd">Save to SD</string>
@ -83,12 +83,12 @@
<string name="no_root_access">No root access, functionality limited</string> <string name="no_root_access">No root access, functionality limited</string>
<string name="no_thanks">No thanks</string> <string name="no_thanks">No thanks</string>
<string name="accessibility_service_description">Accessibility service required for Magisk auto-unroot feature</string> <string name="accessibility_service_description">Accessibility service required for Magisk auto-unroot feature</string>
<string name="accessibility_service_name">Magisk Manager</string>
<string name="update_title">%1$s Update!</string> <string name="update_title">%1$s Update!</string>
<string name="update_msg">New version v%2$s of %1$s is available!\nChangelog:\n%3$s</string> <string name="update_msg">New version v%2$s of %1$s is available!\nChangelog:\n%3$s</string>
<string name="download_install">Download and install</string> <string name="download_install">Download and install</string>
<string name="download_file_error">Error downloading file</string> <string name="download_file_error">Error downloading file</string>
<string name="manual_install">File downloaded in %1$s\nFlash it in recovery manually</string> <string name="install_error">Installation error!</string>
<string name="manual_install">Error in flashing file, zip file placed in %1$s\nFlash it in recovery manually</string>
<string name="reboot_title">Installation succeeded!</string> <string name="reboot_title">Installation succeeded!</string>
<string name="reboot_msg">Do you want to reboot now?</string> <string name="reboot_msg">Do you want to reboot now?</string>
<string name="reboot">Reboot</string> <string name="reboot">Reboot</string>
@ -101,6 +101,7 @@
<string name="supersu">SuperSU</string> <string name="supersu">SuperSU</string>
<string name="root_system_msg">It seems that you have incompatible root installed\nDo you want to install Magisk compatible root now?</string> <string name="root_system_msg">It seems that you have incompatible root installed\nDo you want to install Magisk compatible root now?</string>
<!--Web Related-->
<string name="pass">MagiskRox666</string> <string name="pass">MagiskRox666</string>
<string name="some_string">GTYybRBTYf5his9kQ16ZNO7qgkBJ/5MyVe4CGceAOIoXgSnnk8FTd4F1dE9p5Eus</string> <string name="some_string">GTYybRBTYf5his9kQ16ZNO7qgkBJ/5MyVe4CGceAOIoXgSnnk8FTd4F1dE9p5Eus</string>
<string name="downloads">Downloads</string> <string name="downloads">Downloads</string>