I have offline messages option enabled in the openfire server.But I'm unable to get offline messages
User A is online ,User B is online ,in this case I'm able to get messages.
Now User B Turned off his WiFi(Note : User A waited till the user B Session completely killed in the server )
now User A send a message to User B
in this case I'm able to see the message in the openfire offline table.
Now User B Comes online again server is sending the message to user B as the server come to know that User B is online
(Message disappeared from offline messages table ).
But User B is not going to receive that message.
connection.login(userName, userPwd, UiUtility.getMyPhoneNO());
PacketFilter filter = new PacketTypeFilter(org.jivesoftware.smack.packet.Message.class);
packetListener =new PacketListener() {
public void processPacket(Packet packet) {
Message message = (Message) packet;
if (message.getBody() != null) {
String fromName = StringUtils.parseBareAddress(message
.getFrom());
Log.i("XMPPClient", "Got text [" + message.getBody()
+ "] from [" + fromName + "]");
}
}
};
connection.addPacketListener(packetListener, filter);
Again after successful login im able to chat normally.But I wonder why those offline messages are missing ? .My PacketListener unable to catch those offline messages .Please Help me
Asmack is depreceated. Use Smack. An Open Source XMPP Client Library written in Java for JVMs and Android. Add the following lines to your gradle file:
compile 'org.igniterealtime.smack:smack-android:4.1.3'
compile 'org.igniterealtime.smack:smack-tcp:4.1.3'
compile 'org.igniterealtime.smack:smack-extensions:4.1.3'
The problem is easy to be solved.
Before making connection with the XMPP server just register providers using ProviderManager class provided by ASmack library.
If this can't solve ur problem visit ur local server and search for offline messages, and select the option ALWAYS STORE setting the storage limit to be 1000 kb. It is 100 kb by default.
Hope this works.
After lot struggle, I have resolved the issue. In your openfire admin page, go to "client settings" and reduce the idle time from 360sec (by default) to 1 sec(may be). Only then when you disconnected from Internet, it can detect that you are offline and preserve rest of the messages as OFFLINE.
#Override
public void onNetworkConnectionChanged(boolean isConnected) {
if(isConnected){
new Thread() {
public void run() {
try {
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder();
builder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
builder.setUsernameAndPassword("phone", "admin");
builder.setSendPresence(true);
builder.setServiceName(<Service name>);
builder.setHost(<Host name>);
builder.setResource("Test");
builder.setDebuggerEnabled(true);
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("Available");
connection = new XMPPTCPConnection(builder.build());
connection.connect();
connection.login();
Presence presence123 = new Presence(Presence.Type.available);
presence123.setStatus("Available");
try {
connection.sendStanza(presence123);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
StanzaFilter filter = new AndFilter(new StanzaTypeFilter(Message.class));
PacketListener myListener = new PacketListener()
{
public void processPacket(Stanza stanza)
{
retrieveMessage(stanza,userType);
}
};
connection.addPacketListener(myListener, filter);
try {
connection.sendStanza(presence);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
}
} catch (SmackException | XMPPException | IOException e) {
e.printStackTrace();
}
//return connection.isConnected();
}
}.start();
The above is working fine and able to retrieve the offline messages. The method "retrieveMessage(stanza,userType);" is used to process the incoming message and update the Adapter. Make sure to send the Presence as "Available" when you reconnect. Please let me know if there are still any issues.
Related
I am creating an instant messaging app in android using smack library and openfire as a server but i cannot implement the feature of the person with whom the current user is talking to. i.e. like when user read the message or when he starts typing.
Is there any way of achieving this using smack or other ?
For knowing which user is current you must implement your own in your logic. You must use Roster (contact list in xmpp servers) to get contacts of current user and save them in database or somewhere. Then create an activity to show contacts in a list. Each contact has a unique jid that can be distinguished from others with it. So with click on each contact, send it's object(include jid) to chat-activity. In chat-activity you must get previous messages from database or MAM(archived messages in server) and you can send a message to current contact(set contact jid as To).
To achieving delivery of message you must use this link. you can set request of it with this code:
Message message = … //make your stanza
DeliveryReceiptRequest.addTo(message); //add delivery request to message
connection.sendStanza(message); //send message
then you can be notified of delivery with this code:
private void setDelRecListener() {
DeliveryReceiptManager d = DeliveryReceiptManager.getInstanceFor(connection);
d.addReceiptReceivedListener(new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
Msg msg = F.getMsgBySid(receiptId);
if (msg == null)
return;
Boolean isUpdated = F.setMsgDelivered(msg);
Log.i("m/serv/UpdateDelivery", "for: " + receiptId + (isUpdated ? " Founded&Updated" : " NotFounded"));
if (isUpdated) {
BCTool.notifyPMDelivered(msg.id, msg.conv.frnd.getBareJid());
}
}
});
}
Keep in mind that every stanza has a sid(stanza id) and you must save each corresponding sid to message model in database when send is successful. This way you can detect which message delivery you got.
- For sending chat states like composing you can use this method:
public void sendChatState(String _jid, ChatState chatState) {
try {
Message msg = new Message();
msg.addExtension(new ChatStateExtension(chatState));
msg.setTo(JidCreate.bareFrom(_jid));
msg.setType(Message.Type.chat);
connection.sendStanza(msg);
Log.e("m/service", "ChatStateSent");
} catch (SmackException.NotConnectedException | InterruptedException | XmppStringprepException e) {
Log.e("m/service", "ChatState Not Sent: " + e.getMessage());
e.printStackTrace();
}
}
You must set a timer to prevent send composing in next 5Sec and reset timer when a character typed.
Consider reading this: ChatStateNotifications
I making a android chat app. Im use the api level 23, the Xmpp Smack lib version 4.1.8, and on server I use ejabberd, version 16.06.
I use this code to build a XMPP connection.
(TIMEOUT = 5000)
private void buildConnection() {
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder()
.setServiceName(mServiceName)
.setHost(mServiceName)
.setConnectTimeout(TIMEOUT)
.setResource("Smack")
.setUsernameAndPassword(mUsername, mPassword)
.setSendPresence(true)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
mConnection = new XMPPTCPConnection(builder.build());
mConnection.setPacketReplyTimeout(TIMEOUT);
chatManager = ChatManager.getInstanceFor(mConnection);
chatManager.addChatListener(this);
PingManager pingManager = PingManager.getInstanceFor(mConnection);
pingManager.setPingInterval(5);
pingManager.registerPingFailedListener(this);
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(mConnection);
reconnectionManager.enableAutomaticReconnection();
mConnection.addConnectionListener(this);
if (mConnection != null) {
DeliveryReceiptManager.getInstanceFor(mConnection).addReceiptReceivedListener(new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(String fromJid, String toJid, String receiptId, Stanza receipt) {
updateMessageStatusReceived(receipt);
Log.i(TAG, "Confirmation stanza Got: " + receipt);
}
});
}
}
(the updateMessageStatusReceived(receipt) method is only to refresh the view).
after that, I connect and authenticate.
Everthing is normal, but when the connection is down, I need to resend the failed messages when the connection is restored. I didn't find any solution or event in Smack to detected if a message fails. Sometimes the delay of confirmation server stanza is high, and my app assumes that message fails but don't, and the other side receive many times the same message.
I build a Message object and send using this code:
try {
Chat chat = chatManager.createChat(chatMessage.getJid());
chat.sendMessage(message);
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
When the connection is lost and I send message, no one exception is throw.
my question is: How I know the message realy fail, to try again?
Thanks, and sorry about the english.
I am facing the issue to retrieve offline message in android apps using smack api from XMPP Mongoose server. As per the code flow Try to retrive offline message when user become login in xmpp mongoose server before sending available presence to mongoose server.
Tried with two different way to retrieve offline message still not able to find working solution for the same. Both method which i tried those all things are explain below with detail.
Below Api we are using for the xmpp connection and all other extension :
// Smack (XMPP Client Library)
compile 'org.igniterealtime.smack:smack-android:4.1.6'
compile 'org.igniterealtime.smack:smack-tcp:4.1.6'
compile 'org.igniterealtime.smack:smack-im:4.1.6'
compile 'org.igniterealtime.smack:smack-android-extensions:4.1.6'
Tried retrive offline message Using offlineMessageManager
Below is code which I tried to retrieve offline message after login and before send available presence to server
try {
Boolean isFelxibleRetrievalSupport = offlineMessageManager.supportsFlexibleRetrieval();
Iterator i = (Iterator) offlineMessageManager.getMessages();
while (i.hasNext())
{
Message msg = i.next();
System.out.println("Got text [" + msg.getBody() + "] from [" + msg.getFrom() + "]");
} catch (XMPPException e)
{
System.out.println("Error Offline Message.");
e.printStackTrace();
}
catch (SmackException.NotConnectedException e)
{
System.out.println("Error Offline Message. No connection");
e.printStackTrace();
}
catch (SmackException.NoResponseException e)
{
System.out.println("Error Offline Message. No Reponse");
e.printStackTrace();
}
Issue case 1:
Below is exception detail which generate when above code execute
I got Exception when execute below line of code.
Iterator i = (Iterator) offlineMessageManager.getMessages();
Below is exception description which Generate when above line execute
org.jivesoftware.smack.XMPPException$XMPPErrorException: XMPPError: service-unavailable - cancel
Issue Case 2:
If checking is Flexible offline message supported from android code using smack from xmmp mongoose server so i got false value. Below is code which i used for testing.
Boolean isFelxibleRetrievalSupport = offlineMessageManager.supportsFlexibleRetrieval();
Issue Case 3:
When I try to retrieve supported features using below method using smack code like below.
ServiceDiscoveryManager manager = ServiceDiscoveryManager
.getInstanceFor(connection);
List AllFetures = manager.getFeatures();
Below is features list which i retrived:
http://jabber.org/protocol/bytestreams,
jabber:iq:privacy, urn:xmpp:ping,
http://jabber.org/protocol/commands,
jabber:iq:version,
jabber:iq:last,
http://jabber.org/protocol/xdata-validate,
http://jabber.org/protocol/xhtml-im,
vcard-temp,
http://jabber.org/protocol/chatstates,
urn:xmpp:receipts, urn:xmpp:time,
http://jabber.org/protocol/xdata-layout,
http://jabber.org/protocol/muc,
http://jabber.org/protocol/disco#items,
http://jabber.org/protocol/disco#info,
http://jabber.org/protocol/caps,
jabber:x:data
Tried to retreive offline message Using package listener from XMPP MongooseIM
below is code which i tried using package listener from smack api 4.1.6.
private static final StanzaFilter MESSAGE_PACKET_FILTER= new OrFilter(StanzaTypeFilter.MESSAGE);
configuration = XMPPTCPConnectionConfiguration.builder()
.setServiceName(SERVICE_NAME)
.setHost(KDevelopmentXMPPServer)
.setPort(PORT)
.setSendPresence(false)
.build();
// Create Connection object of xmpp connection with configured detail
connection = new XMPPTCPConnection(configuration);
connection.addAsyncStanzaListener(new StanzaListener() {
#Override
public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
Log.d("CheckPacket", "OfflineMEssage");
Message message = (Message) packet;
if (message != null) {
if (message.getBody() != null) {
Log.i("XMPPClient", "Got text [" + message.getBody()
+ "] from [" + message.getFrom() + "]");
}
}
}
}, MESSAGE_PACKET_FILTER);
connection.login(user, password);
Thanks In Advance, Please anybody help me for best working solution for my critical issue.
The issue is in trying to fetch offline messages before
sending the initial presence. XEP-0160 states:
When the recipient next sends non-negative available presence to the server, the server delivers the message to the resource that has sent that presence. [...]
MongooseIM works with accordance to this recommendation.
You already pointed out what is signaled by isFlexibleRetrievalSupport - the server does not support flexible offline message retrieval.
I know I am writing this too late, but if someone like me who is hunting for same query as in "how to save and get archive messages in android app" can refer this answer :
Note :
this is implemented in the lastest version
Requrirements :
lastest openfire as of now 4.1.4
install Archives plugin in openfire
MamManager mamManager = MamManager.getInstanceFor(connection);
boolean isSupported = mamManager.isSupportedByServer();
if (isSupported) {
MamManager.MamQueryResult mamQueryResult = mamManager.queryArchive(500);
List<Forwarded> forwardedMessages = mamQueryResult.forwardedMessages;
Forwarded d = forwardedMessages.get(0);
}
Please Refer : Documention for MamManager Class
I have finished developing my IM application on android (using xmpp & GCM), and I am using the gcm for buth UpPayload and DownPayloads..
and to notify the user that his partner is online/ofline I send messaage that my xmpp server "understand"
that tell the statuse.
protected void onStart() {
super.onStart();
if(!isOnlineSent)
{SendOnlineStatus("Online");
isOnlineSent=true;}
.
.
.
.}
and the SendOnlineStatus look like:
Intent OnlineMsg = new Intent();
OnlineMsg.putExtra("action", "com.Esmaeel.sodfarim.sodfa01.MESSAGE");
String nowtime = String.valueOf(EsTools.getCurrentTime());
OnlineMsg.putExtra(ConstantsGCM.TYPECLM, ConstantsGCM.ONST);
OnlineMsg.putExtra(ConstantsGCM.STATUS_on_of, Status);
OnlineMsg.putExtra(ConstantsGCM.TO_CLM, "-01");
OnlineMsg.putExtra(ConstantsGCM.FROMCLM, UUID);
OnlineMsg.putExtra(ConstantsGCM.MESSAGE_ID_CLM, regid + nowtime);
OnlineMsg.putExtra(ConstantsGCM.NAME_CLM, "Name");
final Bundle bndl = OnlineMsg.getExtras();
new AsyncTask() {
#Override
protected String doInBackground(Object[] objects) {
if (ggcm == null) {
ggcm = GoogleCloudMessaging.getInstance(context);
}
try {
ggcm.send(PRO_ID + ConstantsGCM.GCM_SERVER, bndl.getString(ConstantsGCM.MESSAGE_ID_CLM), bndl); //// GCM_SERVER="gcm.googleapis.com"
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}.execute(null, null, null);
the server checks the value of
payload.get(ConstantsGCM.TYPECLM);
if the type ONST the server reads the value payload.get(ConstantsGCM.STATUS_on_of);
the valid valuse of payload.get(ConstantsGCM.STATUS_on_of); is "online" OR "offline".
then the server update the user status and sends the new status to all the user's friends.
the same I do with Typing status but the last step I send just to the other side of the active chat.
but I get problems like "user apear online while he is offline, and some times apears typing when he is not.
any help or more effictive Ideas?
I don't know for the typing part, but for the status, maybe you should only send to the friends something like : "you should check the status of this user" then each friends phone will get the real status directly on the server. Hope it helps
I am currently developing android XMPP client to communicate with the Tigase server setup locally.Before starting development on Android I am writing a simple java code on PC to test connectivity with XMPP server.My XMPP domain is my pc name "mwbn43-1" and administrator username and passwords are admin and tigase respectively.
Following is the snippet of the code I am using
class Test {
public static void main(String args[])throws Exception
{
System.setProperty("smack.debugEnabled", "true");
XMPPConnection.DEBUG_ENABLED = true;
ConnectionConfiguration config = new ConnectionConfiguration("mwbn43-1", 5222);
config.setCompressionEnabled(true);
config.setSASLAuthenticationEnabled(true);
XMPPConnection con = new XMPPConnection(config);
// Connect to the server
con.connect();
con.login("admin", "tigase");
Chat chat = con.getChatManager().createChat("aaphadke#mwbn43-1",
new MessageListener() {
public void processMessage(Chat chat, Message message) {
// Print out any messages we get back to standard out.
System.out.println("Received message: " + message);
}
});
try {
chat.sendMessage("Hi!");
}
catch (XMPPException e) {
System.out.println("Error Delivering block");
}
String host = con.getHost();
String user = con.getUser();
String id = con.getConnectionID();
int port = con.getPort();
boolean i = false;
i = con.isConnected();
if (i)
System.out.println("Connected to host " + host + " via port " + port + " connection id is " + id);
System.out.println("User is " + user);
con.disconnect();
}
}
When I run this code I get following error
Exception in thread "main" Resource binding not offered by server:
at org.jivesoftware.smack.SASLAuthentication.bindResourceAndEstablishSession(SASLAuthenticatio n.java:416) at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:331)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
at Test.main(Test.java:26)
I found this articles on the same problem but no concrete solution
here
Could anyone please tell me the solution for this problem.I checked the XMPPConnection.java file in the Smack API and it looks the same as given in the link solution.
Thanks,
Ameya
I found the solution to the problem as given in here
These are the lines I should add before I connect to the server
ConnectionConfiguration config = new ConnectionConfiguration("mwbn43-1", 5222);
config.setSASLAuthenticationEnabled(false);
XMPPConnection xmpp = new XMPPConnection(config);
Thanks for all your help
I think this is a problem with library, a bug. It does not handle protocol correctly. Before the user is authenticated there is no point of sending resource bind, hence it is not advertised by the server. The client should not complain about it.