I am trying to create an Android chat client using ejabberd XMPP server (19.02), Smack library (4.2.4) and Android SDK 25 using Android Studio.
I followed the example app found here: https://www.blikoontech.com/tutorials/android-smack-xmpp-introductionbuilding-a-simple-client
All is working well and I can send messages between two different Android devices running that sample app.
In ejabberd, there are options to send messages to the clients directly from the server using a CLI tool called ejabberdctl or ejabberd REST API. When I sent messages that way, the Android client doesn’t receive those messages. I tried with other clients like Conversations and Gajim and they could all receive it. I am pretty sure messages sent using those methods arrived because they were received as offline messages (on ejabberd web admin) when sent to offline clients.
Here is the part of the Android (java) code (roosterconnection.java from that sample app) that is to receive incoming messages. Please suggest me if I am missing anything. Thanks a lot.
ChatManager.getInstanceFor(mConnection).addIncomingListener(new IncomingChatMessageListener() {
#Override
public void newIncomingMessage(EntityBareJid messageFrom, Message message, Chat chat) {
///ADDED
Log.d(TAG,"message.getBody() :"+message.getBody());
Log.d(TAG,"message.getFrom() :"+message.getFrom());
String from = message.getFrom().toString();
String contactJid="";
if ( from.contains("/"))
{
contactJid = from.split("/")[0];
Log.d(TAG,"The real jid is :" +contactJid);
Log.d(TAG,"The message is from :" +from);
}else
{
contactJid=from;
}
//Bundle up the intent and send the broadcast.
Intent intent = new Intent(RoosterConnectionService.NEW_MESSAGE);
intent.setPackage(mApplicationContext.getPackageName());
intent.putExtra(RoosterConnectionService.BUNDLE_FROM_JID,contactJid);
intent.putExtra(RoosterConnectionService.BUNDLE_MESSAGE_BODY,message.getBody());
mApplicationContext.sendBroadcast(intent);
Log.d(TAG,"Received message from :"+contactJid+" broadcast sent.");
///ADDED
}
});
Here is a possible explanation, based in my experiments with a desktop client, Tkabber:
I login to ejabberd using Tkabber client, account user1#localhost, resource tka1, priority -3. The negative priority in this experiment is important.
Then I execute the command to send to full JID, including the correct resource:
ejabberdctl send_stanza aaa#localhost user1#localhost/tka1
"<message>..."
The client receives the stanza correctly.
Now I send to bare JID (without providing resource), and another setting another resource:
ejabberdctl send_stanza aaa#localhost user1#localhost
"<message>..."
ejabberdctl send_stanza aaa#localhost user1#localhost/sdsd
"<message>..."
In those cases, none of them are received by the client, because the resource doesn't match, and because its priority is negative. I can see those messages stored offline in the database.
In your client, maybe you have to add another call to set the presence online, with a positive priority.
Related
I'm working with one live chatting application via XMPP, Used aSmack as client and configured ejabberd for server end. I'm Implement one to one chat and it's working fantastic. Now I'm trying to integrate Broadcast message to Multiple user.
I'm learn XEP-0033 protocol because I know this protocol is responsible for message broadcasting and also getting full theoretically clarity on same Basically my question is
I'm not getting any proper reference for integrate this protocol in my code.
Is aSmack is provide a predefined stanza for this protocol or May I need to make custom stanza to integrating this protocol. If yes than please suggest any reference link for same.
I'm also check MultiUserChatLightManager but this class is for Group chat but I need to first integrate Message broadcasting.
Is any change is required at ejabberd server side for implementing this protocol?
I'm not too much expert on XMPP.
i had the similar problem and was solved using this
upload a broadcast plugin to your openfire server.link is here
and the read me link for the plugin here
for broadcasting the message follow the pattern to set To Id
all#[serviceName].[serverName]
where serviceName is broadcast and serverName is our server name
send your xmpp message from your android client like this
Message msg = new Message();
msg.setBody(yourmessage);
msg.setFrom(yourJid);
msg.setTo("all#broadcast.yourservername");
yourXmppConnection.sendStanza(msg)
for other alternative and high customization in broadcasting message you can go for XEP-0060: Publish-Subscribe here
and here is the smack e.g
I'm developing an app which users can send a notification to another one.
Moreover, I'm using php scripts to retrieve and sent data to my Mysql database.
Using Volley, a user can inserts a new row into table 'Notifications', but I don't know how to listen that insert from the app.
I mean, now the user who sent the notification in the database should call the method getNotificationsFromDB() to get notifications and see them on a RecyclerView (like Facebook Notifications). There's no other way. And only can know about Notifications if he is running the app.
For example, a Notification could be like this: 'John has sent you a notification'.
Also, this thread runs on the Notifications Fragment...
final Thread thread = new Thread(new Runnable() {
#Override
public void run() {
getNotificacionsFromDB();
try {
Thread.sleep(100000);
run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
But it should consume a lot of resources from device. A friend told me it could be with Triggers running on 'the runtime' of android. But actually I didn't understand him.
How can I listen updates from my MySql DB to create a Push Notification?
Is there a way using Services like IntentService? or how SocialApps like Facebook or twitter manage the database updates?
Is GCM a good option?
Just like Bruno said it is required to have a server in order for your app to receive GCM messages and vice versa. The docs have an example using Java Smack library. But you don't necessarily have to use Java. Since the upstream message you send to the server from the Android devices MUST be xmpp protocol if you decide to use php then you might wanna look into xampp server which supports xmpp protocol. Good luck.
Your architecture is quite unorthodox. You can't have GCM messages without a server pushing those GCM messages. Are you sure you don't want to build a server in between your device and database? Your setup looks very vulnerable to attacks
I'm trying to implement a XMPP protocol in my GCM using app, but even after searching extensively, I don't understand the concepts behind it.
Also, maybe I don't really need XMPP for what I want to do with my app, but I like to learn things.
Let's take this example of what I could do with HTTP :
my app send "hello word" and the regId to my little personnal server : url.openConnection(""), then OutputStream for sending POST data and InputStream for getting the response
the server, at this url, put the "hello word" message in a database with the regId, and then use the curl library of php to send data to GCM servers as a json string like {"myResponse":"I'm not world I'm Dan"} (using a test destinator id, in an emulator)
GCM server do his business
my app (maybe on another phone) use an IntentService in a WakefulBroadcastReceiver that get the message as intent.getExtras().getString("myResponse")
This works well and I could send messages from one phone to another using my app, and collecting data on my server the way through.
Very little Question
Is this way of handling HTTP ok theorically ? (I saw a lot of posts and tutorials, especially Google ones, but still not sure)
Big real Question
What are the steps to do the same with XMPP ?
I don't want a tutorial or pieces of codes, I want to understand the way the info goes through this protocol I don't know well (I managed to install ejabberd on my server and use pidgin on my PC and Xabber on my phone).
Official definition:
The Google Cloud Messaging (GCM) Cloud Connection Server (CCS) is an
XMPP endpoint that provides a persistent, asynchronous, bidirectional
connection to Google servers.
Establishing a connection with CCS is the first and most important step here. Once you are done with this and maintain a long-lived connection, other parts are not that tricky.
Some differences between the two:
1) Unlike HTTP, with XMPP messages you do not need to include Authentication headers with every payload since server is authenticated at the time of connecting and we are maintaining the same connection.
2) CCS uses XMPP as a Transport Layer and therefore after you have successfully established connection you can exchange stanzas.
3) You could keep using HTTP for downstream though and use XMPP only for upstream if you wish.
4) Instead of registration_ids param use to: in XMPP and we can only send to one RegID through one stanza.
So if I were to explain how your example would work with XMPP:
- Establish a connection with CCS
- Send an upstream message to your server from the client "Hello, World!"
- Acknowledge once your server receives this message by sending ACK to GCM
- For downstream message you have choice of using either of HTTP or XMPP
- But if XMPP: receive, save in database and when sending response ({"myResponse":"I'm not world I'm Dan"}) back to the client (same or different RegID) send a downstream stanza to CCS; CCS will send ACK/NACK to acknowledge that it has received the message
- You will also receive delivery_receipt (if requested) once the client app has received the message.
Other than this, you can understand more in depth by reading the official documentation which I have linked throughout the post.
Hope this helps!
I am trying to implement a real-time pushing from my server to a customized android device. (A device which runs on android OS). I can't use GCN because there is no unique token.
Here is the deal.
Problem
I am posting a message from a web portal to the server
I would like the message to be pushed to the android device
Here are the proposed solution, which is the best?
Solution 1
Insert the message with a 'create_date' timestamp
Let the android device req the server every second to check for any new messages via the 'create_date'
Solution 2
Use Pusher with pusher-java-client library installed in the android device.
I am thinking of using solution 2, which is the most ideal, I think! Since I am not too sure how Pusher works, is the architecture of pusher the same as Solution 1?
Any kind souls would answer my question?
Thank you in advance.
The architecture is different in two ways:
The Pusher service will create a persistent connection between the mobile devices and the service so when new data is available it can be instantly pushed to the mobile device
Pusher offers you real-time infrastructure so instead of having to handle multiple polling requests you make a single HTTP request to Pusher and it will push the message you send to the mobile client. This is an easier architecture than building it yourself and you see significant benefits if you need to horizontally scale.
The Code
In the Android app:
Pusher pusher = new Pusher(YOUR_APP_KEY);
pusher.connect();
// Subscribe to a channel
Channel channel = pusher.subscribe("my-channel");
// Bind to listen for events called "my-event" sent to "my-channel"
channel.bind("my-event", new SubscriptionEventListener() {
#Override
public void onEvent(String channel, String event, String data) {
System.out.println("Received event with data: " + data);
}
});
On the Web Server (node):
var Pusher = require('pusher');
var pusher = new Pusher({appId: ID, key: KEY, secret: SECRET});
pusher.trigger('my-channel', 'my-event', {some: 'data'});
To ensure that channels can only be subscribed to by the intended recipient of the message you should use authenticated channels.
I am trying GCM based android app to push messages from server to android client. I am able to push fix string with the following coe. I am wondering about the ways to push XML file from server and parse at the android application. I have done some research but I couldn't find push XML rather I found send XML file. Thank you
if (androidArray.size() == 1) {
String registrationId = androidArray.get(0);
Message message = new Message.Builder()
.collapseKey(collapseKey)
.timeToLive(30)
.delayWhileIdle(true)
.addData("message", Message)
.build();
Result result = sender.send(message, registrationId, 5);
You don't push xml (or JSON preferably) to the android app. You send a simple message to the app.
when the app receives the message it then needs to go and pull the xml/json from the website with an http get request to the relevant url that will supply the xml.
The android app can then parse the response and do whatever you want it to.
Here is an EXCELLENT tutorial on C2DM (The forerunner to GCM) http://www.vogella.com/articles/AndroidCloudToDeviceMessaging/article.html
You should be able to work out the differences needed.
UPDATE
Google Android has a complete section on GCM which can be found here
http://developer.android.com/google/gcm/index.html
Within that link there are getting started guides and a GCM Demo app
There are limits to the amount of data you can send and you should not rely on your data not ever exceeding the limits or Google arbitrarily changing the amount of data you are allowed to send.
Should either of those occur you would need to update your app so just do it right in the first place.
The message you send should act as a "key" to determine what action to take when the message is received.
UPDATE
If you are feeling REALLY adventurous you could use a custom sync adapter to help you consume your web services. It's pretty advanced stuff but if you are feeling curious about this then watch the Google I/O seminar on consuming RESTfull web services http://www.youtube.com/watch?v=xHXn3Kg2IQE