Итак, после долгих мучений, наконец, мне удалось разобраться со всем функционалом (что мне нужно было для моей работы), что есть в библиотеке Signal R для Android.
Самое главное, это jar файлы, которые нужны нашей программе для подключения и работы с сервером.
Их можно скачать из моего сайта, хотя вы тоже сами можете из сделать из Github:
http://smartarmenia.com/android_libs/signalr-client-sdk.jar
http://smartarmenia.com/android_libs/signalr-client-sdk-android.jar
Еще нам нужна библиотека gson, которую можно добавить из maven dependencies в Android Studio или скачать из google для Eclipse.
Так, после добавления этих библиотек в папку libs нашего проекта, можно уже подключиться к серверу.
Я на своем примере буду все делать из сервиса и AsyncTask-ами, как и откуда делать — будете вы решать сами.
Первое, что нужно делать — это вызвать статический метод до того, как начнем использовать signalr в Android.
Platform.loadPlatformComponent(new AndroidPlatformComponent());
Потом создаем connection и hub(s):
HubConnection connection = new HubConnection("signalr_host");
HubProxy mainHubProxy = connection.createHubProxy("MainHub");
После этого нам надо отловить state_change события, чтобы контролировать нашим соединением.
connection.stateChanged(new StateChangedCallback() {
@Override
public void stateChanged(ConnectionState connectionState, ConnectionState connectionState2) {
Log.i("SignalR", connectionState.name() + "->" + connectionState2.name());
}
});
это для изменения state (Disconnected, Connecting, Connected, Reconnecting)
Теперь отловим событие отсоединения:
connection.closed(new Runnable() {
@Override
public void run() {
Log.i("SignalR", "Closed");
connectSignalr();
}
});
Функция, которая вызывает AsyncTask соединения (эту функцию нужно вызвать в начале сервиса и при Disconnect (Close)):
private void connectSignalr() {
try {
SignalRConnectTask signalRConnectTask = new SignalRConnectTask();
signalRConnectTask.execute(connection);
} catch (Exception ex) {
ex.printStackTrace();
}
}
Код класса SignalRConnectTask:
public class SignalRConnectTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
HubConnection connection = (HubConnection) objects[0];
try {
Thread.sleep(2000);
connection.start().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
}
У нас уже есть рабочее подключение к серверу. В дальнейшем нам понадобится подписаться к событиям или вызвать функции hub-а.
subscribe
mainHubProxy.subscribe("newClient").addReceivedHandler(new Action<JsonElement[]>() {
@Override
public void run(JsonElement[] jsonElements) throws Exception {
Log.i("SignalR", "Message From Server: " + jsonElements[0].getAsString());
}
});
В массиве jsonElements — данные, которые нам отправил сервер, они могут быть любого serializable типа. В основном мы знаем, какого они типа и можем преобразовать на нужный тип. Примеры делайте сами, но если будут вопросы или нужны будут примеры, напишите в комментариях.
invoke
Это — для вызова метода hub-а. У нас есть 2 варианта, вызов метода, который возвращает результат и ничего не возвращает (Void).
Сначала посмотрим Void:
public class SignalRTestActionTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
if (connection.getState() == ConnectionState.Connected) {
Object param1 = objects[0];
Object param2 = objects[1];
try {
mainHubProxy.invoke("TestMethod", param1, param2).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
}
}
new SignalRTestActionTask().execute(new Object(), new Object());
Опять же, создаем AsyncTask для выполнения задачи.
Теперь тоже самое сделаем и для другого варианта invoke, который возвращает результат.
public class SignalRTestActionWithResultTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
if (connection.getState() == ConnectionState.Connected) {
Object result = null;
Object param1 = objects[0];
Object param2 = objects[1];
try {
result = mainHubProxy.invoke(Object.class, "TestMethod", param1, param2).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}
@Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
// Тут идет обработка результата.
}
}
new SignalRTestActionWithResultTask().execute(new Object(), new Object());
Все просто.
Далее настало время десериализации json-а в классы.
Например, наш метод в signalr возвращает String — и мы это знаем.
Для этого мы просто передаем функцию invoke тип результата метода и полученный результат с помощью gson преобразует данные в нужный тип.
String result = mainHubProxy.invoke(String.class, "TestMethod", param1, param2).get();
Когда приходит json array, то тип передаем array, так:
String[] result = mainHubProxy.invoke(String[].class, "TestMethod", param1, param2).get();
Ну а наш array легко можно преобразовать в List:
List<String> strings = Arrays.asList(result);
Как тип возвращаемого результата можно задать любой сериализуемый тип, например, сами можем создать собственный класс со структурой json объекта. Но это чудеса библиотеки gson, которому эта статья не посвящена.
Вот и все, наверное. Если будут вопросы и/или замечания, напишите, разберемся вместе.