Replace with ACRA bug reporter.

This commit is contained in:
Amine Bou 2018-05-21 21:39:23 +02:00
parent 9f94af6239
commit 218b8fa843
13 changed files with 129 additions and 38 deletions

View File

@ -38,6 +38,10 @@ repositories {
} }
android { android {
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
compileSdkVersion 27 compileSdkVersion 27
buildToolsVersion '27.0.3' buildToolsVersion '27.0.3'
defaultConfig { defaultConfig {
@ -164,6 +168,10 @@ dependencies {
implementation 'androidx.core:core-ktx:0.3' implementation 'androidx.core:core-ktx:0.3'
// Crash
implementation "ch.acra:acra-http:5.1.3"
implementation "ch.acra:acra-dialog:5.1.3"
} }

View File

@ -1,12 +1,10 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v4.view.MenuItemCompat import android.support.v4.view.MenuItemCompat
@ -164,6 +162,27 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
handleDrawer() handleDrawer()
handleSwipeRefreshLayout() handleSwipeRefreshLayout()
throw NullPointerException()
}
private fun handleGDPRDialog(GDPRShown: Boolean) {
if (!GDPRShown) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle(getString(R.string.gdpr_dialog_title))
alertDialog.setMessage(getString(R.string.gdpr_dialog_message))
alertDialog.setButton(
AlertDialog.BUTTON_NEUTRAL,
"OK",
{ dialog, _ ->
editor.putBoolean("GDPR_shown", true)
editor.commit()
dialog.dismiss()
}
)
alertDialog.show()
}
} }
private fun handleSwipeRefreshLayout() { private fun handleSwipeRefreshLayout() {
@ -339,6 +358,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
handleBottomBarActions() handleBottomBarActions()
getElementsAccordingToTab() getElementsAccordingToTab()
handleGDPRDialog(sharedPref.getBoolean("GDPR_shown", false))
} }
override fun onStop() { override fun onStop() {
@ -417,7 +438,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
) )
.theme(R.style.Theme_App_Light) .theme(R.style.Theme_App_Light)
.guestToken(BuildConfig.GITHUB_TOKEN) .guestToken(BuildConfig.GITHUB_TOKEN)
.guestEmailRequired(true)
.minDescriptionLength(20) .minDescriptionLength(20)
.putExtraInfo("Unique ID", settings.getString("unique_id", "")) .putExtraInfo("Unique ID", settings.getString("unique_id", ""))
.putExtraInfo("From github", BuildConfig.GITHUB_VERSION) .putExtraInfo("From github", BuildConfig.GITHUB_VERSION)

View File

