How to enable the XEP-0199 in Smack? - android

I'm using aSmack. My app listens a chatroom and reacts to the messages but it never send a message. The app doesn't receive more messages if the chatroom remains in silence for a while and then a new message is sent. I researched and I think that XEP-0199 is the solution here. I see that #Flow (the current Smack maintainer) implemented it and the issue related was closed.
I think that I need to use PingProvider but I really don't know how to connect this class with the Connection.
How can I enable the XEP-0199? How can I use PingProvider?
Connection code:
smack = SmackAndroid.init(getActivity().getApplicationContext());
connection = new XMPPConnection(App.getServer());
connection.addConnectionListener(new ConnectionListener() {
private final static String SMACK = "SMACK";
#Override
public void reconnectionSuccessful() {
Log.i(SMACK , "reconnectionSuccessful");
}
#Override
public void reconnectionFailed(Exception e) {
Log.i(SMACK, "reconnectionFailed", e);
}
#Override
public void reconnectingIn(int seconds) {
Log.i(SMACK, "reconnectingIn " + seconds);
}
#Override
public void connectionClosedOnError(Exception e) {
Log.i(SMACK, "connectionClosedOnError", e);
}
#Override
public void connectionClosed() {
Log.i(SMACK, "connectionClosed");
}
});
connection.connect();
connection.login(user, password);

I fix the problem implementing the ping response manually:
connection.addPacketListener(new PacketListener() {
#Override
public void processPacket(Packet packet) {
connection.sendPacket(new Pong((Ping) packet));
}
}, new PacketFilter() {
#Override
public boolean accept(Packet packet) {
return packet instanceof Ping;
}
});

To prevent user from disconnecting your session
PingManager pm = PingManager.getInstanceFor(MyApplication.connection) ;
pm.setPingInterval(5) ; // 5 sec
pm.pingMyServer() ;
pm.registerPingFailedListener(new PingFailedListener() {
#Override
public void pingFailed() {
Log.e(TAG , "pingFailed") ;
}
});

XEP 0199 is not a solution, Ping is used to check weather the server is up or not. actually you will send ping to the server.
Now as fas as your problem is concerned. Show me the message stanza that you are trying to send. and also check if the chat-room is public or private. you can not send a message to a private chat room.
Answer Updated:
Try using this code for detecting message recieve
PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
Network.connection.addPacketListener(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 + "]");
//recieve.setText(message.getBody());
/*messages.add(fromName + ":");
messages.add(message.getBody());*/
// Add the incoming message to the list view
item = new RowItem(R.drawable.billing, message.getBody());
adapter = new CustomListViewAdapter(getBaseContext(),
R.layout.list_item, rowItems);
rowItems.add(item);
//listView.setAdapter(adapter);
}
}
}, filter);

I called PingManager.getInstanceFor method to enable XEP-0199 support.

Related

Recycler view + MQTT sometimes not being redrawn after Data Set Changed

