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 [email protected].
To post to this group, send email to [email protected].
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.