diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java index 89c870099..742746a49 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java @@ -137,13 +137,14 @@ public class MagiskFragment extends Fragment { .setCancelable(true) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive( getActivity(), - new DownloadReceiver(getString(R.string.magisk)) { + new DownloadReceiver() { @Override public void task(Uri uri) { new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } }, - Utils.magiskLink, "latest_magisk.zip")) + Utils.magiskLink, + "Magisk-v" + String.valueOf(Utils.remoteMagiskVersion) + ".zip")) .setNegativeButton(R.string.no_thanks, null) .show()); } else { @@ -153,14 +154,14 @@ public class MagiskFragment extends Fragment { magiskCheckUpdatesStatus.setTextColor(colorOK); } - if (Utils.remoteAppVersion > BuildConfig.VERSION_CODE) { + if (Utils.remoteAppVersionCode > BuildConfig.VERSION_CODE) { appCheckUpdatesContainer.setBackgroundColor(colorNeutral); appCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download); - appCheckUpdatesStatus.setText(getString(R.string.app_update_available, String.valueOf(Utils.remoteAppVersion))); + appCheckUpdatesStatus.setText(getString(R.string.app_update_available, Utils.remoteAppVersion)); appCheckUpdatesStatus.setTextColor(colorNeutral); appUpdateView.setOnClickListener(view -> builder .setTitle(getString(R.string.update_title, getString(R.string.app_name))) - .setMessage(getString(R.string.update_msg, getString(R.string.app_name), String.valueOf(Utils.remoteAppVersion), Utils.appChangelog)) + .setMessage(getString(R.string.update_msg, getString(R.string.app_name), Utils.remoteAppVersion, Utils.appChangelog)) .setCancelable(true) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(getActivity(), new DownloadReceiver() { @@ -168,11 +169,13 @@ public class MagiskFragment extends Fragment { public void task(Uri uri) { Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE); install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - install.setData(uri); + Uri content = FileProvider.getUriForFile(getActivity(), "com.topjohnwu.magisk.provider", new File(uri.getPath())); + install.setData(content); mContext.startActivity(install); } }, - Utils.appLink, "latest_manager.apk")) + Utils.appLink, + "MagiskManager-v" + Utils.remoteAppVersion + ".apk")) .setNegativeButton(R.string.no_thanks, null) .show() ); diff --git a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java index 094f70fe1..bcfb98f9b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java @@ -4,14 +4,11 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Color; import android.net.Uri; import android.os.AsyncTask; -import android.preference.PreferenceManager; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,11 +17,12 @@ import android.view.WindowManager; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; import com.topjohnwu.magisk.module.Repo; import com.topjohnwu.magisk.receivers.DownloadReceiver; import com.topjohnwu.magisk.utils.Async; +import com.topjohnwu.magisk.utils.Logger; +import com.topjohnwu.magisk.utils.Shell; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebWindow; @@ -38,150 +36,107 @@ import butterknife.ButterKnife; public class ReposAdapter extends RecyclerView.Adapter { private final List mList; - List mExpandedList; - private View viewMain; + private List mExpandedList; + private View mView; private Context context; - private boolean mCanUpdate; - private boolean alertUpdate; - private boolean ignoreAlertUpdate; - private Repo repo; - private ViewHolder mHolder; - private String mDonateUrl, mSupportUrl, mLogUrl,alertPackage; - private SharedPreferences prefs; - public ReposAdapter(List list) { - alertPackage = ""; - alertUpdate = false; - this.mList = list; - Log.d("Magisk", "ReposAdapter: I am alive. I have a list " + list.size()); + mList = list; mExpandedList = new ArrayList<>(mList.size()); for (int i = 0; i < mList.size(); i++) { mExpandedList.add(false); - if (mList.get(i).canUpdate()) { - alertUpdate = true; - if (alertPackage.equals("")) { - alertPackage = mList.get(i).getName(); - } else { - alertPackage += mList.get(i).getName() + ", "; - } - } } } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - viewMain = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false); - ButterKnife.bind(this, viewMain); + mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false); + ButterKnife.bind(this, mView); context = parent.getContext(); - return new ViewHolder(viewMain); + return new ViewHolder(mView); } -// @Override -// public boolean onOptionsItemSelected(MenuItem item) { -// switch (item.getItemId()) { -// case R.id.force_reload: -// listModulesDownload.clear(); -// new Utils.LoadModules(getActivity(), true).execute(); -// break; -// } -// -// return super.onOptionsItemSelected(item); -// } - @Override public void onBindViewHolder(final ViewHolder holder, int position) { - prefs = PreferenceManager.getDefaultSharedPreferences(context); - repo = mList.get(position); - mHolder = holder; - mDonateUrl = repo.getDonateUrl(); - mSupportUrl = repo.getSupportUrl(); - mLogUrl = repo.getLogUrl(); + final Repo repo = mList.get(position); mExpandedList = new ArrayList<>(mList.size()); for (int i = 0; i < mList.size(); i++) { mExpandedList.add(false); } - SetupViewElements(repo); + if (repo.isCache()) { + holder.title.setText("[Cache] " + repo.getName()); + } else { + holder.title.setText(repo.getName()); + } + String author = repo.getAuthor(); + String versionName = repo.getVersion(); + String description = repo.getDescription(); + if (versionName != null) { + holder.versionName.setText(versionName); + } + if (author != null) { + holder.author.setText(context.getString(R.string.author, author)); + } + if (description != null) { + holder.description.setText(description); + } + if (repo.isInstalled()) { + holder.installedStatus.setText(context.getString(R.string.module_installed)); + holder.installedStatus.setTextColor(Color.parseColor("#14AD00")); + holder.updateStatus.setText(repo.canUpdate() ? context.getString(R.string.module_update_available) : context.getString(R.string.module_up_to_date)); + } else { + holder.installedStatus.setText(context.getString(R.string.module_not_installed)); + } - } - - private void SetupViewElements(Repo repo) { - int mPosition = mHolder.getAdapterPosition(); - String titleString; - if (repo.getId() != null) { - if (repo.isCacheModule()) { - titleString = "[Cache] " + repo.getName(); - } else { - titleString = repo.getName(); - } - - mHolder.title.setText(titleString); - mHolder.versionName.setText(repo.getVersion()); - mHolder.description.setText(repo.getDescription()); - String authorString = this.context.getResources().getString(R.string.author) + " " + repo.getAuthor(); - mHolder.author.setText(authorString); - if (prefs.contains("ignoreUpdateAlerts")) { - ignoreAlertUpdate = prefs.getBoolean("ignoreUpdateAlerts",false); - } - mHolder.installedStatus.setText(repo.isInstalled() ? this.context.getResources().getString(R.string.module_installed) : this.context.getResources().getString(R.string.module_not_installed)); - if (mExpandedList.get(mPosition)) { - mHolder.expandLayout.setVisibility(View.VISIBLE); - } else { - mHolder.expandLayout.setVisibility(View.GONE); - } - - if (repo.isInstalled()) { - mHolder.installedStatus.setTextColor(Color.parseColor("#14AD00")); - mHolder.updateStatus.setText(repo.canUpdate() ? this.context.getResources().getString(R.string.module_update_available) : this.context.getResources().getString(R.string.module_up_to_date)); - } - - Log.d("Magisk", "ReposAdapter: Setting up info " + repo.getId() + " and " + repo.getDescription() + " and " + repo.getVersion()); - prefs = PreferenceManager.getDefaultSharedPreferences(context); - mCanUpdate = prefs.getBoolean("repo-canUpdate_" + repo.getId(), false); - - - View.OnClickListener oCl = view -> { - Log.d("Magisk", "Onlick captured, view is " + view.getId()); - - if (view.getId() == mHolder.updateImage.getId()) { - if (!repo.isInstalled() | repo.canUpdate()) { - - DownloadReceiver receiver = new DownloadReceiver() { + View.OnClickListener listener = view -> { + if (view.getId() == holder.updateImage.getId()) { + Utils.downloadAndReceive( + context, + new DownloadReceiver(repo.getName() + "-" + repo.getVersion()) { @Override public void task(Uri uri) { - new Async.FlashZIP(context, uri, repo.getName() + "-v" + repo.getVersion()); + new Async.FlashZIP(context, uri, mName) { + @Override + protected void preProcessing() throws Throwable { + super.preProcessing(); + new File(mUri.getPath()).delete(); + Shell.su( + "cd " + mFile.getParent(), + "mkdir git", + "unzip -o install.zip -d git", + "mv git/* install", + "cd install", + "rm -rf system/placeholder", + "chmod 644 $(find . -type f)", + "chmod 755 $(find . -type d)", + "rm -rf ../install.zip ../git", + "zip -r ../install.zip *", + "rm -rf ../install" + ); + } + }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } - }; - String filename = repo.getId().replace(" ", "") + ".zip"; - Utils.downloadAndReceive(context, receiver, repo.getZipUrl(), filename); - } else { - Toast.makeText(context, repo.getId() + " is already installed.", Toast.LENGTH_SHORT).show(); - } - } - if ((view.getId() == mHolder.changeLog.getId()) && (!repo.getLogUrl().equals(""))) { - new WebWindow("Changelog", repo.getLogUrl(),context); - } - if ((view.getId() == mHolder.authorLink.getId()) && (!repo.getSupportUrl().equals(""))) { - new WebWindow("Donate", repo.getDonateUrl(),context); - } - if ((view.getId() == mHolder.supportLink.getId()) && (!repo.getSupportUrl().equals(""))) { - new WebWindow("Support", repo.getSupportUrl(),context); - } - }; - mHolder.changeLog.setOnClickListener(oCl); - mHolder.updateImage.setOnClickListener(oCl); - mHolder.authorLink.setOnClickListener(oCl); - mHolder.supportLink.setOnClickListener(oCl); - if (prefs.contains("repo-isInstalled_" + repo.getId())) { - boolean mIsInstalled = prefs.getBoolean("repo-isInstalled_" + repo.getId(), false); - + }, + repo.getZipUrl(), + repo.getId().replace(" ", "") + ".zip"); } + if ((view.getId() == holder.changeLog.getId()) && (!repo.getLogUrl().equals(""))) { + new WebWindow("Changelog", repo.getLogUrl(), context); + } + if ((view.getId() == holder.authorLink.getId()) && (!repo.getSupportUrl().equals(""))) { + new WebWindow("Donate", repo.getDonateUrl(), context); + } + if ((view.getId() == holder.supportLink.getId()) && (!repo.getSupportUrl().equals(""))) { + new WebWindow("Support", repo.getSupportUrl(), context); + } + }; - } + holder.changeLog.setOnClickListener(listener); + holder.updateImage.setOnClickListener(listener); + holder.authorLink.setOnClickListener(listener); + holder.supportLink.setOnClickListener(listener); } - - @Override public int getItemCount() { return mList.size(); @@ -189,30 +144,19 @@ public class ReposAdapter extends RecyclerView.Adapter class ViewHolder extends RecyclerView.ViewHolder { - @BindView(R.id.title) - TextView title; - @BindView(R.id.version_name) - TextView versionName; - @BindView(R.id.description) - TextView description; - @BindView(R.id.author) - TextView author; - @BindView(R.id.installedStatus) - TextView installedStatus; - @BindView(R.id.updateStatus) - TextView updateStatus; - @BindView(R.id.expand_layout) - LinearLayout expandLayout; - @BindView(R.id.update) - ImageView updateImage; - @BindView(R.id.installed) - ImageView installedImage; - @BindView(R.id.changeLog) - ImageView changeLog; - @BindView(R.id.authorLink) - ImageView authorLink; - @BindView(R.id.supportLink) - ImageView supportLink; + @BindView(R.id.title) TextView title; + @BindView(R.id.version_name) TextView versionName; + @BindView(R.id.description) TextView description; + @BindView(R.id.author) TextView author; + @BindView(R.id.installedStatus) TextView installedStatus; + @BindView(R.id.updateStatus) TextView updateStatus; + @BindView(R.id.expand_layout) LinearLayout expandLayout; + @BindView(R.id.update) ImageView updateImage; + @BindView(R.id.installed) ImageView installedImage; + @BindView(R.id.changeLog) ImageView changeLog; + @BindView(R.id.authorLink) ImageView authorLink; + @BindView(R.id.supportLink) ImageView supportLink; + private ValueAnimator mAnimator; private ObjectAnimator animY2; private ViewHolder holder; @@ -243,7 +187,7 @@ public class ReposAdapter extends RecyclerView.Adapter }); - viewMain.setOnClickListener(view -> { + mView.setOnClickListener(view -> { int position = getAdapterPosition(); if (mExpandedList.get(position)) { collapse(holder.expandLayout); @@ -251,7 +195,6 @@ public class ReposAdapter extends RecyclerView.Adapter expand(holder.expandLayout); } mExpandedList.set(position, !mExpandedList.get(position)); - }); } @@ -267,23 +210,19 @@ public class ReposAdapter extends RecyclerView.Adapter int finalHeight = view.getHeight(); ValueAnimator mAnimator = slideAnimator(finalHeight, 0); mAnimator.addListener(new Animator.AnimatorListener() { - @Override public void onAnimationEnd(Animator animator) { view.setVisibility(View.GONE); } @Override - public void onAnimationStart(Animator animator) { - } + public void onAnimationStart(Animator animator) {} @Override - public void onAnimationCancel(Animator animator) { - } + public void onAnimationCancel(Animator animator) {} @Override - public void onAnimationRepeat(Animator animator) { - } + public void onAnimationRepeat(Animator animator) {} }); mAnimator.start(); animY2.reverse(); diff --git a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java index 43d9f7136..5783a900f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java +++ b/app/src/main/java/com/topjohnwu/magisk/SplashActivity.java @@ -72,7 +72,7 @@ public class SplashActivity extends AppCompatActivity { new Async.CheckUpdates(this).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); new Async.LoadModules(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new Async.LoadRepos(this).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); - new Async.BusyboxEnv(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + new Async.constructEnv(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); // Start main activity Intent intent = new Intent(this, MainActivity.class); diff --git a/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java b/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java index 4dafb1d23..8a8e00a9c 100644 --- a/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java +++ b/app/src/main/java/com/topjohnwu/magisk/receivers/DownloadReceiver.java @@ -17,8 +17,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver { long downloadID; public String mName; - public DownloadReceiver() { - } + public DownloadReceiver() {} public DownloadReceiver(String name) { mName = name; diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java index cb33af841..1497b54a5 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java @@ -10,6 +10,7 @@ import android.os.Environment; import android.preference.PreferenceManager; import android.provider.OpenableColumns; import android.support.v7.app.AlertDialog; +import android.text.TextUtils; import android.util.Log; import android.widget.Toast; @@ -23,6 +24,7 @@ import org.json.JSONException; import org.json.JSONObject; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -33,11 +35,11 @@ import java.util.List; public class Async { - public static class BusyboxEnv extends AsyncTask { + public static class constructEnv extends AsyncTask { Context mContext; - public BusyboxEnv(Context context) { + public constructEnv(Context context) { mContext = context; } @@ -45,16 +47,22 @@ public class Async { protected Void doInBackground(Void... voids) { String toolPath = mContext.getApplicationInfo().dataDir + "/busybox"; String busybox = mContext.getApplicationInfo().dataDir + "/lib/libbusybox.so"; - if (Shell.rootAccess() && !Utils.commandExists("unzip") && !Utils.itemExist(toolPath)) { - Shell.su(true, - "mkdir " + toolPath, - "chmod 755 " + toolPath, - "ln -s " + busybox + " " + toolPath + "/busybox", - "for tool in $(" + toolPath + "/busybox --list); do", - "ln -s " + busybox + " " + toolPath + "/$tool", - "done" - ); + String zip = mContext.getApplicationInfo().dataDir + "/lib/libzip.so"; + if (Shell.rootAccess()) { + if (!Utils.commandExists("unzip") || !Utils.commandExists("zip") || !Utils.itemExist(toolPath)) { + Shell.sh( + "rm -rf " + toolPath, + "mkdir " + toolPath, + "chmod 755 " + toolPath, + "ln -s " + busybox + " " + toolPath + "/busybox", + "for tool in $(" + toolPath + "/busybox --list); do", + "ln -s " + busybox + " " + toolPath + "/$tool", + "done", + !Utils.commandExists("zip") ? "ln -s " + zip + " " + toolPath + "/zip" : "" + ); + } } + return null; } } @@ -75,25 +83,24 @@ public class Async { JSONObject magisk = json.getJSONObject("magisk"); JSONObject app = json.getJSONObject("app"); - JSONObject root = json.getJSONObject("root"); Utils.remoteMagiskVersion = magisk.getInt("versionCode"); Utils.magiskLink = magisk.getString("link"); Utils.magiskChangelog = magisk.getString("changelog"); - Utils.remoteAppVersion = app.getInt("versionCode"); + Utils.remoteAppVersion = app.getString("version"); + Utils.remoteAppVersionCode = app.getInt("versionCode"); Utils.appLink = app.getString("link"); Utils.appChangelog = app.getString("changelog"); - Utils.phhLink = root.getString("phh"); - Utils.supersuLink = root.getString("supersu"); - } catch (JSONException ignored) {} + } catch (JSONException ignored) { + Logger.dev("JSON error!"); + } return null; } @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); + protected void onPostExecute(Void v) { if (Shell.rootAccess() && Utils.magiskVersion == -1) { new AlertDialog.Builder(mContext) .setTitle(R.string.no_magisk_title) @@ -101,14 +108,14 @@ public class Async { .setCancelable(true) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive( mContext, - new DownloadReceiver(mContext.getString(R.string.magisk)) { + new DownloadReceiver() { @Override public void task(Uri uri) { - new FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); + new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } }, Utils.magiskLink, - "latest_magisk.zip")) + "Magisk-v" + String.valueOf(Utils.remoteMagiskVersion) + ".zip")) .setNegativeButton(R.string.no_thanks, null) .show(); } @@ -181,14 +188,13 @@ public class Async { } } - public static class FlashZIP extends AsyncTask { + public static class FlashZIP extends AsyncTask { private String mName; - private Uri mUri; + protected Uri mUri; private ProgressDialog progress; - private File mFile, sdFile; + protected File mFile, sdFile; private Context mContext; - private List ret; private boolean copyToSD; public FlashZIP(Context context, Uri uri, String name) { @@ -204,17 +210,22 @@ public class Async { Cursor c = mContext.getContentResolver().query(uri, null, null, null, null); int nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME); c.moveToFirst(); - mName = c.getString(nameIndex); + if (nameIndex != -1) { + mName = c.getString(nameIndex); + } else { + int idx = uri.getPath().lastIndexOf('/'); + mName = uri.getPath().substring(idx + 1); + } c.close(); copyToSD = false; } - private static void createFileFromInputStream(InputStream inputStream, File f) throws IOException { - if (f.exists() && !f.delete()) { + private void createFileFromInputStream(InputStream inputStream, File file) throws IOException { + if (file.exists() && !file.delete()) { throw new IOException(); } - f.setWritable(true, false); - OutputStream outputStream = new FileOutputStream(f); + file.setWritable(true, false); + OutputStream outputStream = new FileOutputStream(file); byte buffer[] = new byte[1024]; int length; @@ -223,42 +234,53 @@ public class Async { } outputStream.close(); - Logger.dev("FlashZip: File created successfully - " + f.getPath()); + Logger.dev("FlashZip: File created successfully - " + file.getPath()); + } + + protected void preProcessing() throws Throwable { + try { + InputStream in = mContext.getContentResolver().openInputStream(mUri); + mFile = new File(mContext.getCacheDir().getAbsolutePath() + "/install.zip"); + createFileFromInputStream(in, mFile); + in.close(); + } catch (FileNotFoundException e) { + Log.e("Magisk", "FlashZip: Invalid Uri"); + throw e; + } catch (IOException e) { + Log.e("Magisk", "FlashZip: Error in creating file"); + throw e; + } } @Override protected void onPreExecute() { - super.onPreExecute(); progress = ProgressDialog.show(mContext, mContext.getString(R.string.zip_install_progress_title), mContext.getString(R.string.zip_install_progress_msg, mName)); } @Override - protected Boolean doInBackground(Void... voids) { + protected Integer doInBackground(Void... voids) { Logger.dev("FlashZip Running... " + mName); - 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); - progress.cancel(); - e.printStackTrace(); - return false; - } + List ret = null; if (Shell.rootAccess()) { + try { + preProcessing(); + } catch (Throwable e) { + this.cancel(true); + progress.cancel(); + e.printStackTrace(); + return -1; + } ret = Shell.su( "unzip -o " + mFile.getPath() + " META-INF/com/google/android/* -d " + mFile.getParent(), + "if [ \"$(cat " + mFile.getParent() + "/META-INF/com/google/android/updater-script)\" = \"#MAGISK\" ]; then echo true; else echo false; fi" + ); + if (! Boolean.parseBoolean(ret.get(ret.size() - 1))) { + return 0; + } + ret = Shell.su( "BOOTMODE=true sh " + mFile.getParent() + "/META-INF/com/google/android/update-binary dummy 1 "+ mFile.getPath(), - "if [ $? -eq 0 ]; then echo true; else echo false; fi" + "if [ $? -eq 0 ]; then echo true; else echo false; fi", + "rm -rf " + mFile.getParent() + "/META-INF" ); Logger.dev("FlashZip: Console log:"); for (String line : ret) { @@ -266,36 +288,53 @@ public class Async { } } // 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(); + if (copyToSD && mFile != null) { + sdFile = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + (mName.contains(".zip") ? mName : mName + ".zip").replace(" ", "_")); + if ((!sdFile.getParentFile().exists() && !sdFile.getParentFile().mkdirs()) || (sdFile.exists() && !sdFile.delete())) { + sdFile = null; + } else { + try { + FileInputStream in = new FileInputStream(mFile); + createFileFromInputStream(in, sdFile); + in.close(); + mFile.delete(); + } catch (IOException e) { + // Use the badass way :) + Shell.su("cp -af " + mFile.getPath() + " " + sdFile.getPath()); + if (!sdFile.exists()) { + sdFile = null; + } } - createFileFromInputStream(in, sdFile); - assert in != null; - in.close(); - } catch (IOException e) { - Log.e("Magisk", "FlashZip: Unable to copy to sdcard"); - e.printStackTrace(); + } + if (mFile.exists() && !mFile.delete()) { + Shell.su("rm -f " + mFile.getPath()); } } - mFile.delete(); - return ret != null && Boolean.parseBoolean(ret.get(ret.size() - 1)); + if (ret != null && Boolean.parseBoolean(ret.get(ret.size() - 1))) { + return 1; + } + return -1; } + // -1 = error; 0 = invalid zip; 1 = success @Override - protected void onPostExecute(Boolean result) { + protected void onPostExecute(Integer result) { super.onPostExecute(result); progress.dismiss(); - 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, mFile.getAbsolutePath()), Toast.LENGTH_LONG).show(); - } - } else { - done(); + switch (result) { + case -1: + 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, mFile.getAbsolutePath()), Toast.LENGTH_LONG).show(); + } + break; + case 0: + Toast.makeText(mContext, mContext.getString(R.string.invalid_zip), Toast.LENGTH_LONG).show(); + break; + case 1: + done(); + break; } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index 064ab5628..9fedf813e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -49,8 +49,8 @@ import javax.crypto.spec.DESKeySpec; public class Utils { - public static int magiskVersion, remoteMagiskVersion = -1, remoteAppVersion = -1; - public static String magiskLink, magiskChangelog, appChangelog, appLink, phhLink, supersuLink; + public static int magiskVersion, remoteMagiskVersion = -1, remoteAppVersionCode = -1; + public static String magiskLink, magiskChangelog, appLink, appChangelog, remoteAppVersion; private static final String TAG = "Magisk"; public static final String MAGISK_PATH = "/magisk"; @@ -99,27 +99,12 @@ public class Utils { public static boolean createFile(String path) { String command = "touch " + path + " 2>/dev/null; if [ -f " + path + " ]; then echo true; else echo false; fi"; - if (!Shell.rootAccess()) { - return false; - } else { - return Boolean.parseBoolean(Shell.su(command).get(0)); - } + return Shell.rootAccess() && Boolean.parseBoolean(Shell.su(command).get(0)); } public static boolean removeFile(String path) { - boolean check; String command = "rm -f " + path + " 2>/dev/null; if [ -f " + path + " ]; then echo false; else echo true; fi"; - if (!Shell.rootAccess()) { - return false; - } else { - try { - check = Boolean.parseBoolean(Shell.su(command).get(0)); - return check; - } catch (NullPointerException e) { - Log.d("Magisk:", "SU error executing removeFile " + e); - return false; - } - } + return Shell.rootAccess() && Boolean.parseBoolean(Shell.su(command).get(0)); } public static void toggleRoot(Boolean b, Context context) { @@ -132,7 +117,7 @@ public class Utils { if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("enable_quicktile", false)) { SetupQuickSettingsTile(context); } - PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("root",b).apply(); + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("root", b).apply(); } } @@ -183,29 +168,20 @@ public class Utils { return ret; } - public static void downloadAndReceive(Context context, DownloadReceiver receiver, String link, String file) { + public static void downloadAndReceive(Context context, DownloadReceiver receiver, String link, String filename) { + File file = new File(Environment.getExternalStorageDirectory() + "/MagiskManager/" + filename); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(context, R.string.permissionNotGranted, Toast.LENGTH_LONG).show(); return; } - File downloadFile, dir = new File(Environment.getExternalStorageDirectory() + "/MagiskManager"); - downloadFile = new File(dir + "/" + file); - if (!dir.exists()) { - if (!dir.mkdirs()) { - Toast.makeText(context, R.string.toast_error_makedir, Toast.LENGTH_LONG).show(); - return; - } - } - if (downloadFile.exists()) { - if (!downloadFile.delete()) { - Toast.makeText(context, R.string.toast_error_removing_files, Toast.LENGTH_LONG).show(); - return; - } + + if ((!file.getParentFile().exists() && !file.getParentFile().mkdirs()) || (file.exists() && !file.delete())) { + Toast.makeText(context, R.string.toast_error_makedir, Toast.LENGTH_LONG).show(); } DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link)); - request.setDestinationUri(Uri.fromFile(downloadFile)); + request.setDestinationUri(Uri.fromFile(file)); receiver.setDownloadID(downloadManager.enqueue(request)); context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); diff --git a/app/src/main/jniLibs/armeabi/libzip.so b/app/src/main/jniLibs/armeabi/libzip.so new file mode 100644 index 000000000..b6b53eec7 Binary files /dev/null and b/app/src/main/jniLibs/armeabi/libzip.so differ diff --git a/app/src/main/jniLibs/x86/libzip.so b/app/src/main/jniLibs/x86/libzip.so new file mode 100644 index 000000000..e38ca0e27 Binary files /dev/null and b/app/src/main/jniLibs/x86/libzip.so differ diff --git a/app/src/main/res/layout/list_item_module.xml b/app/src/main/res/layout/list_item_module.xml index ce2dbd2f1..9707a89c1 100644 --- a/app/src/main/res/layout/list_item_module.xml +++ b/app/src/main/res/layout/list_item_module.xml @@ -1,18 +1,19 @@ - + - - + + android:layout_gravity="center_vertical"> + android:textStyle="bold|italic" /> + + + + - - + android:gravity="end" /> - - + android:orientation="vertical"> - @@ -162,8 +160,7 @@ android:layout_marginStart="@dimen/card_imageview_margin" android:focusable="false" android:gravity="end" - android:visibility="gone" - /> + android:visibility="gone" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b69a5cf1c..f7238a11d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -91,6 +91,7 @@ Error downloading file Installation error! Error in flashing file, zip file placed in %1$s\nFlash it in recovery manually + The zip is not a Magisk Module!! Installation succeeded! Do you want to reboot now? Reboot