Skip to content

Commit

Permalink
Merge pull request #2052 from OneSignal/fix/v5_work_manager_crash
Browse files Browse the repository at this point in the history
Fix for WorkManager not Initialized Crash
  • Loading branch information
nan-li authored Apr 12, 2024
2 parents 5155827 + 329fb23 commit 8898cb8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.onesignal.notifications.internal.common

import android.annotation.SuppressLint
import android.content.Context
import androidx.work.Configuration
import androidx.work.WorkManager
import androidx.work.impl.WorkManagerImpl
import com.onesignal.debug.internal.logging.Logging

object OSWorkManagerHelper {
/**
* Helper method to provide a way to check if WorkManager is initialized in this process.
* The purpose of this helper is to work around this bug - https://issuetracker.google.com/issues/258176803
*
* This is effectively the `WorkManager.isInitialized()` public method introduced in androidx.work:work-*:2.8.0-alpha02.
* Please see https://android-review.googlesource.com/c/platform/frameworks/support/+/1941186.
*
* @return `true` if WorkManager has been initialized in this process.
*/
@SuppressWarnings("deprecation")
@SuppressLint("RestrictedApi")
private fun isInitialized(): Boolean {
return WorkManagerImpl.getInstance() != null
}

/**
* If there is an instance of WorkManager available, use it. Else, in rare cases, initialize it ourselves.
*
* Calling `WorkManager.getInstance(context)` directly can cause an exception if it is null.
*
* @return an instance of WorkManager
*/
@JvmStatic
@Synchronized
fun getInstance(context: Context): WorkManager {
if (!isInitialized()) {
try {
WorkManager.initialize(context, Configuration.Builder().build())
} catch (e: IllegalStateException) {
/*
This catch is meant for the exception -
https://android.googlesource.com/platform/frameworks/support/+/60ae0eec2a32396c22ad92502cde952c80d514a0/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java#177
1. We lost the race with another call to WorkManager.initialize outside of OneSignal.
2. It is possible for some other unexpected error is thrown from WorkManager.
*/
Logging.error("OSWorkManagerHelper initializing WorkManager failed: ", e)
}
}
return WorkManager.getInstance(context)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import androidx.work.CoroutineWorker
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.onesignal.OneSignal
import com.onesignal.common.AndroidUtils
import com.onesignal.debug.internal.logging.Logging
import com.onesignal.notifications.internal.common.NotificationFormatHelper
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
import com.onesignal.notifications.internal.generation.INotificationGenerationProcessor
import com.onesignal.notifications.internal.generation.INotificationGenerationWorkManager
import org.json.JSONException
Expand Down Expand Up @@ -55,7 +55,7 @@ internal class NotificationGenerationWorkManager : INotificationGenerationWorkMa
Logging.debug(
"NotificationWorkManager enqueueing notification work with notificationId: $osNotificationId and jsonPayload: $jsonPayload",
)
WorkManager.getInstance(context)
OSWorkManagerHelper.getInstance(context)
.enqueueUniqueWork(osNotificationId, ExistingWorkPolicy.KEEP, workRequest)

return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.onesignal.OneSignal
import com.onesignal.common.AndroidUtils
import com.onesignal.core.internal.application.IApplicationService
import com.onesignal.core.internal.config.ConfigModelStore
import com.onesignal.debug.internal.logging.Logging
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
import com.onesignal.notifications.internal.receivereceipt.IReceiveReceiptProcessor
import com.onesignal.notifications.internal.receivereceipt.IReceiveReceiptWorkManager
import com.onesignal.user.internal.subscriptions.ISubscriptionManager
Expand Down Expand Up @@ -57,7 +57,7 @@ internal class ReceiveReceiptWorkManager(
Logging.debug(
"OSReceiveReceiptController enqueueing send receive receipt work with notificationId: $notificationId and delay: $delay seconds",
)
WorkManager.getInstance(_applicationService.appContext)
OSWorkManagerHelper.getInstance(_applicationService.appContext)
.enqueueUniqueWork(
notificationId + "_receive_receipt",
ExistingWorkPolicy.KEEP,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import com.onesignal.OneSignal
import com.onesignal.notifications.internal.common.NotificationHelper
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
import com.onesignal.notifications.internal.restoration.INotificationRestoreProcessor
import com.onesignal.notifications.internal.restoration.INotificationRestoreWorkManager
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -36,7 +36,7 @@ internal class NotificationRestoreWorkManager : INotificationRestoreWorkManager
OneTimeWorkRequest.Builder(NotificationRestoreWorker::class.java)
.setInitialDelay(restoreDelayInSeconds.toLong(), TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context!!)
OSWorkManagerHelper.getInstance(context!!)
.enqueueUniqueWork(
NOTIFICATION_RESTORE_WORKER_IDENTIFIER,
ExistingWorkPolicy.KEEP,
Expand Down

0 comments on commit 8898cb8

Please sign in to comment.