I'm trying to implement a globalized Socket.io connection method for an entire 
application (multiple activities).

The requirements:
1. The socket.io must be enabled as long as the user is logged into the 
application
2. The socket has to keep connected even when switching activities.
3. The socket.io connection must be kept alive even when application is in 
background

The Current Layout:
1. Socket.io methods are implemented in a class that extends the application 
class

The Main Issues:
1. When emitting from the server to the Android the socket.io "on" methods are 
executed multiple times. The server code has been validated and determined it 
is only sending one emit to the client.
2. If I emit the methods from the server multiple times the "on" method 
execution increases exponentially.

The Previous Solution:
1. Moved all the Socket.io methods into an Android Service but it did not work.

What can I do to solve this? Am I missing something else? From what I read on 
other posts The singleton class will be elegible for termination by the OS once 
the application moves into the background, how can I avoid this?

Here is my Application Extended Class

public class AppSettings extends Application {

    private static String TAG = "AppSettings";
    private static String username;
    private boolean isdriver;
    private int time, Buffer, intents;
    public CountDownTimer Clock;
    public Context mainContext;
    GOGODBHelper mGOGODBHelper;
    SQLiteDatabase db;
    private URI uri;
    public static  Socket mSocket;
    public static long transaction_id = 0;

    {
        try {
            uri = new URI("http://gogosocket.cloudapp.net:3000";);
            AppSettings.this.mSocket = IO.socket(uri);

        } catch (URISyntaxException e) {
            Log.d(TAG, e.getMessage());
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        final Fabric fabric = new Fabric.Builder(this)
                .kits(new Crashlytics())
                .debuggable(true)
                .build();
        Fabric.with(this, new Crashlytics());

        mGOGODBHelper = new GOGODBHelper(this);

        registerReceiver(ConnectionReceiver, new 
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));

    }

    public void setMainContext(Context context){
        this.mainContext = context;
    }

    public  Context getMainContext(){
        return this.mainContext;
    }

    //set and get username
    public  void setUsername(String username) {
        this.username = username;
    }

    public  String getUsername() {
        return this.username;
    }

    //set and get isDriver
    public void setIsdriver(boolean isdriver) {
        this.isdriver = isdriver;
    }

    public boolean getIsdriver() {
        return this.isdriver;
    }

    private long saveTransaction(String to, String from,String event,String 
data,String timeStamp) {

        long newRowID = 0;

        db = mGOGODBHelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(Transactions.Transaction.COLUMN_NAME_TO,to);
        values.put(Transactions.Transaction.COLUMN_NAME_FROM, from);
        values.put(Transactions.Transaction.COLUMN_NAME_METHOD,event);
        values.put(Transactions.Transaction.COLUMN_NAME_DATA,data);
        values.put(Transactions.Transaction.COLUMN_NAME_TIMESTAMP, timeStamp);

        newRowID = db.insert(Transactions.Transaction.TABLE_NAME,null,values);

        return newRowID;
    }

    private boolean deleteTransaction(long transaction_id){
        db = mGOGODBHelper.getReadableDatabase();

        return db.delete(Transactions.Transaction.TABLE_NAME, 
Transactions.Transaction._ID + " = " +transaction_id , null) >0;
    }

    public void onSocket() {
        AppSettings.this.mSocket.on(Socket.EVENT_CONNECT_ERROR, onConnectError)
                .on(Socket.EVENT_CONNECT_TIMEOUT, onConnectError)
                .on(Socket.EVENT_RECONNECT_ERROR, onConnectError)
                .on(Socket.EVENT_RECONNECT_FAILED, onConnectError)
                .on(Socket.EVENT_DISCONNECT, onConnectError)
                .on(Socket.EVENT_ERROR, onConnectError)
                .on(Socket.EVENT_RECONNECT_ATTEMPT, onReconnect)
                .on(Socket.EVENT_RECONNECT, onReconnect)
                .on(Socket.EVENT_CONNECT, onConnect)
                .on("ping", ping)
                .on("method", method);
//        AppSettings.this.mSocket.on(Socket.EVENT_CONNECT_TIMEOUT, 
onConnectError);
//        AppSettings.this.mSocket.on(Socket.EVENT_RECONNECT_ERROR, 
onConnectError);
//        AppSettings.this.mSocket.on(Socket.EVENT_RECONNECT_FAILED, 
onConnectError);
//        AppSettings.this.mSocket.on(Socket.EVENT_DISCONNECT, onConnectError);
//        AppSettings.this.mSocket.on(Socket.EVENT_ERROR, onConnectError);
//        AppSettings.this.mSocket.on(Socket.EVENT_RECONNECT_ATTEMPT, 
onReconnect);
//        AppSettings.this.mSocket.on(Socket.EVENT_RECONNECT, onReconnect);
//        AppSettings.this.mSocket.on(Socket.EVENT_CONNECT, onConnect);


