1 package leakcanary
2 
3 import android.app.Notification
4 import android.app.NotificationManager
5 import android.app.PendingIntent
6 import android.content.Context
7 import android.os.Build
8 import com.squareup.leakcanary.core.R
9 import leakcanary.EventListener.Event
10 import leakcanary.EventListener.Event.DumpingHeap
11 import leakcanary.EventListener.Event.HeapAnalysisDone
12 import leakcanary.EventListener.Event.HeapAnalysisDone.HeapAnalysisSucceeded
13 import leakcanary.EventListener.Event.HeapAnalysisProgress
14 import leakcanary.EventListener.Event.HeapDumpFailed
15 import leakcanary.EventListener.Event.HeapDump
16 import leakcanary.internal.InternalLeakCanary
17 import leakcanary.internal.NotificationType.LEAKCANARY_LOW
18 import leakcanary.internal.NotificationType.LEAKCANARY_MAX
19 import leakcanary.internal.Notifications
20 
21 object NotificationEventListener : EventListener {
22 
23   private val appContext = InternalLeakCanary.application
24   private val notificationManager =
25     appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
26 
onEventnull27   override fun onEvent(event: Event) {
28     // TODO Unify Notifications.buildNotification vs Notifications.showNotification
29     // We need to bring in the retained count notifications first though.
30     if (!Notifications.canShowNotification) {
31       return
32     }
33     when (event) {
34       is DumpingHeap -> {
35         val dumpingHeap = appContext.getString(R.string.leak_canary_notification_dumping)
36         val builder = Notification.Builder(appContext)
37           .setContentTitle(dumpingHeap)
38         val notification = Notifications.buildNotification(appContext, builder, LEAKCANARY_LOW)
39         notificationManager.notify(R.id.leak_canary_notification_dumping_heap, notification)
40       }
41       is HeapDumpFailed, is HeapDump -> {
42         notificationManager.cancel(R.id.leak_canary_notification_dumping_heap)
43       }
44       is HeapAnalysisProgress -> {
45         val progress = (event.progressPercent * 100).toInt()
46         val builder = Notification.Builder(appContext)
47           .setContentTitle(appContext.getString(R.string.leak_canary_notification_analysing))
48           .setContentText(event.step.humanReadableName)
49           .setProgress(100, progress, false)
50         val notification =
51           Notifications.buildNotification(appContext, builder, LEAKCANARY_LOW)
52         notificationManager.notify(R.id.leak_canary_notification_analyzing_heap, notification)
53       }
54       is HeapAnalysisDone<*> -> {
55         notificationManager.cancel(R.id.leak_canary_notification_analyzing_heap)
56         val contentTitle = if (event is HeapAnalysisSucceeded) {
57           val heapAnalysis = event.heapAnalysis
58           val retainedObjectCount = heapAnalysis.allLeaks.sumBy { it.leakTraces.size }
59           val leakTypeCount = heapAnalysis.applicationLeaks.size + heapAnalysis.libraryLeaks.size
60           val unreadLeakCount = event.unreadLeakSignatures.size
61           appContext.getString(
62             R.string.leak_canary_analysis_success_notification,
63             retainedObjectCount,
64             leakTypeCount,
65             unreadLeakCount
66           )
67         } else {
68           appContext.getString(R.string.leak_canary_analysis_failed)
69         }
70         val flags = if (Build.VERSION.SDK_INT >= 23) {
71           PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
72         } else {
73           PendingIntent.FLAG_UPDATE_CURRENT
74         }
75         val pendingIntent = PendingIntent.getActivity(appContext, 1,  event.showIntent, flags)
76         showHeapAnalysisResultNotification(contentTitle,pendingIntent)
77       }
78     }
79   }
80 
showHeapAnalysisResultNotificationnull81   private fun showHeapAnalysisResultNotification(contentTitle: String, showIntent: PendingIntent) {
82     val contentText = appContext.getString(R.string.leak_canary_notification_message)
83     Notifications.showNotification(
84       appContext, contentTitle, contentText, showIntent,
85       R.id.leak_canary_notification_analysis_result,
86       LEAKCANARY_MAX
87     )
88   }
89 }
90