add contact to roster if a new conversation is created

This commit is contained in:
Daniel Gultsch 2014-02-23 21:33:37 +01:00
parent 4bffb4d94d
commit bfee69b00b
4 changed files with 109 additions and 75 deletions

View File

@ -1,22 +1,23 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory <PreferenceCategory
android:title="Security"> android:title="Security and Privacy Options">
<CheckBoxPreference
android:key="trust_unknown_tls_certificates"
android:title="Trust TLS certificates"
android:summary="Accounts with untrusted certificates simply will not connect to server"
/>
<ListPreference <ListPreference
android:key="default_conversation_encryption_type" android:key="default_conversation_encryption_type"
android:title="Default conversation encryption" android:title="Default conversation encryption"
android:dialogTitle="Default conversation encryption" android:dialogTitle="Default conversation encryption"
android:entries="@array/conversation_encryption_type_entries" android:entries="@array/conversation_encryption_type_entries"
android:entryValues="@array/conversation_encryption_type_values" android:entryValues="@array/conversation_encryption_type_values"
android:defaultValue="pgp"/> android:defaultValue="none"/>
<CheckBoxPreference
android:key="grant_new_contacts"
android:title="Grant presence updates"
android:summary="Preemptivly grant and ask for presence subscription for contacts you created"
android:defaultValue="true"
/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="Notification settings"> android:title="Notification Settings">
<CheckBoxPreference <CheckBoxPreference
android:key="show_notification" android:key="show_notification"
android:title="Notification" android:title="Notification"
@ -33,9 +34,13 @@
android:ringtoneType="notification" android:ringtoneType="notification"
android:dependency="show_notification" android:dependency="show_notification"
android:summary="Play ringtone with notification"/> android:summary="Play ringtone with notification"/>
<CheckBoxPreference
android:key="notify_in_conversation_when_highlighted"
android:title="Conference notification"
android:summary="Always notify when a new conference message arrives instead of only when highlighted"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="Advanced settings"> android:title="UI Options">
<CheckBoxPreference <CheckBoxPreference
android:key="show_phone_selfcontact_picture" android:key="show_phone_selfcontact_picture"
android:title="Use Phones self contact picture" android:title="Use Phones self contact picture"

View File

@ -38,6 +38,8 @@ public class Contact extends AbstractEntity implements Serializable {
protected Presences presences = new Presences(); protected Presences presences = new Presences();
protected Account account; protected Account account;
protected boolean inRoster = true;
public Contact(Account account, String displayName, String jid, public Contact(Account account, String displayName, String jid,
String photoUri) { String photoUri) {
@ -262,4 +264,13 @@ public class Contact extends AbstractEntity implements Serializable {
public static final int ASKING = 2; public static final int ASKING = 2;
public static final int PREEMPTIVE_GRANT = 4; public static final int PREEMPTIVE_GRANT = 4;
} }
public void flagAsNotInRoster() {
this.inRoster = false;
}
public boolean isInRoster() {
return this.inRoster;
}
} }

View File

