I was trying to fetch facebook friends and send message using asmack library over XMPP.I took reference from this site for facebook messaging.But after executing the code below i got exception.
public class MyActivity extends Activity {
public int state = 0;
private static final String TAG = "MyActivity";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
public void run() {
//XMPPConnection xmpp = new XMPPConnection("jabber.iitsp.com");
XMPPConnection xmpp = new XMPPConnection("chat.facebook.com");
try {
xmpp.connect();
// for other jabber accounts, truncate after the #
//xmpp.login("username", "password");
// for gtalk / gmail, include the #
xmpp.login("fb-username#chat.facebook.com", "your-fb-password");
} catch (XMPPException e) {
Log.v(TAG, "Failed to connect to " + xmpp.getHost());
e.printStackTrace();
}
ChatManager chatmanager = xmpp.getChatManager();
Chat newChat = chatmanager.createChat("friend#chat.facebook.com", new MessageListener() {
// THIS CODE NEVER GETS CALLED FOR SOME REASON
public void processMessage(Chat chat, Message message) {
try {
Log.v(TAG, "Got:" + message.getBody());
chat.sendMessage(message.getBody());
} catch (XMPPException e) {
Log.v(TAG, "Couldn't respond:" + e);
}
Log.v(TAG, message.toString());
}
});
// Send something to friend#chat.facebook.com
try {
newChat.sendMessage("my message");
} catch (XMPPException e) {
Log.v(TAG, "couldn't send:" + e.toString());
}
// Accept only messages from friend#chat.facebook.com
PacketFilter filter
= new AndFilter(new PacketTypeFilter(Message.class),
new FromContainsFilter("friend#chat.facebook.com"));
// Collect these messages
PacketCollector collector = xmpp.createPacketCollector(filter);
while(true) {
Packet packet = collector.nextResult();
if (packet instanceof Message) {
Message msg = (Message) packet;
// Process message
Log.v(TAG, "Got message:" + msg.getBody());
}
}
}
}).start();
//setContentView(this);
}}
I got following errors during execution of the code:-
1) java.security.KeyStoreException: java.security.NoSuchAlgorithmException: KeyStore jks implementation not found
2) SASL authentication failed using mechanism PLAIN:
Then my program crashed
java.lang.IllegalStateException: Not connected to server.
Any help would be appreciated.
Related
I am creating a chat application ,one to one chatting is working properly ,but when comes to multi user chat i am not able to listen their messages
I am using smack for implementing the XMPP protocol
Here is the code
Server configuration part is
public void serverCongig() throws XMPPException {
LOGGER.info(String.format("Initializing connection to server %1$s port
%2$d", server, port));
SmackConfiguration.setPacketReplyTimeout(packetReplyTimeout);
config = new ConnectionConfiguration(server,
port,PropertyReader.getPropertiesValue("server_domain"));
// config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
connection = new XMPPConnection(config);
try
{
connection.connect();
LOGGER.info("Connected: " + connection.isConnected()+" Service
name"+connection.getServiceName());
chatManager = connection.getChatManager();
messageListener = new MyMessageListener();
}
catch(Exception e)
{
callThread();
e.printStackTrace();
}
finally
{
callThread();
}
}
Message listening part is
class MyMessageListener implements MessageListener {
#Override
public void processMessage(Chat chat, Message message) {
try
{
String from = message.getTo();
String body = message.getBody();
String toUser="";
LOGGER.info(String.format("Received message '%1$s' from %2$s", body, from));
String[] user=from.split("#");
for(int i=0;i<user.length;i++)
toUser=user[0];
LOGGER.info("Receiver Phone number"+toUser);
SendMsgToWhatsapp create=new SendMsgToWhatsapp();
try {
if(!body.equalsIgnoreCase(null))
{
create.processWhatsappMessage(toUser, body);
}
} catch (Exception ex) {
callThread();
// Logger.getLogger(XmppManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
catch(Exception e)
{
e.printStackTrace();
callThread();
}
}
I had a similar question and that's what I found:
XEP-0313: Message Archive Management (https://xmpp.org/extensions/xep-0313.html) describes to work with the message archive.
In smack you can use it like that
MamManager mamManager = MamManager.getInstanceFor(connection);
MamManager.MamQueryArgs mamQueryArgs = MamManager.MamQueryArgs.builder()
.limitResultsToJid(jid)
.setResultPageSizeTo(10)
.queryLastPage()
.build();
MamManager.MamQuery mamQuery = mamManager.queryArchive(mamQueryArgs);
List<Message> messages = mamQuery.getMessages();
for (Message m : messages) {
System.out.println(m.getBody());
}
But when I tried to use it, I received problems with dependencies in maven, so I loaded smack jar manually from dailybuilds (https://download.igniterealtime.org/smack/dailybuilds/smack-SNAPSHOT-2020-07-21.zip) and the remaining dependencies added through maven
In my case it work.
https://download.igniterealtime.org/smack/docs/latest/javadoc/org/jivesoftware/smackx/mam/package-summary.html (smackx.mam javadoc)
I have limited Android Experience and had a very basic doubt. My scenario is as follows:
I currently have 2 applications, one being a QR Code Scanner and another which displays a QR Code. These will be running on multiple devices. The communication steps which take place are as follows:
Prior Setup:
There is a firebase database containing strings for QR Codes to be generated.
Device 2 reads the Code off the Firebase Database and displays it on the Screen (2nd App).
Device Communication:
Device 1 has the Scanner App and Device 2 has the QR Code displayed on Screen.
Device 1 now scans the QR Code from the Device 2 and verifies through some logic whether QR Code is valid or not.
If QR Code is valid, then the following takes place:
Device 1 calculates a new QR Code and places it on the Firebase Database.
The Device 2 should now move from displaying the QR Code to another activity which has the logic to Scan QR Codes of other Devices and verifies if they are correct.
Device 3 onwards must display a new QR Code which is on the Firebase Database which can now be scanned by Devices 1 and 2.
Note: The QR Code Updates on UI must keep happening until there is some sort of indication which makes the Device move to the QR Code Scanning stage.
Things which are working:
The 2 activities of the application (QR Code Display and QR Code Scanning) working independently.
QR Code Updates on UI whenever Firebase Database updated.
Things which are not working:
Moving from QR Code Display to Scanning once the QR Code is deemed valid.
Things I have tried:
Creating a Server Socket Implementation on the QR Code Display Application which is running as a Service called by my Main Activity. Client Socket Implementation (placed as a Service) is on the QR Code Scanner, which will send data to the Listening Server Socket once the QR Code is deemed valid. (Issue is that neither data is sent nor received).
Creating a Server Socket Implementation on the QR Code Display Application which is running as a Service called by my Main Activity. Client Socket Implementation (placed on UI Thread) is on the QR Code Scanner, which will send data to the Listening Server Socket once the QR Code is deemed valid.(Issue is that neither data is sent nor received)
I am very confused as to whether my approach is correct. Is there a better way to do it? Code for my service is as follows:
Device 2 - QR Code Display App:
Service
public class MyService extends Service {
private static final String TAG = "MyService";
private T_Client client;
#Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
if (client != null) {
try {
client.stopClient();
} catch (Exception e) {
Log.e(TAG, "Error on close: " + e);
}
}
super.onDestroy();
Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
client = new T_Client();
client.start();
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Display Server Implementation (Called T_Client)
public class T_Client extends Thread {
private static final String TAG = "T_Client";
private Socket sock = null;
private boolean running = false;
private ObjectInputStream in;
private ObjectOutputStream out;
private Object objIn;
public void send(String _msg) {
if (out != null) {
try {
out.writeObject(_msg);
out.flush();
Log.i("Send Method", "Outgoing : " + _msg.toString());
} catch (IOException ex) {
Log.e("Send Method", ex.toString());
}
}
}
public void stopClient() {
Log.v(TAG,"stopClient method run");
running = false;
}
#Override
public void run() {
running = true;
try {
ServerSocket sock1 = new ServerSocket(9999);
try {
Log.i(TAG, "C: Connected.");
while (running) {
sock = sock1.accept();
out = new ObjectOutputStream(sock.getOutputStream());
in = new ObjectInputStream(sock.getInputStream());
objIn = in.readObject();
Log.i("Object Read Class", objIn.getClass().toString());
Log.i("Object Read", objIn.toString());
/* Currently commented because startActivity not recognised
if (objIn != null) {
Intent dialogIntent = new Intent();
dialogIntent.setClass(this, MainActivity.class);
dialogIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(dialogIntent);
}
Atleast the data should get read here
*/
System.out.println("Object Read Class" + objIn.getClass().toString());
System.out.println("Object Read" + objIn.toString());
}
Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + objIn + "'");
} catch (Exception e) {
Log.e(TAG, "S: Error", e);
} finally {
out.close();
in.close();
sock.close();
Log.i(TAG, "Closing socket: " + sock);
}
} catch (Exception e) {
Log.e(TAG, "C: Error", e);
}
}
}
Intent intent=new Intent(getContext().getApplicationContext(),MyService.class);
getContext().startService(intent);
Scanner Application: (Written in Kotlin)
Scanner Client Implementation (Called T_Server)
internal class T_Server : Thread() {
private var sock: Socket? = null
private var running = false
private var out: ObjectOutputStream? = null
private val objIn: Any? = null
var blockchain_kotlin_copy = SecondActivity().blockchain_kotlin_copy
fun send(_msg: String) {
if (out != null) {
try {
out!!.writeObject(_msg)
out!!.flush()
Log.i("Send Method", "Outgoing : $_msg")
} catch (ex: IOException) {
Log.e("Send Method", ex.toString())
}
}
}
fun stopClient() {
Log.v(TAG, "stopClient method run")
running = false
}
override fun run() {
running = true
try {
val sock1 = ServerSocket(9999)
try {
Log.i(TAG, "C: Connected.")
while (running) {
sock = sock1.accept()
try {
out = ObjectOutputStream(sock!!.getOutputStream())
out!!.writeObject(blockchain_kotlin_copy)
out!!.flush()
out!!.reset()
Log.i("Send Method", "Outgoing : $blockchain_kotlin_copy")
println("Out is being sent")
println("$blockchain_kotlin_copy")
} catch (ex: IOException) {
Log.e("Send Method", ex.toString())
}
}
} catch (e: Exception) {
Log.e(TAG, "S: Error", e)
} finally {
out!!.close()
sock!!.close()
Log.i(TAG, "Closing socket: " + sock!!)
}
} catch (e: Exception) {
Log.e(TAG, "C: Error", e)
}
}
companion object {
private val TAG = "T_Server"
}
}
Service
public class MyService extends Service {
private static final String TAG = "MyService";
private T_Server client;
#Override
public void onDestroy() {
Log.v(TAG, "onDestroy");
if (client != null) {
try {
client.stopClient();
} catch (Exception e) {
Log.e(TAG, "Error on close: " + e);
}
}
super.onDestroy();
Toast.makeText(this, "Service stopped", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand");
client = new T_Server();
client.start();
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
Main Activity
val intent = Intent(this, MyService::class.java)
this.startService(intent)
It sounds like you might be interested in Firebase Device-to-Device notification. You might do as follows
Device X displays QR code
Some Device Y reads the QR code from Device X and if(verified) sendNotificationToDevice(X)
Device X moves to Scanner activity to read from some other Device Z.
Besides the link above, there are a number of YouTube tutorials and Medium blog posts on how to implement Device-to-Device notification.
I'm currently developing an email application with a background service used in conjunction with the JavaMail Idle functionality. The background service keeps the idle functionality working by issuing a check every 29 minutes (as the server being used (Exchange server)) can sometimes drop the connection after 30 minutes of being connected.
Whilst this works perfectly, if the Exchange server is offline, then the application will continue to attempt to reconnect to the IMAP folder indefinately. I have noticed spikes in data usage between the hours of 3AM & 6AM (a typical Exchange update time).
To avoid the increased data usage, I am looking to implement functionality where the app should attempt to reconnect to the IMAP folder three times and then display a warning to the user that the server is offline and a new connection attempt will be retried in 30 minutes.
In order to achieve this, how would I be able to detect if the Exchange server is actually offline/updating & would any exceptions be thrown, if the app cannot connect to the IMAP folder? As if an exception would be thrown, then I could save a local int variable and increment it by one every time the exception is thrown and then show the alert to the user on the third time.
My current code implementation can be seen below:
public void checkInboxEmail(final String host, final String user, final String password) {
Log.d(TAG, "checkEmail");
this.host = host;
this.user = user;
this.password = password;
new Thread(new Runnable() {
#Override
public void run() {
try {
Log.d(TAG, "checkEmail - run()");
long databaseRecords;
//create properties field
Properties properties = new Properties();
properties.put("mail.store.protocol", "imaps");
properties.put("mail.imaps.ssl.trust", "*");
properties.put("mail.debug", "true");
emailSession = Session.getInstance(properties, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, password);
}
});
IMAPStore imapStore = (IMAPStore) emailSession.getStore("imaps");
// imapStore.connect();
imapStore.connect(host, user, password);
if (imapStore.isConnected()) {
Log.d("MailPush", "Successfully connected to IMAP");
} else {
Log.d("MailPush", "Not connected to IMAP");
}
final IMAPFolder folder = (IMAPFolder) imapStore.getFolder("Inbox");
folder.open(IMAPFolder.READ_WRITE);
databaseRecords = dbManager.getReceivedEmailRecordsCount();
if (databaseRecords < folder.getMessageCount()) {
Log.d(TAG, "Receiving Mail...");
receiveMail(folder.getMessages());
} else {
Log.d(TAG, "Records match.");
}
Folder[] fdr = imapStore.getDefaultFolder().list();
for (Folder fd : fdr)
System.out.println(">> " + fd.getName());
folder.addMessageCountListener(new MessageCountListener() {
public void messagesAdded(MessageCountEvent e) {
System.out.println("Message Added Event Fired");
Log.d(TAG, "MESSAGE TYPE: " + e.getType());
//ADDED = 1 & REMOVED = 2
try {
Message[] messages = e.getMessages();
System.out.println("messages.length---" + messages.length);
for (Message message : messages) {
if (!message.getFlags().contains(Flags.Flag.SEEN)) {
//Message is new (hasn't been seen) > Message Details
System.out.println("---------------------------------");
System.out.println("Email Number " + (message.getMessageNumber()));
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
System.out.println("Text: " + message.getContent().toString());
String from = message.getFrom()[0].toString();
String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));
Log.d(TAG, "CC 1: " + cc);
Address[] recipients = message.getRecipients(Message.RecipientType.CC);
cc = InternetAddress.toString(recipients);
Log.d(TAG, "CC 2: " + cc);
//Check Encryption Details > Add SEEN Flag > Add to database
checkEncryption((MimeMessage) message, from, cc);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void messagesRemoved(MessageCountEvent e) {
System.out.println("Message Removed Event fired");
}
});
folder.addMessageChangedListener(new MessageChangedListener() {
public void messageChanged(MessageChangedEvent e) {
System.out.println("Message Changed Event fired");
}
});
startListening(folder);
//close the store and folder objects
// emailFolder.close(false);
// store.close();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private void startListening(IMAPFolder imapFolder) {
Log.d(TAG, "startListening");
// We need to create a new thread to keep alive the connection
Thread t = new Thread(
new KeepAliveRunnable(imapFolder), "IdleConnectionKeepAlive"
);
t.start();
while (!Thread.interrupted()) {
Log.d(TAG, "Starting IDLE");
try {
Log.d(TAG, "Setting IDLE");
imapFolder.idle();
} catch (FolderClosedException fex) {
//Server closes connection.
Log.d(TAG, "FolderClosedException. Server potentially dropped connection. Retrying connection...");
fex.printStackTrace();
if (!isServiceRunning(MyService.class)) {
Log.d(TAG, "Service isn't running. Starting service...");
//Start service
Intent intent = new Intent(context, MyService.class);
intent.putExtra("host", host);
intent.putExtra("email", user);
intent.putExtra("password", password);
context.startService(intent);
} else {
Log.d(TAG, "Service is already running. Checking email...");
checkInboxEmail(host, user, password);
}
} catch (MessagingException e) {
//Idle isn't supported by server.
Log.d(TAG, "Messaging exception during IDLE: ");
e.printStackTrace();
}
}
// Shutdown keep alive thread
if (t.isAlive()) {
Log.d(TAG, "Interrupting thread");
t.interrupt();
}
}
private static class KeepAliveRunnable implements Runnable {
private final String TAG = getClass().getName();
private static final long KEEP_ALIVE_FREQ = 60000 * 29; // 29 minutes (Exchange connection drops after 20-30 minutes)
private IMAPFolder folder;
KeepAliveRunnable(IMAPFolder folder) {
this.folder = folder;
}
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Thread.sleep(KEEP_ALIVE_FREQ);
// Perform a messageCount check just to keep alive the connection
Log.d(TAG, "Performing a messageCount check to keep the connection alive");
folder.getMessageCount();
} catch (InterruptedException e) {
// Ignore, just aborting the thread...
Log.d(TAG, "Interrupted...");
e.printStackTrace();
} catch (MessagingException e) {
// Shouldn't really happen...
Log.d(TAG, "Unexpected exception while keeping alive the IDLE connection");
e.printStackTrace();
}
}
}
}
private void receiveMail(Message[] messages) {
try {
System.out.println("messages.length---" + messages.length);
for (Message message : messages) {
if (!message.getFlags().contains(Flags.Flag.SEEN)) {
//Message is new (hasn't been seen) > Message Details
System.out.println("---------------------------------");
System.out.println("Email Number " + (message.getMessageNumber()));
System.out.println("Subject: " + message.getSubject());
System.out.println("From: " + message.getFrom()[0]);
System.out.println("Text: " + message.getContent().toString());
String from = message.getFrom()[0].toString();
String cc = InternetAddress.toString(message.getRecipients(Message.RecipientType.CC));
//Check Encryption Details > Add SEEN Flag > Add to database
checkEncryption((MimeMessage) message, from, cc);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
If the server is up but not accepting connections, the connect will fail immediately (with an exception). If the server is down, and you've set a connect timeout, the connect will fail after the timeout (with an exception).
To clarify #BillShannon's answer, if the server host is up but Exchange is not accepting connections, the connect will fail immediately with a ConnectException: connection refused. If the server host is down, the connect will fail after the timeout with a ConnectException: connect timeout (or possibly a SocketTimeoutException), regardless of whether you've set a connect timeout, as the platform always has one.
i'm newbie in nodejs and express.io , in android application i'm wrote this simple code to connect from android or java but iget connection error
app = require('express.io')()
app.http().io()
// Broadcast the new visitor event on ready route.
app.io.route('ready', function(req) {
req.io.broadcast('new visitor')
console.log('ready');
})
// Send client html.
app.get('/', function(req, res) {
//res.sendfile(__dirname + '/client.html')
req.io.broadcast('new visitor')
console.log('hello');
})
app.listen(7076)
this code maybe is correct, after opening http://192.168.1.5:7076 link in browser i get hello message, now with below code i'm try to connect but i get connection error:
private static final String SERVER_ADDRESS = "http://192.168.1.5:7076";
private Socket mSocket;
{
try {
mSocket = IO.socket(SERVER_ADDRESS);
} catch (URISyntaxException e) {
Log.e("Error URI", String.valueOf(e));
throw new RuntimeException(e);
}
}
public class ActivityHome extends FragmentActivity {
...
mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError);
mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError);
mSocket.on("new message", onNewMessage);
mSocket.on("user joined", onUserJoined);
mSocket.on("user left", onUserLeft);
mSocket.on("typing", onTyping);
mSocket.on("stop typing", onStopTyping);
mSocket.connect();
...
}
private Emitter.Listener onConnectError = new Emitter.Listener() {
#Override
public void call(Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(),
"CONNECT ERROR", Toast.LENGTH_LONG).show();
}
});
}
};
I am trying to develop a XMPP chat client for Android (using Java connected to C#/Unity). I have got the Java -> Unity/C# connection working perfectly. I have also downloaded Asmack and can generate a library and my of wrapper class for initilazing a connection to a OpenFire XMPP server. However, I cannot seem to get Presence sent or recieved. I can log in, register new user and populate their roster, send messages, but cannot send any presence.
The code auto registrate users who never have used the app before. It also uses a preset friend list, and auto populates the roster with these friends.
The code is as follow (sorry for all the debug lines, can't use breakpoints when using Unity):
public class ASmackWrapper
{
private XMPPConnection connection;
private String[] friends;
private static final String eventClass = "ASmackEventListener";
private static ASmackWrapper wrapper;
public static ASmackWrapper instance()
{
System.out.println("instancecreator of ASmackWrapper 1!");
if (wrapper == null)
wrapper = new ASmackWrapper();
return wrapper;
}
public ASmackWrapper()
{
System.out.println("constructor of ASmackWrapper");
}
public boolean tryToRegister(String user, String pass){
AccountManager acManager = connection.getAccountManager();
try {
Map<String, String> attributes = new HashMap<String,String>();
attributes.put("email", "MY email");
acManager.createAccount(user, pass,attributes);
} catch (XMPPException e) {
System.out.println("cant autoregister user "+ user +" ... with pass: "+pass+" on server. error:" + e.getLocalizedMessage());
if (e.getLocalizedMessage().contains("conflict"))
return false; // Wrong password, since there is already an account with that id!
return false;
}
return true;
}
public void setFriends(String[] _friends) {
friends = _friends;
}
public void start(String host, String user, String pass)
{
System.out.println("Java: openConenction host:"+host);
ConnectionConfiguration cc = new ConnectionConfiguration(host,5222);
//cc.setSendPresence(true);
this.connection = new XMPPConnection(cc);
Connection.DEBUG_ENABLED = true;
try {
this.connection.connect();
} catch (XMPPException e) {
System.out.println("Error connecting to server");
return;
}
if(!this.connection.isConnected()) {
System.out.println("Java: is not connected");
onError("Connection failed");
return;
}
boolean loginStatus = login(user, pass);
if (!loginStatus) {
onError("Login Failed");
return;
}
RosterListener rl = new RosterListener() {
public void entriesAdded(Collection<String> addresses) {}
public void entriesUpdated(Collection<String> addresses) {}
public void entriesDeleted(Collection<String> addresses) {}
public void presenceChanged(Presence presence) {
System.out.println("presence changed!" + presence.getFrom() + " "+presence.getStatus());
onPresence(presence);
}
};
if (connection.getRoster() != null) {
connection.getRoster().setSubscriptionMode(Roster.SubscriptionMode.accept_all);
System.out.println("7");
connection.getRoster().addRosterListener(rl);
}
onAuthenticate("");
System.out.println("10");
//Set presence to online!
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("Online, Programmatically!");
presence.setPriority(24);
presence.setMode(Presence.Mode.available);
connection.sendPacket(presence);
}
private void addFriends() throws Exception {
if (friends == null) {
System.out.println("No friends to add");
return;
}
System.out.println("Number of friends to add: "+friends.length);
for (int i = 0;i<friends.length;i++) {
System.out.println("Create user in roster: "+friends[i]);
connection.getRoster().createEntry("fb"+friends[i], "No name_",null);
}
}
private boolean login(String jid, String password) {
System.out.println("1");
boolean isLoggedIn=true;
try {
this.connection.login(jid, password);
} catch (XMPPException e) {
isLoggedIn=false;
}
System.out.println("2");
if(!isLoggedIn) {
boolean isRegistred = tryToRegister(jid,password);
if (isRegistred) {
connection.disconnect();
try {
connection.connect();
connection.login(jid, password);
} catch (XMPPException e) {
onError("Could not connect and login after registring");
return false;
}
} else {
return false;
}
}
try {
addFriends();
} catch (Exception e) {
onError("Could not add friends to roster");
}
ChatManager chatmanager = connection.getChatManager();
chatmanager.addChatListener(new ChatManagerListener()
{
public void chatCreated(final Chat chat, final boolean createdLocally)
{
System.out.println("OK Chat created!");
chat.addMessageListener(new MessageListener()
{
public void processMessage(Chat chat, Message message)
{
onMessage(chat, message);
}
});
}
});
return true;
}
public void sendMessage(String rec, String message) {
System.out.println("sendMessage(string,string) to host :"+connection.getHost());
Chat chat = connection.getChatManager().createChat(rec+"#"+connection.getHost(), new MessageListener() {
public void processMessage(Chat chat, Message message) {
// Print out any messages we get back to standard out.
System.out.println("Probably an error, since we got a instant reply on sent message. Received message body: " + message.getBody() + " from:"+message.getFrom() + " to:"+message.getTo());
}
});
try {
chat.sendMessage(message);
System.out.println("Message sent");
} catch (XMPPException e) {
System.out.println("Error sending message: "+e.toString());
e.printStackTrace();
}
}
public void logout () {
System.out.println("Login out...");
connection.disconnect();
}
public void getOnlineFriends() {
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for(RosterEntry rosterEntry: entries) {
String user = rosterEntry.getUser();
Presence presence = roster.getPresence(user);
System.out.println("Presence : "+presence);
System.out.println("Presence type: "+presence.getType());
System.out.println("Presence mode: "+presence.getMode());
}
//Set presence to online!
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("Online, Programmatically!");
presence.setPriority(24);
presence.setMode(Presence.Mode.available);
connection.sendPacket(presence);
}
private void onMessage(Chat chat, Message message) {
String m = ("Received message: " + (message != null ? message.getBody() : "NULL"));
System.out.println(m);
UnityPlayer.UnitySendMessage(eventClass, "Message", m);
}
private void onError(String message) {
UnityPlayer.UnitySendMessage(eventClass, "Error", message);
}
private void onAuthenticate(String message) {
UnityPlayer.UnitySendMessage(eventClass, "Authenticate", message);
}
private void onPresence(Presence presence) {
String user = presence.getFrom();
if (presence.getType() == Presence.Type.available)
UnityPlayer.UnitySendMessage(eventClass, "Online", user);
else
UnityPlayer.UnitySendMessage(eventClass, "Offline", user);
System.out.println("Java: Presence changed, from:" +presence.getFrom() + " type:"+presence.getType() + " toString:"+presence.toString());
}
}
The presence is checked in two ways, by setting a presence listener and by fetching the status after login. This SO page suggest waiting 5 sec before getting the precense: Unable to get presence of roster by using smack, openfire
I have tried that as well by calling getOnlineFriends from a button, more than 5 sec after login. The listener never gets called. It just fires once after login, once for each on the roster with a presence = null.
Edit: After turning on Debug mode on Asmack I see the following reply to my presence send message:
SENT <presence id="3sG7l-11"><status>Online, Programmatically!</status><priority>24</priority></presence>
RCV <presence id="6s7BX-5" to="787122012#xxx.tripnet.se/Smack" from="10000063946242" type="error">
<error code="404" type="cancel">
<remote-server-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error></presence>
The server log:
org.jivesoftware.openfire.nio.ConnectionHandler - Closing connection due to error while processing message:
<iq id="566-4" type="error" from="xxx.tripnet.se/f55aea72" to="xxx.tripnet.se">
<error /><error type="cancel" code="501">
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" /></error>
<ping xmlns="urn:xmpp:ping" /></iq>
java.lang.IllegalArgumentException: IQ must be of type 'set' or 'get'. Original IQ:
<iq id="566-4" type="error" from="xxx.tripnet.se/f55aea72" to="xxx.tripnet.se">
<error/><error type="cancel" code="501">
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error>
<ping xmlns="urn:xmpp:ping"/></iq>
at org.xmpp.packet.IQ.createResultIQ(IQ.java:384)
I have also tried to pass along setSendPresence = true to the connectionconfiguration passed in connect(), but no difference.
I have also tried to set the subscription mode manually in OpenFire server to "both" (from "none") on both users, but with no effect.
Got it working! It was probably due to that I did not use the correct format on my jid's in the roster list. The correct format had to be user#myserver.se, not just user.
Write a RosterListener and see if it works.
public void rosterOnlineStatus(){
Roster roster = connection.getRoster();
Presence status = new Presence(Type.available);
status.setStatus("Hello This is Phaneendra");
roster.addRosterListener(new RosterListener() {
#Override
public void presenceChanged(Presence presence) {
System.out.println(presence.getFrom()+ "is "+presence+" "+presence.getStatus());
presence.getStatus();
}
#Override
public void entriesUpdated(Collection<String> addresses) {}
#Override
public void entriesDeleted(Collection<String> addresses) {}
#Override
public void entriesAdded(Collection<String> addresses) {}
});
}
See if adding the RosterListener will work?