Skip to content
This repository has been archived by the owner on Sep 25, 2021. It is now read-only.

Commit

Permalink
add crash reporting
Browse files Browse the repository at this point in the history
reports crashes with acra to an instance of acralyzer.
a new setting controls the usage of it.
required some workarounds for the application class.
include the default proguard file, includes some other proguard rules
acra requires (and is cleaner anyway).

closes #390
  • Loading branch information
floens committed Jan 14, 2018
1 parent fef2187 commit f022269
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 12 deletions.
7 changes: 6 additions & 1 deletion Clover/app/build.gradle
Expand Up @@ -78,6 +78,7 @@ android {
resValue "string", "app_name", "Clover"
resValue "string", "app_flavor_name", ""
buildConfigField "String", "UPDATE_API_ENDPOINT", "\"https://floens.github.io/Clover/api/update\""
buildConfigField "String", "CRASH_REPORT_ENDPOINT", "\"https://acra.floens.org/clover/report\""
}

dev {
Expand All @@ -86,6 +87,7 @@ android {
resValue "string", "app_name", "Clover dev"
resValue "string", "app_flavor_name", ""
buildConfigField "String", "UPDATE_API_ENDPOINT", "\"\""
buildConfigField "String", "CRASH_REPORT_ENDPOINT", "\"\""
}

fdroid {
Expand All @@ -94,6 +96,7 @@ android {
resValue "string", "app_name", "Clover"
resValue "string", "app_flavor_name", "F-Droid"
buildConfigField "String", "UPDATE_API_ENDPOINT", "\"https://floens.github.io/Clover/api/update\""
buildConfigField "String", "CRASH_REPORT_ENDPOINT", "\"https://acra.floens.org/clover/report\""
}
}

Expand All @@ -103,7 +106,7 @@ android {
signingConfig signingConfigs.release
}
minifyEnabled true
proguardFiles 'proguard.cfg'
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
}

debug {
Expand Down Expand Up @@ -141,4 +144,6 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.1'
implementation 'me.xdrop:fuzzywuzzy:1.1.9'
implementation 'org.codejargon.feather:feather:1.0'

releaseImplementation 'ch.acra:acra-http:5.0.1'
}
13 changes: 12 additions & 1 deletion Clover/app/proguard.cfg
Expand Up @@ -110,4 +110,15 @@
-keep public class android.support.v7.widget.RecyclerView
-keep public class android.support.v4.widget.SlidingPaneLayout

-dontwarn dagger.internal.**
# Keep Feather inject working.
-keepclassmembers,allowobfuscation class * {
@javax.inject.* *;
<init>();
}

# ACRA stuff
# ACRA loads Plugins using reflection, so we need to keep all Plugin classes
-keep class * extends @android.support.annotation.Keep org.acra.** {*;}

# ACRA uses enum fields in annotations, so we have to keep those
-keep enum org.acra.** {*;}
Expand Up @@ -17,5 +17,16 @@
*/
package org.floens.chan;

/**
* The ChanApplication belonging to the debug configuration.
*
* It does not have acra enabled, unlike the release version, and immediately calls initialize.
*/
public class ChanApplication extends Chan {
@Override
public void onCreate() {
super.onCreate();

initialize();
}
}
13 changes: 9 additions & 4 deletions Clover/app/src/main/java/org/floens/chan/Chan.java
Expand Up @@ -20,6 +20,7 @@
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
Expand All @@ -41,6 +42,7 @@

import de.greenrobot.event.EventBus;

