From 0d80d88736926d06e97f22f9ecc63d4fb696751c Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 4 Feb 2014 15:09:50 +0100 Subject: [PATCH] reworked account managment. now status display actually works --- res/layout/account_row.xml | 6 +- src/de/gultsch/chat/entities/Account.java | 21 ++- .../chat/services/XmppConnectionService.java | 162 ++++++++++-------- .../chat/ui/ManageAccountActivity.java | 108 +++++++----- .../chat/ui/OnAccountListChangedListener.java | 5 + src/de/gultsch/chat/xml/TagWriter.java | 53 ++++-- src/de/gultsch/chat/xmpp/OnStatusChanged.java | 7 + src/de/gultsch/chat/xmpp/XmppConnection.java | 85 ++++++--- 8 files changed, 287 insertions(+), 160 deletions(-) create mode 100644 src/de/gultsch/chat/ui/OnAccountListChangedListener.java create mode 100644 src/de/gultsch/chat/xmpp/OnStatusChanged.java diff --git a/res/layout/account_row.xml b/res/layout/account_row.xml index c10099dd4..92e179f8a 100644 --- a/res/layout/account_row.xml +++ b/res/layout/account_row.xml @@ -35,16 +35,16 @@ android:layout_height="wrap_content" android:text="Status: " android:textStyle="bold" - android:textSize="14sp" /> + android:textSize="16sp" /> + android:textSize="16sp"/> diff --git a/src/de/gultsch/chat/entities/Account.java b/src/de/gultsch/chat/entities/Account.java index 79712b155..3dfb298ac 100644 --- a/src/de/gultsch/chat/entities/Account.java +++ b/src/de/gultsch/chat/entities/Account.java @@ -18,11 +18,20 @@ public class Account extends AbstractEntity{ public static final int OPTION_USETLS = 0; + public static final int STATUS_OFFLINE = 0; + public static final int STATUS_ONLINE = 1; + public static final int STATUS_UNAUTHORIZED = 2; + public static final int STATUS_NOINTERNET = 3; + public static final int STATUS_TLS_ERROR = 4; + public static final int STATUS_SERVER_NOT_FOUND = 5; + protected String username; protected String server; protected String password; protected int options; protected String rosterVersion; + protected String resource; + protected int status = 0; protected boolean online = false; @@ -70,8 +79,16 @@ public class Account extends AbstractEntity{ this.password = password; } - public boolean isOnline() { - return online; + public void setStatus(int status) { + this.status = status; + } + + public int getStatus() { + return this.status; + } + + public void setResource(String resource) { + this.resource = resource; } public String getJid() { diff --git a/src/de/gultsch/chat/services/XmppConnectionService.java b/src/de/gultsch/chat/services/XmppConnectionService.java index fee2aafe2..fbbaca5c0 100644 --- a/src/de/gultsch/chat/services/XmppConnectionService.java +++ b/src/de/gultsch/chat/services/XmppConnectionService.java @@ -1,6 +1,5 @@ package de.gultsch.chat.services; -import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -10,7 +9,7 @@ import de.gultsch.chat.entities.Contact; import de.gultsch.chat.entities.Conversation; import de.gultsch.chat.entities.Message; import de.gultsch.chat.persistance.DatabaseBackend; -import de.gultsch.chat.ui.ConversationActivity; +import de.gultsch.chat.ui.OnAccountListChangedListener; import de.gultsch.chat.ui.OnConversationListChangedListener; import de.gultsch.chat.ui.OnRosterFetchedListener; import de.gultsch.chat.utils.UIHelper; @@ -19,20 +18,15 @@ import de.gultsch.chat.xmpp.IqPacket; import de.gultsch.chat.xmpp.MessagePacket; import de.gultsch.chat.xmpp.OnIqPacketReceived; import de.gultsch.chat.xmpp.OnMessagePacketReceived; +import de.gultsch.chat.xmpp.OnStatusChanged; import de.gultsch.chat.xmpp.XmppConnection; -import android.R; -import android.R.dimen; import android.app.NotificationManager; -import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import android.os.Binder; import android.os.IBinder; import android.os.PowerManager; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.TaskStackBuilder; import android.util.Log; public class XmppConnectionService extends Service { @@ -48,6 +42,7 @@ public class XmppConnectionService extends Service { private Hashtable connections = new Hashtable(); private OnConversationListChangedListener convChangedListener = null; + private OnAccountListChangedListener accountChangedListener = null; private final IBinder mBinder = new XmppConnectionBinder(); private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() { @@ -79,6 +74,16 @@ public class XmppConnectionService extends Service { } } }; + private OnStatusChanged statusListener = new OnStatusChanged() { + + @Override + public void onStatusChanged(Account account) { + Log.d(LOGTAG,account.getJid()+" changed status to "+account.getStatus()); + if (accountChangedListener != null) { + accountChangedListener.onAccountListChangedListener(); + } + } + }; public class XmppConnectionBinder extends Binder { public XmppConnectionService getService() { @@ -88,15 +93,10 @@ public class XmppConnectionService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); for (Account account : accounts) { if (!connections.containsKey(account)) { - XmppConnection connection = new XmppConnection(account, pm); - connection - .setOnMessagePacketReceivedListener(this.messageListener); - Thread thread = new Thread(connection); - thread.start(); - this.connections.put(account, connection); + + this.connections.put(account, this.createConnection(account)); } } return START_STICKY; @@ -107,6 +107,17 @@ public class XmppConnectionService extends Service { databaseBackend = DatabaseBackend.getInstance(getApplicationContext()); this.accounts = databaseBackend.getAccounts(); } + + public XmppConnection createConnection(Account account) { + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + XmppConnection connection = new XmppConnection(account, pm); + connection + .setOnMessagePacketReceivedListener(this.messageListener); + connection.setOnStatusChangedListener(this.statusListener ); + Thread thread = new Thread(connection); + thread.start(); + return connection; + } @Override public IBinder onBind(Intent intent) { @@ -114,68 +125,49 @@ public class XmppConnectionService extends Service { } public void sendMessage(final Account account, final Message message) { - new Thread() { - @Override - public void run() { - Log.d(LOGTAG, "sending message for " + account.getJid() - + " to: " + message.getCounterpart()); - databaseBackend.createMessage(message); - MessagePacket packet = new MessagePacket(); - packet.setType(MessagePacket.TYPE_CHAT); - packet.setTo(message.getCounterpart()); - packet.setFrom(account.getJid()); - packet.setBody(message.getBody()); - try { - connections.get(account).sendMessagePacket(packet); - message.setStatus(Message.STATUS_SEND); - databaseBackend.updateMessage(message); - } catch (IOException e) { - Log.d(LOGTAG, - "io exception during send. message is in database. will try again later"); - } - } - }.start(); + Log.d(LOGTAG, "sending message for " + account.getJid() + " to: " + + message.getCounterpart()); + databaseBackend.createMessage(message); + MessagePacket packet = new MessagePacket(); + packet.setType(MessagePacket.TYPE_CHAT); + packet.setTo(message.getCounterpart()); + packet.setFrom(account.getJid()); + packet.setBody(message.getBody()); + connections.get(account).sendMessagePacket(packet); + message.setStatus(Message.STATUS_SEND); + databaseBackend.updateMessage(message); } public void getRoster(final Account account, final OnRosterFetchedListener listener) { - new Thread() { - @Override - public void run() { - IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); - Element query = new Element("query"); - query.setAttribute("xmlns", "jabber:iq:roster"); - query.setAttribute("ver", ""); - iqPacket.addChild(query); - try { - connections.get(account).sendIqPacket(iqPacket, - new OnIqPacketReceived() { + IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET); + Element query = new Element("query"); + query.setAttribute("xmlns", "jabber:iq:roster"); + query.setAttribute("ver", ""); + iqPacket.addChild(query); + connections.get(account).sendIqPacket(iqPacket, + new OnIqPacketReceived() { - @Override - public void onIqPacketReceived(Account account, - IqPacket packet) { - Element roster = packet.findChild("query"); - List contacts = new ArrayList(); - for (Element item : roster.getChildren()) { - String name = item.getAttribute("name"); - String jid = item.getAttribute("jid"); - if (name == null) { - name = jid.split("@")[0]; - } - Contact contact = new Contact(account, - name, jid, null); - contacts.add(contact); - } - if (listener != null) { - listener.onRosterFetched(contacts); - } - } - }); - } catch (IOException e) { - Log.d(LOGTAG, "io error during roster fetch"); - } - } - }.start(); + @Override + public void onIqPacketReceived(Account account, + IqPacket packet) { + Element roster = packet.findChild("query"); + List contacts = new ArrayList(); + for (Element item : roster.getChildren()) { + String name = item.getAttribute("name"); + String jid = item.getAttribute("jid"); + if (name == null) { + name = jid.split("@")[0]; + } + Contact contact = new Contact(account, name, jid, + null); + contacts.add(contact); + } + if (listener != null) { + listener.onRosterFetched(contacts); + } + } + }); } public void addConversation(Conversation conversation) { @@ -249,14 +241,32 @@ public class XmppConnectionService extends Service { public void createAccount(Account account) { databaseBackend.createAccount(account); + this.accounts.add(account); + this.connections.put(account, this.createConnection(account)); + if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener(); } public void updateAccount(Account account) { databaseBackend.updateAccount(account); + XmppConnection connection = this.connections.get(account); + if (connection != null) { + connection.disconnect(); + this.connections.remove(account); + } + this.connections.put(account, this.createConnection(account)); + if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener(); } public void deleteAccount(Account account) { + Log.d(LOGTAG,"called delete account"); + if (this.connections.containsKey(account)) { + Log.d(LOGTAG,"found connection. disconnecting"); + this.connections.get(account).disconnect(); + this.connections.remove(account); + this.accounts.remove(account); + } databaseBackend.deleteAccount(account); + if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener(); } public void setOnConversationListChangedListener( @@ -267,4 +277,12 @@ public class XmppConnectionService extends Service { public void removeOnConversationListChangedListener() { this.convChangedListener = null; } + + public void setOnAccountListChangedListener(OnAccountListChangedListener listener) { + this.accountChangedListener = listener; + } + + public void removeOnAccountListChangedListener() { + this.accountChangedListener = null; + } } diff --git a/src/de/gultsch/chat/ui/ManageAccountActivity.java b/src/de/gultsch/chat/ui/ManageAccountActivity.java index c7d6ce58d..0a9b03de5 100644 --- a/src/de/gultsch/chat/ui/ManageAccountActivity.java +++ b/src/de/gultsch/chat/ui/ManageAccountActivity.java @@ -6,7 +6,6 @@ import java.util.List; import de.gultsch.chat.R; import de.gultsch.chat.entities.Account; import de.gultsch.chat.ui.EditAccount.EditAccountListener; -import android.app.ActionBar; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -25,28 +24,72 @@ import android.widget.TextView; public class ManageAccountActivity extends XmppActivity { - protected List accountList = new ArrayList(); protected ListView accountListView; protected ArrayAdapter accountListViewAdapter; - + protected OnAccountListChangedListener accountChanged = new OnAccountListChangedListener() { + + @Override + public void onAccountListChangedListener() { + Log.d("xmppService", "ui on account list changed listener"); + accountList.clear(); + accountList.addAll(xmppConnectionService.getAccounts()); + runOnUiThread(new Runnable() { + + @Override + public void run() { + if (accountList.size() == 1) { + startActivity(new Intent(getApplicationContext(), + NewConversationActivity.class)); + } + accountListViewAdapter.notifyDataSetChanged(); + } + }); + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.manage_accounts); - + accountListView = (ListView) findViewById(R.id.account_list); - accountListViewAdapter = new ArrayAdapter(getApplicationContext(), R.layout.account_row, this.accountList) { + accountListViewAdapter = new ArrayAdapter( + getApplicationContext(), R.layout.account_row, this.accountList) { @Override public View getView(int position, View view, ViewGroup parent) { + Account account = getItem(position); if (view == null) { LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = (View) inflater.inflate(R.layout.account_row, null); } - ((TextView) view.findViewById(R.id.account_jid)).setText(getItem(position).getJid()); - + ((TextView) view.findViewById(R.id.account_jid)) + .setText(account.getJid()); + TextView statusView = (TextView) view + .findViewById(R.id.account_status); + switch (account.getStatus()) { + case Account.STATUS_ONLINE: + statusView.setText("online"); + statusView.setTextColor(0xFF83b600); + break; + case Account.STATUS_OFFLINE: + statusView.setText("offline"); + statusView.setTextColor(0xFFe92727); + break; + case Account.STATUS_UNAUTHORIZED: + statusView.setText("unauthorized"); + statusView.setTextColor(0xFFe92727); + break; + case Account.STATUS_SERVER_NOT_FOUND: + statusView.setText("server not found"); + statusView.setTextColor(0xFFe92727); + break; + default: + break; + } + return view; } }; @@ -54,12 +97,12 @@ public class ManageAccountActivity extends XmppActivity { accountListView.setOnItemClickListener(new OnItemClickListener() { @Override - public void onItemClick(AdapterView arg0, View view, int position, - long arg3) { + public void onItemClick(AdapterView arg0, View view, + int position, long arg3) { EditAccount dialog = new EditAccount(); dialog.setAccount(accountList.get(position)); dialog.setEditAccountListener(new EditAccountListener() { - + @Override public void onAccountEdited(Account account) { xmppConnectionService.updateAccount(account); @@ -67,41 +110,27 @@ public class ManageAccountActivity extends XmppActivity { @Override public void onAccountDelete(Account account) { - - Log.d("gultsch","deleting account:"+account.getJid()); - xmppConnectionService.deleteAccount(account); - - //dont bother finding the right account in the frontend list. just reload - accountList.clear(); - accountList.addAll(xmppConnectionService.getAccounts()); - - accountListViewAdapter.notifyDataSetChanged(); - } }); - dialog.show(getFragmentManager(),"edit_account"); + dialog.show(getFragmentManager(), "edit_account"); } }); } @Override - public void onStart() { - super.onStart(); + protected void onStop() { + super.onStop(); if (xmppConnectionServiceBound) { - this.accountList.clear(); - this.accountList.addAll(xmppConnectionService - .getAccounts()); - accountListViewAdapter.notifyDataSetChanged(); - if (this.accountList.size() == 0) { - getActionBar().setDisplayHomeAsUpEnabled(false); - } + xmppConnectionService.removeOnAccountListChangedListener(); + unbindService(mConnection); + xmppConnectionServiceBound = false; } } - + @Override void onBackendConnected() { - Log.d("gultsch","called on backend connected"); + xmppConnectionService.setOnAccountListChangedListener(accountChanged); this.accountList.clear(); this.accountList.addAll(xmppConnectionService.getAccounts()); accountListViewAdapter.notifyDataSetChanged(); @@ -110,14 +139,14 @@ public class ManageAccountActivity extends XmppActivity { addAccount(); } } - + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.manageaccounts, menu); return true; } - + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -137,23 +166,18 @@ public class ManageAccountActivity extends XmppActivity { final Activity activity = this; EditAccount dialog = new EditAccount(); dialog.setEditAccountListener(new EditAccountListener() { - + @Override public void onAccountEdited(Account account) { xmppConnectionService.createAccount(account); - accountList.add(account); - accountListViewAdapter.notifyDataSetChanged(); activity.getActionBar().setDisplayHomeAsUpEnabled(true); - if (accountList.size() == 1) { - activity.startActivity(new Intent(activity,NewConversationActivity.class)); - } } @Override public void onAccountDelete(Account account) { - //this will never be called + // this will never be called } }); - dialog.show(getFragmentManager(),"add_account"); + dialog.show(getFragmentManager(), "add_account"); } } diff --git a/src/de/gultsch/chat/ui/OnAccountListChangedListener.java b/src/de/gultsch/chat/ui/OnAccountListChangedListener.java new file mode 100644 index 000000000..4af5ac9bc --- /dev/null +++ b/src/de/gultsch/chat/ui/OnAccountListChangedListener.java @@ -0,0 +1,5 @@ +package de.gultsch.chat.ui; + +public interface OnAccountListChangedListener { + public void onAccountListChangedListener(); +} diff --git a/src/de/gultsch/chat/xml/TagWriter.java b/src/de/gultsch/chat/xml/TagWriter.java index 35f27477f..401a6eee2 100644 --- a/src/de/gultsch/chat/xml/TagWriter.java +++ b/src/de/gultsch/chat/xml/TagWriter.java @@ -3,12 +3,37 @@ package de.gultsch.chat.xml; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; +import java.util.Collection; +import java.util.Iterator; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import android.util.Log; public class TagWriter { - OutputStreamWriter writer; + private OutputStreamWriter outputStream; + private LinkedBlockingQueue writeQueue = new LinkedBlockingQueue(); + private Thread writer = new Thread() { + public boolean shouldStop = false; + @Override + public void run() { + while(!shouldStop) { + try { + String output = writeQueue.take(); + outputStream.write(output); + outputStream.flush(); + } catch (IOException e) { + Log.d("xmppService", "error writing to stream"); + } catch (InterruptedException e) { + + } + } + } + }; + public TagWriter() { @@ -16,31 +41,29 @@ public class TagWriter { public TagWriter(OutputStream out) { this.setOutputStream(out); + writer.start(); } public void setOutputStream(OutputStream out) { - this.writer = new OutputStreamWriter(out); + this.outputStream = new OutputStreamWriter(out); + if (!writer.isAlive()) writer.start(); } - public TagWriter beginDocument() throws IOException { - writer.write(""); + public TagWriter beginDocument() { + writeQueue.add(""); return this; } - public TagWriter writeTag(Tag tag) throws IOException { - writer.write(tag.toString()); + public TagWriter writeTag(Tag tag) { + writeQueue.add(tag.toString()); return this; } - - public void flush() throws IOException { - writer.flush(); + + public void writeString(String string) { + writeQueue.add(string); } - public void writeString(String string) throws IOException { - writer.write(string); - } - - public void writeElement(Element element) throws IOException { - writer.write(element.toString()); + public void writeElement(Element element) { + writeQueue.add(element.toString()); } } diff --git a/src/de/gultsch/chat/xmpp/OnStatusChanged.java b/src/de/gultsch/chat/xmpp/OnStatusChanged.java new file mode 100644 index 000000000..f79305e35 --- /dev/null +++ b/src/de/gultsch/chat/xmpp/OnStatusChanged.java @@ -0,0 +1,7 @@ +package de.gultsch.chat.xmpp; + +import de.gultsch.chat.entities.Account; + +public interface OnStatusChanged { + public void onStatusChanged(Account account); +} diff --git a/src/de/gultsch/chat/xmpp/XmppConnection.java b/src/de/gultsch/chat/xmpp/XmppConnection.java index 1afe5b0cc..e86bb66c9 100644 --- a/src/de/gultsch/chat/xmpp/XmppConnection.java +++ b/src/de/gultsch/chat/xmpp/XmppConnection.java @@ -39,7 +39,7 @@ public class XmppConnection implements Runnable { private boolean isTlsEncrypted = false; private boolean isAuthenticated = false; //private boolean shouldUseTLS = false; - private boolean shouldReConnect = true; + private boolean shouldConnect = true; private boolean shouldBind = true; private boolean shouldAuthenticate = true; private Element streamFeatures; @@ -52,8 +52,7 @@ public class XmppConnection implements Runnable { private OnPresencePacketReceived presenceListener = null; private OnIqPacketReceived unregisteredIqListener = null; private OnMessagePacketReceived messageListener = null; - - private String resource = null; + private OnStatusChanged statusListener = null; public XmppConnection(Account account, PowerManager pm) { this.account = account; @@ -66,7 +65,6 @@ public class XmppConnection implements Runnable { protected void connect() { try { socket = new Socket(account.getServer(), 5222); - Log.d(LOGTAG, "starting new socket"); OutputStream out = socket.getOutputStream(); tagWriter.setOutputStream(out); InputStream in = socket.getInputStream(); @@ -77,40 +75,54 @@ public class XmppConnection implements Runnable { while ((nextTag = tagReader.readTag()) != null) { if (nextTag.isStart("stream")) { processStream(nextTag); + break; } else { Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName()); return; } } + if (socket.isConnected()) { + socket.close(); + } } catch (UnknownHostException e) { - Log.d(LOGTAG,account.getJid()+": error during connect. unknown host"); + account.setStatus(Account.STATUS_SERVER_NOT_FOUND); return; } catch (IOException e) { - Log.d(LOGTAG, account.getJid()+": error during connect. io exception. falscher port?"); - return; + if (shouldConnect) { + Log.d(LOGTAG,account.getJid()+": connection lost"); + account.setStatus(Account.STATUS_OFFLINE); + if (statusListener!=null) { + statusListener.onStatusChanged(account); + } + } } catch (XmlPullParserException e) { Log.d(LOGTAG,"xml exception "+e.getMessage()); return; } + } @Override public void run() { - while(shouldReConnect) { + shouldConnect = true; + while(shouldConnect) { connect(); try { - Thread.sleep(30000); + if (shouldConnect) { + Thread.sleep(30000); + } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } + Log.d(LOGTAG,"end run"); } private void processStream(Tag currentTag) throws XmlPullParserException, IOException { - Tag nextTag; - while (!(nextTag = tagReader.readTag()).isEnd("stream")) { + Tag nextTag = tagReader.readTag(); + while ((nextTag != null) && (!nextTag.isEnd("stream"))) { if (nextTag.isStart("error")) { processStreamError(nextTag); } else if (nextTag.isStart("features")) { @@ -124,6 +136,12 @@ public class XmppConnection implements Runnable { tagReader.reset(); sendStartStream(); processStream(tagReader.readTag()); + break; + } else if(nextTag.isStart("failure")) { + Element failure = tagReader.readElement(nextTag); + Log.d(LOGTAG,"read failure element"+failure.toString()); + account.setStatus(Account.STATUS_UNAUTHORIZED); + tagWriter.writeTag(Tag.end("stream")); } else if (nextTag.isStart("iq")) { processIq(nextTag); } else if (nextTag.isStart("message")) { @@ -134,6 +152,13 @@ public class XmppConnection implements Runnable { Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName() + " as child of " + currentTag.getName()); } + nextTag = tagReader.readTag(); + } + if (account.getStatus() == Account.STATUS_ONLINE) { + account.setStatus(Account.STATUS_OFFLINE); + if (statusListener!=null) { + statusListener.onStatusChanged(account); + } } } @@ -190,11 +215,11 @@ public class XmppConnection implements Runnable { } } - private void sendStartTLS() throws XmlPullParserException, IOException { + private void sendStartTLS() { Tag startTLS = Tag.empty("starttls"); startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls"); Log.d(LOGTAG,account.getJid()+": sending starttls"); - tagWriter.writeTag(startTLS).flush(); + tagWriter.writeTag(startTLS); } private void switchOverToTls(Tag currentTag) throws XmlPullParserException, @@ -213,6 +238,7 @@ public class XmppConnection implements Runnable { isTlsEncrypted = true; sendStartStream(); processStream(tagReader.readTag()); + sslSocket.close(); } catch (IOException e) { Log.d(LOGTAG, account.getJid()+": error on ssl '" + e.getMessage()+"'"); } @@ -227,7 +253,6 @@ public class XmppConnection implements Runnable { auth.setContent(saslString); Log.d(LOGTAG,account.getJid()+": sending sasl "+auth.toString()); tagWriter.writeElement(auth); - tagWriter.flush(); } private void processStreamFeatures(Tag currentTag) @@ -249,12 +274,10 @@ public class XmppConnection implements Runnable { startSession.addChild(session); sendIqPacket(startSession, null); tagWriter.writeElement(startSession); - tagWriter.flush(); } Element presence = new Element("presence"); tagWriter.writeElement(presence); - tagWriter.flush(); } } @@ -266,8 +289,12 @@ public class XmppConnection implements Runnable { this.sendIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { - resource = packet.findChild("bind").findChild("jid").getContent().split("/")[1]; - Log.d(LOGTAG,account.getJid()+": new resource is "+resource); + String resource = packet.findChild("bind").findChild("jid").getContent().split("/")[1]; + account.setResource(resource); + account.setStatus(Account.STATUS_ONLINE); + if (statusListener!=null) { + statusListener.onStatusChanged(account); + } } }); } @@ -276,7 +303,7 @@ public class XmppConnection implements Runnable { Log.d(LOGTAG, "processStreamError"); } - private void sendStartStream() throws IOException { + private void sendStartStream() { Tag stream = Tag.start("stream"); stream.setAttribute("from", account.getJid()); stream.setAttribute("to", account.getServer()); @@ -284,32 +311,29 @@ public class XmppConnection implements Runnable { stream.setAttribute("xml:lang", "en"); stream.setAttribute("xmlns", "jabber:client"); stream.setAttribute("xmlns:stream", "http://etherx.jabber.org/streams"); - tagWriter.writeTag(stream).flush(); + tagWriter.writeTag(stream); } private String nextRandomId() { return new BigInteger(50, random).toString(32); } - public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) throws IOException { + public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) { String id = nextRandomId(); packet.setAttribute("id",id); tagWriter.writeElement(packet); if (callback != null) { iqPacketCallbacks.put(id, callback); } - tagWriter.flush(); Log.d(LOGTAG,account.getJid()+": sending: "+packet.toString()); } - public void sendMessagePacket(MessagePacket packet) throws IOException { + public void sendMessagePacket(MessagePacket packet){ tagWriter.writeElement(packet); - tagWriter.flush(); } - public void sendPresencePacket(PresencePacket packet) throws IOException { + public void sendPresencePacket(PresencePacket packet) { tagWriter.writeElement(packet); - tagWriter.flush(); } public void setOnMessagePacketReceivedListener(OnMessagePacketReceived listener) { @@ -323,4 +347,13 @@ public class XmppConnection implements Runnable { public void setOnPresencePacketReceivedListener(OnPresencePacketReceived listener) { this.presenceListener = listener; } + + public void setOnStatusChangedListener(OnStatusChanged listener) { + this.statusListener = listener; + } + + public void disconnect() { + shouldConnect = false; + tagWriter.writeTag(Tag.end("stream")); + } }