From 59b1e63bdf12d340b30f16903da50ff5df73f214 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 12 Dec 2018 05:51:45 -0500 Subject: [PATCH] Use internal library for networking --- app/build.gradle | 2 +- .../full/java/com/topjohnwu/magisk/Const.java | 2 +- .../magisk/asyncs/CheckSafetyNet.java | 78 ------- .../topjohnwu/magisk/asyncs/CheckUpdates.java | 12 +- .../magisk/asyncs/DownloadModule.java | 56 +---- .../magisk/asyncs/InstallMagisk.java | 68 ++---- .../topjohnwu/magisk/asyncs/SafetyNet.java | 51 +++++ .../topjohnwu/magisk/asyncs/UpdateRepos.java | 27 +-- .../components/InstallMethodDialog.java | 27 +-- .../components/ProgressNotification.java | 3 +- .../magisk/components/UninstallDialog.java | 32 +-- .../magisk/fragments/MagiskFragment.java | 6 +- .../topjohnwu/magisk/utils/BootSigner.java | 2 - .../magisk/utils/DlInstallManager.java | 34 ++- .../com/topjohnwu/magisk/utils/Utils.java | 4 +- .../topjohnwu/magisk/utils/WebService.java | 30 --- .../com/topjohnwu/magisk/MainActivity.java | 89 +++----- net/.gitignore | 1 + net/build.gradle | 29 +++ net/proguard-rules.pro | 21 ++ net/src/main/AndroidManifest.xml | 2 + .../net/DownloadProgressListener.java | 5 + .../java/com/topjohnwu/net/ErrorHandler.java | 7 + .../java/com/topjohnwu/net/Networking.java | 33 +++ .../topjohnwu/net/ProgressInputStream.java | 47 +++++ .../main/java/com/topjohnwu/net/Request.java | 193 ++++++++++++++++++ .../com/topjohnwu/net/ResponseListener.java | 5 + .../java/com/topjohnwu/net/StubRequest.java | 49 +++++ settings.gradle | 2 +- 29 files changed, 552 insertions(+), 365 deletions(-) delete mode 100644 app/src/full/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java create mode 100644 app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java delete mode 100644 app/src/main/java/com/topjohnwu/magisk/utils/WebService.java create mode 100644 net/.gitignore create mode 100644 net/build.gradle create mode 100644 net/proguard-rules.pro create mode 100644 net/src/main/AndroidManifest.xml create mode 100644 net/src/main/java/com/topjohnwu/net/DownloadProgressListener.java create mode 100644 net/src/main/java/com/topjohnwu/net/ErrorHandler.java create mode 100644 net/src/main/java/com/topjohnwu/net/Networking.java create mode 100644 net/src/main/java/com/topjohnwu/net/ProgressInputStream.java create mode 100644 net/src/main/java/com/topjohnwu/net/Request.java create mode 100644 net/src/main/java/com/topjohnwu/net/ResponseListener.java create mode 100644 net/src/main/java/com/topjohnwu/net/StubRequest.java diff --git a/app/build.gradle b/app/build.gradle index bc9f8a8e1..0a9bf4a5f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -71,8 +71,8 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'androidx.core:core:1.0.1' + implementation project(':net') fullImplementation project(':utils') - fullImplementation 'com.amitshekhar.android:android-networking:1.0.2' fullImplementation 'androidx.appcompat:appcompat:1.0.2' fullImplementation "androidx.preference:preference:${rootProject.ext.androidXVersion}" fullImplementation "androidx.recyclerview:recyclerview:${rootProject.ext.androidXVersion}" diff --git a/app/src/full/java/com/topjohnwu/magisk/Const.java b/app/src/full/java/com/topjohnwu/magisk/Const.java index 13e871b6a..cf31dd1c5 100644 --- a/app/src/full/java/com/topjohnwu/magisk/Const.java +++ b/app/src/full/java/com/topjohnwu/magisk/Const.java @@ -67,7 +67,7 @@ public class Const { public static class Url { 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 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 ZIP_URL = "https://github.com/Magisk-Modules-Repo/%s/archive/master.zip"; public static final String PAYPAL_URL = "https://www.paypal.me/topjohnwu"; diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java deleted file mode 100644 index afbe164d4..000000000 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckSafetyNet.java +++ /dev/null @@ -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 { - - 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; - } -} diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java index 7f5ecf26f..5971df0c3 100644 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/CheckUpdates.java @@ -1,13 +1,12 @@ 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.Const; import com.topjohnwu.magisk.Data; import com.topjohnwu.magisk.components.Notifications; import com.topjohnwu.magisk.utils.Topic; +import com.topjohnwu.net.Networking; +import com.topjohnwu.net.ResponseListener; import org.json.JSONException; import org.json.JSONObject; @@ -57,14 +56,14 @@ public class CheckUpdates { default: return; } - AndroidNetworking.get(url).build().getAsJSONObject(new UpdateListener(cb)); + Networking.get(url).getAsJSONObject(new UpdateListener(cb)); } public static void check() { check(null); } - private static class UpdateListener implements JSONObjectRequestListener { + private static class UpdateListener implements ResponseListener { private Runnable cb; @@ -100,8 +99,5 @@ public class CheckUpdates { } Topic.publish(Topic.UPDATE_CHECK_DONE); } - - @Override - public void onError(ANError anError) {} } } diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java index 6f914b0b2..221d282f9 100644 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/DownloadModule.java @@ -12,18 +12,15 @@ import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.components.BaseActivity; import com.topjohnwu.magisk.components.ProgressNotification; import com.topjohnwu.magisk.container.Repo; -import com.topjohnwu.magisk.utils.WebService; +import com.topjohnwu.net.Networking; import com.topjohnwu.superuser.ShellUtils; -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.OutputStream; -import java.net.HttpURLConnection; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -40,12 +37,10 @@ public class DownloadModule { ProgressNotification progress = new ProgressNotification(output.getName()); try { MagiskManager mm = Data.MM(); - HttpURLConnection conn = WebService.mustRequest(repo.getZipUrl()); - ProgressInputStream pis = new ProgressInputStream(conn.getInputStream(), - conn.getContentLength(), progress); - removeTopFolder(new BufferedInputStream(pis), - new BufferedOutputStream(new FileOutputStream(output))); - conn.disconnect(); + InputStream in = Networking.get(repo.getZipUrl()) + .setDownloadProgressListener(progress) + .execForInputStream().getResult(); + removeTopFolder(in, new BufferedOutputStream(new FileOutputStream(output))); if (install) { progress.dismiss(); 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; - } - } } diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java index 5939cd741..103ea6eb4 100644 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/InstallMagisk.java @@ -15,8 +15,9 @@ import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.container.TarEntry; import com.topjohnwu.magisk.utils.Utils; -import com.topjohnwu.magisk.utils.WebService; 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.ShellUtils; import com.topjohnwu.superuser.internal.NOPList; @@ -34,16 +35,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.HttpURLConnection; import java.util.Arrays; import java.util.List; -import androidx.annotation.NonNull; - public class InstallMagisk extends ParallelTask { private static final int PATCH_MODE = 0; @@ -86,69 +83,40 @@ public class InstallMagisk extends ParallelTask { } } - private class ProgressStream extends FilterInputStream { + class ProgressLog implements DownloadProgressListener { private int prev = -1; - private int progress = 0; - private int total; + private int location; - private ProgressStream(HttpURLConnection conn) throws IOException { - super(conn.getInputStream()); - total = conn.getContentLength(); - console.add("... 0%"); - } - - private void update(int step) { - progress += step; - int curr = (int) (100 * (double) progress / total); + @Override + public void onProgress(long bytesDownloaded, long totalBytes) { + if (prev < 0) { + location = console.size(); + console.add("... 0%"); + } + int curr = (int) (100 * bytesDownloaded / totalBytes); if (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 { File zip = new File(mm.getFilesDir(), "magisk.zip"); - BufferedInputStream buf; if (!ShellUtils.checkSum("MD5", zip, Data.magiskMD5)) { console.add("- Downloading zip"); - HttpURLConnection conn = WebService.mustRequest(Data.magiskLink); - buf = new BufferedInputStream(new ProgressStream(conn), conn.getContentLength()); - buf.mark(conn.getContentLength() + 1); - try (OutputStream out = new FileOutputStream(zip)) { - ShellUtils.pump(buf, out); - } - buf.reset(); - conn.disconnect(); + Networking.get(Data.magiskLink) + .setDownloadProgressListener(new ProgressLog()) + .execForFile(zip); } else { 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"); try (InputStream in = buf) { ZipUtils.unzip(in, installDir, arch + "/", true); diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java new file mode 100644 index 000000000..c1477e1b2 --- /dev/null +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/SafetyNet.java @@ -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); + } + } +} diff --git a/app/src/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java b/app/src/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java index 1f2bcce99..be860219b 100644 --- a/app/src/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java +++ b/app/src/full/java/com/topjohnwu/magisk/asyncs/UpdateRepos.java @@ -3,15 +3,15 @@ package com.topjohnwu.magisk.asyncs; import android.database.Cursor; 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.Data; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.container.Repo; import com.topjohnwu.magisk.utils.Logger; 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.JSONException; @@ -84,22 +84,23 @@ public class UpdateRepos { * first page is updated to determine whether the online repo database is changed */ private boolean loadPage(int page) { - ANRequest.GetRequestBuilder req = AndroidNetworking.get(Const.Url.REPO_URL) - .addQueryParameter("page", String.valueOf(page + 1)); + Request req = Networking.get(Utils.fmt(Const.Url.REPO_URL, page + 1)); if (page == 0) { String etag = mm.prefs.getString(Const.Key.ETAG_KEY, null); if (etag != null) req.addHeaders(Const.Key.IF_NONE_MATCH, etag); } - ANResponse res = req.build().executeForJSONArray(); - // Network drop - if (res.getOkHttpResponse() == null) - return true; + Request.Result res = req.execForJSONArray(); // JSON not updated - if (res.getOkHttpResponse().code() == HttpURLConnection.HTTP_NOT_MODIFIED) + if (res.getCode() == HttpURLConnection.HTTP_NOT_MODIFIED) return false; + // Network error + if (res.getResult() == null) { + cached.clear(); + return true; + } // Current page is the last page - if (res.getResult() == null || res.getResult().length() == 0) + if (res.getResult().length() == 0) return true; try { @@ -111,14 +112,14 @@ public class UpdateRepos { // Update ETAG if (page == 0) { - String etag = res.getOkHttpResponse().header(Const.Key.ETAG_KEY); + String etag = res.getConnection().getHeaderField(Const.Key.ETAG_KEY); if (etag != null) { etag = etag.substring(etag.indexOf('\"'), etag.lastIndexOf('\"') + 1); 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); } diff --git a/app/src/full/java/com/topjohnwu/magisk/components/InstallMethodDialog.java b/app/src/full/java/com/topjohnwu/magisk/components/InstallMethodDialog.java index f6b6e36d4..187e21ff1 100644 --- a/app/src/full/java/com/topjohnwu/magisk/components/InstallMethodDialog.java +++ b/app/src/full/java/com/topjohnwu/magisk/components/InstallMethodDialog.java @@ -5,16 +5,15 @@ import android.app.Activity; import android.content.Intent; 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.topjohnwu.magisk.Const; import com.topjohnwu.magisk.Data; import com.topjohnwu.magisk.FlashActivity; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.net.Networking; +import java.io.File; import java.util.List; import androidx.appcompat.app.AlertDialog; @@ -67,25 +66,17 @@ class InstallMethodDialog extends AlertDialog.Builder { a.runWithPermission(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, () -> { String filename = Utils.fmt("Magisk-v%s(%d).zip", Data.remoteMagiskVersionString, Data.remoteMagiskVersionCode); + File zip = new File(Const.EXTERNAL_PATH, filename); ProgressNotification progress = new ProgressNotification(filename); - AndroidNetworking - .download(Data.magiskLink, Const.EXTERNAL_PATH.getPath(), filename) - .build() + Networking.get(Data.magiskLink) .setDownloadProgressListener(progress) - .startDownload(new DownloadListener() { - @Override - public void onDownloadComplete() { - progress.dlDone(); - SnackbarMaker.make(a, + .setErrorHandler(((conn, e) -> progress.dlFail())) + .getAsFile(f -> { + progress.dlDone(); + SnackbarMaker.make(a, a.getString(R.string.internal_storage, "/Download/" + filename), Snackbar.LENGTH_LONG).show(); - } - - @Override - public void onError(ANError anError) { - progress.dlFail(); - } - }); + }, zip); }); } diff --git a/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java b/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java index 92dca7cd2..5b8e5ded9 100644 --- a/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java +++ b/app/src/full/java/com/topjohnwu/magisk/components/ProgressNotification.java @@ -2,17 +2,16 @@ package com.topjohnwu.magisk.components; import android.widget.Toast; -import com.androidnetworking.interfaces.DownloadProgressListener; import com.topjohnwu.magisk.Data; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.net.DownloadProgressListener; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; public class ProgressNotification implements DownloadProgressListener { - private NotificationManagerCompat mgr; private NotificationCompat.Builder builder; private long prevTime; diff --git a/app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java b/app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java index 97092061f..c685a22fe 100644 --- a/app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java +++ b/app/src/full/java/com/topjohnwu/magisk/components/UninstallDialog.java @@ -7,14 +7,12 @@ import android.net.Uri; import android.text.TextUtils; 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.Data; import com.topjohnwu.magisk.FlashActivity; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.net.Networking; import com.topjohnwu.superuser.Shell; import java.io.File; @@ -44,25 +42,17 @@ public class UninstallDialog extends CustomAlertDialog { setPositiveButton(R.string.complete_uninstall, (d, i) -> { File zip = new File(activity.getFilesDir(), "uninstaller.zip"); ProgressNotification progress = new ProgressNotification(zip.getName()); - AndroidNetworking.download(Data.uninstallerLink, zip.getParent(), zip.getName()) - .build() + Networking.get(Data.uninstallerLink) .setDownloadProgressListener(progress) - .startDownload(new DownloadListener() { - @Override - public void onDownloadComplete() { - progress.dismiss(); - Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class)) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - .setData(Uri.fromFile(zip)) - .putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL); - activity.startActivity(intent); - } - - @Override - public void onError(ANError anError) { - progress.dlFail(); - } - }); + .setErrorHandler(((conn, e) -> progress.dlFail())) + .getAsFile(f -> { + progress.dismiss(); + Intent intent = new Intent(activity, Data.classMap.get(FlashActivity.class)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + .setData(Uri.fromFile(f)) + .putExtra(Const.Key.FLASH_ACTION, Const.Value.UNINSTALL); + activity.startActivity(intent); + }, zip); }); } } diff --git a/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java b/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java index 995858d2f..4da8ab0ce 100644 --- a/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java +++ b/app/src/full/java/com/topjohnwu/magisk/fragments/MagiskFragment.java @@ -20,8 +20,8 @@ import com.topjohnwu.magisk.Const; import com.topjohnwu.magisk.Data; import com.topjohnwu.magisk.MainActivity; import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.asyncs.CheckSafetyNet; import com.topjohnwu.magisk.asyncs.CheckUpdates; +import com.topjohnwu.magisk.asyncs.SafetyNet; import com.topjohnwu.magisk.components.BaseActivity; import com.topjohnwu.magisk.components.BaseFragment; import com.topjohnwu.magisk.components.CustomAlertDialog; @@ -91,10 +91,10 @@ public class MagiskFragment extends BaseFragment safetyNetProgress.setVisibility(View.VISIBLE); safetyNetRefreshIcon.setVisibility(View.GONE); safetyNetStatusText.setText(R.string.checking_safetyNet_status); - new CheckSafetyNet(requireActivity()).exec(); + SafetyNet.check(requireActivity()); collapse(); }; - if (!CheckSafetyNet.dexPath.exists()) { + if (!SafetyNet.EXT_APK.exists()) { // Show dialog new CustomAlertDialog(requireActivity()) .setTitle(R.string.proprietary_title) diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/BootSigner.java b/app/src/full/java/com/topjohnwu/magisk/utils/BootSigner.java index bb150c661..63567599c 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/BootSigner.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/BootSigner.java @@ -5,8 +5,6 @@ import com.topjohnwu.utils.SignBoot; import java.io.FileInputStream; import java.io.InputStream; -import androidx.annotation.Keep; - public class BootSigner { public static void main(String[] args) throws Exception { diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/DlInstallManager.java b/app/src/full/java/com/topjohnwu/magisk/utils/DlInstallManager.java index 32fe43e48..30c0ee58f 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/DlInstallManager.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/DlInstallManager.java @@ -2,15 +2,14 @@ package com.topjohnwu.magisk.utils; 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.Data; import com.topjohnwu.magisk.MagiskManager; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.asyncs.PatchAPK; import com.topjohnwu.magisk.components.ProgressNotification; +import com.topjohnwu.net.Networking; +import com.topjohnwu.net.ResponseListener; import com.topjohnwu.superuser.ShellUtils; import com.topjohnwu.utils.JarMap; import com.topjohnwu.utils.SignAPK; @@ -31,42 +30,35 @@ public class DlInstallManager { dlInstall(name, new RestoreManager()); } - public static void dlInstall(String name, ManagerDownloadListener listener) { + private static void dlInstall(String name, ManagerDownloadListener listener) { MagiskManager mm = Data.MM(); File apk = new File(mm.getFilesDir(), "manager.apk"); ProgressNotification progress = new ProgressNotification(name); - listener.setInstances(apk, progress); - AndroidNetworking - .download(Data.managerLink, apk.getParent(), apk.getName()) + listener.setProgressNotification(progress); + Networking.get(Data.managerLink) .setExecutor(AsyncTask.THREAD_POOL_EXECUTOR) - .build() .setDownloadProgressListener(progress) - .startDownload(listener); + .setErrorHandler((conn, e) -> progress.dlFail()) + .getAsFile(listener, apk); } - public abstract static class ManagerDownloadListener implements DownloadListener { - private File apk; + abstract static class ManagerDownloadListener implements ResponseListener { + private ProgressNotification progress; - private void setInstances(File apk, ProgressNotification progress) { - this.apk = apk; + private void setProgressNotification(ProgressNotification progress) { this.progress = progress; } public abstract void onDownloadComplete(File apk, ProgressNotification progress); @Override - public final void onDownloadComplete() { + public void onResponse(File apk) { onDownloadComplete(apk, progress); } - - @Override - public void onError(ANError anError) { - progress.dlFail(); - } } - private static class PatchPackageName extends ManagerDownloadListener { + static class PatchPackageName extends ManagerDownloadListener { @Override 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 public void onDownloadComplete(File apk, ProgressNotification progress) { diff --git a/app/src/full/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/full/java/com/topjohnwu/magisk/utils/Utils.java index 05a735e82..6dbb72321 100644 --- a/app/src/full/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/full/java/com/topjohnwu/magisk/utils/Utils.java @@ -16,7 +16,6 @@ import android.os.AsyncTask; import android.provider.OpenableColumns; import android.widget.Toast; -import com.androidnetworking.AndroidNetworking; import com.topjohnwu.magisk.Const; import com.topjohnwu.magisk.Data; 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.ValueSortedMap; import com.topjohnwu.magisk.services.UpdateCheckService; +import com.topjohnwu.net.Networking; import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.io.SuFile; @@ -152,7 +152,7 @@ public class Utils { } 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; } } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/WebService.java b/app/src/main/java/com/topjohnwu/magisk/utils/WebService.java deleted file mode 100644 index ad5ba03f1..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/utils/WebService.java +++ /dev/null @@ -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; - } -} diff --git a/app/src/stub/java/com/topjohnwu/magisk/MainActivity.java b/app/src/stub/java/com/topjohnwu/magisk/MainActivity.java index 6ad7bf6f9..64b081d06 100644 --- a/app/src/stub/java/com/topjohnwu/magisk/MainActivity.java +++ b/app/src/stub/java/com/topjohnwu/magisk/MainActivity.java @@ -3,26 +3,17 @@ package com.topjohnwu.magisk; import android.app.Activity; import android.app.AlertDialog; import android.app.Application; -import android.os.AsyncTask; import android.os.Bundle; import com.topjohnwu.magisk.utils.APKInstall; 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.JSONObject; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; 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 { @@ -33,65 +24,18 @@ public class MainActivity extends Activity { private void dlAPK() { Application app = getApplication(); - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { - try { - 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(); - } - }); + Networking.get(apkLink) + .getAsFile(apk -> APKInstall.install(app, apk), new File(getFilesDir(), "manager.apk")); 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 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Download.checkNetworkStatus(this)) { - AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { - try { - dlJSON(); - 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(); - } - }); + Networking.get(URL) + .setErrorHandler(((conn, e) -> finish())) + .getAsJSONObject(new JSONLoader()); } else { new AlertDialog.Builder(this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT) .setCancelable(false) @@ -100,6 +44,25 @@ public class MainActivity extends Activity { .setNegativeButton(R.string.ok, (d, w) -> finish()) .show(); } + } + class JSONLoader implements ResponseListener { + + @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(); + } + } } } diff --git a/net/.gitignore b/net/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/net/.gitignore @@ -0,0 +1 @@ +/build diff --git a/net/build.gradle b/net/build.gradle new file mode 100644 index 000000000..8d04b32af --- /dev/null +++ b/net/build.gradle @@ -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']) +} diff --git a/net/proguard-rules.pro b/net/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/net/proguard-rules.pro @@ -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 diff --git a/net/src/main/AndroidManifest.xml b/net/src/main/AndroidManifest.xml new file mode 100644 index 000000000..b8128f247 --- /dev/null +++ b/net/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/net/src/main/java/com/topjohnwu/net/DownloadProgressListener.java b/net/src/main/java/com/topjohnwu/net/DownloadProgressListener.java new file mode 100644 index 000000000..9395699d4 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/DownloadProgressListener.java @@ -0,0 +1,5 @@ +package com.topjohnwu.net; + +public interface DownloadProgressListener { + void onProgress(long bytesDownloaded, long totalBytes); +} diff --git a/net/src/main/java/com/topjohnwu/net/ErrorHandler.java b/net/src/main/java/com/topjohnwu/net/ErrorHandler.java new file mode 100644 index 000000000..12f7548c1 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/ErrorHandler.java @@ -0,0 +1,7 @@ +package com.topjohnwu.net; + +import java.net.HttpURLConnection; + +public interface ErrorHandler { + void onError(HttpURLConnection conn, Exception e); +} diff --git a/net/src/main/java/com/topjohnwu/net/Networking.java b/net/src/main/java/com/topjohnwu/net/Networking.java new file mode 100644 index 000000000..fb4a7630e --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/Networking.java @@ -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"); + } + +} diff --git a/net/src/main/java/com/topjohnwu/net/ProgressInputStream.java b/net/src/main/java/com/topjohnwu/net/ProgressInputStream.java new file mode 100644 index 000000000..18a075926 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/ProgressInputStream.java @@ -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; + } +} diff --git a/net/src/main/java/com/topjohnwu/net/Request.java b/net/src/main/java/com/topjohnwu/net/Request.java new file mode 100644 index 000000000..3f40ad875 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/Request.java @@ -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 request() throws Exception; + } + + public class Result { + 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 execForInputStream() { + return exec(this::getInputStream); + } + + public void getAsFile(ResponseListener rs, File out) { + submit(() -> dlFile(out), rs); + } + + public void execForFile(File out) { + exec(() -> dlFile(out)); + } + + public void getAsString(ResponseListener rs) { + submit(this::dlString, rs); + } + + public Result execForString() { + return exec(this::dlString); + } + + public void getAsJSONObject(ResponseListener rs) { + submit(this::dlJSONObject, rs); + } + + public Result execForJSONObject() { + return exec(this::dlJSONObject); + } + + public void getAsJSONArray(ResponseListener rs) { + submit(this::dlJSONArray, rs); + } + + public Result execForJSONArray() { + return exec(this::dlJSONArray); + } + + private Result exec(Requestor req) { + Result res = new Result<>(); + try { + res.result = req.request(); + } catch (Exception ignored) {} + return res; + } + + private void submit(Requestor req, ResponseListener 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; + } +} diff --git a/net/src/main/java/com/topjohnwu/net/ResponseListener.java b/net/src/main/java/com/topjohnwu/net/ResponseListener.java new file mode 100644 index 000000000..c8f0be7b6 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/ResponseListener.java @@ -0,0 +1,5 @@ +package com.topjohnwu.net; + +public interface ResponseListener { + void onResponse(T response); +} diff --git a/net/src/main/java/com/topjohnwu/net/StubRequest.java b/net/src/main/java/com/topjohnwu/net/StubRequest.java new file mode 100644 index 000000000..d9d9d9872 --- /dev/null +++ b/net/src/main/java/com/topjohnwu/net/StubRequest.java @@ -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 execForInputStream() { return new Result<>(); } + + @Override + public void getAsFile(ResponseListener rs, File out) {} + + @Override + public void getAsString(ResponseListener rs) {} + + @Override + public Result execForString() { return new Result<>(); } + + @Override + public void getAsJSONObject(ResponseListener rs){} + + @Override + public Result execForJSONObject() { return new Result<>(); } + + @Override + public void getAsJSONArray(ResponseListener rs){} + + @Override + public Result execForJSONArray() { return new Result<>(); } +} diff --git a/settings.gradle b/settings.gradle index 115c565b8..3c9ca144d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':app', ':native', ':utils', ':snet' +include ':app', ':native', ':utils', ':snet', ':net'