I have been struggling with what I believe is a screen repainting problem for a RecylerView when my underlying model is modified by another Thread. But have run out of ideas.
My application receives messages from a MQTT topic and displays it in a RecyclerView as a sort of "history" or "log" display.
This works fine as long as the MQTT session does not auto reconnect.
Once the MQTT session reconnects after a dropped connection, I still receive messages from the MQTT topic, the messages are still added to my model, I still raise the "Data changed" notification, I still invalidate the RecyclerView control, but the RecyclerView is no longer repainted to reveal the new message on screen.
If I manually force a refresh/repaint of the screen (e.g. scroll the recycler view, switch to another app and back again etc) then the RecyclerView is repainted and shows the "missing" messages.
My question is: what is it about the RecyclerView that seems to be causing it to not repaint when the underlying model is modified as a result of messages being received from an MQTT topic, but only if the MQTT session is dropped and reconnected?????
And obviously, what do I need to do to fix it?????
Update
I've tried adding the following method (which is activated by the onClick of a Floating button).
public void buttonClick (View v) {
mAdapter.add("Button Message");
Toast.makeText(getApplicationContext(),"Button message added", Toast.LENGTH_SHORT).show();
}
This method suffers from the same problem as messages received from the MQTT topic. If I click it before the MQTT auto-reconnect, the "Button Message" is added to my RecyclerView and displayed.
Once MQTT session is dropped and then auto reconnected, even this "buttonClick" method's "Button Message" is no longer displayed unless I force a refresh of the RecyclerList. FWIW, the "Toast" is always displayed (before and after the MQTT autoreconnect).
Could it be that I've stumbled upon some sort of wierd bug in RecyclerView???
FWIW 1, I've read many posts trying to get RecyclerView to work in relation to background thread updates of the underlying data model. Some suggest running the notification on the MainUI thread. I believe that this does make a difference. Previously it never displayed any of the messages received from the MQTT topic, now it does - but not if the connection is lost and reconnected.
FWIW 2, I know that the notifyDataSetChanged should be used as a last resort as it is least efficient. I have tried some of the other notify methods. These other notification methods produce the exact same problem as notifyDataSetChanged. At this point I am trying to keep it simple, so as to get it to work. Next I can focus on efficiency.
Here are the relevant code snippets.
Firstly, the MQTT callback which is invoked when a message is received:
#Override
public void messageArrived(final String topic, MqttMessage message) throws Exception {
final String msg = new String(message.getPayload());
if ("glennm/test/temp".equals(topic)) {
Log.i("RCVD", "Temperature: " + msg); // This code is shown to illustrate a control that
if (textViewTemperature != null) { // always seems to be redisplayed when a message is received
textViewTemperature.setText(msg + "°"); // even if the connection is lost and reconnected
textViewTemperature.invalidate();
temperatureHistory.add(msg);
temperatureHistory.dump("TEMP");
} else {
Log.e("NULL", "textView temperature control is null");
}
} else if ("glennm/test/humid".equals(topic)) {
// Code that updates the humidity text view omitted for brevity (as it is basically the same as the temperature code above.
} else { /***** This is the problem area - other messages logged to the Recycler view ****/
String wrk = topic;
if (topic != null && topic.toLowerCase().startsWith("glennm/test")) {
wrk = topic.substring(12);
}
final String topicToShow = wrk;
textViewOtherTopic.setText(topicToShow);
textViewOtherMessage.setText(msg);
// mAdapter.add(topicToShow + ": " + msg);
// The notify that the add method calls ***MUST*** be run on the main UI thread.
// Failure to do so means that the call will sometimes be ignored and the
// Recycler view is not updated to show the new incoming value.
// https://stackoverflow.com/questions/36467236/notifydatasetchanged-recyclerview-is-it-an-asynchronous-call/36512407#36512407
// This seems to help, but we still seem to have the same behaviour if the MQTT connection resets.
runOnUiThread(new Runnable() {
// recyclerView.post(new Runnable() {
#Override
public void run() {
mAdapter.add(topicToShow + ": " + msg);
recyclerView.invalidate();
}
});
Log.i("RCVD", "Other Topic: " + topic + ", message: " + msg);
}
}
}
Secondly, the code that is invoked to add the message to the underlying data model (and notify the UI to repaint it).
public void add(String msg) {
Log.d("HISTORY", "Adding message: " + msg);
messageList.add(msg);
while (messageList.size() > MAX_HISTORY) {
messageList.remove(0);
}
Log.d("HISTORY", "Notifying data set changed");
_parent.runOnUiThread(new Runnable () {
#Override
public void run() {
notifyDataSetChanged();
}
});
Log.d("HISTORY", "Notifying data set changed - complete");
}
Finally, here are three screen snapshots which try to illustrate the problem. In the first, messages have been received from the MQTT topic and are displayed both in the journal and the "current message" field (textViewOtherTopic and textViewOtherMessage controls) located below the humidity.
What happens between the first and second screen shot is that the MQTT service lost its connection and auto-reconnected. After that, the received message is only displayed in the "current message" view and not the "message log" recycler view (despite being added to the model).
Only when the Recycler View is forced to be repainted by an external (manual) user action (e.g. scrolling) does the missing message(s) show up.
Here is an example of a command using the mosquitto mqtt client that is used to post a message to the app:
mosquitto_pub -h test.mosquitto.org -t "glennm/test/comment" -q 1 -m "It's a new day, but still cold! 3"
Following is the full code for the two classes (including many of the commented out attempts I've made)...
The Main activity:
package com.gtajb.tempmonitorapp;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.DisconnectedBufferOptions;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.util.ArrayList;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
private MqttAndroidClient mqttAndroidClient;
private String serverUri = "tcp://test.mosquitto.org:1883";
public static final String clientId = UUID.randomUUID().toString();
public final String subscriptionTopic = "glennm/test/#";
public final String publishTopic = "glennm/test/tome";
public final String publishMessage = "Hello from Android test client";
private TextView textViewTemperature;
private TextView textViewHumidity;
private TextView textViewOtherTopic;
private TextView textViewOtherMessage;
private MessageCallBack messageCallBack = new MessageCallBack();
private RecyclerView recyclerView;
private MessageHistory mAdapter;
private RecyclerView.LayoutManager layoutManager;
private ReadingsHistory temperatureHistory = new ReadingsHistory();
private ReadingsHistory humidityHistory = new ReadingsHistory();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("INFO", "Createing the mqtt client with client ID: " + clientId);
mqttAndroidClient = new MqttAndroidClient(getApplicationContext(), serverUri, clientId);
mqttAndroidClient.setCallback(new MqttClientCallback());
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
mqttConnectOptions.setAutomaticReconnect(true);
mqttConnectOptions.setCleanSession(false);
textViewTemperature = findViewById(R.id.temperatureValueLabel);
textViewTemperature.setText("Temp goes here");
textViewHumidity = findViewById(R.id.humidtyValueLabel);
textViewHumidity.setText("Humid goes here");
textViewOtherTopic = findViewById(R.id.otherTopicValueLabel);
textViewOtherMessage = findViewById(R.id.otherMessageValueLabel);
textViewOtherTopic.setText(".");
textViewOtherMessage.setText(".");
recyclerView = findViewById(R.id.historyPanel);
mAdapter = new MessageHistory(new ArrayList<String>(), this, recyclerView);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(mAdapter);
mAdapter.add("A test message");
messageCallBack = new MessageCallBack();
try {
mqttAndroidClient.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
mqttAndroidClient.setBufferOpts(disconnectedBufferOptions);
//subscribeToTopic();
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.e("CONNECT", "Failed to connect to " + serverUri);
Log.e("CONNECT", exception.getMessage());
}
});
} catch (MqttException e) {
Log.e("CONNECT", "Exception connecting to " + serverUri);
Log.e("CONNECT", e.getMessage());
Log.e("CONNECT", Log.getStackTraceString(e));
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.i("CONN", "Closing MQTT connection");
mqttAndroidClient.close();
}
public class MqttClientCallback implements MqttCallbackExtended {
#Override
public void connectComplete(boolean reconnect, String serverURI) {
if (reconnect) {
Log.i("CONN", "Reconnected to: " + serverURI);
subscribeToTopic();
} else {
Log.i("CONN", "Connected to: " + serverURI);
subscribeToTopic();
}
}
#Override
public void connectionLost(Throwable cause) {
Log.i("CONN", "Connection lost");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i("MSG", topic + " - " + new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.i("PUB", "Delivery complete");
}
}
public void subscribeToTopic() {
try {
Log.i("TOPIC", "Subscribing to: " + subscriptionTopic);
// mqttAndroidClient.subscribe(subscriptionTopic, 0, null, new IMqttActionListener() {
// #Override
// public void onSuccess(IMqttToken asyncActionToken) {
// Log.i("SUBS", "Subscription to " + subscriptionTopic + " on " + serverUri + " successful");
// }
//
// #Override
// public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// Log.i("SUBS", "Subscription to " + subscriptionTopic + " on " + serverUri + " FAILED");
// }
// });
mqttAndroidClient.subscribe(subscriptionTopic, 0, messageCallBack);
} catch (MqttException e) {
Log.e("SUBS", "Failed to subscribe to topic: " + subscriptionTopic + " on " + serverUri);
Log.e("SUBS", e.getMessage());
}
}
public void setTemperatureValue(String val) {
textViewTemperature.setText(val);
}
public void setHumidityValue(String val) {
textViewHumidity.setText(val);
}
public class MessageCallBack implements IMqttMessageListener , IMqttActionListener {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i("MQTT", "Successful operation " + asyncActionToken.toString());
textViewTemperature.setText("Subscribed");
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.i("MQTT", "Un Successful operation + " + asyncActionToken.toString());
textViewTemperature.setText("Not Subscribed");
}
#Override
public void messageArrived(final String topic, MqttMessage message) throws Exception {
final String msg = new String(message.getPayload());
if ("glennm/test/temp".equals(topic)) {
Log.i("RCVD", "Temperature: " + msg);
if (textViewTemperature != null) {
textViewTemperature.setText(msg + "°");
textViewTemperature.invalidate();
temperatureHistory.add(msg);
temperatureHistory.dump("TEMP");
} else {
Log.e("NULL", "textView temperature control is null");
}
} else if ("glennm/test/humid".equals(topic)) {
Log.i("RCVD", "Humidity: " + msg);
textViewHumidity.setText(msg + "%");
textViewHumidity.invalidate();
humidityHistory.add(msg);
humidityHistory.dump("HUMID");
} else {
String wrk = topic;
if (topic != null && topic.toLowerCase().startsWith("glennm/test")) {
wrk = topic.substring(12);
}
final String topicToShow = wrk;
textViewOtherTopic.setText(topicToShow);
textViewOtherMessage.setText(msg);
// mAdapter.add(topicToShow + ": " + msg);
// The notify that the add method calls ***MUST*** be run on the main UI thread.
// Failure to do so means that the call will sometimes be ignored and the
// Recycler view is not updated to show the new incoming value.
// https://stackoverflow.com/questions/36467236/notifydatasetchanged-recyclerview-is-it-an-asynchronous-call/36512407#36512407
// This seems to help, but we still seem to have the same behaviour.
runOnUiThread(new Runnable() {
// recyclerView.post(new Runnable() {
#Override
public void run() {
mAdapter.add(topicToShow + ": " + msg);
// recyclerView.invalidate();
}
});
Log.i("RCVD", "Other Topic: " + topic + ", message: " + msg);
// Context context = getApplicationContext();
// Toast msgPopup = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
// msgPopup.show();
}
}
}
}
The Message History class:
package com.gtajb.tempmonitorapp;
import android.app.Activity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class MessageHistory extends RecyclerView.Adapter<MessageHistory.Callback> {
private ArrayList<String> messageList = new ArrayList();
public static final int MAX_HISTORY = 100;
private Activity _parent;
private RecyclerView rv;
public class Callback extends RecyclerView.ViewHolder {
TextView mTextView;
Callback(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.row_text);
}
}
public MessageHistory(ArrayList<String> messageList, Activity parent, RecyclerView rv) {
super();
this.messageList = messageList;
this._parent = parent;
this.rv = rv;
add("Test Message 1");
add("Test Message 2");
}
#NonNull
#Override
public Callback onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_row, parent, false);
return new Callback(v);
}
#Override
public void onBindViewHolder(#NonNull Callback holder, int position) {
Log.d("HISTORY", "Setting " + position + ": " + messageList.get(position));
holder.mTextView.setText(messageList.get(position));
}
#Override
public int getItemCount() {
Log.d("HISTORY", "Message Count: " + messageList.size());
return messageList.size();
}
/**
* Add a message to the message log.
* #param msg the message to add.
*/
public void add(String msg) {
Log.d("HISTORY", "Adding message: " + msg);
messageList.add(msg);
while (messageList.size() > MAX_HISTORY) {
messageList.remove(0);
}
// getItemCount();
Log.d("HISTORY", "Notifying data set changed");
_parent.runOnUiThread(new Runnable () {
#Override
public void run() {
notifyDataSetChanged();
}
});
//this.notifyDataSetChanged();
Log.d("HISTORY", "Notifying data set changed - complete");
// rv.invalidate();
// rv.refreshDrawableState();
// this.notifyItemInserted(messageList.size());
// final RecyclerView.Adapter adapter = this;
// _parent.runOnUiThread(new Runnable() {
// #Override
// public void run() {
// adapter.notifyDataSetChanged();
// }
// });
}
}

