1package eu.siacs.conversations.services;
2
3import android.provider.Settings;
4import android.util.Log;
5
6import com.google.android.gms.common.ConnectionResult;
7import com.google.android.gms.common.GoogleApiAvailability;
8import com.google.android.gms.gcm.GoogleCloudMessaging;
9import com.google.android.gms.iid.InstanceID;
10
11import eu.siacs.conversations.Config;
12import eu.siacs.conversations.R;
13import eu.siacs.conversations.entities.Account;
14import eu.siacs.conversations.utils.PhoneHelper;
15import eu.siacs.conversations.xml.Element;
16import eu.siacs.conversations.xml.Namespace;
17import eu.siacs.conversations.xmpp.XmppConnection;
18import eu.siacs.conversations.xmpp.forms.Data;
19import eu.siacs.conversations.xmpp.stanzas.IqPacket;
20import rocks.xmpp.addr.Jid;
21
22public class PushManagementService {
23
24 private static final Jid APP_SERVER = Jid.of("p2.siacs.eu");
25
26 protected final XmppConnectionService mXmppConnectionService;
27
28 PushManagementService(XmppConnectionService service) {
29 this.mXmppConnectionService = service;
30 }
31
32 void registerPushTokenOnServer(final Account account) {
33 Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": has push support");
34 retrieveGcmInstanceToken(token -> {
35 final String androidId = PhoneHelper.getAndroidId(mXmppConnectionService);
36 IqPacket packet = mXmppConnectionService.getIqGenerator().pushTokenToAppServer(APP_SERVER, token, androidId);
37 mXmppConnectionService.sendIqPacket(account, packet, (a, p) -> {
38 Element command = p.findChild("command", "http://jabber.org/protocol/commands");
39 if (p.getType() == IqPacket.TYPE.RESULT && command != null) {
40 Element x = command.findChild("x", Namespace.DATA);
41 if (x != null) {
42 Data data = Data.parse(x);
43 try {
44 String node = data.getValue("node");
45 String secret = data.getValue("secret");
46 Jid jid = Jid.of(data.getValue("jid"));
47 if (node != null && secret != null) {
48 enablePushOnServer(a, jid, node, secret);
49 }
50 } catch (IllegalArgumentException e) {
51 e.printStackTrace();
52 }
53 }
54 } else {
55 Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": invalid response from app server");
56 }
57 });
58 });
59 }
60
61 private void enablePushOnServer(final Account account, final Jid jid, final String node, final String secret) {
62 IqPacket enable = mXmppConnectionService.getIqGenerator().enablePush(jid, node, secret);
63 mXmppConnectionService.sendIqPacket(account, enable, (a, p) -> {
64 if (p.getType() == IqPacket.TYPE.RESULT) {
65 Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": successfully enabled push on server");
66 } else if (p.getType() == IqPacket.TYPE.ERROR) {
67 Log.d(Config.LOGTAG, a.getJid().asBareJid() + ": enabling push on server failed");
68 }
69 });
70 }
71
72 private void retrieveGcmInstanceToken(final OnGcmInstanceTokenRetrieved instanceTokenRetrieved) {
73 new Thread(() -> {
74 InstanceID instanceID = InstanceID.getInstance(mXmppConnectionService);
75 try {
76 String token = instanceID.getToken(mXmppConnectionService.getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
77 instanceTokenRetrieved.onGcmInstanceTokenRetrieved(token);
78 } catch (Exception e) {
79 Log.d(Config.LOGTAG, "unable to get push token");
80 }
81 }).start();
82
83 }
84
85
86 public boolean available(Account account) {
87 final XmppConnection connection = account.getXmppConnection();
88 return connection != null
89 && connection.getFeatures().sm()
90 && connection.getFeatures().push()
91 && playServicesAvailable();
92 }
93
94 private boolean playServicesAvailable() {
95 return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(mXmppConnectionService) == ConnectionResult.SUCCESS;
96 }
97
98 public boolean isStub() {
99 return false;
100 }
101
102 interface OnGcmInstanceTokenRetrieved {
103 void onGcmInstanceTokenRetrieved(String token);
104 }
105}