[DO NOT MERGE] Add setup screen

Also the usual fixes and whatnot

Note the setup is rather broken right now as something else is overwriting the pref right away

Signed-off-by: androidacy-user <opensource@androidacy.com>
pull/242/head
androidacy-user 2 years ago
parent 20d51c5b9c
commit 2c675577cb

@ -29,7 +29,7 @@
<application
android:name=".MainApplication"
android:allowBackup="true"
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/full_backup_content"
android:icon="@mipmap/ic_launcher"

@ -26,6 +26,8 @@ import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.cardview.widget.CardView;
import androidx.core.app.NotificationManagerCompat;
@ -51,6 +53,7 @@ import com.fox2code.mmm.utils.ExternalHelper;
import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.IntentHelper;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.materialswitch.MaterialSwitch;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import org.chromium.net.ExperimentalCronetEngine;
@ -61,6 +64,7 @@ import org.json.JSONObject;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Objects;
import eightbitlab.com.blurview.BlurView;
@ -168,7 +172,6 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
moduleViewListBuilder.addNotification(NotificationType.MAGISK_OUTDATED);
if (!MainApplication.isShowcaseMode())
moduleViewListBuilder.addNotification(NotificationType.INSTALL_FROM_STORAGE);
ensurePermissions();
ModuleManager.getINSTANCE().scan();
ModuleManager.getINSTANCE().runAfterScan(moduleViewListBuilder::appendInstalledModules);
this.commonNext();
@ -195,6 +198,22 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
// Fix insets not being accounted for correctly
updateScreenInsets(getResources().getConfiguration());
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
showSetupBox();
// Wait for pref_first_launch to be false
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
while (prefs.getBoolean("pref_first_launch", true)) {
try {
//noinspection BusyWait
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
ensurePermissions();
Log.i(TAG, "Scanning for modules!");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Initialize Update");
final int max = ModuleManager.getINSTANCE().getUpdatableModuleCount();
@ -260,6 +279,16 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
String lastEventId = preferences.getString("lastEventId", "");
if (BuildConfig.DEBUG) Log.d("NoodleDebug", "Last Event ID: " + lastEventId);
if (!lastEventId.equals("")) {
try {
ExperimentalCronetEngine cronetEngine = new ExperimentalCronetEngine.Builder(this).build();
CronetURLStreamHandlerFactory cronetURLStreamHandlerFactory = new CronetURLStreamHandlerFactory(cronetEngine);
URL.setURLStreamHandlerFactory(cronetURLStreamHandlerFactory);
} catch (Exception e) {
if (BuildConfig.DEBUG) {
Log.w(TAG, "Failed to setup cronet HTTPURLConnection factory", e);
Log.w(TAG, "This might mean the factory is already set");
}
}
// Three edit texts for the user to enter their email, name and a description of the issue
EditText email = new EditText(this);
email.setHint(R.string.email);
@ -320,9 +349,7 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
if (connection.getResponseCode() == 200) {
runOnUiThread(() -> Toast.makeText(this, R.string.sentry_dialogue_success, Toast.LENGTH_LONG).show());
} else {
runOnUiThread(() -> Toast.makeText(this,
R.string.sentry_dialogue_failed_toast,
Toast.LENGTH_LONG).show());
runOnUiThread(() -> Toast.makeText(this, R.string.sentry_dialogue_failed_toast, Toast.LENGTH_LONG).show());
}
} catch (IOException | JSONException ignored) {
// Show a toast if the user feedback could not be submitted
@ -619,4 +646,53 @@ public class MainActivity extends FoxActivity implements SwipeRefreshLayout.OnRe
}
}
}
// Method to show a setup box on first launch
@RequiresApi(api = Build.VERSION_CODES.M)
@SuppressLint({"InflateParams", "RestrictedApi", "UnspecifiedImmutableFlag", "ApplySharedPref"})
private void showSetupBox() {
// Check if this is the first launch
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean("pref_first_launch", true)) {
MainApplication.getBootSharedPreferences().edit().putBoolean("mm_first_scan", false).commit();
// Show setup box
runOnUiThread(() -> {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
builder.setCancelable(false);
builder.setTitle(R.string.setup_title);
builder.setView(getLayoutInflater().inflate(R.layout.setup_box, null));
// For now, we'll just have the positive button save the preferences and dismiss the dialog
builder.setPositiveButton(R.string.setup_button, (dialog, which) -> {
// Set the preferences
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.edit().putBoolean("pref_background_update_check",
((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_background_update_check))).isChecked()).commit();
prefs.edit().putBoolean("pref_crash_reporting", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_crash_reporting))).isChecked()).commit();
prefs.edit().putBoolean("pref_androidacy_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_androidacy_repo))).isChecked()).commit();
prefs.edit().putBoolean("pref_magisk_alt_repo_enabled", ((MaterialSwitch) Objects.requireNonNull(((AlertDialog) dialog).findViewById(R.id.setup_magisk_alt_repo))).isChecked()).commit();
if (BuildConfig.DEBUG) {
Log.d("MainActivity", String.format("Background update check: %s, Crash reporting: %s, Androidacy repo: %s, Magisk alt repo: %s",
prefs.getBoolean("pref_background_update_check", false),
prefs.getBoolean("pref_crash_reporting", false),
prefs.getBoolean("pref_androidacy_repo_enabled", false),
prefs.getBoolean("pref_magisk_alt_repo_enabled", false)));
}
// Set pref_first_launch to false
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_first_launch",
false).commit();
// Restart the app
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
});
builder.setNegativeButton(R.string.setup_button_skip, (dialog, which) -> {
// Set pref_first_launch to false
PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean("pref_first_launch",
false).commit();
dialog.dismiss();
});
builder.show();
});
}
}
}