Receiving Xmpp message, Attribute missing

I am developing small chat application using xmpp and ASMACK android-8-4.0.6 .On sending message, server sends me reply to acknowledge that message has successfully reached the server. and reply looks like as follows
<message to="abc#ofsrv1"><a xmlns="urn:xmpp:sm:3" h="6vO1d-7"/></message>
where attribute 'h' inside element contains packet id of sent message. I am sending message as follows
public void sendMessage(String to, String messageData)
{
try
{
Message msg = new Message(to, Message.Type.chat);
addMessageToLocalDb(to, messageData, msg.getPacketID());
msg.setBody(messageData);
DeliveryReceiptManager.addDeliveryReceiptRequest(msg);
xmppConnection.sendPacket(msg);
} catch (Exception e)
{
}
}
I have attach packet listener in which i am receiving server's reply but it receives in the form as follow
<message to='sender#ofsrv1'><a xmlns='urn:xmpp:sm:3'></a></message>
where 'h' attribute in element is clearly missing. Interesting part is some where in my log cat, under "SMACK" tag i received perfect reply along with h attribute just as follows
<message to="sender#ofsrv1"><a xmlns="urn:xmpp:sm:3" h="6vO1d-7"/></message>
so servers reply is successfully reaching to android client but some how attached packet listener is not receiving it . code for attaching packet listener is
public void configureConnection()
{
try
{
//PacketFilter filter1 = new IQTypeFilter(IQ.Type.RESULT);
PacketFilter filter = new PacketFilter()
{
#Override
public boolean accept(Packet packet)
{
return true;
}
};
XmppPacketListener xmppPacketListener = new XmppPacketListener(this, xmppConnection);
xmppConnection.addPacketListener(xmppPacketListener, filter);
//Registering Delivery receipt Listener
deliveryReceiptManager = DeliveryReceiptManager.getInstanceFor(xmppConnection);
XmppReceiptReceivedListener receiptReceivedListener = new XmppReceiptReceivedListener();
deliveryReceiptManager.addReceiptReceivedListener(receiptReceivedListener);
//Enabling carbons
CarbonManager carbonManager = CarbonManager.getInstanceFor(xmppConnection);
if (carbonManager.isSupportedByServer())
{
carbonManager.sendCarbonsEnabled(true);
}
} catch (Exception e)
{
CustomLogger.showLog("Xmpp", "Error in configuring xmpp connection" + e.toString());
}
}
public class XmppPacketListener implements PacketListener
{
private XMPPConnection mXmppConnection;
private Context mContext;
public XmppPacketListener(Context context, XMPPConnection xmppConnection)
{
CustomLogger.showLog(TAG, "Packet listener init");
this.mContext = context;
this.mXmppConnection = xmppConnection;
}
#Override
public void processPacket(Packet packet)
{
try
{
CustomLogger.showLog("Message", "Received packet" + packet);
} catch (Exception e)
{
}
}
}
Can any one help me to figure out what exactly i am missing in receiving packets
any help is greatly appreciated

