more cleanup. more listeners

This commit is contained in:
Daniel Gultsch 2014-02-01 15:07:20 +01:00
parent 43531113b7
commit 53d9c9997a
14 changed files with 243 additions and 64 deletions

View file

@ -18,4 +18,8 @@ public abstract class AbstractEntity implements Serializable {
public abstract ContentValues getContentValues();
public boolean equals(AbstractEntity entity) {
return this.getUuid().equals(entity.getUuid());
}
}

View file

@ -32,11 +32,13 @@ public class Conversation extends AbstractEntity {
private long created;
private transient List<Message> messages = null;
private transient Account account = null;
public Conversation(String name, String profilePhoto, Account account,
String contactJid) {
this(java.util.UUID.randomUUID().toString(), name, profilePhoto, account.getUuid(), contactJid, System
.currentTimeMillis(), STATUS_AVAILABLE);
this.account = account;
}
public Conversation(String uuid, String name, String profilePhoto,
@ -94,6 +96,14 @@ public class Conversation extends AbstractEntity {
return this.accountUuid;
}
public Account getAccount() {
return this.account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getContactJid() {
return this.contactJid;
}

View file

@ -40,6 +40,11 @@ public class Message extends AbstractEntity {
this.conversation = conversation;
}
public Message(Conversation conversation, String counterpart, String body, int encryption, int status) {
this(java.util.UUID.randomUUID().toString(), conversation.getUuid(),counterpart, body, System.currentTimeMillis(), encryption,status);
this.conversation = conversation;
}
public Message(String uuid, String conversationUUid, String counterpart,
String body, long timeSent, int encryption, int status) {
this.uuid = uuid;

View file

@ -111,9 +111,9 @@ public class DatabaseBackend extends SQLiteOpenHelper {
return list;
}
public Conversation findConversation(Account account, Contact contact) {
public Conversation findConversation(Account account, String contactJid) {
SQLiteDatabase db = this.getReadableDatabase();
String[] selectionArgs = { account.getUuid(), contact.getJid() };
String[] selectionArgs = { account.getUuid(), contactJid };
Cursor cursor = db.query(Conversation.TABLENAME, null,
Conversation.ACCOUNT + "=? AND " + Conversation.CONTACT + "=?",
selectionArgs, null, null, null);

View file

@ -1,24 +1,17 @@
package de.gultsch.chat.services;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Hashtable;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import de.gultsch.chat.entities.Account;
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.xml.Tag;
import de.gultsch.chat.xml.XmlReader;
import de.gultsch.chat.ui.OnConversationListChangedListener;
import de.gultsch.chat.xmpp.MessagePacket;
import de.gultsch.chat.xmpp.OnMessagePacketReceived;
import de.gultsch.chat.xmpp.XmppConnection;
import android.app.Service;
import android.content.Context;
@ -36,10 +29,32 @@ public class XmppConnectionService extends Service {
public long startDate;
private List<Account> accounts;
private List<Conversation> conversations = null;
public boolean connectionRunnig = false;
private Hashtable<Account,XmppConnection> connections = new Hashtable<Account, XmppConnection>();
private OnConversationListChangedListener convChangedListener = null;
private final IBinder mBinder = new XmppConnectionBinder();
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
@Override
public void onMessagePacketReceived(Account account, MessagePacket packet) {
String fullJid = packet.getFrom();
String jid = fullJid.split("/")[0];
String name = jid.split("@")[0];
Log.d(LOGTAG,"message received for "+account.getJid()+" from "+jid);
Log.d(LOGTAG,packet.toString());
Contact contact = new Contact(name,jid,null); //dummy contact
Conversation conversation = findOrCreateConversation(account, contact);
Message message = new Message(conversation, fullJid, packet.getBody(), Message.ENCRYPTION_NONE, Message.STATUS_RECIEVED);
conversation.getMessages().add(message);
databaseBackend.createMessage(message);
if (convChangedListener != null) {
convChangedListener.onConversationListChanged();
}
}
};
public class XmppConnectionBinder extends Binder {
public XmppConnectionService getService() {
@ -49,16 +64,15 @@ public class XmppConnectionService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(LOGTAG,"recieved start command. been running for "+((System.currentTimeMillis() - startDate) / 1000)+"s");
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (!connectionRunnig) {
for(Account account : accounts) {
Log.d(LOGTAG,"connection wasnt running");
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);
}
connectionRunnig = true;
}
return START_STICKY;
}
@ -67,7 +81,6 @@ public class XmppConnectionService extends Service {
public void onCreate() {
databaseBackend = DatabaseBackend.getInstance(getApplicationContext());
this.accounts = databaseBackend.getAccounts();
startDate = System.currentTimeMillis();
}
@Override
@ -83,8 +96,18 @@ public class XmppConnectionService extends Service {
databaseBackend.createConversation(conversation);
}
public List<Conversation> getConversations(int status) {
return databaseBackend.getConversations(status);
public List<Conversation> getConversations() {
if (this.conversations == null) {
Hashtable<String, Account> accountLookupTable = new Hashtable<String, Account>();
for(Account account : this.accounts) {
accountLookupTable.put(account.getUuid(), account);
}
this.conversations = databaseBackend.getConversations(Conversation.STATUS_AVAILABLE);
for(Conversation conv : this.conversations) {
conv.setAccount(accountLookupTable.get(conv.getAccountUuid()));
}
}
return this.conversations;
}
public List<Account> getAccounts() {
@ -96,20 +119,37 @@ public class XmppConnectionService extends Service {
}
public Conversation findOrCreateConversation(Account account, Contact contact) {
Conversation conversation = databaseBackend.findConversation(account, contact);
Log.d(LOGTAG,"was asked to find conversation for "+contact.getJid());
for(Conversation conv : this.getConversations()) {
if ((conv.getAccount().equals(account))&&(conv.getContactJid().equals(contact.getJid()))) {
Log.d(LOGTAG,"found one in memory");
return conv;
}
}
Conversation conversation = databaseBackend.findConversation(account, contact.getJid());
if (conversation!=null) {
Log.d("gultsch","found one. unarchive it");
conversation.setStatus(Conversation.STATUS_AVAILABLE);
conversation.setAccount(account);
this.databaseBackend.updateConversation(conversation);
} else {
Log.d(LOGTAG,"didnt find one in archive. create new one");
conversation = new Conversation(contact.getDisplayName(), contact.getProfilePhoto(), account, contact.getJid());
this.databaseBackend.createConversation(conversation);
}
this.conversations.add(conversation);
if (this.convChangedListener != null) {
this.convChangedListener.onConversationListChanged();
}
return conversation;
}
public void updateConversation(Conversation conversation) {
public void archiveConversation(Conversation conversation) {
this.databaseBackend.updateConversation(conversation);
this.conversations.remove(conversation);
if (this.convChangedListener != null) {
this.convChangedListener.onConversationListChanged();
}
}
public int getConversationCount() {
@ -127,4 +167,12 @@ public class XmppConnectionService extends Service {
public void deleteAccount(Account account) {
databaseBackend.deleteAccount(account);
}
public void setOnConversationListChangedListener(OnConversationListChangedListener listener) {
this.convChangedListener = listener;
}
public void removeOnConversationListChangedListener() {
this.convChangedListener = null;
}
}

View file

@ -43,6 +43,37 @@ public class ConversationActivity extends XmppActivity {
private ListView listView;
private boolean paneShouldBeOpen = true;
private ArrayAdapter<Conversation> listAdapter;
private OnConversationListChangedListener onConvChanged = new OnConversationListChangedListener() {
@Override
public void onConversationListChanged() {
Log.d("xmppService","on conversation list changed event received");
conversationList.clear();
conversationList.addAll(xmppConnectionService
.getConversations());
runOnUiThread(new Runnable() {
@Override
public void run() {
listAdapter.notifyDataSetChanged();
if(paneShouldBeOpen) {
selectedConversation = 0;
if (conversationList.size() >= 1) {
updateConversationList();
swapConversationFragment();
} else {
startActivity(new Intent(getApplicationContext(), NewConversationActivity.class));
finish();
}
} else {
Log.d("xmppService","pane wasnt open. dont swap fragment");
}
}
});
}
};
public List<Conversation> getConversationList() {
@ -93,7 +124,7 @@ public class ConversationActivity extends XmppActivity {
listView = (ListView) findViewById(R.id.list);
listView.setAdapter(new ArrayAdapter<Conversation>(this,
this.listAdapter = new ArrayAdapter<Conversation>(this,
R.layout.conversation_list_row, conversationList) {
@Override
public View getView(int position, View view, ViewGroup parent) {
@ -122,7 +153,9 @@ public class ConversationActivity extends XmppActivity {
return view;
}
});
};
listView.setAdapter(this.listAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@ -212,19 +245,9 @@ public class ConversationActivity extends XmppActivity {
case R.id.action_archive:
Conversation conv = getConversationList().get(selectedConversation);
conv.setStatus(Conversation.STATUS_ARCHIVED);
xmppConnectionService.updateConversation(conv);
conversationList.remove(selectedConversation);
selectedConversation = 0;
if (conversationList.size() >= 1) {
paneShouldBeOpen = true;
swapConversationFragment();
((ArrayAdapter) listView.getAdapter()).notifyDataSetChanged();
spl.openPane();
} else {
startActivity(new Intent(this, NewConversationActivity.class));
finish();
}
//goto new
xmppConnectionService.archiveConversation(conv);
break;
default:
break;
@ -259,15 +282,39 @@ public class ConversationActivity extends XmppActivity {
if (xmppConnectionServiceBound) {
conversationList.clear();
conversationList.addAll(xmppConnectionService
.getConversations(Conversation.STATUS_AVAILABLE));
.getConversations());
}
}
@Override
public void onPause() {
super.onPause();
if (xmppConnectionServiceBound) {
Log.d("xmppService","called on pause. remove listener");
xmppConnectionService.removeOnConversationListChangedListener();
}
}
@Override
protected void onStop() {
super.onStop();
if (xmppConnectionServiceBound) {
Log.d("xmppService","called on stop. remove listener");
xmppConnectionService.removeOnConversationListChangedListener();
unbindService(mConnection);
xmppConnectionServiceBound = false;
}
}
@Override
void onBackendConnected() {
xmppConnectionService.setOnConversationListChangedListener(this.onConvChanged);
conversationList.clear();
conversationList.addAll(xmppConnectionService
.getConversations(Conversation.STATUS_AVAILABLE));
.getConversations());
for(Conversation conversation : conversationList) {
conversation.setMessages(xmppConnectionService.getMessages(conversation));

View file

@ -116,13 +116,16 @@ public class ConversationFragment extends Fragment {
} else {
Log.d("gultsch", "recylecd a view");
}
ImageView imageView = (ImageView) view.findViewById(R.id.message_photo);
if (type == RECIEVED) {
((ImageView) view.findViewById(R.id.message_photo))
.setImageURI(item.getConversation()
.getProfilePhotoUri());
Uri uri = item.getConversation().getProfilePhotoUri();
if (uri!=null) {
imageView.setImageURI(uri);
} else {
((ImageView) view.findViewById(R.id.message_photo))
.setImageURI(profilePicture);
imageView.setImageBitmap(Beautifier.getUnknownContactPicture(item.getConversation().getName(), 200));
}
} else {
imageView.setImageURI(profilePicture);
}
((TextView) view.findViewById(R.id.message_body)).setText(item
.getBody());

View file

@ -0,0 +1,5 @@
package de.gultsch.chat.ui;
public interface OnConversationListChangedListener {
public void onConversationListChanged();
}

View file

@ -28,6 +28,15 @@ public class Element {
return this;
}
public Element findChild(String name) {
for(Element child : this.children) {
if (child.getName().equals(name)) {
return child;
}
}
return null;
}
public boolean hasChild(String name) {
for(Element child : this.children) {
if (child.getName().equals(name)) {
@ -37,6 +46,10 @@ public class Element {
return false;
}
public String getContent() {
return content;
}
public Element setAttribute(String name, String value) {
this.attributes.put(name, value);
return this;

View file

@ -10,4 +10,12 @@ public class MessagePacket extends Element {
public MessagePacket() {
super("message");
}
public String getFrom() {
return getAttribute("from");
}
public String getBody() {
return this.findChild("body").getContent();
}
}

View file

@ -1,5 +1,7 @@
package de.gultsch.chat.xmpp;
import de.gultsch.chat.entities.Account;
public interface OnIqPacketReceived {
public void onIqPacketReceived(IqPacket packet);
public void onIqPacketReceived(Account account, IqPacket packet);
}

View file

@ -1,5 +1,7 @@
package de.gultsch.chat.xmpp;
import de.gultsch.chat.entities.Account;
public interface OnMessagePacketReceived {
public void onMessagePacketReceived(MessagePacket packet);
public void onMessagePacketReceived(Account account, MessagePacket packet);
}

View file

@ -1,5 +1,7 @@
package de.gultsch.chat.xmpp;
import de.gultsch.chat.entities.Account;
public interface OnPresencePacketReceived {
public void onPresencePacketReceived(PresencePacket packet);
public void onPresencePacketReceived(Account account, PresencePacket packet);
}

View file

@ -49,6 +49,9 @@ public class XmppConnection implements Runnable {
private static final int PACKET_PRESENCE = 2;
private Hashtable<String, OnIqPacketReceived> iqPacketCallbacks = new Hashtable<String, OnIqPacketReceived>();
private OnPresencePacketReceived presenceListener = null;
private OnIqPacketReceived unregisteredIqListener = null;
private OnMessagePacketReceived messageListener = null;
public XmppConnection(Account account, PowerManager pm) {
this.account = account;
@ -115,11 +118,11 @@ public class XmppConnection implements Runnable {
sendStartStream();
processStream(tagReader.readTag());
} else if (nextTag.isStart("iq")) {
Log.d(LOGTAG,processIq(nextTag).toString());
processIq(nextTag);
} else if (nextTag.isStart("message")) {
Log.d(LOGTAG,processMessage(nextTag).toString());
processMessage(nextTag);
} else if (nextTag.isStart("presence")) {
Log.d(LOGTAG,processPresence(nextTag).toString());
processPresence(nextTag);
} else {
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName()
+ " as child of " + currentTag.getName());
@ -158,18 +161,26 @@ public class XmppConnection implements Runnable {
private IqPacket processIq(Tag currentTag) throws XmlPullParserException, IOException {
IqPacket packet = (IqPacket) processPacket(currentTag,PACKET_IQ);
if (iqPacketCallbacks.containsKey(packet.getId())) {
iqPacketCallbacks.get(packet.getId()).onIqPacketReceived(packet);
iqPacketCallbacks.get(packet.getId()).onIqPacketReceived(account,packet);
iqPacketCallbacks.remove(packet.getId());
} else if (this.unregisteredIqListener != null) {
this.unregisteredIqListener.onIqPacketReceived(account,packet);
}
return packet;
}
private MessagePacket processMessage(Tag currentTag) throws XmlPullParserException, IOException {
return (MessagePacket) processPacket(currentTag, PACKET_MESSAGE);
private void processMessage(Tag currentTag) throws XmlPullParserException, IOException {
MessagePacket packet = (MessagePacket) processPacket(currentTag, PACKET_MESSAGE);
if (this.messageListener != null) {
this.messageListener.onMessagePacketReceived(account,packet);
}
}
private PresencePacket processPresence(Tag currentTag) throws XmlPullParserException, IOException {
return (PresencePacket) processPacket(currentTag, PACKET_PRESENCE);
private void processPresence(Tag currentTag) throws XmlPullParserException, IOException {
PresencePacket packet = (PresencePacket) processPacket(currentTag, PACKET_PRESENCE);
if (this.presenceListener != null) {
this.presenceListener.onPresencePacketReceived(account,packet);
}
}
private void sendStartTLS() throws XmlPullParserException, IOException {
@ -248,7 +259,7 @@ public class XmppConnection implements Runnable {
iq.addChild(bind);
this.sendIqPacket(iq, new OnIqPacketReceived() {
@Override
public void onIqPacketReceived(IqPacket packet) {
public void onIqPacketReceived(Account account, IqPacket packet) {
Log.d(LOGTAG,"answer for our bind was: "+packet.toString());
}
});
@ -277,10 +288,29 @@ public class XmppConnection implements Runnable {
String id = nextRandomId();
packet.setAttribute("id",id);
tagWriter.writeElement(packet);
tagWriter.flush();
if (callback != null) {
iqPacketCallbacks.put(id, callback);
}
Log.d(LOGTAG,"sending: "+packet.toString());
}
public void sendMessagePacket(MessagePacket packet) throws IOException {
tagWriter.writeElement(packet);
}
public void sendPresencePacket(PresencePacket packet) throws IOException {
tagWriter.writeElement(packet);
}
public void setOnMessagePacketReceivedListener(OnMessagePacketReceived listener) {
this.messageListener = listener;
}
public void setOnUnregisteredIqPacketReceivedListener(OnIqPacketReceived listener) {
this.unregisteredIqListener = listener;
}
public void setOnPresencePacketReceivedListener(OnPresencePacketReceived listener) {
this.presenceListener = listener;
}
}