/* * CDDL HEADER START * * The contents of this file are subject to the terms of the Common Development * and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at * src/com/vodafone360/people/VODAFONE.LICENSE.txt or * http://github.com/360/360-Engine-for-Android * See the License for the specific language governing permissions and * limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each file and * include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt. * If applicable, add the following below this CDDL HEADER, with the fields * enclosed by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved. * Use is subject to license terms. */ package com.vodafone360.people.service.transport; import java.util.ArrayList; import android.content.Context; import android.os.AsyncTask; import android.widget.Toast; import com.vodafone360.people.engine.EngineManager; import com.vodafone360.people.engine.login.LoginEngine.ILoginEventsListener; import com.vodafone360.people.service.RemoteService; import com.vodafone360.people.service.io.QueueManager; import com.vodafone360.people.service.transport.http.HttpConnectionThread; import com.vodafone360.people.service.transport.http.authentication.AuthenticationManager; import com.vodafone360.people.service.transport.tcp.ITcpConnectionListener; import com.vodafone360.people.service.transport.tcp.TcpConnectionThread; /** * ConnectionManager - responsible for controlling the current connection * Connects and disconnects based on network availability etc and start or stops * RPG polling. Currently handles HTTP connections - this will be extended to * support TCP sockets. */ public class ConnectionManager implements ILoginEventsListener, IQueueListener { private static ConnectionManager mInstance; private IConnection mConnection; private RemoteService mService; private DecoderThread mDecoder; /** * ApplicationContext */ private Context mContext; /** * the class member variable to keep the connection state. * * @see ITcpConnectionListener */ private int mConnectionState; /** * the list of connection state change listeners, e.g. PresenceEngine. */ private ArrayList<ITcpConnectionListener> mListeners = new ArrayList<ITcpConnectionListener>(); public static synchronized ConnectionManager getInstance() { if (mInstance == null) { mInstance = new ConnectionManager(); } return mInstance; } /** * Shows a Toast ruinning on a UI Thread. There can be a crash if the * connectionmanager is called outside of an UI Thread and then treis to * show a toast. Using this approach with the AsyncTask Toasts will allways * be shown inside an UI Thread. * * @param messageResId */ private void showToast(int messageResId) { new AsyncTask<Integer, Void, Boolean>() { protected Boolean doInBackground(Integer... messageResId) { try { Toast toast = Toast.makeText(mContext, messageResId[0], Toast.LENGTH_LONG); toast.show(); } catch (Exception exc) { return false; } return true; } }.execute(messageResId); } private ConnectionManager() { EngineManager.getInstance().getLoginEngine().addListener(this); } public void connect(RemoteService service) { HttpConnectionThread.logI("ConnectionManager.connect()", "CONNECT CALLED BY NETWORKAGENT"); mService = service; mContext = mService.getApplicationContext(); // start decoder if (mDecoder == null) { mDecoder = new DecoderThread(); } if (!mDecoder.getIsRunning()) { mDecoder.startThread(); } boolean isCurrentlyLoggedIn = EngineManager.getInstance().getLoginEngine().isLoggedIn(); onLoginStateChanged(isCurrentlyLoggedIn); HttpConnectionThread.logI("ConnectionManager.connect()", (isCurrentlyLoggedIn) ? "We are logged in!" : "We are not logged in!"); } /** * Returns an autodetected connection. Where available, TCP will be used. * HTTP is used as a fallback alternative. * * @return Returns the correct implmentation of the connection. If TCP is * available it will be used preferably. Otherwise, HTTP is used as * a fallback. */ private IConnection getAutodetectedConnection(RemoteService service) { return new TcpConnectionThread(mDecoder, service); } public void disconnect() { HttpConnectionThread.logI("ConnectionManager.disconnect()", "DISCONNECT CALLED BY NETWORKAGENT"); if (null != mDecoder) { mDecoder.stopThread(); } stopActiveConnection(); } @Override public synchronized void onLoginStateChanged(boolean loggedIn) { HttpConnectionThread.logI("ConnectionManager.onLoginStateChanged()", "Is logged in: " + loggedIn); stopActiveConnection(); if (loggedIn) { mConnection = getAutodetectedConnection(mService); } else { mConnection = new AuthenticationManager(mDecoder); } QueueManager.getInstance().addQueueListener(mConnection); mConnection.startThread(); } /** * * Stops the connection if it was currently running. * */ private void stopActiveConnection() { if (null != mConnection) { synchronized (mConnection) { mConnection.stopThread(); mConnection = null; unsubscribeFromQueueEvents(); } } } @Override public synchronized void notifyOfItemInRequestQueue() { mConnection.notifyOfItemInRequestQueue(); } public void notifyOfUiActivity() { if (null != mConnection) { mConnection.notifyOfUiActivity(); } } private void unsubscribeFromQueueEvents() { QueueManager queue = QueueManager.getInstance(); queue.removeQueueListener(mConnection); queue.clearRequestTimeouts(); } /** * Enable test connection (for Unit testing purposes) * * @param testConn handle to test connection */ public void setTestConnection(IConnection testConn) { mConnection = testConn; QueueManager.getInstance().addQueueListener(mConnection); } /** * This method is called by the protocol to signal the connection state change. * * @param state The new connection state, @see ITcpConnectionListener. */ public void onConnectionStateChanged(int state) { HttpConnectionThread.logI("ConnectionManager.onConnectionStateChanged()", "State is " + state); if (state == ITcpConnectionListener.STATE_DISCONNECTED) { // TODO show toast only if activity in foreground // showToast(R.string.ContactProfile_no_connection); } mConnectionState = state; for (ITcpConnectionListener listener : mListeners) { listener.onConnectionStateChanged(state); } } /** * This method adds a listener for the connection state changes to the list, * if it is not there yet. * * @param listener ITcpConnectionListener - listener. */ public void addConnectionListener(ITcpConnectionListener listener) { if (!mListeners.contains(listener)) { mListeners.add(listener); } } /** * This method removes a listener from the connection state changes * listeners list. * * @param listener ITcpConnectionListener - listener. */ public void removeConnectionListener(ITcpConnectionListener listener) { mListeners.remove(listener); } /** * This method returns the current connection state of the application. * * @see ITcpConnectionListener * @return int - the connection state @see ITcpConnectionListener. */ public int getConnectionState() { return mConnectionState; } }