Explicitly disable all feedback, dev info and crash reporting.
Addresses https://github.com/zcash/zcash-android-wallet/issues/143 by placing everything behind a user setting that can be enabled in the future by users who want to continue helping us improve the user experience. For the most part, this will just be turned on for internal company releases in order to continue learning and improving the app.
This commit is contained in:
parent
340fb8c993
commit
de69567812
|
@ -5,8 +5,7 @@ apply plugin: 'kotlin-android'
|
|||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
apply plugin: 'io.fabric'
|
||||
apply plugin: 'com.google.firebase.firebase-perf'
|
||||
apply plugin: 'com.google.firebase.crashlytics'
|
||||
//apply plugin: 'com.github.ben-manes.versions'
|
||||
|
||||
archivesBaseName = 'zcash-android-wallet'
|
||||
|
@ -102,10 +101,6 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
crashlytics {
|
||||
enableNdk true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation project(':qrecycler')
|
||||
|
@ -161,9 +156,6 @@ dependencies {
|
|||
|
||||
// Analytics (for dogfooding/crash-reporting/feedback only on internal team builds)
|
||||
implementation Deps.Analytics.CRASHLYTICS
|
||||
implementation Deps.Analytics.CRASHLYTICS_NDK
|
||||
implementation Deps.Analytics.FIREBASE
|
||||
implementation Deps.Analytics.FIREBASE_PERF
|
||||
implementation Deps.Analytics.MIXPANEL
|
||||
|
||||
// Misc.
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
<!-- Firebase options -->
|
||||
<meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="barcode" />
|
||||
<!-- All reporting is opt-in, only -->
|
||||
<meta-data android:name="firebase_crashlytics_collection_enabled" android:value="false" />
|
||||
|
||||
<!-- Mixpanel options -->
|
||||
<meta-data android:name="com.mixpanel.android.MPConfig.AutoShowMixpanelUpdates" android:value="false" />
|
||||
|
|
|
@ -37,7 +37,6 @@ class ZcashWalletApp : Application(), CameraXConfig.Provider {
|
|||
|
||||
override fun onCreate() {
|
||||
Thread.setDefaultUncaughtExceptionHandler(ExceptionReporter(Thread.getDefaultUncaughtExceptionHandler()))
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
creationTime = System.currentTimeMillis()
|
||||
instance = this
|
||||
// Setup handler for uncaught exceptions.
|
||||
|
|
|
@ -2,9 +2,14 @@ package cash.z.ecc.android.di.module
|
|||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import cash.z.ecc.android.ZcashWalletApp
|
||||
import cash.z.ecc.android.di.component.MainActivitySubcomponent
|
||||
import cash.z.ecc.android.feedback.*
|
||||
import cash.z.ecc.android.sdk.ext.SilentTwig
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.IntoSet
|
||||
|
@ -27,6 +32,11 @@ class AppModule {
|
|||
// Feedback
|
||||
//
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePreferences(context: Context): SharedPreferences
|
||||
= context.getSharedPreferences("Application", Context.MODE_PRIVATE)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideFeedback(): Feedback = Feedback()
|
||||
|
@ -35,8 +45,16 @@ class AppModule {
|
|||
@Singleton
|
||||
fun provideFeedbackCoordinator(
|
||||
feedback: Feedback,
|
||||
preferences: SharedPreferences,
|
||||
defaultObservers: Set<@JvmSuppressWildcards FeedbackCoordinator.FeedbackObserver>
|
||||
): FeedbackCoordinator = FeedbackCoordinator(feedback, defaultObservers)
|
||||
): FeedbackCoordinator {
|
||||
return preferences.getBoolean(FeedbackCoordinator.ENABLED, false).let { isEnabled ->
|
||||
// observe nothing unless feedback is enabled
|
||||
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(isEnabled)
|
||||
Twig.plant(if (isEnabled) TroubleshootingTwig() else SilentTwig())
|
||||
FeedbackCoordinator(feedback, if (isEnabled) defaultObservers else setOf())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package cash.z.ecc.android.feedback
|
||||
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
|
||||
class FeedbackCrashlytics : FeedbackCoordinator.FeedbackObserver {
|
||||
/**
|
||||
|
@ -18,7 +18,7 @@ class FeedbackCrashlytics : FeedbackCoordinator.FeedbackObserver {
|
|||
)
|
||||
else -> null
|
||||
}
|
||||
exception?.let { Crashlytics.logException(it) }
|
||||
exception?.let { FirebaseCrashlytics.getInstance().recordException(it) }
|
||||
}
|
||||
|
||||
private class ReorgException(errorHeight: Int, rewindHeight: Int, reorgMesssage: String) :
|
||||
|
|
|
@ -63,6 +63,7 @@ object Report {
|
|||
val errorHeight: Int by propertyMap
|
||||
val rewindHeight: Int by propertyMap
|
||||
}
|
||||
class TxUpdateFailed(t: Throwable) : Feedback.AppError("txupdate", t, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,73 +29,75 @@ class TransactionViewHolder<T : ConfirmedTransaction>(itemView: View) : Recycler
|
|||
private val formatter = SimpleDateFormat("M/d h:mma", Locale.getDefault())
|
||||
private val addressRegex = """zs\d\w{65,}""".toRegex()
|
||||
|
||||
fun bindTo(transaction: T?) = (itemView.context as MainActivity).lifecycleScope.launch {
|
||||
// update view
|
||||
var lineOne: String = ""
|
||||
var lineTwo: String = ""
|
||||
var amountZec: String = ""
|
||||
var amountDisplay: String = ""
|
||||
var amountColor: Int = R.color.text_light_dimmed
|
||||
var lineOneColor: Int = R.color.text_light
|
||||
var lineTwoColor: Int = R.color.text_light_dimmed
|
||||
var indicatorBackground: Int = R.drawable.background_indicator_unknown
|
||||
fun bindTo(transaction: T?) {
|
||||
(itemView.context as MainActivity).lifecycleScope.launch {
|
||||
// update view
|
||||
var lineOne: String = ""
|
||||
var lineTwo: String = ""
|
||||
var amountZec: String = ""
|
||||
var amountDisplay: String = ""
|
||||
var amountColor: Int = R.color.text_light_dimmed
|
||||
var lineOneColor: Int = R.color.text_light
|
||||
var lineTwoColor: Int = R.color.text_light_dimmed
|
||||
var indicatorBackground: Int = R.drawable.background_indicator_unknown
|
||||
|
||||
transaction?.apply {
|
||||
itemView.setOnClickListener {
|
||||
onTransactionClicked(this)
|
||||
}
|
||||
itemView.setOnLongClickListener {
|
||||
onTransactionLongPressed(this)
|
||||
true
|
||||
}
|
||||
amountZec = value.convertZatoshiToZecString()
|
||||
// TODO: these might be good extension functions
|
||||
val timestamp = formatter.format(blockTimeInSeconds * 1000L)
|
||||
val isMined = blockTimeInSeconds != 0L
|
||||
when {
|
||||
!toAddress.isNullOrEmpty() -> {
|
||||
lineOne = "You paid ${toAddress?.toAbbreviatedAddress()}"
|
||||
lineTwo = if (isMined) "Sent $timestamp" else "Pending confirmation"
|
||||
amountDisplay = "- $amountZec"
|
||||
if (isMined) {
|
||||
amountColor = R.color.zcashRed
|
||||
indicatorBackground = R.drawable.background_indicator_outbound
|
||||
} else {
|
||||
lineOneColor = R.color.text_light_dimmed
|
||||
lineTwoColor = R.color.text_light
|
||||
transaction?.apply {
|
||||
itemView.setOnClickListener {
|
||||
onTransactionClicked(this)
|
||||
}
|
||||
itemView.setOnLongClickListener {
|
||||
onTransactionLongPressed(this)
|
||||
true
|
||||
}
|
||||
amountZec = value.convertZatoshiToZecString()
|
||||
// TODO: these might be good extension functions
|
||||
val timestamp = formatter.format(blockTimeInSeconds * 1000L)
|
||||
val isMined = blockTimeInSeconds != 0L
|
||||
when {
|
||||
!toAddress.isNullOrEmpty() -> {
|
||||
lineOne = "You paid ${toAddress?.toAbbreviatedAddress()}"
|
||||
lineTwo = if (isMined) "Sent $timestamp" else "Pending confirmation"
|
||||
amountDisplay = "- $amountZec"
|
||||
if (isMined) {
|
||||
amountColor = R.color.zcashRed
|
||||
indicatorBackground = R.drawable.background_indicator_outbound
|
||||
} else {
|
||||
lineOneColor = R.color.text_light_dimmed
|
||||
lineTwoColor = R.color.text_light
|
||||
}
|
||||
}
|
||||
toAddress.isNullOrEmpty() && value > 0L && minedHeight > 0 -> {
|
||||
lineOne = getSender(transaction)
|
||||
lineTwo = "Received $timestamp"
|
||||
amountDisplay = "+ $amountZec"
|
||||
amountColor = R.color.zcashGreen
|
||||
indicatorBackground = R.drawable.background_indicator_inbound
|
||||
}
|
||||
else -> {
|
||||
lineOne = "Unknown"
|
||||
lineTwo = "Unknown"
|
||||
amountDisplay = "$amountZec"
|
||||
amountColor = R.color.text_light
|
||||
}
|
||||
}
|
||||
toAddress.isNullOrEmpty() && value > 0L && minedHeight > 0 -> {
|
||||
lineOne = getSender(transaction)
|
||||
lineTwo = "Received $timestamp"
|
||||
amountDisplay = "+ $amountZec"
|
||||
amountColor = R.color.zcashGreen
|
||||
indicatorBackground = R.drawable.background_indicator_inbound
|
||||
}
|
||||
else -> {
|
||||
lineOne = "Unknown"
|
||||
lineTwo = "Unknown"
|
||||
amountDisplay = "$amountZec"
|
||||
amountColor = R.color.text_light
|
||||
// sanitize amount
|
||||
if (value < ZcashSdk.MINERS_FEE_ZATOSHI) amountDisplay = "< 0.001"
|
||||
else if (amountZec.length > 10) { // 10 allows 3 digits to the left and 6 to the right of the decimal
|
||||
amountDisplay = "tap to view"
|
||||
}
|
||||
}
|
||||
// sanitize amount
|
||||
if (value < ZcashSdk.MINERS_FEE_ZATOSHI) amountDisplay = "< 0.001"
|
||||
else if (amountZec.length > 10) { // 10 allows 3 digits to the left and 6 to the right of the decimal
|
||||
amountDisplay = "tap to view"
|
||||
}
|
||||
|
||||
|
||||
topText.text = lineOne
|
||||
bottomText.text = lineTwo
|
||||
amountText.text = amountDisplay
|
||||
amountText.setTextColor(amountColor.toAppColor())
|
||||
topText.setTextColor(lineOneColor.toAppColor())
|
||||
bottomText.setTextColor(lineTwoColor.toAppColor())
|
||||
val context = itemView.context
|
||||
indicator.background = context.resources.getDrawable(indicatorBackground)
|
||||
shieldIcon.goneIf((transaction?.raw != null || transaction?.expiryHeight != null) && !transaction?.toAddress.isShielded())
|
||||
}
|
||||
|
||||
|
||||
topText.text = lineOne
|
||||
bottomText.text = lineTwo
|
||||
amountText.text = amountDisplay
|
||||
amountText.setTextColor(amountColor.toAppColor())
|
||||
topText.setTextColor(lineOneColor.toAppColor())
|
||||
bottomText.setTextColor(lineTwoColor.toAppColor())
|
||||
val context = itemView.context
|
||||
indicator.background = context.resources.getDrawable(indicatorBackground)
|
||||
shieldIcon.goneIf((transaction?.raw != null || transaction?.expiryHeight != null) && !transaction?.toAddress.isShielded())
|
||||
}
|
||||
|
||||
private suspend fun getSender(transaction: ConfirmedTransaction): String {
|
||||
|
|
|
@ -21,8 +21,8 @@ import cash.z.ecc.android.feedback.Report.Tap.SCAN_RECEIVE
|
|||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.ui.base.BaseFragment
|
||||
import cash.z.ecc.android.ui.send.SendViewModel
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
@ -102,7 +102,7 @@ class ScanFragment : BaseFragment<FragmentScanBinding>() {
|
|||
preview.setSurfaceProvider(binding.preview.createSurfaceProvider())
|
||||
} catch (t: Throwable) {
|
||||
// TODO: consider bubbling this up to the user
|
||||
Crashlytics.logException(t)
|
||||
mainActivity?.feedback?.report(t)
|
||||
twig("Error while opening the camera: $t")
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import cash.z.ecc.android.sdk.db.entity.*
|
|||
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
|
||||
import cash.z.ecc.android.sdk.ext.toAbbreviatedAddress
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
@ -112,8 +111,8 @@ class SendFinalFragment : BaseFragment<FragmentSendFinalBinding>() {
|
|||
} catch(t: Throwable) {
|
||||
val message = "ERROR: error while handling pending transaction update! $t"
|
||||
twig(message)
|
||||
Crashlytics.log(message)
|
||||
Crashlytics.logException(t)
|
||||
mainActivity?.feedback?.report(Report.Error.NonFatal.TxUpdateFailed(t))
|
||||
mainActivity?.feedback?.report(t)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import cash.z.ecc.android.sdk.ext.ZcashSdk
|
|||
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.sdk.validate.AddressType
|
||||
import com.crashlytics.android.Crashlytics
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
@ -144,7 +143,7 @@ class SendViewModel @Inject constructor() : ViewModel() {
|
|||
report(metricId)
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
Crashlytics.logException(RuntimeException("Error while updating Metrics", t))
|
||||
feedback.report(t)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,9 @@ import android.widget.TextView
|
|||
import android.widget.Toast
|
||||
import androidx.activity.addCallback
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import cash.z.ecc.android.R
|
||||
import cash.z.ecc.android.ZcashWalletApp
|
||||
import cash.z.ecc.android.databinding.FragmentBackupBinding
|
||||
import cash.z.ecc.android.di.viewmodel.activityViewModel
|
||||
import cash.z.ecc.android.di.viewmodel.viewModel
|
||||
import cash.z.ecc.android.feedback.Report
|
||||
import cash.z.ecc.android.feedback.Report.MetricType.SEED_PHRASE_LOADED
|
||||
import cash.z.ecc.android.feedback.Report.Tap.BACKUP_DONE
|
||||
|
|
|
@ -13,7 +13,7 @@ buildscript {
|
|||
classpath 'com.google.gms:google-services:4.3.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${Deps.kotlinVersion}"
|
||||
classpath 'io.fabric.tools:gradle:1.31.2'
|
||||
classpath 'com.google.firebase:perf-plugin:1.3.1'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.1.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,10 +61,7 @@ object Deps {
|
|||
val STUB = "io.grpc:grpc-stub:$version"
|
||||
}
|
||||
object Analytics { // for dogfooding/crash-reporting/feedback only on internal team builds
|
||||
val CRASHLYTICS = "com.crashlytics.sdk.android:crashlytics:2.10.1"
|
||||
val CRASHLYTICS_NDK = "com.crashlytics.sdk.android:crashlytics-ndk:2.1.1"
|
||||
val FIREBASE = "com.google.firebase:firebase-analytics:17.4.3"
|
||||
val FIREBASE_PERF = "com.google.firebase:firebase-perf:19.0.7"
|
||||
val CRASHLYTICS = "com.google.firebase:firebase-crashlytics:17.0.1"
|
||||
val MIXPANEL = "com.mixpanel.android:mixpanel-android:5.6.3"
|
||||
}
|
||||
object JavaX {
|
||||
|
|
|
@ -125,6 +125,7 @@ class FeedbackCoordinator(val feedback: Feedback, defaultObservers: Set<Feedback
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val ENABLED = "setting.feedbackcoordinater.enabled"
|
||||
private val mutex: Mutex = Mutex()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue