We setup socket.io in our node.js server. We try to use Socket.io Java Client and Socket.io iOS Client. We able to connect through iOS but we cannot able to connect through Android. We don't have any clue , why Android is not connecting.
Server Side:
var socketIO = require('socket.io');
//var io =
GLOBAL._io = socketIO(httpServer);
_io.on('connection', (socket) => {
console.log('Client connected');
setInterval(() => _io.emit('time', new Date().toTimeString()), 1000);
socket.on('disconnect', () => console.log('Client disconnected'));
});
Android Not Working
public void addSocketConnection() throws URISyntaxException {
Log.i("Socket.io","Init");
mSocket = IO.socket("http://dev.myapp.com/parse");
mSocket.on(Socket.EVENT_CONNECT,onConnect);
mSocket.on("time",onTime);
mSocket.on(Socket.EVENT_DISCONNECT,onDisconnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.connect();
Log.i("Socket.io","Connect");
}
private Emitter.Listener onTime = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("Socket.io","OnTime");
}
};
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("Socket.io","OnConnect");
}
};
private Emitter.Listener onDisconnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.i("Socket.io","DisConnect");
}
};
iOS Working
NSURL* url = [[NSURL alloc] initWithString:#"http://dev.myapp.com/parse"];
SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url options:#{#"log": #YES, #"forcePolling": #YES}];
[socket on:#"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
NSLog(#"socket connected");
}];
[socket onAny:^(SocketAnyEvent *event) {
NSLog(#"On any event :%#",event.event);
}];
[socket on:#"time" callback:^(NSArray* data, SocketAckEmitter* ack) {
NSLog(#"Time %#",data[0]);
}];
[socket connect];
I have fixed and updated in github and forgot to update here.github issue link
A little bit confusion but fixed to work on both.
We have parse server URL : "http://dev.myapp.com/parse"
Our Node URL: "http://dev.myapp.com/"
By mistake we point to URL "http://dev.myapp.com/parse" for iOS, it is working.
So we point to the same URL for Android , it is not working.
Then we changed both urls to "http://dev.myapp.com", now working on both iOS and Android.
Note:
We have no clue why iOS is working for "http://dev.myapp.com/parse"
Related
I successed to send ack to android client from nodejs server but I don't succeed to do reverse. I have this error: Callbacks are not supported when broadcasting at Socket.emit
Serveur nodejs:
socket.broadcast.to(socketid).emit('message', data, callThis);
//this function is executed when client calls it
function callThis (dataFromClient){
console.log("Call back fired: " + dataFromClient);
}
client android:
socket.on("message", new Emitter.Listener() {
#Override
public void call(Object... args) {
Ack ack = (Ack) args[args.length - 1];
ack.call();
JSONObject data = (JSONObject) args[0];
.....
}
}
What can I do to resolve this problem?
Basically support the answer of #Xeoncross. When a connection came, just saved the socket into a map, like below
this.connections = new Map<string, SocketIO.Socket>()
this.server.on("connection", (socket: SocketIO.Socket) => {
this.connections.set(socket.id, socket)
})
Then use a loop to send all users individually
public broadcast(msg: string) {
for(const socket of this.connections.values()) {
socket.emit("block", msg, (confirm: string) => {
console.log("confirmation msg: ", confirm)
})
}
}
As the error says, "Callbacks are not supported when broadcasting". It doesn't look like you are broadcasting though, as you are trying to send to a single client. So assuming socket is an actual client socket instance you can change your code:
socket.broadcast.to(socketid).emit('message', data, callThis);
to just send to that one person
socket.emit('message', data, callThis);
I'm running an application with SignalR 2.2.0 on server side and signalr-java-client (self compiled, last GitHub version) on Android as client.
Currently, there are 4 clients connected to my hub. From time to time, it happens, that all 4 clients simultaneously receive the HTTP status 400 with the message "The connection id is in the incorrect format" (the clients were connected before). I analyzed this multiple times and am not able to find any information/pattern when or why this happens.
The connecten is secured via JWT, the token is definitely valid. When retrieving a new token, the connection is stopped and started again. Apart from this, it is very unlikely that the error is device-related, because the error is thrown at all 4 clients the same time.
I know, this error can occur when the client's Identity changes, but an Identity change for 4 clients the same time seems very unlikely to me.
This is the server-code used for authentication (Deepak asked).
The following method gets called in my Startup.cs:
public static void ConfigureOAuth(IAppBuilder app, string audienceID, string sharedSecret)
{
byte[] secret = TextEncodings.Base64Url.Decode(sharedSecret);
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
Provider = new MyOAuthBearerAuthenticationProvider(),
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audienceID },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(Issuer, secret)
}
});
}
Here's the code of MyOAuthBearerAuthenticationProvider class:
class MyOAuthBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
{
/// <summary>
/// Get's a JWT from querysting and puts it to context
/// </summary>
public override Task RequestToken(OAuthRequestTokenContext context)
{
if (context.Token == null)
{
string value = context.Request.Query.Get("auth_token");
if (!string.IsNullOrEmpty(value)) //token from queryString
{
context.Token = value;
}
}
return Task.FromResult<object>(null);
}
}
I have to retrieve the token from query string, because additionally to the java-client, a javascript client is used, which is not able to set headers.
Lastly, I secure my hub and some of it's methods with the Authorization attribute:
[Authorize(Roles = "MyExampleRole")]
This is the client-code for connection:
public boolean connect(String url, String token) {
if (connected) {
return true;
}
try {
this.hubConnection = new HubConnection(url, "auth_token=" + token, true, logger);
this.hubProxy = hubConnection.createHubProxy("MyHub");
this.hubProxy.subscribe(this.signalRMethodProvider);
this.hubConnection.stateChanged(stateChangedCallback);
SignalRFuture<Void> awaitConnection = this.hubConnection.start();
awaitConnection.get(10000, TimeUnit.MILLISECONDS);
return true;
}
catch (InterruptedException | TimeoutException | ExecutionException e) {
log.error("connect", e);
return false;
}
}
Does anybody have an Idea, how to fix this problem or where I may receive further information?
Thank you very much
-Lukas
seems fine...
possible alteration you can do is change
awaitConnection.get(10000, TimeUnit.MILLISECONDS);
to
awaitConnection.done(new Action<Void>() {
#Override
public void run(Void obj) throws Exception {
Log.d(TAG, "Hub Connected");
}
}).onError(new ErrorCallback() {
#Override
public void onError(Throwable error) {
error.printStackTrace();
Log.d(TAG, "SignalRServiceHub Cancelled");
}
}).onCancelled(new Runnable() {
#Override
public void run() {
Log.d(TAG, "SignalRServiceHub Cancelled");
}
});
I have been working in a chat app using nodejs and socket.io. I already have an Android client that works perfect in this schema. I started to use express.io instead of use express an socket.io separately. Everything works well except for my Android client. Im using https://github.com/socketio/socket.io-client-java socket client in Android, but my app never connect to my socket server.
I received the following error:
io.socket.engineio.client.EngineIOException: server error
Does anybody knows something about this issue?
Server side config:
var express = require('express.io');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');
var multer = require('multer');
var app = express();
app.http().io()
app.io.route('storeClientInfo', function(req) {
req.io.join(req.io.request.data.customId);
});
app.io.route('enviar_room', function(req) {
app.io.room(req.params.correo).broadcast('new visitor');
});
// Start the server
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + server.address().port);
});
Android side:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
mSocket = IO.socket(LoginActivity.URL_HOST);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on("new visitor",onNuevoMensaje);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
private Emitter.Listener onConnectError = new Emitter.Listener() {
#Override
public void call(Object... args) {
Log.d("SocketMsg: ", args[0].toString());
for (Object o : args) {
Log.i("IO " + Socket.EVENT_CONNECT_ERROR, o.toString());
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"CONNECT ERROR", Toast.LENGTH_LONG).show();
}
});
}
};
Currently I already have a Angularjs web version running with my server. The problem is that in Android i always received Socket.EVENT_CONNECT_ERROR.
After two days of tests I found that the problem was that Express.io include a socket.io version 0.9.6. The socket.io-client-java library (https://github.com/socketio/socket.io-client-java) support socket.io 1.x or later. I manually changed the socket.io version on Express.io to the 1.3.7 version. I just had to modify some parts of the code on the Express library.
Software Stack:
Tomcat v7.0.62
Primefaces 5.0 application with Atmosphere (#PushEndpoint) - atmosphere-runtime v.2.1.3
External Android app with Atmosphere Wasync client v1.4.3
We have 2 separate applications. On the one hand, we have a PrimeFaces application that, among other things, send notifications. On the other hand, we have an independent android app. We're trying to figure out the best way for PF browser clients to send/receive messages with standalone android client using wAsync.
It seems that the android app is able to connect successfully. But, send notification with PF didn't have any effect, the app doesn't receive it, and there were no error messages on either android app or the server.
This is the primefaces code:
#PushEndpoint("/servicios")
public class ServiciosPushControlador implements ServiciosControladorListener {
#Override
#OnMessage(encoders = {JSONEncoder.class})
public String servicioActualizado(Servicio servicio) {
return "update";
}
}
And web.xml configuration for Atmosphere
<!-- PUSH PrimeFaces-->
<servlet>
<servlet-name>Push Servlet</servlet-name>
<servlet-class>org.primefaces.push.PushServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Push Servlet</servlet-name>
<url-pattern>/primepush/*</url-pattern>
</servlet-mapping>
And this is the Android code:
public <ResultType> void notificationSuscriber(Function<ResultType> succesFunction, Function<IOException> errorFunction, final Class<ResultType> clazz) throws IOException {
RequestBuilder request = client.newRequestBuilder()
.method(org.atmosphere.wasync.Request.METHOD.GET)
.uri("http://192.168.0.101:8080/calview/primepush/servicios")
.encoder(new Encoder<ResultType, String>() {
#Override
public String encode(ResultType s) {
try {
return mapper.writeValueAsString(s);
} catch (IOException iOEx) {
throw new RuntimeException(iOEx);
}
}
})
.decoder(new Decoder<String, ResultType>() {
#Override
public ResultType decode(Event e, String s) {
if (s.length() == 0)
return null;
if (e.equals(Event.MESSAGE)) {
try {
return new ObjectMapper().readValue(s, clazz);
} catch (IOException iOEx) {
iOEx.printStackTrace();
return null;
}
} else
return null;
}
})
.transport(org.atmosphere.wasync.Request.TRANSPORT.WEBSOCKET);
Socket socket = client.create();
socket.on("message", succesFunction)
.on(errorFunction)
.open(request.build());
}
I'd like to use RabbitMQ client from an android App.
From the server side, i use SpringBoot with spring AMQP. RabbitMQ (rabbitmq_server-3.4.3) is installed correctly and an integration test valid the server behaviour.
The difficult part is when i try to create a connection from RabbitMQ connectionFactory inside my android project.
I get this exception :
failed to connect to localhost/127.0.0.1 (port 5672):
connect failed: ECONNREFUSED (Connection refused)
In android manifest, Internet permission is set :
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Here is my code :
public class LoadingTask extends AsyncTask<String, Integer, Integer> {
private static String replyQueue = "REPLY_QUEUE";
public interface LoadingTaskListener {
void onResourceLoaded();
}
private final ProgressBar progressBar;
private final LoadingTaskListener loadingTaskListener;
private ConnectionFactory connectionFactory;
public LoadingTask(ProgressBar progressBar, LoadingTaskListener loadingTaskListener) {
this.progressBar = progressBar;
this.loadingTaskListener = loadingTaskListener;
this.connectionFactory = new ConnectionFactory();
connectionFactory.setAutomaticRecoveryEnabled(true);
}
#Override
protected Integer doInBackground(String... params) {
try {
/*init rabbitMQ Context*/
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
channel.basicQos(1);
channel.queueDeclare(DATA_QUEUE.getName(), false, false, false, null);
AMQP.Queue.DeclareOk q = channel.queueDeclare();
channel.queueBind(q.getQueue(), "amq.fanout", "chat");
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(replyQueue, true, consumer);
/* initiate RPC */
String corrId = java.util.UUID.randomUUID().toString();
AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
.correlationId(corrId)
.replyTo(replyQueue)
.build();
AmqpRequest request = new AmqpRequest(LIST_IMAGE);
Gson gson = new Gson();
String jsonRequest = gson.toJson(request);
channel.basicPublish(MAIN_EXCHANGE.getName(), DATA_QUEUE.getRoutingKey(), props, jsonRequest.getBytes());
String response;
while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
if (delivery.getProperties().getCorrelationId().equals(corrId)) {
response = new String(delivery.getBody());
break;
}
}
System.out.println(response);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Dummy Data until i can't connect to rabbitMQ
return 1234;
}
}
Is it really possible to connect Android on RabbitMQ, or should i use a kind of http bridge ?
Could anyone provide me an exemple for both http bridge or RabbitMQ connection.
Thank you