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