Как использовать signalr в Android

Я пытаюсь интегрировать signalR в приложение для android , но не повезло. Я рассматривал различные ссылки, но ни один из них не предоставил надлежащую информацию о реализации.

У меня есть следующие вопросы.

  • Интеграция SignalR должна выполняться внутри Service / Intent Service?
  • Если мы хотим получить ответ через тот же метод вызова, то как получить?

Я добавил три библиотеки: signalr android , signalr client и gson но не смог понять, как работает код, для понимания кода не существует соответствующей документации.

Некоторые из вопросов задавали, но не много информации

SignalR в Android Studio Невозможно реализовать p2p-чат с помощью SignalR на Android

Если бы кто-нибудь испытал сигнал для родных приложений, это было бы очень полезно для меня.

Обновить

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

Solutions Collecting From Web of "Как использовать signalr в Android"

СЕРВЕРНАЯ СТОРОНА:

Ниже приведен пример кода на стороне сервера, вы можете обратить внимание на public void Send(string message) и public void SendChatMessage(string to, string message) .

  • Серверное приложение: public void SendChatMessage (строка в, строковое сообщение)

    • Приложение для Android: mHubProxy.invoke («SendChatMessage», имя_принимателя, сообщение);
  • Серверное приложение: public void Send (строковое сообщение)

    • Android-приложение для Android: mHubProxy.invoke («Отправить», сообщение);
 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; } } } 

СТОРОНА КЛИЕНТА:

Если вы не прочитали мой ответ по следующему вопросу:

Интеграция SignalR в студии Android

Тогда вот мой рабочий базовый код:

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

Мероприятия:

 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:

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

Вы также можете увидеть мой примерный проект клиента на этой ссылке GitHub


ОБНОВЛЕНИЕ ОТВЕТСТВЕННОСТИ ОТ ОТКРЫТИЯ:

Я только что добавил новые методы:

Серверная сторона:

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

Сторона клиента:

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

И вот скриншот:

Android SignalR Invoke Response

Эта работа для меня: полный исходный код Android (клиент) и сервер GitHub

Слайд сервера Если один аргумент должен использовать этот интерфейс SubscriptionHandler1, если два аргумента должны использовать этот интерфейсSubscriptionHandler2, …

Пример для двух аргументов:

Слайд сервера:

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

Слайд клиента:

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

Для catch все сообщение может использовать это:

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

Для тех, кто реализует клиент signalR в android, и данный ответ здесь не помогает при получении сообщений, вы можете проверить этот ответ rejnev .

Ответ реализует другой метод connection.received (), который способен принимать обратные вызовы сообщений с сервера в моем случае.