/* This file is part of Project MAXS. MAXS and its modules is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. MAXS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with MAXS. If not, see <http://www.gnu.org/licenses/>. */ package org.projectmaxs.transport.xmpp; import org.jivesoftware.smack.util.Async; import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager; import org.projectmaxs.shared.global.GlobalConstants; import org.projectmaxs.shared.global.Message; import org.projectmaxs.shared.global.jul.JULHandler; import org.projectmaxs.shared.global.util.Log; import org.projectmaxs.shared.maintransport.CommandOrigin; import org.projectmaxs.shared.maintransport.TransportConstants; import org.projectmaxs.shared.maintransport.TransportInformation; import org.projectmaxs.shared.maintransport.TransportInformation.TransportComponent; import org.projectmaxs.shared.transport.MAXSTransportService; import org.projectmaxs.transport.xmpp.receivers.NetworkConnectivityReceiver; import org.projectmaxs.transport.xmpp.util.Constants; import org.projectmaxs.transport.xmpp.xmppservice.XMPPEntityCapsCache; import org.projectmaxs.transport.xmpp.xmppservice.XMPPService; import android.content.Intent; import android.os.IBinder; public class TransportService extends MAXSTransportService { public static final String TRANSPORT_OUTGOING_FILESERVICE = Constants.PACKAGE + ".xmppservice.XMPPFileTransfer$MAXSOutgoingFileTransferService"; public TransportService() { super("XMPP", TransportService.class); } // @formatter:off public static final TransportInformation sTransportInformation = new TransportInformation( Constants.PACKAGE, "XMPP Transport", true, TRANSPORT_OUTGOING_FILESERVICE, new TransportComponent[] { new TransportComponent("Message", Constants.ACTION_SEND_AS_MESSAGE, true), new TransportComponent("IQ", Constants.ACTION_SEND_AS_IQ, false) } ); // @formatter:on private static final Log LOG = Log.getLog(); private XMPPService mXMPPService; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); LOG.d("onCreate"); JULHandler.init(Settings.getInstance(this)); XMPPEntityCapsCache.onCreate(this); ServerPingWithAlarmManager.onCreate(this); } @Override public void onDestroy() { super.onDestroy(); LOG.d("onDestroy"); final XMPPService xmppService = mXMPPService; if (xmppService != null) { // Ensure that all receivers are unregistered by calling XMPPService.disconnect(). We // need to perform that action async, since onDestory() is called from the main thread, // disconnect() is possible causing network IO and we want to avoid a // NetworkOnMainThreadException. Note that we can not use the Service's Looper, since it // will be already exited, because we already called super.onDestory(). Async.go(new Runnable() { @Override public void run() { xmppService.disconnect(); } }); } XMPPEntityCapsCache.onDestroy(this); ServerPingWithAlarmManager.onDestroy(); } @Override protected void onHandleIntent(Intent intent) { // In order to avoid NetworkOnMainThread - some methods like // Socks5Proxy.getSocks5Proxy() do DNS lookups - exceptions, we // initialize the XMPP service here. if (mXMPPService == null) mXMPPService = XMPPService.getInstance(this); final String action = intent.getAction(); LOG.d("onHandleIntent: " + action); if (TransportConstants.ACTION_START_SERVICE.equals(action)) { if (hasMessage(TransportConstants.ACTION_STOP_SERVICE.hashCode())) { LOG.d("Not starting service because there is a stop service action queued"); } else { NetworkConnectivityReceiver.register(this); mXMPPService.connect(); } } else if (TransportConstants.ACTION_STOP_SERVICE.equals(action)) { if (hasMessage(TransportConstants.ACTION_START_SERVICE.hashCode())) { LOG.d("Not stopping service because there is a start service action queued"); } else { NetworkConnectivityReceiver.unregister(this); mXMPPService.disconnect(); stopSelf(); } } else if (TransportConstants.ACTION_SET_STATUS.equals(action)) { String status = intent.getStringExtra(GlobalConstants.EXTRA_CONTENT); mXMPPService.setStatus(status); } else if (TransportConstants.ACTION_REQUEST_TRANSPORT_STATUS.equals(action)) { mXMPPService.getHandleTransportStatus().sendStatus(); } else if (Constants.ACTION_SEND_AS_MESSAGE.equals(action) || (Constants.ACTION_SEND_AS_IQ.equals(action))) { Message message = intent.getParcelableExtra(GlobalConstants.EXTRA_MESSAGE); CommandOrigin origin = intent .getParcelableExtra(TransportConstants.EXTRA_COMMAND_ORIGIN); mXMPPService.send(message, origin); } else if (Constants.ACTION_NETWORK_CONNECTED.equals(action)) { if (hasMessage(Constants.ACTION_NETWORK_CONNECTED.hashCode())) { LOG.d("Not handling NETWORK_CONNECTED because another intent of the same type is in the queue"); } else { mXMPPService.connect(); } } else if (Constants.ACTION_NETWORK_DISCONNECTED.equals(action)) { if (hasMessage(Constants.ACTION_NETWORK_DISCONNECTED.hashCode())) { LOG.d("Not handling NETWORK_DISCONNECTED because another intent of the same type is in the queue"); } else { mXMPPService.networkDisconnected(); } } else if (Constants.ACTION_NETWORK_TYPE_CHANGED.equals(action)) { if (hasMessage(Constants.ACTION_NETWORK_TYPE_CHANGED.hashCode())) { LOG.d("Not handling NETWORK_TYPE_CHANGED because another intent of the same type is in the queue"); } else if (mXMPPService.fastPingServer()) { LOG.d("Not issuing instantDisconnect as result of NETWORK_TYPE_CHANGED, because connection is (still/again) alive"); } else { mXMPPService.instantDisconnect(); } } else { throw new IllegalStateException("Unknown intent action: " + action); } LOG.d("onHandleIntent: " + action + " handled"); } }