//        this.mSocket.on("ping", ping);
//        this.mSocket.on("method", method);
    }

    public void offSocket() {
        AppSettings.this.mSocket.off(Socket.EVENT_CONNECT_ERROR, onConnectError)
                .off(Socket.EVENT_CONNECT_TIMEOUT, onConnectError)
                .off(Socket.EVENT_RECONNECT_ERROR, onConnectError)
                .off(Socket.EVENT_RECONNECT_FAILED, onConnectError)
                .off(Socket.EVENT_ERROR, onConnectError)
                .off(Socket.EVENT_DISCONNECT, onConnectError)
                .off(Socket.EVENT_RECONNECT, onReconnect)
                .off(Socket.EVENT_RECONNECT_ATTEMPT, onReconnect)
                .off("ping", ping)
                .off("method", method);
//        AppSettings.this.mSocket.off(Socket.EVENT_CONNECT_TIMEOUT, 
onConnectError);
//        AppSettings.this.mSocket.off(Socket.EVENT_RECONNECT_ERROR, 
onConnectError);
//        AppSettings.this.mSocket.off(Socket.EVENT_RECONNECT_FAILED, 
onConnectError);
//        AppSettings.this.mSocket.off(Socket.EVENT_ERROR, onConnectError);
//        AppSettings.this.mSocket.off(Socket.EVENT_DISCONNECT, onConnectError);
//        AppSettings.this.mSocket.off(Socket.EVENT_RECONNECT, onReconnect);
//        AppSettings.this.mSocket.off(Socket.EVENT_RECONNECT_ATTEMPT, 
onReconnect);
//        AppSettings.this.mSocket.off("ping", ping);
//        AppSettings.this.mSocket.off("method", method);
    }

    BroadcastReceiver ConnectionReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            //startActivity(new Intent(AppSettings.this, LoginActivity.class));

        }
    };

    public long setTimeout(int B, int T, int I, int D) {
        long result = 0;

        if (D > 0) {
            result = ((B + T * I) * D);
        } else {
            result = B + T * I;
        }

        return result;
    }

    public void setBuffer(int buffer) {
        this.Buffer = buffer;
    }

    public int getBuffer() {
        return this.Buffer;
    }

    public void setTime(int time) {
        this.time = time;
    }

    public int getTime() {
        return this.time;
    }

    public void startClockWaitTime(Context context,final int B, final int T, 
final int I, final int D) {


        ((Activity)context).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AppSettings.this.Clock == null) {

                    AppSettings.this.Clock = 
AppSettings.this.setClockWaitTime(B, T, I, D);
                    AppSettings.this.Clock.start();
                    Log.d(TAG, "CountDownTimer was starting");
                }
            }
        });
    }

    public void stopClockWaitTime(Context context) {

        ((Activity)context).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (AppSettings.this.Clock != null) {
                    AppSettings.this.Clock.cancel();
                    AppSettings.this.Clock = null;

                    Log.d(TAG, "CountDownTimer was stoped");
                }

            }
        });
    }

    public CountDownTimer setClockWaitTime(int B, int T, int I, int D) {


        CountDownTimer result;
        long waitTime = setTimeout(B, T, I, D) * 1000;
        Log.d(TAG, "Waitime: " + waitTime);

        result = new CountDownTimer(waitTime, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {

                Log.d(TAG, "CountDownTimer tick");
            }

            @Override
            public void onFinish() {

                Log.d(TAG, "CountDownTimer finish");

                AppSettings.this.reconnect();

                if (AppSettings.this.Clock != null) {
                    AppSettings.this.Clock.cancel();
                    AppSettings.this.Clock = null;
                }
            }
        }.start();

        Log.d(TAG, "CountDownTimer was set");
        return  result;
    }

    public  boolean isConnected() {

        boolean result = false;

        if (AppSettings.this.mSocket != null && 
AppSettings.this.mSocket.connected() ) {
            result = true;
        }

        return result;
    }

    public void connect() {
        if (AppSettings.this.mSocket != null) {
            if(AppSettings.this.mSocket.connect() == null){
                reconnect();
            }

        }
    }

    private void ResetTravelElements() {
        Session.setSelectedLocation(null);
        Session.setSelectedDestination(null);
        Session.setEstimateDistance(0);
        Session.setEstimatePayment(null);
        Session.setPaxCount(null);
        Session.setBagCount(null);
        Session.setTypeVehicle(null);
        Session.setTotalTravelled(0);
        Session.resetWaitInstance();
        Session.setStartWaitTime(0);
    }

    public void reconnect(){

        Intent intent_expirate = new Intent("expirate");
        intent_expirate.putExtra("message", "Reconnection - Comunication 
Error");
        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_expirate);


    }


    public  void Emit(JSONObject jsonObject, int B, int T, int I, int D) {

        try {

            SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
            Calendar c = Calendar.getInstance();
            this.transaction_id = 
saveTransaction(null,getUsername(),jsonObject.getString("event"),jsonObject.toString(),df.format(c.getTime()));

            jsonObject.put("TID",transaction_id);

            if(AppSettings.this.mSocket.emit("method", jsonObject) == null){
                reconnect();
                return;
            }

            Log.d(TAG, this.getUsername() + " emit the event: " + 
jsonObject.getString("event"));
            
LogFile(getApplicationContext(),String.valueOf(transaction_id),AppSettings.this.mSocket.id(),AppSettings.this.mSocket.id(),jsonObject.getString("event"),this.getUsername()
            ,Session.getDriver(),Session.getEmei());

            if (AppSettings.this.Clock == null) {

                if(getMainContext() != null){
                    AppSettings.this.startClockWaitTime(this.getMainContext(), 
B, T, I, D);
                }

            }



        } catch (JSONException e) {
            e.printStackTrace();
        }
    }



    private Emitter.Listener onConnectError = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {
            //final JSONObject data = (JSONObject) args[0];

            Log.i("Data", String.valueOf(args[0]));

            AppSettings.this.connect();

            if (!AppSettings.this.isConnected()){

                Log.d(TAG, "onConnectError Socket disconnected");
                if(AppSettings.this.Clock == null){
                    if(getMainContext() != null){
                        
AppSettings.this.startClockWaitTime(AppSettings.this.getMainContext(),15, 15, 
1, 0);
                    }
                }

                AppSettings.this.reconnect();
            }
        }
    };

    private Emitter.Listener onReconnect = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {

            Log.i("onReconect Data", String.valueOf(args[0]));
            JSONObject object = new JSONObject();

            if(AppSettings.this.isConnected()){

                try{
                    object.put("event","join");
                    object.put("uid", username);
                    AppSettings.this.Emit(object, 15, 15, 1, 0);
                }
                catch (JSONException e){
                    Log.d(TAG,e.getMessage());
                 }
            }else{
                AppSettings.this.reconnect();
            }
        }
    };

    private  Emitter.Listener onConnect = new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            try {

                if(isConnected()){

                    JSONObject object = new JSONObject();
                    object.put("event", "join");
                    object.put("uid", username);
                     AppSettings.this.Emit(object, 15, 15, 1, 0);
                }
                else {
                    AppSettings.this.reconnect();
                }


            } catch (JSONException e) {
                Log.d(TAG, e.getMessage());
            }

        }
    };

    private  Emitter.Listener ping = new Emitter.Listener() {
        @Override
        public void call(final Object... args) {

            Log.i("Data", String.valueOf(args[0]));
            try {
                JSONObject object = new JSONObject();
                object.put("beat", 1);
                AppSettings.this.mSocket.emit("pong", object);
            } catch (JSONException e) {
                Log.d(TAG, e.getMessage());
            }
        }
    };

    public static void LogFile(Context context,String transaction,String 
socketID,String receivedID,String methodSocket,String userID,boolean 
Taxiser,String imei){
        try {
            // Creates a trace file in the primary external storage space of the
            // current application.
            // If the file does not exists, it is created.

            Calendar c = Calendar.getInstance();
            SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
            File traceFile = new File(context.getExternalFilesDir(null), 
"GPS_Data.csv");
            if (!traceFile.exists())
                traceFile.createNewFile();
            // Adds a line to the trace file
            BufferedWriter writer = new BufferedWriter(new 
FileWriter(traceFile, true /*append*/));
            writer.write(df.format(c.getTime()) +", "+ transaction + ", 
"+socketID+", "
                    +receivedID+", "+ methodSocket+", "+userID+", 
"+Taxiser+'\n');
            writer.close();
            // Refresh the data so it can seen when the device is plugged in a
            // computer. You may have to unplug and replug the device to see the
            // latest changes. This is not necessary if the user should not 
modify
            // the files.
            MediaScannerConnection.scanFile(context,
                    new String[]{traceFile.toString()},
                    null,
                    null);

        } catch (IOException e) {
           //Log.d("com.cindypotvin.FileTest", "Unable to write to the 
TraceFile.txt file.");
        }
    }

    private  Emitter.Listener method = new Emitter.Listener() {
        @Override
        public void call(Object... args) {

            try {

                long tid = 0;

                JSONObject received_object = (JSONObject) args[0];
                String method = received_object.getString("event");

                Log.d(TAG,"method: "+method+" is called...");

                if(!method.equals("received")) {
                    JSONObject sender_object = new JSONObject();
                    sender_object.put("TID", received_object.getString("TID"));
                    sender_object.put("event","received");
                    AppSettings.this.mSocket.emit("method", sender_object);
                }else{
                    tid = received_object.getLong("TID");
                }

                switch (method){
                    case "DriverConfirmed":

                        //Log.d(TAG,"Socket on DriverConfirm");

                        String driver = received_object.getString("UID");
                        String name = received_object.getString("Name");
                        String driverPhone = received_object.getString("Phone");
                        double lat = received_object.getDouble("lat");
                        double lng = received_object.getDouble("lon");
                        float rating = 
Float.parseFloat(received_object.getString("Rating"));
                        String tripnum = received_object.getString("TripNum");
                        boolean answer = received_object.getBoolean("answer");
                        String driverphoto = 
received_object.getString("driverPhoto");
                        String vehiclephoto = 
received_object.getString("vehiclePhoto");

                        Intent intent_DriverConfirmed = new 
Intent("DriverConfirmed");
                        intent_DriverConfirmed.putExtra("driver",driver);
                        intent_DriverConfirmed.putExtra("name",name);
                        
intent_DriverConfirmed.putExtra("driverPhone",driverPhone);
                        intent_DriverConfirmed.putExtra("lat",lat);
                        intent_DriverConfirmed.putExtra("lon",lng);
                        intent_DriverConfirmed.putExtra("rating",rating);
                        intent_DriverConfirmed.putExtra("tripnum",tripnum);
                        intent_DriverConfirmed.putExtra("answer",answer);
                        
intent_DriverConfirmed.putExtra("driverphoto",driverphoto);
                        intent_DriverConfirmed.putExtra("vehiclephoto", 
vehiclephoto);

                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_DriverConfirmed);

                        break;
                    case "DriverSelected":

                        //Log.d(TAG,"Socket on DriverSelected");

                        String pass = received_object.getString("pass");
                        int requestID = received_object.getInt("requestid");
                        double passlat = received_object.getDouble("lat");
                        double passlng = received_object.getDouble("lon");

                        Intent intent_DriverSelected = new 
Intent("DriverSelected");
                        intent_DriverSelected.putExtra("pass",pass);
                        intent_DriverSelected.putExtra("requestID",requestID);
                        intent_DriverSelected.putExtra("passlat",passlat);
                        intent_DriverSelected.putExtra("passlng", passlng);

                        if (Session.getCurrentLocationInfo() != null) {

                            
NotificationManagement.statiticsNotification(AppSettings.this, 1);
                            Location mCurrentLocation = 
Session.getCurrentLocationInfo();
                            intent_DriverSelected.putExtra("driverlat", 
mCurrentLocation.getLatitude());
                            intent_DriverSelected.putExtra("driverlng", 
mCurrentLocation.getLongitude());

                            
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_DriverSelected);
                        }else{
                            Log.d(TAG, "Current Location isn't available.");
                            Intent intent = new Intent("LOCATION_STATUS");
                            intent.putExtra("message", "Localizacion no 
disponible");
                            
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent);
                        }

                        break;
                    case "TaxiArrived":

                        //Log.d(TAG,"Socket on TaxiArrived");

                        //Verificar si logica sigue igual.
                        Intent intent_TaxiArrived = new Intent("TaxiArrived");
                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_TaxiArrived);

                        break;
                    case "tripcancelled":

                       // Log.d(TAG,"Socket on tripcancelled");

                        //Implementar logica de navegacion en activity 
waitTaxi,GetPassenger,PassengerTrip,
                        ResetTravelElements();

                            Intent intent_tripcancelled = new 
Intent("tripcancelled");
                            
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_tripcancelled);

                        break;
                    case "currentfare":

                        //Log.d(TAG,"Socket on currentfare");

                        String fare = received_object.getString("fare");

                        Intent intent_currentfare = new Intent("currentfare");
                        intent_currentfare.putExtra("fare", fare);
                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_currentfare);

                        break;
                    case "endtrip":

                       // Log.d(TAG,"Socket on endtrip");

                        String tripID = received_object.getString("tripid");
                        String final_fare = received_object.getString("fare");
                        String estimate = received_object.getString("estimate");

                        Intent intent_endtrip = new Intent("endtrip");
                        intent_endtrip.putExtra("tripid",tripID);
                        intent_endtrip.putExtra("fare",final_fare);
                        intent_endtrip.putExtra("estimate", estimate);

                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_endtrip);
                        break;
                    case "location":

                        //Log.d(TAG, "Socket on location");

                        float bearing = 
