Base solution for your next web application
Open Closed

Push notification implementation in Xamarin Mobile application #6841


0
Synciant created

Hi Team,

We're having a requirement where we need to display live push notifications for users in mobile application.

Is there any documentation for implementing the same in Xamarin forms(using SignalR)?

If not, kindly guide us on how to proceed with this.

Thanks


9 Answer(s)
  • 0
    alper created
    Support Team

    Currently there's no implementation of SignalR in AspNet Zero Xamarin App. But you can follow this guide https://montemagno.com/real-time-communication-for-mobile-with-signalr/

  • 0
    Synciant created

    We've tried implementing the same but without a success. For the Hub Backend, we're using 'Abp.AspNetCore.SignalR' and for Xamarin, we've used 'Microsoft.AspNetCore.SignalR.Client'. Is this the point of concern?

    Also, how can we receive already implemented push notifications by ABP. Eg. new user created?

    Kindly guide us through.

    Thanks

  • 0
    alper created
    Support Team

    Hi,

    This is demo code to show you, how to achieve SignalR implementation in the Xamarin app.

    SendChatMessageInput.cs

    public class SendChatMessageInput
        {
            public int? TenantId { get; set; }
    
            public long UserId { get; set; }
    
            public string UserName { get; set; }
    
            public string TenancyName { get; set; }
    
            public Guid? ProfilePictureId { get; set; }
    
            public string Message { get; set; }
        }
    

    IChatService.cs

    public interface IChatService
        {
            HubConnection ChatConnection { get; }
    
            Task ConnectAsync();
    
            Task SendMessageAsync(string message);
        }
    

    ChatService.cs

       public class ChatService : ISingletonDependency, IChatService
        {
            private readonly IApplicationContext _applicationContext;
    
            public HubConnection ChatConnection { get; }
    
            public ChatService(IApplicationContext applicationContext)
            {
                _applicationContext = applicationContext;
    
                try
                {
                    var chatHost = ApiUrlConfig.BaseUrl + "signalr-chat";
    
                    ChatConnection = new HubConnectionBuilder()
                        .WithUrl(chatHost)
                        .Build();
    
                    ChatConnection.Closed += async (error) =>
                    {
                        await Task.Delay(new Random().Next(0, 5) * 1000);
                        await ChatConnection.StartAsync();
                    };
                }
                catch (Exception ex)
                {
                    ExceptionHandler.LogException(ex);
                }
            }
    
            public async Task ConnectAsync()
            {
                try
                {
                    await ChatConnection.StartAsync();
                }
                catch (Exception ex)
                {
                    ExceptionHandler.LogException(ex);
                }
            }
    
            public async Task SendMessageAsync(string message)
            {
                if (ChatConnection.State == HubConnectionState.Disconnected)
                {
                    return;
                }
    
                try
                {
                    var messageData = new SendChatMessageInput
                    {
                        TenantId = _applicationContext.LoginInfo.Tenant?.Id,
                        UserId = _applicationContext.LoginInfo.User.Id,
                        Message = message,
                        TenancyName = _applicationContext.LoginInfo.Tenant?.TenancyName,
                        UserName = _applicationContext.LoginInfo.User.UserName,
                        ProfilePictureId = _applicationContext.LoginInfo.User.ProfilePictureIdAsGuid
                    };
    
                    await ChatConnection.InvokeAsync("SendMessage", messageData);
                    
                    Console.WriteLine(@"Message sent!");
                }
                catch (Exception ex)
                {
                    ExceptionHandler.LogException(ex);
                }
            }
        }
    

    In your Xamarin.Shared project, open App.xaml.cs On the startup, you can connect to SignalR Hub.

    protected override async void OnStart()
            {
                base.OnStart();
    
                if (Device.RuntimePlatform == Device.iOS)
                {
                    SetInitialScreenForIos();
                    await UserConfigurationManager.GetIfNeedsAsync();
                }
    
               //Here we go...
                await DependencyResolver.Resolve<IChatService>().ConnectAsync();
    
                await DependencyResolver.Resolve<INavigationService>().InitializeAsync();
    
                OnResume();
            }
    

    Finally you can send message by injecting IChatService to any of your model view.

    await _chatService.SendMessageAsync("hi there!");
    

    I guess, you can do the similar work for Domain Events by connecting to the AbpCommonHub.

  • 0
    Synciant created

    Thanks for reply Alper. We've tried implementing it, but when it hits out our backend API i.e. ChatHub >> SendMessage, we are receiving sender information i.e. AbpSession.ToUserIdentifier()as null.

    Do we need to pass authentication token with new HubConnectionBuilder().WithUrl(chatHost)?

    If not, is there anything else we're missing with?

    Kindly guide.

  • 0
    alper created
    Support Team

    you're right we need to add the AccessToken to the SignalR requests. I'll show you how to do that.

  • 0
    Synciant created

    Sure, also help me out in implementing entity notifications. After connecting to AbpCommonHub using url /signalr, how can we listen to entity notifications as we only have notification names with us (eg. App.WelcomeToTheApplication) and for sending and receiving notifications using SignalR.Client, we need the method names.

    eg. ChatConnection.On<string>("MethodName", (message) => { AppendMessage(message); });

    Kindly guide us in achieving the same.

  • 1
    alper created
    Support Team

    Hi,

    I created a branch to show, how to implement a SignalR connection between the backend and the Xamarin App. Currently this implementation sends a message from the Xamarin App to the backend. I guess it's a big step to kick start your -SignalR based feature-. You can improve it for your requirements.

    Also you can do the similar development steps for the domain event notifications. Whenever a record is deleted/added/updated, you can trigger a domain event. And in the HandleEvent method of your domain event, send the notification to the Xamarin client. Just like in the SignalRChatCommunicator which sends notification from host to the client.

    Xamarin Chat Branch: github.com/aspnetzero/aspnet-zero-core/tree/alper/xamarin-chat

    Notice that, to be able to access this branch, you need to be signed in GitHub and you have to be granted access to the private aspnetzero/aspnet-zero-core repository.

  • 0
    Synciant created

    Thank you so much Alper. Now we're able to send and listen to push notifications in Mobile app. I hope, this solution will help all those who want to implement push notifications in xamarin mobile application.

    Last question, We having Abp version 4.1.0 and many of the functionalities you've used are not there e.g. in App.xaml.cs we don't have OnSessionTimeout() and OnAccessTokenRefresh() functions. To counter that, I've placed DependencyResolver.Resolve<IChatService>().ConnectAsync(); in Account service in SetCurrentUserInfoAsync(). And disconnected it in Logout functionality of MySettingsViewModel. Is there a better place for me to connect and disconnect SignalR?

    Kindly guide.

  • 1
    alper created
    Support Team

    Hi,

    Good to know it works for you!

    yeah you can locate connect method to AuthenticateSucceed method. and logout to Logout of AccountService But I'd also put connect to Resume() of App.xaml.cs and logout to Sleep().