mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-24 07:37:30 +00:00
Add sentry to github builds
This commit adds github and fdroid product flavors. Sentry is added only to github builds. Sentry is opt-in.
This commit is contained in:
parent
16ac573859
commit
5bdfb7df51
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@
|
|||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
.cxx
|
.cxx
|
||||||
app/release
|
app/release
|
||||||
|
/sentry.properties
|
@ -1,5 +1,6 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: "androidx.navigation.safeargs"
|
apply plugin: "androidx.navigation.safeargs"
|
||||||
|
apply from: 'sentry.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
@ -48,8 +49,22 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flavorDimensions "repo"
|
||||||
|
|
||||||
|
productFlavors {
|
||||||
|
github {
|
||||||
|
dimension "repo"
|
||||||
|
versionNameSuffix "-github"
|
||||||
|
buildConfigField("String", "dsn", SENTRY_DSN)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fdroid {
|
||||||
|
dimension "repo"
|
||||||
|
versionNameSuffix "-fdroid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
configurations.all {
|
configurations.all {
|
||||||
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
|
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
|
||||||
@ -81,7 +96,7 @@ dependencies {
|
|||||||
implementation 'androidx.palette:palette:1.0.0'
|
implementation 'androidx.palette:palette:1.0.0'
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
|
||||||
|
|
||||||
implementation 'com.google.guava:guava:27.1-jre'
|
implementation 'com.google.guava:guava:27.0.1-android'
|
||||||
|
|
||||||
// Room
|
// Room
|
||||||
def room_version = "2.2.6"
|
def room_version = "2.2.6"
|
||||||
@ -116,5 +131,7 @@ dependencies {
|
|||||||
|
|
||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6'
|
||||||
|
|
||||||
|
githubImplementation 'io.sentry:sentry-android:4.3.0'
|
||||||
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.7.1'
|
||||||
}
|
}
|
||||||
|
13
app/sentry.gradle
Normal file
13
app/sentry.gradle
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
def dsnKey = 'DSN'
|
||||||
|
def defaultDsn = '\"\"'
|
||||||
|
|
||||||
|
final Properties properties = new Properties()
|
||||||
|
File propertiesFile = rootProject.file('sentry.properties')
|
||||||
|
if (!propertiesFile.exists()) {
|
||||||
|
propertiesFile.createNewFile()
|
||||||
|
}
|
||||||
|
properties.load(new FileInputStream(propertiesFile))
|
||||||
|
|
||||||
|
ext{
|
||||||
|
SENTRY_DSN = properties.getProperty(dsnKey, defaultDsn)
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package awais.instagrabber.fragments.settings;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.fragments.settings.IFlavorSettings;
|
||||||
|
import awais.instagrabber.fragments.settings.SettingCategory;
|
||||||
|
|
||||||
|
public final class FlavorSettings implements IFlavorSettings {
|
||||||
|
|
||||||
|
private static FlavorSettings instance;
|
||||||
|
|
||||||
|
private FlavorSettings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlavorSettings getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new FlavorSettings();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<Preference> getPreferences(@NonNull final Context context,
|
||||||
|
@NonNull final FragmentManager fragmentManager,
|
||||||
|
@NonNull final SettingCategory settingCategory) {
|
||||||
|
// switch (settingCategory) {
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
56
app/src/fdroid/java/awaisomereport/CrashHandler.java
Normal file
56
app/src/fdroid/java/awaisomereport/CrashHandler.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package awaisomereport;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class CrashHandler implements ICrashHandler {
|
||||||
|
private static final String TAG = CrashHandler.class.getSimpleName();
|
||||||
|
|
||||||
|
private final Application application;
|
||||||
|
|
||||||
|
public CrashHandler(@NonNull final Application application) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(@NonNull final Thread t,
|
||||||
|
@NonNull final Throwable exception,
|
||||||
|
@NonNull final Thread.UncaughtExceptionHandler defaultEH) {
|
||||||
|
CrashReporterHelper.startErrorReporterActivity(application, exception);
|
||||||
|
// zipLogs();
|
||||||
|
defaultEH.uncaughtException(t, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public synchronized CrashReporter zipLogs() {
|
||||||
|
// final File logDir = Utils.logCollector != null ? Utils.logCollector.getLogDir() :
|
||||||
|
// new File(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? application.getDataDir() : application.getFilesDir(), "crashlogs");
|
||||||
|
//
|
||||||
|
// try (final FileOutputStream fos = new FileOutputStream(crashLogsZip);
|
||||||
|
// final ZipOutputStream zos = new ZipOutputStream(fos)) {
|
||||||
|
//
|
||||||
|
// final File[] files = logDir.listFiles();
|
||||||
|
//
|
||||||
|
// if (files != null) {
|
||||||
|
// zos.setLevel(5);
|
||||||
|
// byte[] buffer;
|
||||||
|
// for (final File file : files) {
|
||||||
|
// if (file != null && file.length() > 0) {
|
||||||
|
// buffer = new byte[1024];
|
||||||
|
// try (final FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
// zos.putNextEntry(new ZipEntry(file.getName()));
|
||||||
|
// int length;
|
||||||
|
// while ((length = fis.read(buffer)) > 0) zos.write(buffer, 0, length);
|
||||||
|
// zos.closeEntry();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (final Exception e) {
|
||||||
|
// if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
}
|
10
app/src/github/AndroidManifest.xml
Normal file
10
app/src/github/AndroidManifest.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="awais.instagrabber">
|
||||||
|
|
||||||
|
<application>
|
||||||
|
<meta-data
|
||||||
|
android:name="io.sentry.auto-init"
|
||||||
|
android:value="false" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
@ -0,0 +1,83 @@
|
|||||||
|
package awais.instagrabber.fragments.settings;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.dialogs.ConfirmDialogFragment;
|
||||||
|
|
||||||
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
|
public final class FlavorSettings implements IFlavorSettings {
|
||||||
|
|
||||||
|
private static FlavorSettings instance;
|
||||||
|
|
||||||
|
private FlavorSettings() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlavorSettings getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new FlavorSettings();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public List<Preference> getPreferences(@NonNull final Context context,
|
||||||
|
@NonNull final FragmentManager fragmentManager,
|
||||||
|
@NonNull final SettingCategory settingCategory) {
|
||||||
|
switch (settingCategory) {
|
||||||
|
case GENERAL:
|
||||||
|
return getGeneralPrefs(context, fragmentManager);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Preference> getGeneralPrefs(@NonNull final Context context,
|
||||||
|
@NonNull final FragmentManager fragmentManager) {
|
||||||
|
return ImmutableList.of(
|
||||||
|
getSentryPreference(context, fragmentManager)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Preference getSentryPreference(@NonNull final Context context,
|
||||||
|
@NonNull final FragmentManager fragmentManager) {
|
||||||
|
if (!settingsHelper.hasPreference(PREF_ENABLE_SENTRY)) {
|
||||||
|
// disabled by default
|
||||||
|
settingsHelper.putBoolean(PREF_ENABLE_SENTRY, false);
|
||||||
|
}
|
||||||
|
return PreferenceHelper.getSwitchPreference(
|
||||||
|
context,
|
||||||
|
PREF_ENABLE_SENTRY,
|
||||||
|
R.string.enable_sentry,
|
||||||
|
R.string.sentry_summary,
|
||||||
|
false,
|
||||||
|
(preference, newValue) -> {
|
||||||
|
if (!(newValue instanceof Boolean)) return true;
|
||||||
|
final boolean enabled = (Boolean) newValue;
|
||||||
|
if (enabled) {
|
||||||
|
final ConfirmDialogFragment dialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
|
111,
|
||||||
|
0,
|
||||||
|
R.string.sentry_start_next_launch,
|
||||||
|
R.string.ok,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
dialogFragment.show(fragmentManager, "sentry_dialog");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
59
app/src/github/java/awaisomereport/CrashHandler.java
Normal file
59
app/src/github/java/awaisomereport/CrashHandler.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package awaisomereport;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import awais.instagrabber.BuildConfig;
|
||||||
|
import awais.instagrabber.fragments.settings.PreferenceKeys;
|
||||||
|
import io.sentry.SentryLevel;
|
||||||
|
import io.sentry.android.core.SentryAndroid;
|
||||||
|
import io.sentry.protocol.Contexts;
|
||||||
|
import io.sentry.protocol.Device;
|
||||||
|
|
||||||
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
|
public class CrashHandler implements ICrashHandler {
|
||||||
|
private static final String TAG = CrashHandler.class.getSimpleName();
|
||||||
|
|
||||||
|
private final Application application;
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
public CrashHandler(@NonNull final Application application) {
|
||||||
|
this.application = application;
|
||||||
|
if (!settingsHelper.hasPreference(PreferenceKeys.PREF_ENABLE_SENTRY)) {
|
||||||
|
// disabled by default (change to true if we need enabled by default)
|
||||||
|
enabled = false;
|
||||||
|
} else {
|
||||||
|
enabled = settingsHelper.getBoolean(PreferenceKeys.PREF_ENABLE_SENTRY);
|
||||||
|
}
|
||||||
|
if (!enabled) return;
|
||||||
|
SentryAndroid.init(application, options -> {
|
||||||
|
options.setDsn(BuildConfig.dsn);
|
||||||
|
options.setDiagnosticLevel(SentryLevel.ERROR);
|
||||||
|
options.setBeforeSend((event, hint) -> {
|
||||||
|
// Removing unneeded info from event
|
||||||
|
final Contexts contexts = event.getContexts();
|
||||||
|
final Device device = contexts.getDevice();
|
||||||
|
device.setName(null);
|
||||||
|
device.setTimezone(null);
|
||||||
|
device.setCharging(null);
|
||||||
|
device.setBootTime(null);
|
||||||
|
device.setFreeStorage(null);
|
||||||
|
device.setBatteryTemperature(null);
|
||||||
|
return event;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uncaughtException(@NonNull final Thread t,
|
||||||
|
@NonNull final Throwable exception,
|
||||||
|
@NonNull final Thread.UncaughtExceptionHandler defaultEH) {
|
||||||
|
// When enabled, Sentry auto captures unhandled exceptions
|
||||||
|
if (!enabled) {
|
||||||
|
CrashReporterHelper.startErrorReporterActivity(application, exception);
|
||||||
|
}
|
||||||
|
defaultEH.uncaughtException(t, exception);
|
||||||
|
}
|
||||||
|
}
|
@ -18,14 +18,12 @@ import awais.instagrabber.utils.LocaleUtils;
|
|||||||
import awais.instagrabber.utils.SettingsHelper;
|
import awais.instagrabber.utils.SettingsHelper;
|
||||||
import awais.instagrabber.utils.TextUtils;
|
import awais.instagrabber.utils.TextUtils;
|
||||||
import awaisomereport.CrashReporter;
|
import awaisomereport.CrashReporter;
|
||||||
//import awaisomereport.LogCollector;
|
|
||||||
|
|
||||||
import static awais.instagrabber.utils.CookieUtils.NET_COOKIE_MANAGER;
|
import static awais.instagrabber.utils.CookieUtils.NET_COOKIE_MANAGER;
|
||||||
import static awais.instagrabber.utils.Utils.applicationHandler;
|
import static awais.instagrabber.utils.Utils.applicationHandler;
|
||||||
import static awais.instagrabber.utils.Utils.cacheDir;
|
import static awais.instagrabber.utils.Utils.cacheDir;
|
||||||
import static awais.instagrabber.utils.Utils.clipboardManager;
|
import static awais.instagrabber.utils.Utils.clipboardManager;
|
||||||
import static awais.instagrabber.utils.Utils.datetimeParser;
|
import static awais.instagrabber.utils.Utils.datetimeParser;
|
||||||
//import static awais.instagrabber.utils.Utils.logCollector;
|
|
||||||
import static awais.instagrabber.utils.Utils.settingsHelper;
|
import static awais.instagrabber.utils.Utils.settingsHelper;
|
||||||
|
|
||||||
public final class InstaGrabberApplication extends Application {
|
public final class InstaGrabberApplication extends Application {
|
||||||
@ -34,16 +32,16 @@ public final class InstaGrabberApplication extends Application {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
// final Set<RequestListener> requestListeners = new HashSet<>();
|
CookieHandler.setDefault(NET_COOKIE_MANAGER);
|
||||||
// requestListeners.add(new RequestLoggingListener());
|
|
||||||
final ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig
|
if (settingsHelper == null) {
|
||||||
.newBuilder(this)
|
settingsHelper = new SettingsHelper(this);
|
||||||
// .setMainDiskCacheConfig(diskCacheConfig)
|
}
|
||||||
// .setRequestListeners(requestListeners)
|
|
||||||
.setDownsampleEnabled(true)
|
if (!BuildConfig.DEBUG) {
|
||||||
.build();
|
CrashReporter.get(this).start();
|
||||||
Fresco.initialize(this, imagePipelineConfig);
|
}
|
||||||
// FLog.setMinimumLoggingLevel(FLog.VERBOSE);
|
// logCollector = new LogCollector(this);
|
||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
try {
|
try {
|
||||||
@ -55,13 +53,16 @@ public final class InstaGrabberApplication extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!BuildConfig.DEBUG) CrashReporter.get(this).start();
|
// final Set<RequestListener> requestListeners = new HashSet<>();
|
||||||
// logCollector = new LogCollector(this);
|
// requestListeners.add(new RequestLoggingListener());
|
||||||
|
final ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig
|
||||||
CookieHandler.setDefault(NET_COOKIE_MANAGER);
|
.newBuilder(this)
|
||||||
|
// .setMainDiskCacheConfig(diskCacheConfig)
|
||||||
if (settingsHelper == null)
|
// .setRequestListeners(requestListeners)
|
||||||
settingsHelper = new SettingsHelper(this);
|
.setDownsampleEnabled(true)
|
||||||
|
.build();
|
||||||
|
Fresco.initialize(this, imagePipelineConfig);
|
||||||
|
// FLog.setMinimumLoggingLevel(FLog.VERBOSE);
|
||||||
|
|
||||||
if (applicationHandler == null) {
|
if (applicationHandler == null) {
|
||||||
applicationHandler = new Handler(getApplicationContext().getMainLooper());
|
applicationHandler = new Handler(getApplicationContext().getMainLooper());
|
||||||
|
@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
@ -17,6 +18,9 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||||||
private Context context;
|
private Context context;
|
||||||
private ConfirmDialogFragmentCallback callback;
|
private ConfirmDialogFragmentCallback callback;
|
||||||
|
|
||||||
|
private final int defaultPositiveButtonText = R.string.ok;
|
||||||
|
// private final int defaultNegativeButtonText = R.string.cancel;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static ConfirmDialogFragment newInstance(final int requestCode,
|
public static ConfirmDialogFragment newInstance(final int requestCode,
|
||||||
@StringRes final int title,
|
@StringRes final int title,
|
||||||
@ -26,11 +30,21 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||||||
@StringRes final int neutralText) {
|
@StringRes final int neutralText) {
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putInt("requestCode", requestCode);
|
args.putInt("requestCode", requestCode);
|
||||||
|
if (title != 0) {
|
||||||
args.putInt("title", title);
|
args.putInt("title", title);
|
||||||
|
}
|
||||||
|
if (message != 0) {
|
||||||
args.putInt("message", message);
|
args.putInt("message", message);
|
||||||
|
}
|
||||||
|
if (positiveText != 0) {
|
||||||
args.putInt("positive", positiveText);
|
args.putInt("positive", positiveText);
|
||||||
|
}
|
||||||
|
if (negativeText != 0) {
|
||||||
args.putInt("negative", negativeText);
|
args.putInt("negative", negativeText);
|
||||||
|
}
|
||||||
|
if (neutralText != 0) {
|
||||||
args.putInt("neutral", neutralText);
|
args.putInt("neutral", neutralText);
|
||||||
|
}
|
||||||
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
|
ConfirmDialogFragment fragment = new ConfirmDialogFragment();
|
||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
return fragment;
|
return fragment;
|
||||||
@ -41,10 +55,9 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onAttach(@NonNull final Context context) {
|
public void onAttach(@NonNull final Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
try {
|
final Fragment parentFragment = getParentFragment();
|
||||||
callback = (ConfirmDialogFragmentCallback) getParentFragment();
|
if (parentFragment instanceof ConfirmDialogFragmentCallback) {
|
||||||
} catch (ClassCastException e) {
|
callback = (ConfirmDialogFragmentCallback) parentFragment;
|
||||||
throw new ClassCastException("Calling fragment must implement ConfirmDialogFragmentCallback interface");
|
|
||||||
}
|
}
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@ -53,38 +66,42 @@ public class ConfirmDialogFragment extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||||
final Bundle arguments = getArguments();
|
final Bundle arguments = getArguments();
|
||||||
int title = -1;
|
int title = 0;
|
||||||
int message = -1;
|
int message = 0;
|
||||||
int positiveButtonText = R.string.ok;
|
int neutralButtonText = 0;
|
||||||
int negativeButtonText = R.string.cancel;
|
int negativeButtonText = 0;
|
||||||
int neutralButtonText = -1;
|
|
||||||
|
final int positiveButtonText;
|
||||||
final int requestCode;
|
final int requestCode;
|
||||||
if (arguments != null) {
|
if (arguments != null) {
|
||||||
title = arguments.getInt("title", -1);
|
title = arguments.getInt("title", 0);
|
||||||
message = arguments.getInt("message", -1);
|
message = arguments.getInt("message", 0);
|
||||||
positiveButtonText = arguments.getInt("positive", R.string.ok);
|
positiveButtonText = arguments.getInt("positive", defaultPositiveButtonText);
|
||||||
negativeButtonText = arguments.getInt("negative", R.string.cancel);
|
negativeButtonText = arguments.getInt("negative", 0);
|
||||||
neutralButtonText = arguments.getInt("neutral", -1);
|
neutralButtonText = arguments.getInt("neutral", 0);
|
||||||
requestCode = arguments.getInt("requestCode", 0);
|
requestCode = arguments.getInt("requestCode", 0);
|
||||||
} else {
|
} else {
|
||||||
requestCode = 0;
|
requestCode = 0;
|
||||||
|
positiveButtonText = defaultPositiveButtonText;
|
||||||
}
|
}
|
||||||
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context)
|
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(context)
|
||||||
.setPositiveButton(positiveButtonText, (d, w) -> {
|
.setPositiveButton(positiveButtonText, (d, w) -> {
|
||||||
if (callback == null) return;
|
if (callback == null) return;
|
||||||
callback.onPositiveButtonClicked(requestCode);
|
callback.onPositiveButtonClicked(requestCode);
|
||||||
})
|
});
|
||||||
.setNegativeButton(negativeButtonText, (dialog, which) -> {
|
if (title != 0) {
|
||||||
|
builder.setTitle(title);
|
||||||
|
}
|
||||||
|
if (message != 0) {
|
||||||
|
builder.setMessage(message);
|
||||||
|
}
|
||||||
|
if (negativeButtonText != 0) {
|
||||||
|
builder.setNegativeButton(negativeButtonText, (dialog, which) -> {
|
||||||
if (callback == null) return;
|
if (callback == null) return;
|
||||||
callback.onNegativeButtonClicked(requestCode);
|
callback.onNegativeButtonClicked(requestCode);
|
||||||
});
|
});
|
||||||
if (title > 0) {
|
|
||||||
builder.setTitle(title);
|
|
||||||
}
|
}
|
||||||
if (message > 0) {
|
if (neutralButtonText != 0) {
|
||||||
builder.setMessage(message);
|
|
||||||
}
|
|
||||||
if (neutralButtonText > 0) {
|
|
||||||
builder.setNeutralButton(neutralButtonText, (dialog, which) -> {
|
builder.setNeutralButton(neutralButtonText, (dialog, which) -> {
|
||||||
if (callback == null) return;
|
if (callback == null) return;
|
||||||
callback.onNeutralButtonClicked(requestCode);
|
callback.onNeutralButtonClicked(requestCode);
|
||||||
|
@ -186,7 +186,7 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
R.string.admin_approval_required_description,
|
R.string.admin_approval_required_description,
|
||||||
R.string.ok,
|
R.string.ok,
|
||||||
R.string.cancel,
|
R.string.cancel,
|
||||||
-1
|
0
|
||||||
);
|
);
|
||||||
confirmDialogFragment.show(getChildFragmentManager(), "approval_required_dialog");
|
confirmDialogFragment.show(getChildFragmentManager(), "approval_required_dialog");
|
||||||
return;
|
return;
|
||||||
@ -272,10 +272,10 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
final ConfirmDialogFragment confirmDialogFragment = ConfirmDialogFragment.newInstance(
|
||||||
LEAVE_THREAD_REQUEST_CODE,
|
LEAVE_THREAD_REQUEST_CODE,
|
||||||
R.string.dms_action_leave_question,
|
R.string.dms_action_leave_question,
|
||||||
-1,
|
0,
|
||||||
R.string.yes,
|
R.string.yes,
|
||||||
R.string.no,
|
R.string.no,
|
||||||
-1
|
0
|
||||||
);
|
);
|
||||||
confirmDialogFragment.show(getChildFragmentManager(), "leave_thread_confirmation_dialog");
|
confirmDialogFragment.show(getChildFragmentManager(), "leave_thread_confirmation_dialog");
|
||||||
});
|
});
|
||||||
@ -290,7 +290,7 @@ public class DirectMessageSettingsFragment extends Fragment implements ConfirmDi
|
|||||||
R.string.dms_action_end_description,
|
R.string.dms_action_end_description,
|
||||||
R.string.yes,
|
R.string.yes,
|
||||||
R.string.no,
|
R.string.no,
|
||||||
-1
|
0
|
||||||
);
|
);
|
||||||
confirmDialogFragment.show(getChildFragmentManager(), "end_thread_confirmation_dialog");
|
confirmDialogFragment.show(getChildFragmentManager(), "end_thread_confirmation_dialog");
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,8 @@ import androidx.preference.Preference;
|
|||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
import androidx.preference.SwitchPreferenceCompat;
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import awais.instagrabber.R;
|
import awais.instagrabber.R;
|
||||||
import awais.instagrabber.utils.Constants;
|
import awais.instagrabber.utils.Constants;
|
||||||
import awais.instagrabber.utils.CookieUtils;
|
import awais.instagrabber.utils.CookieUtils;
|
||||||
@ -29,6 +31,14 @@ public class GeneralPreferencesFragment extends BasePreferencesFragment {
|
|||||||
}
|
}
|
||||||
screen.addPreference(getUpdateCheckPreference(context));
|
screen.addPreference(getUpdateCheckPreference(context));
|
||||||
screen.addPreference(getFlagSecurePreference(context));
|
screen.addPreference(getFlagSecurePreference(context));
|
||||||
|
final List<Preference> preferences = FlavorSettings.getInstance().getPreferences(context,
|
||||||
|
getChildFragmentManager(),
|
||||||
|
SettingCategory.GENERAL);
|
||||||
|
if (preferences != null) {
|
||||||
|
for (final Preference preference : preferences) {
|
||||||
|
screen.addPreference(preference);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Preference getDefaultTabPreference(@NonNull final Context context) {
|
private Preference getDefaultTabPreference(@NonNull final Context context) {
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package awais.instagrabber.fragments.settings;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IFlavorSettings {
|
||||||
|
List<Preference> getPreferences(Context context,
|
||||||
|
FragmentManager childFragmentManager,
|
||||||
|
SettingCategory settingCategory);
|
||||||
|
}
|
@ -5,4 +5,5 @@ public final class PreferenceKeys {
|
|||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH = "enable_dm_auto_refresh";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH = "enable_dm_auto_refresh";
|
||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit";
|
||||||
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
|
||||||
|
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package awais.instagrabber.fragments.settings;
|
||||||
|
|
||||||
|
public enum SettingCategory {
|
||||||
|
GENERAL,
|
||||||
|
// add more as and when required
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package awais.instagrabber.utils;
|
package awais.instagrabber.utils;
|
||||||
|
|
||||||
public final class Constants {
|
public final class Constants {
|
||||||
|
public static final String CRASH_REPORT_EMAIL = "barinsta@austinhuang.me";
|
||||||
|
|
||||||
// string prefs
|
// string prefs
|
||||||
public static final String FOLDER_PATH = "custom_path";
|
public static final String FOLDER_PATH = "custom_path";
|
||||||
public static final String DATE_TIME_FORMAT = "date_time_format";
|
public static final String DATE_TIME_FORMAT = "date_time_format";
|
||||||
|
@ -12,6 +12,7 @@ import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_D
|
|||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT;
|
||||||
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_DM_NOTIFICATIONS;
|
||||||
|
import static awais.instagrabber.fragments.settings.PreferenceKeys.PREF_ENABLE_SENTRY;
|
||||||
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
import static awais.instagrabber.utils.Constants.APP_LANGUAGE;
|
||||||
import static awais.instagrabber.utils.Constants.APP_THEME;
|
import static awais.instagrabber.utils.Constants.APP_THEME;
|
||||||
import static awais.instagrabber.utils.Constants.APP_UA;
|
import static awais.instagrabber.utils.Constants.APP_UA;
|
||||||
@ -130,6 +131,10 @@ public final class SettingsHelper {
|
|||||||
if (sharedPreferences != null) sharedPreferences.edit().putBoolean(key, val).apply();
|
if (sharedPreferences != null) sharedPreferences.edit().putBoolean(key, val).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasPreference(final String key) {
|
||||||
|
return sharedPreferences != null && sharedPreferences.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
@StringDef(
|
@StringDef(
|
||||||
{APP_LANGUAGE, APP_THEME, APP_UA, BROWSER_UA, COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION,
|
{APP_LANGUAGE, APP_THEME, APP_UA, BROWSER_UA, COOKIE, FOLDER_PATH, DATE_TIME_FORMAT, DATE_TIME_SELECTION,
|
||||||
CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME,
|
CUSTOM_DATE_TIME_FORMAT, DEVICE_UUID, SKIPPED_VERSION, DEFAULT_TAB, PREF_DARK_THEME, PREF_LIGHT_THEME,
|
||||||
@ -141,7 +146,7 @@ public final class SettingsHelper {
|
|||||||
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
@StringDef({DOWNLOAD_USER_FOLDER, FOLDER_SAVE_TO, AUTOPLAY_VIDEOS, SHOW_QUICK_ACCESS_DIALOG, MUTED_VIDEOS,
|
||||||
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
SHOW_CAPTIONS, CUSTOM_DATE_TIME_FORMAT_ENABLED, MARK_AS_SEEN, DM_MARK_AS_SEEN, CHECK_ACTIVITY,
|
||||||
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
CHECK_UPDATES, SWAP_DATE_TIME_FORMAT_ENABLED, PREF_ENABLE_DM_NOTIFICATIONS, PREF_ENABLE_DM_AUTO_REFRESH,
|
||||||
FLAG_SECURE})
|
FLAG_SECURE, PREF_ENABLE_SENTRY})
|
||||||
public @interface BooleanSettings {}
|
public @interface BooleanSettings {}
|
||||||
|
|
||||||
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
@StringDef({PREV_INSTALL_VERSION, BROWSER_UA_CODE, APP_UA_CODE, PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER})
|
||||||
|
@ -1,50 +1,35 @@
|
|||||||
package awaisomereport;
|
package awaisomereport;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Process;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.FileProvider;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.Date;
|
|
||||||
//import java.util.zip.ZipEntry;
|
|
||||||
//import java.util.zip.ZipOutputStream;
|
|
||||||
|
|
||||||
import awais.instagrabber.BuildConfig;
|
|
||||||
import awais.instagrabber.utils.Utils;
|
|
||||||
|
|
||||||
public final class CrashReporter implements Thread.UncaughtExceptionHandler {
|
public final class CrashReporter implements Thread.UncaughtExceptionHandler {
|
||||||
|
private static final String TAG = CrashReporter.class.getSimpleName();
|
||||||
|
|
||||||
private static CrashReporter reporterInstance;
|
private static CrashReporter reporterInstance;
|
||||||
private final Application application;
|
|
||||||
private final String email;
|
|
||||||
// private final File crashLogsZip;
|
// private final File crashLogsZip;
|
||||||
|
private final CrashHandler crashHandler;
|
||||||
|
|
||||||
private boolean startAttempted = false;
|
private boolean startAttempted = false;
|
||||||
|
private Thread.UncaughtExceptionHandler defaultEH;
|
||||||
|
|
||||||
public static CrashReporter get(final Application application) {
|
public static CrashReporter get(final Application application) {
|
||||||
if (reporterInstance == null) reporterInstance = new CrashReporter(application);
|
if (reporterInstance == null) {
|
||||||
|
reporterInstance = new CrashReporter(application);
|
||||||
|
}
|
||||||
return reporterInstance;
|
return reporterInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CrashReporter(@NonNull final Application application) {
|
private CrashReporter(@NonNull final Application application) {
|
||||||
this.application = application;
|
crashHandler = new CrashHandler(application);
|
||||||
this.email = "barinsta@austinhuang.me";
|
|
||||||
// this.crashLogsZip = new File(application.getExternalCacheDir(), "crash_logs.zip");
|
// this.crashLogsZip = new File(application.getExternalCacheDir(), "crash_logs.zip");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
if (!startAttempted) {
|
if (!startAttempted) {
|
||||||
|
defaultEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||||
startAttempted = true;
|
startAttempted = true;
|
||||||
}
|
}
|
||||||
@ -52,140 +37,10 @@ public final class CrashReporter implements Thread.UncaughtExceptionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException(@NonNull final Thread t, @NonNull final Throwable exception) {
|
public void uncaughtException(@NonNull final Thread t, @NonNull final Throwable exception) {
|
||||||
final StringBuilder reportBuilder = new StringBuilder();
|
if (crashHandler == null) {
|
||||||
reportBuilder.append("IMPORTANT: If sending by email, your email address and the entire content will be made public on GitHub issues.");
|
defaultEH.uncaughtException(t, exception);
|
||||||
reportBuilder.append("\r\nIMPORTANT: When possible, please describe the steps leading to this crash. Thank you for your cooperation.");
|
return;
|
||||||
reportBuilder.append("\r\n\r\nError report collected on: ").append(new Date().toString());
|
}
|
||||||
|
crashHandler.uncaughtException(t, exception, defaultEH);
|
||||||
reportBuilder
|
|
||||||
.append("\r\n\r\nInformation:\r\n==============")
|
|
||||||
.append("\r\nVERSION : ").append(BuildConfig.VERSION_NAME)
|
|
||||||
.append("\r\nVERSION_CODE : ").append(BuildConfig.VERSION_CODE)
|
|
||||||
.append("\r\nPHONE-MODEL : ").append(Build.MODEL)
|
|
||||||
.append("\r\nANDROID_VERS : ").append(Build.VERSION.RELEASE)
|
|
||||||
.append("\r\nANDROID_REL : ").append(Build.VERSION.SDK_INT)
|
|
||||||
.append("\r\nBRAND : ").append(Build.BRAND)
|
|
||||||
.append("\r\nMANUFACTURER : ").append(Build.MANUFACTURER)
|
|
||||||
.append("\r\nBOARD : ").append(Build.BOARD)
|
|
||||||
.append("\r\nDEVICE : ").append(Build.DEVICE)
|
|
||||||
.append("\r\nPRODUCT : ").append(Build.PRODUCT)
|
|
||||||
.append("\r\nHOST : ").append(Build.HOST)
|
|
||||||
.append("\r\nTAGS : ").append(Build.TAGS);
|
|
||||||
|
|
||||||
reportBuilder.append("\r\n\r\nStack:\r\n==============\r\n");
|
|
||||||
final Writer result = new StringWriter();
|
|
||||||
try (final PrintWriter printWriter = new PrintWriter(result)) {
|
|
||||||
exception.printStackTrace(printWriter);
|
|
||||||
reportBuilder.append(result.toString());
|
|
||||||
|
|
||||||
reportBuilder.append("\r\nCause:\r\n==============");
|
|
||||||
|
|
||||||
// for AsyncTask crashes
|
|
||||||
Throwable cause = exception.getCause();
|
|
||||||
while (cause != null) {
|
|
||||||
cause.printStackTrace(printWriter);
|
|
||||||
reportBuilder.append(result.toString());
|
|
||||||
cause = cause.getCause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reportBuilder.append("\r\n\r\n**** End of current Report ***");
|
|
||||||
|
|
||||||
final String errorContent = reportBuilder.toString();
|
|
||||||
try (final FileOutputStream trace = application.openFileOutput("stack-" + System.currentTimeMillis() + ".stacktrace", Context.MODE_PRIVATE)) {
|
|
||||||
trace.write(errorContent.getBytes());
|
|
||||||
} catch (final Exception ex) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
application.startActivity(new Intent(application, ErrorReporterActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
|
||||||
|
|
||||||
// zipLogs();
|
|
||||||
|
|
||||||
Process.killProcess(Process.myPid());
|
|
||||||
System.exit(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// public synchronized CrashReporter zipLogs() {
|
|
||||||
// final File logDir = Utils.logCollector != null ? Utils.logCollector.getLogDir() :
|
|
||||||
// new File(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? application.getDataDir() : application.getFilesDir(), "crashlogs");
|
|
||||||
//
|
|
||||||
// try (final FileOutputStream fos = new FileOutputStream(crashLogsZip);
|
|
||||||
// final ZipOutputStream zos = new ZipOutputStream(fos)) {
|
|
||||||
//
|
|
||||||
// final File[] files = logDir.listFiles();
|
|
||||||
//
|
|
||||||
// if (files != null) {
|
|
||||||
// zos.setLevel(5);
|
|
||||||
// byte[] buffer;
|
|
||||||
// for (final File file : files) {
|
|
||||||
// if (file != null && file.length() > 0) {
|
|
||||||
// buffer = new byte[1024];
|
|
||||||
// try (final FileInputStream fis = new FileInputStream(file)) {
|
|
||||||
// zos.putNextEntry(new ZipEntry(file.getName()));
|
|
||||||
// int length;
|
|
||||||
// while ((length = fis.read(buffer)) > 0) zos.write(buffer, 0, length);
|
|
||||||
// zos.closeEntry();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// } catch (final Exception e) {
|
|
||||||
// if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return this;
|
|
||||||
// }
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
public void startCrashEmailIntent(final Context context) {
|
|
||||||
try {
|
|
||||||
final String filePath = context.getFilesDir().getAbsolutePath();
|
|
||||||
|
|
||||||
String[] errorFileList;
|
|
||||||
|
|
||||||
try {
|
|
||||||
final File dir = new File(filePath);
|
|
||||||
if (dir.exists() && !dir.isDirectory()) dir.delete();
|
|
||||||
dir.mkdir();
|
|
||||||
errorFileList = dir.list((d, name) -> name.endsWith(".stacktrace"));
|
|
||||||
} catch (final Exception e) {
|
|
||||||
errorFileList = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorFileList != null && errorFileList.length > 0) {
|
|
||||||
final StringBuilder errorStringBuilder;
|
|
||||||
|
|
||||||
errorStringBuilder = new StringBuilder("\r\n\r\n");
|
|
||||||
final int maxSendMail = 5;
|
|
||||||
|
|
||||||
int curIndex = 0;
|
|
||||||
for (final String curString : errorFileList) {
|
|
||||||
final File file = new File(filePath + '/' + curString);
|
|
||||||
|
|
||||||
if (curIndex++ <= maxSendMail) {
|
|
||||||
errorStringBuilder.append("New Trace collected:\r\n=====================\r\n");
|
|
||||||
try (final BufferedReader input = new BufferedReader(new FileReader(file))) {
|
|
||||||
String line;
|
|
||||||
while ((line = input.readLine()) != null)
|
|
||||||
errorStringBuilder.append(line).append("\r\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorStringBuilder.append("\r\n\r\n");
|
|
||||||
|
|
||||||
context.startActivity(Intent.createChooser(new Intent(Intent.ACTION_SEND).setType("message/rfc822")
|
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
|
||||||
.putExtra(Intent.EXTRA_EMAIL, new String[]{email})
|
|
||||||
// .putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(application, BuildConfig.APPLICATION_ID + ".provider", crashLogsZip))
|
|
||||||
.putExtra(Intent.EXTRA_SUBJECT, "Barinsta Crash Report")
|
|
||||||
.putExtra(Intent.EXTRA_TEXT, errorStringBuilder.toString()), "Select an email app to send crash logs"));
|
|
||||||
}
|
|
||||||
} catch (final Exception e) {
|
|
||||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
134
app/src/main/java/awaisomereport/CrashReporterHelper.java
Normal file
134
app/src/main/java/awaisomereport/CrashReporterHelper.java
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package awaisomereport;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import awais.instagrabber.BuildConfig;
|
||||||
|
import awais.instagrabber.R;
|
||||||
|
import awais.instagrabber.utils.Constants;
|
||||||
|
|
||||||
|
public final class CrashReporterHelper {
|
||||||
|
private static final String TAG = CrashReporterHelper.class.getSimpleName();
|
||||||
|
|
||||||
|
public static void startErrorReporterActivity(@NonNull final Application application,
|
||||||
|
@NonNull final Throwable exception) {
|
||||||
|
final StringBuilder reportBuilder = new StringBuilder();
|
||||||
|
reportBuilder.append("IMPORTANT: If sending by email, your email address and the entire content will be made public on GitHub issues.")
|
||||||
|
.append("\r\nIMPORTANT: When possible, please describe the steps leading to this crash. Thank you for your cooperation.")
|
||||||
|
.append("\r\n\r\nError report collected on: ").append(new Date().toString())
|
||||||
|
.append("\r\n\r\nInformation:\r\n==============")
|
||||||
|
.append("\r\nVERSION : ").append(BuildConfig.VERSION_NAME)
|
||||||
|
.append("\r\nVERSION_CODE : ").append(BuildConfig.VERSION_CODE)
|
||||||
|
.append("\r\nPHONE-MODEL : ").append(Build.MODEL)
|
||||||
|
.append("\r\nANDROID_VERS : ").append(Build.VERSION.RELEASE)
|
||||||
|
.append("\r\nANDROID_REL : ").append(Build.VERSION.SDK_INT)
|
||||||
|
.append("\r\nBRAND : ").append(Build.BRAND)
|
||||||
|
.append("\r\nMANUFACTURER : ").append(Build.MANUFACTURER)
|
||||||
|
.append("\r\nBOARD : ").append(Build.BOARD)
|
||||||
|
.append("\r\nDEVICE : ").append(Build.DEVICE)
|
||||||
|
.append("\r\nPRODUCT : ").append(Build.PRODUCT)
|
||||||
|
.append("\r\nHOST : ").append(Build.HOST)
|
||||||
|
.append("\r\nTAGS : ").append(Build.TAGS);
|
||||||
|
|
||||||
|
reportBuilder.append("\r\n\r\nStack:\r\n==============\r\n");
|
||||||
|
final Writer result = new StringWriter();
|
||||||
|
try (final PrintWriter printWriter = new PrintWriter(result)) {
|
||||||
|
exception.printStackTrace(printWriter);
|
||||||
|
reportBuilder.append(result.toString());
|
||||||
|
reportBuilder.append("\r\nCause:\r\n==============");
|
||||||
|
// for AsyncTask crashes
|
||||||
|
Throwable cause = exception.getCause();
|
||||||
|
while (cause != null) {
|
||||||
|
cause.printStackTrace(printWriter);
|
||||||
|
reportBuilder.append(result.toString());
|
||||||
|
cause = cause.getCause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reportBuilder.append("\r\n\r\n**** End of current Report ***");
|
||||||
|
|
||||||
|
final String errorContent = reportBuilder.toString();
|
||||||
|
try (final FileOutputStream trace = application.openFileOutput("stack-" + System.currentTimeMillis() + ".stacktrace", Context.MODE_PRIVATE)) {
|
||||||
|
trace.write(errorContent.getBytes());
|
||||||
|
} catch (final Exception ex) {
|
||||||
|
if (BuildConfig.DEBUG) Log.e(TAG, "", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
application.startActivity(new Intent(application, ErrorReporterActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startCrashEmailIntent(final Context context) {
|
||||||
|
try {
|
||||||
|
final String filePath = context.getFilesDir().getAbsolutePath();
|
||||||
|
|
||||||
|
String[] errorFileList;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final File dir = new File(filePath);
|
||||||
|
if (dir.exists() && !dir.isDirectory()) {
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
dir.delete();
|
||||||
|
}
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
dir.mkdirs();
|
||||||
|
errorFileList = dir.list((d, name) -> name.endsWith(".stacktrace"));
|
||||||
|
} catch (final Exception e) {
|
||||||
|
errorFileList = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorFileList == null || errorFileList.length <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final StringBuilder errorStringBuilder;
|
||||||
|
|
||||||
|
errorStringBuilder = new StringBuilder("\r\n\r\n");
|
||||||
|
final int maxSendMail = 5;
|
||||||
|
int curIndex = 0;
|
||||||
|
for (final String curString : errorFileList) {
|
||||||
|
final File file = new File(filePath + '/' + curString);
|
||||||
|
|
||||||
|
if (curIndex++ <= maxSendMail) {
|
||||||
|
errorStringBuilder.append("New Trace collected:\r\n=====================\r\n");
|
||||||
|
try (final BufferedReader input = new BufferedReader(new FileReader(file))) {
|
||||||
|
String line;
|
||||||
|
while ((line = input.readLine()) != null)
|
||||||
|
errorStringBuilder.append(line).append("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorStringBuilder.append("\r\n\r\n");
|
||||||
|
final Resources resources = context.getResources();
|
||||||
|
context.startActivity(Intent.createChooser(
|
||||||
|
new Intent(Intent.ACTION_SEND)
|
||||||
|
.setType("message/rfc822")
|
||||||
|
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
| Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
.putExtra(Intent.EXTRA_EMAIL, new String[]{Constants.CRASH_REPORT_EMAIL})
|
||||||
|
// .putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(application, BuildConfig.APPLICATION_ID + ".provider", crashLogsZip))
|
||||||
|
.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.crash_report_subject))
|
||||||
|
.putExtra(Intent.EXTRA_TEXT, errorStringBuilder.toString()),
|
||||||
|
context.getResources().getString(R.string.crash_report_title))
|
||||||
|
);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
Log.e(TAG, "", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -43,8 +43,9 @@ public final class ErrorReporterActivity extends Activity implements View.OnClic
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NonNull final View v) {
|
public void onClick(@NonNull final View v) {
|
||||||
if (v == btnReport)
|
if (v == btnReport) {
|
||||||
CrashReporter.get(getApplication()).startCrashEmailIntent(this);
|
CrashReporterHelper.startCrashEmailIntent(this);
|
||||||
|
}
|
||||||
finish();
|
finish();
|
||||||
System.exit(10);
|
System.exit(10);
|
||||||
}
|
}
|
||||||
|
7
app/src/main/java/awaisomereport/ICrashHandler.java
Normal file
7
app/src/main/java/awaisomereport/ICrashHandler.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package awaisomereport;
|
||||||
|
|
||||||
|
public interface ICrashHandler {
|
||||||
|
void uncaughtException(Thread t,
|
||||||
|
Throwable exception,
|
||||||
|
Thread.UncaughtExceptionHandler defaultEH);
|
||||||
|
}
|
@ -468,4 +468,9 @@
|
|||||||
<string name="generic_failed_request">Request failed!</string>
|
<string name="generic_failed_request">Request failed!</string>
|
||||||
<string name="marked_as_seen">Marked as seen</string>
|
<string name="marked_as_seen">Marked as seen</string>
|
||||||
<string name="delete_unsuccessful">Delete unsuccessful</string>
|
<string name="delete_unsuccessful">Delete unsuccessful</string>
|
||||||
|
<string name="crash_report_subject">Barinsta Crash Report</string>
|
||||||
|
<string name="crash_report_title">Select an email app to send crash logs</string>
|
||||||
|
<string name="enable_sentry">Enable Sentry</string>
|
||||||
|
<string name="sentry_summary">Sentry is a listener/handler for errors that asynchronously sends out the error/event to Sentry.io</string>
|
||||||
|
<string name="sentry_start_next_launch">Sentry will start on next launch</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user