Ich versuche, signalR
in Android
app zu integrieren, aber kein Glück. Ich habe mir verschiedene Links angesehen, aber keiner von ihnen liefert korrekte Informationen zur Implementierung.
Ich habe folgende Fragen.
SignalR
Integration muss innerhalb von Service/Intent Service erfolgen?Ich habe drei Bibliotheken hinzugefügt, d. H. signalr Android
, signalr client
und gson
, aber ich kann die Funktionsweise von Code nicht verstehen. Es ist keine geeignete Dokumentation verfügbar, um den Code zu verstehen.
Einige der gestellten Fragen, aber nicht viele Informationen
SignalR in Android Studiop2p-Chat kann nicht mit SignalR in Android implementiert werden
Wenn jemand Erfahrung mit Signal für native Apps hat, wäre das für mich sehr hilfreich.
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();
}
}
UPDATE 2018:
Wenn Sie SignalR.net Core verwenden, verwenden Sie diese Bibliothek , andernfalls erhalten Sie einen Verbindungsfehler.
SERVER-SEITE:
Das Folgende ist mein serverseitiger Beispielcode. Sie können auf public void Send(string message)
und public void SendChatMessage(string to, string message)
achten.
Serverseitige App: public void SendChatMessage (Zeichenfolge an, Zeichenfolge)
- Android-Client-App: mHubProxy.invoke ("SendChatMessage", Empfängername, Nachricht);
Serverseitige App: public void Send (Zeichenfolge)
- Android-Client-App: mHubProxy.invoke ("Senden", Nachricht);
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:
Wenn Sie meine Antwort nicht bei der folgenden Frage gelesen haben:
SignalR-Integration in Android Studio
Dann ist hier mein funktionierender grundlegender 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);
}
}
Aktivität:
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-Klasse:
public class CustomMessage {
public String UserName;
public String Message;
}
Sie können mein Beispielclientprojekt auch unter diesem GitHub-Link sehen.
UPDATE FOR RESPONSE FROM INVOKE:
Ich habe gerade neue Beispielmethoden hinzugefügt:
Server Seite:
public string iAmAvailable(string username, string password, string message)
{
return "BNK Response for testing Android INVOKE";
}
Client-Seite:
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());
}
});
Und hier ist der Screenshot:
Diese Arbeit für mich: Full Source Android (Client) & Server GitHub
Serverfolie Wenn ein Argument diese Schnittstelle verwenden muss SubscriptionHandler1, wenn zwei Argumente diese Schnittstelle verwenden müssenSubscriptionHandler2, ...
Beispiel für zwei Argumente wie:
Serverfolie:
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);
}
}
}
Kundenfolie:
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 kann folgendes verwenden:
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();
}
});
}
});
Für diejenigen, die den signalR-Client in Android implementieren und die hier gegebene Antwort nicht beim Empfang der Nachrichten hilft, können Sie this durch rejnev beantworten.
Die Antwort implementiert eine andere Methode connection.received (), die in meinem Fall Nachrichtenrückrufe vom Server empfangen kann.
Das SignalR-Team hat kürzlich einen Java-Client für ASP.NET Core SignalR veröffentlicht. Hier ist ein Link zum Einstieg docs https://docs.Microsoft.com/en-us/aspnet/core/signalr/Java-client?view=aspnetcore-2.2