From 82e0a217007809dc7756d51a96c50f55dc019e6a Mon Sep 17 00:00:00 2001 From: jinliu9508 Date: Tue, 14 Nov 2023 02:25:31 -0500 Subject: [PATCH 1/5] Add UserStateObserver that returns both previous and current use states --- .../sdktest/model/MainActivityViewModel.java | 18 +++++- .../java/com/onesignal/common/IDManager.kt | 15 +++++ .../onesignal/common/events/EventProducer.kt | 8 ++- .../common/modeling/IModelChangedHandler.kt | 11 ++++ .../ISingletonModelStoreChangeHandler.kt | 2 +- .../common/modeling/SingletonModelStore.kt | 12 ++-- .../config/impl/ConfigModelStoreListener.kt | 3 +- .../listeners/SingletonModelStoreListener.kt | 5 +- .../java/com/onesignal/user/IUserManager.kt | 11 ++++ .../com/onesignal/user/IUserStateObserver.kt | 15 +++++ .../com/onesignal/user/UserChangedState.kt | 14 +++++ .../main/java/com/onesignal/user/UserState.kt | 39 ++++++++++++ .../onesignal/user/internal/UserManager.kt | 60 ++++++++++++++++++- .../listeners/IdentityModelStoreListener.kt | 3 +- .../listeners/PropertiesModelStoreListener.kt | 3 +- .../java/com/onesignal/mocks/MockHelper.kt | 2 +- .../internal/InAppMessagesManager.kt | 3 +- .../notifications/consumer-rules.pro | 4 ++ .../listeners/DeviceRegistrationListener.kt | 5 +- 19 files changed, 214 insertions(+), 19 deletions(-) create mode 100644 OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt create mode 100644 OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt create mode 100644 OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt diff --git a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java index 30508b0d35..6aa6e10d21 100644 --- a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java +++ b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java @@ -28,7 +28,11 @@ import com.onesignal.Continue; import com.onesignal.OneSignal; +import com.onesignal.debug.internal.logging.Logging; import com.onesignal.sdktest.adapter.SubscriptionRecyclerViewAdapter; +import com.onesignal.user.IUserStateObserver; +import com.onesignal.user.UserChangedState; +import com.onesignal.user.UserState; import com.onesignal.user.subscriptions.IEmailSubscription; import com.onesignal.user.subscriptions.IPushSubscription; import com.onesignal.user.subscriptions.ISmsSubscription; @@ -63,7 +67,7 @@ import java.util.Map; @RequiresApi(api = Build.VERSION_CODES.N) -public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver { +public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver, IUserStateObserver { private Animate animate; private Dialog dialog; @@ -293,6 +297,7 @@ public ActivityViewModel onActivityCreated(Context context) { triggerArrayList = new ArrayList<>(); OneSignal.getUser().getPushSubscription().addObserver(this); + OneSignal.getUser().addObserver(this); return this; } @@ -501,6 +506,17 @@ public void onPushSubscriptionChange(@NonNull PushSubscriptionChangedState state refreshSubscriptionState(); } + @Override + public void onUserStateChange(@NonNull UserChangedState state) { + UserState currentState = state.getCurrent(); + UserState prevState = state.getPrevious(); + Logging.debug("onUserStateChanged; previous onesignalId: " + String.valueOf(prevState.getOnesignalId()) + + ", previous externalId: " + String.valueOf(prevState.getExternalId()) + + ", current onesignalId: " + String.valueOf(currentState.getOnesignalId()) + + ", current externalId: " + String.valueOf(currentState.getExternalId()), + null); + } + private class DummySubscription implements ISubscription { private String _id; diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt index d0e168a787..c3de6dcb08 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt @@ -26,4 +26,19 @@ object IDManager { * @return true if the [id] provided was created via [createLocalId]. */ fun isLocalId(id: String): Boolean = id.startsWith(LOCAL_PREFIX) + + /** + * Get non local ID or null. + * + * @param id The ID to test. + * + * @return [id] or null if the [id] provided was created via [createLocalId]. + */ + fun getNonLocalIDOrNull(id: String): String? { + if (isLocalId(id)) { + return null + } + + return id + } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt index ae49ecf512..d05a9a46f7 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt @@ -38,9 +38,11 @@ open class EventProducer : IEventNotifier { * * @param callback The callback will be invoked for each subscribed handler, allowing you to call the handler. */ - fun fire(callback: (THandler) -> Unit) { - for (s in subscribers) { - callback(s) + open fun fire(callback: (THandler) -> Unit) { + synchronized(subscribers) { + for (s in subscribers) { + callback(s) + } } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt index ba526dc4ad..ae7eec5eba 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt @@ -49,3 +49,14 @@ class ModelChangedArgs( */ val newValue: Any?, ) + +/** + * The arguments passed to the [IModelChangedHandler] handler when subscribed via [Model.subscribe] + */ +class ModelReplacedArgs( + /** + * The full model in its previous and current state. + */ + val oldModel: TModel, + val newModel: TModel, +) where TModel : Model diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt index c929fe8ff9..143711f2d3 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt @@ -12,7 +12,7 @@ interface ISingletonModelStoreChangeHandler where TModel : Model { * @param tag The tag which identifies how/why the model was replaced. */ fun onModelReplaced( - model: TModel, + model: ModelReplacedArgs, tag: String, ) 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 0c6c3dd9da..3305ebdf54 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 @@ -35,10 +35,14 @@ open class SingletonModelStore( model: TModel, tag: String, ) { - val existingModel = this.model - existingModel.initializeFromModel(singletonId, model) - store.persist() - changeSubscription.fire { it.onModelReplaced(existingModel, tag) } + synchronized(replaceLock) { + val oldModel = this.store.create() ?: throw Exception("Unable to initialize model from store $store") + oldModel.initializeFromModel(singletonId, this.model) + val existingModel = this.model + existingModel.initializeFromModel(singletonId, model) + store.persist() + changeSubscription.fire { it.onModelReplaced(ModelReplacedArgs(oldModel, existingModel), tag) } + } } override fun subscribe(handler: ISingletonModelStoreChangeHandler) = changeSubscription.subscribe(handler) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt index 87d7eae6b0..7121989606 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt @@ -4,6 +4,7 @@ import com.onesignal.common.exceptions.BackendException import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.backend.IParamsBackendService import com.onesignal.core.internal.config.ConfigModel @@ -43,7 +44,7 @@ internal class ConfigModelStoreListener( } override fun onModelReplaced( - model: ConfigModel, + model: ModelReplacedArgs, tag: String, ) { if (tag != ModelChangeTags.NORMAL) { diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt index 26261d8db2..34d2331ba6 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt @@ -5,6 +5,7 @@ import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.Model import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.modeling.SingletonModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -30,7 +31,7 @@ internal abstract class SingletonModelStoreListener( } override fun onModelReplaced( - model: TModel, + model: ModelReplacedArgs, tag: String, ) { if (tag != ModelChangeTags.NORMAL) { @@ -62,7 +63,7 @@ internal abstract class SingletonModelStoreListener( * * @return The operation to enqueue when the model has been replaced, or null if no operation should be enqueued. */ - abstract fun getReplaceOperation(model: TModel): Operation? + abstract fun getReplaceOperation(model: ModelReplacedArgs): Operation? /** * Called when the model has been updated. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt index b3e2bc3864..3c628ce375 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt @@ -138,4 +138,15 @@ interface IUserManager { * Return a copy of all local tags from the current user. */ fun getTags(): Map + + /** + * Add an observer to the user state, allowing the provider to be + * notified whenever the user state has changed. + */ + fun addObserver(observer: IUserStateObserver) + + /** + * Remove an observer from the user state. + */ + fun removeObserver(observer: IUserStateObserver) } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt new file mode 100644 index 0000000000..7a0f9f3e82 --- /dev/null +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt @@ -0,0 +1,15 @@ +package com.onesignal.user + +/** + * A user state changed handler. Implement this interface and provide the implementation + * to be notified when the user has changed. + */ +interface IUserStateObserver { + /** + * Called when the user state this change handler was added to, has changed. A + * user state can change when user has logged in or out + * + * @param state The user changed state. + */ + fun onUserStateChange(state: UserChangedState) +} diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt new file mode 100644 index 0000000000..b6d74391cb --- /dev/null +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt @@ -0,0 +1,14 @@ +package com.onesignal.user + +import org.json.JSONObject + +class UserChangedState( + val previous: UserState, + val current: UserState, +) { + fun toJSONObject(): JSONObject { + return JSONObject() + .put("previous", previous.toJSONObject()) + .put("current", current.toJSONObject()) + } +} diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt new file mode 100644 index 0000000000..ac9ff10e34 --- /dev/null +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt @@ -0,0 +1,39 @@ +package com.onesignal.user + +import com.onesignal.common.IDManager +import org.json.JSONObject + +/** + * A user state. + */ +class UserState { + /** + * The unique identifier for your OneSignal account. This will be a null string until the + * user has been successfully logged in on the backend and assigned an ID. + * Use [addObserver] to be notified when the [onesignalId] has been successfully assigned. + */ + val onesignalId: String? + + /** + * The external identifier that you use to identify users. This will be an null string + * until the user has been successfully logged in on the backend and + * assigned an ID. Use [addObserver] to be notified when the [externalId] has + * been successfully assigned. + */ + val externalId: String? + + constructor(onesignalId: String?, externalId: String?) { + if (onesignalId == null) { + this.onesignalId = null + } else { + this.onesignalId = IDManager.getNonLocalIDOrNull(onesignalId) + } + this.externalId = externalId + } + + fun toJSONObject(): JSONObject { + return JSONObject() + .put("onesignalId", onesignalId) + .put("externalId", externalId) + } +} diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt index 0effb3c9ed..f77a55f7a3 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt @@ -1,10 +1,18 @@ package com.onesignal.user.internal +import com.onesignal.common.IDManager import com.onesignal.common.OneSignalUtils +import com.onesignal.common.events.EventProducer +import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler +import com.onesignal.common.modeling.ModelChangedArgs +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.language.ILanguageContext import com.onesignal.debug.LogLevel import com.onesignal.debug.internal.logging.Logging import com.onesignal.user.IUserManager +import com.onesignal.user.IUserStateObserver +import com.onesignal.user.UserChangedState +import com.onesignal.user.UserState import com.onesignal.user.internal.backend.IdentityConstants import com.onesignal.user.internal.identity.IdentityModel import com.onesignal.user.internal.identity.IdentityModelStore @@ -19,7 +27,10 @@ internal open class UserManager( private val _identityModelStore: IdentityModelStore, private val _propertiesModelStore: PropertiesModelStore, private val _languageContext: ILanguageContext, -) : IUserManager { +) : IUserManager, ISingletonModelStoreChangeHandler { + val onesignalId: String? + get() = IDManager.getNonLocalIDOrNull(_identityModel.onesignalId) + val externalId: String? get() = _identityModel.externalId @@ -29,6 +40,8 @@ internal open class UserManager( val subscriptions: SubscriptionList get() = _subscriptionManager.subscriptions + val changeHandlersNotifier = EventProducer() + override val pushSubscription: IPushSubscription get() = _subscriptionManager.subscriptions.push @@ -42,6 +55,10 @@ internal open class UserManager( _languageContext.language = value } + init { + _identityModelStore.subscribe(this) + } + override fun addAlias( label: String, id: String, @@ -219,4 +236,45 @@ internal open class UserManager( override fun getTags(): Map { return _propertiesModel.tags.toMap() } + + override fun addObserver(observer: IUserStateObserver) { + changeHandlersNotifier.subscribe(observer) + } + + override fun removeObserver(observer: IUserStateObserver) { + changeHandlersNotifier.unsubscribe(observer) + } + + override fun onModelReplaced( + args: ModelReplacedArgs, + tag: String, + ) { + val oldUserState = UserState(args.oldModel[IdentityConstants.ONESIGNAL_ID], args.oldModel.externalId) + val newUserState = UserState(args.newModel.onesignalId, args.newModel.externalId) + + // do not fire the callback if onesignalId is null or the new model is identical to the old model + if (newUserState.onesignalId == null || + oldUserState.onesignalId.equals(newUserState.onesignalId) && + oldUserState.externalId.equals(newUserState.externalId) + ) { + return + } + this.changeHandlersNotifier.fire { + it.onUserStateChange(UserChangedState(oldUserState, newUserState)) + } + } + + override fun onModelUpdated( + args: ModelChangedArgs, + tag: String, + ) { + if (args.property.equals(IdentityConstants.ONESIGNAL_ID)) { + val oldUserState = UserState(args.oldValue.toString(), externalId) + val newUserState = UserState(args.newValue.toString(), externalId) + this.changeHandlersNotifier.fire { + it.onUserStateChange(UserChangedState(oldUserState, newUserState)) + } + } + Logging.debug(args.property) + } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt index 90a565a5a2..cb4d7cffeb 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.operations.impl.listeners +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.config.ConfigModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -14,7 +15,7 @@ internal class IdentityModelStoreListener( opRepo: IOperationRepo, private val _configModelStore: ConfigModelStore, ) : SingletonModelStoreListener(store, opRepo) { - override fun getReplaceOperation(model: IdentityModel): Operation? { + override fun getReplaceOperation(model: ModelReplacedArgs): Operation? { // when the identity model is replaced, nothing to do on the backend. Already handled via login process. return null } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt index d020c5cc66..ed724a0cc7 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt @@ -1,5 +1,6 @@ package com.onesignal.user.internal.operations.impl.listeners +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.config.ConfigModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -15,7 +16,7 @@ internal class PropertiesModelStoreListener( opRepo: IOperationRepo, private val _configModelStore: ConfigModelStore, ) : SingletonModelStoreListener(store, opRepo) { - override fun getReplaceOperation(model: PropertiesModel): Operation? { + override fun getReplaceOperation(model: ModelReplacedArgs): Operation? { // when the property model is replaced, nothing to do on the backend. Already handled via login process. return null } diff --git a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/mocks/MockHelper.kt b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/mocks/MockHelper.kt index 1974ff9a3c..58cf3a3f82 100644 --- a/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/mocks/MockHelper.kt +++ b/OneSignalSDK/onesignal/core/src/test/java/com/onesignal/mocks/MockHelper.kt @@ -65,7 +65,7 @@ object MockHelper { action(identityModel) } - val mockIdentityStore = mockk() + val mockIdentityStore = mockk(relaxed = true) every { mockIdentityStore.model } returns identityModel diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt index df598f273d..fe1e299457 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt @@ -8,6 +8,7 @@ import com.onesignal.common.events.EventProducer import com.onesignal.common.exceptions.BackendException import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangedArgs +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.application.IApplicationService import com.onesignal.core.internal.config.ConfigModel @@ -184,7 +185,7 @@ internal class InAppMessagesManager( } override fun onModelReplaced( - model: ConfigModel, + model: ModelReplacedArgs, tag: String, ) { suspendifyOnThread { diff --git a/OneSignalSDK/onesignal/notifications/consumer-rules.pro b/OneSignalSDK/onesignal/notifications/consumer-rules.pro index d9fc948356..7826a22a4b 100644 --- a/OneSignalSDK/onesignal/notifications/consumer-rules.pro +++ b/OneSignalSDK/onesignal/notifications/consumer-rules.pro @@ -20,6 +20,10 @@ void onPushSubscriptionChange(com.onesignal.user.subscriptions.PushSubscriptionChangedState); } +-keep class ** implements com.onesignal.user.IUserStateObserver { + void onUserStateChange(com.onesignal.user.UserChangedState); +} + -keep class ** implements com.onesignal.notifications.INotificationServiceExtension{ void onNotificationReceived(com.onesignal.notifications.INotificationReceivedEvent); } diff --git a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt index 49b9f95e2e..88eb84e201 100644 --- a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt +++ b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt @@ -3,6 +3,7 @@ package com.onesignal.notifications.internal.listeners import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs +import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.config.ConfigModel import com.onesignal.core.internal.config.ConfigModelStore @@ -42,7 +43,7 @@ internal class DeviceRegistrationListener( } override fun onModelReplaced( - model: ConfigModel, + model: ModelReplacedArgs, tag: String, ) { // we only need to do things when the config model was replaced @@ -51,7 +52,7 @@ internal class DeviceRegistrationListener( return } - _channelManager.processChannelList(model.notificationChannels) + _channelManager.processChannelList(model.newModel.notificationChannels) retrievePushTokenAndUpdateSubscription() } From 07ae6e034a136da15649877337b3257e966c065b Mon Sep 17 00:00:00 2001 From: jinliu9508 Date: Tue, 5 Dec 2023 18:32:12 -0500 Subject: [PATCH 2/5] Remove code related to the previous user state --- .../sdktest/application/MainApplication.java | 11 +++++++ .../sdktest/model/MainActivityViewModel.java | 25 +-------------- .../java/com/onesignal/common/IDManager.kt | 15 --------- .../onesignal/common/events/EventProducer.kt | 2 +- .../common/modeling/IModelChangedHandler.kt | 11 ------- .../ISingletonModelStoreChangeHandler.kt | 2 +- .../common/modeling/SingletonModelStore.kt | 4 +-- .../config/impl/ConfigModelStoreListener.kt | 3 +- .../listeners/SingletonModelStoreListener.kt | 5 ++- .../java/com/onesignal/user/IUserManager.kt | 10 ++++++ .../com/onesignal/user/UserChangedState.kt | 2 -- .../main/java/com/onesignal/user/UserState.kt | 27 +++++----------- .../onesignal/user/internal/UserManager.kt | 32 +++++-------------- .../listeners/IdentityModelStoreListener.kt | 3 +- .../listeners/PropertiesModelStoreListener.kt | 3 +- .../internal/InAppMessagesManager.kt | 3 +- .../listeners/DeviceRegistrationListener.kt | 5 ++- 17 files changed, 49 insertions(+), 114 deletions(-) diff --git a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java index 8d82807c91..eaecd7774c 100644 --- a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java +++ b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java @@ -26,6 +26,9 @@ import com.onesignal.sdktest.constant.Text; import com.onesignal.sdktest.notification.OneSignalNotificationSender; import com.onesignal.sdktest.util.SharedPreferenceUtil; +import com.onesignal.user.IUserStateObserver; +import com.onesignal.user.UserChangedState; +import com.onesignal.user.UserState; import org.json.JSONObject; @@ -116,6 +119,14 @@ public void onWillDisplay(@NonNull INotificationWillDisplayEvent event) { } }); + OneSignal.getUser().addObserver(new IUserStateObserver() { + @Override + public void onUserStateChange(@NonNull UserChangedState state) { + UserState currentUserState = state.getCurrent(); + Log.v(Tag.LOG_TAG, "onUserStateChange fired " + currentUserState.toJSONObject()); + } + }); + OneSignal.getInAppMessages().setPaused(true); OneSignal.getLocation().setShared(false); diff --git a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java index 6aa6e10d21..58069a298c 100644 --- a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java +++ b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/model/MainActivityViewModel.java @@ -3,7 +3,6 @@ import android.app.Activity; import android.content.Context; import com.google.android.material.appbar.AppBarLayout; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; @@ -13,10 +12,8 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.appcompat.widget.Toolbar; - import android.content.Intent; import android.os.Build; -import android.util.Log; import android.util.Pair; import android.view.View; import android.view.ViewTreeObserver; @@ -25,17 +22,10 @@ import android.widget.RelativeLayout; import android.widget.Switch; import android.widget.TextView; - import com.onesignal.Continue; import com.onesignal.OneSignal; -import com.onesignal.debug.internal.logging.Logging; import com.onesignal.sdktest.adapter.SubscriptionRecyclerViewAdapter; -import com.onesignal.user.IUserStateObserver; -import com.onesignal.user.UserChangedState; -import com.onesignal.user.UserState; -import com.onesignal.user.subscriptions.IEmailSubscription; import com.onesignal.user.subscriptions.IPushSubscription; -import com.onesignal.user.subscriptions.ISmsSubscription; import com.onesignal.sdktest.R; import com.onesignal.sdktest.activity.SecondaryActivity; import com.onesignal.sdktest.adapter.InAppMessageRecyclerViewAdapter; @@ -61,13 +51,12 @@ import com.onesignal.user.subscriptions.ISubscription; import com.onesignal.user.subscriptions.IPushSubscriptionObserver; import com.onesignal.user.subscriptions.PushSubscriptionChangedState; - import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @RequiresApi(api = Build.VERSION_CODES.N) -public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver, IUserStateObserver { +public class MainActivityViewModel implements ActivityViewModel, IPushSubscriptionObserver { private Animate animate; private Dialog dialog; @@ -297,7 +286,6 @@ public ActivityViewModel onActivityCreated(Context context) { triggerArrayList = new ArrayList<>(); OneSignal.getUser().getPushSubscription().addObserver(this); - OneSignal.getUser().addObserver(this); return this; } @@ -506,17 +494,6 @@ public void onPushSubscriptionChange(@NonNull PushSubscriptionChangedState state refreshSubscriptionState(); } - @Override - public void onUserStateChange(@NonNull UserChangedState state) { - UserState currentState = state.getCurrent(); - UserState prevState = state.getPrevious(); - Logging.debug("onUserStateChanged; previous onesignalId: " + String.valueOf(prevState.getOnesignalId()) - + ", previous externalId: " + String.valueOf(prevState.getExternalId()) - + ", current onesignalId: " + String.valueOf(currentState.getOnesignalId()) - + ", current externalId: " + String.valueOf(currentState.getExternalId()), - null); - } - private class DummySubscription implements ISubscription { private String _id; diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt index c3de6dcb08..d0e168a787 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/IDManager.kt @@ -26,19 +26,4 @@ object IDManager { * @return true if the [id] provided was created via [createLocalId]. */ fun isLocalId(id: String): Boolean = id.startsWith(LOCAL_PREFIX) - - /** - * Get non local ID or null. - * - * @param id The ID to test. - * - * @return [id] or null if the [id] provided was created via [createLocalId]. - */ - fun getNonLocalIDOrNull(id: String): String? { - if (isLocalId(id)) { - return null - } - - return id - } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt index d05a9a46f7..c8c0aedb0b 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/events/EventProducer.kt @@ -38,7 +38,7 @@ open class EventProducer : IEventNotifier { * * @param callback The callback will be invoked for each subscribed handler, allowing you to call the handler. */ - open fun fire(callback: (THandler) -> Unit) { + fun fire(callback: (THandler) -> Unit) { synchronized(subscribers) { for (s in subscribers) { callback(s) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt index ae7eec5eba..ba526dc4ad 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/IModelChangedHandler.kt @@ -49,14 +49,3 @@ class ModelChangedArgs( */ val newValue: Any?, ) - -/** - * The arguments passed to the [IModelChangedHandler] handler when subscribed via [Model.subscribe] - */ -class ModelReplacedArgs( - /** - * The full model in its previous and current state. - */ - val oldModel: TModel, - val newModel: TModel, -) where TModel : Model diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt index 143711f2d3..c929fe8ff9 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/common/modeling/ISingletonModelStoreChangeHandler.kt @@ -12,7 +12,7 @@ interface ISingletonModelStoreChangeHandler where TModel : Model { * @param tag The tag which identifies how/why the model was replaced. */ fun onModelReplaced( - model: ModelReplacedArgs, + model: TModel, tag: String, ) 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 3305ebdf54..5bffa828bc 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 @@ -36,12 +36,10 @@ open class SingletonModelStore( tag: String, ) { synchronized(replaceLock) { - val oldModel = this.store.create() ?: throw Exception("Unable to initialize model from store $store") - oldModel.initializeFromModel(singletonId, this.model) val existingModel = this.model existingModel.initializeFromModel(singletonId, model) store.persist() - changeSubscription.fire { it.onModelReplaced(ModelReplacedArgs(oldModel, existingModel), tag) } + changeSubscription.fire { it.onModelReplaced(existingModel, tag) } } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt index 7121989606..87d7eae6b0 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/config/impl/ConfigModelStoreListener.kt @@ -4,7 +4,6 @@ import com.onesignal.common.exceptions.BackendException import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.backend.IParamsBackendService import com.onesignal.core.internal.config.ConfigModel @@ -44,7 +43,7 @@ internal class ConfigModelStoreListener( } override fun onModelReplaced( - model: ModelReplacedArgs, + model: ConfigModel, tag: String, ) { if (tag != ModelChangeTags.NORMAL) { diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt index 34d2331ba6..26261d8db2 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/core/internal/operations/listeners/SingletonModelStoreListener.kt @@ -5,7 +5,6 @@ import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.Model import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.modeling.SingletonModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -31,7 +30,7 @@ internal abstract class SingletonModelStoreListener( } override fun onModelReplaced( - model: ModelReplacedArgs, + model: TModel, tag: String, ) { if (tag != ModelChangeTags.NORMAL) { @@ -63,7 +62,7 @@ internal abstract class SingletonModelStoreListener( * * @return The operation to enqueue when the model has been replaced, or null if no operation should be enqueued. */ - abstract fun getReplaceOperation(model: ModelReplacedArgs): Operation? + abstract fun getReplaceOperation(model: TModel): Operation? /** * Called when the model has been updated. diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt index 3c628ce375..9d10b948e1 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt @@ -25,6 +25,16 @@ interface IUserManager { */ val pushSubscription: IPushSubscription + /** + * onesignalId, null if this is current unavailable + */ + val onesignalId: String + + /** + * externalId, null if this is current unavailable + */ + val externalId: String + /** * Set the 2-character language either as a detected language or explicitly set for this user. See * See [Supported Languages | OneSignal](https://documentation.onesignal.com/docs/language-localization#what-languages-are-supported) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt index b6d74391cb..eab8ba9b8b 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt @@ -3,12 +3,10 @@ package com.onesignal.user import org.json.JSONObject class UserChangedState( - val previous: UserState, val current: UserState, ) { fun toJSONObject(): JSONObject { return JSONObject() - .put("previous", previous.toJSONObject()) .put("current", current.toJSONObject()) } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt index ac9ff10e34..2b741bd3d0 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt @@ -1,36 +1,25 @@ package com.onesignal.user -import com.onesignal.common.IDManager import org.json.JSONObject /** * A user state. */ -class UserState { +class UserState( /** - * The unique identifier for your OneSignal account. This will be a null string until the + * The unique identifier for your OneSignal account. This will be an empty string until the * user has been successfully logged in on the backend and assigned an ID. * Use [addObserver] to be notified when the [onesignalId] has been successfully assigned. */ - val onesignalId: String? - + val onesignalId: String, /** - * The external identifier that you use to identify users. This will be an null string - * until the user has been successfully logged in on the backend and - * assigned an ID. Use [addObserver] to be notified when the [externalId] has + * The external identifier that you use to identify users. This will be an empty string + * until the user has been successfully logged in on the backend and assigned an ID. + * Use [addObserver] to be notified when the [externalId] has * been successfully assigned. */ - val externalId: String? - - constructor(onesignalId: String?, externalId: String?) { - if (onesignalId == null) { - this.onesignalId = null - } else { - this.onesignalId = IDManager.getNonLocalIDOrNull(onesignalId) - } - this.externalId = externalId - } - + val externalId: String, +) { fun toJSONObject(): JSONObject { return JSONObject() .put("onesignalId", onesignalId) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt index f77a55f7a3..147aa4f4e5 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt @@ -5,7 +5,6 @@ import com.onesignal.common.OneSignalUtils import com.onesignal.common.events.EventProducer import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangedArgs -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.language.ILanguageContext import com.onesignal.debug.LogLevel import com.onesignal.debug.internal.logging.Logging @@ -28,11 +27,11 @@ internal open class UserManager( private val _propertiesModelStore: PropertiesModelStore, private val _languageContext: ILanguageContext, ) : IUserManager, ISingletonModelStoreChangeHandler { - val onesignalId: String? - get() = IDManager.getNonLocalIDOrNull(_identityModel.onesignalId) + override val onesignalId: String + get() = if (IDManager.isLocalId(_identityModel.onesignalId)) "" else _identityModel.onesignalId - val externalId: String? - get() = _identityModel.externalId + override val externalId: String + get() = _identityModel.externalId ?: "" val aliases: Map get() = _identityModel.filter { it.key != IdentityModel::id.name }.toMap() @@ -246,33 +245,18 @@ internal open class UserManager( } override fun onModelReplaced( - args: ModelReplacedArgs, + model: IdentityModel, tag: String, - ) { - val oldUserState = UserState(args.oldModel[IdentityConstants.ONESIGNAL_ID], args.oldModel.externalId) - val newUserState = UserState(args.newModel.onesignalId, args.newModel.externalId) - - // do not fire the callback if onesignalId is null or the new model is identical to the old model - if (newUserState.onesignalId == null || - oldUserState.onesignalId.equals(newUserState.onesignalId) && - oldUserState.externalId.equals(newUserState.externalId) - ) { - return - } - this.changeHandlersNotifier.fire { - it.onUserStateChange(UserChangedState(oldUserState, newUserState)) - } - } + ) { } override fun onModelUpdated( args: ModelChangedArgs, tag: String, ) { - if (args.property.equals(IdentityConstants.ONESIGNAL_ID)) { - val oldUserState = UserState(args.oldValue.toString(), externalId) + if (args.property == IdentityConstants.ONESIGNAL_ID) { val newUserState = UserState(args.newValue.toString(), externalId) this.changeHandlersNotifier.fire { - it.onUserStateChange(UserChangedState(oldUserState, newUserState)) + it.onUserStateChange(UserChangedState(newUserState)) } } Logging.debug(args.property) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt index cb4d7cffeb..90a565a5a2 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/IdentityModelStoreListener.kt @@ -1,6 +1,5 @@ package com.onesignal.user.internal.operations.impl.listeners -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.config.ConfigModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -15,7 +14,7 @@ internal class IdentityModelStoreListener( opRepo: IOperationRepo, private val _configModelStore: ConfigModelStore, ) : SingletonModelStoreListener(store, opRepo) { - override fun getReplaceOperation(model: ModelReplacedArgs): Operation? { + override fun getReplaceOperation(model: IdentityModel): Operation? { // when the identity model is replaced, nothing to do on the backend. Already handled via login process. return null } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt index ed724a0cc7..d020c5cc66 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/operations/impl/listeners/PropertiesModelStoreListener.kt @@ -1,6 +1,5 @@ package com.onesignal.user.internal.operations.impl.listeners -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.core.internal.config.ConfigModelStore import com.onesignal.core.internal.operations.IOperationRepo import com.onesignal.core.internal.operations.Operation @@ -16,7 +15,7 @@ internal class PropertiesModelStoreListener( opRepo: IOperationRepo, private val _configModelStore: ConfigModelStore, ) : SingletonModelStoreListener(store, opRepo) { - override fun getReplaceOperation(model: ModelReplacedArgs): Operation? { + override fun getReplaceOperation(model: PropertiesModel): Operation? { // when the property model is replaced, nothing to do on the backend. Already handled via login process. return null } diff --git a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt index fe1e299457..df598f273d 100644 --- a/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt +++ b/OneSignalSDK/onesignal/in-app-messages/src/main/java/com/onesignal/inAppMessages/internal/InAppMessagesManager.kt @@ -8,7 +8,6 @@ import com.onesignal.common.events.EventProducer import com.onesignal.common.exceptions.BackendException import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangedArgs -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.application.IApplicationService import com.onesignal.core.internal.config.ConfigModel @@ -185,7 +184,7 @@ internal class InAppMessagesManager( } override fun onModelReplaced( - model: ModelReplacedArgs, + model: ConfigModel, tag: String, ) { suspendifyOnThread { diff --git a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt index 88eb84e201..49b9f95e2e 100644 --- a/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt +++ b/OneSignalSDK/onesignal/notifications/src/main/java/com/onesignal/notifications/internal/listeners/DeviceRegistrationListener.kt @@ -3,7 +3,6 @@ package com.onesignal.notifications.internal.listeners import com.onesignal.common.modeling.ISingletonModelStoreChangeHandler import com.onesignal.common.modeling.ModelChangeTags import com.onesignal.common.modeling.ModelChangedArgs -import com.onesignal.common.modeling.ModelReplacedArgs import com.onesignal.common.threading.suspendifyOnThread import com.onesignal.core.internal.config.ConfigModel import com.onesignal.core.internal.config.ConfigModelStore @@ -43,7 +42,7 @@ internal class DeviceRegistrationListener( } override fun onModelReplaced( - model: ModelReplacedArgs, + model: ConfigModel, tag: String, ) { // we only need to do things when the config model was replaced @@ -52,7 +51,7 @@ internal class DeviceRegistrationListener( return } - _channelManager.processChannelList(model.newModel.notificationChannels) + _channelManager.processChannelList(model.notificationChannels) retrievePushTokenAndUpdateSubscription() } From dbf14527142be465d67e76c9ddb5bcbae6acace1 Mon Sep 17 00:00:00 2001 From: jinliu9508 Date: Fri, 8 Dec 2023 16:05:14 -0500 Subject: [PATCH 3/5] Improve comments --- .../onesignal/sdktest/application/MainApplication.java | 7 +++---- .../src/main/java/com/onesignal/user/IUserManager.kt | 5 +++-- .../main/java/com/onesignal/user/internal/UserManager.kt | 7 +++---- .../com/onesignal/user/{ => state}/IUserStateObserver.kt | 6 +++--- .../com/onesignal/user/{ => state}/UserChangedState.kt | 2 +- .../java/com/onesignal/user/{ => state}/UserState.kt | 9 ++++----- OneSignalSDK/onesignal/notifications/consumer-rules.pro | 4 ++-- 7 files changed, 19 insertions(+), 21 deletions(-) rename OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/{ => state}/IUserStateObserver.kt (63%) rename OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/{ => state}/UserChangedState.kt (86%) rename OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/{ => state}/UserState.kt (65%) diff --git a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java index eaecd7774c..7c48f4b070 100644 --- a/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java +++ b/Examples/OneSignalDemo/app/src/main/java/com/onesignal/sdktest/application/MainApplication.java @@ -8,7 +8,6 @@ import androidx.multidex.MultiDexApplication; import com.onesignal.OneSignal; -import com.onesignal.inAppMessages.IInAppMessage; import com.onesignal.inAppMessages.IInAppMessageClickListener; import com.onesignal.inAppMessages.IInAppMessageClickEvent; import com.onesignal.inAppMessages.IInAppMessageDidDismissEvent; @@ -26,9 +25,9 @@ import com.onesignal.sdktest.constant.Text; import com.onesignal.sdktest.notification.OneSignalNotificationSender; import com.onesignal.sdktest.util.SharedPreferenceUtil; -import com.onesignal.user.IUserStateObserver; -import com.onesignal.user.UserChangedState; -import com.onesignal.user.UserState; +import com.onesignal.user.state.IUserStateObserver; +import com.onesignal.user.state.UserChangedState; +import com.onesignal.user.state.UserState; import org.json.JSONObject; diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt index 9d10b948e1..850bc5567f 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt @@ -1,6 +1,7 @@ package com.onesignal.user import com.onesignal.OneSignal +import com.onesignal.user.state.IUserStateObserver import com.onesignal.user.subscriptions.IPushSubscription /** @@ -26,12 +27,12 @@ interface IUserManager { val pushSubscription: IPushSubscription /** - * onesignalId, null if this is current unavailable + * onesignalId, empty if this is current unavailable */ val onesignalId: String /** - * externalId, null if this is current unavailable + * externalId, empty if this is current unavailable */ val externalId: String diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt index 147aa4f4e5..934d233183 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/internal/UserManager.kt @@ -9,9 +9,6 @@ import com.onesignal.core.internal.language.ILanguageContext import com.onesignal.debug.LogLevel import com.onesignal.debug.internal.logging.Logging import com.onesignal.user.IUserManager -import com.onesignal.user.IUserStateObserver -import com.onesignal.user.UserChangedState -import com.onesignal.user.UserState import com.onesignal.user.internal.backend.IdentityConstants import com.onesignal.user.internal.identity.IdentityModel import com.onesignal.user.internal.identity.IdentityModelStore @@ -19,6 +16,9 @@ import com.onesignal.user.internal.properties.PropertiesModel import com.onesignal.user.internal.properties.PropertiesModelStore import com.onesignal.user.internal.subscriptions.ISubscriptionManager import com.onesignal.user.internal.subscriptions.SubscriptionList +import com.onesignal.user.state.IUserStateObserver +import com.onesignal.user.state.UserChangedState +import com.onesignal.user.state.UserState import com.onesignal.user.subscriptions.IPushSubscription internal open class UserManager( @@ -259,6 +259,5 @@ internal open class UserManager( it.onUserStateChange(UserChangedState(newUserState)) } } - Logging.debug(args.property) } } diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/IUserStateObserver.kt similarity index 63% rename from OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt rename to OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/IUserStateObserver.kt index 7a0f9f3e82..aa25d9106e 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserStateObserver.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/IUserStateObserver.kt @@ -1,8 +1,8 @@ -package com.onesignal.user +package com.onesignal.user.state /** - * A user state changed handler. Implement this interface and provide the implementation - * to be notified when the user has changed. + * A user state changed observer. Implement this interface and provide the implementation + * to be notified when the user state has changed. */ interface IUserStateObserver { /** diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserChangedState.kt similarity index 86% rename from OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt rename to OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserChangedState.kt index eab8ba9b8b..aef57d55bb 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserChangedState.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserChangedState.kt @@ -1,4 +1,4 @@ -package com.onesignal.user +package com.onesignal.user.state import org.json.JSONObject diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserState.kt similarity index 65% rename from OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt rename to OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserState.kt index 2b741bd3d0..ea986e84c6 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/UserState.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/state/UserState.kt @@ -1,4 +1,4 @@ -package com.onesignal.user +package com.onesignal.user.state import org.json.JSONObject @@ -13,10 +13,9 @@ class UserState( */ val onesignalId: String, /** - * The external identifier that you use to identify users. This will be an empty string - * until the user has been successfully logged in on the backend and assigned an ID. - * Use [addObserver] to be notified when the [externalId] has - * been successfully assigned. + * The external identifier that you use to identify users. Use [addObserver] to be notified + * when the [externalId] has been successfully assigned. This will be an empty string if no + * external identifier has been assigned to the associated [onesignalId]. */ val externalId: String, ) { diff --git a/OneSignalSDK/onesignal/notifications/consumer-rules.pro b/OneSignalSDK/onesignal/notifications/consumer-rules.pro index 7826a22a4b..2d829efe1b 100644 --- a/OneSignalSDK/onesignal/notifications/consumer-rules.pro +++ b/OneSignalSDK/onesignal/notifications/consumer-rules.pro @@ -20,8 +20,8 @@ void onPushSubscriptionChange(com.onesignal.user.subscriptions.PushSubscriptionChangedState); } --keep class ** implements com.onesignal.user.IUserStateObserver { - void onUserStateChange(com.onesignal.user.UserChangedState); +-keep class ** implements com.onesignal.user.state.IUserStateObserver { + void onUserStateChange(com.onesignal.user.state.UserChangedState); } -keep class ** implements com.onesignal.notifications.INotificationServiceExtension{ From 847a721a38dffd04ec7cdef5f3a44900ca68d67b Mon Sep 17 00:00:00 2001 From: jinliu9508 Date: Wed, 13 Dec 2023 12:01:00 -0500 Subject: [PATCH 4/5] Update comments to better explain the IDs --- .../src/main/java/com/onesignal/user/IUserManager.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt index 850bc5567f..2b71ca11de 100644 --- a/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt +++ b/OneSignalSDK/onesignal/core/src/main/java/com/onesignal/user/IUserManager.kt @@ -27,12 +27,15 @@ interface IUserManager { val pushSubscription: IPushSubscription /** - * onesignalId, empty if this is current unavailable + * The UUID generated by OneSignal to represent a user, empty if this is currently unavailable */ val onesignalId: String /** - * externalId, empty if this is current unavailable + * The External ID is OneSignal's default and recommended alias label. This should be the main + * identifier you use to identify users. It is set when calling the [OneSignal.login] method. + * + * This is empty if the External ID has not been set. */ val externalId: String @@ -153,6 +156,9 @@ interface IUserManager { /** * Add an observer to the user state, allowing the provider to be * notified whenever the user state has changed. + * + * Important: When using the observer to retrieve the onesignalId, check the externalId as well + * to confirm the values are associated with the expected user. */ fun addObserver(observer: IUserStateObserver) From c5669d3371cd7fa1c5d435a9b193d59174a15693 Mon Sep 17 00:00:00 2001 From: Nan Date: Thu, 28 Dec 2023 11:43:46 -0800 Subject: [PATCH 5/5] Update Migration Guide with ID getters and observer --- MIGRATION_GUIDE.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 6414f29a10..94a2ec5c31 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -259,8 +259,12 @@ The user name space is accessible via `OneSignal.User` (in Kotlin) or `OneSignal | `val pushSubscription: IPushSubscription` | `IPushSubscription getPushSubscription()` | *The push subscription associated to the current user.* | | `fun setLanguage(value: String)` | `void setLanguage(String value)` | *Set the 2-character language either as a detected language or explicitly set for this user.* | | `fun pushSubscription.addChangeHandler(handler: ISubscriptionChangedHandler)` | `void pushSubscription.addChangeHandler(ISubscriptionChangedHandler handler)` | *Adds a change handler that will run whenever the push subscription has been changed.* | +| `val onesignalId: String` | `String getOnesignalId()` | *Returns the OneSignal ID for the current user, which can be the empty string if it is not yet available.* | +| `val externalId: String` | `String getExternalId()` | *Returns the external ID for the current user, which can be the empty string if not set.* | +| `fun addObserver(observer: IUserStateObserver)` | `void addObserve(IUserStateObserver observer)` | *The `IUserStateObserver.onUserStateChange` method will be fired on the passed-in object when the user state changes. The User State contains the onesignalId and externalId (which can be empty strings), and the observer will be fired when these values change.* | +| `fun removeObserver(observer: IUserStateObserver)` | `void removeObserver(IUserStateObserver observer)` | *Remove a user state observer that has been previously added.* | | `fun addAlias(label: String, id: String)` | `void addAlias(String label, String id)` | *Set an alias for the current user. If this alias already exists it will be overwritten.* | -| `fun addAliases(aliases: Map)` | `void addAliases(Map aliases)` | S*et aliases for the current user. If any alias already exists it will be overwritten.* | +| `fun addAliases(aliases: Map)` | `void addAliases(Map aliases)` | *Set aliases for the current user. If any alias already exists it will be overwritten.* | | `fun removeAlias(label: String)` | `void removeAlias(String label)` | *Remove an alias from the current user.* | | `fun removeAliases(labels: Collection)` | `void removeAliases(Collection labels)` | *Remove multiple aliases from the current user.* | | `fun addEmail(email: String)` | `void addEmail(String email)` | *Add a new email subscription to the current user.* |