subscription mgmt works

This commit is contained in:
Daniel Gultsch 2014-02-21 21:35:23 +01:00
parent b71bfbaa9d
commit b8e85a2846
4 changed files with 199 additions and 34 deletions

View file

@ -9,6 +9,8 @@ import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import de.gultsch.chat.xml.Element;
import android.content.ContentValues; import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
@ -29,7 +31,7 @@ public class Contact extends AbstractEntity implements Serializable {
protected String accountUuid; protected String accountUuid;
protected String displayName; protected String displayName;
protected String jid; protected String jid;
protected String subscription; protected int subscription = 0;
protected String systemAccount; protected String systemAccount;
protected String photoUri; protected String photoUri;
protected JSONObject keys = new JSONObject(); protected JSONObject keys = new JSONObject();
@ -52,7 +54,7 @@ public class Contact extends AbstractEntity implements Serializable {
} }
public Contact(String uuid, String account, String displayName, String jid, public Contact(String uuid, String account, String displayName, String jid,
String subscription, String photoUri, String systemAccount, int subscription, String photoUri, String systemAccount,
String keys, String presences) { String keys, String presences) {
this.uuid = uuid; this.uuid = uuid;
this.accountUuid = account; this.accountUuid = account;
@ -109,18 +111,14 @@ public class Contact extends AbstractEntity implements Serializable {
cursor.getString(cursor.getColumnIndex(ACCOUNT)), cursor.getString(cursor.getColumnIndex(ACCOUNT)),
cursor.getString(cursor.getColumnIndex(DISPLAYNAME)), cursor.getString(cursor.getColumnIndex(DISPLAYNAME)),
cursor.getString(cursor.getColumnIndex(JID)), cursor.getString(cursor.getColumnIndex(JID)),
cursor.getString(cursor.getColumnIndex(SUBSCRIPTION)), cursor.getInt(cursor.getColumnIndex(SUBSCRIPTION)),
cursor.getString(cursor.getColumnIndex(PHOTOURI)), cursor.getString(cursor.getColumnIndex(PHOTOURI)),
cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)), cursor.getString(cursor.getColumnIndex(SYSTEMACCOUNT)),
cursor.getString(cursor.getColumnIndex(KEYS)), cursor.getString(cursor.getColumnIndex(KEYS)),
cursor.getString(cursor.getColumnIndex(PRESENCES))); cursor.getString(cursor.getColumnIndex(PRESENCES)));
} }
public void setSubscription(String subscription) { public int getSubscription() {
this.subscription = subscription;
}
public String getSubscription() {
return this.subscription; return this.subscription;
} }
@ -220,4 +218,48 @@ public class Contact extends AbstractEntity implements Serializable {
} }
} }
public void setSubscriptionOption(int option) {
this.subscription |= 1 << option;
}
public void resetSubscriptionOption(int option) {
this.subscription &= ~(1 << option);
}
public boolean getSubscriptionOption(int option) {
return ((this.subscription & (1 << option)) != 0);
}
public void parseSubscriptionFromElement(Element item) {
String ask = item.getAttribute("ask");
String subscription = item.getAttribute("subscription");
if (subscription!=null) {
if (subscription.equals("to")) {
this.resetSubscriptionOption(Contact.Subscription.FROM);
this.setSubscriptionOption(Contact.Subscription.TO);
} else if (subscription.equals("from")) {
this.resetSubscriptionOption(Contact.Subscription.TO);
this.setSubscriptionOption(Contact.Subscription.FROM);
} else if (subscription.equals("both")) {
this.setSubscriptionOption(Contact.Subscription.TO);
this.setSubscriptionOption(Contact.Subscription.FROM);
}
}
if ((ask!=null)&&(ask.equals("subscribe"))) {
this.setSubscriptionOption(Contact.Subscription.ASKING);
} else {
this.resetSubscriptionOption(Contact.Subscription.ASKING);
}
}
public class Subscription {
public static final int TO = 0;
public static final int FROM = 1;
public static final int ASKING = 2;
public static final int PREEMPTIVE_GRANT = 4;
}
} }

View file

@ -58,7 +58,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
+ Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT," + Contact.DISPLAYNAME + " TEXT," + Contact.JID + " TEXT,"
+ Contact.PRESENCES + " TEXT, " + Contact.KEYS + Contact.PRESENCES + " TEXT, " + Contact.KEYS
+ " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION + " TEXT," + Contact.PHOTOURI + " TEXT," + Contact.SUBSCRIPTION
+ " TEXT," + Contact.SYSTEMACCOUNT + " NUMBER, " + " NUMBER," + Contact.SYSTEMACCOUNT + " NUMBER, "
+ "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES " + "FOREIGN KEY(" + Contact.ACCOUNT + ") REFERENCES "
+ Account.TABLENAME + "(" + Account.UUID + Account.TABLENAME + "(" + Account.UUID
+ ") ON DELETE CASCADE);"); + ") ON DELETE CASCADE);");

