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