38

I am trying to integrate signalR in android app but no luck. I've been looking at various links but none of them provide proper information about implementation.

I've the following questions.

  • SignalR integration has to be done inside Service/Intent Service?
  • If we want to receive response via same calling method then how to get?

I've added three libraries i.e signalr android,signalr client and gson but unable to understand how code works, no proper documentation is available to understand the code.

Some of the questions asked but not much information

SignalR in Android Studio Unable to implement p2p chat using SignalR in Android

If anyone experienced in signal for native apps, it would be very helpful for me.

Update

    public class SignalRService extends Service {


    private static final String TAG = "Service";
    private HubConnection mHubConnection;
    private HubProxy mHubProxy;
    private Handler mHandler; // to display Toast message
    private final IBinder mBinder = new LocalBinder(); 

    private SharedPreferences sp;

    @Override
    public void onCreate() {
        super.onCreate();

        Utility.showLog(TAG, "Service Created");

        sp = getSharedPreferences(Utility.SHARED_PREFS, MODE_PRIVATE);
        mHandler = new Handler(Looper.myLooper());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        int result = super.onStartCommand(intent, flags, startId);
        startSignalR();
        return result;
    }

    @Override
    public IBinder onBind(Intent intent) {

        startSignalR();
        return mBinder;
    }

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        public SignalRService getService() {
            // Return this instance of SignalRService so clients can call public methods
            return SignalRService.this;
        }
    }

    /**
     * method for clients (activities)
     */
    public void sendMessage() {

        String SERVER_METHOD_SEND = "iAmAvailable";
        final String string = new String();

        mHubProxy.invoke(new String(), SERVER_METHOD_SEND, sp.getString("user_id", null), sp.getString("pass", null), "TransMedic").done(new Action() {
            @Override
            public void run(Object o) throws Exception {

                Utility.showLog(TAG, o.toString());

            }


        }).onError(new ErrorCallback() {
            @Override
            public void onError(Throwable throwable) {

            }
        });
    }

    private void startSignalR() {

        Platform.loadPlatformComponent(new AndroidPlatformComponent());

        String serverUrl = "http://transit.alwaysaware.org/signalr";

        mHubConnection = new HubConnection(serverUrl);

        String SERVER_HUB_CHAT = "ChatHub";

        mHubProxy = mHubConnection.createHubProxy(SERVER_HUB_CHAT);

        ClientTransport clientTransport = new ServerSentEventsTransport(mHubConnection.getLogger());

        SignalRFuture<Void> signalRFuture = mHubConnection.start(clientTransport);


        try {

            signalRFuture.get();

        } catch (InterruptedException | ExecutionException e) {

            e.printStackTrace();
            return;

        }

        sendMessage();
    }

    @Override
    public void onDestroy() {

        mHubConnection.stop();
        super.onDestroy();

    }
}
Ahmad Aghazadeh
  • 16,571
  • 12
  • 101
  • 98
moDev
  • 5,248
  • 4
  • 33
  • 63
  • Your "mHubProxy.invoke" looks different from mine, I wonder if it is the same as your server Hub definition or not. Its first parameter is a blank String? Moreover, where do you use "string" variable? – BNK Sep 16 '15 at 00:19
  • @BNK I want to receive callback from invoke and for that I have used new String() – moDev Sep 16 '15 at 05:45
  • Hi! Now I understand your idea about response from invoke, you use `public SignalRFuture invoke(final Class resultClass, final String method, Object... args)` :) – BNK Sep 17 '15 at 15:43
  • Why don't you try `String.class` instead of `new String()` such as `mHub.invoke(String.class, "hello", "123").done(new Action() { @Override public void run(String s) throws Exception { } }).onError(new ErrorCallback() { @Override public void onError(Throwable throwable) { } });` – BNK Sep 17 '15 at 15:57
  • I have just tested with your server Url `http://transit.alwaysaware.org/signalr`, perhaps your server Hub name is not ChatHub, because my app got `[InvalidOperationException]: 'chathub' Hub could not be resolved.` – BNK Sep 18 '15 at 01:25
  • I've implemented an Android chat application with Signal R. Everything is working fine but the problem is that I don't get a message when the Android app is completely closed. I don't close my connection. Do you have a solution to this problem? – reyhane Sep 26 '19 at 07:25