Delivery receipt requests not working for XMPP Android (aSmack)

I'm using OpenFire with aSmack.
I can't seem to get DeliveryReceipts working.
I do the following when I create a connection:
//create connection
connection.login(username, password);
DeliveryReceiptManager.getInstanceFor(connection).enableAutoReceipts();
DeliveryReceiptManager.getInstanceFor(connection).addReceiptReceivedListener(new ReceiptReceivedListener()
{
#Override
public void onReceiptReceived(String arg0, String arg1, String arg2)
{
Log.v("app", arg0 + ", " + arg1 + ", " + arg2);
}
});
I'm sending a message to another user using:
//send chat
Message msg = new Message(id, Message.Type.chat);
msg.setBody(chat);
DeliveryReceiptManager.addDeliveryReceiptRequest(msg);
connection.sendPacket(msg);
The above does not work although the message gets sent with the ReceiptRequest. The listener does not get fired at the sender's end although the receiver receives the message. (I confirmed it through debugging that a DeliveryReceiptRequest does indeed get attached to the message that is sent).
I've also tried manually sending back the Receipt by using the following in my PacketListener with (MessageTypeFilter(Message.Type.chat)):
Packet received = new Message();
received.addExtension(new DeliveryReceipt(packet.getPacketID()));
received.setTo(packet.getFrom());
getConnection().sendPacket(received);
Still, the client at the receiving end receives the message alright but the listener does not get fired in the sender's system. Anything I'm missing?
Add these lines before you set up your connection and Auto Receipts will work with ReceiptReceivedListener. Seems like the DeliveryReceipt extensions aren't registered by default.
ProviderManager.getInstance().addExtensionProvider(DeliveryReceipt.ELEMENT, DeliveryReceipt.NAMESPACE, new DeliveryReceipt.Provider());
ProviderManager.getInstance().addExtensionProvider(DeliveryReceiptRequest.ELEMENT, new DeliveryReceiptRequest().getNamespace(), new DeliveryReceiptRequest.Provider());
Hi the above said answer given me NPE, so I used following code to get message notifications which was working perfectly for me:
Don't forget to add this ProviderManager
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider("x", "jabber:x:event",new MessageEventProvider());
MessageEventManager messageEventManager = new MessageEventManager(connection);
messageEventManager.addMessageEventNotificationListener(m_messageEventNotificationListener);
messageEventManager.addMessageEventRequestListener(m_DefaultMessageEventRequestListener);
/*
* Notifies when message events happend
*
*/
MessageEventNotificationListener m_messageEventNotificationListener = new MessageEventNotificationListener() {
#Override
public void deliveredNotification(String fromJID, String messageID) {
final String _messageID =messageID;
System.out.println("deliveredNotification");
UiUtility.printMe("Message("+messageID+") Was Delivered to "+fromJID);
//WRITE YOUR CUSTOM METHOD WHEN MSG DELIVERED NOTFICATIONN RECIEVED.
}
#Override
public void displayedNotification(String string, String string1) {
}
#Override
public void composingNotification(String string, String string1) {
}
#Override
public void offlineNotification(String string, String string1) {
}
#Override
public void cancelledNotification(String string, String string1) {
}
};
/*
* Send a request when message events occured
*/
DefaultMessageEventRequestListener m_DefaultMessageEventRequestListener = new DefaultMessageEventRequestListener() {
#Override
public void deliveredNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.deliveredNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void displayedNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.displayedNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void offlineNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.offlineNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
#Override
public void composingNotificationRequested(String from, String packetID, MessageEventManager messageEventManager) {
super.composingNotificationRequested(from, packetID, messageEventManager); //To change body of generated methods, choose Tools | Templates.
}
};
It's a bit late but this will help someone, take note of
receiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
Check below code:
DeliveryReceiptManager receiptManager = DeliveryReceiptManager.getInstanceFor(connection);
//automatically enable delivery receipts to every message
receiptManager.autoAddDeliveryReceiptRequests();
receiptManager.setAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.always);
receiptManager.addReceiptReceivedListener(new ReceiptReceivedListener() {
#Override
public void onReceiptReceived(Jid fromJid, Jid toJid, String receiptId, Stanza receipt) {
//handle delivery receipts here
}
});

