Skip to content

Commit f09845a

Browse files
committed
fix WorkManager exception
* Before using WorkManager, check for its existence. Else, in rare cases that caused crashing, initialize it ourselves. * Additionally, as another layer to handling this issue, when initializing WorkManager ourselves, surround it in a try-catch as it is may be the slightest bit possible for another thread to initialize it in the interim between checking and initializing. * Provides a method to check if WorkManager is initialized in this process. - 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 for the library's implementation
1 parent 5155827 commit f09845a

File tree

4 files changed

+52
-6
lines changed

4 files changed

+52
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.onesignal.notifications.internal.common
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import androidx.work.Configuration
6+
import androidx.work.WorkManager
7+
import androidx.work.impl.WorkManagerImpl
8+
9+
object OSWorkManagerHelper {
10+
/**
11+
* Helper method to provide a way to check if WorkManager is initialized in this process.
12+
* The purpose of this helper is to work around this bug - https://issuetracker.google.com/issues/258176803
13+
*
14+
* This is effectively the `WorkManager.isInitialized()` public method introduced in androidx.work:work-*:2.8.0-alpha02.
15+
* Please see https://android-review.googlesource.com/c/platform/frameworks/support/+/1941186.
16+
*
17+
* @return `true` if WorkManager has been initialized in this process.
18+
*/
19+
@SuppressWarnings("deprecation")
20+
@SuppressLint("RestrictedApi")
21+
private fun isInitialized(): Boolean {
22+
return WorkManagerImpl.getInstance() != null
23+
}
24+
25+
/**
26+
* If there is an instance of WorkManager available, use it. Else, in rare cases, initialize it ourselves.
27+
*
28+
* Calling `WorkManager.getInstance(context)` directly can cause an exception if it is null.
29+
*
30+
* @return an instance of WorkManager
31+
*/
32+
@JvmStatic
33+
@Synchronized
34+
fun getInstance(context: Context): WorkManager {
35+
if (!isInitialized()) {
36+
try {
37+
// Initialization can fail if another thread initializes in the small time gap
38+
// https://android.googlesource.com/platform/frameworks/support/+/60ae0eec2a32396c22ad92502cde952c80d514a0/work/workmanager/src/main/java/androidx/work/impl/WorkManagerImpl.java#177
39+
WorkManager.initialize(context, Configuration.Builder().build())
40+
} catch (e: IllegalStateException) {
41+
// Admittedly starting to get hacky
42+
}
43+
}
44+
return WorkManager.getInstance(context)
45+
}
46+
}

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationWorkManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import androidx.work.CoroutineWorker
55
import androidx.work.Data
66
import androidx.work.ExistingWorkPolicy
77
import androidx.work.OneTimeWorkRequest
8-
import androidx.work.WorkManager
98
import androidx.work.WorkerParameters
109
import com.onesignal.OneSignal
1110
import com.onesignal.common.AndroidUtils
1211
import com.onesignal.debug.internal.logging.Logging
1312
import com.onesignal.notifications.internal.common.NotificationFormatHelper
13+
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
1414
import com.onesignal.notifications.internal.generation.INotificationGenerationProcessor
1515
import com.onesignal.notifications.internal.generation.INotificationGenerationWorkManager
1616
import org.json.JSONException
@@ -55,7 +55,7 @@ internal class NotificationGenerationWorkManager : INotificationGenerationWorkMa
5555
Logging.debug(
5656
"NotificationWorkManager enqueueing notification work with notificationId: $osNotificationId and jsonPayload: $jsonPayload",
5757
)
58-
WorkManager.getInstance(context)
58+
OSWorkManagerHelper.getInstance(context)
5959
.enqueueUniqueWork(osNotificationId, ExistingWorkPolicy.KEEP, workRequest)
6060

6161
return true

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/receivereceipt/impl/ReceiveReceiptWorkManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import androidx.work.Data
77
import androidx.work.ExistingWorkPolicy
88
import androidx.work.NetworkType
99
import androidx.work.OneTimeWorkRequest
10-
import androidx.work.WorkManager
1110
import androidx.work.WorkerParameters
1211
import com.onesignal.OneSignal
1312
import com.onesignal.common.AndroidUtils
1413
import com.onesignal.core.internal.application.IApplicationService
1514
import com.onesignal.core.internal.config.ConfigModelStore
1615
import com.onesignal.debug.internal.logging.Logging
16+
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
1717
import com.onesignal.notifications.internal.receivereceipt.IReceiveReceiptProcessor
1818
import com.onesignal.notifications.internal.receivereceipt.IReceiveReceiptWorkManager
1919
import com.onesignal.user.internal.subscriptions.ISubscriptionManager
@@ -57,7 +57,7 @@ internal class ReceiveReceiptWorkManager(
5757
Logging.debug(
5858
"OSReceiveReceiptController enqueueing send receive receipt work with notificationId: $notificationId and delay: $delay seconds",
5959
)
60-
WorkManager.getInstance(_applicationService.appContext)
60+
OSWorkManagerHelper.getInstance(_applicationService.appContext)
6161
.enqueueUniqueWork(
6262
notificationId + "_receive_receipt",
6363
ExistingWorkPolicy.KEEP,

OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/restoration/impl/NotificationRestoreWorkManager.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import android.content.Context
44
import androidx.work.CoroutineWorker
55
import androidx.work.ExistingWorkPolicy
66
import androidx.work.OneTimeWorkRequest
7-
import androidx.work.WorkManager
87
import androidx.work.WorkerParameters
98
import com.onesignal.OneSignal
109
import com.onesignal.notifications.internal.common.NotificationHelper
10+
import com.onesignal.notifications.internal.common.OSWorkManagerHelper
1111
import com.onesignal.notifications.internal.restoration.INotificationRestoreProcessor
1212
import com.onesignal.notifications.internal.restoration.INotificationRestoreWorkManager
1313
import java.util.concurrent.TimeUnit
@@ -36,7 +36,7 @@ internal class NotificationRestoreWorkManager : INotificationRestoreWorkManager
3636
OneTimeWorkRequest.Builder(NotificationRestoreWorker::class.java)
3737
.setInitialDelay(restoreDelayInSeconds.toLong(), TimeUnit.SECONDS)
3838
.build()
39-
WorkManager.getInstance(context!!)
39+
OSWorkManagerHelper.getInstance(context!!)
4040
.enqueueUniqueWork(
4141
NOTIFICATION_RESTORE_WORKER_IDENTIFIER,
4242
ExistingWorkPolicy.KEEP,

0 commit comments

Comments
 (0)