@SuppressLint("Registered") // extended by ChanApplication, which is registered in the manifest.
public class Chan extends Application implements UserAgentProvider, Application.ActivityLifecycleCallbacks {
private static final String TAG = "ChanApplication";

Expand All @@ -55,6 +57,7 @@ public class Chan extends Application implements UserAgentProvider, Application.

@Inject
DatabaseManager databaseManager;

private Feather feather;

public Chan() {
Expand All @@ -75,15 +78,17 @@ public static <T> T inject(T instance) {
}

@Override
public void onCreate() {
super.onCreate();
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);

AndroidUtils.init(this);
}

public void initialize() {
final long startTime = Time.startTiming();

registerActivityLifecycleCallbacks(this);

AndroidUtils.init(this);

userAgent = createUserAgent();

initializeGraph();
Expand Down
Expand Up @@ -155,6 +155,8 @@ public String getName() {
public static final LongSetting updateCheckTime;
public static final LongSetting updateCheckInterval;

public static final BooleanSetting crashReporting;

static {
SharedPreferences p = AndroidUtils.getPreferences();

Expand Down Expand Up @@ -238,6 +240,8 @@ public String getName() {
updateCheckTime = new LongSetting(p, "update_check_time", 0L);
updateCheckInterval = new LongSetting(p, "update_check_interval", UpdateManager.DEFAULT_UPDATE_CHECK_INTERVAL_MS);

crashReporting = new BooleanSetting(p, "preference_crash_reporting", true);

// Old (but possibly still in some users phone)
// preference_board_view_mode default "list"
// preference_board_editor_filler default false
Expand Down
Expand Up @@ -29,6 +29,7 @@
import org.floens.chan.core.presenter.SettingsPresenter;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.activity.StartActivity;
import org.floens.chan.ui.settings.BooleanSettingView;
import org.floens.chan.ui.settings.LinkSettingView;
import org.floens.chan.ui.settings.SettingView;
import org.floens.chan.ui.settings.SettingsController;
Expand All @@ -49,6 +50,7 @@ public class MainSettingsController extends SettingsController implements Settin
private SettingView developerView;
private LinkSettingView sitesSetting;
private LinkSettingView filtersSetting;
private SettingView crashReportSetting;

public MainSettingsController(Context context) {
super(context);
Expand Down Expand Up @@ -106,6 +108,15 @@ public void setWatchEnabled(boolean enabled) {
R.string.setting_watch_summary_enabled : R.string.setting_watch_summary_disabled);
}

@Override
public void onPreferenceChange(SettingView item) {
super.onPreferenceChange(item);
if (item == crashReportSetting) {
Toast.makeText(context, R.string.settings_crash_reporting_toggle_notice,
Toast.LENGTH_LONG).show();
}
}

private void populatePreferences() {
// General group
{
Expand Down Expand Up @@ -153,6 +164,11 @@ private void setupAboutGroup() {

setupUpdateSetting(about);

crashReportSetting = about.add(new BooleanSettingView(this,
ChanSettings.crashReporting,
R.string.settings_crash_reporting,
R.string.settings_crash_reporting_description));

setupExtraAboutSettings(about, version);

about.add(new LinkSettingView(this,
Expand Down
18 changes: 12 additions & 6 deletions Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java
Expand Up @@ -75,14 +75,16 @@ public class AndroidUtils {
private static final Handler mainHandler = new Handler(Looper.getMainLooper());

public static void init(Application application) {
AndroidUtils.application = application;
if (AndroidUtils.application == null) {
AndroidUtils.application = application;

ROBOTO_MEDIUM = getTypeface("Roboto-Medium.ttf");
ROBOTO_MEDIUM_ITALIC = getTypeface("Roboto-MediumItalic.ttf");
ROBOTO_CONDENSED_REGULAR = getTypeface("RobotoCondensed-Regular.ttf");
ROBOTO_MEDIUM = getTypeface("Roboto-Medium.ttf");
ROBOTO_MEDIUM_ITALIC = getTypeface("Roboto-MediumItalic.ttf");
ROBOTO_CONDENSED_REGULAR = getTypeface("RobotoCondensed-Regular.ttf");

connectivityManager = (ConnectivityManager)
application.getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager = (ConnectivityManager)
application.getSystemService(Context.CONNECTIVITY_SERVICE);
}
}

public static Resources getRes() {
Expand All @@ -101,6 +103,10 @@ public static SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(application);
}

public static SharedPreferences getPreferences(Application application) {
return PreferenceManager.getDefaultSharedPreferences(application);
}

public static SharedPreferences getPreferences(String name) {
return application.getSharedPreferences(name, Context.MODE_PRIVATE);
}
Expand Down
4 changes: 4 additions & 0 deletions Clover/app/src/main/res/values/strings.xml
Expand Up @@ -421,6 +421,10 @@ Re-enable this permission in the app settings if you permanently disabled it."</
<!-- Main About group -->
<string name="settings_group_about">About</string>
<string name="settings_update_check">Check for updates</string>
<string name="settings_crash_reporting">Report crashes</string>
<string name="settings_crash_reporting_description">Crash reporting creates reports of errors in Clover.
Crash reports do not collect any personally identifiable information.</string>
<string name="settings_crash_reporting_toggle_notice">Setting will be applied on next app start.</string>
<string name="settings_about_license">Released under the GNU GPLv3 license</string>
<string name="settings_about_license_description">Tap to see license</string>
<string name="settings_about_licenses">Open Source Licenses</string>
Expand Down
121 changes: 121 additions & 0 deletions Clover/app/src/release/java/org/floens/chan/ChanApplication.java
@@ -0,0 +1,121 @@
/*
* Clover - 4chan browser https://github.com/Floens/Clover/
* Copyright (C) 2014 Floens
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.floens.chan;

import android.content.Context;

import org.acra.ACRA;
import org.acra.annotation.AcraCore;
import org.acra.annotation.AcraHttpSender;
import org.acra.data.StringFormat;
import org.acra.sender.HttpSender;
import org.floens.chan.core.settings.ChanSettings;

import static org.acra.ReportField.ANDROID_VERSION;
import static org.acra.ReportField.APP_VERSION_CODE;
import static org.acra.ReportField.APP_VERSION_NAME;
import static org.acra.ReportField.AVAILABLE_MEM_SIZE;
import static org.acra.ReportField.BRAND;
import static org.acra.ReportField.BUILD;
import static org.acra.ReportField.BUILD_CONFIG;
import static org.acra.ReportField.LOGCAT;
import static org.acra.ReportField.MEDIA_CODEC_LIST;
import static org.acra.ReportField.PACKAGE_NAME;
import static org.acra.ReportField.PHONE_MODEL;
import static org.acra.ReportField.PRODUCT;
import static org.acra.ReportField.REPORT_ID;
import static org.acra.ReportField.STACK_TRACE;
import static org.acra.ReportField.TOTAL_MEM_SIZE;
import static org.acra.ReportField.USER_APP_START_DATE;
import static org.acra.ReportField.USER_CRASH_DATE;

/**
* The ChanApplication belonging to the release configuration.
* <p>
* It has acra enabled. Acra unfortunately believes it needs to have annotations on our
* application class, which I find really intrusive. We already had ChanApplication pointing to
* Chan, so we now have a debug and release variant of ChanApplication. The real initialization
* is done with the {@link Chan#initialize()} method, which does not get called from acra
* processes.
*/
@AcraCore(
sharedPreferencesName = "acra_preferences",
alsoReportToAndroidFramework = true,
buildConfigClass = BuildConfig.class,
reportFormat = StringFormat.JSON,
reportContent = {
// Required
REPORT_ID,

// What app version
APP_VERSION_CODE,
APP_VERSION_NAME,
PACKAGE_NAME,
BUILD_CONFIG,

// What phone
PHONE_MODEL,
BRAND,
PRODUCT,

// What Android version
ANDROID_VERSION,
BUILD,

// Memory details
TOTAL_MEM_SIZE,
AVAILABLE_MEM_SIZE,

// Useful for webm debugging
MEDIA_CODEC_LIST,

// The error
STACK_TRACE,
LOGCAT,
USER_APP_START_DATE,
USER_CRASH_DATE
}
)
@AcraHttpSender(
httpMethod = HttpSender.Method.PUT,
uri = BuildConfig.CRASH_REPORT_ENDPOINT
)
public class ChanApplication extends Chan {
@Override
public void onCreate() {
super.onCreate();

// Do not initialize again if running from the crash reporting process.
if (!ACRA.isACRASenderServiceProcess()) {
initialize();
}
}

@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);

if (enableAcra()) {
ACRA.init(this);
}
}

private boolean enableAcra() {
return !BuildConfig.CRASH_REPORT_ENDPOINT.isEmpty() && ChanSettings.crashReporting.get();
}
}

0 comments on commit f022269

Please sign in to comment.