Skip to content

Commit

Permalink
Fix WorkerManager crash pre API 31
Browse files Browse the repository at this point in the history
setExpedited() isn't enough, we also needed to provide ForegroundInfo. The documentation doesn't make this very obvious, and there's no API enforcement.

Fixes #2268
  • Loading branch information
pyricau committed Jan 6, 2022
1 parent 9f15c75 commit b58cd46
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package leakcanary.internal

import android.app.Notification
import android.content.Context
import androidx.work.Data
import androidx.work.ForegroundInfo
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.impl.utils.futures.SettableFuture
import com.google.common.util.concurrent.ListenableFuture
import com.squareup.leakcanary.core.R
import leakcanary.EventListener.Event

internal class HeapAnalyzerWorker(appContext: Context, workerParams: WorkerParameters) :
Expand All @@ -17,13 +22,35 @@ internal class HeapAnalyzerWorker(appContext: Context, workerParams: WorkerParam
return Result.success()
}

override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
return applicationContext.heapAnalysisForegroundInfoAsync()
}

companion object {
private const val EVENT_BYTES = "EVENT_BYTES"

fun Event.asWorkerInputData(dataBuilder: Data.Builder = Data.Builder()) = dataBuilder
.putByteArray(EVENT_BYTES, toByteArray())
.build()

inline fun <reified T> Data.asEvent(): T = Serializables.fromByteArray<T>(getByteArray(EVENT_BYTES)!!)!!
inline fun <reified T> Data.asEvent(): T =
Serializables.fromByteArray<T>(getByteArray(EVENT_BYTES)!!)!!

fun Context.heapAnalysisForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
val infoFuture = SettableFuture.create<ForegroundInfo>()
val builder = Notification.Builder(this)
.setContentTitle(getString(R.string.leak_canary_notification_analysing))
.setContentText("LeakCanary is working.")
.setProgress(100, 0, true)
val notification =
Notifications.buildNotification(this, builder, NotificationType.LEAKCANARY_LOW)
infoFuture.set(
ForegroundInfo(
R.id.leak_canary_notification_analyzing_heap,
notification
)
)
return infoFuture
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package leakcanary.internal

import android.content.Context
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import androidx.work.impl.utils.futures.SettableFuture
import androidx.work.multiprocess.RemoteListenableWorker
import com.google.common.util.concurrent.ListenableFuture
import leakcanary.BackgroundThreadHeapAnalyzer.heapAnalyzerThreadHandler
import leakcanary.EventListener.Event.HeapDump
import leakcanary.internal.HeapAnalyzerWorker.Companion.asEvent
import leakcanary.internal.HeapAnalyzerWorker.Companion.heapAnalysisForegroundInfoAsync
import shark.SharkLog

internal class RemoteHeapAnalyzerWorker(appContext: Context, workerParams: WorkerParameters) :
Expand All @@ -33,4 +35,8 @@ internal class RemoteHeapAnalyzerWorker(appContext: Context, workerParams: Worke
}
return result
}

override fun getForegroundInfoAsync(): ListenableFuture<ForegroundInfo> {
return applicationContext.heapAnalysisForegroundInfoAsync()
}
}

0 comments on commit b58cd46

Please sign in to comment.