mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 12:05:30 +00:00
Use internal library for networking
This commit is contained in:
parent
eab74ef06b
commit
59b1e63bdf
@ -71,8 +71,8 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'androidx.core:core:1.0.1'
|
implementation 'androidx.core:core:1.0.1'
|
||||||
|
implementation project(':net')
|
||||||
fullImplementation project(':utils')
|
fullImplementation project(':utils')
|
||||||
fullImplementation 'com.amitshekhar.android:android-networking:1.0.2'
|
|
||||||
fullImplementation 'androidx.appcompat:appcompat:1.0.2'
|
fullImplementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}"
|
fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}"
|
||||||
fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
|
fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}"
|
||||||
|
@ -67,7 +67,7 @@ public class Const {
|
|||||||
public static class Url {
|
public static class Url {
|
||||||
public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/stable.json";
|
public static final String STABLE_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/stable.json";
|
||||||
public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/beta.json";
|
public static final String BETA_URL = "https://raw.githubusercontent.com/topjohnwu/magisk_files/master/beta.json";
|
||||||
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&sort=pushed";
|
public static final String REPO_URL = "https://api.github.com/users/Magisk-Modules-Repo/repos?per_page=100&sort=pushed&page=%d";
|
||||||
public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
|
public static final String FILE_URL = "https://raw.githubusercontent.com/Magisk-Modules-Repo/%s/master/%s";
|
||||||
public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
|
public static final String ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip";
|
||||||
public static final String PAYPAL_URL = "https://www.paypal.me/topjohnwu";
|
public static final String PAYPAL_URL = "https://www.paypal.me/topjohnwu";
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
|
|
||||||
import com.topjohnwu.magisk.Const;
|
|
||||||
import com.topjohnwu.magisk.Data;
|
|
||||||
import com.topjohnwu.magisk.utils.ISafetyNetHelper;
|
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
|
||||||
import com.topjohnwu.magisk.utils.WebService;
|
|
||||||
import com.topjohnwu.superuser.Shell;
|
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
|
|
||||||
import dalvik.system.DexClassLoader;
|
|
||||||
|
|
||||||
public class CheckSafetyNet extends ParallelTask<Void, Void, Void> {
|
|
||||||
|
|
||||||
public static final File dexPath =
|
|
||||||
new File(Data.MM().getFilesDir().getParent() + "/snet", "snet.apk");
|
|
||||||
private ISafetyNetHelper helper;
|
|
||||||
|
|
||||||
public CheckSafetyNet(Activity activity) {
|
|
||||||
super(activity);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dlSnet() throws Exception {
|
|
||||||
Shell.sh("rm -rf " + dexPath.getParent()).exec();
|
|
||||||
dexPath.getParentFile().mkdir();
|
|
||||||
HttpURLConnection conn = WebService.mustRequest(Const.Url.SNET_URL);
|
|
||||||
try (
|
|
||||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(dexPath));
|
|
||||||
InputStream in = new BufferedInputStream(conn.getInputStream())) {
|
|
||||||
ShellUtils.pump(in, out);
|
|
||||||
} finally {
|
|
||||||
conn.disconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dyload() throws Exception {
|
|
||||||
DexClassLoader loader = new DexClassLoader(dexPath.getPath(), dexPath.getParent(),
|
|
||||||
null, ISafetyNetHelper.class.getClassLoader());
|
|
||||||
Class<?> clazz = loader.loadClass("com.topjohnwu.snet.Snet");
|
|
||||||
helper = (ISafetyNetHelper) clazz.getMethod("newHelper",
|
|
||||||
Class.class, String.class, Activity.class, Object.class)
|
|
||||||
.invoke(null, ISafetyNetHelper.class, dexPath.getPath(), getActivity(),
|
|
||||||
(ISafetyNetHelper.Callback) code ->
|
|
||||||
Topic.publish(false, Topic.SNET_CHECK_DONE, code));
|
|
||||||
if (helper.getVersion() < Const.SNET_EXT_VER) {
|
|
||||||
throw new Exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void doInBackground(Void... voids) {
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
dyload();
|
|
||||||
} catch (Exception e) {
|
|
||||||
// If dynamic load failed, try re-downloading and reload
|
|
||||||
dlSnet();
|
|
||||||
dyload();
|
|
||||||
}
|
|
||||||
// Run attestation
|
|
||||||
helper.attest();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Topic.publish(false, Topic.SNET_CHECK_DONE, -1);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,12 @@
|
|||||||
package com.topjohnwu.magisk.asyncs;
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.androidnetworking.error.ANError;
|
|
||||||
import com.androidnetworking.interfaces.JSONObjectRequestListener;
|
|
||||||
import com.topjohnwu.magisk.BuildConfig;
|
import com.topjohnwu.magisk.BuildConfig;
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.components.Notifications;
|
import com.topjohnwu.magisk.components.Notifications;
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
|
import com.topjohnwu.net.ResponseListener;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -57,14 +56,14 @@ public class CheckUpdates {
|
|||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AndroidNetworking.get(url).build().getAsJSONObject(new UpdateListener(cb));
|
Networking.get(url).getAsJSONObject(new UpdateListener(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void check() {
|
public static void check() {
|
||||||
check(null);
|
check(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class UpdateListener implements JSONObjectRequestListener {
|
private static class UpdateListener implements ResponseListener<JSONObject> {
|
||||||
|
|
||||||
private Runnable cb;
|
private Runnable cb;
|
||||||
|
|
||||||
@ -100,8 +99,5 @@ public class CheckUpdates {
|
|||||||
}
|
}
|
||||||
Topic.publish(Topic.UPDATE_CHECK_DONE);
|
Topic.publish(Topic.UPDATE_CHECK_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ANError anError) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,15 @@ import com.topjohnwu.magisk.MagiskManager;
|
|||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.components.ProgressNotification;
|
import com.topjohnwu.magisk.components.ProgressNotification;
|
||||||
import com.topjohnwu.magisk.container.Repo;
|
import com.topjohnwu.magisk.container.Repo;
|
||||||
import com.topjohnwu.magisk.utils.WebService;
|
import com.topjohnwu.net.Networking;
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilterInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
@ -40,12 +37,10 @@ public class DownloadModule {
|
|||||||
ProgressNotification progress = new ProgressNotification(output.getName());
|
ProgressNotification progress = new ProgressNotification(output.getName());
|
||||||
try {
|
try {
|
||||||
MagiskManager mm = Data.MM();
|
MagiskManager mm = Data.MM();
|
||||||
HttpURLConnection conn = WebService.mustRequest(repo.getZipUrl());
|
InputStream in = Networking.get(repo.getZipUrl())
|
||||||
ProgressInputStream pis = new ProgressInputStream(conn.getInputStream(),
|
.setDownloadProgressListener(progress)
|
||||||
conn.getContentLength(), progress);
|
.execForInputStream().getResult();
|
||||||
removeTopFolder(new BufferedInputStream(pis),
|
removeTopFolder(in, new BufferedOutputStream(new FileOutputStream(output)));
|
||||||
new BufferedOutputStream(new FileOutputStream(output)));
|
|
||||||
conn.disconnect();
|
|
||||||
if (install) {
|
if (install) {
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
Intent intent = new Intent(mm, Data.classMap.get(FlashActivity.class));
|
Intent intent = new Intent(mm, Data.classMap.get(FlashActivity.class));
|
||||||
@ -81,45 +76,4 @@ public class DownloadModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ProgressInputStream extends FilterInputStream {
|
|
||||||
|
|
||||||
private long totalBytes;
|
|
||||||
private long bytesDownloaded;
|
|
||||||
private ProgressNotification progress;
|
|
||||||
|
|
||||||
protected ProgressInputStream(InputStream in, long size, ProgressNotification p) {
|
|
||||||
super(in);
|
|
||||||
totalBytes = size;
|
|
||||||
progress = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgress() {
|
|
||||||
progress.onProgress(bytesDownloaded, totalBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
int b = super.read();
|
|
||||||
if (b >= 0) {
|
|
||||||
bytesDownloaded++;
|
|
||||||
updateProgress();
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] b) throws IOException {
|
|
||||||
return read(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(byte[] b, int off, int len) throws IOException {
|
|
||||||
int sz = super.read(b, off, len);
|
|
||||||
if (sz > 0) {
|
|
||||||
bytesDownloaded += sz;
|
|
||||||
updateProgress();
|
|
||||||
}
|
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,9 @@ import com.topjohnwu.magisk.MagiskManager;
|
|||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.container.TarEntry;
|
import com.topjohnwu.magisk.container.TarEntry;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.magisk.utils.WebService;
|
|
||||||
import com.topjohnwu.magisk.utils.ZipUtils;
|
import com.topjohnwu.magisk.utils.ZipUtils;
|
||||||
|
import com.topjohnwu.net.DownloadProgressListener;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
import com.topjohnwu.superuser.internal.NOPList;
|
import com.topjohnwu.superuser.internal.NOPList;
|
||||||
@ -34,16 +35,12 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FilterInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
||||||
|
|
||||||
private static final int PATCH_MODE = 0;
|
private static final int PATCH_MODE = 0;
|
||||||
@ -86,69 +83,40 @@ public class InstallMagisk extends ParallelTask<Void, Void, Boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ProgressStream extends FilterInputStream {
|
class ProgressLog implements DownloadProgressListener {
|
||||||
|
|
||||||
private int prev = -1;
|
private int prev = -1;
|
||||||
private int progress = 0;
|
private int location;
|
||||||
private int total;
|
|
||||||
|
|
||||||
private ProgressStream(HttpURLConnection conn) throws IOException {
|
@Override
|
||||||
super(conn.getInputStream());
|
public void onProgress(long bytesDownloaded, long totalBytes) {
|
||||||
total = conn.getContentLength();
|
if (prev < 0) {
|
||||||
|
location = console.size();
|
||||||
console.add("... 0%");
|
console.add("... 0%");
|
||||||
}
|
}
|
||||||
|
int curr = (int) (100 * bytesDownloaded / totalBytes);
|
||||||
private void update(int step) {
|
|
||||||
progress += step;
|
|
||||||
int curr = (int) (100 * (double) progress / total);
|
|
||||||
if (prev != curr) {
|
if (prev != curr) {
|
||||||
prev = curr;
|
prev = curr;
|
||||||
console.set(console.size() - 1, "... " + prev + "%");
|
console.set(location, "... " + prev + "%");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException {
|
|
||||||
int b = super.read();
|
|
||||||
if (b > 0)
|
|
||||||
update(1);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(@NonNull byte[] b) throws IOException {
|
|
||||||
return read(b, 0, b.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(@NonNull byte[] b, int off, int len) throws IOException {
|
|
||||||
int step = super.read(b, off, len);
|
|
||||||
if (step > 0)
|
|
||||||
update(step);
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void extractFiles(String arch) throws IOException {
|
private void extractFiles(String arch) throws IOException {
|
||||||
File zip = new File(mm.getFilesDir(), "magisk.zip");
|
File zip = new File(mm.getFilesDir(), "magisk.zip");
|
||||||
BufferedInputStream buf;
|
|
||||||
|
|
||||||
if (!ShellUtils.checkSum("MD5", zip, Data.magiskMD5)) {
|
if (!ShellUtils.checkSum("MD5", zip, Data.magiskMD5)) {
|
||||||
console.add("- Downloading zip");
|
console.add("- Downloading zip");
|
||||||
HttpURLConnection conn = WebService.mustRequest(Data.magiskLink);
|
Networking.get(Data.magiskLink)
|
||||||
buf = new BufferedInputStream(new ProgressStream(conn), conn.getContentLength());
|
.setDownloadProgressListener(new ProgressLog())
|
||||||
buf.mark(conn.getContentLength() + 1);
|
.execForFile(zip);
|
||||||
try (OutputStream out = new FileOutputStream(zip)) {
|
|
||||||
ShellUtils.pump(buf, out);
|
|
||||||
}
|
|
||||||
buf.reset();
|
|
||||||
conn.disconnect();
|
|
||||||
} else {
|
} else {
|
||||||
console.add("- Existing zip found");
|
console.add("- Existing zip found");
|
||||||
buf = new BufferedInputStream(new FileInputStream(zip), (int) zip.length());
|
|
||||||
buf.mark((int) zip.length() + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(zip), (int) zip.length());
|
||||||
|
buf.mark((int) zip.length() + 1);
|
||||||
|
|
||||||
console.add("- Extracting files");
|
console.add("- Extracting files");
|
||||||
try (InputStream in = buf) {
|
try (InputStream in = buf) {
|
||||||
ZipUtils.unzip(in, installDir, arch + "/", true);
|
ZipUtils.unzip(in, installDir, arch + "/", true);
|
||||||
|
51
app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java
Normal file
51
app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package com.topjohnwu.magisk.asyncs;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.Const;
|
||||||
|
import com.topjohnwu.magisk.Data;
|
||||||
|
import com.topjohnwu.magisk.utils.ISafetyNetHelper;
|
||||||
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import dalvik.system.DexClassLoader;
|
||||||
|
|
||||||
|
public class SafetyNet {
|
||||||
|
|
||||||
|
public static final File EXT_APK =
|
||||||
|
new File(Data.MM().getFilesDir().getParent() + "/snet", "snet.apk");
|
||||||
|
|
||||||
|
private static void dyRun(Activity activity) throws Exception {
|
||||||
|
DexClassLoader loader = new DexClassLoader(EXT_APK.getPath(), EXT_APK.getParent(),
|
||||||
|
null, ISafetyNetHelper.class.getClassLoader());
|
||||||
|
Class<?> clazz = loader.loadClass("com.topjohnwu.snet.Snet");
|
||||||
|
ISafetyNetHelper helper = (ISafetyNetHelper) clazz.getMethod("newHelper",
|
||||||
|
Class.class, String.class, Activity.class, Object.class)
|
||||||
|
.invoke(null, ISafetyNetHelper.class, EXT_APK.getPath(), activity,
|
||||||
|
(ISafetyNetHelper.Callback) code ->
|
||||||
|
Topic.publish(false, Topic.SNET_CHECK_DONE, code));
|
||||||
|
if (helper.getVersion() < Const.SNET_EXT_VER)
|
||||||
|
throw new Exception();
|
||||||
|
helper.attest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void check(Activity activity) {
|
||||||
|
try {
|
||||||
|
dyRun(activity);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
Shell.sh("rm -rf " + EXT_APK.getParent()).exec();
|
||||||
|
EXT_APK.getParentFile().mkdir();
|
||||||
|
Networking.get(Const.Url.SNET_URL).getAsFile(f -> {
|
||||||
|
try {
|
||||||
|
dyRun(activity);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Topic.publish(false, Topic.SNET_CHECK_DONE, -1);
|
||||||
|
}
|
||||||
|
}, EXT_APK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,15 +3,15 @@ package com.topjohnwu.magisk.asyncs;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.androidnetworking.common.ANRequest;
|
|
||||||
import com.androidnetworking.common.ANResponse;
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
import com.topjohnwu.magisk.container.Repo;
|
import com.topjohnwu.magisk.container.Repo;
|
||||||
import com.topjohnwu.magisk.utils.Logger;
|
import com.topjohnwu.magisk.utils.Logger;
|
||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
|
import com.topjohnwu.net.Request;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
@ -84,22 +84,23 @@ public class UpdateRepos {
|
|||||||
* first page is updated to determine whether the online repo database is changed
|
* first page is updated to determine whether the online repo database is changed
|
||||||
*/
|
*/
|
||||||
private boolean loadPage(int page) {
|
private boolean loadPage(int page) {
|
||||||
ANRequest.GetRequestBuilder req = AndroidNetworking.get(Const.Url.REPO_URL)
|
Request req = Networking.get(Utils.fmt(Const.Url.REPO_URL, page + 1));
|
||||||
.addQueryParameter("page", String.valueOf(page + 1));
|
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
String etag = mm.prefs.getString(Const.Key.ETAG_KEY, null);
|
String etag = mm.prefs.getString(Const.Key.ETAG_KEY, null);
|
||||||
if (etag != null)
|
if (etag != null)
|
||||||
req.addHeaders(Const.Key.IF_NONE_MATCH, etag);
|
req.addHeaders(Const.Key.IF_NONE_MATCH, etag);
|
||||||
}
|
}
|
||||||
ANResponse<JSONArray> res = req.build().executeForJSONArray();
|
Request.Result<JSONArray> res = req.execForJSONArray();
|
||||||
// Network drop
|
|
||||||
if (res.getOkHttpResponse() == null)
|
|
||||||
return true;
|
|
||||||
// JSON not updated
|
// JSON not updated
|
||||||
if (res.getOkHttpResponse().code() == HttpURLConnection.HTTP_NOT_MODIFIED)
|
if (res.getCode() == HttpURLConnection.HTTP_NOT_MODIFIED)
|
||||||
return false;
|
return false;
|
||||||
|
// Network error
|
||||||
|
if (res.getResult() == null) {
|
||||||
|
cached.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Current page is the last page
|
// Current page is the last page
|
||||||
if (res.getResult() == null || res.getResult().length() == 0)
|
if (res.getResult().length() == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -111,14 +112,14 @@ public class UpdateRepos {
|
|||||||
|
|
||||||
// Update ETAG
|
// Update ETAG
|
||||||
if (page == 0) {
|
if (page == 0) {
|
||||||
String etag = res.getOkHttpResponse().header(Const.Key.ETAG_KEY);
|
String etag = res.getConnection().getHeaderField(Const.Key.ETAG_KEY);
|
||||||
if (etag != null) {
|
if (etag != null) {
|
||||||
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
|
etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1);
|
||||||
mm.prefs.edit().putString(Const.Key.ETAG_KEY, etag).apply();
|
mm.prefs.edit().putString(Const.Key.ETAG_KEY, etag).apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String links = res.getOkHttpResponse().header(Const.Key.LINK_KEY);
|
String links = res.getConnection().getHeaderField(Const.Key.LINK_KEY);
|
||||||
return links == null || !links.contains("next") || loadPage(page + 1);
|
return links == null || !links.contains("next") || loadPage(page + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,16 +5,15 @@ import android.app.Activity;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.androidnetworking.error.ANError;
|
|
||||||
import com.androidnetworking.interfaces.DownloadListener;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.FlashActivity;
|
import com.topjohnwu.magisk.FlashActivity;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
@ -67,25 +66,17 @@ class InstallMethodDialog extends AlertDialog.Builder {
|
|||||||
a.runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
|
a.runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> {
|
||||||
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
String filename = Utils.fmt("Magisk-v%s(%d).zip",
|
||||||
Data.remoteMagiskVersionString, Data.remoteMagiskVersionCode);
|
Data.remoteMagiskVersionString, Data.remoteMagiskVersionCode);
|
||||||
|
File zip = new File(Const.EXTERNAL_PATH, filename);
|
||||||
ProgressNotification progress = new ProgressNotification(filename);
|
ProgressNotification progress = new ProgressNotification(filename);
|
||||||
AndroidNetworking
|
Networking.get(Data.magiskLink)
|
||||||
.download(Data.magiskLink, Const.EXTERNAL_PATH.getPath(), filename)
|
|
||||||
.build()
|
|
||||||
.setDownloadProgressListener(progress)
|
.setDownloadProgressListener(progress)
|
||||||
.startDownload(new DownloadListener() {
|
.setErrorHandler(((conn, e) -> progress.dlFail()))
|
||||||
@Override
|
.getAsFile(f -> {
|
||||||
public void onDownloadComplete() {
|
|
||||||
progress.dlDone();
|
progress.dlDone();
|
||||||
SnackbarMaker.make(a,
|
SnackbarMaker.make(a,
|
||||||
a.getString(R.string.internal_storage, "/Download/" + filename),
|
a.getString(R.string.internal_storage, "/Download/" + filename),
|
||||||
Snackbar.LENGTH_LONG).show();
|
Snackbar.LENGTH_LONG).show();
|
||||||
}
|
}, zip);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ANError anError) {
|
|
||||||
progress.dlFail();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,17 +2,16 @@ package com.topjohnwu.magisk.components;
|
|||||||
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.androidnetworking.interfaces.DownloadProgressListener;
|
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.net.DownloadProgressListener;
|
||||||
|
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
public class ProgressNotification implements DownloadProgressListener {
|
public class ProgressNotification implements DownloadProgressListener {
|
||||||
|
|
||||||
private NotificationManagerCompat mgr;
|
private NotificationManagerCompat mgr;
|
||||||
private NotificationCompat.Builder builder;
|
private NotificationCompat.Builder builder;
|
||||||
private long prevTime;
|
private long prevTime;
|
||||||
|
@ -7,14 +7,12 @@ import android.net.Uri;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.androidnetworking.error.ANError;
|
|
||||||
import com.androidnetworking.interfaces.DownloadListener;
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.FlashActivity;
|
import com.topjohnwu.magisk.FlashActivity;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -44,25 +42,17 @@ public class UninstallDialog extends CustomAlertDialog {
|
|||||||
setPositiveButton(R.string.complete_uninstall, (d, i) -> {
|
setPositiveButton(R.string.complete_uninstall, (d, i) -> {
|
||||||
File zip = new File(activity.getFilesDir(), "uninstaller.zip");
|
File zip = new File(activity.getFilesDir(), "uninstaller.zip");
|
||||||
ProgressNotification progress = new ProgressNotification(zip.getName());
|
ProgressNotification progress = new ProgressNotification(zip.getName());
|
||||||
AndroidNetworking.download(Data.uninstallerLink, zip.getParent(), zip.getName())
|
Networking.get(Data.uninstallerLink)
|
||||||
.build()
|
|
||||||
.setDownloadProgressListener(progress)
|
.setDownloadProgressListener(progress)
|
||||||
.startDownload(new DownloadListener() {
|
.setErrorHandler(((conn, e) -> progress.dlFail()))
|
||||||
@Override
|
.getAsFile(f -> {
|
||||||
public void onDownloadComplete() {
|
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class))
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
.setData(Uri.fromFile(zip))
|
.setData(Uri.fromFile(f))
|
||||||
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);
|
.putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL);
|
||||||
activity.startActivity(intent);
|
activity.startActivity(intent);
|
||||||
}
|
}, zip);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ANError anError) {
|
|
||||||
progress.dlFail();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ import com.topjohnwu.magisk.Const;
|
|||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MainActivity;
|
import com.topjohnwu.magisk.MainActivity;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.asyncs.CheckSafetyNet;
|
|
||||||
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
import com.topjohnwu.magisk.asyncs.CheckUpdates;
|
||||||
|
import com.topjohnwu.magisk.asyncs.SafetyNet;
|
||||||
import com.topjohnwu.magisk.components.BaseActivity;
|
import com.topjohnwu.magisk.components.BaseActivity;
|
||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
import com.topjohnwu.magisk.components.CustomAlertDialog;
|
||||||
@ -91,10 +91,10 @@ public class MagiskFragment extends BaseFragment
|
|||||||
safetyNetProgress.setVisibility(View.VISIBLE);
|
safetyNetProgress.setVisibility(View.VISIBLE);
|
||||||
safetyNetRefreshIcon.setVisibility(View.GONE);
|
safetyNetRefreshIcon.setVisibility(View.GONE);
|
||||||
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
safetyNetStatusText.setText(R.string.checking_safetyNet_status);
|
||||||
new CheckSafetyNet(requireActivity()).exec();
|
SafetyNet.check(requireActivity());
|
||||||
collapse();
|
collapse();
|
||||||
};
|
};
|
||||||
if (!CheckSafetyNet.dexPath.exists()) {
|
if (!SafetyNet.EXT_APK.exists()) {
|
||||||
// Show dialog
|
// Show dialog
|
||||||
new CustomAlertDialog(requireActivity())
|
new CustomAlertDialog(requireActivity())
|
||||||
.setTitle(R.string.proprietary_title)
|
.setTitle(R.string.proprietary_title)
|
||||||
|
@ -5,8 +5,6 @@ import com.topjohnwu.utils.SignBoot;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import androidx.annotation.Keep;
|
|
||||||
|
|
||||||
public class BootSigner {
|
public class BootSigner {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -2,15 +2,14 @@ package com.topjohnwu.magisk.utils;
|
|||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.androidnetworking.error.ANError;
|
|
||||||
import com.androidnetworking.interfaces.DownloadListener;
|
|
||||||
import com.topjohnwu.magisk.BuildConfig;
|
import com.topjohnwu.magisk.BuildConfig;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
import com.topjohnwu.magisk.asyncs.PatchAPK;
|
||||||
import com.topjohnwu.magisk.components.ProgressNotification;
|
import com.topjohnwu.magisk.components.ProgressNotification;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
|
import com.topjohnwu.net.ResponseListener;
|
||||||
import com.topjohnwu.superuser.ShellUtils;
|
import com.topjohnwu.superuser.ShellUtils;
|
||||||
import com.topjohnwu.utils.JarMap;
|
import com.topjohnwu.utils.JarMap;
|
||||||
import com.topjohnwu.utils.SignAPK;
|
import com.topjohnwu.utils.SignAPK;
|
||||||
@ -31,42 +30,35 @@ public class DlInstallManager {
|
|||||||
dlInstall(name, new RestoreManager());
|
dlInstall(name, new RestoreManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dlInstall(String name, ManagerDownloadListener listener) {
|
private static void dlInstall(String name, ManagerDownloadListener listener) {
|
||||||
MagiskManager mm = Data.MM();
|
MagiskManager mm = Data.MM();
|
||||||
File apk = new File(mm.getFilesDir(), "manager.apk");
|
File apk = new File(mm.getFilesDir(), "manager.apk");
|
||||||
ProgressNotification progress = new ProgressNotification(name);
|
ProgressNotification progress = new ProgressNotification(name);
|
||||||
listener.setInstances(apk, progress);
|
listener.setProgressNotification(progress);
|
||||||
AndroidNetworking
|
Networking.get(Data.managerLink)
|
||||||
.download(Data.managerLink, apk.getParent(), apk.getName())
|
|
||||||
.setExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
.setExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||||
.build()
|
|
||||||
.setDownloadProgressListener(progress)
|
.setDownloadProgressListener(progress)
|
||||||
.startDownload(listener);
|
.setErrorHandler((conn, e) -> progress.dlFail())
|
||||||
|
.getAsFile(listener, apk);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract static class ManagerDownloadListener implements DownloadListener {
|
abstract static class ManagerDownloadListener implements ResponseListener<File> {
|
||||||
private File apk;
|
|
||||||
private ProgressNotification progress;
|
private ProgressNotification progress;
|
||||||
|
|
||||||
private void setInstances(File apk, ProgressNotification progress) {
|
private void setProgressNotification(ProgressNotification progress) {
|
||||||
this.apk = apk;
|
|
||||||
this.progress = progress;
|
this.progress = progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void onDownloadComplete(File apk, ProgressNotification progress);
|
public abstract void onDownloadComplete(File apk, ProgressNotification progress);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDownloadComplete() {
|
public void onResponse(File apk) {
|
||||||
onDownloadComplete(apk, progress);
|
onDownloadComplete(apk, progress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ANError anError) {
|
|
||||||
progress.dlFail();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PatchPackageName extends ManagerDownloadListener {
|
static class PatchPackageName extends ManagerDownloadListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
||||||
@ -92,7 +84,7 @@ public class DlInstallManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class RestoreManager extends ManagerDownloadListener {
|
static class RestoreManager extends ManagerDownloadListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
public void onDownloadComplete(File apk, ProgressNotification progress) {
|
||||||
|
@ -16,7 +16,6 @@ import android.os.AsyncTask;
|
|||||||
import android.provider.OpenableColumns;
|
import android.provider.OpenableColumns;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.androidnetworking.AndroidNetworking;
|
|
||||||
import com.topjohnwu.magisk.Const;
|
import com.topjohnwu.magisk.Const;
|
||||||
import com.topjohnwu.magisk.Data;
|
import com.topjohnwu.magisk.Data;
|
||||||
import com.topjohnwu.magisk.MagiskManager;
|
import com.topjohnwu.magisk.MagiskManager;
|
||||||
@ -24,6 +23,7 @@ import com.topjohnwu.magisk.R;
|
|||||||
import com.topjohnwu.magisk.container.Module;
|
import com.topjohnwu.magisk.container.Module;
|
||||||
import com.topjohnwu.magisk.container.ValueSortedMap;
|
import com.topjohnwu.magisk.container.ValueSortedMap;
|
||||||
import com.topjohnwu.magisk.services.UpdateCheckService;
|
import com.topjohnwu.magisk.services.UpdateCheckService;
|
||||||
|
import com.topjohnwu.net.Networking;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
import com.topjohnwu.superuser.io.SuFile;
|
import com.topjohnwu.superuser.io.SuFile;
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ public class Utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String dlString(String url) {
|
public static String dlString(String url) {
|
||||||
String s = (String) AndroidNetworking.get(url).build().executeForString().getResult();
|
String s = Networking.get(url).execForString().getResult();
|
||||||
return s == null ? "" : s;
|
return s == null ? "" : s;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,30 +0,0 @@
|
|||||||
package com.topjohnwu.magisk.utils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
public class WebService {
|
|
||||||
|
|
||||||
public static HttpURLConnection request(String address) throws IOException {
|
|
||||||
URL url = new URL(address);
|
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
||||||
conn.setReadTimeout(15000);
|
|
||||||
conn.setConnectTimeout(15000);
|
|
||||||
conn.connect();
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static HttpURLConnection mustRequest(String address) throws IOException {
|
|
||||||
HttpURLConnection conn;
|
|
||||||
do {
|
|
||||||
conn = WebService.request(address);
|
|
||||||
int total = conn.getContentLength();
|
|
||||||
if (total < 0)
|
|
||||||
conn.disconnect();
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
} while (true);
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,26 +3,17 @@ package com.topjohnwu.magisk;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import com.topjohnwu.magisk.utils.APKInstall;
|
import com.topjohnwu.magisk.utils.APKInstall;
|
||||||
import com.topjohnwu.magisk.utils.Download;
|
import com.topjohnwu.magisk.utils.Download;
|
||||||
import com.topjohnwu.magisk.utils.WebService;
|
import com.topjohnwu.net.Networking;
|
||||||
|
import com.topjohnwu.net.ResponseListener;
|
||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.BufferedOutputStream;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
|
|
||||||
public class MainActivity extends Activity {
|
public class MainActivity extends Activity {
|
||||||
|
|
||||||
@ -33,65 +24,18 @@ public class MainActivity extends Activity {
|
|||||||
|
|
||||||
private void dlAPK() {
|
private void dlAPK() {
|
||||||
Application app = getApplication();
|
Application app = getApplication();
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
Networking.get(apkLink)
|
||||||
try {
|
.getAsFile(apk -> APKInstall.install(app, apk), new File(getFilesDir(), "manager.apk"));
|
||||||
HttpURLConnection conn = WebService.request(apkLink);
|
|
||||||
File apk = new File(getFilesDir(), "manager.apk");
|
|
||||||
try (InputStream in = new BufferedInputStream(conn.getInputStream());
|
|
||||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(apk))) {
|
|
||||||
int len;
|
|
||||||
byte[] buf = new byte[4096];
|
|
||||||
while ((len = in.read(buf)) != -1) {
|
|
||||||
out.write(buf, 0, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn.disconnect();
|
|
||||||
APKInstall.install(app, apk);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dlJSON() throws IOException, JSONException {
|
|
||||||
HttpURLConnection conn = WebService.request(URL);
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
|
||||||
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
|
|
||||||
int len;
|
|
||||||
char buf[] = new char[4096];
|
|
||||||
while ((len = br.read(buf)) != -1) {
|
|
||||||
builder.append(buf, 0, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
conn.disconnect();
|
|
||||||
JSONObject json = new JSONObject(builder.toString());
|
|
||||||
JSONObject manager = json.getJSONObject("app");
|
|
||||||
apkLink = manager.getString("link");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
if (Download.checkNetworkStatus(this)) {
|
if (Download.checkNetworkStatus(this)) {
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
Networking.get(URL)
|
||||||
try {
|
.setErrorHandler(((conn, e) -> finish()))
|
||||||
dlJSON();
|
.getAsJSONObject(new JSONLoader());
|
||||||
runOnUiThread(() -> {
|
|
||||||
new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setTitle(R.string.app_name)
|
|
||||||
.setMessage(R.string.upgrade_msg)
|
|
||||||
.setPositiveButton(R.string.yes, (d, w) -> dlAPK())
|
|
||||||
.setNegativeButton(R.string.no_thanks, (d, w) -> finish())
|
|
||||||
.show();
|
|
||||||
});
|
|
||||||
} catch (JSONException | IOException e) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
|
new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
@ -100,6 +44,25 @@ public class MainActivity extends Activity {
|
|||||||
.setNegativeButton(R.string.ok, (d, w) -> finish())
|
.setNegativeButton(R.string.ok, (d, w) -> finish())
|
||||||
.show();
|
.show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JSONLoader implements ResponseListener<JSONObject> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResponse(JSONObject json) {
|
||||||
|
try {
|
||||||
|
JSONObject manager = json.getJSONObject("app");
|
||||||
|
apkLink = manager.getString("link");
|
||||||
|
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setTitle(R.string.app_name)
|
||||||
|
.setMessage(R.string.upgrade_msg)
|
||||||
|
.setPositiveButton(R.string.yes, (d, w) -> dlAPK())
|
||||||
|
.setNegativeButton(R.string.no_thanks, (d, w) -> finish())
|
||||||
|
.show();
|
||||||
|
} catch (JSONException e) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
net/.gitignore
vendored
Normal file
1
net/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/build
|
29
net/build.gradle
Normal file
29
net/build.gradle
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||||
|
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
}
|
21
net/proguard-rules.pro
vendored
Normal file
21
net/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
2
net/src/main/AndroidManifest.xml
Normal file
2
net/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.topjohnwu.net" />
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
public interface DownloadProgressListener {
|
||||||
|
void onProgress(long bytesDownloaded, long totalBytes);
|
||||||
|
}
|
7
net/src/main/java/com/topjohnwu/net/ErrorHandler.java
Normal file
7
net/src/main/java/com/topjohnwu/net/ErrorHandler.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
|
public interface ErrorHandler {
|
||||||
|
void onError(HttpURLConnection conn, Exception e);
|
||||||
|
}
|
33
net/src/main/java/com/topjohnwu/net/Networking.java
Normal file
33
net/src/main/java/com/topjohnwu/net/Networking.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
public class Networking {
|
||||||
|
|
||||||
|
private static final int READ_TIMEOUT = 15000;
|
||||||
|
private static final int CONNECT_TIMEOUT = 15000;
|
||||||
|
static Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
|
private static Request request(String url, String method) {
|
||||||
|
try {
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
|
||||||
|
conn.setRequestMethod(method);
|
||||||
|
conn.setReadTimeout(READ_TIMEOUT);
|
||||||
|
conn.setConnectTimeout(CONNECT_TIMEOUT);
|
||||||
|
return new Request(conn);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return new StubRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Request get(String url) {
|
||||||
|
return request(url, "GET");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
net/src/main/java/com/topjohnwu/net/ProgressInputStream.java
Normal file
47
net/src/main/java/com/topjohnwu/net/ProgressInputStream.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class ProgressInputStream extends FilterInputStream {
|
||||||
|
|
||||||
|
private long totalBytes;
|
||||||
|
private long bytesDownloaded;
|
||||||
|
|
||||||
|
public ProgressInputStream(InputStream in, long total) {
|
||||||
|
super(in);
|
||||||
|
totalBytes = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateProgress(long bytesDownloaded, long totalBytes) {}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
Networking.mainHandler.post(() -> updateProgress(bytesDownloaded, totalBytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
int b = super.read();
|
||||||
|
if (b >= 0) {
|
||||||
|
bytesDownloaded++;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return read(b, 0, b.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
int sz = super.read(b, off, len);
|
||||||
|
if (sz > 0) {
|
||||||
|
bytesDownloaded += sz;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
}
|
193
net/src/main/java/com/topjohnwu/net/Request.java
Normal file
193
net/src/main/java/com/topjohnwu/net/Request.java
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FilterInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
public class Request {
|
||||||
|
private HttpURLConnection conn;
|
||||||
|
private Executor executor = null;
|
||||||
|
private DownloadProgressListener progress = null;
|
||||||
|
private ErrorHandler err = null;
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
private interface Requestor<T> {
|
||||||
|
T request() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Result<T> {
|
||||||
|
T result;
|
||||||
|
|
||||||
|
public T getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpURLConnection getConnection() {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Request(HttpURLConnection c) {
|
||||||
|
conn = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request addHeaders(String key, String value) {
|
||||||
|
conn.setRequestProperty(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request setDownloadProgressListener(DownloadProgressListener listener) {
|
||||||
|
progress = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request setErrorHandler(ErrorHandler handler) {
|
||||||
|
err = handler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request setExecutor(Executor e) {
|
||||||
|
executor = e;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<InputStream> execForInputStream() {
|
||||||
|
return exec(this::getInputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAsFile(ResponseListener<File> rs, File out) {
|
||||||
|
submit(() -> dlFile(out), rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execForFile(File out) {
|
||||||
|
exec(() -> dlFile(out));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAsString(ResponseListener<String> rs) {
|
||||||
|
submit(this::dlString, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<String> execForString() {
|
||||||
|
return exec(this::dlString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAsJSONObject(ResponseListener<JSONObject> rs) {
|
||||||
|
submit(this::dlJSONObject, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<JSONObject> execForJSONObject() {
|
||||||
|
return exec(this::dlJSONObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAsJSONArray(ResponseListener<JSONArray> rs) {
|
||||||
|
submit(this::dlJSONArray, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<JSONArray> execForJSONArray() {
|
||||||
|
return exec(this::dlJSONArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> Result<T> exec(Requestor<T> req) {
|
||||||
|
Result<T> res = new Result<>();
|
||||||
|
try {
|
||||||
|
res.result = req.request();
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> void submit(Requestor<T> req, ResponseListener<T> rs) {
|
||||||
|
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
|
||||||
|
try {
|
||||||
|
T t = req.request();
|
||||||
|
Runnable cb = () -> rs.onResponse(t);
|
||||||
|
if (executor == null)
|
||||||
|
Networking.mainHandler.post(cb);
|
||||||
|
else
|
||||||
|
executor.execute(cb);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (err != null)
|
||||||
|
err.onError(conn, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private BufferedInputStream getInputStream() throws IOException {
|
||||||
|
conn.connect();
|
||||||
|
code = conn.getResponseCode();
|
||||||
|
InputStream in = conn.getInputStream();
|
||||||
|
if (progress != null) {
|
||||||
|
in = new ProgressInputStream(in, conn.getContentLength()) {
|
||||||
|
@Override
|
||||||
|
protected void updateProgress(long bytesDownloaded, long totalBytes) {
|
||||||
|
progress.onProgress(bytesDownloaded, totalBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
super.close();
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
in = new FilterInputStream(in) {
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
super.close();
|
||||||
|
conn.disconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return new BufferedInputStream(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String dlString() throws IOException {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
try (Reader reader = new InputStreamReader(getInputStream())) {
|
||||||
|
int len;
|
||||||
|
char buf[] = new char[4096];
|
||||||
|
while ((len = reader.read(buf)) != -1) {
|
||||||
|
builder.append(buf, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONObject dlJSONObject() throws IOException, JSONException {
|
||||||
|
return new JSONObject(dlString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONArray dlJSONArray() throws IOException, JSONException {
|
||||||
|
return new JSONArray(dlString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private File dlFile(File f) throws IOException {
|
||||||
|
try (InputStream in = getInputStream();
|
||||||
|
OutputStream out = new BufferedOutputStream(new FileOutputStream(f))) {
|
||||||
|
int len;
|
||||||
|
byte buf[] = new byte[4096];
|
||||||
|
while ((len = in.read(buf)) != -1) {
|
||||||
|
out.write(buf, 0, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
public interface ResponseListener<T> {
|
||||||
|
void onResponse(T response);
|
||||||
|
}
|
49
net/src/main/java/com/topjohnwu/net/StubRequest.java
Normal file
49
net/src/main/java/com/topjohnwu/net/StubRequest.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package com.topjohnwu.net;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
class StubRequest extends Request {
|
||||||
|
|
||||||
|
StubRequest() { super(null); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request addHeaders(String key, String value) { return this; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setDownloadProgressListener(DownloadProgressListener listener) { return this; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setErrorHandler(ErrorHandler handler) { return this; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Request setExecutor(Executor e) { return this; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<InputStream> execForInputStream() { return new Result<>(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAsFile(ResponseListener<File> rs, File out) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAsString(ResponseListener<String> rs) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<String> execForString() { return new Result<>(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAsJSONObject(ResponseListener<JSONObject> rs){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<JSONObject> execForJSONObject() { return new Result<>(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getAsJSONArray(ResponseListener<JSONArray> rs){}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<JSONArray> execForJSONArray() { return new Result<>(); }
|
||||||
|
}
|
@ -1 +1 @@
|
|||||||
include ':app', ':native', ':utils', ':snet'
|
include ':app', ':native', ':utils', ':snet', ':net'
|
||||||
|
Loading…
Reference in New Issue
Block a user