<lambda>null1package leakcanary.internal.activity.screen 2 3 import android.app.ActivityManager 4 import android.text.Html 5 import android.text.SpannableStringBuilder 6 import android.text.method.LinkMovementMethod 7 import android.view.View 8 import android.view.ViewGroup 9 import android.widget.TextView 10 import com.squareup.leakcanary.core.R 11 import java.util.UUID 12 import leakcanary.EventListener.Event.HeapDump 13 import leakcanary.internal.InternalLeakCanary 14 import leakcanary.internal.activity.db.HeapAnalysisTable 15 import leakcanary.internal.activity.db.executeOnDb 16 import leakcanary.internal.activity.shareHeapDump 17 import leakcanary.internal.activity.shareToGitHubIssue 18 import leakcanary.internal.activity.ui.UiUtils 19 import leakcanary.internal.navigation.Screen 20 import leakcanary.internal.navigation.activity 21 import leakcanary.internal.navigation.goBack 22 import leakcanary.internal.navigation.inflate 23 import leakcanary.internal.navigation.onCreateOptionsMenu 24 import shark.HeapAnalysisFailure 25 26 internal class HeapAnalysisFailureScreen( 27 private val analysisId: Long 28 ) : Screen() { 29 30 override fun createView(container: ViewGroup) = 31 container.inflate(R.layout.leak_canary_heap_analysis_failure_screen).apply { 32 activity.title = resources.getString(R.string.leak_canary_loading_title) 33 executeOnDb { 34 val heapAnalysis = HeapAnalysisTable.retrieve<HeapAnalysisFailure>(db, analysisId) 35 if (heapAnalysis == null) { 36 updateUi { 37 activity.title = resources.getString(R.string.leak_canary_analysis_deleted_title) 38 } 39 } else { 40 val heapDumpFileExist = heapAnalysis.heapDumpFile.exists() 41 updateUi { onFailureRetrieved(heapAnalysis, heapDumpFileExist) } 42 } 43 } 44 } 45 46 private fun View.onFailureRetrieved( 47 heapAnalysis: HeapAnalysisFailure, 48 heapDumpFileExist: Boolean 49 ) { 50 activity.title = resources.getString(R.string.leak_canary_analysis_failed) 51 52 val failureText = 53 if (heapDumpFileExist) { 54 "You can <a href=\"try_again\">run the analysis again</a>.<br><br>" 55 } else { 56 "" 57 } + """ 58 Please <a href="file_issue">click here</a> to file a bug report. 59 The stacktrace details will be copied into the clipboard and you just need to paste into the 60 GitHub issue description.""" + (if (heapDumpFileExist) { 61 """ 62 <br><br>To help reproduce the issue, please share the 63 <a href="share_hprof">Heap Dump file</a> and upload it to the GitHub issue. 64 """ 65 } else "") 66 67 val failure = Html.fromHtml(failureText) as SpannableStringBuilder 68 69 UiUtils.replaceUrlSpanWithAction(failure) { urlSpan -> 70 when (urlSpan) { 71 "file_issue" -> { 72 { 73 shareToGitHubIssue(heapAnalysis) 74 } 75 } 76 "share_hprof" -> { 77 { 78 shareHeapDump(heapAnalysis.heapDumpFile) 79 } 80 } 81 "try_again" -> { 82 { 83 InternalLeakCanary.sendEvent( 84 HeapDump( 85 uniqueId = UUID.randomUUID().toString(), 86 file = heapAnalysis.heapDumpFile, 87 durationMillis = heapAnalysis.dumpDurationMillis, 88 reason = "Retrying heap analysis after failure." 89 ) 90 ) 91 } 92 } 93 else -> null 94 } 95 } 96 findViewById<TextView>(R.id.leak_canary_header_text).apply { 97 movementMethod = LinkMovementMethod.getInstance() 98 text = failure 99 } 100 101 findViewById<TextView>(R.id.leak_canary_stacktrace).text = heapAnalysis.exception.toString() 102 103 onCreateOptionsMenu { menu -> 104 if (!ActivityManager.isUserAMonkey()) { 105 menu.add(R.string.leak_canary_delete) 106 .setOnMenuItemClickListener { 107 executeOnDb { 108 HeapAnalysisTable.delete(db, analysisId, heapAnalysis.heapDumpFile) 109 updateUi { 110 goBack() 111 } 112 } 113 true 114 } 115 } 116 } 117 } 118 } 119