Android - Autobahn web socket communication

I am working on Web socket communication with Autobahn library.
The problem I have is after connecting server, then message should be sent without connection again. But the message is sent with different connection that it connects to server every single time to send a message.
public class WebSocket_Connector extends Activity{
private static final String TAG = "ECHOCLIENT";
private static final String TAG1 = "My app";
public final WebSocketConnection mConnection = new WebSocketConnection();
private String tmpString = "";
public void connect(final String wsuri) {
Log.d(TAG, "Connecting to: " + wsuri);
try {
mConnection.connect(wsuri, new WebSocketHandler() {
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri );
Log.d(TAG, "Connection successful!\n");
mConnection.sendTextMessage(tmpString);
tmpString = "";
}
#Override
public void onTextMessage(String payload) {
Log.d(TAG, "Got echo: " + payload);
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection closed.");
}
});
} catch (WebSocketException e) {
Log.d(TAG, e.toString());
}
}
public void sendMessage(String message) {
if (mConnection.isConnected()) {
Log.d(TAG1, "Messeage is sent : " + message);
mConnection.sendTextMessage(message);
}
else {
tmpString = message;
connect("ws://192.168.3.100:7681");
}
}
}
This is the code I have, and...When you see "sendMessage" method, it always goes to 'else' not, if loop. Any suggestion 'experts' please..?
i don't know the package name you are dealing with for websocket. So first it has to be provided to get reliable answer to your question. But let say if it is something similar to :
https://code.google.com/p/weberknecht/source/browse/trunk/src/main/de/roderick/weberknecht/WebSocketConnection.java?r=2
note: i have not seen there isConnected() method but assume that it is added somewhere else.
you can see from source that onOpen() (line 88) is called before connected = true; on line (91). if this member var will be used as result of isConnected() then your code always will follow "else" part of the condition.
i would advice to dig into websocket api and its usage pattern further.

