Android - XMPP over websockets - android

I am trying to implement a chat functionality in my android app using XMPP over WebSockets.
I was able to find a library (org.igniterealtime.smack), but the connection is established over TCP and not over WebSockets, which I don't want.
Does anybody had to implement the same functionality and can point me in the right direction?

Websocket support for Smack is tracked as SMACK-835. It is currently in Smack's main branch and scheduled to become the Smack 4.5 release.
You can use it right now by consuming either Smack pre-releases or the nightly artifacts from https://www.igniterealtime.org/archiva/repository/maven/

Not sure if it's OK and doesn't violate TOS and whatnot but first sentence implies general guidance for XMPP + WebSocket and not strictly asking for Smack answer so - you could use JaXMPP library (https://github.com/tigase/jaxmpp), which already supports WebSocket and and is compatible with Android (StorkIM, https://github.com/tigase/stork is based on it).
It's quite easy to establish WebSocket connection (even encrypted):
JID user = JID.jidInstance("user#example.com/resource");
String password = "password";
Jaxmpp contact = new Jaxmpp();
contact.getModulesManager().register(new MessageModule());
contact.getConnectionConfiguration().setConnectionType(ConnectionConfiguration.ConnectionType.websocket);
contact.getConnectionConfiguration().setBoshService("wss://xmpp.example.com:5291");
contact.getConnectionConfiguration().setUserJID(user.getBareJid());
contact.getConnectionConfiguration().setUserPassword(password);
try {
contact.login(true);
if (contact.isConnected()) {
contact.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
(disclaimer: I'm from Tigase team, which created both JaXMPP and StorkIM)

Related

SignalR v2.3.0 in Android

I have a MVC .NET application that uses signalR.
I tried to download this client:
https://github.com/Gurgen/SignalR-.net-core-android-client
I ran it on my device. Pressed the connect button. But kept getting an exception.
Debugging it I found that I had to change this line
String connectionId = jsonElement.getAsJsonObject().get("connectionId").getAsString();
to this
String connectionId = jsonElement.getAsJsonObject().get("ConnectionId").getAsString();
I am already starting to feel like this client doesn't support v2.3.0 of the SignalR library in my .NET application. Any way the next exception is caused by this line:
JsonElement availableTransportsElements = jsonElement.getAsJsonObject().get("availableTransports");
I had a look at the JSON returned by SignalR and there is no such element as "availableTransports". This is what it returned
{ "Url":"/signalr/hubs/auth","ConnectionToken":"zzK0SAWXNEB1pLY2VYHWPYTMcyJIX8PnhKfLRP9fij5xbY2jDIaDyKuZQa5RvHt+KSe6h1PD9JC+RL7V2nhPzevktK781hL7ndAnZqAe3E12GawCVddFUI4R9FLDE//L","ConnectionId":"9cb5ff73-14d3-4e59-8b14-d92e47bbe948","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"ConnectionTimeout":110.0,"TryWebSockets":false,"ProtocolVersion":"1.2","TransportConnectTimeout":5.0,"LongPollDelay":0.0 }
Ok my question, has anyone used this library? Or is there another Android library I can use that is compatible? I am new to SignalR but from what the server sent does the .NET application support websockets? I want my Android client to connect using websockets.
UPDATE
OK I have discovered that WebSocket Protocol feature was not installed in IIS. I have done that now and now this is what is returned, however the client cannot still connect to it.
{ "Url":"/signalr/hubs/auth","ConnectionToken":"6CkVnCK9KmbDemtXY/S+zCyBUdaYbaK8WmQxIw6+JxjeEzWCP7BPTiItqgvzu+hhaf6kIS4NlPln8LJLfS95UbUG4rF/8C6Y5D7eq2aKCLEU6up/c4l8YvMKheodRsKy","ConnectionId":"abe2cdca-e237-4cbd-8523-98af8c864b9b","KeepAliveTimeout":20.0,"DisconnectTimeout":30.0,"ConnectionTimeout":110.0,"TryWebSockets":true,"ProtocolVersion":"1.2","TransportConnectTimeout":5.0,"LongPollDelay":0.0}
That is a step closer as now TryWebSockets is true.

Sending alerts / notifications from server side to android application without internet access

I need to send a push notificiation from a webapp to an android app.
Basically I just want to inform the android client that new data is available on the server. So it only has to be a string + vibration/sound of the phone.
The (big) problem here is that I am inside a corporate network without access to the internet. This is why I cannot use GCM.
So far I found the following options to accomplish the task without GCM:
Use XMPP
WebSockets
Ajax Polling
Is it possible to include WebSockets or AjaxPolling into a native Android app to trigger events like vibrate?
Is there an easier solution, without that much overhead as with xmpp, since I just need to send a short notification? So far I understand that I need somethink like SMACK XMPP for Android + e.g. Openfire and XMPPHP on the server side for this scenario.
Since nobody replied, I want to provide you with an approach I now try to pursue.
I use Laravel to write the API. It comes with an out-of-the-box support for Redis, which is awesome to Broadcasts Events -> https://laravel.com/docs/5.1/events
The following is just a quick example:
Redis::publish('test', json_encode($data));
Those events are received from a Socket.IO Server-Instance running on the same machine.
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('test');
....
server.listen(3000);
Socket.IO has an android client implementation, which allows me to connect to the socket.io server in a native android app.
Here is an example: http://socket.io/blog/native-socket-io-and-android/
private Socket mSocket;
{
try {
mSocket = IO.socket("http://localhost:3000");
} catch (URISyntaxException e) {}
}

Which WebSocket library to use in Android app? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I want to add a Service to my Android app which runs in the background holding a WebSocket connection (possibly over several hours or even days) and regularly sends some data to a server.
Now there seems to be a bunch of WebSocket libraries for Java, and I'm not sure which one I should use:
TooTallNate/Java-WebSocket
Description from GitHub: A barebones WebSocket client and server implementation written in 100% Java. http://java-websocket.org/
-- This one is linked in my first result of googling "android websocket". However, it has quite a few open issues, especially about SSL connections, and it doesn't seem to be actively maintained at the moment.
koush/AndroidAsync
Description from GitHub: Asynchronous socket, http (client+server), websocket, and socket.io library for android. Based on nio, not threads.
-- Again many open issues, but seems to be activiley maintained/worked on.
Project Tyrus
Description from Website: JSR 356: Java API for WebSocket - Reference Implementation
-- This is made by Oracle. Not sure if it works in Android.
Jetty WebSocket Client API
Info from Website: Jetty also provides a Jetty WebSocket Client Library to write make talking to WebSocket servers easier.
-- Again: Not sure if it works in Android.
codebutler/android-websockets
Description from GitHub: Bare minimum websockets (hybi13/RFC) client for Android
-- This one is used in schwiz/android-websocket-example, which is the accepted answer for the StackOverflow-question "How to make the Android device hold a TCP connection to Internet without wake lock?".
Atmosphere/wasync
Description from GitHub: WebSockets with fallback transports client library for Node.js, Android and Java http://async-io.org
TakahikoKawasaki/nv-websocket-client
Description from GitHub: High-quality WebSocket client implementation in Java.
square/okhttp
Description from GitHub: An HTTP+SPDY client for Android and Java applications. http://square.github.io/okhttp/
-- It has a Websocket module. As mentioned by scorpiodawg, OkHttp has built-in websocket support since version 3.5.
firebase/TubeSock
Description from GitHub: A WebSocket client library implemented in Java
Autobahn|Android (GitHub)
Description from Website: Autobahn|Android is an open-source networking library for Java/Android created by the Autobahn project that implements the WebSocket Protocol and the Web Application Messaging Protocol (WAMP) for creating native mobile WebSocket/WAMP clients. -- cloudsurfin pointed out that this has no support for wss.
In addition, there is a native socket.io client library for Android:
nkzawa/socket.io-client.java
Description from GitHub: Full-featured Socket.IO Client Library for Java, which is compatible with Socket.IO v1.0 and later.
To use the socket.io Android client would be handy for me, because I plan to use nodejs/socket.io for the web frontend anyway. But the native client is quite young and has several open issues. And in addition to that, it is my understanding that an android app does not have any benefit of using the socket.io client library (apart from being compatible with socket.io 1.0 server), because WebSocket support can be assured at the client side.
My requirements are as follows:
Compatibility with Android API 9 and higher
Possibility to connect via SSL
Keep the connection for a long time without having to hold a permanent wakelock
Compatibility with an available nodejs websocket server implementation or with socket.io
Any suggestions which one is the right library for these requirements?
Some notes.
koush/AndroidAsync does not perform the closing handshake which is required by RFC 6455. See this for details.
Project Tyrus works on Android, but make sure that its license (CDDL 1.1 and GPL 2 with CPE) and its size (Reducing WebSocket client jar size with ProGuard) meet your requirements. Also note that Tyrus may throw an exception when a text size is large (it's probably a bug). See this for details.
Jetty: A 2-year-ago email thread in jetty-users mailing list says "We currently have no Android compatible Jetty 9 WebSocket client. There are plans to attempt to backport the Jetty WebSocket Client from JDK 7 to JDK 5/6 for android use, but its a lower priority than finishing our implementation of JSR-356 Java WebSocket API (javax.websocket)." Jetty's current document about its WebSocket Client API does not mention anything about Android.
codebutler/android-websocket does not perform the closing handshake which is required by RFC 6455 and may throw an exception on close. See this.
Atmosphere/wasync uses AsyncHttpClient/async-http-client as its WebSocket implementation. So, rather, AsyncHttpClient/async-http-client should be mentioned instead.
firebase/TubeSock does not verify Sec-WebSocket-Accept. This is a violation against RFC 6455. Also, TubeSock has a bug in building a text message. You will encounter the bug sooner or later if you use multi-byte UTF-8 characters for text messages. See Issue 3 in delight-im/Android-DDP for a long list about TubeSock problems.
Consideration Points
Consideration points in selecting a WebSocket client implementation written in Java:
Compliance. Not a small number of implementations do not implement the closing handshake required by RFC 6455. (What happens if the closing handshake is not implemented? See this.)
Required Java version. Java SE 5, 6, 7, 8 or Java EE? Works even on Android?
Size. Some implementations have many dependencies.
wss support.
HTTP proxy support.
wss over HTTP proxy support. See Figure 2 in How HTML5 Web Sockets Interact With Proxy Servers about what a WebSocket client library has to do to support wss over HTTP proxy.
Flexibility on SSL configuration. SSLSocketFactory and SSLContext should be able to be utilized without unnecessary restrictions.
Custom HTTP headers in the opening handshake, including Basic Authentication.
Custom HTTP headers in HTTP proxy negotiation, including authentication at the proxy server.
Capable of sending all the frame types (continuation, binary, text, close, ping and pong) or not. Most implementations do not provide developers with means to send fragmented frames and unsolicited pong frames manually.
Listener interface to receive various WebSocket events. A poor interface makes developers frustrated. A rich interface helps developers write robust applications.
Able to inquire WebSocket state or not. RFC 6455 defines CONNECTING, OPEN, CLOSING and CLOSED states, but few implementations maintain their internal state transition in the defined way.
Able to set a timeout value for socket connection. (Equivalent to the second argument of Socket.connect(SocketAddress endpoint, int timeout) method)
Able to access the underlying raw socket.
Intuitive easy-to-use API or not.
Well-documented or not.
RFC 7692 (Compression Extensions for WebSocket) support (aka permessage-deflate).
Redirection (3xx) support.
Digest Authentication support.
nv-websocket-client covers all the above except the last two. In addition, one of its small but convenient features is to send ping/pong frames periodically. It can be achieved just by calling setPingInterval/setPongInterval methods (See JavaDoc).
Disclaimer: Takahiko Kawasaki is the author of nv-websocket-client.
Some other considerations:
Tyrus works on Android. However, the SSL libraries it uses in Android 5.0 are buggy and fail SSL handshakes. This is supposed to be fixed in newer versions of Android, but with the way that Android is not updated on many devices, this may be a problem for you.
Depending on how SSL is implemented for other websocket implementations, this may also be a problem.
AndroidAsync does not have this SSL issue. It does have other issues like not being able to set timeouts.
a) Add this file in gradle file
compile 'com.github.nkzawa:socket.io-client:0.3.0'
b) Add these lines in Application Activity:
public class MyApplication extends Application {
private Socket mSocket;
{
try {
mSocket = IO.socket(Config.getBaseURL());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public Socket getSocket() {
return mSocket;
}
}
c) Add this function to your activity, where you called WebSocket:
private void websocketConnection() {
//Get websocket from application
MyApplication app = (MyApplication ) getApplication();
mSocket = app.getSocket();
mSocket.on(Socket.EVENT_CONNECT, onConnect);
mSocket.on(Socket.EVENT_DISCONNECT, onDisconnect);
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.on("messageFromServer", onNewLocation);
mSocket.connect();
}
private Emitter.Listener onConnect = new Emitter.Listener() {
#Override
public void call(Object... args) {
runOnUiThread(() -> {
if (!isConnected) {
RequestSocket mRequestSocket = new RequestSocket();
mRequestSocket.setToken("anil_singhania");
/* your parameter */
mSocket.emit("messageFromClient", new Gson().toJson(mRequestSocket));
Log.i("Socket Data", new Gson().toJson(mRequestSocket));
isConnected = true;
}
});
}
};
private Emitter.Listener onDisconnect = args -> runOnUiThread(() -> {
isConnected = false;
/* Toast.makeText(getApplicationContext(),
R.string.disconnect, Toast.LENGTH_LONG).show();*/
});
private Emitter.Listener onConnectError = args -> runOnUiThread(() -> {
/* Toast.makeText(getApplicationContext(),
R.string.error_connect, Toast.LENGTH_LONG).show()*/
});
private Emitter.Listener onNewLocation = new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(() -> {
});
}
};

flexible offline messages retrieval returning false

In my XMPP chat application, I am using ASMACK library 4.0.6 on the Android client side.
I want to retrieve offline messages when an XMPP connection is established. For that, first I check whether the server has support for flexible retrieval. The server always returns false. We enabled the offline module in MongooseIM server. But why am I getting false from server?
if (!offlineMessageManager.supportsFlexibleRetrieval()) {
Log.i("Offline messages not supported","" + offlineMessageManager.supportsFlexibleRetrieval());
return;
}
If I try with pidgin client, I get offline messages..
Disclaimer: I work on MongooseIM.
Guessing from the API you're trying to use it implements XEP-0013 - MongooseIM doesn't support this XEP. Ensure what protocol .supportsFlexibleRetrieval() really uses underneath.
MongooseIM supports XEP-0313 version 0.2 and will support the newest version of this XEP. Verify whether your client library supports this XEP and which version of it. The relevant module to run on the server is mod_mam. Please refer to the MongooseIM wiki on GitHub, since its configuration is a bit complex.
Alternatively, you can rely on mod_offline automatically pushing the offline messages when a resource connects.

Asmack/Openfire 401 error

I'm trying to write a simple XMPP application on Android using asmack, but I've encountered a problem that I cannot login to several jabber servers. For example, I can't login into my test Openfire server, although the code works fine with jabber.org accounts.
Login code:
public void login() throws XMPPException
{
if (connection != null && connection.isConnected())
{
try
{
Random generator = new Random();
int resource_int = generator.nextInt();
connection.login(USERNAME, PASSWORD,
"Smack_" + Integer.toString(resource_int));
}
catch (XMPPException e)
{
e.printStackTrace();
connection.disconnect();
setConnection(null);
throw e;
}
Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.accept_all);
}
}
As I said, it works with jabber.org, but Openfire returns not-authorized(401) error. How can I fix it?
I never used Openfire, but I'm sure there is a Logfile somewhere - can you post it?
IIRC in Android some security functions (not sure if for SSL or TLS) are not compatible to Smack or Asmack, maybe thats the problem. In this case there is a way to solve it by using an own Socket connection (instead of the included SSL functions of Smack) - To verify this you can port your (XMPP-relevant) code to PC and use the Standard Smack Library.
Another point is, that there are different Smack ports for Android. I personally use the Asmack port from the Beem-project (because the originally Asmack had some issues - but I can't remember which ones...)
But still...without more information I can only guess.
Are you sure that you have the same account and password on the OpenFire server? Try logging into your server using the same username and password with an existing XMPP client. Take Android out of the equation altogether and make sure you can log into both servers first.

Categories

Resources