diff options
author | Christian Schneppe <christian@pix-art.de> | 2019-07-01 08:35:00 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2019-07-01 08:35:00 +0200 |
commit | 66a57e01292d576dc7df6480ad8f3fa9090094d5 (patch) | |
tree | b1a856154ee4857612c0747da1c2179bd87460ac | |
parent | 226d45a136d84ac8a95d25aa0c083c4fc471f1f4 (diff) |
implement FCM push for group chats
6 files changed, 128 insertions, 37 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Conversation.java b/src/main/java/de/pixart/messenger/entities/Conversation.java index b3e92fba2..d38a40888 100644 --- a/src/main/java/de/pixart/messenger/entities/Conversation.java +++ b/src/main/java/de/pixart/messenger/entities/Conversation.java @@ -57,6 +57,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl public static final String ATTRIBUTE_MUTED_TILL = "muted_till"; public static final String ATTRIBUTE_ALWAYS_NOTIFY = "always_notify"; + public static final String ATTRIBUTE_PUSH_NODE = "push_node"; public static final String ATTRIBUTE_LAST_CLEAR_HISTORY = "last_clear_history"; static final String ATTRIBUTE_MUC_PASSWORD = "muc_password"; private static final String ATTRIBUTE_NEXT_MESSAGE = "next_message"; diff --git a/src/main/java/de/pixart/messenger/generator/IqGenerator.java b/src/main/java/de/pixart/messenger/generator/IqGenerator.java index feb1473db..ad977c7b4 100644 --- a/src/main/java/de/pixart/messenger/generator/IqGenerator.java +++ b/src/main/java/de/pixart/messenger/generator/IqGenerator.java @@ -433,14 +433,21 @@ public class IqGenerator extends AbstractGenerator { } public IqPacket pushTokenToAppServer(Jid appServer, String token, String deviceId) { - IqPacket packet = new IqPacket(IqPacket.TYPE.SET); + return pushTokenToAppServer(appServer, token, deviceId, null); + } + + public IqPacket pushTokenToAppServer(Jid appServer, String token, String deviceId, Jid muc) { + final IqPacket packet = new IqPacket(IqPacket.TYPE.SET); packet.setTo(appServer); - Element command = packet.addChild("command", "http://jabber.org/protocol/commands"); + final Element command = packet.addChild("command", Namespace.COMMANDS); command.setAttribute("node", "register-push-fcm"); command.setAttribute("action", "execute"); - Data data = new Data(); + final Data data = new Data(); data.put("token", token); data.put("android-id", deviceId); + if (muc != null) { + data.put("muc", muc.toEscapedString()); + } data.submit(); command.addChild(data); return packet; @@ -464,7 +471,7 @@ public class IqGenerator extends AbstractGenerator { public IqPacket disablePush(final Jid jid, final String node) { IqPacket packet = new IqPacket(IqPacket.TYPE.SET); Element disable = packet.addChild("disable", Namespace.PUSH); - disable.setAttribute("jid", jid.toString()); + disable.setAttribute("jid", jid.toEscapedString()); disable.setAttribute("node", node); return packet; } diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index bad55aed9..9d9be2a5b 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -2854,31 +2854,35 @@ public class XmppConnectionService extends Service { } } - private void enableMucPush(final Conversation conversation) { + private void enableDirectMucPush(final Conversation conversation) { final Account account = conversation.getAccount(); final Jid room = conversation.getJid().asBareJid(); final IqPacket enable = mIqGenerator.enablePush(conversation.getAccount().getJid(), conversation.getUuid(), null); enable.setTo(room); sendIqPacket(account, enable, (a, response) -> { if (response.getType() == IqPacket.TYPE.RESULT) { - Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabled push for muc " + room); + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabled direct push for muc " + room); } else if (response.getType() == IqPacket.TYPE.ERROR) { - Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": unable to enable push for muc " + room + " " + response.getError()); + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": unable to enable direct push for muc " + room + " " + response.getError()); } }); + } + private void enableMucPush(final Conversation conversation) { + enableDirectMucPush(conversation); + mPushManagementService.registerPushTokenOnServer(conversation); } - private void disableMucPush(final Conversation conversation) { + private void disableDirectMucPush(final Conversation conversation) { final Account account = conversation.getAccount(); final Jid room = conversation.getJid().asBareJid(); final IqPacket disable = mIqGenerator.disablePush(conversation.getAccount().getJid(), conversation.getUuid()); disable.setTo(room); sendIqPacket(account, disable, (a, response) -> { if (response.getType() == IqPacket.TYPE.RESULT) { - Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": disabled push for muc " + room); + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": disabled direct push for muc " + room); } else if (response.getType() == IqPacket.TYPE.ERROR) { - Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": unable to disable push for muc " + room + " " + response.getError()); + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": unable to disable direct push for muc " + room + " " + response.getError()); } }); } @@ -3064,7 +3068,8 @@ public class XmppConnectionService extends Service { account.pendingConferenceLeaves.remove(conversation); if (account.getStatus() == Account.State.ONLINE || now) { if (conversation.getMucOptions().push()) { - disableMucPush(conversation); + disableDirectMucPush(conversation); + mPushManagementService.disablePushOnServer(conversation); } sendPresencePacket(conversation.getAccount(), mPresenceGenerator.leave(conversation.getMucOptions())); conversation.getMucOptions().setOffline(); @@ -4409,6 +4414,7 @@ public class XmppConnectionService extends Service { for (Account account : getAccounts()) { if (account.isOnlineAndConnected() && mPushManagementService.available(account)) { mPushManagementService.registerPushTokenOnServer(account); + //TODO renew mucs } } } diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java index d46bb6d32..e9af9f4a4 100644 --- a/src/main/java/de/pixart/messenger/utils/Namespace.java +++ b/src/main/java/de/pixart/messenger/utils/Namespace.java @@ -29,4 +29,5 @@ public final class Namespace { public static final String JINGLE_TRANSPORTS_IBB = "urn:xmpp:jingle:transports:ibb:1"; public static final String PING = "urn:xmpp:ping"; public static final String PUSH = "urn:xmpp:push:0"; + public static final String COMMANDS = "http://jabber.org/protocol/commands"; } diff --git a/src/standard/java/de/pixart/messenger/services/PushManagementService.java b/src/standard/java/de/pixart/messenger/services/PushManagementService.java index b76f5b4de..0f11e3759 100644 --- a/src/standard/java/de/pixart/messenger/services/PushManagementService.java +++ b/src/standard/java/de/pixart/messenger/services/PushManagementService.java @@ -10,7 +10,15 @@ public class PushManagementService { this.mXmppConnectionService = service; } - public void registerPushTokenOnServer(Account account) { + void registerPushTokenOnServer(Account account) { + //stub implementation. only affects playstore flavor + } + + void registerPushTokenOnServer(Conversation conversation) { + //stub implementation. only affects playstore flavor + } + + void disablePushOnServer(Conversation conversation) { //stub implementation. only affects playstore flavor } diff --git a/src/standardPush/java/de/pixart/messenger/services/PushManagementService.java b/src/standardPush/java/de/pixart/messenger/services/PushManagementService.java index 7daa552d4..bc41ef1e6 100644 --- a/src/standardPush/java/de/pixart/messenger/services/PushManagementService.java +++ b/src/standardPush/java/de/pixart/messenger/services/PushManagementService.java @@ -5,10 +5,12 @@ import android.util.Log; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; import com.google.firebase.iid.FirebaseInstanceId; +import com.google.firebase.iid.InstanceIdResult; import de.pixart.messenger.Config; import de.pixart.messenger.R; import de.pixart.messenger.entities.Account; +import de.pixart.messenger.entities.Conversation; import de.pixart.messenger.utils.Namespace; import de.pixart.messenger.utils.PhoneHelper; import de.pixart.messenger.xml.Element; @@ -25,28 +27,60 @@ public class PushManagementService { this.mXmppConnectionService = service; } + private static Data findResponseData(IqPacket response) { + final Element command = response.findChild("command", Namespace.COMMANDS); + final Element x = command == null ? null : command.findChild("x", Namespace.DATA); + return x == null ? null : Data.parse(x); + } + + private Jid getAppServer() { + return Jid.of(mXmppConnectionService.getString(R.string.app_server)); + } + void registerPushTokenOnServer(final Account account) { Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": has push support"); retrieveFcmInstanceToken(token -> { final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService); - final Jid appServer = Jid.of(mXmppConnectionService.getString(R.string.app_server)); - IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(appServer, token, androidId); - mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> { - Element command = p.findChild("command", "http://jabber.org/protocol/commands"); - if (p.getType() == IqPacket.TYPE.RESULT && command != null) { - Element x = command.findChild("x", Namespace.DATA); - if (x != null) { - Data data = Data.parse(x); - try { - String node = data.getValue("node"); - String secret = data.getValue("secret"); - Jid jid = Jid.of(data.getValue("jid")); - if (node != null && secret != null) { - enablePushOnServer(a, jid, node, secret); - } - } catch (IllegalArgumentException e) { - e.printStackTrace(); + final IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(getAppServer(), token, androidId); + mXmppConnectionService.sendIqPacket(account, packet, (a, response) -> { + final Data data = findResponseData(response); + if (response.getType() == IqPacket.TYPE.RESULT && data != null) { + try { + String node = data.getValue("node"); + String secret = data.getValue("secret"); + Jid jid = Jid.of(data.getValue("jid")); + if (node != null && secret != null) { + enablePushOnServer(a, jid, node, secret); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } else { + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server"); + } + }); + }); + } + + void registerPushTokenOnServer(final Conversation conversation) { + Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": room " + conversation.getJid().asBareJid() + " has push support"); + retrieveFcmInstanceToken(token -> { + final Jid muc = conversation.getJid().asBareJid(); + final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService); + final IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(getAppServer(), token, androidId, muc); + packet.setTo(muc); + mXmppConnectionService.sendIqPacket(conversation.getAccount(), packet, (a, response) -> { + final Data data = findResponseData(response); + if (response.getType() == IqPacket.TYPE.RESULT && data != null) { + try { + final String node = data.getValue("node"); + final String secret = data.getValue("secret"); + final Jid jid = Jid.of(data.getValue("jid")); + if (node != null && secret != null) { + enablePushOnServer(conversation, jid, node, secret); } + } catch (IllegalArgumentException e) { + e.printStackTrace(); } } else { Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server"); @@ -55,8 +89,8 @@ public class PushManagementService { }); } - private void enablePushOnServer(final Account account, final Jid jid, final String node, final String secret) { - IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(jid, node, secret); + private void enablePushOnServer(final Account account, final Jid appServer, final String node, final String secret) { + final IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(appServer, node, secret); mXmppConnectionService.sendIqPacket(account, enable, (a, p) -> { if (p.getType() == IqPacket.TYPE.RESULT) { Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully enabled push on server"); @@ -66,14 +100,48 @@ public class PushManagementService { }); } + private void enablePushOnServer(final Conversation conversation, final Jid appServer, final String node, final String secret) { + final Jid muc = conversation.getJid().asBareJid(); + final IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(appServer, node, secret); + enable.setTo(muc); + mXmppConnectionService.sendIqPacket(conversation.getAccount(), enable, (a, p) -> { + if (p.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully enabled push on " + muc); + if (conversation.setAttribute(Conversation.ATTRIBUTE_ALWAYS_NOTIFY, node)) { + mXmppConnectionService.updateConversation(conversation); + } + } else if (p.getType() == IqPacket.TYPE.ERROR) { + Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabling push on " + muc + " failed"); + } + }); + } + + public void disablePushOnServer(final Conversation conversation) { + final Jid muc = conversation.getJid().asBareJid(); + final String node = conversation.getAttribute(Conversation.ATTRIBUTE_PUSH_NODE); + if (node != null) { + final IqPacket disable = mXmppConnectionService.getIqGenerator().disablePush(getAppServer(), node); + disable.setTo(muc); + mXmppConnectionService.sendIqPacket(conversation.getAccount(), disable, (account, response) -> { + if (response.getType() == IqPacket.TYPE.ERROR) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to disable push for room " + muc); + } + }); + } else { + Log.d(Config.LOGTAG, conversation.getAccount().getJid().asBareJid() + ": room " + muc + " has no stored node. unable to disable push"); + } + } + private void retrieveFcmInstanceToken(final OnGcmInstanceTokenRetrieved instanceTokenRetrieved) { - new Thread(() -> { - try { - instanceTokenRetrieved.onGcmInstanceTokenRetrieved(FirebaseInstanceId.getInstance().getToken()); - } catch (Exception e) { - Log.d(Config.LOGTAG, "unable to get push token", e); + FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(task -> { + if (!task.isSuccessful()) { + Log.d(Config.LOGTAG, "unable to get Firebase instance token", task.getException()); + } + final InstanceIdResult result = task.getResult(); + if (result != null) { + instanceTokenRetrieved.onGcmInstanceTokenRetrieved(result.getToken()); } - }).start(); + }); } |