@ -23,6 +23,7 @@ import apps.amine.bou.readerforselfoss.utils.isBaseUrlValid
import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.activity_login.*
import org.acra.ACRA
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -208,7 +209,7 @@ class LoginActivity : AppCompatActivity() {
httpLoginView.error = getString(R.string.wrong_infos) httpLoginView.error = getString(R.string.wrong_infos)
httpPasswordView.error = getString(R.string.wrong_infos) httpPasswordView.error = getString(R.string.wrong_infos)
if (logErrors) { if (logErrors) {
// TODO: log ACRA.getErrorReporter().handleSilentException(t)
Toast.makeText( Toast.makeText(
this@LoginActivity, this@LoginActivity,
t.message, t.message,

View File

@ -1,6 +1,7 @@
package apps.amine.bou.readerforselfoss package apps.amine.bou.readerforselfoss
import android.content.Context import android.content.Context
import android.content.SharedPreferences
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.preference.PreferenceManager import android.preference.PreferenceManager
@ -16,9 +17,31 @@ import com.github.stkent.amplify.feedback.GooglePlayStoreFeedbackCollector
import com.github.stkent.amplify.tracking.Amplify import com.github.stkent.amplify.tracking.Amplify
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
import com.mikepenz.materialdrawer.util.DrawerImageLoader import com.mikepenz.materialdrawer.util.DrawerImageLoader
import org.acra.ACRA
import org.acra.ReportField
import org.acra.annotation.AcraCore
import org.acra.annotation.AcraDialog
import org.acra.annotation.AcraHttpSender
import org.acra.sender.HttpSender
import java.io.IOException import java.io.IOException
import java.util.UUID.randomUUID import java.util.UUID.randomUUID
@AcraHttpSender(uri = "http://amine-bou.fr:5984/acra-selfoss/_design/acra-storage/_update/report",
basicAuthLogin = "selfoss",
basicAuthPassword = "selfoss",
httpMethod = HttpSender.Method.PUT)
@AcraDialog(resText = R.string.crash_dialog_text,
resCommentPrompt = R.string.crash_dialog_comment,
resTheme = android.R.style.Theme_DeviceDefault_Dialog)
@AcraCore(reportContent = [ReportField.REPORT_ID, ReportField.INSTALLATION_ID,
ReportField.APP_VERSION_CODE, ReportField.APP_VERSION_NAME,
ReportField.BUILD, ReportField.ANDROID_VERSION, ReportField.BRAND, ReportField.PHONE_MODEL,
ReportField.AVAILABLE_MEM_SIZE, ReportField.TOTAL_MEM_SIZE,
ReportField.STACK_TRACE, ReportField.APPLICATION_LOG, ReportField.LOGCAT,
ReportField.INITIAL_CONFIGURATION, ReportField.CRASH_CONFIGURATION, ReportField.IS_SILENT,
ReportField.USER_APP_START_DATE, ReportField.USER_COMMENT, ReportField.USER_CRASH_DATE, ReportField.USER_EMAIL, ReportField.CUSTOM_DATA],
buildConfigClass = BuildConfig::class)
class MyApp : MultiDexApplication() { class MyApp : MultiDexApplication() {
override fun onCreate() { override fun onCreate() {
@ -42,6 +65,14 @@ class MyApp : MultiDexApplication() {
tryToHandleBug() tryToHandleBug()
} }
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
val prefs = getSharedPreferences(Config.settingsName, Context.MODE_PRIVATE)
ACRA.init(this)
ACRA.getErrorReporter().putCustomData("unique_id", prefs.getString("unique_id", ""))
}
private fun initAmplify() { private fun initAmplify() {
Amplify.initSharedInstance(this) Amplify.initSharedInstance(this)
.setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector()) .setPositiveFeedbackCollectors(GooglePlayStoreFeedbackCollector())

View File

@ -27,6 +27,7 @@ import apps.amine.bou.readerforselfoss.utils.toggleStar
import com.ftinc.scoop.Scoop import com.ftinc.scoop.Scoop
import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.*
import me.relex.circleindicator.CircleIndicator import me.relex.circleindicator.CircleIndicator
import org.acra.ACRA
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -131,7 +132,7 @@ class ReaderActivity : AppCompatActivity() {
"response errorBody: ${response.errorBody()?.string()} " + "response errorBody: ${response.errorBody()?.string()} " +
"body success: ${response.body()?.success} " + "body success: ${response.body()?.success} " +
"body isSuccess: ${response.body()?.isSuccess}" "body isSuccess: ${response.body()?.isSuccess}"
// TODO: logs ACRA.getErrorReporter().handleSilentException(Exception(message))
} }
} }
@ -140,7 +141,7 @@ class ReaderActivity : AppCompatActivity() {
t: Throwable t: Throwable
) { ) {
if (debugReadingItems) { if (debugReadingItems) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(t)
} }
} }
} }

View File

@ -89,7 +89,7 @@ class ItemCardAdapter(
TextDrawable TextDrawable
.builder() .builder()
.round() .round()
.build(itm.sourcetitle.toTextDrawableString(), color) .build(itm.sourcetitle.toTextDrawableString(c), color)
holder.mView.sourceImage.setImageDrawable(drawable) holder.mView.sourceImage.setImageDrawable(drawable)
} else { } else {
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.sourceImage) c.circularBitmapDrawable(itm.getIcon(c), holder.mView.sourceImage)

View File

@ -97,7 +97,7 @@ class ItemListAdapter(
TextDrawable TextDrawable
.builder() .builder()
.round() .round()
.build(itm.sourcetitle.toTextDrawableString(), color) .build(itm.sourcetitle.toTextDrawableString(c), color)
holder.mView.itemImage.setImageDrawable(drawable) holder.mView.itemImage.setImageDrawable(drawable)
} else { } else {

View File

@ -12,6 +12,7 @@ import apps.amine.bou.readerforselfoss.api.selfoss.SelfossApi
import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse import apps.amine.bou.readerforselfoss.api.selfoss.SuccessResponse
import apps.amine.bou.readerforselfoss.themes.AppColors import apps.amine.bou.readerforselfoss.themes.AppColors
import apps.amine.bou.readerforselfoss.utils.succeeded import apps.amine.bou.readerforselfoss.utils.succeeded
import org.acra.ACRA
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -88,7 +89,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
"response errorBody: ${response.errorBody()?.string()} " + "response errorBody: ${response.errorBody()?.string()} " +
"body success: ${response.body()?.success} " + "body success: ${response.body()?.success} " +
"body isSuccess: ${response.body()?.isSuccess}" "body isSuccess: ${response.body()?.isSuccess}"
// TODO: logs ACRA.getErrorReporter().handleSilentException(Exception(message))
Toast.makeText(app.baseContext, message, Toast.LENGTH_LONG).show() Toast.makeText(app.baseContext, message, Toast.LENGTH_LONG).show()
} }
doUnmark(i, position) doUnmark(i, position)
@ -96,7 +97,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
override fun onFailure(call: Call<SuccessResponse>, t: Throwable) { override fun onFailure(call: Call<SuccessResponse>, t: Throwable) {
if (debugReadingItems) { if (debugReadingItems) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(t)
Toast.makeText(app.baseContext, t.message, Toast.LENGTH_LONG).show() Toast.makeText(app.baseContext, t.message, Toast.LENGTH_LONG).show()
} }
Toast.makeText( Toast.makeText(

View File

@ -48,7 +48,7 @@ class SourcesListAdapter(
TextDrawable TextDrawable
.builder() .builder()
.round() .round()
.build(itm.title.toTextDrawableString(), color) .build(itm.title.toTextDrawableString(c), color)
holder.mView.itemImage.setImageDrawable(drawable) holder.mView.itemImage.setImageDrawable(drawable)
} else { } else {
c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage) c.circularBitmapDrawable(itm.getIcon(c), holder.mView.itemImage)

View File

@ -37,6 +37,7 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.github.rubensousa.floatingtoolbar.FloatingToolbar import com.github.rubensousa.floatingtoolbar.FloatingToolbar
import kotlinx.android.synthetic.main.fragment_article.view.* import kotlinx.android.synthetic.main.fragment_article.view.*
import org.acra.ACRA
import retrofit2.Call import retrofit2.Call
import retrofit2.Callback import retrofit2.Callback
import retrofit2.Response import retrofit2.Response
@ -195,13 +196,13 @@ class ArticleFragment : Fragment() {
rootView.titleView.text = response.body()!!.title rootView.titleView.text = response.body()!!.title
url = response.body()!!.url url = response.body()!!.url
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
try { try {
htmlToWebview(response.body()!!.content.orEmpty(), prefs, context) htmlToWebview(response.body()!!.content.orEmpty(), prefs, context)
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
try { try {
@ -215,13 +216,13 @@ class ArticleFragment : Fragment() {
.apply(RequestOptions.fitCenterTransform()) .apply(RequestOptions.fitCenterTransform())
.into(rootView.imageView) .into(rootView.imageView)
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
} else { } else {
rootView.imageView.visibility = View.GONE rootView.imageView.visibility = View.GONE
} }
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
try { try {
@ -229,17 +230,17 @@ class ArticleFragment : Fragment() {
rootView.progressBar.visibility = View.GONE rootView.progressBar.visibility = View.GONE
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
} else { } else {
try { try {
openInBrowserAfterFailing(customTabsIntent) openInBrowserAfterFailing(customTabsIntent)
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
} }

View File

@ -1,18 +1,20 @@
package apps.amine.bou.readerforselfoss.utils package apps.amine.bou.readerforselfoss.utils
import android.content.Context
import android.text.format.DateUtils import android.text.format.DateUtils
import apps.amine.bou.readerforselfoss.api.selfoss.Item import apps.amine.bou.readerforselfoss.api.selfoss.Item
import org.acra.ACRA
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
fun String.toTextDrawableString(): String { fun String.toTextDrawableString(c: Context): String {
val textDrawable = StringBuilder() val textDrawable = StringBuilder()
for (s in this.split(" ".toRegex()).filter { !it.isEmpty() }.toTypedArray()) { for (s in this.split(" ".toRegex()).filter { !it.isEmpty() }.toTypedArray()) {
try { try {
textDrawable.append(s[0]) textDrawable.append(s[0])
} catch (e: StringIndexOutOfBoundsException) { } catch (e: StringIndexOutOfBoundsException) {
// TODO: logs ACRA.getErrorReporter().handleSilentException(e)
} }
} }
return textDrawable.toString() return textDrawable.toString()

View File

@ -157,4 +157,15 @@
<string name="markall_dialog_message">This will mark all the items as read.</string> <string name="markall_dialog_message">This will mark all the items as read.</string>
<string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string> <string name="pref_switch_actions_pager_scroll">Mark as read on swipe</string>
<string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string> <string name="pref_switch_actions_pager_scroll_off">Don\'t mark articles as read when swiping.</string>
<string name="gdpr_dialog_message">The app does not collect any personal data. Every analytics tools were removed. Crash reports sending is now optional, as is the debug logging. Keep in mind that debugging and crash reports are essential for the app development (You can configure everything in Settings > Debug).</string>
<string name="gdpr_dialog_title">The app does not share any personal data about you.</string>
<string name="crash_dialog_text">Something went wrong. Please send the report to the developer.</string>
<string name="crash_dialog_comment">You can add any helpful details in the comment bellow.</string>
<string name="pref_acra_user_email">Contact email</string>
<string name="pref_acra_user_email_summary">Add an email so I can contact you about the crash reports you send.</string>
<string name="pref_acra_alwaysaccept">Automatically send crash reports</string>
<string name="pref_acra_alwaysaccept_enabled">Will send crash reports automatically</string>
<string name="pref_acra_alwaysaccept_disabled">Will ask everytime when sending crash reports.</string>
<string name="pref_debug_crash_reports">Crash reports</string>
<string name="pref_debug_debug_logs">Debug logging (these will be sent without a dialog)</string>
</resources> </resources>

View File

@ -1,27 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/pref_debug_crash_reports">
<EditTextPreference
android:key="acra.user.email"
android:summary="@string/pref_acra_user_email_summary"
android:title="@string/pref_acra_user_email" />
<CheckBoxPreference
android:defaultValue="false"
android:key="acra.alwaysaccept"
android:summaryOff="@string/pref_acra_alwaysaccept_disabled"
android:summaryOn="@string/pref_acra_alwaysaccept_enabled"
android:title="@string/pref_acra_alwaysaccept" />
</PreferenceCategory>
<PreferenceCategory>
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="should_log_everything" android:key="should_log_everything"
android:summaryOff="@string/login_everything_off" android:summaryOff="@string/login_everything_off"
android:summaryOn="@string/login_everything_on" android:summaryOn="@string/login_everything_on"
android:title="@string/login_everything_title" /> android:title="@string/login_everything_title" />
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="login_debug" android:key="login_debug"
android:summaryOff="@string/login_debug_off" android:summaryOff="@string/login_debug_off"
android:summaryOn="@string/login_debug_on" android:summaryOn="@string/login_debug_on"
android:title="@string/login_debug_title" /> android:title="@string/login_debug_title" />
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="read_debug" android:key="read_debug"
android:summaryOff="@string/read_debug_off" android:summaryOff="@string/read_debug_off"
android:summaryOn="@string/read_debug_on" android:summaryOn="@string/read_debug_on"
android:title="@string/read_debug_title" /> android:title="@string/read_debug_title" />
</PreferenceCategory>
<Preference <Preference
android:enabled="true" android:enabled="true"