From baf9213db8ae8df05575bfc8554ae4ce986ad6a9 Mon Sep 17 00:00:00 2001 From: Nan Date: Wed, 12 Jun 2024 10:16:09 -0700 Subject: [PATCH] Getter for WorkManager considers the app context * We were getting the WorkManager instance via `WorkManagerImpl.getInstance()` and initializing it with a blank Configuration when the getter returned null. * However, we should use `WorkManagerImpl.getInstance(Context)` instead as this getter will allow for on-demand initialization with the app's custom WorkManager. --- .../java/com/onesignal/OSWorkManagerHelper.kt | 56 ++++++++++++------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSWorkManagerHelper.kt b/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSWorkManagerHelper.kt index 05c63ddbe4..8e161cb01b 100644 --- a/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSWorkManagerHelper.kt +++ b/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSWorkManagerHelper.kt @@ -27,40 +27,58 @@ package com.onesignal -import android.annotation.SuppressLint import android.content.Context import androidx.work.Configuration import androidx.work.WorkManager -import androidx.work.impl.WorkManagerImpl object OSWorkManagerHelper { - /** - * Helper method to provide a way 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. - * - * @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. + * However, this is the appropriate way to check as the non-throwing `WorkManager.getInstance()` + * method does not allow the opportunity for on-demand initialization with custom WorkManager. + * + * The purpose of this helper is to work around this bug - https://issuetracker.google.com/issues/258176803 * * @return an instance of WorkManager */ @JvmStatic @Synchronized fun getInstance(context: Context): WorkManager { - if (!isInitialized()) { - WorkManager.initialize(context, Configuration.Builder().build()) + return try { + WorkManager.getInstance(context) + } catch (e: IllegalStateException) { + /* + This aims to catch the IllegalStateException "WorkManager is not initialized properly..." - + https://androidx.tech/artifacts/work/work-runtime/2.8.1-source/androidx/work/impl/WorkManagerImpl.java.html + */ + OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "OSWorkManagerHelper.getInstance failed, attempting to initialize: ", e) + initializeWorkManager(context) + WorkManager.getInstance(context) + } + } + + /** + * This method is called in rare cases to initialize WorkManager ourselves. + */ + private fun initializeWorkManager(context: Context) { + try { + /* + Note: `WorkManager.getInstance(context)` should already initialize WorkManager when the + application implements Configuration.Provider. However, as a further safeguard, let's detect + for this when we attempt to initialize WorkManager. + */ + val configuration = (context.applicationContext as? Configuration.Provider)?.workManagerConfiguration ?: Configuration.Builder().build() + WorkManager.initialize(context, configuration) + } 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. + */ + OneSignal.Log(OneSignal.LOG_LEVEL.ERROR, "OSWorkManagerHelper initializing WorkManager failed: ", e) } - return WorkManager.getInstance(context) } }