@ -64,8 +64,7 @@ public enum NotificationType implements NotificationTypeCst {
NO_INTERNET(R.string.fail_internet, R.drawable.ic_baseline_cloud_off_24) {
@Override
public boolean shouldRemove() {
return AppUpdateManager.getAppUpdateManager().isLastCheckSuccess() ||
RepoManager.getINSTANCE().hasConnectivity();
return RepoManager.getINSTANCE().hasConnectivity();
}
},
REPO_UPDATE_FAILED(R.string.repo_update_failed, R.drawable.ic_baseline_cloud_off_24) {

@ -202,9 +202,12 @@ public final class RepoManager extends SyncManager {
if (repoData == null) {
if (ANDROIDACY_TEST_MAGISK_REPO_ENDPOINT.equals(url) ||
ANDROIDACY_MAGISK_REPO_ENDPOINT.equals(url)) {
if (this.androidacyRepoData != null)
//noinspection ReplaceNullCheck
if (this.androidacyRepoData != null) {
return this.androidacyRepoData;
return this.addAndroidacyRepoData();
} else {
return this.addAndroidacyRepoData();
}
} else {
return this.addRepoData(url, fallBackName);
}
@ -289,7 +292,6 @@ public final class RepoManager extends SyncManager {
HttpURLConnection urlConnection = (HttpURLConnection) new URL(
"https://connectivitycheck.gstatic.com/generate_204").openConnection();
urlConnection.setInstanceFollowRedirects(false);
urlConnection.setConnectTimeout(1000);
urlConnection.setReadTimeout(1000);
urlConnection.setUseCaches(false);
urlConnection.getInputStream().close();

@ -9,6 +9,8 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -61,6 +63,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.internal.TextWatcherAdapter;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
import com.google.common.hash.Hashing;
import com.mikepenz.aboutlibraries.LibsBuilder;
import com.topjohnwu.superuser.internal.UiThreadHandler;
@ -461,9 +464,24 @@ public class SettingsActivity extends FoxActivity implements LanguageActivity {
openFragment(libsBuilder.supportFragment(), R.string.licenses);
return true;
});
findPreference("pref_pkg_info").setSummary(BuildConfig.APPLICATION_ID +
" v" + BuildConfig.VERSION_NAME + " (" + BuildConfig.VERSION_CODE + ")" +
getRepackageState()); // State may not be "I am just running from myself as myself"
// Determine if this is an official build based on the signature
boolean isOfficial = false;
try {
// Get the signature of the key used to sign the app
@SuppressLint("PackageManagerGetSignatures") Signature[] signatures = requireContext().getPackageManager().getPackageInfo(requireContext().getPackageName(), PackageManager.GET_SIGNATURES).signatures;
String officialSignatureHash =
"7bec7c4462f4aac616612d9f56a023ee3046e83afa956463b5fab547fd0a0be6";
String ourSignatureHash = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
isOfficial = ourSignatureHash.equals(officialSignatureHash);
} catch (PackageManager.NameNotFoundException ignored) {
}
String flavor = BuildConfig.FLAVOR;
String type = BuildConfig.BUILD_TYPE;
// Set the summary of pref_pkg_info to something like Github-debug v1.0 (123) (Official)
String pkgInfo = getString(R.string.pref_pkg_info_summary, flavor + "-" + type,
BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, isOfficial ?
getString(R.string.official) : getString(R.string.unofficial));
findPreference("pref_pkg_info").setSummary(pkgInfo);
}
@SuppressLint("RestrictedApi")

@ -54,7 +54,6 @@ import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.dnsoverhttps.DnsOverHttps;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.BufferedSink;
public class Http {
@ -159,6 +158,12 @@ public class Http {
}
builder.setStoragePath(mainApplication.getCacheDir().getAbsolutePath() + "/cronet");
builder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK_NO_HTTP, 10 * 1024 * 1024);
// Add quic hint
builder.addQuicHint("github.com", 443, 443);
builder.addQuicHint("githubusercontent.com", 443, 443);
builder.addQuicHint("jsdelivr.net", 443, 443);
builder.addQuicHint("androidacy.com", 443, 443);
builder.addQuicHint("sentry.io", 443, 443);
CronetEngine engine = builder.build();
httpclientBuilder.addInterceptor(CronetInterceptor.newBuilder(engine).build());
} catch (Exception e) {
@ -172,13 +177,6 @@ public class Http {
httpClient = followRedirects(httpclientBuilder, true).build();
followRedirects(httpclientBuilder, false).build();
httpclientBuilder.dns(fallbackDNS);
if (BuildConfig.DEBUG) {
// Enable logging
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(s -> Log.d(TAG, s));
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpclientBuilder.addInterceptor(logging);
Log.d(TAG, "OkHttp logging enabled");
}
httpClientDoH = followRedirects(httpclientBuilder, true).build();
followRedirects(httpclientBuilder, false).build();
httpclientBuilder.cache(new Cache(new File(mainApplication.getCacheDir(), "http_cache"), 16L * 1024L * 1024L)); // 16Mib of cache
@ -343,24 +341,49 @@ public class Http {
}
public static void ensureCacheDirs(MainActivity mainActivity) {
// Recursively ensure cache dirs for webview exist under our cache dir
File cacheDir = mainActivity.getCacheDir();
File cacheDir2 = new File(cacheDir, "HTTP Cache");
if (!cacheDir2.exists()) {
if (!cacheDir2.mkdirs()) {
Log.e(TAG, "Failed to create cache dir");
File webviewCacheDir = new File(cacheDir, "WebView");
if (!webviewCacheDir.exists()) {
if (!webviewCacheDir.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
File webviewCacheDirCache = new File(webviewCacheDir, "Default");
if (!webviewCacheDirCache.exists()) {
if (!webviewCacheDirCache.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
File webviewCacheDirCacheCodeCache = new File(webviewCacheDirCache, "HTTP Cache");
if (!webviewCacheDirCacheCodeCache.exists()) {
if (!webviewCacheDirCacheCodeCache.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
File webviewCacheDirCacheCodeCacheIndex = new File(webviewCacheDirCacheCodeCache, "Code Cache");
if (!webviewCacheDirCacheCodeCacheIndex.exists()) {
if (!webviewCacheDirCacheCodeCacheIndex.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
File webviewCacheDirCacheCodeCacheIndexIndex = new File(webviewCacheDirCacheCodeCacheIndex, "Index");
if (!webviewCacheDirCacheCodeCacheIndexIndex.exists()) {
if (!webviewCacheDirCacheCodeCacheIndexIndex.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
// Ensure js and wasm cache dirs
File jsCacheDir = new File(cacheDir2, "js");
if (!jsCacheDir.exists()) {
if (!jsCacheDir.mkdirs()) {
Log.e(TAG, "Failed to create js cache dir");
// Create the js and wasm dirs
File webviewCacheDirCacheCodeCacheIndexIndexJs = new File(webviewCacheDirCacheCodeCache, "js");
if (!webviewCacheDirCacheCodeCacheIndexIndexJs.exists()) {
if (!webviewCacheDirCacheCodeCacheIndexIndexJs.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
File wasmCacheDir = new File(cacheDir2, "wasm");
if (!wasmCacheDir.exists()) {
if (!wasmCacheDir.mkdirs()) {
Log.e(TAG, "Failed to create wasm cache dir");
File webviewCacheDirCacheCodeCacheIndexIndexWasm = new File(webviewCacheDirCacheCodeCache, "wasm");
if (!webviewCacheDirCacheCodeCacheIndexIndexWasm.exists()) {
if (!webviewCacheDirCacheCodeCacheIndexIndexWasm.mkdirs()) {
Log.e(TAG, "Failed to create webview cache dir");
}
}
}

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="fill"
android:orientation="vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:scrollbars="vertical">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:text="@string/setup_message"
android:textSize="14sp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="6dp"
android:text="@string/repos"
android:textSize="18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/setup_androidacy_repo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:checked="true"
android:key="pref_androidacy_repo_enabled"
android:text="@string/setup_androidacy_repo"
android:textSize="14sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/setup_magisk_alt_repo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:checked="false"
android:key="pref_magisk_alt_repo_enabled"
android:text="@string/setup_magisk_alt_repo"
android:textSize="14sp" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="2dp"
android:checked="true"
android:text="@string/setup_custom_repos"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="6dp"
android:text="@string/misc"
android:textSize="18sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/setup_crash_reporting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:checked="true"
android:key="pref_crash_reporting_enabled"
android:text="@string/setup_crash_reporting"
android:textSize="14sp" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/setup_background_update_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="4dp"
android:checked="true"
android:key="pref_background_update_check"
android:text="@string/setup_background_update_check"
android:textSize="14sp" />
</LinearLayout>
</ScrollView>
</LinearLayout>

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----

@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----

@ -208,8 +208,8 @@
by adding some information about the error below.\nName and email are optional but will
allow us to contact you if needed for more information.</string>
<string name="sentry_dialogue_title">Oops! Looks like the app closed unexpectedly.</string>
<string name="name">Name</string>
<string name="email">Email</string>
<string name="name">Your name</string>
<string name="email">Your email</string>
<string name="additional_info">Tell us what happened</string>
<string name="submit">Submit</string>
<string name="sentry_dialogue_failed_toast">Could not submit feedback due to an error</string>
@ -218,4 +218,19 @@
<string name="sentry_dialogue_no_description">Could not submit feedback as no
description was provided</string>
<string name="go_to_online_repo">Scroll to online repo</string>
<string name="pref_pkg_info_summary">%1$s v%2$s (%3$o) | %4$s Build</string>
<string name="official">Official</string>
<string name="unofficial">Unofficial</string>
<string name="setup_title">First time setup</string>
<string name="setup_message">Looks like this is your first time opening the app.\nPick
the basic options you desire below. You can change them later in settings.</string>
<string name="setup_button">Finish setup</string>
<string name="setup_background_update_check">Allow us to check for updates in the background. May use more battery.</string>
<string name="setup_androidacy_repo">Enable the Androidacy repo, which features user reviews, automatic virus scans, fast updates, a wide selection, and is backed by Androidacy.</string>
<string name="setup_magisk_alt_repo">Enable the Magisk Alternative Repo. Less rules and reviewing than the original. Fully hosted on GitHub.</string>
<string name="setup_crash_reporting">Enable automatic crash reporting and performance monitoring. Crash reports are anonymized with all personal info removed, and are onlly accessible to the developers. Uses sentry.io.</string>
<string name="setup_custom_repos">You can add custom repos later in settings.</string>
<string name="repos">Repos</string>
<string name="misc">Misc settings</string>
<string name="setup_button_skip">Skip</string>
</resources>

@ -8,20 +8,27 @@
</domain-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">github.com</domain>
<domain includeSubdomains="true">githubusercontent.com</domain>
<trust-anchors>
<certificates src="@raw/gh_root_ca" />
</trust-anchors>
</domain-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">githubusercontent.com</domain>
<domain includeSubdomains="true">gstatic.com</domain>
<trust-anchors>
<certificates src="@raw/gh_root_ca" />
<certificates src="@raw/gstatic_root_ca" />
</trust-anchors>
</domain-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="true">gstatic.com</domain>
<domain includeSubdomains="true">ingest.sentry.io</domain>
<trust-anchors>
<certificates src="@raw/gstatic_root_ca" />
<certificates src="@raw/sentry_root_ca" />
</trust-anchors>
</domain-config>
<domain-config cleartextTrafficPermitted="false">
<domain includeSubdomains="false">sentry.io</domain>
<trust-anchors>
<certificates src="@raw/sentry_io_root_ca" />
</trust-anchors>
</domain-config>
</network-security-config>

@ -25,9 +25,9 @@ public class SentryMain {
@SuppressLint({"RestrictedApi", "UnspecifiedImmutableFlag"})
public static void initialize(final MainApplication mainApplication) {
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
SharedPreferences.Editor editor = mainApplication.getSharedPreferences(
"sentry", Context.MODE_PRIVATE).edit();
SharedPreferences.Editor editor = mainApplication.getSharedPreferences("sentry", Context.MODE_PRIVATE).edit();
editor.putString("lastExitReason", "crash");
editor.putLong("lastExitTime", System.currentTimeMillis());
editor.apply();
// If we just let the default uncaught exception handler handle the
// exception, the app will hang and never close.
@ -56,9 +56,7 @@ public class SentryMain {
// With this callback, you can modify the event or, when returning null, also discard the event.
options.setBeforeSend((event, hint) -> {
// Save lastEventId to private shared preferences
SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences(
"sentry",
Context.MODE_PRIVATE);
SharedPreferences sharedPreferences = MainApplication.getINSTANCE().getSharedPreferences("sentry", Context.MODE_PRIVATE);
String lastEventId = Objects.requireNonNull(event.getEventId()).toString();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("lastEventId", lastEventId);

Loading…
Cancel
Save