roster versioning. roster updates on air. performance fixes in conversation listview
This commit is contained in:
parent
0392e6b2dc
commit
746f959155
|
@ -3,7 +3,9 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingLeft="8dp">
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:paddingRight="8dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -34,7 +36,8 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"
|
||||||
|
android:typeface="monospace"/>
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -49,5 +52,6 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp"
|
||||||
|
android:typeface="monospace"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -80,7 +80,8 @@
|
||||||
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
android:text="2674D6A0 0B1421B1 BFC42AEC C56F3719 672437D8"
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"
|
||||||
|
android:typeface="monospace"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -201,4 +201,16 @@ public class Account extends AbstractEntity{
|
||||||
}
|
}
|
||||||
return this.otrFingerprint;
|
return this.otrFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRosterVersion() {
|
||||||
|
if (this.rosterVersion==null) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
return this.rosterVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRosterVersion(String version) {
|
||||||
|
this.rosterVersion = version;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
protected String subscription;
|
protected String subscription;
|
||||||
protected String systemAccount;
|
protected String systemAccount;
|
||||||
protected String photoUri;
|
protected String photoUri;
|
||||||
protected JSONObject keys;
|
protected JSONObject keys = new JSONObject();
|
||||||
protected Presences presences = new Presences();
|
protected Presences presences = new Presences();
|
||||||
|
|
||||||
protected Account account;
|
protected Account account;
|
||||||
|
@ -47,6 +47,7 @@ public class Contact extends AbstractEntity implements Serializable {
|
||||||
this.displayName = displayName;
|
this.displayName = displayName;
|
||||||
this.jid = jid;
|
this.jid = jid;
|
||||||
this.photoUri = photoUri;
|
this.photoUri = photoUri;
|
||||||
|
this.uuid = java.util.UUID.randomUUID().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Contact(String uuid, String account, String displayName, String jid,
|
public Contact(String uuid, String account, String displayName, String jid,
|
||||||
|
|
|
@ -246,6 +246,16 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Contact> getContats(String where) {
|
||||||
|
List<Contact> list = new ArrayList<Contact>();
|
||||||
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
|
Cursor cursor = db.query(Contact.TABLENAME, null, where, null, null, null, null);
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
list.add(Contact.fromCursor(cursor));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public Contact findContact(Account account, String jid) {
|
public Contact findContact(Account account, String jid) {
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
String[] selectionArgs = { account.getUuid(), jid };
|
String[] selectionArgs = { account.getUuid(), jid };
|
||||||
|
@ -263,4 +273,12 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
String[] args = { message.getUuid() };
|
String[] args = { message.getUuid() };
|
||||||
db.delete(Message.TABLENAME, Message.UUID + "=?", args);
|
db.delete(Message.TABLENAME, Message.UUID + "=?", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void deleteContact(Contact contact) {
|
||||||
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
|
String[] args = { contact.getUuid() };
|
||||||
|
db.delete(Contact.TABLENAME, Contact.UUID + "=?", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package de.gultsch.chat.persistance;
|
||||||
|
|
||||||
|
public interface OnPhoneContactsMerged {
|
||||||
|
public void phoneContactsMerged();
|
||||||
|
}
|
|
@ -19,9 +19,11 @@ import de.gultsch.chat.entities.Conversation;
|
||||||
import de.gultsch.chat.entities.Message;
|
import de.gultsch.chat.entities.Message;
|
||||||
import de.gultsch.chat.entities.Presences;
|
import de.gultsch.chat.entities.Presences;
|
||||||
import de.gultsch.chat.persistance.DatabaseBackend;
|
import de.gultsch.chat.persistance.DatabaseBackend;
|
||||||
|
import de.gultsch.chat.persistance.OnPhoneContactsMerged;
|
||||||
import de.gultsch.chat.ui.OnAccountListChangedListener;
|
import de.gultsch.chat.ui.OnAccountListChangedListener;
|
||||||
import de.gultsch.chat.ui.OnConversationListChangedListener;
|
import de.gultsch.chat.ui.OnConversationListChangedListener;
|
||||||
import de.gultsch.chat.ui.OnRosterFetchedListener;
|
import de.gultsch.chat.ui.OnRosterFetchedListener;
|
||||||
|
import de.gultsch.chat.utils.MessageParser;
|
||||||
import de.gultsch.chat.utils.OnPhoneContactsLoadedListener;
|
import de.gultsch.chat.utils.OnPhoneContactsLoadedListener;
|
||||||
import de.gultsch.chat.utils.PhoneHelper;
|
import de.gultsch.chat.utils.PhoneHelper;
|
||||||
import de.gultsch.chat.utils.UIHelper;
|
import de.gultsch.chat.utils.UIHelper;
|
||||||
|
@ -39,6 +41,7 @@ import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
|
import android.database.DatabaseUtils;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
@ -49,14 +52,14 @@ import android.util.Log;
|
||||||
public class XmppConnectionService extends Service {
|
public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
protected static final String LOGTAG = "xmppService";
|
protected static final String LOGTAG = "xmppService";
|
||||||
protected DatabaseBackend databaseBackend;
|
public DatabaseBackend databaseBackend;
|
||||||
|
|
||||||
public long startDate;
|
public long startDate;
|
||||||
|
|
||||||
private List<Account> accounts;
|
private List<Account> accounts;
|
||||||
private List<Conversation> conversations = null;
|
private List<Conversation> conversations = null;
|
||||||
|
|
||||||
private OnConversationListChangedListener convChangedListener = null;
|
public OnConversationListChangedListener convChangedListener = null;
|
||||||
private OnAccountListChangedListener accountChangedListener = null;
|
private OnAccountListChangedListener accountChangedListener = null;
|
||||||
|
|
||||||
private ContentObserver contactObserver = new ContentObserver(null) {
|
private ContentObserver contactObserver = new ContentObserver(null) {
|
||||||
|
@ -64,148 +67,74 @@ public class XmppConnectionService extends Service {
|
||||||
public void onChange(boolean selfChange) {
|
public void onChange(boolean selfChange) {
|
||||||
super.onChange(selfChange);
|
super.onChange(selfChange);
|
||||||
Log.d(LOGTAG, "contact list has changed");
|
Log.d(LOGTAG, "contact list has changed");
|
||||||
mergePhoneContactsWithRoster();
|
mergePhoneContactsWithRoster(null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private XmppConnectionService service = this;
|
||||||
|
|
||||||
private final IBinder mBinder = new XmppConnectionBinder();
|
private final IBinder mBinder = new XmppConnectionBinder();
|
||||||
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
|
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessagePacketReceived(Account account,
|
public void onMessagePacketReceived(Account account,
|
||||||
MessagePacket packet) {
|
MessagePacket packet) {
|
||||||
if ((packet.getType() == MessagePacket.TYPE_CHAT)
|
Message message = null;
|
||||||
|| (packet.getType() == MessagePacket.TYPE_GROUPCHAT)) {
|
boolean notify = false;
|
||||||
boolean notify = true;
|
if ((packet.getType() == MessagePacket.TYPE_CHAT)) {
|
||||||
boolean runOtrCheck = false;
|
if (packet.hasChild("body")
|
||||||
int status = Message.STATUS_RECIEVED;
|
&& (packet.getBody().startsWith("?OTR"))) {
|
||||||
int encryption = Message.ENCRYPTION_NONE;
|
message = MessageParser.parseOtrChat(packet, account,
|
||||||
String body;
|
service);
|
||||||
String fullJid;
|
notify = true;
|
||||||
if (!packet.hasChild("body")) {
|
} else if (packet.hasChild("body")) {
|
||||||
Element forwarded;
|
message = MessageParser.parsePlainTextChat(packet, account,
|
||||||
if (packet.hasChild("received")) {
|
service);
|
||||||
forwarded = packet.findChild("received").findChild(
|
notify = true;
|
||||||
"forwarded");
|
} else if (packet.hasChild("received")
|
||||||
} else if (packet.hasChild("sent")) {
|
|| (packet.hasChild("sent"))) {
|
||||||
forwarded = packet.findChild("sent").findChild(
|
message = MessageParser.parseCarbonMessage(packet, account,
|
||||||
"forwarded");
|
service);
|
||||||
status = Message.STATUS_SEND;
|
|
||||||
notify = false;
|
|
||||||
} else {
|
|
||||||
return; // massage has no body and is not carbon. just
|
|
||||||
// skip
|
|
||||||
}
|
|
||||||
if (forwarded != null) {
|
|
||||||
Element message = forwarded.findChild("message");
|
|
||||||
if ((message == null) || (!message.hasChild("body")))
|
|
||||||
return; // either malformed or boring
|
|
||||||
if (status == Message.STATUS_RECIEVED) {
|
|
||||||
fullJid = message.getAttribute("from");
|
|
||||||
} else {
|
|
||||||
fullJid = message.getAttribute("to");
|
|
||||||
}
|
|
||||||
body = message.findChild("body").getContent();
|
|
||||||
} else {
|
|
||||||
return; // packet malformed. has no forwarded element
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fullJid = packet.getFrom();
|
|
||||||
body = packet.getBody();
|
|
||||||
runOtrCheck = true;
|
|
||||||
}
|
}
|
||||||
Conversation conversation = null;
|
|
||||||
String[] fromParts = fullJid.split("/");
|
} else if (packet.getType() == MessagePacket.TYPE_GROUPCHAT) {
|
||||||
String jid = fromParts[0];
|
message = MessageParser
|
||||||
boolean muc = (packet.getType() == MessagePacket.TYPE_GROUPCHAT);
|
.parseGroupchat(packet, account, service);
|
||||||
String counterPart = null;
|
if (message != null) {
|
||||||
conversation = findOrCreateConversation(account, jid, muc);
|
notify = (message.getStatus() == Message.STATUS_RECIEVED);
|
||||||
if (muc) {
|
|
||||||
if ((fromParts.length == 1) || (packet.hasChild("subject"))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
counterPart = fromParts[1];
|
|
||||||
if (counterPart.equals(account.getUsername())) {
|
|
||||||
status = Message.STATUS_SEND;
|
|
||||||
notify = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
counterPart = fullJid;
|
|
||||||
if ((runOtrCheck) && body.startsWith("?OTR")) {
|
|
||||||
if (!conversation.hasValidOtrSession()) {
|
|
||||||
conversation.startOtrSession(
|
|
||||||
getApplicationContext(), fromParts[1]);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Session otrSession = conversation.getOtrSession();
|
|
||||||
SessionStatus before = otrSession
|
|
||||||
.getSessionStatus();
|
|
||||||
body = otrSession.transformReceiving(body);
|
|
||||||
SessionStatus after = otrSession.getSessionStatus();
|
|
||||||
if ((before != after)
|
|
||||||
&& (after == SessionStatus.ENCRYPTED)) {
|
|
||||||
Log.d(LOGTAG, "otr session etablished");
|
|
||||||
List<Message> messages = conversation
|
|
||||||
.getMessages();
|
|
||||||
for (int i = 0; i < messages.size(); ++i) {
|
|
||||||
Message msg = messages.get(i);
|
|
||||||
if ((msg.getStatus() == Message.STATUS_UNSEND)
|
|
||||||
&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
|
|
||||||
MessagePacket outPacket = prepareMessagePacket(
|
|
||||||
account, msg, otrSession);
|
|
||||||
msg.setStatus(Message.STATUS_SEND);
|
|
||||||
databaseBackend.updateMessage(msg);
|
|
||||||
account.getXmppConnection()
|
|
||||||
.sendMessagePacket(outPacket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (convChangedListener!=null) {
|
|
||||||
convChangedListener.onConversationListChanged();
|
|
||||||
}
|
|
||||||
} else if ((before != after) && (after == SessionStatus.FINISHED)) {
|
|
||||||
conversation.resetOtrSession();
|
|
||||||
Log.d(LOGTAG,"otr session stoped");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(LOGTAG, "error receiving otr. resetting");
|
|
||||||
conversation.resetOtrSession();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (body == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
encryption = Message.ENCRYPTION_OTR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Message message = new Message(conversation, counterPart, body,
|
} else {
|
||||||
encryption, status);
|
Log.d(LOGTAG, "unparsed message " + packet.toString());
|
||||||
if (packet.hasChild("delay")) {
|
}
|
||||||
try {
|
if (message == null) {
|
||||||
String stamp = packet.findChild("delay").getAttribute(
|
return;
|
||||||
"stamp");
|
}
|
||||||
stamp = stamp.replace("Z", "+0000");
|
if (packet.hasChild("delay")) {
|
||||||
Date date = new SimpleDateFormat(
|
try {
|
||||||
"yyyy-MM-dd'T'HH:mm:ssZ").parse(stamp);
|
String stamp = packet.findChild("delay").getAttribute(
|
||||||
message.setTime(date.getTime());
|
"stamp");
|
||||||
} catch (ParseException e) {
|
stamp = stamp.replace("Z", "+0000");
|
||||||
Log.d(LOGTAG,
|
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||||
"error trying to parse date" + e.getMessage());
|
.parse(stamp);
|
||||||
}
|
message.setTime(date.getTime());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
Log.d(LOGTAG, "error trying to parse date" + e.getMessage());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (notify) {
|
||||||
|
message.markUnread();
|
||||||
|
}
|
||||||
|
Conversation conversation = message.getConversation();
|
||||||
|
conversation.getMessages().add(message);
|
||||||
|
databaseBackend.createMessage(message);
|
||||||
|
if (convChangedListener != null) {
|
||||||
|
convChangedListener.onConversationListChanged();
|
||||||
|
} else {
|
||||||
if (notify) {
|
if (notify) {
|
||||||
message.markUnread();
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
}
|
mNotificationManager.notify(2342, UIHelper
|
||||||
conversation.getMessages().add(message);
|
.getUnreadMessageNotification(
|
||||||
databaseBackend.createMessage(message);
|
getApplicationContext(), conversation));
|
||||||
if (convChangedListener != null) {
|
|
||||||
convChangedListener.onConversationListChanged();
|
|
||||||
} else {
|
|
||||||
if (notify) {
|
|
||||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
mNotificationManager.notify(2342, UIHelper
|
|
||||||
.getUnreadMessageNotification(
|
|
||||||
getApplicationContext(), conversation));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,10 +201,53 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private OnIqPacketReceived unknownIqListener = new OnIqPacketReceived() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||||
|
if (packet.hasChild("query")) {
|
||||||
|
Element query = packet.findChild("query");
|
||||||
|
String xmlns = query.getAttribute("xmlns");
|
||||||
|
if ((xmlns != null) && (xmlns.equals("jabber:iq:roster"))) {
|
||||||
|
processRosterItems(account, query);
|
||||||
|
mergePhoneContactsWithRoster(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void processRosterItems(Account account, Element elements) {
|
||||||
|
for (Element item : elements.getChildren()) {
|
||||||
|
if (item.getName().equals("item")) {
|
||||||
|
String jid = item.getAttribute("jid");
|
||||||
|
String subscription = item.getAttribute("subscription");
|
||||||
|
Contact contact = databaseBackend.findContact(account, jid);
|
||||||
|
if (contact == null) {
|
||||||
|
String name = item.getAttribute("name");
|
||||||
|
if (name == null) {
|
||||||
|
name = jid.split("@")[0];
|
||||||
|
}
|
||||||
|
contact = new Contact(account, name, jid, null);
|
||||||
|
contact.setSubscription(subscription);
|
||||||
|
databaseBackend.createContact(contact);
|
||||||
|
} else {
|
||||||
|
if (subscription.equals("remove")) {
|
||||||
|
databaseBackend.deleteContact(contact);
|
||||||
|
} else {
|
||||||
|
contact.setSubscription(subscription);
|
||||||
|
databaseBackend.updateContact(contact);
|
||||||
|
replaceContactInConversation(contact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void replaceContactInConversation(Contact contact) {
|
private void replaceContactInConversation(Contact contact) {
|
||||||
List<Conversation> conversations = getConversations();
|
List<Conversation> conversations = getConversations();
|
||||||
for(int i = 0; i < conversations.size(); ++i) {
|
for (int i = 0; i < conversations.size(); ++i) {
|
||||||
if (conversations.get(i).getContact().equals(contact)) {
|
if ((conversations.get(i).getContact() != null)
|
||||||
|
&& (conversations.get(i).getContact().equals(contact))) {
|
||||||
conversations.get(i).setContact(contact);
|
conversations.get(i).setContact(contact);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -325,6 +297,8 @@ public class XmppConnectionService extends Service {
|
||||||
connection.setOnMessagePacketReceivedListener(this.messageListener);
|
connection.setOnMessagePacketReceivedListener(this.messageListener);
|
||||||
connection.setOnStatusChangedListener(this.statusListener);
|
connection.setOnStatusChangedListener(this.statusListener);
|
||||||
connection.setOnPresencePacketReceivedListener(this.presenceListener);
|
connection.setOnPresencePacketReceivedListener(this.presenceListener);
|
||||||
|
connection
|
||||||
|
.setOnUnregisteredIqPacketReceivedListener(this.unknownIqListener);
|
||||||
Thread thread = new Thread(connection);
|
Thread thread = new Thread(connection);
|
||||||
thread.start();
|
thread.start();
|
||||||
return connection;
|
return connection;
|
||||||
|
@ -338,10 +312,11 @@ public class XmppConnectionService extends Service {
|
||||||
MessagePacket packet;
|
MessagePacket packet;
|
||||||
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
if (message.getEncryption() == Message.ENCRYPTION_OTR) {
|
||||||
if (!conv.hasValidOtrSession()) {
|
if (!conv.hasValidOtrSession()) {
|
||||||
//starting otr session. messages will be send later
|
// starting otr session. messages will be send later
|
||||||
conv.startOtrSession(getApplicationContext(), presence);
|
conv.startOtrSession(getApplicationContext(), presence);
|
||||||
} else if (conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED){
|
} else if (conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
|
||||||
//otr session aleary exists, creating message packet accordingly
|
// otr session aleary exists, creating message packet
|
||||||
|
// accordingly
|
||||||
packet = prepareMessagePacket(account, message,
|
packet = prepareMessagePacket(account, message,
|
||||||
conv.getOtrSession());
|
conv.getOtrSession());
|
||||||
account.getXmppConnection().sendMessagePacket(packet);
|
account.getXmppConnection().sendMessagePacket(packet);
|
||||||
|
@ -398,8 +373,8 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MessagePacket prepareMessagePacket(Account account,
|
public MessagePacket prepareMessagePacket(Account account, Message message,
|
||||||
Message message, Session otrSession) {
|
Session otrSession) {
|
||||||
MessagePacket packet = new MessagePacket();
|
MessagePacket packet = new MessagePacket();
|
||||||
if (message.getConversation().getMode() == Conversation.MODE_SINGLE) {
|
if (message.getConversation().getMode() == Conversation.MODE_SINGLE) {
|
||||||
packet.setType(MessagePacket.TYPE_CHAT);
|
packet.setType(MessagePacket.TYPE_CHAT);
|
||||||
|
@ -416,7 +391,8 @@ public class XmppConnectionService extends Service {
|
||||||
Element privateMarker = new Element("private");
|
Element privateMarker = new Element("private");
|
||||||
privateMarker.setAttribute("xmlns", "urn:xmpp:carbons:2");
|
privateMarker.setAttribute("xmlns", "urn:xmpp:carbons:2");
|
||||||
packet.addChild(privateMarker);
|
packet.addChild(privateMarker);
|
||||||
packet.setTo(otrSession.getSessionID().getAccountID()+"/"+otrSession.getSessionID().getUserID());
|
packet.setTo(otrSession.getSessionID().getAccountID() + "/"
|
||||||
|
+ otrSession.getSessionID().getUserID());
|
||||||
packet.setFrom(account.getFullJid());
|
packet.setFrom(account.getFullJid());
|
||||||
} else {
|
} else {
|
||||||
packet.setBody(message.getBody());
|
packet.setBody(message.getBody());
|
||||||
|
@ -445,81 +421,65 @@ public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
public void updateRoster(final Account account,
|
public void updateRoster(final Account account,
|
||||||
final OnRosterFetchedListener listener) {
|
final OnRosterFetchedListener listener) {
|
||||||
|
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||||
PhoneHelper.loadPhoneContacts(this,
|
Element query = new Element("query");
|
||||||
new OnPhoneContactsLoadedListener() {
|
query.setAttribute("xmlns", "jabber:iq:roster");
|
||||||
|
query.setAttribute("ver", account.getRosterVersion());
|
||||||
|
iqPacket.addChild(query);
|
||||||
|
account.getXmppConnection().sendIqPacket(iqPacket,
|
||||||
|
new OnIqPacketReceived() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPhoneContactsLoaded(
|
public void onIqPacketReceived(final Account account,
|
||||||
final Hashtable<String, Bundle> phoneContacts) {
|
IqPacket packet) {
|
||||||
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
Element roster = packet.findChild("query");
|
||||||
Element query = new Element("query");
|
if (roster != null) {
|
||||||
query.setAttribute("xmlns", "jabber:iq:roster");
|
String version = roster.getAttribute("ver");
|
||||||
query.setAttribute("ver", "");
|
processRosterItems(account, roster);
|
||||||
iqPacket.addChild(query);
|
if (version!=null) {
|
||||||
account.getXmppConnection().sendIqPacket(iqPacket,
|
account.setRosterVersion(version);
|
||||||
new OnIqPacketReceived() {
|
databaseBackend.updateAccount(account);
|
||||||
|
} else {
|
||||||
@Override
|
StringBuilder mWhere = new StringBuilder();
|
||||||
public void onIqPacketReceived(
|
mWhere.append("jid NOT IN(");
|
||||||
Account account, IqPacket packet) {
|
List<Element> items = roster.getChildren();
|
||||||
List<Contact> contacts = new ArrayList<Contact>();
|
for(int i = 0; i < items.size(); ++i) {
|
||||||
Element roster = packet
|
mWhere.append("\"");
|
||||||
.findChild("query");
|
mWhere.append(DatabaseUtils.sqlEscapeString(items.get(i).getAttribute("jid")));
|
||||||
if (roster != null) {
|
if (i != items.size() - 1) {
|
||||||
for (Element item : roster
|
mWhere.append("\",");
|
||||||
.getChildren()) {
|
} else {
|
||||||
Contact contact;
|
mWhere.append("\"");
|
||||||
String name = item
|
|
||||||
.getAttribute("name");
|
|
||||||
String jid = item
|
|
||||||
.getAttribute("jid");
|
|
||||||
if (phoneContacts
|
|
||||||
.containsKey(jid)) {
|
|
||||||
Bundle phoneContact = phoneContacts
|
|
||||||
.get(jid);
|
|
||||||
String systemAccount = phoneContact
|
|
||||||
.getInt("phoneid")
|
|
||||||
+ "#"
|
|
||||||
+ phoneContact
|
|
||||||
.getString("lookup");
|
|
||||||
contact = new Contact(
|
|
||||||
account,
|
|
||||||
phoneContact
|
|
||||||
.getString("displayname"),
|
|
||||||
jid,
|
|
||||||
phoneContact
|
|
||||||
.getString("photouri"));
|
|
||||||
contact.setSystemAccount(systemAccount);
|
|
||||||
} else {
|
|
||||||
if (name == null) {
|
|
||||||
name = jid.split("@")[0];
|
|
||||||
}
|
|
||||||
contact = new Contact(
|
|
||||||
account, name, jid,
|
|
||||||
null);
|
|
||||||
|
|
||||||
}
|
|
||||||
contact.setAccount(account);
|
|
||||||
contact.setSubscription(item
|
|
||||||
.getAttribute("subscription"));
|
|
||||||
contacts.add(contact);
|
|
||||||
}
|
|
||||||
databaseBackend
|
|
||||||
.mergeContacts(contacts);
|
|
||||||
if (listener != null) {
|
|
||||||
listener.onRosterFetched(contacts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
mWhere.append(") and accountUuid = \"");
|
||||||
|
mWhere.append(account.getUuid());
|
||||||
|
mWhere.append("\"");
|
||||||
|
List<Contact> contactsToDelete = databaseBackend.getContats(mWhere.toString());
|
||||||
|
for(Contact contact : contactsToDelete) {
|
||||||
|
databaseBackend.deleteContact(contact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void phoneContactsMerged() {
|
||||||
|
if (listener != null) {
|
||||||
|
getRoster(account, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (listener != null) {
|
||||||
|
getRoster(account, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mergePhoneContactsWithRoster() {
|
public void mergePhoneContactsWithRoster(final OnPhoneContactsMerged listener) {
|
||||||
PhoneHelper.loadPhoneContacts(this,
|
PhoneHelper.loadPhoneContacts(getApplicationContext(),
|
||||||
new OnPhoneContactsLoadedListener() {
|
new OnPhoneContactsLoadedListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onPhoneContactsLoaded(
|
public void onPhoneContactsLoaded(
|
||||||
|
@ -550,6 +510,9 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (listener!=null) {
|
||||||
|
listener.phoneContactsMerged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -606,7 +569,8 @@ public class XmppConnectionService extends Service {
|
||||||
conversation.setMode(Conversation.MODE_SINGLE);
|
conversation.setMode(Conversation.MODE_SINGLE);
|
||||||
}
|
}
|
||||||
this.databaseBackend.updateConversation(conversation);
|
this.databaseBackend.updateConversation(conversation);
|
||||||
conversation.setContact(findContact(account, conversation.getContactJid()));
|
conversation.setContact(findContact(account,
|
||||||
|
conversation.getContactJid()));
|
||||||
} else {
|
} else {
|
||||||
String conversationName;
|
String conversationName;
|
||||||
Contact contact = findContact(account, jid);
|
Contact contact = findContact(account, jid);
|
||||||
|
@ -728,8 +692,8 @@ public class XmppConnectionService extends Service {
|
||||||
if (conversation.getMessages().size() != 0) {
|
if (conversation.getMessages().size() != 0) {
|
||||||
Element history = new Element("history");
|
Element history = new Element("history");
|
||||||
long lastMsgTime = conversation.getLatestMessage().getTimeSent();
|
long lastMsgTime = conversation.getLatestMessage().getTimeSent();
|
||||||
long diff = (System.currentTimeMillis() - lastMsgTime) / 1000;
|
long diff = (System.currentTimeMillis() - lastMsgTime) / 1000 - 1;
|
||||||
history.setAttribute("seconds",diff+"");
|
history.setAttribute("seconds", diff + "");
|
||||||
x.addChild(history);
|
x.addChild(history);
|
||||||
}
|
}
|
||||||
packet.addChild(x);
|
packet.addChild(x);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package de.gultsch.chat.ui;
|
package de.gultsch.chat.ui;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -19,13 +22,17 @@ import android.app.AlertDialog;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
import android.view.View.OnLayoutChangeListener;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
@ -43,6 +50,7 @@ public class ConversationFragment extends Fragment {
|
||||||
protected List<Message> messageList = new ArrayList<Message>();
|
protected List<Message> messageList = new ArrayList<Message>();
|
||||||
protected ArrayAdapter<Message> messageListAdapter;
|
protected ArrayAdapter<Message> messageListAdapter;
|
||||||
protected Contact contact;
|
protected Contact contact;
|
||||||
|
protected BitmapCache mBitmapCache = new BitmapCache();
|
||||||
|
|
||||||
private EditText chatMsg;
|
private EditText chatMsg;
|
||||||
|
|
||||||
|
@ -104,13 +112,24 @@ public class ConversationFragment extends Fragment {
|
||||||
boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
|
boolean showPhoneSelfContactPicture = sharedPref.getBoolean(
|
||||||
"show_phone_selfcontact_picture", true);
|
"show_phone_selfcontact_picture", true);
|
||||||
|
|
||||||
final Uri selfiUri;
|
Bitmap self;
|
||||||
|
|
||||||
if (showPhoneSelfContactPicture) {
|
if (showPhoneSelfContactPicture) {
|
||||||
selfiUri = PhoneHelper.getSefliUri(getActivity());
|
Uri selfiUri = PhoneHelper.getSefliUri(getActivity());
|
||||||
|
try {
|
||||||
|
self = BitmapFactory.decodeStream(getActivity()
|
||||||
|
.getContentResolver().openInputStream(selfiUri));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
self = UIHelper.getUnknownContactPicture(conversation
|
||||||
|
.getAccount().getJid(), 200);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
selfiUri = null;
|
self = UIHelper.getUnknownContactPicture(conversation.getAccount()
|
||||||
|
.getJid(), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Bitmap selfBitmap = self;
|
||||||
|
|
||||||
messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
|
messageListAdapter = new ArrayAdapter<Message>(this.getActivity()
|
||||||
.getApplicationContext(), R.layout.message_sent,
|
.getApplicationContext(), R.layout.message_sent,
|
||||||
this.messageList) {
|
this.messageList) {
|
||||||
|
@ -136,68 +155,73 @@ public class ConversationFragment extends Fragment {
|
||||||
public View getView(int position, View view, ViewGroup parent) {
|
public View getView(int position, View view, ViewGroup parent) {
|
||||||
Message item = getItem(position);
|
Message item = getItem(position);
|
||||||
int type = getItemViewType(position);
|
int type = getItemViewType(position);
|
||||||
|
ViewHolder viewHolder;
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SENT:
|
case SENT:
|
||||||
|
viewHolder = new ViewHolder();
|
||||||
view = (View) inflater.inflate(R.layout.message_sent,
|
view = (View) inflater.inflate(R.layout.message_sent,
|
||||||
null);
|
null);
|
||||||
|
viewHolder.imageView = (ImageView) view
|
||||||
|
.findViewById(R.id.message_photo);
|
||||||
|
viewHolder.messageBody = (TextView) view
|
||||||
|
.findViewById(R.id.message_body);
|
||||||
|
viewHolder.time = (TextView) view
|
||||||
|
.findViewById(R.id.message_time);
|
||||||
|
view.setTag(viewHolder);
|
||||||
break;
|
break;
|
||||||
case RECIEVED:
|
case RECIEVED:
|
||||||
|
viewHolder = new ViewHolder();
|
||||||
view = (View) inflater.inflate(
|
view = (View) inflater.inflate(
|
||||||
R.layout.message_recieved, null);
|
R.layout.message_recieved, null);
|
||||||
|
viewHolder.imageView = (ImageView) view
|
||||||
|
.findViewById(R.id.message_photo);
|
||||||
|
viewHolder.messageBody = (TextView) view
|
||||||
|
.findViewById(R.id.message_body);
|
||||||
|
viewHolder.time = (TextView) view
|
||||||
|
.findViewById(R.id.message_time);
|
||||||
|
view.setTag(viewHolder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
viewHolder = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
viewHolder = (ViewHolder) view.getTag();
|
||||||
}
|
}
|
||||||
ImageView imageView = (ImageView) view
|
|
||||||
.findViewById(R.id.message_photo);
|
|
||||||
if (type == RECIEVED) {
|
if (type == RECIEVED) {
|
||||||
if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
|
if (item.getConversation().getMode() == Conversation.MODE_SINGLE) {
|
||||||
Uri uri = item.getConversation().getProfilePhotoUri();
|
Uri uri = item.getConversation().getProfilePhotoUri();
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
imageView.setImageURI(uri);
|
viewHolder.imageView.setImageBitmap(mBitmapCache.get(item.getConversation().getName(), uri));
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageBitmap(UIHelper
|
viewHolder.imageView.setImageBitmap(mBitmapCache.get(item.getConversation().getName(),null));
|
||||||
.getUnknownContactPicture(item
|
|
||||||
.getConversation().getName(), 200));
|
|
||||||
}
|
}
|
||||||
} else if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
|
} else if (item.getConversation().getMode() == Conversation.MODE_MULTI) {
|
||||||
if (item.getCounterpart() != null) {
|
if (item.getCounterpart() != null) {
|
||||||
imageView.setImageBitmap(UIHelper
|
viewHolder.imageView.setImageBitmap(mBitmapCache.get(item.getCounterpart(),null));
|
||||||
.getUnknownContactPicture(
|
|
||||||
item.getCounterpart(), 200));
|
|
||||||
} else {
|
} else {
|
||||||
imageView.setImageBitmap(UIHelper
|
viewHolder.imageView.setImageBitmap(mBitmapCache.get(item.getConversation().getName(),null));
|
||||||
.getUnknownContactPicture(item
|
|
||||||
.getConversation().getName(), 200));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (selfiUri != null) {
|
viewHolder.imageView.setImageBitmap(selfBitmap);
|
||||||
imageView.setImageURI(selfiUri);
|
|
||||||
} else {
|
|
||||||
imageView.setImageBitmap(UIHelper
|
|
||||||
.getUnknownContactPicture(conversation
|
|
||||||
.getAccount().getJid(), 200));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TextView messageBody = (TextView) view
|
|
||||||
.findViewById(R.id.message_body);
|
|
||||||
String body = item.getBody();
|
String body = item.getBody();
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
messageBody.setText(body.trim());
|
viewHolder.messageBody.setText(body.trim());
|
||||||
}
|
}
|
||||||
TextView time = (TextView) view.findViewById(R.id.message_time);
|
|
||||||
if (item.getStatus() == Message.STATUS_UNSEND) {
|
if (item.getStatus() == Message.STATUS_UNSEND) {
|
||||||
time.setTypeface(null, Typeface.ITALIC);
|
viewHolder.time.setTypeface(null, Typeface.ITALIC);
|
||||||
time.setText("sending\u2026");
|
viewHolder.time.setText("sending\u2026");
|
||||||
} else {
|
} else {
|
||||||
time.setTypeface(null, Typeface.NORMAL);
|
viewHolder.time.setTypeface(null, Typeface.NORMAL);
|
||||||
if ((item.getConversation().getMode() == Conversation.MODE_SINGLE)
|
if ((item.getConversation().getMode() == Conversation.MODE_SINGLE)
|
||||||
|| (type != RECIEVED)) {
|
|| (type != RECIEVED)) {
|
||||||
time.setText(UIHelper.readableTimeDifference(item
|
viewHolder.time.setText(UIHelper
|
||||||
.getTimeSent()));
|
.readableTimeDifference(item.getTimeSent()));
|
||||||
} else {
|
} else {
|
||||||
time.setText(item.getCounterpart()
|
viewHolder.time.setText(item.getCounterpart()
|
||||||
+ " \u00B7 "
|
+ " \u00B7 "
|
||||||
+ UIHelper.readableTimeDifference(item
|
+ UIHelper.readableTimeDifference(item
|
||||||
.getTimeSent()));
|
.getTimeSent()));
|
||||||
|
@ -275,24 +299,31 @@ public class ConversationFragment extends Fragment {
|
||||||
protected void makeFingerprintWarning(int latestEncryption) {
|
protected void makeFingerprintWarning(int latestEncryption) {
|
||||||
final LinearLayout fingerprintWarning = (LinearLayout) getView()
|
final LinearLayout fingerprintWarning = (LinearLayout) getView()
|
||||||
.findViewById(R.id.new_fingerprint);
|
.findViewById(R.id.new_fingerprint);
|
||||||
Set<String> knownFingerprints = conversation.getContact()
|
if (conversation.getContact() != null) {
|
||||||
.getOtrFingerprints();
|
Set<String> knownFingerprints = conversation.getContact()
|
||||||
if ((latestEncryption == Message.ENCRYPTION_OTR)
|
.getOtrFingerprints();
|
||||||
&& (conversation.hasValidOtrSession()
|
if ((latestEncryption == Message.ENCRYPTION_OTR)
|
||||||
&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
|
&& (conversation.hasValidOtrSession()
|
||||||
.contains(conversation.getOtrFingerprint())))) {
|
&& (conversation.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) && (!knownFingerprints
|
||||||
fingerprintWarning.setVisibility(View.VISIBLE);
|
.contains(conversation.getOtrFingerprint())))) {
|
||||||
TextView fingerprint = (TextView) getView().findViewById(
|
fingerprintWarning.setVisibility(View.VISIBLE);
|
||||||
R.id.otr_fingerprint);
|
TextView fingerprint = (TextView) getView().findViewById(
|
||||||
fingerprint.setText(conversation.getOtrFingerprint());
|
R.id.otr_fingerprint);
|
||||||
fingerprintWarning.setOnClickListener(new OnClickListener() {
|
fingerprint.setText(conversation.getOtrFingerprint());
|
||||||
|
fingerprintWarning.setOnClickListener(new OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
AlertDialog dialog = UIHelper.getVerifyFingerprintDialog((ConversationActivity) getActivity(),conversation,fingerprintWarning);
|
AlertDialog dialog = UIHelper
|
||||||
dialog.show();
|
.getVerifyFingerprintDialog(
|
||||||
}
|
(ConversationActivity) getActivity(),
|
||||||
});
|
conversation, fingerprintWarning);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
fingerprintWarning.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fingerprintWarning.setVisibility(View.GONE);
|
fingerprintWarning.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
@ -300,8 +331,8 @@ public class ConversationFragment extends Fragment {
|
||||||
|
|
||||||
protected void sendPlainTextMessage(Message message) {
|
protected void sendPlainTextMessage(Message message) {
|
||||||
ConversationActivity activity = (ConversationActivity) getActivity();
|
ConversationActivity activity = (ConversationActivity) getActivity();
|
||||||
activity.xmppConnectionService.sendMessage(conversation.getAccount(), message,
|
activity.xmppConnectionService.sendMessage(conversation.getAccount(),
|
||||||
null);
|
message, null);
|
||||||
chatMsg.setText("");
|
chatMsg.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,9 +344,13 @@ public class ConversationFragment extends Fragment {
|
||||||
conversation.getAccount(), message, null);
|
conversation.getAccount(), message, null);
|
||||||
chatMsg.setText("");
|
chatMsg.setText("");
|
||||||
} else {
|
} else {
|
||||||
Hashtable<String, Integer> presences = conversation
|
Hashtable<String, Integer> presences;
|
||||||
.getContact().getPresences();
|
if (conversation.getContact() != null) {
|
||||||
if (presences.size() == 0) {
|
presences = conversation.getContact().getPresences();
|
||||||
|
} else {
|
||||||
|
presences = null;
|
||||||
|
}
|
||||||
|
if ((presences != null) && (presences.size() == 0)) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(
|
AlertDialog.Builder builder = new AlertDialog.Builder(
|
||||||
getActivity());
|
getActivity());
|
||||||
builder.setTitle("Contact is offline");
|
builder.setTitle("Contact is offline");
|
||||||
|
@ -330,16 +365,15 @@ public class ConversationFragment extends Fragment {
|
||||||
conversation.nextMessageEncryption = Message.ENCRYPTION_NONE;
|
conversation.nextMessageEncryption = Message.ENCRYPTION_NONE;
|
||||||
message.setEncryption(Message.ENCRYPTION_NONE);
|
message.setEncryption(Message.ENCRYPTION_NONE);
|
||||||
xmppService.sendMessage(
|
xmppService.sendMessage(
|
||||||
conversation.getAccount(),
|
conversation.getAccount(), message,
|
||||||
message, null);
|
null);
|
||||||
chatMsg.setText("");
|
chatMsg.setText("");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
builder.setNegativeButton("Cancel", null);
|
builder.setNegativeButton("Cancel", null);
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
} else if (presences.size() == 1) {
|
} else if (presences.size() == 1) {
|
||||||
xmppService.sendMessage(conversation.getAccount(),
|
xmppService.sendMessage(conversation.getAccount(), message,
|
||||||
message,
|
|
||||||
(String) presences.keySet().toArray()[0]);
|
(String) presences.keySet().toArray()[0]);
|
||||||
chatMsg.setText("");
|
chatMsg.setText("");
|
||||||
} else {
|
} else {
|
||||||
|
@ -348,16 +382,51 @@ public class ConversationFragment extends Fragment {
|
||||||
builder.setTitle("Choose Presence");
|
builder.setTitle("Choose Presence");
|
||||||
final String[] presencesArray = new String[presences.size()];
|
final String[] presencesArray = new String[presences.size()];
|
||||||
presences.keySet().toArray(presencesArray);
|
presences.keySet().toArray(presencesArray);
|
||||||
builder.setItems(presencesArray, new DialogInterface.OnClickListener() {
|
builder.setItems(presencesArray,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog,
|
||||||
xmppService.sendMessage(conversation.getAccount(), message, presencesArray[which]);
|
int which) {
|
||||||
chatMsg.setText("");
|
xmppService.sendMessage(
|
||||||
}
|
conversation.getAccount(), message,
|
||||||
});
|
presencesArray[which]);
|
||||||
|
chatMsg.setText("");
|
||||||
|
}
|
||||||
|
});
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ViewHolder {
|
||||||
|
|
||||||
|
protected TextView time;
|
||||||
|
protected TextView messageBody;
|
||||||
|
protected ImageView imageView;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BitmapCache {
|
||||||
|
private HashMap<String, Bitmap> bitmaps = new HashMap<String, Bitmap>();
|
||||||
|
public Bitmap get(String name, Uri uri) {
|
||||||
|
if (bitmaps.containsKey(name)) {
|
||||||
|
return bitmaps.get(name);
|
||||||
|
} else {
|
||||||
|
Bitmap bm;
|
||||||
|
if (uri!=null) {
|
||||||
|
try {
|
||||||
|
bm = BitmapFactory.decodeStream(getActivity()
|
||||||
|
.getContentResolver().openInputStream(uri));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
bm = UIHelper.getUnknownContactPicture(name, 200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bm = UIHelper.getUnknownContactPicture(name, 200);
|
||||||
|
}
|
||||||
|
bitmaps.put(name, bm);
|
||||||
|
return bm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
package de.gultsch.chat.utils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import net.java.otr4j.session.Session;
|
||||||
|
import net.java.otr4j.session.SessionStatus;
|
||||||
|
import android.util.Log;
|
||||||
|
import de.gultsch.chat.entities.Account;
|
||||||
|
import de.gultsch.chat.entities.Conversation;
|
||||||
|
import de.gultsch.chat.entities.Message;
|
||||||
|
import de.gultsch.chat.services.XmppConnectionService;
|
||||||
|
import de.gultsch.chat.xml.Element;
|
||||||
|
import de.gultsch.chat.xmpp.MessagePacket;
|
||||||
|
|
||||||
|
public class MessageParser {
|
||||||
|
|
||||||
|
protected static final String LOGTAG = "xmppService";
|
||||||
|
|
||||||
|
public static Message parsePlainTextChat(MessagePacket packet, Account account, XmppConnectionService service) {
|
||||||
|
String[] fromParts = packet.getFrom().split("/");
|
||||||
|
Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
|
||||||
|
String body = packet.getBody();
|
||||||
|
return new Message(conversation, packet.getFrom(), body, Message.ENCRYPTION_NONE, Message.STATUS_RECIEVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message parseOtrChat(MessagePacket packet, Account account, XmppConnectionService service) {
|
||||||
|
String[] fromParts = packet.getFrom().split("/");
|
||||||
|
Conversation conversation = service.findOrCreateConversation(account, fromParts[0],false);
|
||||||
|
String body = packet.getBody();
|
||||||
|
if (!conversation.hasValidOtrSession()) {
|
||||||
|
conversation.startOtrSession(service.getApplicationContext(), fromParts[1]);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Session otrSession = conversation.getOtrSession();
|
||||||
|
SessionStatus before = otrSession
|
||||||
|
.getSessionStatus();
|
||||||
|
body = otrSession.transformReceiving(body);
|
||||||
|
SessionStatus after = otrSession.getSessionStatus();
|
||||||
|
if ((before != after)
|
||||||
|
&& (after == SessionStatus.ENCRYPTED)) {
|
||||||
|
Log.d(LOGTAG, "otr session etablished");
|
||||||
|
List<Message> messages = conversation
|
||||||
|
.getMessages();
|
||||||
|
for (int i = 0; i < messages.size(); ++i) {
|
||||||
|
Message msg = messages.get(i);
|
||||||
|
if ((msg.getStatus() == Message.STATUS_UNSEND)
|
||||||
|
&& (msg.getEncryption() == Message.ENCRYPTION_OTR)) {
|
||||||
|
MessagePacket outPacket = service.prepareMessagePacket(
|
||||||
|
account, msg, otrSession);
|
||||||
|
msg.setStatus(Message.STATUS_SEND);
|
||||||
|
service.databaseBackend.updateMessage(msg);
|
||||||
|
account.getXmppConnection()
|
||||||
|
.sendMessagePacket(outPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (service.convChangedListener!=null) {
|
||||||
|
service.convChangedListener.onConversationListChanged();
|
||||||
|
}
|
||||||
|
} else if ((before != after) && (after == SessionStatus.FINISHED)) {
|
||||||
|
conversation.resetOtrSession();
|
||||||
|
Log.d(LOGTAG,"otr session stoped");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(LOGTAG, "error receiving otr. resetting");
|
||||||
|
conversation.resetOtrSession();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (body == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Message(conversation, packet.getFrom(), body, Message.ENCRYPTION_OTR,Message.STATUS_RECIEVED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message parseGroupchat(MessagePacket packet, Account account, XmppConnectionService service) {
|
||||||
|
int status;
|
||||||
|
String[] fromParts = packet.getFrom().split("/");
|
||||||
|
Conversation conversation = service.findOrCreateConversation(account, fromParts[0],true);
|
||||||
|
if ((fromParts.length == 1) || (packet.hasChild("subject"))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String counterPart = fromParts[1];
|
||||||
|
if (counterPart.equals(account.getUsername())) {
|
||||||
|
status = Message.STATUS_SEND;
|
||||||
|
} else {
|
||||||
|
status = Message.STATUS_RECIEVED;
|
||||||
|
}
|
||||||
|
return new Message(conversation, counterPart, packet.getBody(), Message.ENCRYPTION_NONE, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message parseCarbonMessage(MessagePacket packet,
|
||||||
|
Account account, XmppConnectionService service) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
int status;
|
||||||
|
String fullJid;
|
||||||
|
Element forwarded;
|
||||||
|
if (packet.hasChild("received")) {
|
||||||
|
forwarded = packet.findChild("received").findChild(
|
||||||
|
"forwarded");
|
||||||
|
status = Message.STATUS_RECIEVED;
|
||||||
|
} else if (packet.hasChild("sent")) {
|
||||||
|
forwarded = packet.findChild("sent").findChild(
|
||||||
|
"forwarded");
|
||||||
|
status = Message.STATUS_SEND;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Element message = forwarded.findChild("message");
|
||||||
|
if ((message == null) || (!message.hasChild("body")))
|
||||||
|
return null; // either malformed or boring
|
||||||
|
if (status == Message.STATUS_RECIEVED) {
|
||||||
|
fullJid = message.getAttribute("from");
|
||||||
|
} else {
|
||||||
|
fullJid = message.getAttribute("to");
|
||||||
|
}
|
||||||
|
String[] parts = fullJid.split("/");
|
||||||
|
Conversation conversation = service.findOrCreateConversation(account, parts[0],false);
|
||||||
|
return new Message(conversation,fullJid, message.findChild("body").getContent(), Message.ENCRYPTION_NONE,status);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package de.gultsch.chat.utils;
|
package de.gultsch.chat.utils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
@ -11,12 +10,17 @@ import android.content.Loader.OnLoadCompleteListener;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Looper;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.provider.ContactsContract.Profile;
|
import android.provider.ContactsContract.Profile;
|
||||||
|
|
||||||
public class PhoneHelper {
|
public class PhoneHelper {
|
||||||
|
|
||||||
public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) {
|
public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) {
|
||||||
|
if (Looper.myLooper()==null) {
|
||||||
|
Looper.prepare();
|
||||||
|
}
|
||||||
|
final Looper mLooper = Looper.myLooper();
|
||||||
final Hashtable<String, Bundle> phoneContacts = new Hashtable<String, Bundle>();
|
final Hashtable<String, Bundle> phoneContacts = new Hashtable<String, Bundle>();
|
||||||
|
|
||||||
final String[] PROJECTION = new String[] {
|
final String[] PROJECTION = new String[] {
|
||||||
|
@ -61,6 +65,7 @@ public class PhoneHelper {
|
||||||
if (listener!=null) {
|
if (listener!=null) {
|
||||||
listener.onPhoneContactsLoaded(phoneContacts);
|
listener.onPhoneContactsLoaded(phoneContacts);
|
||||||
}
|
}
|
||||||
|
mLooper.quit();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mCursorLoader.startLoading();
|
mCursorLoader.startLoading();
|
||||||
|
|
|
@ -59,6 +59,10 @@ public class XmlReader {
|
||||||
for(int i = 0; i < parser.getAttributeCount(); ++i) {
|
for(int i = 0; i < parser.getAttributeCount(); ++i) {
|
||||||
tag.setAttribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
tag.setAttribute(parser.getAttributeName(i), parser.getAttributeValue(i));
|
||||||
}
|
}
|
||||||
|
String xmlns = parser.getNamespace();
|
||||||
|
if (xmlns!=null) {
|
||||||
|
tag.setAttribute("xmlns",xmlns);
|
||||||
|
}
|
||||||
return tag;
|
return tag;
|
||||||
} else if (parser.getEventType() == XmlPullParser.END_TAG) {
|
} else if (parser.getEventType() == XmlPullParser.END_TAG) {
|
||||||
Tag tag = Tag.end(parser.getName());
|
Tag tag = Tag.end(parser.getName());
|
||||||
|
|
Loading…
Reference in New Issue