且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使用signalr Android中

更新时间:2023-02-24 20:12:51

服务器端:

下面是我的示例服务器端code,你可以留意公共无效发送(字符串消息)公共无效SendChatMessage(字符串,字符串消息)

  
      
  • 服务器端的应用程序中:public void SendChatMessage(字符串,字符串消息)

         
        
    • 在Android客户端应用程序:mHubProxy.invoke(SendChatMessage,receiverName,消息);
    •   
  •   
  • 服务器端的应用程序:公共无效发送(字符串消息)

         
        
    • 在Android客户端应用程序:mHubProxy.invoke(发送,消息);
    •   
  •   
 命名空间SignalRDemo
{
    公共类ChatHub:集线器
    {
        私有静态ConcurrentDictionary<字符串,字符串> FromUsers =新ConcurrentDictionary<字符串,字符串>(); //< ConnectionId之外,用户名>
        私有静态ConcurrentDictionary<字符串,字符串> ToUsers =新ConcurrentDictionary<字符串,字符串>(); //<用户名,的ConnectionId>
        私人字符串username =;

    公众覆盖任务OnConnected()
    {
        DoConnect();
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(新ChatMessage(){用户名=用户名,消息=我在线});
        返回base.OnConnected();
    }

    公众覆盖任务OnDisconnected(布尔stopCalled)
    {
        如果(stopCalled)//客户明确地关闭了连接
        {
            字符串ID = Context.ConnectionId;
            FromUsers.TryRemove(ID,从用户名);
            ToUsers.TryRemove(用户名,掉id);
            Clients.AllExcept(Context.ConnectionId).broadcastMessage(新ChatMessage(){用户名=用户名,消息=我是离线});
        }
        否则//客户端超时
        {
            //在这里做什么?
            // FromUsers.TryGetValue(Context.ConnectionId,从用户名);
            // Clients.AllExcept(Context.ConnectionId).broadcastMessage(新ChatMessage(){用户名=用户名,消息=我是脱机超时});
        }

        返回base.OnDisconnected(stopCalled);
    }

    公众覆盖任务OnReconnected()
    {
        DoConnect();
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(新ChatMessage(){用户名=用户名,消息=我在线上再次});
        返回base.OnReconnected();
    }

    私人无效DoConnect()
    {
        的userName = Context.Request.Headers [用户名];
        如果(用户名== NULL || userName.Length == 0)
        {
            的userName = Context.QueryString [用户名]; //为JavaScript客户端
        }
        FromUsers.TryAdd(Context.ConnectionId,用户名);
        字符串OLDID; //为案例:从客户端断开连接
        ToUsers.TryRemove(用户名,出OLDID);
        ToUsers.TryAdd(用户名,Context.ConnectionId);
    }

    公共无效发送(字符串消息)
    {
        //调用broadcastMessage方法来更新客户端。
        串FROMUSER;
        FromUsers.TryGetValue(Context.ConnectionId,出FROMUSER);
        Clients.AllExcept(Context.ConnectionId).broadcastMessage(新ChatMessage(){用户名= FROMUSER,消息=消息});
    }

    公共无效SendChatMessage(字符串,字符串消息)
    {
        FromUsers.TryGetValue(Context.ConnectionId,从用户名);
        串receiver_ConnectionId;
        ToUsers.TryGetValue(于出receiver_ConnectionId);

        如果(receiver_ConnectionId =空&安培;!&安培; receiver_ConnectionId.Length大于0)
        {
            Clients.Client(receiver_ConnectionId).broadcastMessage(新ChatMessage(){用户名=用户名,消息=消息});
        }
    }
}

公共类ChatMessage
{
    公共字符串用户名{获得;组; }
    公共字符串信息{获得;组; }
}
}
 

客户端:

如果你还没有在以下问题看我的答案是:

SignalR集成在Android的工作室