View file

@ -200,6 +200,20 @@ public class XmppConnectionService extends Service {
contact.removePresence(fromParts[1]); contact.removePresence(fromParts[1]);
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
} }
} else if (type.equals("subscribe")) {
Log.d(LOGTAG,account.getJid()+": "+contact.getJid()+" asked to subscribe");
if (contact.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
Log.d(LOGTAG,"preemptive grant existed. granting");
sendPresenceUpdatesTo(contact);
contact.setSubscriptionOption(Contact.Subscription.FROM);
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
replaceContactInConversation(contact.getJid(), contact);
databaseBackend.updateContact(contact);
} else {
//TODO: ask user to handle it maybe
}
} else {
Log.d(LOGTAG,packet.toString());
} }
replaceContactInConversation(contact.getJid(),contact); replaceContactInConversation(contact.getJid(),contact);
} }
@ -227,19 +241,21 @@ public class XmppConnectionService extends Service {
String subscription = item.getAttribute("subscription"); String subscription = item.getAttribute("subscription");
Contact contact = databaseBackend.findContact(account, jid); Contact contact = databaseBackend.findContact(account, jid);
if (contact == null) { if (contact == null) {
if (!subscription.equals("remove")) {
String name = item.getAttribute("name"); String name = item.getAttribute("name");
if (name == null) { if (name == null) {
name = jid.split("@")[0]; name = jid.split("@")[0];
} }
contact = new Contact(account, name, jid, null); contact = new Contact(account, name, jid, null);
contact.setSubscription(subscription); contact.parseSubscriptionFromElement(item);
databaseBackend.createContact(contact); databaseBackend.createContact(contact);
}
} else { } else {
if (subscription.equals("remove")) { if (subscription.equals("remove")) {
databaseBackend.deleteContact(contact); databaseBackend.deleteContact(contact);
replaceContactInConversation(contact.getJid(), null); replaceContactInConversation(contact.getJid(), null);
} else { } else {
contact.setSubscription(subscription); contact.parseSubscriptionFromElement(item);
databaseBackend.updateContact(contact); databaseBackend.updateContact(contact);
replaceContactInConversation(contact.getJid(),contact); replaceContactInConversation(contact.getJid(),contact);
} }
@ -506,12 +522,14 @@ 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);
} 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);
} }
} }
} }
@ -545,7 +563,11 @@ public class XmppConnectionService extends Service {
} }
public Contact findContact(Account account, String jid) { public Contact findContact(Account account, String jid) {
return databaseBackend.findContact(account, jid); Contact contact = databaseBackend.findContact(account, jid);
if (contact!=null) {
contact.setAccount(account);
}
return contact;
} }
public Conversation findOrCreateConversation(Account account, String jid, public Conversation findOrCreateConversation(Account account, String jid,
@ -766,4 +788,44 @@ public class XmppConnectionService extends Service {
replaceContactInConversation(contact.getJid(), contact); replaceContactInConversation(contact.getJid(), contact);
databaseBackend.createContact(contact); databaseBackend.createContact(contact);
} }
public void requestPresenceUpdatesFrom(Contact contact) {
//Requesting a Subscription type=subscribe
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "subscribe");
packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet);
}
public void stopPresenceUpdatesFrom(Contact contact) {
//Unsubscribing type='unsubscribe'
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "unsubscribe");
packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet);
}
public void stopPresenceUpdatesTo(Contact contact) {
//Canceling a Subscription type=unsubscribed
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "unsubscribed");
packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet);
}
public void sendPresenceUpdatesTo(Contact contact) {
//type='subscribed'
PresencePacket packet = new PresencePacket();
packet.setAttribute("type", "subscribed");
packet.setAttribute("to", contact.getJid());
packet.setAttribute("from",contact.getAccount().getJid());
Log.d(LOGTAG,packet.toString());
contact.getAccount().getXmppConnection().sendPresencePacket(packet);
}
} }

View file

