Skip to content

Commit

Permalink
Merge pull request #98 from OneSignal/get_ids
Browse files Browse the repository at this point in the history
Add OneSignalId and ExternalId getters as well as a user changed observer
  • Loading branch information
emawby committed Apr 15, 2024
2 parents 4faa752 + 3005fc0 commit f37e79c
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 1 deletion.
13 changes: 12 additions & 1 deletion MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ Once (or if) the user is no longer identifiable in your app (i.e. they logged ou

Logging out has the affect of reverting to a “device-scoped” user, which is the new owner of the device’s push subscription.

To observe changes to the onesignalId or externalId you can add a custom method to the event:

OneSignal.User.Changed += User_Changed;

private void User_Changed(object sender, OneSignalSDK.DotNet.Core.User.UserStateChangedEventArgs e) {
var user = e.State.Current;
...
}

## Subscriptions

Expand Down Expand Up @@ -172,7 +180,10 @@ The user name space is accessible via `OneSignal.User` and provides access to us
| **C#** | **Description** |
| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `IPushSubscription PushSubscription { get; }` | *The push subscription associated to the current user.* |
| `string Language { set; }` | *Set the 2-character language either as a detected language or explicitly set for this user.* |
| `string Language { set; }` | *Set the 2-character language either as a detected language or explicitly set for this user.*
| `string OneSignalId` | *The UUID generated by OneSignal to represent a user, null if this is currently unavailable.* |
| `string ExternalId` | *The External ID is OneSignal's default and recommended alias label. This should be the mainidentifier you use to identify users. It is set when calling the [OneSignal.login] method. Return null if this is currently unavailable.*
| `event EventHandler<UserStateChangedEventArgs> Changed` | *Adds a change event that will run whenever the onesignalId or externalId has been changed.*
| `void AddAlias(string label, string id)` | *Set an alias for the current user. If this alias already exists it will be overwritten.* |
| `void AddAliases(IDictionary<string, string> aliases)` | *Set aliases for the current user. If any alias already exists it will be overwritten.* |
| `void RemoveAlias(string label)` | *Remove an alias from the current user.* |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<attr path="/api/package[@name='com.onesignal.session']" name="managedName">Com.OneSignal.Android.Session</attr>
<attr path="/api/package[@name='com.onesignal.user']" name="managedName">Com.OneSignal.Android.User</attr>
<attr path="/api/package[@name='com.onesignal.user.subscriptions']" name="managedName">Com.OneSignal.Android.User.Subscriptions</attr>
<attr path="/api/package[@name='com.onesignal.user.state']" name="managedName">Com.OneSignal.Android.User.State</attr>

<remove-node path="/api/package[starts-with(@name, 'com.onesignal.common.events')]" />
<remove-node path="/api/package[starts-with(@name, 'com.onesignal.common.exceptions')]" />
Expand Down
52 changes: 52 additions & 0 deletions OneSignalSDK.DotNet.Android/AndroidUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,33 @@ public string Language

public IPushSubscription PushSubscription { get; } = new AndroidPushSubscription();

private InternalUserChangedHandler? _userChangedHandler;

public void Initialize()
{
_userChangedHandler = new InternalUserChangedHandler(this);
OneSignalNative.User.AddObserver(_userChangedHandler);
((AndroidPushSubscription)PushSubscription).Initialize();
}

public string OneSignalId
{
get {
string id = OneSignalNative.User.OnesignalId;
return string.IsNullOrEmpty(id)? null : id;
}
}

public string ExternalId
{
get {
string id = OneSignalNative.User.ExternalId;
return string.IsNullOrEmpty(id)? null : id;
}
}

public event EventHandler<UserStateChangedEventArgs> Changed;

public void AddAlias(string label, string id) => OneSignalNative.User.AddAlias(label, id);
public void AddAliases(IDictionary<string, string> aliases) => OneSignalNative.User.AddAliases(aliases);
public void RemoveAlias(string label) => OneSignalNative.User.RemoveAlias(label);
Expand All @@ -36,6 +58,35 @@ public void Initialize()
public void RemoveTag(string key) => OneSignalNative.User.RemoveTag(key);
public void RemoveTags(params string[] keys) => OneSignalNative.User.RemoveTags(keys);
public IDictionary<string, string> GetTags() => OneSignalNative.User.Tags;

private sealed class InternalUserState : IUserState
{
public string OneSignalId { get; }

public string ExternalId { get; }

public InternalUserState(string onesignalId, string externalId)
{
OneSignalId = onesignalId;
ExternalId = externalId;
}
}

private class InternalUserChangedHandler : Java.Lang.Object, Com.OneSignal.Android.User.State.IUserStateObserver
{
private AndroidUserManager _manager;
public InternalUserChangedHandler(AndroidUserManager manager)
{
_manager = manager;
}

public void OnUserStateChange(Com.OneSignal.Android.User.State.UserChangedState state)
{
var current = new InternalUserState(state.Current.OnesignalId, state.Current.ExternalId);
var userChangedState = new UserChangedState(current);
_manager.Changed?.Invoke(_manager, new UserStateChangedEventArgs(userChangedState));
}
}
}