5 Answers5

44

UPDATE 2018:

If you are using SignalR.net Core use this library otherwise you will get error on connection.

SERVER SIDE:

The following is my sample server-side code, you can pay attention to public void Send(string message) and public void SendChatMessage(string to, string message).

  • Server-side app: public void SendChatMessage(string to, string message)

    • Android client app: mHubProxy.invoke("SendChatMessage", receiverName, message);
  • Server-side app: public void Send(string message)

    • Android client app: mHubProxy.invoke("Send", message);
namespace SignalRDemo
{
    public class ChatHub : Hub
    {
        private static ConcurrentDictionary<string, string> FromUsers = new ConcurrentDictionary<string, string>();         // <connectionId, userName>
        private static ConcurrentDictionary<string, string> ToUsers = new ConcurrentDictionary<string, string>();           // <userName, connectionId>
        private string userName = "";

    public override Task OnConnected()
    {
        DoConnect();
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(new ChatMessage() { UserName = userName, Message = "I'm Online" });
        return base.OnConnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        if (stopCalled) // Client explicitly closed the connection
        {
            string id = Context.ConnectionId;
            FromUsers.TryRemove(id, out userName);
            ToUsers.TryRemove(userName, out id);
            Clients.AllExcept(Context.ConnectionId).broadcastMessage(new ChatMessage() { UserName = userName, Message = "I'm Offline" });
        }
        else // Client timed out
        {
            // Do nothing here...
            // FromUsers.TryGetValue(Context.ConnectionId, out userName);            
            // Clients.AllExcept(Context.ConnectionId).broadcastMessage(new ChatMessage() { UserName = userName, Message = "I'm Offline By TimeOut"});                
        }

        return base.OnDisconnected(stopCalled);
    }

    public override Task OnReconnected()
    {
        DoConnect();
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(new ChatMessage() { UserName = userName, Message = "I'm Online Again" });
        return base.OnReconnected();
    }

    private void DoConnect()
    {
        userName = Context.Request.Headers["User-Name"];
        if (userName == null || userName.Length == 0)
        {
            userName = Context.QueryString["User-Name"]; // for javascript clients
        }
        FromUsers.TryAdd(Context.ConnectionId, userName);
        String oldId; // for case: disconnected from Client
        ToUsers.TryRemove(userName, out oldId);
        ToUsers.TryAdd(userName, Context.ConnectionId);
    }

    public void Send(string message)
    {
        // Call the broadcastMessage method to update clients.            
        string fromUser;
        FromUsers.TryGetValue(Context.ConnectionId, out fromUser);
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(new ChatMessage() { UserName = fromUser, Message = message });
    }

    public void SendChatMessage(string to, string message)
    {
        FromUsers.TryGetValue(Context.ConnectionId, out userName);
        string receiver_ConnectionId;
        ToUsers.TryGetValue(to, out receiver_ConnectionId);

        if (receiver_ConnectionId != null && receiver_ConnectionId.Length > 0)
        {
            Clients.Client(receiver_ConnectionId).broadcastMessage(new ChatMessage() { UserName = userName, Message = message });
        }
    }        
}

public class ChatMessage
{
    public string UserName { get; set; }
    public string Message { get; set; }
}
}

CLIENT SIDE:

If you have not read my answer at the following question:

SignalR integration in android studio

Then, here is my working basic code:

public class SignalRService extends Service {
    private HubConnection mHubConnection;
    private HubProxy mHubProxy;
    private Handler mHandler; // to display Toast message
    private final IBinder mBinder = new LocalBinder(); // Binder given to clients

public SignalRService() {
}

@Override
public void onCreate() {
    super.onCreate();
    mHandler = new Handler(Looper.getMainLooper());
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    int result = super.onStartCommand(intent, flags, startId);
    startSignalR();
    return result;
}

@Override
public void onDestroy() {
    mHubConnection.stop();
    super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
    // Return the communication channel to the service.
    startSignalR();
    return mBinder;
}

/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
    public SignalRService getService() {
        // Return this instance of SignalRService so clients can call public methods
        return SignalRService.this;
    }
}

/**
 * method for clients (activities)
 */
public void sendMessage(String message) {
    String SERVER_METHOD_SEND = "Send";
    mHubProxy.invoke(SERVER_METHOD_SEND, message);
}    

private void startSignalR() {
    Platform.loadPlatformComponent(new AndroidPlatformComponent());

    Credentials credentials = new Credentials() {
        @Override
        public void prepareRequest(Request request) {
            request.addHeader("User-Name", "BNK");
        }
    };

    String serverUrl = "http://192.168.1.100";
    mHubConnection = new HubConnection(serverUrl);
    mHubConnection.setCredentials(credentials);
    String SERVER_HUB_CHAT = "ChatHub";
    mHubProxy = mHubConnection.createHubProxy(SERVER_HUB_CHAT);
    ClientTransport clientTransport = new ServerSentEventsTransport(mHubConnection.getLogger());
    SignalRFuture<Void> signalRFuture = mHubConnection.start(clientTransport);

    try {
        signalRFuture.get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
        return;
    }

    String HELLO_MSG = "Hello from Android!";
    sendMessage(HELLO_MSG);

    String CLIENT_METHOD_BROADAST_MESSAGE = "broadcastMessage";
    mHubProxy.on(CLIENT_METHOD_BROADAST_MESSAGE,
            new SubscriptionHandler1<CustomMessage>() {
                @Override
                public void run(final CustomMessage msg) {
                    final String finalMsg = msg.UserName + " says " + msg.Message;
                    // display Toast message
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(getApplicationContext(), finalMsg, Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
            , CustomMessage.class);
}
}

Activity:

public class MainActivity extends AppCompatActivity {

private final Context mContext = this;
private SignalRService mService;
private boolean mBound = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent intent = new Intent();
    intent.setClass(mContext, SignalRService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    // Unbind from the service
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
    super.onStop();
}    

public void sendMessage(View view) {
    if (mBound) {
        // Call a method from the SignalRService.
        // However, if this call were something that might hang, then this request should
        // occur in a separate thread to avoid slowing down the activity performance.
        EditText editText = (EditText) findViewById(R.id.edit_message);            
        if (editText != null && editText.getText().length() > 0) {                
            String message = editText.getText().toString();
            mService.sendMessage(message);
        }
    }
}

/**
 * Defines callbacks for service binding, passed to bindService()
 */
private final ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
                                   IBinder service) {
        // We've bound to SignalRService, cast the IBinder and get SignalRService instance
        SignalRService.LocalBinder binder = (SignalRService.LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
    }
};
}

CustomMessage Class:

public class CustomMessage {
    public String UserName;
    public String Message;
}

You can also see my sample client project at this GitHub link


UPDATE FOR RESPONSE FROM INVOKE:

I have just added new sample methods:

Server side:

public string iAmAvailable(string username, string password, string message)
{            
     return "BNK Response for testing Android INVOKE";
}

Client side:

mHubProxy.invoke(String.class, "iAmAvailable", "username", "password", "TransMedic").done(new Action<String>() {
            @Override
            public void run(String s) throws Exception {
                Log.w("SimpleSignalR", s);
            }
        }).onError(new ErrorCallback() {
            @Override
            public void onError(Throwable throwable) {
                Log.e("SimpleSignalR", throwable.toString());
            }
        });

And here is the screenshot:

Android SignalR Invoke Response

Viks
  • 1,510
  • 4
  • 22
  • 50
BNK
  • 23,994
  • 8
  • 77
  • 87
  • How to check if connection is established – moDev Sep 15 '15 at 08:20
  • Basically I've two different calls to `signalR`. In one call it sends few parameters and receives response and in other call, it receives response from different method like you mentioned for broadcast Message. How we can do for the first call? – moDev Sep 15 '15 at 10:34
  • 2
    I am getting error `java.util.concurrent.ExecutionException: microsoft.aspnet.signalr.client.transport.NegotiationException: There was a problem in the negotiation with the server` – moDev Sep 15 '15 at 12:24
  • Can you post your code? Both client and server app. – BNK Sep 15 '15 at 13:30
  • I can post client side code. I don't have access to server code. – moDev Sep 15 '15 at 14:02
  • I've just changed hub name and app got hanged with blank screen. – moDev Sep 16 '15 at 08:34
  • How to receive response from same method using invoke? – moDev Sep 16 '15 at 08:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89780/discussion-between-droid-dev-and-bnk). – moDev Sep 16 '15 at 08:50
  • I am not sure if it can be or not, if have freetime, I will test and inform you the result. IMO, if you start learning SignalR, try simple cases to check if it works, then more complicated ones, moreover, check more with the person who has written the server app :-) – BNK Sep 16 '15 at 10:00
  • I think it is the simplest case. I am just trying to make connection and send request data to server. It just hangs the entire application. I tried by removing request data but it still hangs the application. Something is wrong – moDev Sep 16 '15 at 10:04
  • You can write your own sample SignalR server app to test with your Android client app – BNK Sep 16 '15 at 10:06
  • I am an mobile developer, so can't do it. – moDev Sep 16 '15 at 10:08
  • Basically, I am more concerned for the client side. Other guys are working on server and they have confirmed that server side is working fine with web UI. It looks may be client side has some issues. I am not sure though – moDev Sep 16 '15 at 10:17
  • Sorry I cannot help you solve your issue. IMO, you can create your own apps to test at home if you have time. Goodluck! – BNK Sep 16 '15 at 10:22
  • Android code that you posted works for you?? Why it hangs entire application and displays black background unless app is forced closed? – moDev Sep 16 '15 at 10:23
  • Of course it works with my own ASP.NET server app :-) – BNK Sep 16 '15 at 10:27
  • can you show how to receive response via callback in invoke method? – moDev Sep 16 '15 at 10:37
  • As you have seen, android client receives response inside SubscriptionHandler1 – BNK Sep 16 '15 at 11:38
  • Ah, I have reviewed your code more, you should implement SubscriptionHandler1 to receive server response – BNK Sep 16 '15 at 14:36
  • Glad it finally helps you! – BNK Sep 18 '15 at 13:18
  • do you know how to get result in JSON? I tried to get into object and then converted into JSON but got error. is there any direct way to get JSON result without using object class? – moDev Sep 20 '15 at 14:22
  • Do you mean that your server app returned JSON? I think it returned a List instead, for example List – BNK Sep 20 '15 at 23:52
  • 1
    I found the solution for JSON. Thanks for your help. – moDev Sep 23 '15 at 21:26
  • We are using LongPollingTransport but looks like its getting disconnected but it never returns to closed function of hub connection. We need to keep connection alive always – moDev Dec 03 '15 at 20:04
  • can you help on this? – moDev Dec 03 '15 at 20:04
  • Have you tried `mConnection.closed(new Runnable() { @Override public void run() { mLogger.log(Log.ERROR, mConnectionId + " Disconnected!"); if (mConnection.getState().toString().equals("Disconnected")) { new reconnectPulling().execute(); } } });` yet? – BNK Dec 04 '15 at 01:05
  • 1
    Looks like that `closed` only called when server terminated the connection, I tried stop and start IIS later, then getting the following logcat `12-04 11:43:52.555 4105-5449/com.example.signalrclient E/SignalRClient: cec7f6e8-0d9b-43f0-abdd-18c1265d6452 connectionSlow! 12-04 11:43:59.256 4105-5707/com.example.signalrclient E/SignalRClient: cec7f6e8-0d9b-43f0-abdd-18c1265d6452 reconnecting! 12-04 11:43:59.296 4105-5710/com.example.signalrclient E/SignalRClient: cec7f6e8-0d9b-43f0-abdd-18c1265d6452 Disconnected!` – BNK Dec 04 '15 at 04:46
  • `12-04 11:44:45.406 4105-7380/com.example.signalrclient I/SignalRClient: Connecting to server... 12-04 11:44:50.397 4105-7570/com.example.signalrclient I/SignalRClient: Connected 12-04 11:45:00.947 4105-7943/com.example.signalrclient E/SignalRClient: 96330534-3952-4b65-8187-b5a3499a2749 connectionSlow!` – BNK Dec 04 '15 at 04:47
  • http://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events – BNK Dec 04 '15 at 04:47
  • I've been using signalR and it disconnects/closes the connected after 2-3 minutes if app is closed but if app is idle and on the same screen then connection is active for longer time. is that signalR issue? – moDev Dec 08 '15 at 05:10
  • Sorry, I am not sure about that – BNK Dec 08 '15 at 06:44
  • Thanks. I found out the solution. I've another bug. App works in debug mode but when its signed and uploaded to store. Connection doesnt work, nothing works. Any idea? – moDev Dec 19 '15 at 23:37
  • If WIFI is connected then start without any parameter else start with long polling transport parameter – moDev Dec 19 '15 at 23:38
  • Sorry, I have not any app in store :). – BNK Dec 20 '15 at 00:07
  • @BNK Awesome answer! I had a very similar issue in SignalR Android. Can you have a look please? http://stackoverflow.com/questions/35264835/setting-up-signal-r-in-android-crash-hung-issue – Jay Feb 08 '16 at 10:00
  • @BNK I have implemented a chat using your signlr demo and Works fine but I want to implement notification of new message arrive in app. even though app close like whatsapp. Please help me – Dipanki Jadav Oct 11 '16 at 12:27
  • @DipankiJadav sorry I can't help now, however, I think you can search more in SO about the permanent service in Android, for example http://stackoverflow.com/questions/15758980/android-service-need-to-run-alwaysnever-pause-or-stop – BNK Oct 12 '16 at 01:29
  • @moDev Please help me to solve the issue of Disconnection which you face earlier and you have solve it I have see the comments of 8Dec2015 . Please let me know the solution Please help me to solve the issue of Signlr Disconnection due to Internet problem or when App is Idle for longer time – Dipanki Jadav Oct 19 '16 at 07:53
  • @BNK Hello Please help me to solve the issue of Signlr disconnection due to internet problem or when App is Idle for longer time – Dipanki Jadav Oct 20 '16 at 08:16
  • @DipankiJadav sorry I am busy with my work now, however, have you tried using `LongPollingTransport` and have you read about `reconnectPulling` in my 2 comments above yet (on Dec 04, 2015)? And pls read https://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events#clientdisconnect to see if it can help or not – BNK Oct 20 '16 at 09:12
  • @DipankiJadav You need to reconnect everytime connection is lost.Have you tried anything? – moDev Oct 20 '16 at 12:07
  • @moDev I can not handel the disconnection in closed() closed is not call so I can not call reconnect. – Dipanki Jadav Oct 20 '16 at 12:39
  • @DipankiJadav have you tried using LongPollingTransport yet? – BNK Oct 20 '16 at 13:11
  • can you please share server side code am getting java.lang.InterruptedException: Operation was cancelled – M.Yogeshwaran Oct 24 '16 at 13:55
  • @M.Yogeshwaran the server side code is on top of my answer already – BNK Oct 25 '16 at 04:06
  • am getting operation was cancelled exception don't know why – M.Yogeshwaran Oct 25 '16 at 04:37
  • @BNK can you please take a look at this http://stackoverflow.com/q/40231733/5498065 – M.Yogeshwaran Oct 25 '16 at 05:28
  • @M.Yogeshwaran since I am busy now, so please try my sample project at https://github.com/ngocchung/SimpleSignalRClient, there you will find a link to server side code (i.e https://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr). Hope it helps! – BNK Oct 25 '16 at 09:31
  • @moDev Can you please provide the code which you implemented for solve issue of disconnection of signlr while app is idle or due Internet connection. Please help me – Dipanki Jadav Oct 26 '16 at 04:42
  • @DipankiJadav Let me know your code. I'll surely help. – moDev Oct 26 '16 at 17:29
  • @moDev BNK DipankiJadav i have successfully created the working hub but my doubt is it possible to generate notification when application in background like whatsapp,facebook from android using signalr – M.Yogeshwaran Nov 02 '16 at 05:33
  • I am using the same code base and can send message but I cant receive any... Can anyone help me ? My control doesnt go inside "SubscriptionHandler1" – Umar Farooque Nov 09 '16 at 18:45
  • @UmarFarooque I think you should check the connection between android client and web server first, you can also set breakpoints inside your server side code, then debug – BNK Nov 11 '16 at 01:53
  • @BNK Ok I will be adding logs for receving method at the server. Would get back to you incase I need some help. – Umar Farooque Nov 11 '16 at 05:53
  • @BNK what seemed to work for me is described in this http://stackoverflow.com/a/40520578/2570153 The method "mHubProxy.on()" gives no callback in my project. – Umar Farooque Nov 16 '16 at 06:23
  • @UmarFarooque glad that your issue has been solved. About `connection.received(new MessageReceivedHandler() `, actually I have used it inside one of my projects before, but then commented already. About `mHubProxy.on`, have you made sure that their pararameters' values are correct and exactly the same as the server code? I mean method name (i.e `broadcastMessage`, class name (i.e `String` or `CustomMessage`...). One more thing, does your project use the 2 jar files look like the files at https://github.com/ngocchung/SimpleSignalRClient/tree/master/app/libs? – BNK Nov 16 '16 at 07:10
  • Yes my project does use the same jar as mentioned in the link. As far as naming is concerned. I did match it with server. If you want or can check it.. I could post my method name, return, etc – Umar Farooque Nov 16 '16 at 07:23
  • @UmarFarooque ok, if you post it, please post to pastebin – BNK Nov 16 '16 at 07:30
  • @UmarFarooque please post server-side code also, and why `CustomMessage` and `CustomMsg`? They are different – BNK Nov 16 '16 at 08:04
  • @BNK it was a typo, CustomMessage and CustomMsg are same. Also, I'll post the server code for this msg soon and update. – Umar Farooque Nov 16 '16 at 08:25
  • @BNK Hi ! This is the function on server end. http://pastebin.com/7A9geVGD . Please help me out with it. The "mHubProxy.on() method is giving multiple duplicates. – Umar Farooque Dec 03 '16 at 18:05
  • @BNK this is the updated code i am using in my client where i receive callback in mhubproxy.on() method. http://pastebin.com/F9PBcJCK – Umar Farooque Dec 03 '16 at 18:12
  • @UmarFarooque at server code, `Clients.All.addNewMessageToPage(name, message, day, hour, avatar);` which has 5 parameters (String, Integer types...), however, in android code, you used `mHubProxy.on("addNewMessageToPage", new SubscriptionHandler1() {` so that's why it's not called. Pls review my code above – BNK Dec 05 '16 at 02:03
  • @BNK i tried with 5 parameters i.e. SubscriptionHandler5 and all my parameters are string type but i got stack over flow exception. – Umar Farooque Dec 05 '16 at 09:23
  • @UmarFarooque try using POJO class `ChatMessage` with 5 member variables instead of 2, and also `SubscriptionHandler1` as in my sample code – BNK Dec 06 '16 at 01:05
  • Does this client work with v2.3.0 of the SignalR .net library? See more details here: https://stackoverflow.com/questions/51165953/signalr-v2-3-0-in-android – rukiman Jul 04 '18 at 05:03
  • I've implemented an Android chat application with Signal R. Everything is working fine but the problem is that I don't get a message when the Android app is completely closed. I don't close my connection. Do you have a solution to this problem? – reyhane Sep 26 '19 at 07:25
  • @reyhane sorry bro, I haven't developed Android for years, cannot be sure now. Sorry – BNK Sep 27 '19 at 07:40