@ -40,12 +40,14 @@ import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.database.DatabaseUtils; 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;
import android.os.PowerManager; import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.util.Log; import android.util.Log;
@ -104,7 +106,7 @@ public class XmppConnectionService extends Service {
notify = (message.getStatus() == Message.STATUS_RECIEVED); notify = (message.getStatus() == Message.STATUS_RECIEVED);
} }
} else if (packet.getType() == MessagePacket.TYPE_ERROR) { } else if (packet.getType() == MessagePacket.TYPE_ERROR) {
message = MessageParser.parseError(packet,account,service); message = MessageParser.parseError(packet, account, service);
} else { } else {
Log.d(LOGTAG, "unparsed message " + packet.toString()); Log.d(LOGTAG, "unparsed message " + packet.toString());
} }
@ -175,7 +177,8 @@ public class XmppConnectionService extends Service {
Contact contact = findContact(account, fromParts[0]); Contact contact = findContact(account, fromParts[0]);
if (contact == null) { if (contact == null) {
// most likely muc, self or roster not synced // most likely muc, self or roster not synced
Log.d(LOGTAG,"got presence for non contact "+packet.toString()); Log.d(LOGTAG,
"got presence for non contact " + packet.toString());
return; return;
} }
String type = packet.getAttribute("type"); String type = packet.getAttribute("type");
@ -201,21 +204,26 @@ public class XmppConnectionService extends Service {
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
} }
} else if (type.equals("subscribe")) { } else if (type.equals("subscribe")) {
Log.d(LOGTAG,account.getJid()+": "+contact.getJid()+" asked to subscribe"); if (contact
if (contact.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) { .getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
Log.d(LOGTAG,"preemptive grant existed. granting");
sendPresenceUpdatesTo(contact); sendPresenceUpdatesTo(contact);
contact.setSubscriptionOption(Contact.Subscription.FROM); contact.setSubscriptionOption(Contact.Subscription.FROM);
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT); contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
replaceContactInConversation(contact.getJid(), contact); replaceContactInConversation(contact.getJid(), contact);
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
if ((contact
.getSubscriptionOption(Contact.Subscription.ASKING))
&& (!contact
.getSubscriptionOption(Contact.Subscription.TO))) {
requestPresenceUpdatesFrom(contact);
}
} else { } else {
//TODO: ask user to handle it maybe // TODO: ask user to handle it maybe
} }
} else { } else {
Log.d(LOGTAG,packet.toString()); Log.d(LOGTAG, packet.toString());
} }
replaceContactInConversation(contact.getJid(),contact); replaceContactInConversation(contact.getJid(), contact);
} }
}; };
@ -257,7 +265,7 @@ public class XmppConnectionService extends Service {
} else { } else {
contact.parseSubscriptionFromElement(item); contact.parseSubscriptionFromElement(item);
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
replaceContactInConversation(contact.getJid(),contact); replaceContactInConversation(contact.getJid(), contact);
} }
} }
} }
@ -456,48 +464,44 @@ public class XmppConnectionService extends Service {
if (roster != null) { if (roster != null) {
String version = roster.getAttribute("ver"); String version = roster.getAttribute("ver");
processRosterItems(account, roster); processRosterItems(account, roster);
if (version!=null) { StringBuilder mWhere = new StringBuilder();
account.setRosterVersion(version); mWhere.append("jid NOT IN(");
databaseBackend.updateAccount(account); List<Element> items = roster.getChildren();
} else { for (int i = 0; i < items.size(); ++i) {
StringBuilder mWhere = new StringBuilder(); mWhere.append(DatabaseUtils
mWhere.append("jid NOT IN("); .sqlEscapeString(items.get(i)
List<Element> items = roster.getChildren(); .getAttribute("jid")));
for(int i = 0; i < items.size(); ++i) { if (i != items.size() - 1) {
mWhere.append(DatabaseUtils.sqlEscapeString(items.get(i).getAttribute("jid"))); mWhere.append(",");
if (i != items.size() - 1) {
mWhere.append(",");
}
}
mWhere.append(") and accountUuid = \"");
mWhere.append(account.getUuid());
mWhere.append("\"");
Log.d(LOGTAG,mWhere.toString());
List<Contact> contactsToDelete = databaseBackend.getContats(mWhere.toString());
for(Contact contact : contactsToDelete) {
databaseBackend.deleteContact(contact);
replaceContactInConversation(contact.getJid(), null);
} }
} }
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() { mWhere.append(") and accountUuid = \"");
mWhere.append(account.getUuid());
@Override mWhere.append("\"");
public void phoneContactsMerged() { List<Contact> contactsToDelete = databaseBackend
if (listener != null) { .getContats(mWhere.toString());
getRoster(account, listener); for (Contact contact : contactsToDelete) {
} databaseBackend.deleteContact(contact);
} replaceContactInConversation(contact.getJid(),
}); null);
} else {
if (listener != null) {
getRoster(account, listener);
} }
} }
mergePhoneContactsWithRoster(new OnPhoneContactsMerged() {
@Override
public void phoneContactsMerged() {
if (listener != null) {
getRoster(account, listener);
}
}
});
} }
}); });
} }
public void mergePhoneContactsWithRoster(final OnPhoneContactsMerged listener) { public void mergePhoneContactsWithRoster(
final OnPhoneContactsMerged listener) {
PhoneHelper.loadPhoneContacts(getApplicationContext(), PhoneHelper.loadPhoneContacts(getApplicationContext(),
new OnPhoneContactsLoadedListener() { new OnPhoneContactsLoadedListener() {
@Override @Override
@ -520,18 +524,20 @@ public class XmppConnectionService extends Service {
contact.setDisplayName(phoneContact contact.setDisplayName(phoneContact
.getString("displayname")); .getString("displayname"));
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
replaceContactInConversation(contact.getJid(), contact); replaceContactInConversation(contact.getJid(),
contact);
} else { } else {
if ((contact.getSystemAccount() != null) if ((contact.getSystemAccount() != null)
|| (contact.getProfilePhoto() != null)) { || (contact.getProfilePhoto() != null)) {
contact.setSystemAccount(null); contact.setSystemAccount(null);
contact.setPhotoUri(null); contact.setPhotoUri(null);
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
replaceContactInConversation(contact.getJid(), contact); replaceContactInConversation(
contact.getJid(), contact);
} }
} }
} }
if (listener!=null) { if (listener != null) {
listener.phoneContactsMerged(); listener.phoneContactsMerged();
} }
} }
@ -562,7 +568,7 @@ public class XmppConnectionService extends Service {
public Contact findContact(Account account, String jid) { public Contact findContact(Account account, String jid) {
Contact contact = databaseBackend.findContact(account, jid); Contact contact = databaseBackend.findContact(account, jid);
if (contact!=null) { if (contact != null) {
contact.setAccount(account); contact.setAccount(account);
} }
return contact; return contact;
@ -650,7 +656,7 @@ public class XmppConnectionService extends Service {
if (accountChangedListener != null) if (accountChangedListener != null)
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
public void deleteContact(Contact contact) { public void deleteContact(Contact contact) {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element query = new Element("query"); Element query = new Element("query");
@ -772,6 +778,14 @@ public class XmppConnectionService extends Service {
} }
public void createContact(Contact contact) { public void createContact(Contact contact) {
SharedPreferences sharedPref = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
boolean autoGrant = sharedPref.getBoolean("grant_new_contacts", true);
if (autoGrant) {
contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
contact.setSubscriptionOption(Contact.Subscription.ASKING);
}
databaseBackend.createContact(contact);
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
Element query = new Element("query"); Element query = new Element("query");
query.setAttribute("xmlns", "jabber:iq:roster"); query.setAttribute("xmlns", "jabber:iq:roster");
@ -781,49 +795,50 @@ public class XmppConnectionService extends Service {
query.addChild(item); query.addChild(item);
iq.addChild(query); iq.addChild(query);
Account account = contact.getAccount(); Account account = contact.getAccount();
Log.d(LOGTAG,account.getJid()+": adding "+contact.getJid()+" to roster");
account.getXmppConnection().sendIqPacket(iq, null); account.getXmppConnection().sendIqPacket(iq, null);
if (autoGrant) {
requestPresenceUpdatesFrom(contact);
}
replaceContactInConversation(contact.getJid(), contact); replaceContactInConversation(contact.getJid(), contact);
databaseBackend.createContact(contact);
} }
public void requestPresenceUpdatesFrom(Contact contact) { public void requestPresenceUpdatesFrom(Contact contact) {
//Requesting a Subscription type=subscribe // Requesting a Subscription type=subscribe
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "subscribe"); packet.setAttribute("type", "subscribe");
packet.setAttribute("to", contact.getJid()); packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid()); packet.setAttribute("from", contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString()); Log.d(LOGTAG, packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet); contact.getAccount().getXmppConnection().sendPresencePacket(packet);
} }
public void stopPresenceUpdatesFrom(Contact contact) { public void stopPresenceUpdatesFrom(Contact contact) {
//Unsubscribing type='unsubscribe' // Unsubscribing type='unsubscribe'
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "unsubscribe"); packet.setAttribute("type", "unsubscribe");
packet.setAttribute("to", contact.getJid()); packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid()); packet.setAttribute("from", contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString()); Log.d(LOGTAG, packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet); contact.getAccount().getXmppConnection().sendPresencePacket(packet);
} }
public void stopPresenceUpdatesTo(Contact contact) { public void stopPresenceUpdatesTo(Contact contact) {
//Canceling a Subscription type=unsubscribed // Canceling a Subscription type=unsubscribed
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "unsubscribed"); packet.setAttribute("type", "unsubscribed");
packet.setAttribute("to", contact.getJid()); packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid()); packet.setAttribute("from", contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString()); Log.d(LOGTAG, packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet); contact.getAccount().getXmppConnection().sendPresencePacket(packet);
} }
public void sendPresenceUpdatesTo(Contact contact) { public void sendPresenceUpdatesTo(Contact contact) {
//type='subscribed' // type='subscribed'
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "subscribed"); packet.setAttribute("type", "subscribed");
packet.setAttribute("to", contact.getJid()); packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid()); packet.setAttribute("from", contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString()); Log.d(LOGTAG, packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet); contact.getAccount().getXmppConnection().sendPresencePacket(packet);
} }
} }

View File

@ -79,6 +79,7 @@ public class NewConversationActivity extends XmppActivity {
if (Validator.isValidJid(searchString)) { if (Validator.isValidJid(searchString)) {
String name = searchString.split("@")[0]; String name = searchString.split("@")[0];
Contact newContact = new Contact(null, name, searchString, null); Contact newContact = new Contact(null, name, searchString, null);
newContact.flagAsNotInRoster();
aggregatedContacts.add(newContact); aggregatedContacts.add(newContact);
contactsHeader.setText("Create new contact"); contactsHeader.setText("Create new contact");
} else { } else {
@ -228,7 +229,9 @@ public class NewConversationActivity extends XmppActivity {
} }
public void startConversation(Contact contact, Account account, boolean muc) { public void startConversation(Contact contact, Account account, boolean muc) {
Log.d("xmppService","starting conversation for account:"+account.getJid()+" and contact:"+contact.getJid()); if (!contact.isInRoster()) {
xmppConnectionService.createContact(contact);
}
Conversation conversation = xmppConnectionService Conversation conversation = xmppConnectionService
.findOrCreateConversation(account, contact.getJid(), muc); .findOrCreateConversation(account, contact.getJid(), muc);