Networking and Threads in Android Apps

I know that i must use threads to use internet in Android application, but i don't know how to write it.
I have one class call "JabberSmackAPI" - on this class i have Login,send and receive functions via XMPP.
And i have one button on my app, when i press the button it should login to googleTalk account.
This works well on Java project ( i can login and send messages) but not on Android app project.
i receive this error: "android.os.NetworkOnMainThreadException".
My class is:
public class JabberSmackAPI
{
XMPPConnection connection;
public void login(String userName, String password) throws XMPPException
{
ConnectionConfiguration config = new ConnectionConfiguration("talk.google.com",5222,"gmail.com");
connection = new XMPPConnection(config);
connection.connect();
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
connection.login("email", "password");
}
public void sendMessage(String message, String to) throws XMPPException
{
Message msg = new Message(to, Message.Type.chat);
msg.setBody(message);
connection.sendPacket(msg);
listeningForMessages();
}
public void disconnect()
{
connection.disconnect();
}
public void listeningForMessages() {
PacketFilter filter = new AndFilter(new PacketTypeFilter(Message.class));
PacketCollector collector = connection.createPacketCollector(filter);
while (true) {
Packet packet = collector.nextResult();
if (packet instanceof Message) {
Message message = (Message) packet;
if (message != null && message.getBody() != null)
System.out.println("Received message from "
+ packet.getFrom() + " : "
+ (message != null ? message.getBody() : "NULL"));
}
}
}
My app code is:
public class MainActivity extends Activity implements OnClickListener {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn1=(Button)findViewById(R.id.button1);
btn1.setOnClickListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.button1)
{
try{
Toast.makeText(this, "T", Toast.LENGTH_LONG).show();
JabberSmackAPI c = new JabberSmackAPI();
c.login("username", "password");
}
catch(Exception e)
{
Log.e("Error","Error in code:"+e.toString());
e.printStackTrace();
}
}
}
}
The main application thread should only be used for interface-related work. You need to use multithreading, since networking is not allowed at all on the main thread of Android applications. Since your app requires a persistent data connection, AsyncTasks won't work either, since they are single-serving - fire, get result and close connection.
android.os.NetworkOnMainThreadException
Means exactly what it says - don't do network operations on the main/ui thread

Categories

Resources