0

I am developing a Xamarin Forms app that connects to a Azure SignalR service to get server side events to notify the application about some events happening on the server.

I have created a background service that is able make this connection to SignalR service, however after a while looks like the device enters Doze Mode which is causing the service to loose its tcp connection to the SignalR server. I see the following error when this happens:

Server timeout (30000.00ms) elapsed without receiving a message from the server.

I have a retry logic built to reconnect even that fails as there is no internet connection looks like in this state. however if during this retry cycle, if I get the device to wakeup, the connection succeeds.

So my question is, how can I ensure that my service always has internet access to prevent such issue irrespective of the device state.

Update 1

here is the code requested for what I am doing:

public string AssetId { get; private set; }
public async Task ConnectAsync(string assetId)
{
    try
    {
        AssetId = assetId;
        if (connection == null)
        {
            var client = new HttpClient(); //new HttpClient(new Xamarin.Android.Net.AndroidClientHandler());

            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add("asset-id", assetId);
            string negotiateJson = await client.GetStringAsync(Constants.SignalRNegotiateFunctionURL);
            NegotiateInfo negotiate = JsonConvert.DeserializeObject<NegotiateInfo>(negotiateJson);
            connection = new HubConnectionBuilder()
                .WithUrl(negotiate.Url, options =>
                {
                    options.AccessTokenProvider = async () => negotiate.AccessToken;
                })
                .Build();
            connection.Closed += Connection_Closed;
            connection.On<JObject>("OnAssetApproaching", OnAssetApproachingSignalREvent);
        }
        IsConnected = true;

        await connection.StartAsync();
    }
    catch (Exception ex)
    {
        IsConnected = false;
    }
}

async Task Connection_Closed(Exception arg)
{
    if (IsConnected)
    {
        var retryCount = 0;
        while (retryCount < 5)
        {
            try
            {
                await connection?.StopAsync();
                await Task.Delay(new Random().Next(0, 5) * 1000);
                await connection.StartAsync();
                if (connection.State == HubConnectionState.Connected)
                {
                    break;
                }
            }
            catch (Exception ex)
            {
                retryCount++;
            }
        }
        if (connection.State == HubConnectionState.Disconnected)
        {
            IsConnected = false;
        }
    }
}
Kiran
  • 2,997
  • 6
  • 31
  • 62
  • Please post some relevant code to show where the timeout occurs. – yams Aug 28 '19 at 18:03
  • @yams: Timeout occurs in the SignalR library, I don't have access to those code. all I get is an event that the connection is closed with the error mentioned above. moreover I think the reason for timeout is not pretty much clear, after 3 days of searching. its due to device going to s state where it shuts off even the internet / wifi access on my KitKat 4.4 device on which I am testing – Kiran Aug 28 '19 at 18:05
  • But it could be happening in conjunction with your code. Or you could post the entire stacktrace from the The logcat. – yams Aug 28 '19 at 18:08
  • @yams: Added the code, not sure how it helps as from what I can see so far, issue is due to Android locking down all network activity of my background service when it enters the suspended mode. – Kiran Aug 28 '19 at 18:19
  • it's part of the stackoverflow guidelines for documenting clear questions with code. Not having any code listed is probably why someone marked down your question. – yams Aug 29 '19 at 14:43

1 Answers1

0

SignalR automatically closes connection in this case because of timeout. I strongly suggest to change notifications idea to push notifications. Azure offers such a service.

Adlorem
  • 1,457
  • 1
  • 11
  • 10
  • thanks!, I was thinking about the same and refactored my application to use the FCM and Azure Push notification. One question I have is does the app create a new instance of `MyFirebaseMessagingService` every time a notification is received or it just maintains the same instance as along running service. – Kiran Aug 31 '19 at 08:29