package eu.musesproject.client.connectionmanager; /* * #%L * MUSES Client * %% * Copyright (C) 2013 - 2014 Sweden Connectivity * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import eu.musesproject.client.ui.DebugFileLog; import eu.musesproject.client.usercontexteventhandler.JSONManager; import android.content.Context; import android.os.AsyncTask; import android.util.Log; /** * Connection Manager class implements the iConnection interface * * @author Yasir Ali * @version Jan 27, 2014 */ public class ConnectionManager extends HttpConnectionsHelper implements IConnectionManager{ private static String URL = ""; private static String certificate; public static IConnectionCallbacks callBacks; public static final String CONNECT = "connect"; public static final String POLL = "poll"; public static final String DATA = "data"; public static final String DISCONNECT = "disconnect"; public static final String ACK = "ack"; private static final String TAG = ConnectionManager.class.getSimpleName(); private static final String APP_TAG = "APP_TAG"; private static Boolean isServerConnectionSet = false; static private int lastSentStatus = Statuses.OFFLINE; private AtomicInteger mCommandOngoing = new AtomicInteger(0); private AlarmReceiver alarmReceiver; public static Context context; public static boolean isNewSession = true; public ConnectionManager(){ alarmReceiver = new AlarmReceiver(); AlarmReceiver.setManager(this); } /** * Connect to the server with specified parameter * @param url * @param pollInterval * @param sleepPollInterval * @param callbacks * @param cntext * @return void */ @Override public void connect(String url, String cert, int pollInterval, int sleepPollInterval, IConnectionCallbacks callbacks, Context cntext) { /* FIXME, temporary fix for dual calls */ synchronized (this){ if (isServerConnectionSet){ Log.d(TAG, "connect: More then one more connect call!"); return; } isServerConnectionSet = true; } URL = url; callBacks = callbacks; context = cntext; certificate = cert; /* Check that cert is ok, spec length */ /* FIXME which Length.. */ if (cert.isEmpty() || cert.length() < 1000){ callBacks.statusCb(Statuses.CONNECTION_FAILED, DetailedStatuses.INCORRECT_CERTIFICATE, 0); Log.d(TAG, "connect: Incorrect certificate!"); DebugFileLog.write(TAG+ " connect: Incorrect certificate!"); return; } NetworkChecker networkChecker = new NetworkChecker(cntext); PhoneModeReceiver phoneModeReceiver = new PhoneModeReceiver(cntext); phoneModeReceiver.register(); Log.d(TAG, "Connecting to URL:"+url); DebugFileLog.write(TAG+ " Connecting to URL:"+url); if (networkChecker.isInternetConnected()) { Log.d(TAG, "InternetConnected"); } setCommandOngoing(); startHttpThread( CONNECT, URL, Integer.toString(pollInterval),"", ""); alarmReceiver.setPollInterval(pollInterval, sleepPollInterval); alarmReceiver.setDefaultPollInterval(pollInterval, sleepPollInterval); alarmReceiver.setAlarm(cntext); } /** * Send data to the server * @param data * @return void */ @Override public void sendData(String data, int dataId) { String dataIdStr = ""; dataIdStr = Integer.toString(dataId); setCommandOngoing(); Log.d(APP_TAG, "ConnManager=> send data to server with request type: "+JSONManager.getRequestType(data)); DebugFileLog.write(APP_TAG+ " ConnManager=> send data to server with request type: "+JSONManager.getRequestType(data)); startHttpThread(DATA, URL, Integer.toString(AlarmReceiver.getCurrentPollInterval()), data, dataIdStr); } /** * Disconnects session from the server * @return void */ @Override public void disconnect() { // FIXME What if the server is not online, How should we stop polling from here // As we are disconnecting we need to stop the polling Log.d(TAG, "Disconnecting .."); synchronized (this){ isServerConnectionSet = false; } Log.d(APP_TAG, "ConnManager=> disconnecting session to server"); DebugFileLog.write(APP_TAG+ " ConnManager=> disconnecting session to server"); startHttpThread(DISCONNECT, URL, Integer.toString(AlarmReceiver.getCurrentPollInterval()), "", ""); //callBacks.statusCb(Statuses.DISCONNECTED, Statuses.DISCONNECTED); // FIXME alarmReceiver.cancelAlarm(context); } /** * Sets poll timeouts * @param pollInterval * @param sleepPollInterval * @return void */ @Override public void setPollTimeOuts(int pollInterval, int sleepPollInterval) { alarmReceiver.setPollInterval(pollInterval, sleepPollInterval); alarmReceiver.setDefaultPollInterval(pollInterval, sleepPollInterval); } /** * Set timeout * @param timeout * @return void */ @Override public void setTimeout(int timeout) { CONNECTION_TIMEOUT = timeout; } /** * Enable polling * @param polling * @return void */ @Override public void setPolling(int polling) { POLLING_ENABLED = polling; } /** * Starts to poll with the server either in sleep/active mode * @return void */ public void periodicPoll() { //Log.d(APP_TAG, "Polling !!"); // If ongoing command, don't poll if (mCommandOngoing.get()==0){ poll(); } } /** * Starts to poll with the server either in sleep/active mode * @return void */ public void poll() { //Log.d(APP_TAG, "Polling !!"); setCommandOngoing(); startHttpThread(POLL, URL, Integer.toString(AlarmReceiver.getCurrentPollInterval()), "", ""); } /** * Sends ack to the server to tell that data has been received on the client * @return void */ public void ack() { Log.d(TAG, "Sending ack.."); DebugFileLog.write(TAG+ "Sending ack.."); startHttpThread(ACK, URL, Integer.toString(AlarmReceiver.getCurrentPollInterval()), "", ""); } private void startHttpThread(String cmd, String url, String pollInterval, String data, String dataId) { HttpClientAsyncThread httpClientAsyncThread = new HttpClientAsyncThread(); httpClientAsyncThread.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, cmd, url, pollInterval, data, certificate, dataId); /* If too many threads, use serial executor */ // httpClientAsyncThread.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, cmd, url, // pollInterval, data, certificate); } /** * Handler Http/Https (Networking in background or separate thread) * @author Yasir Ali * @version Jan 27, 2014 */ private class HttpClientAsyncThread extends AsyncTask<String, Void, String> { /* FIXME use onPost Execute to send callbacks */ @Override protected String doInBackground(String... params) { HttpResponse response = null; Request request = new Request(params[0], params[1], params[2], params[3], params[4], params[5]); if (!NetworkChecker.isInternetConnected) { if (request.getType().contentEquals(CONNECT)){ callBacks.statusCb(Statuses.CONNECTION_FAILED, DetailedStatuses.NO_INTERNET_CONNECTION, request.getDataId()); } else if (request.getType().contentEquals(DATA)){ Log.d(APP_TAG, "ConnManager=> can't send data with no internet connection, calling statusCB"); sendServerStatus(Statuses.OFFLINE, DetailedStatuses.NO_INTERNET_CONNECTION, request.getDataId()); callBacks.statusCb(Statuses.DATA_SEND_FAILED, DetailedStatuses.NO_INTERNET_CONNECTION, request.getDataId()); } else if (request.getType().contentEquals(DISCONNECT)){ callBacks.statusCb(Statuses.DISCONNECTED, DetailedStatuses.NO_INTERNET_CONNECTION, request.getDataId()); //HttpConnectionsHelper.current_cookie = null; } } else { Log.d(APP_TAG,"doInBackground: starts with parameters: "+params[0]+", "+params[1]+", "+params[2]+", "+params[3]); DebugFileLog.write(APP_TAG+" doInBackground: starts with parameters: "+params[0]+", "+params[1]+", "+params[2]+", "+params[3]); try { HttpResponseHandler httpResponseHandler = doSecurePost(request, params[4]); if (httpResponseHandler != null){ httpResponseHandler.checkHttpResponse(); } } catch (ClientProtocolException e) { e.printStackTrace(); Log.d(APP_TAG, Log.getStackTraceString(e)); } catch (IOException e) { e.printStackTrace(); Log.d(APP_TAG, Log.getStackTraceString(e)); } catch (Exception e) { e.printStackTrace(); Log.d(APP_TAG, Log.getStackTraceString(e)); } if (request.getType().contentEquals(DISCONNECT)){ //HttpConnectionsHelper.current_cookie = null; } } setCommandNotOngoing(); Log.d(APP_TAG,"doInBackground: finished."); DebugFileLog.write(APP_TAG +" doInBackground: finished."); return null; } } private void setCommandOngoing(){ mCommandOngoing.set(1); } private void setCommandNotOngoing(){ mCommandOngoing.set(0); } public static void sendServerStatus(int status, int detailedStatus, int dataId) { if (status == Statuses.OFFLINE || status == Statuses.ONLINE) { if (lastSentStatus != status ){ ConnectionManager.callBacks.statusCb(status, detailedStatus, dataId); lastSentStatus = status; } } else { //DBG SweFileLog.write("Weird status: "+Integer.toString(status)+", , "); } } }