public class AndroidPushSubscription : IPushSubscription
Expand Down Expand Up @@ -99,5 +150,6 @@ public void OnPushSubscriptionChange(Com.OneSignal.Android.User.Subscriptions.Pu
_manager.Changed?.Invoke(_manager, new PushSubscriptionChangedEventArgs(changedState));
}
}

}
}
18 changes: 18 additions & 0 deletions OneSignalSDK.DotNet.Core/User/IUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,24 @@ public interface IUserManager
/// </summary>
IPushSubscription PushSubscription { get; }

/// <summary>
/// The UUID generated by OneSignal to represent a user, null if this is currently unavailable.
/// </summary>
string OneSignalId { get; }

/// <summary>
/// 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 null if the External ID has not been set.
/// </summary>
string ExternalId { get; }

/// <summary>
/// When onesignalId or externalId has changed
/// </summary>
event EventHandler<UserStateChangedEventArgs> Changed;

/// <summary>
/// Set an alias for the current user. If this alias already exists it will be overwritten.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions OneSignalSDK.DotNet.Core/User/IUserState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace OneSignalSDK.DotNet.Core.User
{
public interface IUserState {
/// <summary>
/// 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 [Changed] to be notified when the [OneSignalId] has been successfully assigned.
/// </summary>
string OneSignalId { get; }

/// <summary>
/// The external identifier that you use to identify users. Use [Changed] 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].
/// </summary>
string ExternalId { get; }
}
}
24 changes: 24 additions & 0 deletions OneSignalSDK.DotNet.Core/User/UserStateChangedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace OneSignalSDK.DotNet.Core.User
{
/// <summary>
/// Several states associated with the SDK can be changed in and outside of the application.
/// </summary>
public class UserStateChangedEventArgs : EventArgs
{
public UserChangedState State { get; }

public UserStateChangedEventArgs(UserChangedState state) {
State = state;
}
}

public sealed class UserChangedState {
public IUserState Current { get; }

public UserChangedState(IUserState state) {
Current = state;
}
}
}
74 changes: 74 additions & 0 deletions OneSignalSDK.DotNet.iOS.Binding/ApiDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,60 @@ interface OSPushSubscription
void RemoveObserver(OSPushSubscriptionObserver observer);
}

// @interface OSUserState : NSObject
[BaseType (typeof(NSObject), Name = "_TtC13OneSignalUser11OSUserState")]
[DisableDefaultCtor]
interface OSUserState
{
// @property (readonly, copy, nonatomic) NSString * _Nullable onesignalId;
[NullAllowed, Export ("onesignalId")]
string OnesignalId { get; }

// @property (readonly, copy, nonatomic) NSString * _Nullable externalId;
[NullAllowed, Export ("externalId")]
string ExternalId { get; }

// @property (readonly, copy, nonatomic) NSString * _Nonnull description;
[Export ("description")]
string Description { get; }

// -(NSDictionary * _Nonnull)jsonRepresentation __attribute__((warn_unused_result("")));
[Export ("jsonRepresentation")]
//[Verify (MethodToProperty)]
NSDictionary JsonRepresentation { get; }
}

// @interface OSUserChangedState : NSObject
[BaseType (typeof(NSObject), Name = "_TtC13OneSignalUser18OSUserChangedState")]
[DisableDefaultCtor]
interface OSUserChangedState
{
// @property (readonly, nonatomic, strong) OSUserState * _Nonnull current;
[Export ("current", ArgumentSemantic.Strong)]
OSUserState Current { get; }

// @property (readonly, copy, nonatomic) NSString * _Nonnull description;
[Export ("description")]
string Description { get; }

// -(NSDictionary * _Nonnull)jsonRepresentation __attribute__((warn_unused_result("")));
[Export ("jsonRepresentation")]
//[Verify (MethodToProperty)]
NSDictionary JsonRepresentation { get; }
}

// @protocol OSUserStateObserver
[Protocol (Name = "_TtP13OneSignalUser19OSUserStateObserver_")]
[Model]
[BaseType(typeof(NSObject))]
interface OSUserStateObserver
{
// @required -(void)onUserStateDidChangeWithState:(OSUserChangedState * _Nonnull)state;
//[Abstract]
[Export ("onUserStateDidChangeWithState:")]
void OnUserStateDidChangeWithState (OSUserChangedState state);
}

// @protocol OSUser
[Protocol(Name = "_TtP13OneSignalUser6OSUser_")]
[BaseType(typeof(NSObject))]
Expand All @@ -454,6 +508,26 @@ interface OSUser
[Export ("pushSubscription", ArgumentSemantic.Strong)]
OSPushSubscription PushSubscription { get; }

