TvEventListener.kt
TLDR
This file contains the TvEventListener
object, which is an implementation of the EventListener
interface. It handles events related to heap analysis on Android TV devices. The TvEventListener
object has two private methods: showToast
and printIntentInfo
, which display toast messages and print adb commands, respectively.
Methods
showToast(heapAnalysis: HeapAnalysis)
This private method displays a toast message on the screen of the resumed activity of the application. It is used to grab user attention and direct them to Logcat, where a more detailed report will be printed. The message displayed depends on the outcome of the heap analysis. If the analysis is successful, the message will include the number of application leaks and library leaks found. If the analysis fails, a generic failure message will be displayed.
printIntentInfo()
This private method prints an adb command in the logcat. The adb command can be used to launch LeakCanary Activity on Android TV devices with API 26+ where the launcher icon may not appear. The command is displayed as a string template, including the package name and the name of the LeakLauncherActivity class.
package leakcanary
import com.squareup.leakcanary.core.R
import leakcanary.EventListener.Event
import leakcanary.EventListener.Event.HeapAnalysisDone
import leakcanary.internal.InternalLeakCanary
import leakcanary.internal.activity.LeakActivity
import leakcanary.internal.friendly.mainHandler
import leakcanary.internal.tv.TvToast
import shark.HeapAnalysis
import shark.HeapAnalysisFailure
import shark.HeapAnalysisSuccess
import shark.SharkLog
object TvEventListener : EventListener {
private val appContext = InternalLeakCanary.application
override fun onEvent(event: Event) {
when (event) {
is HeapAnalysisDone<*> -> {
showToast(event.heapAnalysis)
printIntentInfo()
}
else -> {}
}
}
/**
* Android TV devices do not have notifications, therefore the only easy and non-invasive way
* to communicate with user is via Toast messages. These are used just to grab user attention and
* to direct them to Logcat where a much more detailed report will be printed.
*/
private fun showToast(heapAnalysis: HeapAnalysis) {
mainHandler.post {
val resumedActivity = InternalLeakCanary.resumedActivity ?: return@post
val message: String = when (heapAnalysis) {
is HeapAnalysisSuccess -> {
appContext.getString(
R.string.leak_canary_tv_analysis_success,
heapAnalysis.applicationLeaks.size,
heapAnalysis.libraryLeaks.size
)
}
is HeapAnalysisFailure -> appContext.getString(R.string.leak_canary_tv_analysis_failure)
}
TvToast.makeText(resumedActivity, message)
.show()
}
}
/**
* Android TV with API 26+ has a bug where the launcher icon doesn't appear, so users won't know how
* to launch LeakCanary Activity.
* This method prints an adb command that launched LeakCanary into the logcat
*/
private fun printIntentInfo() {
val leakClass = LeakActivity::class.java
SharkLog.d {"""
====================================
ANDROID TV LAUNCH INTENT
====================================
Run the following adb command to display the list of leaks:
adb shell am start -n "${appContext.packageName}/${leakClass.`package`?.name}.LeakLauncherActivity"
====================================""".trimIndent()
}
}
}