diff --git a/app/src/main/java/com/fox2code/mmm/MainActivity.java b/app/src/main/java/com/fox2code/mmm/MainActivity.java index 611ec4a..17bf080 100644 --- a/app/src/main/java/com/fox2code/mmm/MainActivity.java +++ b/app/src/main/java/com/fox2code/mmm/MainActivity.java @@ -3,7 +3,6 @@ package com.fox2code.mmm; import androidx.annotation.NonNull; import androidx.appcompat.widget.SearchView; import androidx.cardview.widget.CardView; -import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -34,7 +33,6 @@ import com.fox2code.mmm.utils.IntentHelper; import com.google.android.material.progressindicator.LinearProgressIndicator; import eightbitlab.com.blurview.BlurView; -import eightbitlab.com.blurview.BlurViewFacade; import eightbitlab.com.blurview.RenderScriptBlur; public class MainActivity extends CompatActivity implements SwipeRefreshLayout.OnRefreshListener, @@ -161,6 +159,8 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O updateScreenInsets(); // Fix an edge case if (MainApplication.isShowcaseMode()) moduleViewListBuilder.addNotification(NotificationType.SHOWCASE_MODE); + if (!Http.hasWebView()) // Check Http for WebView availability + moduleViewListBuilder.addNotification(NotificationType.NO_WEB_VIEW); moduleViewListBuilder.applyTo(moduleList, moduleViewAdapter); runOnUiThread(() -> { progressIndicator.setIndeterminate(false); diff --git a/app/src/main/java/com/fox2code/mmm/MainApplication.java b/app/src/main/java/com/fox2code/mmm/MainApplication.java index 3a502df..d2c2443 100644 --- a/app/src/main/java/com/fox2code/mmm/MainApplication.java +++ b/app/src/main/java/com/fox2code/mmm/MainApplication.java @@ -1,7 +1,6 @@ package com.fox2code.mmm; import android.annotation.SuppressLint; -import android.app.Application; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; diff --git a/app/src/main/java/com/fox2code/mmm/ModuleHolder.java b/app/src/main/java/com/fox2code/mmm/ModuleHolder.java index 5c4a1b8..416115b 100644 --- a/app/src/main/java/com/fox2code/mmm/ModuleHolder.java +++ b/app/src/main/java/com/fox2code/mmm/ModuleHolder.java @@ -11,6 +11,7 @@ import androidx.annotation.StringRes; import com.fox2code.mmm.manager.LocalModuleInfo; import com.fox2code.mmm.manager.ModuleInfo; import com.fox2code.mmm.repo.RepoModule; +import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.IntentHelper; import com.fox2code.mmm.utils.PropUtils; @@ -167,7 +168,7 @@ public final class ModuleHolder implements Comparable { } String config = this.getMainModuleConfig(); if (config != null) { - if (config.startsWith("https://www.androidacy.com/")) { + if (config.startsWith("https://www.androidacy.com/") && Http.hasWebView()) { buttonTypeList.add(ActionButtonType.CONFIG); } else { String pkg = IntentHelper.getPackageOfConfig(config); diff --git a/app/src/main/java/com/fox2code/mmm/NotificationType.java b/app/src/main/java/com/fox2code/mmm/NotificationType.java index 06b4330..ab1f86f 100644 --- a/app/src/main/java/com/fox2code/mmm/NotificationType.java +++ b/app/src/main/java/com/fox2code/mmm/NotificationType.java @@ -12,6 +12,7 @@ import com.fox2code.mmm.compat.CompatActivity; import com.fox2code.mmm.installer.InstallerInitializer; import com.fox2code.mmm.repo.RepoManager; import com.fox2code.mmm.utils.Files; +import com.fox2code.mmm.utils.Http; import com.fox2code.mmm.utils.IntentHelper; import java.io.File; @@ -56,6 +57,12 @@ public enum NotificationType implements NotificationTypeCst { RepoManager.getINSTANCE().hasConnectivity(); } }, + NO_WEB_VIEW(R.string.no_web_view, R.drawable.ic_baseline_android_24) { + @Override + public boolean shouldRemove() { + return Http.hasWebView(); + } + }, UPDATE_AVAILABLE(R.string.app_update_available, R.drawable.ic_baseline_system_update_24, R.attr.colorPrimary, R.attr.colorOnPrimary, v -> { IntentHelper.openUrl(v.getContext(), diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyActivity.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyActivity.java index 391e6c1..ca09b1b 100644 --- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyActivity.java +++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyActivity.java @@ -66,6 +66,11 @@ public class AndroidacyActivity extends CompatActivity { this.forceBackPressed(); return; } + if (!Http.hasWebView()) { + Log.w(TAG, "No WebView found to load url: " + url); + this.forceBackPressed(); + return; + } if (!url.endsWith(REFERRER) && (url.startsWith("https://www.androidacy.com/") || url.startsWith("https://api.androidacy.com/magisk/"))) { if (url.lastIndexOf('/') < url.lastIndexOf('?')) { diff --git a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java index 2609f4b..e722f02 100644 --- a/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java +++ b/app/src/main/java/com/fox2code/mmm/androidacy/AndroidacyRepoData.java @@ -18,11 +18,24 @@ import org.json.JSONObject; import java.io.File; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import okhttp3.Cookie; +import okhttp3.HttpUrl; + +@SuppressWarnings("KotlinInternalInJava") public class AndroidacyRepoData extends RepoData { private static final String TAG = "AndroidacyRepoData"; + private static final HttpUrl OK_HTTP_URL; + static { + HttpUrl.Builder OK_HTTP_URL_BUILDER = + new HttpUrl.Builder().scheme("https"); + // Using HttpUrl.Builder.host(String) crash the app + OK_HTTP_URL_BUILDER.setHost$okhttp(".androidacy.com"); + OK_HTTP_URL = OK_HTTP_URL_BUILDER.build(); + } private long androidacyBlockade = 0; public AndroidacyRepoData(String url, File cacheRoot, @@ -36,13 +49,29 @@ public class AndroidacyRepoData extends RepoData { } } + private static String getCookies() { + if (Http.hasWebView()) { + return CookieManager.getInstance().getCookie("https://.androidacy.com/"); + } else { + Iterator cookies = Http.getCookieJar() + .loadForRequest(OK_HTTP_URL).iterator(); + if (!cookies.hasNext()) return ""; + StringBuilder stringBuilder = new StringBuilder(); + while (true) { + stringBuilder.append(cookies.next().toString()); + if (!cookies.hasNext()) return stringBuilder.toString(); + stringBuilder.append(","); + } + } + } + @Override protected boolean prepare() { // Implementation details discussed on telegram long time = System.currentTimeMillis(); if (this.androidacyBlockade > time) return false; this.androidacyBlockade = time + 5_000L; - String cookies = CookieManager.getInstance().getCookie("https://.androidacy.com/"); + String cookies = AndroidacyRepoData.getCookies(); int start = cookies == null ? -1 : cookies.indexOf("USER="); String token = null; if (start != -1) { @@ -61,9 +90,14 @@ public class AndroidacyRepoData extends RepoData { return false; } Log.w(TAG, "Invalid token, resetting..."); - CookieManager.getInstance().setCookie("https://.androidacy.com/", - "USER=; expires=Thu, 01 Jan 1970 00:00:00 GMT;" + - " path=/; secure; domain=.androidacy.com"); + if (Http.hasWebView()) { + CookieManager.getInstance().setCookie("https://.androidacy.com/", + "USER=; expires=Thu, 01 Jan 1970 00:00:00 GMT;" + + " path=/; secure; domain=.androidacy.com"); + } else { + Http.getCookieJar().saveFromResponse( + OK_HTTP_URL, Collections.emptyList()); + } token = null; } } @@ -73,9 +107,16 @@ public class AndroidacyRepoData extends RepoData { token = new String(Http.doHttpPost( "https://api.androidacy.com/auth/register", "",true), StandardCharsets.UTF_8); - CookieManager.getInstance().setCookie("https://.androidacy.com/", - "USER="+ token + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;" + - " path=/; secure; domain=.androidacy.com"); + if (Http.hasWebView()) { + CookieManager.getInstance().setCookie("https://.androidacy.com/", + "USER=" + token + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;" + + " path=/; secure; domain=.androidacy.com"); + } else { + Http.getCookieJar().saveFromResponse(OK_HTTP_URL, + Collections.singletonList(Cookie.parse(OK_HTTP_URL, + "USER=" + token + "; expires=Fri, 31 Dec 9999 23:59:59 GMT;" + + " path=/; secure; domain=.androidacy.com"))); + } } catch (Exception e) { if ("Received error code: 419".equals(e.getMessage()) || "Received error code: 429".equals(e.getMessage()) || diff --git a/app/src/main/java/com/fox2code/mmm/compat/CompatThemeWrapper.java b/app/src/main/java/com/fox2code/mmm/compat/CompatThemeWrapper.java index c623c63..d192ce9 100644 --- a/app/src/main/java/com/fox2code/mmm/compat/CompatThemeWrapper.java +++ b/app/src/main/java/com/fox2code/mmm/compat/CompatThemeWrapper.java @@ -2,7 +2,6 @@ package com.fox2code.mmm.compat; import android.content.Context; import android.content.res.Resources; -import android.graphics.Color; import android.os.Build; import android.util.TypedValue; @@ -12,7 +11,6 @@ import androidx.annotation.ColorRes; import androidx.annotation.StyleRes; import androidx.appcompat.view.ContextThemeWrapper; import androidx.core.content.ContextCompat; -import androidx.core.content.res.ComplexColorCompat; import androidx.core.graphics.ColorUtils; import com.fox2code.mmm.R; diff --git a/app/src/main/java/com/fox2code/mmm/installer/InstallerInitializer.java b/app/src/main/java/com/fox2code/mmm/installer/InstallerInitializer.java index 7de78d7..49fc6da 100644 --- a/app/src/main/java/com/fox2code/mmm/installer/InstallerInitializer.java +++ b/app/src/main/java/com/fox2code/mmm/installer/InstallerInitializer.java @@ -10,7 +10,6 @@ import com.fox2code.mmm.MainApplication; import com.fox2code.mmm.utils.Files; import com.topjohnwu.superuser.NoShellException; import com.topjohnwu.superuser.Shell; -import com.topjohnwu.superuser.io.SuFile; import java.io.File; import java.util.ArrayList; diff --git a/app/src/main/java/com/fox2code/mmm/utils/Http.java b/app/src/main/java/com/fox2code/mmm/utils/Http.java index 4ca5984..9518aad 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/Http.java +++ b/app/src/main/java/com/fox2code/mmm/utils/Http.java @@ -56,7 +56,9 @@ public class Http { private static final OkHttpClient httpClientWithCache; private static final OkHttpClient httpClientWithCacheDoH; private static final FallBackDNS fallbackDNS; + private static final CookieJar cookieJar; private static final String androidacyUA; + private static final boolean hasWebView; private static boolean doh; static { @@ -102,7 +104,7 @@ public class Http { return Dns.SYSTEM.lookup(s); }; httpclientBuilder.dns(dns); - httpclientBuilder.cookieJar(new CDNCookieJar(false)); + httpclientBuilder.cookieJar(new CDNCookieJar()); dns = new DnsOverHttps.Builder().client(httpclientBuilder.build()).url( Objects.requireNonNull(HttpUrl.parse("https://cloudflare-dns.com/dns-query"))) .bootstrapDnsHosts(cloudflareBootstrap).resolvePrivateAddresses(true).build(); @@ -139,7 +141,16 @@ public class Http { "camo.githubusercontent.com", "user-images.githubusercontent.com", "cdn.jsdelivr.net", "img.shields.io", "magisk-modules-repo.github.io", "www.androidacy.com", "api.androidacy.com"); - httpclientBuilder.cookieJar(new CDNCookieJar(true)); + CookieManager cookieManager; + try { + cookieManager = CookieManager.getInstance(); + cookieManager.flush(); // Make sure the instance work + } catch (Throwable t) { + cookieManager = null; + Log.e(TAG, "No WebView support!", t); + } + hasWebView = cookieManager != null; + httpclientBuilder.cookieJar(cookieJar = new CDNCookieJar(cookieManager)); httpclientBuilder.dns(Dns.SYSTEM); httpClient = httpclientBuilder.build(); httpclientBuilder.dns(fallbackDNS); @@ -268,9 +279,20 @@ public class Http { private static class CDNCookieJar implements CookieJar { private final HashMap cookieMap = new HashMap<>(); private final boolean androidacySupport; + private final CookieManager cookieManager; + private List androidacyCookies; - private CDNCookieJar(boolean androidacySupport) { - this.androidacySupport = androidacySupport; + private CDNCookieJar() { + this.androidacySupport = false; + this.cookieManager = null; + } + + private CDNCookieJar(CookieManager cookieManager) { + this.androidacySupport = true; + this.cookieManager = cookieManager; + if (cookieManager == null) { + this.androidacyCookies = Collections.emptyList(); + } } @NonNull @@ -278,7 +300,8 @@ public class Http { public List loadForRequest(@NonNull HttpUrl httpUrl) { if (!httpUrl.isHttps()) return Collections.emptyList(); if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) { - String cookies = CookieManager.getInstance().getCookie(httpUrl.uri().toString()); + if (this.cookieManager == null) return this.androidacyCookies; + String cookies = this.cookieManager.getCookie(httpUrl.uri().toString()); if (cookies == null || cookies.isEmpty()) return Collections.emptyList(); String[] splitCookies = cookies.split(";"); ArrayList cookieList = new ArrayList<>(splitCookies.length); @@ -296,8 +319,13 @@ public class Http { public void saveFromResponse(@NonNull HttpUrl httpUrl, @NonNull List cookies) { if (!httpUrl.isHttps()) return; if (this.androidacySupport && httpUrl.host().endsWith(".androidacy.com")) { + if (this.cookieManager == null) { + if (httpUrl.host().equals(".androidacy.com") || !cookies.isEmpty()) + this.androidacyCookies = cookies; + return; + } for (Cookie cookie : cookies) { - CookieManager.getInstance().setCookie( + this.cookieManager.setCookie( httpUrl.uri().toString(), cookie.toString()); } return; @@ -454,6 +482,10 @@ public class Http { } } + public static boolean hasWebView() { + return hasWebView; + } + /** * Change URL to appropriate url and force Magisk link to use latest version. */ @@ -495,4 +527,8 @@ public class Http { } return string; } + + public static CookieJar getCookieJar() { + return cookieJar; + } } diff --git a/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java b/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java index 027b600..4d751e0 100644 --- a/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java +++ b/app/src/main/java/com/fox2code/mmm/utils/IntentHelper.java @@ -29,8 +29,6 @@ import com.fox2code.mmm.installer.InstallerActivity; import com.fox2code.mmm.markdown.MarkdownActivity; import com.topjohnwu.superuser.CallbackList; import com.topjohnwu.superuser.Shell; -import com.topjohnwu.superuser.ShellUtils; -import com.topjohnwu.superuser.internal.Utils; import com.topjohnwu.superuser.io.SuFileInputStream; import java.io.File; @@ -38,8 +36,6 @@ import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; public class IntentHelper { private static final String TAG = "IntentHelper"; @@ -103,6 +99,11 @@ public class IntentHelper { public static void openUrlAndroidacy(Context context, String url, boolean allowInstall, String title,String config) { + if (!Http.hasWebView()) { + Log.w(TAG, "Using custom tab for: " + url); + openCustomTab(context, url); + return; + } Uri uri = Uri.parse(url); try { Intent myIntent = new Intent( diff --git a/app/src/main/res/drawable/ic_baseline_android_24.xml b/app/src/main/res/drawable/ic_baseline_android_24.xml new file mode 100644 index 0000000..8679049 --- /dev/null +++ b/app/src/main/res/drawable/ic_baseline_android_24.xml @@ -0,0 +1,8 @@ + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 93046bf..42adfe2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -10,6 +10,7 @@ Failed to download file. Modules took too long to boot, consider disabling some modules Failed to connect to the internet + Failed to get system WebView SettingsActivity Application update available Update diff --git a/rundebug b/rundebug new file mode 100755 index 0000000..3c812e9 --- /dev/null +++ b/rundebug @@ -0,0 +1,7 @@ +#!/bin/sh +# File created to run debug when IDE is failing. +./gradlew app:assembleDefaultDebug +adb install -r -t -d ./app/build/outputs/apk/default/debug/app-default-debug.apk +if [ "$?" == "0" ]; then + adb shell am start com.fox2code.mmm.debug/com.fox2code.mmm.MainActivity +fi