Add Support for systems without a working WebView

pull/133/head
Fox2Code 2 years ago
parent 6daa94108e
commit e90472aae4

@ -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);

@ -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;

@ -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<ModuleHolder> {
}
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);

@ -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(),

@ -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('?')) {

@ -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<Cookie> 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()) ||

@ -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;

@ -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;

@ -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<String, Cookie> cookieMap = new HashMap<>();
private final boolean androidacySupport;
private final CookieManager cookieManager;
private List<Cookie> 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<Cookie> 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<Cookie> cookieList = new ArrayList<>(splitCookies.length);
@ -296,8 +319,13 @@ public class Http {
public void saveFromResponse(@NonNull HttpUrl httpUrl, @NonNull List<Cookie> 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;
}
}

@ -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(

@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white" android:pathData="M17.6,9.48l1.84,-3.18c0.16,-0.31 0.04,-0.69 -0.26,-0.85c-0.29,-0.15 -0.65,-0.06 -0.83,0.22l-1.88,3.24c-2.86,-1.21 -6.08,-1.21 -8.94,0L5.65,5.67c-0.19,-0.29 -0.58,-0.38 -0.87,-0.2C4.5,5.65 4.41,6.01 4.56,6.3L6.4,9.48C3.3,11.25 1.28,14.44 1,18h22C22.72,14.44 20.7,11.25 17.6,9.48zM7,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25S8.25,13.31 8.25,14C8.25,14.69 7.69,15.25 7,15.25zM17,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25s1.25,0.56 1.25,1.25C18.25,14.69 17.69,15.25 17,15.25z"/>
</vector>

@ -10,6 +10,7 @@
<string name="failed_download">Failed to download file.</string>
<string name="slow_modules">Modules took too long to boot, consider disabling some modules</string>
<string name="fail_internet">Failed to connect to the internet</string>
<string name="no_web_view">Failed to get system WebView</string>
<string name="title_activity_settings">SettingsActivity</string>
<string name="app_update_available">Application update available</string>
<string name="app_update">Update</string>

@ -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
Loading…
Cancel
Save