Issue
I implemented SignalR in my Xamarin Forms app and I'm getting the connection time out error.
I'm using SignalR for two things in the app. First is a typical chat feature and the second is to notify user of important data changes in the backend triggered by other users interacting with current user.
I implemented all SignalR related methods in a service class -- see below:
public class MySignalRService : IMySignalRService
{
private readonly url = "https://example.com/myhub";
HubConnection _connection;
public async Task Connect()
{
var accessToken = SecureStorage.GetAsync("access_token").Result;
_connection = new HubConnectionBuilder()
.WithUrl(_url, options =>
{
options.AccessTokenProvider = () => Task.FromResult(accessToken);
})
.Build();
await _connection.StartAsync();
_connection.On<string>("ReceiveMessage", async (message) =>
{
await UpdateChat(message);
});
_connection.On<string>("ReceiveDataUpdate", async (data) =>
{
await UpdateUserData(data);
});
}
private async Task UpdateChat(message)
{
// Handle message
}
private async Task UpdateUserData(data)
{
// Handle data update
}
public async Task Disconnect()
{
await _connection.DisposeAsync();
}
}
I then call the Connect()
method in OnStart()
and OnResume()
methods in code behind for App.xaml
. I also call the Disconnect()
method in OnSleep()
method.
My idea was to keep the connection open while my app is active on user's device but this still means periods of inactivity.
I have two questions:
- I understand
SignalR
doesn't want to sit idle. Is the idea withSignalR
to connect to the hub EXACTLY when the user needs the feature and disconnect as soon as he's done? If so, how do I make user aware of updates? Am I to set up some type of long polling myself to wake upSignalR
every so often which seems to go against the idea of using it in the first place? - I'd also appreciate it if those who've implemented
SignalR
in Xamarin Forms would let me know if the service approach I took is not how I need to implement this in my app.
Solution
please consider the suggestion to help you understand to begin trouble shooting/isolating the issue, there are three types of disconnects.
Understanding connection
, lifetime & disconnections
in the below cases will narrow down your problem, at least where is the disconnect happening.
Transport disconnection
Client disconnection
Server disconnection
Option 1: AutomaticReconnect
_yourHubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri($"/{HubMethods.SomeResultHub.my}"))
.WithAutomaticReconnect() // did you try this option
.Build();
_yourHubConnection.ServerTimeout = TimeSpan.FromHours(8); // Hrs 24/8 etc
Finding out the reason for disconnect using code, per Microsoft ref:
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{
if (stopCalled)
{
Console.WriteLine(String.Format("Client {0} explicitly closed the connection.", Context.ConnectionId));
}
else
{
Console.WriteLine(String.Format("Client {0} timed out .", Context.ConnectionId));
}
return base.OnDisconnected(stopCalled);
}
Armed with these two
your Question 1/Answer
...If so, how do I make user aware of updates?
$.connection.hub.reconnecting(function() {
notifyUserOfTryingToReconnect(); // wire up your custom function to notify user.
});
$.connection.hub.connectionSlow(function() {
notifyUserOfConnectionProblem(); // wire up your custom function let them know its slow.
});
Question 2: on Xamarin / Android
On mobile/Android (ios is pain though) you will need a Foreground Service running, which aids the app in keeping the connection alive. Alternatively like your original idea, long polling is another good option.
For e.g
[Service]
public class MyUserChatForegroundService : Service
{
// implement your foreground service to keep the connection alive.
...
}
Wherever you start your Activity with Intent wire this up, and lastly your Service first,
invoke StartForeground
using OnStartCommand override
, otherwise the service will just get killed.
var intent = new Intent(this, typeof(MyUserChatForegroundService ));
StartForegroundService(intent);
Intent & a Full reference Xamarin Signalr Sample
Hope this helps.
Answered By - Transformer
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.