diff --git a/OneSignalSDK/onesignal/core/build.gradle b/OneSignalSDK/onesignal/core/build.gradle index 81ed88df4..bd1219c24 100644 --- a/OneSignalSDK/onesignal/core/build.gradle +++ b/OneSignalSDK/onesignal/core/build.gradle @@ -42,6 +42,8 @@ android { jvmTarget = '1.8' } namespace 'com.onesignal.core' + + kotlinOptions.freeCompilerArgs += ['-module-name', namespace] } tasks.withType(Test) { diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/TimeUtils.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/TimeUtils.kt index d126ecc21..a71fcdb68 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/TimeUtils.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/TimeUtils.kt @@ -17,7 +17,7 @@ object TimeUtils { return offset / 1000 } - fun getTimeZoneId(): String? { + fun getTimeZoneId(): String { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ZoneId.systemDefault().id } else { diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelStore.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelStore.kt index c3f38ecb8..28d742856 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelStore.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelStore.kt @@ -16,7 +16,7 @@ interface IModelStore : * * @param jsonObject The optional [JSONObject] to initialize the new model with. */ - fun create(jsonObject: JSONObject? = null): TModel + fun create(jsonObject: JSONObject? = null): TModel? /** * List the models that are owned by this model store. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ModelStore.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ModelStore.kt index 91bb502c6..185b60415 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ModelStore.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ModelStore.kt @@ -126,7 +126,7 @@ abstract class ModelStore( val str = _prefs.getString(PreferenceStores.ONESIGNAL, PreferenceOneSignalKeys.MODEL_STORE_PREFIX + name, "[]") val jsonArray = JSONArray(str) for (index in 0 until jsonArray.length()) { - val newModel = create(jsonArray.getJSONObject(index)) + val newModel = create(jsonArray.getJSONObject(index)) ?: continue _models.add(newModel) // listen for changes to this model newModel.subscribe(this) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/SingletonModelStore.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/SingletonModelStore.kt index 4b1890110..73ba0aabd 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/SingletonModelStore.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/SingletonModelStore.kt @@ -24,7 +24,7 @@ open class SingletonModelStore( return model } - val createdModel = store.create() + val createdModel = store.create() ?: throw Exception("Unable to initialize model from store $store") createdModel.id = _singletonId store.add(createdModel) return createdModel diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/IOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/IOperationExecutor.kt index 8af45ce8a..e27c49421 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/IOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/IOperationExecutor.kt @@ -68,4 +68,10 @@ enum class ExecutionResult { * retried if authorization can be achieved. */ FAIL_UNAUTHORIZED, + + /** + * Used in special login case. + * The operation failed due to a conflict and can be handled. + */ + FAIL_CONFLICT, } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationModelStore.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationModelStore.kt index 2a0319d07..4577ad7b0 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationModelStore.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationModelStore.kt @@ -3,11 +3,13 @@ package com.onesignal.core.internal.operations.impl import com.onesignal.common.modeling.ModelStore import com.onesignal.core.internal.operations.Operation import com.onesignal.core.internal.preferences.IPreferencesService +import com.onesignal.debug.internal.logging.Logging import com.onesignal.user.internal.operations.CreateSubscriptionOperation import com.onesignal.user.internal.operations.DeleteAliasOperation import com.onesignal.user.internal.operations.DeleteSubscriptionOperation import com.onesignal.user.internal.operations.DeleteTagOperation import com.onesignal.user.internal.operations.LoginUserOperation +import com.onesignal.user.internal.operations.LoginUserFromSubscriptionOperation import com.onesignal.user.internal.operations.RefreshUserOperation import com.onesignal.user.internal.operations.SetAliasOperation import com.onesignal.user.internal.operations.SetPropertyOperation @@ -18,6 +20,7 @@ import com.onesignal.user.internal.operations.TrackSessionStartOperation import com.onesignal.user.internal.operations.TransferSubscriptionOperation import com.onesignal.user.internal.operations.UpdateSubscriptionOperation import com.onesignal.user.internal.operations.impl.executors.IdentityOperationExecutor +import com.onesignal.user.internal.operations.impl.executors.LoginUserFromSubscriptionOperationExecutor import com.onesignal.user.internal.operations.impl.executors.LoginUserOperationExecutor import com.onesignal.user.internal.operations.impl.executors.RefreshUserOperationExecutor import com.onesignal.user.internal.operations.impl.executors.SubscriptionOperationExecutor @@ -30,13 +33,15 @@ internal class OperationModelStore(prefs: IPreferencesService) : ModelStore DeleteSubscriptionOperation() SubscriptionOperationExecutor.TRANSFER_SUBSCRIPTION -> TransferSubscriptionOperation() LoginUserOperationExecutor.LOGIN_USER -> LoginUserOperation() + LoginUserFromSubscriptionOperationExecutor.LOGIN_USER_FROM_SUBSCRIPTION_USER -> LoginUserFromSubscriptionOperation() RefreshUserOperationExecutor.REFRESH_USER -> RefreshUserOperation() UpdateUserOperationExecutor.SET_TAG -> SetTagOperation() UpdateUserOperationExecutor.DELETE_TAG -> DeleteTagOperation() diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt index 91eaeb30c..937fc037e 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/impl/OperationRepo.kt @@ -167,6 +167,7 @@ internal class OperationRepo( } ExecutionResult.FAIL_UNAUTHORIZED, // TODO: Need to provide callback for app to reset JWT. For now, fail with no retry. ExecutionResult.FAIL_NORETRY, + ExecutionResult.FAIL_CONFLICT, -> { Logging.error("Operation execution failed without retry: $operations") // on failure we remove the operation from the store and wake any waiters diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/IdentityOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/IdentityOperationExecutor.kt index 51818ea4f..5d11f99fd 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/IdentityOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/IdentityOperationExecutor.kt @@ -51,10 +51,10 @@ internal class IdentityOperationExecutor( return when (responseType) { NetworkUtils.ResponseStatusType.RETRYABLE -> ExecutionResponse(ExecutionResult.FAIL_RETRY) - NetworkUtils.ResponseStatusType.INVALID, - NetworkUtils.ResponseStatusType.CONFLICT, - -> + NetworkUtils.ResponseStatusType.INVALID -> ExecutionResponse(ExecutionResult.FAIL_NORETRY) + NetworkUtils.ResponseStatusType.CONFLICT -> + ExecutionResponse(ExecutionResult.FAIL_CONFLICT) NetworkUtils.ResponseStatusType.UNAUTHORIZED -> ExecutionResponse(ExecutionResult.FAIL_UNAUTHORIZED) NetworkUtils.ResponseStatusType.MISSING -> { diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserOperationExecutor.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserOperationExecutor.kt index 17d4c49b5..ac537a1e0 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserOperationExecutor.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/executors/LoginUserOperationExecutor.kt @@ -82,9 +82,16 @@ internal class LoginUserOperationExecutor( ExecutionResponse(ExecutionResult.SUCCESS_STARTING_ONLY, mapOf(loginUserOp.onesignalId to backendOneSignalId)) } + ExecutionResult.FAIL_CONFLICT -> { + // When the SetAliasOperation fails with conflict that *most likely* means the externalId provided + // is already associated to a user. This *expected* condition means we must create a user. + // We hardcode the response of "user-2" in the log to provide information to the SDK consumer + Logging.debug("LoginUserOperationExecutor now handling 409 response with \"code\": \"user-2\" by switching to user with \"external_id\": \"${loginUserOp.externalId}\"") + createUser(loginUserOp, operations) + } ExecutionResult.FAIL_NORETRY -> { - // When the SetAliasOperation fails without retry that *most likely* means the externalId provided - // is already associated to a user. This expected condition means we must create a user. + // Some other failure occurred, still try to recover by creating the user + Logging.error("LoginUserOperationExecutor encountered error. Attempt to recover by switching to user with \"external_id\": \"${loginUserOp.externalId}\"") createUser(loginUserOp, operations) } else -> ExecutionResponse(result.result) diff --git a/OneSignalSDK/onesignal/in-app-messages/build.gradle b/OneSignalSDK/onesignal/in-app-messages/build.gradle index 25350132d..35529ab73 100644 --- a/OneSignalSDK/onesignal/in-app-messages/build.gradle +++ b/OneSignalSDK/onesignal/in-app-messages/build.gradle @@ -42,6 +42,8 @@ android { jvmTarget = '1.8' } namespace 'com.onesignal.inAppMessages' + + kotlinOptions.freeCompilerArgs += ['-module-name', namespace] } tasks.withType(Test) { diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt index b6cf4240f..be750dbda 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/display/impl/WebViewManager.kt @@ -279,13 +279,14 @@ internal class WebViewManager( } Logging.debug("In app message, showing first one with height: $newHeight") - messageView!!.setWebView(webView!!) + messageView?.setWebView(webView!!) if (newHeight != null) { lastPageHeight = newHeight - messageView!!.updateHeight(newHeight) + messageView?.updateHeight(newHeight) } - messageView!!.showView(activity) - messageView!!.checkIfShouldDismiss() + // showView does not return until in-app is dismissed + messageView?.showView(activity) + messageView?.checkIfShouldDismiss() } } diff --git a/OneSignalSDK/onesignal/location/build.gradle b/OneSignalSDK/onesignal/location/build.gradle index 8496a4a86..f66be7455 100644 --- a/OneSignalSDK/onesignal/location/build.gradle +++ b/OneSignalSDK/onesignal/location/build.gradle @@ -42,6 +42,8 @@ android { jvmTarget = '1.8' } namespace 'com.onesignal.location' + + kotlinOptions.freeCompilerArgs += ['-module-name', namespace] } tasks.withType(Test) { diff --git a/OneSignalSDK/onesignal/notifications/build.gradle b/OneSignalSDK/onesignal/notifications/build.gradle index 5cf80e97a..3dd557788 100644 --- a/OneSignalSDK/onesignal/notifications/build.gradle +++ b/OneSignalSDK/onesignal/notifications/build.gradle @@ -42,6 +42,8 @@ android { jvmTarget = '1.8' } namespace 'com.onesignal.notifications' + + kotlinOptions.freeCompilerArgs += ['-module-name', namespace] } tasks.withType(Test) { diff --git a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/common/NotificationGenerationJob.kt b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/common/NotificationGenerationJob.kt index c22821f9e..33d1e8f49 100644 --- a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/common/NotificationGenerationJob.kt +++ b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/common/NotificationGenerationJob.kt @@ -7,25 +7,17 @@ import org.json.JSONObject import java.security.SecureRandom class NotificationGenerationJob( - private var _notification: Notification, + inNotification: Notification, var jsonPayload: JSONObject, ) { - var notification: Notification - get() = _notification - private set(value) { - // If there is no android ID on the notification coming in, create one either - // copying from the previous one or generating a new one. - if (value != null && !value!!.hasNotificationId()) { - val curNotification = _notification - if (curNotification != null && curNotification.hasNotificationId()) { - value.androidNotificationId = curNotification.androidNotificationId - } else { - value.androidNotificationId = SecureRandom().nextInt() - } - } + val notification: Notification = inNotification.setAndroidNotificationId() - _notification = value + private fun Notification.setAndroidNotificationId() = this.also { + // If there is no android ID on the notification coming in, generate a new one. + if (it != null && !it.hasNotificationId()) { + it.androidNotificationId = SecureRandom().nextInt() } + } var isRestoring = false var isNotificationToDisplay = false diff --git a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationProcessor.kt b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationProcessor.kt index 5bd0b59f8..f66883522 100644 --- a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationProcessor.kt +++ b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/generation/impl/NotificationGenerationProcessor.kt @@ -116,7 +116,7 @@ internal class NotificationGenerationProcessor( }.join() } } catch (to: TimeoutCancellationException) { - Logging.error("notificationWillShowInForegroundHandler timed out, continuing with wantsToDisplay=$wantsToDisplay.", to) + Logging.info("notificationWillShowInForegroundHandler timed out, continuing with wantsToDisplay=$wantsToDisplay.", to) } catch (t: Throwable) { Logging.error("notificationWillShowInForegroundHandler threw an exception. Displaying normal OneSignal notification.", t) }