那么,这是我的工作基本code,当然也必须实现服务器端的应用程序(也许在MVC和的WebAPI为例),希望这有助于!

 公共类SignalRService延伸服务{
    私人HubConnection mHubConnection;
    私人HubProxy mHubProxy;
    私人处理器mHandler; //显示吐司消息
    私人最终的IBinder mBinder =新LocalBinder(); //粘合剂给客户端

公共SignalRService(){
}

@覆盖
公共无效的onCreate(){
    super.onCreate();
    mHandler =新的处理程序(Looper.getMainLooper());
}

@覆盖
公众诠释onStartCommand(意向意图,诠释标志,诠释startId){
    INT结果= super.onStartCommand(意向,标志,startId);
    startSignalR();
    返回结果;
}

@覆盖
公共无效的onDestroy(){
    mHubConnection.stop();
    super.onDestroy();
}

@覆盖
公众的IBinder onBind(意向意图){
    //返回通信的服务通道。
    startSignalR();
    返回mBinder;
}

/ **
 *用于客户端粘合剂类。因为我们知道这种服务始终
 *运行在同一进程作为其客户,我们不需要处理IPC。
 * /
公共类LocalBinder扩展粘合剂{
    公共SignalRService的getService(){
        //返回SignalRService这个实例,以便客户端可以调用的公共方法
        返回SignalRService.this;
    }
}

/ **
 *方法,为客户(活动)
 * /
公共无效的sendMessage(字符串消息){
    字符串SERVER_METHOD_SEND =发送;
    mHubProxy.invoke(SERVER_METHOD_SEND,消息);
}

私人无效startSignalR(){
    Platform.loadPlatformComponent(新AndroidPlatformComponent());

    凭证凭证=新凭证(){
        @覆盖
        公共无效prepareRequest(申请要求){
            request.addHeader(用户名,BNK);
        }
    };

    字符串的serverUrl =htt​​p://192.168.1.100;
    mHubConnection =新HubConnection(的serverUrl);
    mHubConnection.setCredentials(凭证);
    字符串SERVER_HUB_CHAT =ChatHub;
    mHubProxy = mHubConnection.createHubProxy(SERVER_HUB_CHAT);
    ClientTransport clientTransport =新ServerSentEventsTransport(mHubConnection.getLogger());
    SignalRFuture<太虚> signalRFuture = mHubConnection.start(clientTransport);

    尝试 {
        signalRFuture.get();
    }赶上(InterruptedException的|为ExecutionException E){
        e.printStackTrace();
        返回;
    }

    字符串HELLO_MSG =你好,从Android的!;
    的sendMessage(HELLO_MSG);

    字符串CLIENT_METHOD_BROADAST_MESSAGE =broadcastMessage;
    mHubProxy.on(CLIENT_METHOD_BROADAST_MESSAGE,
            新SubscriptionHandler1< CustomMessage>(){
                @覆盖
                公共无效的run(最终CustomMessage味精){
                    最后弦乐finalMsg = msg.UserName +云+ msg.Message;
                    //显示吐司消息
                    mHandler.post(新的Runnable(){
                        @覆盖
                        公共无效的run(){
                            Toast.makeText(getApplicationContext(),finalMsg,Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
            ,CustomMessage.class);
}
}
 

活动:

 公共类MainActivity扩展AppCompatActivity {

私人最终上下文mContext =这一点;
私人SignalRService MSERVICE;
私人布尔mBound = FALSE;

@覆盖
保护无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_main);

    意向意图=新的意图();
    intent.setClass(mContext,SignalRService.class);
    bindService(意向,mConnection,Context.BIND_AUTO_CREATE);
}

@覆盖
保护无效的onStop(){
    //取消绑定从服务
    如果(mBound){
        unbindService(mConnection);
        mBound = FALSE;
    }
    super.onStop();
}

公共无效的sendMessage(查看视图){
    如果(mBound){
        //调用从SignalRService的方法。
        //然而,如果这一呼吁是一些可能会挂起,那么这个请求应该
        //发生在一个单独的线程以避免减慢活性性能。
        EditText上EDITTEXT =(EditText上)findViewById(R.id.edit_message);
        如果(EDITTEXT = NULL和放大器;!&安培; editText.getText()长度()0){
            字符串消息= editText.getText()的toString()。
            mService.sendMessage(消息);
        }
    }
}

/ **
 *定义回调服务绑定,传递给bindService()
 * /
私人最终ServiceConnection mConnection =新ServiceConnection(){

    @覆盖
    公共无效onServiceConnected(组件名类名,
                                   的IBinder服务){
        //我们必将SignalRService,投的IBinder并获得SignalRService实例
        SignalRService.LocalBinder粘合剂=(SignalRService.LocalBinder)服务;
        MSERVICE = binder.getService();
        mBound = TRUE;
    }

    @覆盖
    公共无效onServiceDisconnected(组件名称为arg0){
        mBound = FALSE;
    }
};
}
 

CustomMessage类:

 公共类CustomMessage {
    公共字符串用户名;
    公共字符串信息;
}
 

您可以找到与Android在这个GitHub的链接

更新回应INVOKE:

我刚添加了新样本的方法:

服务器端:

 公共字符串iAmAvailable(用户名字符串,字符串密码,字符串消息)
{
     返回BNK响应测试的Andr​​oid里启动;
}
 

客户端:

  mHubProxy.invoke(为String.class,iAmAvailable,用户名,密码,TransMedic)来实现(新动作<字符串>(){
            @覆盖
            公共无效的run(String s)将抛出异常{
                Log.w(SimpleSignalR,多个);
            }
        })。onerror的(新ErrorCallback(){
            @覆盖
            公共无效onerror的(可抛出抛出){
                Log.e(SimpleSignalR,throwable.toString());
            }
        });
 

这里是截图:

如何使用signalr Android中

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();

}

}

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, of course you must also implement server-side app (perhaps in MVC or WebAPI for example), hope this helps!

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 find more sample with Android 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: