PushManagementService.java

  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}