// @required @property (readonly, copy, nonatomic) NSString * _Nullable onesignalId;
//[Abstract]
[NullAllowed, Export ("onesignalId")]
string OnesignalId { get; }

// @required @property (readonly, copy, nonatomic) NSString * _Nullable externalId;
//[Abstract]
[NullAllowed, Export ("externalId")]
string ExternalId { get; }

// @required -(void)addObserver:(id<OSUserStateObserver> _Nonnull)observer;
//[Abstract]
[Export ("addObserver:")]
void AddObserver (OSUserStateObserver observer);

// @required -(void)removeObserver:(id<OSUserStateObserver> _Nonnull)observer;
[Abstract]
[Export ("removeObserver:")]
void RemoveObserver (OSUserStateObserver observer);

// @required -(void)addAliasWithLabel:(NSString * _Nonnull)label id:(NSString * _Nonnull)id;
//[Abstract]
[Export ("addAliasWithLabel:id:")]
Expand Down
44 changes: 44 additions & 0 deletions OneSignalSDK.DotNet.iOS/iOSUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,26 @@ public string Language

public IPushSubscription PushSubscription { get; } = new iOSPushSubscription();

private InternalUserChangedHandler _userChangedHandler;

public void Initialize()
{
_userChangedHandler = new InternalUserChangedHandler(this);
OneSignalNative.User.AddObserver(_userChangedHandler);
((iOSPushSubscription)PushSubscription).Initialize();
}

public string OneSignalId
{
get => OneSignalNative.User.OnesignalId;
}

public string ExternalId
{
get => OneSignalNative.User.ExternalId;
}
public event EventHandler<UserStateChangedEventArgs>? Changed;

public void AddAlias(string label, string id) => OneSignalNative.User.AddAliasWithLabel(label, id);
public void AddAliases(IDictionary<string, string> aliases) => OneSignalNative.User.AddAliases(NativeConversion.DictToNSDict(aliases));
public void RemoveAlias(string label) => OneSignalNative.User.RemoveAlias(label);
Expand All @@ -39,6 +54,35 @@ public void Initialize()
public void RemoveTag(string key) => OneSignalNative.User.RemoveTag(key);
public void RemoveTags(params string[] keys) => OneSignalNative.User.RemoveTags(keys);
public IDictionary<string, string> GetTags() => FromNativeConversion.NSDictToPureStringDict(OneSignalNative.User.GetTags());

private sealed class InternalUserState : IUserState
{
public string OneSignalId { get; }

public string ExternalId { get; }

public InternalUserState(string onesignalId, string externalId)
{
OneSignalId = onesignalId;
ExternalId = externalId;
}
}

private class InternalUserChangedHandler : Com.OneSignal.iOS.OSUserStateObserver
{
private iOSUserManager _manager;
public InternalUserChangedHandler(iOSUserManager manager)
{
_manager = manager;
}

public override void OnUserStateDidChangeWithState(OSUserChangedState state)
{
var current = new InternalUserState(state.Current.OnesignalId, state.Current.ExternalId);
var userChangedState = new UserChangedState(current);
_manager.Changed?.Invoke(_manager, new UserStateChangedEventArgs(userChangedState));
}
}
}

public class iOSPushSubscription : IPushSubscription
Expand Down
8 changes: 8 additions & 0 deletions Samples/OneSignalApp/Models/MainPageModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Windows.Input;
using OneSignalSDK.DotNet;
using OneSignalSDK.DotNet.Core.Debug;
using OneSignalSDK.DotNet.Core.User;
using OneSignalSDK.DotNet.Core.User.Subscriptions;

namespace OneSignalApp.Models
Expand Down Expand Up @@ -190,6 +191,7 @@ public MainPageModel(Page page)

OneSignal.Initialize(_appId);

OneSignal.User.Changed += User_Changed;
OneSignal.User.PushSubscription.Changed += PushSubscription_Changed;
OneSignal.Notifications.PermissionChanged += Notifications_PermissionChanged;
OneSignal.Notifications.Clicked += Notifications_Clicked;
Expand All @@ -208,6 +210,12 @@ public MainPageModel(Page page)
PushSubscriptionId = OneSignal.User.PushSubscription.Id;
}

private void User_Changed(object sender, OneSignalSDK.DotNet.Core.User.UserStateChangedEventArgs e)
{
var user = e.State.Current;
Debug.WriteLine($"User has changed: OneSignalId=${user.OneSignalId}, ExternalId={user.ExternalId}");
}

private void InAppMessages_Clicked(object sender, OneSignalSDK.DotNet.Core.InAppMessages.InAppMessageClickedEventArgs e)
{
Debug.WriteLine($"IAM clicked: ${e.Result.ActionId}.");
Expand Down

0 comments on commit f37e79c

Please sign in to comment.