I'm trying to create a handler that will produce a popup when a message is received from SignalR which is running in a service. I've got this working in a non-service, but it won't work in a service.
This code works from a non-service:
client.OnMessageReceived +=
(sender2, message) =>
RunOnUiThread(() =>
showMessage(message));
Where client
is the SignalR client and showMessage
is the method called when a message is received from client. No problem.
Now I want to run the client in/as a service and I need to wire up a handler to do basically the same thing. I've tried several methods I found on StackOverflow and other sites, but all the stuff out there is java, not c# for Xamarin for Visual Studio (2017) and does not translate well. I'm at a loss as to how to proceed.
* Update * This is my forground service code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Acr.UserDialogs;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V4.App;
using Android.Views;
using Android.Widget;
using ChatClient.Shared;
using Java.Lang;
namespace OML_Android
{
public class SignalRService : Service
{
public const int SERVICE_RUNNING_NOTIFICATION_ID = 10000;
public const string ACTION_MAIN_ACTIVITY = "OML_Android.action.MainActivity";
public const string SERVICE_STARTED_KEY = "has_service_been_started";
bool isStarted;
Handler handler;
Action runnable;
// This information will eventually be pulled from the intent, this is just for testing
public string firstname = "";
public string lastname = "";
public string username = "";
public string name = "";
private Client mInstance;
public override IBinder OnBind(Intent intent)
{
return null;
// throw new NotImplementedException();
}
public override void OnCreate()
{
base.OnCreate();
mInstance = Client.Getinstance(name, username, firstname, lastname);
mInstance.Connect();
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
return StartCommandResult.Sticky;
}
public override void OnDestroy()
{
// Not sure what to do here yet, got to get the service working first
}
void RegisterForegroundService()
{
var notification = new NotificationCompat.Builder(this)
.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.alert_box)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
//.AddAction(BuildRestartTimerAction())
//.AddAction(BuildStopServiceAction())
.Build();
// Enlist this instance of the service as a foreground service
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
}
PendingIntent BuildIntentToShowMainActivity()
{
var notificationIntent = new Intent(this, typeof(MainActivity));
notificationIntent.SetAction(ACTION_MAIN_ACTIVITY);
notificationIntent.SetFlags(ActivityFlags.SingleTop | ActivityFlags.ClearTask);
notificationIntent.PutExtra(SERVICE_STARTED_KEY, true);
var pendingIntent = PendingIntent.GetActivity(this, 0, notificationIntent, PendingIntentFlags.UpdateCurrent);
return pendingIntent;
}
public async void showMessage(string message)
{
var result = await UserDialogs.Instance.ConfirmAsync(new ConfirmConfig
{
Message = "Text Message from Company: " + System.Environment.NewLine + message,
OkText = "Ok",
});
if (result)
{
// do something
var x = message;
}
}
}
}
This service sets the client to run as a foreground service (I assume), the client code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client;
namespace ChatClient.Shared
{
public sealed class Client
{
//public string username;
private string username = "";
private string _platform = "";
private readonly HubConnection _connection;
private readonly IHubProxy _proxy;
public string _Username
{
get { return username; }
set { username = value; }
}
public string _Platform
{
get { return _platform; }
set { _platform = value; }
}
public event EventHandler<string> OnMessageReceived;
public static Client instance = null;
public Client(string name, string username, string firstname, string lastname, string company, string department, string section)
{
_Username = username;
_Platform = name;
_platform = _Platform;
Dictionary<string, string> queryString = new Dictionary<string, string>();
queryString.Add("username", username);
queryString.Add("firstname", firstname);
queryString.Add("lastname", lastname);
queryString.Add("company", company);
queryString.Add("department", department);
queryString.Add("section", section);
_connection = new HubConnection("https://www.example.com/SignalRhub",queryString );
_proxy = _connection.CreateHubProxy("chathub");
}
public static Client Getinstance(string name, string username, string firstname, string lastname)
{
// create the instance only if the instance is null
if (instance == null)
{
// The username and user's name are set before instantiation
instance = new Client(name, username, firstname, lastname,"","","");
}
// Otherwise return the already existing instance
return instance;
}
public async Task Connect()
{
await _connection.Start(); //.ContinueWith._connection.server.registerMeAs("");
_proxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
// Send("Connected");
}
public async Task<List<string>> ConnectedUsers()
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedUsers");
return Users;
}
public async Task<List<string>> ConnectedSectionUsers(string company, string department, string section, string username)
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedSectionUsers",company, department, section, username);
return Users;
}
public Task Send(string message)
{
return _proxy.Invoke("Send", _platform, message);
}
public Task SendSectionMessage(string company, string department, string section, string name, string message)
{
return _proxy.Invoke("messageSection", company, department, section, name, message);
}
public Task SendCompanyMessage(string company, string department, string section, string name, string message)
{
return _proxy.Invoke("messageCompany", company, name, message);
}
}
}
This is the code I plan to use to start the service (not working yet), I will be adding information to the intent via intent.PutExtras, namely Firstname, lastname, username, name, company, department and section. For now I just set them to null string in the service for testing purposes.:
public static void StartForegroundServiceComapt<SignalRService>(this Context context, Bundle args = null) where SignalRService : Service
{
var intent = new Intent(context, typeof(SignalRService));
if (args != null)
{
intent.PutExtras(args);
}
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.O)
{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
}
This all works as expected, I still need to do some work to clean it up but it is working. I am able to connect to the server hub and send messages to the correct groups of people. Now I need to get this to run as a foreground service.