2

This work for me : Full source Android (Client) & Server GitHub

Server Slide If one argument must use this interface SubscriptionHandler1 if two argument must use this interfaceSubscriptionHandler2 ,...

Sample for two argument like :

Server slide :

using Microsoft.AspNet.SignalR;
namespace SignalRChat
{
    public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Two argument must use this interfaceSubscriptionHandler2 .
            Clients.All.broadcastMessage(name, message);
        }

    }
}

Client slide :

mHubProxy.on(CLIENT_METHOD_BROADAST_MESSAGE,
                new SubscriptionHandler2<String, String>() {
                    @Override
                    public void run(final String name,final String msg) {
                        final String finalMsg =  msg.toString();
                        // display Toast message
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(getApplicationContext(), finalMsg, Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                }
                , String.class,String.class);

For catch all message can use this :

mHubConnection.received(new MessageReceivedHandler() {

            @Override
            public void onMessageReceived(final JsonElement json) {
                Log.e("onMessageReceived ", json.toString());
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), json.toString(), Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
Ahmad Aghazadeh
  • 16,571
  • 12
  • 101
  • 98
2

The SignalR team recently released a Java client for ASP.NET Core SignalR. Here is a link to getting started docs https://learn.microsoft.com/en-us/aspnet/core/signalr/java-client?view=aspnetcore-2.2

Mikael Mengistu
  • 332
  • 1
  • 6
1

do this tutorial step by step : https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?tabs=visual-studio-mac&view=aspnetcore-5.0

1.According above tutorial publish your chat server to favorite host

2.add this dependency to your android sample:

 implementation 'com.microsoft.signalr:signalr:3.0.0'
 

3.add these permission to manifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

4.below code is MainActivity.class:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        HubConnection hubConnection = 
 HubConnectionBuilder.create("https://your_chat_server_url/chatHub").build();
        TextView textView = (TextView)findViewById(R.id.tvMain);
        ListView listView = (ListView)findViewById(R.id.lvMessages);
        Button sendButton = (Button)findViewById(R.id.bSend);
        EditText editText = (EditText)findViewById(R.id.etMessageText);

        List<String> messageList = new ArrayList<String>();
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(MainActivity.this,
                android.R.layout.simple_list_item_1, messageList);
        listView.setAdapter(arrayAdapter);


        hubConnection.on("ReceiveMessage", (user, message)-> {

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    arrayAdapter.add( user + " : " + message);
                    arrayAdapter.notifyDataSetChanged();
                }
            });
        }, String.class,String.class);

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String message = editText.getText().toString();
                String user = "SAEID";
                editText.setText("");
                try {
                    hubConnection.send("SendMessage", user,message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        new HubConnectionTask().execute(hubConnection);
    }

    static class HubConnectionTask extends AsyncTask<HubConnection, Void, Void>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(HubConnection... hubConnections) {
            HubConnection hubConnection = hubConnections[0];
            hubConnection.start().blockingAwait();
            return null;
        }
    }
}

5.below code is activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="vertical" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/tvMain" />
    <ListView
        android:layout_height="0dp"
        android:layout_weight="1"
        android:layout_width="fill_parent"
        android:id="@+id/lvMessages"
        android:transcriptMode="alwaysScroll">
    </ListView>
    <EditText
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:id="@+id/etMessageText"
        android:hint="Enter Message" />
    <Button
        android:text="Send"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/bSend" />
</LinearLayout>
Saeid Mohammadi
  • 319
  • 1
  • 2
  • 11
0

For those who are implementing signalR client in android and the given answer here doesn't help in receiving the messages can check out this answer by rejnev.

The answer implements a different method connection.received() which is able to receive message callbacks from the server in my case.

Community
  • 1
  • 1
Umar Farooque
  • 2,049
  • 21
  • 32