@ -13,6 +13,7 @@ import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds; import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents; import android.provider.ContactsContract.Intents;
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;
@ -28,6 +29,9 @@ public class DialogContactDetails extends DialogFragment {
private DialogContactDetails mDetailsDialog = this; private DialogContactDetails mDetailsDialog = this;
private XmppActivity activity; private XmppActivity activity;
private CheckBox send;
private CheckBox receive;
private DialogInterface.OnClickListener askRemoveFromRoster = new DialogInterface.OnClickListener() { private DialogInterface.OnClickListener askRemoveFromRoster = new DialogInterface.OnClickListener() {
@Override @Override
@ -64,6 +68,58 @@ public class DialogContactDetails extends DialogFragment {
} }
}; };
private DialogInterface.OnClickListener updateSubscriptions = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
boolean needsUpdating = false;
if (contact.getSubscriptionOption(Contact.Subscription.FROM)) {
if (!send.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.FROM);
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
activity.xmppConnectionService.stopPresenceUpdatesTo(contact);
needsUpdating=true;
}
} else {
if (contact.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
if (!send.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
needsUpdating=true;
}
} else {
if (send.isChecked()) {
contact.setSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT);
needsUpdating=true;
}
}
}
if (contact.getSubscriptionOption(Contact.Subscription.TO)) {
if (!receive.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.TO);
activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
needsUpdating=true;
}
} else {
if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) {
if (!receive.isChecked()) {
contact.resetSubscriptionOption(Contact.Subscription.ASKING);
activity.xmppConnectionService.stopPresenceUpdatesFrom(contact);
needsUpdating=true;
}
} else {
if (receive.isChecked()) {
contact.setSubscriptionOption(Contact.Subscription.ASKING);
activity.xmppConnectionService.requestPresenceUpdatesFrom(contact);
needsUpdating=true;
}
}
}
if (needsUpdating) {
activity.xmppConnectionService.updateContact(contact);
}
}
};
public void setContact(Contact contact) { public void setContact(Contact contact) {
this.contact = contact; this.contact = contact;
} }
@ -77,21 +133,29 @@ public class DialogContactDetails extends DialogFragment {
TextView contactJid = (TextView) view.findViewById(R.id.details_contactjid); TextView contactJid = (TextView) view.findViewById(R.id.details_contactjid);
TextView accountJid = (TextView) view.findViewById(R.id.details_account); TextView accountJid = (TextView) view.findViewById(R.id.details_account);
TextView status = (TextView) view.findViewById(R.id.details_contactstatus); TextView status = (TextView) view.findViewById(R.id.details_contactstatus);
CheckBox send = (CheckBox) view.findViewById(R.id.details_send_presence); send = (CheckBox) view.findViewById(R.id.details_send_presence);
CheckBox receive = (CheckBox) view.findViewById(R.id.details_receive_presence); receive = (CheckBox) view.findViewById(R.id.details_receive_presence);
//ImageView contactPhoto = (ImageView) view.findViewById(R.id.details_contact_picture); //ImageView contactPhoto = (ImageView) view.findViewById(R.id.details_contact_picture);
QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.details_contact_badge); QuickContactBadge badge = (QuickContactBadge) view.findViewById(R.id.details_contact_badge);
boolean subscriptionSend = false; if (contact.getSubscriptionOption(Contact.Subscription.FROM)) {
boolean subscriptionReceive = false; send.setChecked(true);
if (contact.getSubscription()!=null) { } else {
if (contact.getSubscription().equals("both")) { send.setText("Preemptively grant subscription request");
subscriptionReceive = true; if (contact.getSubscriptionOption(Contact.Subscription.PREEMPTIVE_GRANT)) {
subscriptionSend = true; send.setChecked(true);
} else if (contact.getSubscription().equals("from")) { } else {
subscriptionSend = true; send.setChecked(false);
} else if (contact.getSubscription().equals("to")) { }
subscriptionReceive = true; }
if (contact.getSubscriptionOption(Contact.Subscription.TO)) {
receive.setChecked(true);
} else {
receive.setText("Request presence updates");
if (contact.getSubscriptionOption(Contact.Subscription.ASKING)) {
receive.setChecked(true);
} else {
receive.setChecked(false);
} }
} }
@ -125,9 +189,6 @@ public class DialogContactDetails extends DialogFragment {
status.setTextColor(0xFFe92727); status.setTextColor(0xFFe92727);
break; break;
} }
send.setChecked(subscriptionSend);
receive.setChecked(subscriptionReceive);
contactJid.setText(contact.getJid()); contactJid.setText(contact.getJid());
accountJid.setText(contact.getAccount().getJid()); accountJid.setText(contact.getAccount().getJid());
@ -151,7 +212,7 @@ public class DialogContactDetails extends DialogFragment {
builder.setView(view); builder.setView(view);
builder.setTitle(contact.getDisplayName()); builder.setTitle(contact.getDisplayName());
builder.setNeutralButton("Done", null); builder.setNeutralButton("Done", this.updateSubscriptions);
builder.setPositiveButton("Remove from roster", this.askRemoveFromRoster); builder.setPositiveButton("Remove from roster", this.askRemoveFromRoster);
return builder.create(); return builder.create();
} }