Double.valueOf(received_object.getString("bearing")).floatValue();
                        boolean billable = 
received_object.getBoolean("billable");
                        double distance = received_object.getDouble("dist");
                        double ltd = received_object.getDouble("lat");
                        double lon = received_object.getDouble("lon");
                        double speed = received_object.getDouble("spd");
                        String tripNum = received_object.getString("tripnum");

                        Intent intent_location = new Intent("location");
                        intent_location.putExtra("bearing",bearing);
                        intent_location.putExtra("billable",billable);
                        intent_location.putExtra("dist",distance);
                        intent_location.putExtra("lat",ltd);
                        intent_location.putExtra("lon",lon);
                        intent_location.putExtra("spd",speed);
                        intent_location.putExtra("lon",lon);
                        intent_location.putExtra("tripnum", tripNum);

                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_location);

                        break;

                    case "received":

                       // Log.d(TAG, "Socket on received");

                        if(tid > 0){
                            if(deleteTransaction(tid)){
                                if(AppSettings.this.Clock != null){
                                    if(getMainContext() != null){
                                        
AppSettings.this.stopClockWaitTime(AppSettings.this.getMainContext());
                                    }
                                }
                            }
                        }else{
                            if(AppSettings.this.Clock != null){
                                if(getMainContext() != null){
                                    
AppSettings.this.stopClockWaitTime(AppSettings.this.getMainContext());
                                }
                            }
                        }
                        Intent intent_received = new Intent("received");
                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_received);

                        return;


                    case "PassengerReceipt":

                        //Log.d(TAG,"Socket on PassengerReceipt");

                        String TID = received_object.getString("TripNum");
                        String passenger = received_object.getString("PID");

                        Intent intent_PassengerReceipt = new 
Intent("PassengerReceipt");
                        intent_PassengerReceipt.putExtra("tripnum", TID);
                        intent_PassengerReceipt.putExtra("pass", passenger);
                        
LocalBroadcastManager.getInstance(AppSettings.this).sendBroadcast(intent_PassengerReceipt);

                        break;
                }

                LogFile(getApplicationContext(), 
received_object.getString("TID"), AppSettings.this.mSocket.id(), 
AppSettings.this.mSocket.id(), received_object.getString("event"), 
AppSettings.this.getUsername()
                        , Session.getDriver(), Session.getEmei());
            }
            catch (JSONException e){
                Log.d(TAG,e.getMessage());
            }
        }
    };
} 

-- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to android-developers+unsubscr...@googlegroups.com.
To post to this group, send email to android-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/android-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/android-developers/730fc15c-e5b7-449e-b0ed-64eb7eea688b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to