Zip Autoflash; Massive refactor
This commit is contained in:
parent
1f02d0f6d0
commit
e21131d67e
@ -16,8 +16,6 @@ android {
|
|||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
|
||||||
shrinkResources true
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,12 +48,7 @@ public class AboutActivity extends AppCompatActivity {
|
|||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
toolbar.setNavigationOnClickListener(view -> finish());
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ActionBar ab = getSupportActionBar();
|
ActionBar ab = getSupportActionBar();
|
||||||
if (ab != null) {
|
if (ab != null) {
|
||||||
@ -81,37 +76,31 @@ public class AboutActivity extends AppCompatActivity {
|
|||||||
appChangelog.setVisibility(View.GONE);
|
appChangelog.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
final String finalChanges = changes;
|
final String finalChanges = changes;
|
||||||
appChangelog.setOnClickListener(new View.OnClickListener() {
|
appChangelog.setOnClickListener(v -> {
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
AlertDialog d = new AlertDialog.Builder(AboutActivity.this)
|
|
||||||
.setTitle(R.string.app_changelog)
|
|
||||||
.setMessage(Html.fromHtml(finalChanges))
|
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
|
||||||
.create();
|
|
||||||
|
|
||||||
d.show();
|
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
|
||||||
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
appDevelopers.removeSummary();
|
|
||||||
appDevelopers.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
AlertDialog d = new AlertDialog.Builder(AboutActivity.this)
|
AlertDialog d = new AlertDialog.Builder(AboutActivity.this)
|
||||||
.setTitle(R.string.app_developers)
|
.setTitle(R.string.app_changelog)
|
||||||
.setMessage(Html.fromHtml(getString(R.string.app_developers_)))
|
.setMessage(Html.fromHtml(finalChanges))
|
||||||
.setPositiveButton(android.R.string.ok, null)
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
d.show();
|
d.show();
|
||||||
|
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
appDevelopers.removeSummary();
|
||||||
|
appDevelopers.setOnClickListener(view -> {
|
||||||
|
AlertDialog d = new AlertDialog.Builder(AboutActivity.this)
|
||||||
|
.setTitle(R.string.app_developers)
|
||||||
|
.setMessage(Html.fromHtml(getString(R.string.app_developers_)))
|
||||||
|
.setPositiveButton(android.R.string.ok, null)
|
||||||
|
.create();
|
||||||
|
|
||||||
|
d.show();
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
((TextView) d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
});
|
});
|
||||||
|
|
||||||
String translators = getString(R.string.translators);
|
String translators = getString(R.string.translators);
|
||||||
@ -122,20 +111,10 @@ public class AboutActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
appSourceCode.removeSummary();
|
appSourceCode.removeSummary();
|
||||||
appSourceCode.setOnClickListener(new View.OnClickListener() {
|
appSourceCode.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(SOURCE_CODE_URL))));
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(SOURCE_CODE_URL)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
supportThread.removeSummary();
|
supportThread.removeSummary();
|
||||||
supportThread.setOnClickListener(new View.OnClickListener() {
|
supportThread.setOnClickListener(view -> startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(XDA_THREAD))));
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(XDA_THREAD)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
setFloating();
|
setFloating();
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ import android.widget.CheckBox;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.module.Module;
|
import com.topjohnwu.magisk.module.Module;
|
||||||
import com.topjohnwu.magisk.rv.ItemClickListener;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.magisk.rv.ModulesAdapter;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -38,36 +37,27 @@ public abstract class BaseModuleFragment extends Fragment {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
recyclerView.setAdapter(new ModulesAdapter(listModules(), new ItemClickListener() {
|
recyclerView.setAdapter(new ModulesAdapter(listModules(), (chk, position) -> {
|
||||||
@Override
|
// On Checkbox change listener
|
||||||
public void onItemClick(View view, int position) {
|
CheckBox chbox = (CheckBox) chk;
|
||||||
// On Checkbox change listener
|
|
||||||
CheckBox chbox = (CheckBox) view;
|
|
||||||
|
|
||||||
if (!chbox.isChecked()) {
|
if (!chbox.isChecked()) {
|
||||||
listModules().get(position).createDisableFile();
|
listModules().get(position).createDisableFile();
|
||||||
Snackbar.make(view, R.string.disable_file_created, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(chk, R.string.disable_file_created, Snackbar.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
listModules().get(position).removeDisableFile();
|
listModules().get(position).removeDisableFile();
|
||||||
Snackbar.make(view, R.string.disable_file_removed, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(chk, R.string.disable_file_removed, Snackbar.LENGTH_SHORT).show();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, new ItemClickListener() {
|
}, (deleteBtn, position) -> {
|
||||||
@Override
|
// On delete button click listener
|
||||||
public void onItemClick(View view, int position) {
|
|
||||||
// On delete button click listener
|
|
||||||
|
|
||||||
listModules().get(position).createRemoveFile();
|
listModules().get(position).createRemoveFile();
|
||||||
Snackbar.make(view, R.string.remove_file_created, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(deleteBtn, R.string.remove_file_created, Snackbar.LENGTH_SHORT).show();
|
||||||
}
|
}, (undeleteBtn, position) -> {
|
||||||
}, new ItemClickListener() {
|
// On undelete button click listener
|
||||||
@Override
|
|
||||||
public void onItemClick(View view, int position) {
|
|
||||||
// On undelete button click listener
|
|
||||||
|
|
||||||
listModules().get(position).deleteRemoveFile();
|
listModules().get(position).deleteRemoveFile();
|
||||||
Snackbar.make(view, R.string.remove_file_deleted, Snackbar.LENGTH_SHORT).show();
|
Snackbar.make(undeleteBtn, R.string.remove_file_deleted, Snackbar.LENGTH_SHORT).show();
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
@ -101,18 +101,8 @@ public class LogFragment extends Fragment {
|
|||||||
|
|
||||||
private void reloadErrorLog() {
|
private void reloadErrorLog() {
|
||||||
new LogsManager(true).execute();
|
new LogsManager(true).execute();
|
||||||
svLog.post(new Runnable() {
|
svLog.post(() -> svLog.scrollTo(0, txtLog.getHeight()));
|
||||||
@Override
|
hsvLog.post(() -> hsvLog.scrollTo(0, 0));
|
||||||
public void run() {
|
|
||||||
svLog.scrollTo(0, txtLog.getHeight());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
hsvLog.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
hsvLog.scrollTo(0, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear() {
|
private void clear() {
|
||||||
@ -134,12 +124,7 @@ public class LogFragment extends Fragment {
|
|||||||
if (requestCode == 0) {
|
if (requestCode == 0) {
|
||||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
if (mClickedMenuItem != null) {
|
if (mClickedMenuItem != null) {
|
||||||
new Handler().postDelayed(new Runnable() {
|
new Handler().postDelayed(() -> onOptionsItemSelected(mClickedMenuItem), 500);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onOptionsItemSelected(mClickedMenuItem);
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(txtLog, R.string.permissionNotGranted, Snackbar.LENGTH_LONG).show();
|
||||||
|
@ -1,17 +1,9 @@
|
|||||||
package com.topjohnwu.magisk;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.DownloadManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.ActivityCompat;
|
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.content.FileProvider;
|
import android.support.v4.content.FileProvider;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
@ -22,24 +14,10 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.receivers.ApkReceiver;
|
|
||||||
import com.topjohnwu.magisk.receivers.DownloadReceiver;
|
|
||||||
import com.topjohnwu.magisk.receivers.ZipReceiver;
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import butterknife.BindColor;
|
import butterknife.BindColor;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
@ -47,8 +25,6 @@ import butterknife.ButterKnife;
|
|||||||
|
|
||||||
public class MagiskFragment extends Fragment {
|
public class MagiskFragment extends Fragment {
|
||||||
|
|
||||||
private static final String JSON_UPDATE_CHECK = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json";
|
|
||||||
|
|
||||||
@BindView(R.id.progressBarVersion) ProgressBar progressBar;
|
@BindView(R.id.progressBarVersion) ProgressBar progressBar;
|
||||||
|
|
||||||
@BindView(R.id.magiskStatusView) View magiskStatusView;
|
@BindView(R.id.magiskStatusView) View magiskStatusView;
|
||||||
@ -76,10 +52,6 @@ public class MagiskFragment extends Fragment {
|
|||||||
int statusOK = R.drawable.ic_check_circle;
|
int statusOK = R.drawable.ic_check_circle;
|
||||||
int statusUnknown = R.drawable.ic_help;
|
int statusUnknown = R.drawable.ic_help;
|
||||||
|
|
||||||
private String mLastLink, mLastFile;
|
|
||||||
private boolean mLastIsApp;
|
|
||||||
private List<String> version;
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
@ -87,49 +59,14 @@ public class MagiskFragment extends Fragment {
|
|||||||
ButterKnife.bind(this, v);
|
ButterKnife.bind(this, v);
|
||||||
|
|
||||||
new updateUI().execute();
|
new updateUI().execute();
|
||||||
new CheckUpdates().execute();
|
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setListener(View clickView, DownloadReceiver receiver, String link, String msg, String file) {
|
|
||||||
clickView.setOnClickListener(view -> new AlertDialog.Builder(getContext())
|
|
||||||
.setTitle(R.string.update_available)
|
|
||||||
.setMessage(Html.fromHtml(msg))
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(R.string.download, (dialogInterface, i) -> {
|
|
||||||
|
|
||||||
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
Toast.makeText(getContext(), R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File downloadFile, dir = new File(Environment.getExternalStorageDirectory() + "/MagiskManager");
|
|
||||||
|
|
||||||
downloadFile = new File(dir + "/" + file);
|
|
||||||
|
|
||||||
if (!dir.exists()) dir.mkdir();
|
|
||||||
|
|
||||||
DownloadManager downloadManager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link));
|
|
||||||
request.setDestinationUri(Uri.fromFile(downloadFile));
|
|
||||||
|
|
||||||
if (downloadFile.exists()) downloadFile.delete();
|
|
||||||
|
|
||||||
receiver.setDownloadID(downloadManager.enqueue(request));
|
|
||||||
|
|
||||||
getActivity().registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
|
||||||
.show());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class updateUI extends AsyncTask<Void, Void, Void> {
|
private class updateUI extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
// Make sure static block invoked
|
|
||||||
Shell.rootAccess();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +74,7 @@ public class MagiskFragment extends Fragment {
|
|||||||
protected void onPostExecute(Void v) {
|
protected void onPostExecute(Void v) {
|
||||||
super.onPostExecute(v);
|
super.onPostExecute(v);
|
||||||
|
|
||||||
if (Shell.magiskVersion == -1) {
|
if (Utils.magiskVersion == -1) {
|
||||||
magiskStatusContainer.setBackgroundColor(grey500);
|
magiskStatusContainer.setBackgroundColor(grey500);
|
||||||
magiskStatusIcon.setImageResource(statusUnknown);
|
magiskStatusIcon.setImageResource(statusUnknown);
|
||||||
|
|
||||||
@ -148,46 +85,10 @@ public class MagiskFragment extends Fragment {
|
|||||||
magiskStatusIcon.setImageResource(statusOK);
|
magiskStatusIcon.setImageResource(statusOK);
|
||||||
|
|
||||||
magiskVersion.setTextColor(green500);
|
magiskVersion.setTextColor(green500);
|
||||||
magiskVersion.setText(getString(R.string.magisk_version, String.valueOf(Shell.magiskVersion)));
|
magiskVersion.setText(getString(R.string.magisk_version, String.valueOf(Utils.magiskVersion)));
|
||||||
}
|
}
|
||||||
|
|
||||||
progressBar.setVisibility(View.GONE);
|
if (Utils.remoteMagiskVersion == -1) {
|
||||||
magiskStatusView.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CheckUpdates extends AsyncTask<Void, Void, String> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String doInBackground(Void... voids) {
|
|
||||||
try {
|
|
||||||
HttpURLConnection c = (HttpURLConnection) new URL(JSON_UPDATE_CHECK).openConnection();
|
|
||||||
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();
|
|
||||||
return sb.toString();
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String result) {
|
|
||||||
super.onPostExecute(result);
|
|
||||||
|
|
||||||
appCheckUpdatesProgress.setVisibility(View.GONE);
|
|
||||||
magiskCheckUpdatesProgress.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
appCheckUpdatesContainer.setBackgroundColor(accent);
|
appCheckUpdatesContainer.setBackgroundColor(accent);
|
||||||
magiskCheckUpdatesContainer.setBackgroundColor(accent);
|
magiskCheckUpdatesContainer.setBackgroundColor(accent);
|
||||||
|
|
||||||
@ -196,59 +97,68 @@ public class MagiskFragment extends Fragment {
|
|||||||
|
|
||||||
appCheckUpdatesStatus.setText(R.string.cannot_check_updates);
|
appCheckUpdatesStatus.setText(R.string.cannot_check_updates);
|
||||||
magiskCheckUpdatesStatus.setText(R.string.cannot_check_updates);
|
magiskCheckUpdatesStatus.setText(R.string.cannot_check_updates);
|
||||||
return;
|
} else {
|
||||||
}
|
if (Utils.remoteMagiskVersion > Utils.magiskVersion) {
|
||||||
|
|
||||||
magiskUpdateView.setVisibility(View.VISIBLE);
|
|
||||||
appUpdateView.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
try {
|
|
||||||
JSONObject json = new JSONObject(result);
|
|
||||||
|
|
||||||
JSONObject app = json.getJSONObject("app");
|
|
||||||
JSONObject magisk = json.getJSONObject("magisk");
|
|
||||||
|
|
||||||
String appVersionCode = app.getString("versionCode");
|
|
||||||
String appLink = app.getString("link");
|
|
||||||
String appChangelog = app.getString("changelog");
|
|
||||||
|
|
||||||
String magiskVersionCode = magisk.getString("versionCode");
|
|
||||||
String magiskLink = magisk.getString("link");
|
|
||||||
String magiskChangelog = magisk.getString("changelog");
|
|
||||||
|
|
||||||
//if (Integer.parseInt(magiskVersionCode) > versionInt) {
|
|
||||||
if (99 > Shell.magiskVersion) {
|
|
||||||
magiskCheckUpdatesContainer.setBackgroundColor(blue500);
|
magiskCheckUpdatesContainer.setBackgroundColor(blue500);
|
||||||
magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download);
|
magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download);
|
||||||
magiskCheckUpdatesStatus.setText(getString(R.string.magisk_update_available, magiskVersionCode));
|
magiskCheckUpdatesStatus.setText(getString(R.string.magisk_update_available, String.valueOf(Utils.remoteMagiskVersion)));
|
||||||
setListener(magiskUpdateView, new ZipReceiver(), "https://www.dropbox.com/s/dc16jf1ifhv6ef4/Magisk-v7.zip?dl=1",
|
magiskUpdateView.setOnClickListener(view -> new AlertDialog.Builder(getActivity())
|
||||||
getString(R.string.update_available_message, "Magisk", appVersionCode, magiskChangelog),
|
.setTitle(getString(R.string.update_title, getString(R.string.magisk)))
|
||||||
"latest_magisk.zip"
|
.setMessage(Html.fromHtml(getString(R.string.update_msg, getString(R.string.magisk), String.valueOf(Utils.remoteMagiskVersion), Utils.magiskChangelog)))
|
||||||
);
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> {
|
||||||
|
Utils.downloadAndReceive(
|
||||||
|
getActivity(),
|
||||||
|
new Utils.DownloadReceiver(getString(R.string.magisk)) {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
new Utils.FlashZIP(mContext, mName, file.getPath()).execute();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Utils.magiskLink, "latest_magisk.zip");
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
|
.show());
|
||||||
} else {
|
} else {
|
||||||
magiskCheckUpdatesContainer.setBackgroundColor(green500);
|
magiskCheckUpdatesContainer.setBackgroundColor(green500);
|
||||||
magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle);
|
magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle);
|
||||||
magiskCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.magisk)));
|
magiskCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.magisk)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Integer.parseInt(appVersionCode) > BuildConfig.VERSION_CODE) {
|
if (Utils.remoteAppVersion > BuildConfig.VERSION_CODE) {
|
||||||
appCheckUpdatesContainer.setBackgroundColor(blue500);
|
appCheckUpdatesContainer.setBackgroundColor(blue500);
|
||||||
appCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download);
|
appCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download);
|
||||||
appCheckUpdatesStatus.setText(getString(R.string.app_update_available, appVersionCode));
|
appCheckUpdatesStatus.setText(getString(R.string.app_update_available, String.valueOf(Utils.remoteAppVersion)));
|
||||||
setListener(appUpdateView, new ApkReceiver(), appLink,
|
appUpdateView.setOnClickListener(view -> new AlertDialog.Builder(getActivity())
|
||||||
getString(R.string.update_available_message, "Magisk Manager", appVersionCode, appChangelog),
|
.setTitle(getString(R.string.update_title, getString(R.string.app_name)))
|
||||||
"latest_manager.apk"
|
.setMessage(Html.fromHtml(getString(R.string.update_msg, getString(R.string.app_name), String.valueOf(Utils.remoteAppVersion), Utils.appChangelog)))
|
||||||
|
.setCancelable(true)
|
||||||
|
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> {
|
||||||
|
Utils.downloadAndReceive(getActivity(),
|
||||||
|
new Utils.DownloadReceiver() {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
||||||
|
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
install.setData(FileProvider.getUriForFile(mContext, "com.topjohnwu.magisk.provider", file));
|
||||||
|
mContext.startActivity(install);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Utils.appLink, "latest_manager.apk");
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
|
.show()
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
appCheckUpdatesContainer.setBackgroundColor(green500);
|
appCheckUpdatesContainer.setBackgroundColor(green500);
|
||||||
appCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle);
|
appCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle);
|
||||||
appCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.app_name)));
|
appCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.app_name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (JSONException ignored) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
appCheckUpdatesProgress.setVisibility(View.GONE);
|
||||||
|
magiskCheckUpdatesProgress.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.topjohnwu.magisk.rv;
|
package com.topjohnwu.magisk;
|
||||||
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
@ -9,7 +9,6 @@ import android.widget.CompoundButton;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
import com.topjohnwu.magisk.module.Module;
|
import com.topjohnwu.magisk.module.Module;
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
import com.topjohnwu.magisk.utils.Shell;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
@ -22,11 +21,11 @@ import butterknife.ButterKnife;
|
|||||||
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
|
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
|
||||||
|
|
||||||
private final List<Module> mList;
|
private final List<Module> mList;
|
||||||
private final ItemClickListener chboxListener;
|
private final Utils.ItemClickListener chboxListener;
|
||||||
private final ItemClickListener deleteBtnListener;
|
private final Utils.ItemClickListener deleteBtnListener;
|
||||||
private final ItemClickListener unDeleteBtnListener;
|
private final Utils.ItemClickListener unDeleteBtnListener;
|
||||||
|
|
||||||
public ModulesAdapter(List<Module> list, ItemClickListener chboxListener, ItemClickListener deleteBtnListener, ItemClickListener undeleteBtnListener) {
|
public ModulesAdapter(List<Module> list, Utils.ItemClickListener chboxListener, Utils.ItemClickListener deleteBtnListener, Utils.ItemClickListener undeleteBtnListener) {
|
||||||
this.mList = list;
|
this.mList = list;
|
||||||
this.chboxListener = chboxListener;
|
this.chboxListener = chboxListener;
|
||||||
this.deleteBtnListener = deleteBtnListener;
|
this.deleteBtnListener = deleteBtnListener;
|
||||||
@ -49,24 +48,16 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
|
|||||||
holder.description.setText(module.getDescription());
|
holder.description.setText(module.getDescription());
|
||||||
|
|
||||||
holder.checkBox.setChecked(module.isEnabled());
|
holder.checkBox.setChecked(module.isEnabled());
|
||||||
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> chboxListener.onItemClick(compoundButton, holder.getAdapterPosition()));
|
||||||
@Override
|
|
||||||
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
|
|
||||||
chboxListener.onItemClick(compoundButton, holder.getAdapterPosition());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
holder.delete.setOnClickListener(new View.OnClickListener() {
|
holder.delete.setOnClickListener(view -> {
|
||||||
@Override
|
if (module.willBeRemoved()) {
|
||||||
public void onClick(View view) {
|
unDeleteBtnListener.onItemClick(holder.delete, holder.getAdapterPosition());
|
||||||
if (module.willBeRemoved()) {
|
} else {
|
||||||
unDeleteBtnListener.onItemClick(holder.delete, holder.getAdapterPosition());
|
deleteBtnListener.onItemClick(holder.delete, holder.getAdapterPosition());
|
||||||
} else {
|
|
||||||
deleteBtnListener.onItemClick(holder.delete, holder.getAdapterPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
updateDeleteButton(holder, module);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDeleteButton(holder, module);
|
||||||
});
|
});
|
||||||
|
|
||||||
updateDeleteButton(holder, module);
|
updateDeleteButton(holder, module);
|
@ -28,13 +28,8 @@ import butterknife.ButterKnife;
|
|||||||
|
|
||||||
public class ModulesFragment extends Fragment {
|
public class ModulesFragment extends Fragment {
|
||||||
|
|
||||||
private static final String MAGISK_PATH = "/magisk";
|
public static List<Module> listModules = new ArrayList<>();
|
||||||
private static final String MAGISK_CACHE_PATH = "/cache/magisk";
|
public static List<Module> listModulesCache = new ArrayList<>();
|
||||||
|
|
||||||
private static List<Module> listModules = new ArrayList<>();
|
|
||||||
private static List<Module> listModulesCache = new ArrayList<>();
|
|
||||||
|
|
||||||
public static loadModules loadMod;
|
|
||||||
|
|
||||||
@BindView(R.id.progressBar) ProgressBar progressBar;
|
@BindView(R.id.progressBar) ProgressBar progressBar;
|
||||||
@BindView(R.id.pager) ViewPager viewPager;
|
@BindView(R.id.pager) ViewPager viewPager;
|
||||||
@ -67,8 +62,7 @@ public class ModulesFragment extends Fragment {
|
|||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
viewPager.setAdapter(new TabsAdapter(getChildFragmentManager()));
|
viewPager.setAdapter(new TabsAdapter(getChildFragmentManager()));
|
||||||
tabLayout.setupWithViewPager(viewPager);
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
loadMod = new loadModules();
|
new Utils.LoadModules(getContext()).execute();
|
||||||
loadMod.execute();
|
|
||||||
new updateUI().execute();
|
new updateUI().execute();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -94,40 +88,10 @@ public class ModulesFragment extends Fragment {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class loadModules extends AsyncTask<Void, Void, Void> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... voids) {
|
|
||||||
listModules.clear();
|
|
||||||
listModulesCache.clear();
|
|
||||||
List<String> magisk = Utils.getModList(MAGISK_PATH);
|
|
||||||
List<String> magiskCache = Utils.getModList(MAGISK_CACHE_PATH);
|
|
||||||
if (!magisk.isEmpty()) {
|
|
||||||
for (String mod : magisk) {
|
|
||||||
listModules.add(new Module(mod));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!magiskCache.isEmpty()) {
|
|
||||||
for (String mod : magiskCache) {
|
|
||||||
listModulesCache.add(new Module(mod));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class updateUI extends AsyncTask<Void, Void, Void> {
|
private class updateUI extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
// Ensure loadMod is done
|
|
||||||
try {
|
|
||||||
loadMod.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,14 +3,12 @@ package com.topjohnwu.magisk;
|
|||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.support.annotation.IdRes;
|
import android.support.annotation.IdRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.design.widget.NavigationView;
|
import android.support.design.widget.NavigationView;
|
||||||
import android.support.design.widget.Snackbar;
|
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentTransaction;
|
import android.support.v4.app.FragmentTransaction;
|
||||||
@ -22,7 +20,7 @@ import android.support.v7.widget.Toolbar;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.Shell;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
@ -50,10 +48,14 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
|||||||
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load mods in the background, as it is time consuming
|
// Startups
|
||||||
ModulesFragment.loadMod = new ModulesFragment.loadModules();
|
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|
||||||
ModulesFragment.loadMod.execute();
|
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
new Popups().execute();
|
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
|
||||||
|
}
|
||||||
|
new Utils.Initialize(this).execute();
|
||||||
|
new Utils.CheckUpdates(this).execute();
|
||||||
|
new Utils.LoadModules(this).execute();
|
||||||
|
|
||||||
setSupportActionBar(toolbar);
|
setSupportActionBar(toolbar);
|
||||||
|
|
||||||
@ -84,10 +86,6 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
|||||||
|
|
||||||
navigationView.setNavigationItemSelectedListener(this);
|
navigationView.setNavigationItemSelectedListener(this);
|
||||||
|
|
||||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
|
|
||||||
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -156,20 +154,4 @@ public class WelcomeActivity extends AppCompatActivity implements NavigationView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Popups extends AsyncTask <Void, Void, Boolean> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... voids) {
|
|
||||||
return Shell.rootAccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean rootAccess) {
|
|
||||||
super.onPostExecute(rootAccess);
|
|
||||||
if (!rootAccess) {
|
|
||||||
Snackbar.make(findViewById(android.R.id.content), R.string.no_root_access, Snackbar.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.module;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@ -13,13 +14,16 @@ public class Module {
|
|||||||
private String mRemoveFile;
|
private String mRemoveFile;
|
||||||
private String mDisableFile;
|
private String mDisableFile;
|
||||||
|
|
||||||
private String mName;
|
private String mName = null;
|
||||||
private String mVersion;
|
private String mVersion = "(No version provided)";
|
||||||
private String mDescription;
|
private String mDescription = "(No description provided)";
|
||||||
|
|
||||||
private boolean mEnable;
|
private boolean mEnable;
|
||||||
private boolean mRemove;
|
private boolean mRemove;
|
||||||
|
|
||||||
|
private String mId;
|
||||||
|
private int mVersionCode;
|
||||||
|
|
||||||
|
|
||||||
public Module(String path) {
|
public Module(String path) {
|
||||||
mRemoveFile = path + "/remove";
|
mRemoveFile = path + "/remove";
|
||||||
@ -46,9 +50,25 @@ public class Module {
|
|||||||
case "description":
|
case "description":
|
||||||
mDescription = value;
|
mDescription = value;
|
||||||
break;
|
break;
|
||||||
|
case "id":
|
||||||
|
mId = value;
|
||||||
|
break;
|
||||||
|
case "versionCode":
|
||||||
|
try {
|
||||||
|
mVersionCode = Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
mVersionCode = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mName == null) {
|
||||||
|
int sep = path.lastIndexOf('/');
|
||||||
|
mName = path.substring(sep + 1);
|
||||||
|
mId = mName;
|
||||||
|
}
|
||||||
|
|
||||||
mEnable = !Utils.fileExist(mDisableFile);
|
mEnable = !Utils.fileExist(mDisableFile);
|
||||||
mRemove = Utils.fileExist(mRemoveFile);
|
mRemove = Utils.fileExist(mRemoveFile);
|
||||||
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.receivers;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.support.v4.content.FileProvider;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class ApkReceiver extends DownloadReceiver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void task(File file) {
|
|
||||||
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
|
|
||||||
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
install.setData(FileProvider.getUriForFile(mContext, "com.topjohnwu.magisk.provider", file));
|
|
||||||
mContext.startActivity(install);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.receivers;
|
|
||||||
|
|
||||||
import android.app.DownloadManager;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.support.v4.content.FileProvider;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by topjohnwu
|
|
||||||
*/
|
|
||||||
public abstract class DownloadReceiver extends BroadcastReceiver {
|
|
||||||
public Context mContext;
|
|
||||||
long downloadID;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
mContext = context;
|
|
||||||
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
String action = intent.getAction();
|
|
||||||
if(DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)){
|
|
||||||
DownloadManager.Query query = new DownloadManager.Query();
|
|
||||||
query.setFilterById(downloadID);
|
|
||||||
Cursor c = downloadManager.query(query);
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
|
|
||||||
int status = c.getInt(columnIndex);
|
|
||||||
switch (status) {
|
|
||||||
case DownloadManager.STATUS_SUCCESSFUL:
|
|
||||||
File file = new File(Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))).getPath());
|
|
||||||
task(file);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Toast.makeText(context, R.string.error_download_file, Toast.LENGTH_LONG).show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
context.unregisterReceiver(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDownloadID(long id) { downloadID = id;}
|
|
||||||
|
|
||||||
public abstract void task(File file);
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.receivers;
|
|
||||||
|
|
||||||
import android.support.v7.app.AlertDialog;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.R;
|
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public class ZipReceiver extends DownloadReceiver {
|
|
||||||
@Override
|
|
||||||
public void task(File file) {
|
|
||||||
new AlertDialog.Builder(mContext)
|
|
||||||
.setTitle("Installation")
|
|
||||||
.setMessage("Do you want to install now?")
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton("Yes, flash now", (dialogInterface, i) -> {
|
|
||||||
new Utils.flashZIP(file.getPath(), mContext).execute();
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.rv;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
public interface ItemClickListener {
|
|
||||||
|
|
||||||
void onItemClick(View view, int position);
|
|
||||||
|
|
||||||
}
|
|
@ -17,7 +17,6 @@ public class Shell {
|
|||||||
|
|
||||||
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted; 2 = improperly rooted;
|
// -1 = problematic/unknown issue; 0 = not rooted; 1 = properly rooted; 2 = improperly rooted;
|
||||||
public static int rootStatus;
|
public static int rootStatus;
|
||||||
public static int magiskVersion;
|
|
||||||
|
|
||||||
private static Process rootShell;
|
private static Process rootShell;
|
||||||
private static DataOutputStream rootSTDIN;
|
private static DataOutputStream rootSTDIN;
|
||||||
@ -30,13 +29,6 @@ public class Shell {
|
|||||||
|
|
||||||
private static void init() {
|
private static void init() {
|
||||||
|
|
||||||
List<String> ret = sh("getprop magisk.version");
|
|
||||||
if (ret.get(0).replaceAll("\\s", "").isEmpty()) {
|
|
||||||
magiskVersion = -1;
|
|
||||||
} else {
|
|
||||||
magiskVersion = Integer.parseInt(ret.get(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
rootShell = Runtime.getRuntime().exec(sh("getprop magisk.supath").get(0) + "/su");
|
rootShell = Runtime.getRuntime().exec(sh("getprop magisk.supath").get(0) + "/su");
|
||||||
rootStatus = 1;
|
rootStatus = 1;
|
||||||
@ -56,7 +48,7 @@ public class Shell {
|
|||||||
rootSTDOUT = new StreamGobbler(rootShell.getInputStream(), rootOutList);
|
rootSTDOUT = new StreamGobbler(rootShell.getInputStream(), rootOutList);
|
||||||
rootSTDOUT.start();
|
rootSTDOUT.start();
|
||||||
|
|
||||||
ret = su("echo -BOC-", "id");
|
List<String> ret = su("echo -BOC-", "id");
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
// Something wrong with root, not allowed?
|
// Something wrong with root, not allowed?
|
||||||
rootStatus = -1;
|
rootStatus = -1;
|
||||||
|
@ -1,17 +1,48 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
package com.topjohnwu.magisk.utils;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.DownloadManager;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.design.widget.Snackbar;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.ModulesFragment;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
|
import com.topjohnwu.magisk.module.Module;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
|
public static int magiskVersion, remoteMagiskVersion = -1, remoteAppVersion = -1;
|
||||||
|
public static String magiskLink, magiskChangelog, appChangelog, appLink, phhLink, supersuLink;
|
||||||
|
|
||||||
|
public static final String MAGISK_PATH = "/magisk";
|
||||||
|
public static final String MAGISK_CACHE_PATH = "/cache/magisk";
|
||||||
|
public static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json";
|
||||||
|
|
||||||
public static boolean fileExist(String path) {
|
public static boolean fileExist(String path) {
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
ret = Shell.sh("if [ -f " + path + " ]; then echo true; else echo false; fi");
|
ret = Shell.sh("if [ -f " + path + " ]; then echo true; else echo false; fi");
|
||||||
@ -37,33 +68,336 @@ public class Utils {
|
|||||||
|
|
||||||
public static List<String> getModList(String path) {
|
public static List<String> getModList(String path) {
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
ret = Shell.sh("find " + path + " -type d -maxdepth 1 | while read ITEM ; do if [ -f $ITEM/module.prop ]; then echo $ITEM; fi; done");
|
ret = Shell.sh("find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\"");
|
||||||
if (ret.isEmpty() && Shell.rootAccess()) ret = Shell.su("find " + path + " -type d -maxdepth 1 | while read ITEM ; do if [ -f $ITEM/module.prop ]; then echo $ITEM; fi; done");
|
if (ret.isEmpty() && Shell.rootAccess())
|
||||||
|
ret = Shell.su("find " + path + " -type d -maxdepth 1 ! -name \"*.core\" ! -name \"*lost+found\" ! -name \"*magisk\"");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<String> readFile(String path) {
|
public static List<String> readFile(String path) {
|
||||||
List<String> ret;
|
List<String> ret;
|
||||||
ret = Shell.sh("cat " + path);
|
ret = Shell.sh("cat " + path);
|
||||||
if (ret.isEmpty() && Shell.rootAccess()) ret = Shell.su("cat " + path);
|
if (ret.isEmpty() && Shell.rootAccess())
|
||||||
|
ret = Shell.su("cat " + path);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class flashZIP extends AsyncTask<Void, Void, Boolean> {
|
public static void downloadAndReceive(Context context, DownloadReceiver receiver, String link, String file) {
|
||||||
|
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()) dir.mkdir();
|
||||||
|
if (downloadFile.exists()) downloadFile.delete();
|
||||||
|
|
||||||
private String mPath;
|
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
private ProgressDialog progress;
|
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(link));
|
||||||
Context mContext;
|
request.setDestinationUri(Uri.fromFile(downloadFile));
|
||||||
|
|
||||||
public flashZIP(String path, Context context) {
|
receiver.setDownloadID(downloadManager.enqueue(request));
|
||||||
mPath = path;
|
context.registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class DownloadReceiver extends BroadcastReceiver {
|
||||||
|
public Context mContext;
|
||||||
|
long downloadID;
|
||||||
|
public String mName;
|
||||||
|
|
||||||
|
public DownloadReceiver() {}
|
||||||
|
public DownloadReceiver(String name) { mName = name; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
|
String action = intent.getAction();
|
||||||
|
if(DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)){
|
||||||
|
DownloadManager.Query query = new DownloadManager.Query();
|
||||||
|
query.setFilterById(downloadID);
|
||||||
|
Cursor c = downloadManager.query(query);
|
||||||
|
if (c.moveToFirst()) {
|
||||||
|
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
|
||||||
|
int status = c.getInt(columnIndex);
|
||||||
|
switch (status) {
|
||||||
|
case DownloadManager.STATUS_SUCCESSFUL:
|
||||||
|
File file = new File(Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))).getPath());
|
||||||
|
task(file);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
context.unregisterReceiver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadID(long id) { downloadID = id;}
|
||||||
|
public abstract void task(File file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Initialize extends AsyncTask <Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
public Initialize(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
List<String> ret = Shell.sh("getprop magisk.version");
|
||||||
|
if (ret.get(0).replaceAll("\\s", "").isEmpty()) {
|
||||||
|
magiskVersion = -1;
|
||||||
|
} else {
|
||||||
|
magiskVersion = Integer.parseInt(ret.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install Busybox and set as top priority
|
||||||
|
if (Shell.rootAccess()) {
|
||||||
|
String busybox = mContext.getApplicationInfo().nativeLibraryDir + "/libbusybox.so";
|
||||||
|
Shell.su(
|
||||||
|
"rm -rf /data/busybox",
|
||||||
|
"mkdir -p /data/busybox",
|
||||||
|
"cp -af " + busybox + " /data/busybox/busybox",
|
||||||
|
"chmod 755 /data/busybox /data/busybox/busybox",
|
||||||
|
"chcon u:object_r:system_file:s0 /data/busybox /data/busybox/busybox",
|
||||||
|
"/data/busybox/busybox --install -s /data/busybox",
|
||||||
|
"rm -f /data/busybox/su",
|
||||||
|
"export PATH=/data/busybox:$PATH"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
if (!Shell.rootAccess()) {
|
||||||
|
Snackbar.make(((Activity)mContext).findViewById(android.R.id.content), R.string.no_root_access, Snackbar.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CheckUpdates extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
public CheckUpdates(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
try {
|
||||||
|
HttpURLConnection c = (HttpURLConnection) new URL(UPDATE_JSON).openConnection();
|
||||||
|
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 app = json.getJSONObject("app");
|
||||||
|
JSONObject root = json.getJSONObject("root");
|
||||||
|
|
||||||
|
remoteMagiskVersion = magisk.getInt("versionCode");
|
||||||
|
magiskLink = magisk.getString("link");
|
||||||
|
magiskChangelog = magisk.getString("changelog");
|
||||||
|
|
||||||
|
remoteAppVersion = app.getInt("versionCode");
|
||||||
|
appLink = app.getString("link");
|
||||||
|
appChangelog = app.getString("changelog");
|
||||||
|
|
||||||
|
phhLink = root.getString("phh");
|
||||||
|
supersuLink = root.getString("supersu");
|
||||||
|
|
||||||
|
} catch (IOException | JSONException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
if (Shell.rootAccess() && magiskVersion == -1) {
|
||||||
|
new AlertDialog.Builder(mContext)
|
||||||
|
.setTitle(R.string.no_magisk_title)
|
||||||
|
.setMessage(R.string.no_magisk_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) -> {
|
||||||
|
DownloadReceiver rootReceiver;
|
||||||
|
String link, filename;
|
||||||
|
switch (root) {
|
||||||
|
case 0:
|
||||||
|
link = phhLink;
|
||||||
|
filename = "phhsu.zip";
|
||||||
|
rootReceiver = new DownloadReceiver(mContext.getString(R.string.phh)) {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
new RemoveSystemSU().execute();
|
||||||
|
new FlashZIP(mContext, mName, file.getPath()).execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
link = supersuLink;
|
||||||
|
filename = "supersu.zip";
|
||||||
|
rootReceiver = new DownloadReceiver(mContext.getString(R.string.supersu)) {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
new RemoveSystemSU().execute();
|
||||||
|
new FlashZIP(mContext, mName, file.getPath()).execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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() {
|
||||||
|
downloadAndReceive(temp, rootReceiver, link, filename);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
downloadAndReceive(mContext, magiskReceiver, 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:
|
||||||
|
downloadAndReceive(
|
||||||
|
mContext,
|
||||||
|
new DownloadReceiver(mContext.getString(R.string.phh)) {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
new FlashZIP(mContext, mName, file.getPath()).execute();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
phhLink, "phhsu.zip");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
downloadAndReceive(
|
||||||
|
mContext,
|
||||||
|
new DownloadReceiver(mContext.getString(R.string.supersu)) {
|
||||||
|
@Override
|
||||||
|
public void task(File file) {
|
||||||
|
new FlashZIP(mContext, mName, file.getPath()).execute();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
supersuLink, "supersu.zip");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RemoveSystemSU extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
Shell.su(
|
||||||
|
"umount /system/xbin",
|
||||||
|
"umount -l /system/xbin",
|
||||||
|
"if [ ! -z $(which su | grep system) ]; then",
|
||||||
|
"mount -o rw,remount /system",
|
||||||
|
"rm -rf /system/.pin /system/app/SuperSU /system/bin/.ext /system/etc/.installed_su_daemon " +
|
||||||
|
"/system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /system/xbin/daemonsu " +
|
||||||
|
"/system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy " +
|
||||||
|
"/data/app/eu.chainfire.supersu-*",
|
||||||
|
"mv -f /system/bin/app_process32_original /system/bin/app_process32",
|
||||||
|
"mv -f /system/bin/app_process64_original /system/bin/app_process64",
|
||||||
|
"mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh",
|
||||||
|
"if [ -e /system/bin/app_process64 ]; then",
|
||||||
|
"ln -sf /system/bin/app_process64 /system/bin/app_process",
|
||||||
|
"else",
|
||||||
|
"ln -sf /system/bin/app_process32 /system/bin/app_process",
|
||||||
|
"fi",
|
||||||
|
"umount /system",
|
||||||
|
"fi",
|
||||||
|
"setprop magisk.root 1"
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LoadModules extends AsyncTask<Void, Void, Void> {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
public LoadModules(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
ModulesFragment.listModules.clear();
|
||||||
|
ModulesFragment.listModulesCache.clear();
|
||||||
|
List<String> magisk = getModList(MAGISK_PATH);
|
||||||
|
List<String> magiskCache = getModList(MAGISK_CACHE_PATH);
|
||||||
|
for (String mod : magisk) {
|
||||||
|
ModulesFragment.listModules.add(new Module(mod));
|
||||||
|
}
|
||||||
|
for (String mod : magiskCache) {
|
||||||
|
ModulesFragment.listModulesCache.add(new Module(mod));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FlashZIP extends AsyncTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
|
private String mPath, mName;
|
||||||
|
private ProgressDialog progress;
|
||||||
|
private Context mContext;
|
||||||
|
|
||||||
|
public FlashZIP(Context context, String name, String path) {
|
||||||
|
mContext = context;
|
||||||
|
mName = name;
|
||||||
|
mPath = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPreExecute() {
|
protected void onPreExecute() {
|
||||||
super.onPreExecute();
|
super.onPreExecute();
|
||||||
progress = ProgressDialog.show(mContext, "Installing", "Patching boot image for Magisk....");
|
progress = ProgressDialog.show(mContext, mContext.getString(R.string.zip_install_progress_title), mContext.getString(R.string.zip_install_progress_msg, mName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -71,14 +405,15 @@ public class Utils {
|
|||||||
if (!Shell.rootAccess()) {
|
if (!Shell.rootAccess()) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
Shell.su(
|
List<String> ret = Shell.su(
|
||||||
"rm -rf /data/tmp",
|
"rm -rf /data/tmp",
|
||||||
"mkdir -p /data/tmp",
|
"mkdir -p /data/tmp",
|
||||||
"cp -af " + mPath + " /data/tmp/install.zip",
|
"cp -af " + mPath + " /data/tmp/install.zip",
|
||||||
"unzip -o /data/tmp/install.zip META-INF/com/google/android/* -d /data/tmp",
|
"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"
|
"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"
|
||||||
);
|
);
|
||||||
return Boolean.parseBoolean(Shell.su("if [ $? -eq 0 ]; then echo true; else echo false; fi").get(0));
|
return Boolean.parseBoolean(ret.get(ret.size() -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,15 +423,25 @@ public class Utils {
|
|||||||
Shell.su("rm -rf /data/tmp");
|
Shell.su("rm -rf /data/tmp");
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
if (!result) {
|
if (!result) {
|
||||||
Toast.makeText(mContext, "Installation failed...", Toast.LENGTH_LONG).show();
|
Toast.makeText(mContext, mContext.getString(R.string.manual_install, mPath), Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void done() {
|
||||||
new AlertDialog.Builder(mContext)
|
new AlertDialog.Builder(mContext)
|
||||||
.setTitle("Reboot now?")
|
.setTitle(R.string.reboot_title)
|
||||||
.setPositiveButton("Yes", (dialogInterface1, i1) -> Toast.makeText(mContext, "Reboot...", Toast.LENGTH_LONG).show())
|
.setMessage(R.string.reboot_msg)
|
||||||
|
.setPositiveButton(R.string.reboot, (dialogInterface1, i) -> Shell.su("reboot"))
|
||||||
.setNegativeButton(R.string.no_thanks, null)
|
.setNegativeButton(R.string.no_thanks, null)
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ItemClickListener {
|
||||||
|
|
||||||
|
void onItemClick(View view, int position);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
BIN
app/src/main/jniLibs/armeabi/libbusybox.so
Normal file
BIN
app/src/main/jniLibs/armeabi/libbusybox.so
Normal file
Binary file not shown.
BIN
app/src/main/jniLibs/x86/libbusybox.so
Normal file
BIN
app/src/main/jniLibs/x86/libbusybox.so
Normal file
Binary file not shown.
@ -5,7 +5,7 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/force_reload"
|
android:id="@+id/force_reload"
|
||||||
android:icon="@drawable/ic_refresh"
|
android:icon="@drawable/ic_refresh"
|
||||||
android:title="@string/force_reload"
|
android:title="@string/menuReload"
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Magisk Manager</string>
|
|
||||||
<string name="about">Info su…</string>
|
<string name="about">Info su…</string>
|
||||||
<string name="app_changelog">Changelog dell\'app</string>
|
<string name="app_changelog">Changelog dell\'app</string>
|
||||||
<string name="app_developers">Sviluppatori principali</string>
|
<string name="app_developers">Sviluppatori principali</string>
|
||||||
@ -11,8 +10,6 @@
|
|||||||
<string name="cache_modules">Moduli in cache</string>
|
<string name="cache_modules">Moduli in cache</string>
|
||||||
<string name="disable_file_created">Il modulo verrà disabilitato al prossimo riavvio</string>
|
<string name="disable_file_created">Il modulo verrà disabilitato al prossimo riavvio</string>
|
||||||
<string name="disable_file_removed">Il modulo verrà abilitato al prossimo riavvio</string>
|
<string name="disable_file_removed">Il modulo verrà abilitato al prossimo riavvio</string>
|
||||||
<string name="force_reload">Aggiorna</string>
|
|
||||||
<string name="loading">Caricamento…</string>
|
|
||||||
<string name="log">Log</string>
|
<string name="log">Log</string>
|
||||||
<string name="log_is_empty">Il log è vuoto</string>
|
<string name="log_is_empty">Il log è vuoto</string>
|
||||||
<string name="logs_clear_failed">Non è possibile leggere il log:</string>
|
<string name="logs_clear_failed">Non è possibile leggere il log:</string>
|
||||||
|
@ -1,10 +1,28 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Magisk Manager</string>
|
<!--Universal-->
|
||||||
|
<string name="app_name" translatable="false">Magisk Manager</string>
|
||||||
<string name="magisk" translatable="false">Magisk</string>
|
<string name="magisk" translatable="false">Magisk</string>
|
||||||
|
|
||||||
|
<!--Welcome Activity-->
|
||||||
|
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||||
|
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||||
|
<string name="root">Root</string>
|
||||||
|
<string name="modules">Modules</string>
|
||||||
|
<string name="log">Log</string>
|
||||||
|
|
||||||
|
<!--Magisk Fragment-->
|
||||||
<string name="magisk_version">Installed Magisk v%1$s</string>
|
<string name="magisk_version">Installed Magisk v%1$s</string>
|
||||||
<string name="magisk_version_error">Have you installed Magisk?</string>
|
<string name="magisk_version_error">Have you installed Magisk?</string>
|
||||||
|
|
||||||
|
<string name="app_update_available">Magisk Manager App v%1$s update!</string>
|
||||||
|
<string name="magisk_update_available">Magisk v%1$s update!</string>
|
||||||
|
<string name="cannot_check_updates">Cannot check for updates</string>
|
||||||
|
<string name="up_to_date">Latest version of %1$s installed</string>
|
||||||
|
|
||||||
|
<!--Root Fragment-->
|
||||||
|
<string name="root_toggle">Root Toggle</string>
|
||||||
|
<string name="selinux_toggle">SELinux Toggle</string>
|
||||||
|
|
||||||
<string name="root_error">Root Error</string>
|
<string name="root_error">Root Error</string>
|
||||||
<string name="root_error_info">Safety Net Status Unknown</string>
|
<string name="root_error_info">Safety Net Status Unknown</string>
|
||||||
<string name="root_none">Not Rooted</string>
|
<string name="root_none">Not Rooted</string>
|
||||||
@ -13,7 +31,7 @@
|
|||||||
<string name="root_mounted_info">Root mounted and enabled. Safety Net (Android Pay) will NOT work</string>
|
<string name="root_mounted_info">Root mounted and enabled. Safety Net (Android Pay) will NOT work</string>
|
||||||
<string name="root_unmounted">Root not mounted</string>
|
<string name="root_unmounted">Root not mounted</string>
|
||||||
<string name="root_unmounted_info">Safety Net (Android Pay) should work, but no root temporarily\nYou might need to manually add a card in Android Pay app to refresh the root status of AP</string>
|
<string name="root_unmounted_info">Safety Net (Android Pay) should work, but no root temporarily\nYou might need to manually add a card in Android Pay app to refresh the root status of AP</string>
|
||||||
<string name="root_system">Improperly Installed</string>
|
<string name="root_system">Magisk Incompatible Root Detected</string>
|
||||||
<string name="root_system_info">Root improperly installed. Safety Net (Android Pay) will NOT work, and impossible to toggle</string>
|
<string name="root_system_info">Root improperly installed. Safety Net (Android Pay) will NOT work, and impossible to toggle</string>
|
||||||
|
|
||||||
<string name="selinux_error_info">SELinux Status Unknown</string>
|
<string name="selinux_error_info">SELinux Status Unknown</string>
|
||||||
@ -21,17 +39,15 @@
|
|||||||
<string name="selinux_permissive_info">SELinux is permissive\nOnly turn off SELinux if necessary!</string>
|
<string name="selinux_permissive_info">SELinux is permissive\nOnly turn off SELinux if necessary!</string>
|
||||||
<string name="selinux_samsung_info">Samsung need custom kernel for switching SELinux status!</string>
|
<string name="selinux_samsung_info">Samsung need custom kernel for switching SELinux status!</string>
|
||||||
|
|
||||||
<string name="root_toggle">Root Toggle</string>
|
<!--Module Fragment-->
|
||||||
<string name="selinux_toggle">SELinux Toggle</string>
|
<string name="cache_modules">Cache modules</string>
|
||||||
|
<string name="no_modules_found">No modules found</string>
|
||||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
|
||||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
|
||||||
|
|
||||||
<string name="modules">Modules</string>
|
|
||||||
<string name="log">Log</string>
|
|
||||||
<string name="no_root_access">No root access, functionality limited</string>
|
|
||||||
<string name="remove_file_created">Module will be removed at next reboot</string>
|
<string name="remove_file_created">Module will 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>
|
||||||
|
|
||||||
|
<!--Log Fragment-->
|
||||||
<string name="menuSaveToSd">Save to SD</string>
|
<string name="menuSaveToSd">Save to SD</string>
|
||||||
<string name="menuSend">Send</string>
|
<string name="menuSend">Send</string>
|
||||||
<string name="menuReload">Reload</string>
|
<string name="menuReload">Reload</string>
|
||||||
@ -41,10 +57,8 @@
|
|||||||
<string name="logs_clear_failed">Could not clear the log:</string>
|
<string name="logs_clear_failed">Could not clear the log:</string>
|
||||||
<string name="log_is_empty">Log is empty</string>
|
<string name="log_is_empty">Log is empty</string>
|
||||||
<string name="logs_save_failed">Could not write log to SD card:</string>
|
<string name="logs_save_failed">Could not write log to SD card:</string>
|
||||||
<string name="permissionNotGranted">This feature will not work without permission to write external storage.</string>
|
|
||||||
<string name="disable_file_removed">Module will be enabled at next reboot</string>
|
<!--About Activity-->
|
||||||
<string name="remove_file_deleted">Module will not be removed at next reboot</string>
|
|
||||||
<string name="cache_modules">Cache modules</string>
|
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
<string name="app_developers">Main developers</string>
|
<string name="app_developers">Main developers</string>
|
||||||
<string name="app_developers_"><![CDATA[App created by <a href="https://github.com/topjohnwu">topjohnwu</a> in collaboration with <a href="https://github.com/dvdandroid">dvdandroid</a>]]></string>
|
<string name="app_developers_"><![CDATA[App created by <a href="https://github.com/topjohnwu">topjohnwu</a> in collaboration with <a href="https://github.com/dvdandroid">dvdandroid</a>]]></string>
|
||||||
@ -54,20 +68,25 @@
|
|||||||
<string name="app_source_code">Source code</string>
|
<string name="app_source_code">Source code</string>
|
||||||
<string name="app_translators">App\'s translators</string>
|
<string name="app_translators">App\'s translators</string>
|
||||||
<string name="support_thread">Support thread</string>
|
<string name="support_thread">Support thread</string>
|
||||||
<string name="force_reload">Refresh</string>
|
|
||||||
<string name="no_modules_found">No modules found</string>
|
|
||||||
<string name="loading">Loading…</string>
|
|
||||||
<string name="update_available">Update available!</string>
|
|
||||||
<string name="download">Download</string>
|
|
||||||
<string name="update_available_message"><![CDATA[A new version of %1$s is available!<br>Version: v%2$s<br>Changelog:<br>%3$s]]></string>
|
|
||||||
<string name="no_thanks">No, thanks</string>
|
|
||||||
<string name="never_show_again">Don\'t show again</string>
|
|
||||||
<string name="error_download_file">Error downloading file</string>
|
|
||||||
<string name="flash_recovery">File downloaded in Magisk directory, you can flash it in recovery</string>
|
|
||||||
<string name="root">Root</string>
|
|
||||||
<string name="app_update_available">Magisk Manager App v%1$s update!</string>
|
|
||||||
<string name="magisk_update_available">Magisk v%1$s update!</string>
|
|
||||||
<string name="cannot_check_updates">Cannot check for updates</string>
|
|
||||||
<string name="up_to_date">Latest version of %1$s installed</string>
|
|
||||||
|
|
||||||
|
<!--Toasts, Dialogs-->
|
||||||
|
<string name="permissionNotGranted">This feature will not work without permission to write external storage.</string>
|
||||||
|
<string name="no_root_access">No root access, functionality limited</string>
|
||||||
|
<string name="no_thanks">No thanks</string>
|
||||||
|
<string name="update_title">%1$s Update!</string>
|
||||||
|
<string name="update_msg"><![CDATA[New version v%2$s of %1$s is available!<br>Changelog:<br>%3$s]]></string>
|
||||||
|
<string name="download_install">Download and install</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="reboot_title">Installation succeeded!</string>
|
||||||
|
<string name="reboot_msg">Do you want to reboot now?</string>
|
||||||
|
<string name="reboot">Reboot</string>
|
||||||
|
<string name="zip_install_progress_title">Installing</string>
|
||||||
|
<string name="zip_install_progress_msg">"Installing %1$s …"</string>
|
||||||
|
<string name="no_magisk_title">No Magisk Installed!</string>
|
||||||
|
<string name="no_magisk_msg">Do you want to download and install Magisk?</string>
|
||||||
|
<string name="root_method_title">Choose a root method</string>
|
||||||
|
<string name="phh">phh\'s superuser</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>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user