AppWarp persists listeners and/or events when app crashes or client is not closed properly

+1 vote

I have android Game that uses AppWarp,

JFYI since the code base is quite complicated to share everything is very modular and distributed to multiple small classes so It might be better to describe the issue and how I debugged it.

First I'll describe what I'm doing there (Currently contains a lot of hacks even).

0-I have a nice debug log saying Main Activity of the app is created OnCreate(..).

1-I Instantiate AppWarp with key/secret.

2-Make sure the it's currently diconnected <-- Pure hack, normally shouldn't be like that.

2-Try to remove any listener (even 2 times). <-- Pure hack that normally should not be necessary.

3-Attach list of listeners Zone,Connection .... etc.

4-Connect AppWarp. and debug log just before asking for connect.

5-Debug log on every single method of the listeners. <-- Even the events that I never use (just in case).

6-When the user clicks start game ( I log debug this).

7-I search for old rooms that were not terminated properly, I first start search for room where the current user is "guestUser" (that's how I name it in the room properties).

8-I search for old rooms that were not terminated properly where the current use is "hostUser".

9-If I found any of the above (old rooms) and If I'm the host I terminate it, if I'm the guest, I don't do anything for now.

10-If I didn't find old rooms (usually the case): I search for rooms with at least and at most 1 user.

11-if (I didn't find rooms to join, then I create a room and join, and subscribe to it).

General note: for all the searching and finding / not finding logic I always use event-based call backs, i.e. if I search for rooms to join and the event is done and the result doesn't have rooms, then I move to creating a new room .... etc, I only ask to join a room once creation is done, I ask for subscribing only when joining is done ...... etc.

Now that's what I'm currently Getting with the happy scenario:

1-App starts,

2-Connection done.

3-No old rooms found.

4-No rooms with 1 user found.

5-I create room

6-I join and subscribe to room.

7-I wait.

8-14:  User 2 from my other phone repeates the same steps exactly except that He finds room with 1 user and joins then game starts.

15-The game crashes on one phone

16-The game becomes paused on the other phone (the phone that didn't have a crash).

17-The game ends after the pause time ends (20 seconds in my case).

Now the trouble STARTS

1-I launch the app where the app crashed last time.

2-I instantiate the client.

3-I make sure its status is "Disconnected" i.e. Status 2.

4-I try to remove all the listeners that I never added since this launch.

5-I connect the client then I get connection done

6-I search for old rooms and find nothing.

7-I Search for rooms to join and find nothing.

8-I get a very random connection done event. <---- very suspicous.

9-I get another very random connection done. <----- very suspicous.

10-I choose to create room

11-I get room created done.

12-I get another room created done. <----- very suspicous.

13-I get a thirdt room created done. <----- very suspicous.

Each of these events try to do something to interact with UI, (The app crashes of course due to conflict of so many things).

14-I repeat the same bad scenario and I get more and more events triggered, as If the App Warp client is still persisting with so many events and listeners without any easy way to reset or clean it.

 

Now this is the scenario, My questions come next:

1-Is there any easy way to Completely and fully hard-reset the client without hacks (Reflection and accessing private properties) ?

2-Do you have open source version of the client ( i can decompile it but it's not the proper way to do things) ?

3-Are you persisting events / listeners or anything on disk or memory that doesn't terminate with the app?

 

How to reproduce:

1-Create a very simple Android app with 1 activity.

2-Create an external class that you'll use as a listener and implement the appropriate Listener Interfaces.

3-Initialize WarpClient.

4-Add the external listener class that your created.

5-Connect to AppWarp, Create a room,

6-From another phone/app you need to join the same room.

7-Now in your app, force throwing an exception on click on one view or something.

8-Start the app again, and repeat the steps above, then inspect the WarpClient, and especially the list of listeners, you'll find it duplicated.

9-Crash the app again and repeat the steps above, and you'll find 3 listeners .... etc

asked Nov 24, 2015 in AppWarp by shehabic (15 points)
edited Nov 27, 2015 by shehabic
Hi Shehab,
Thanks for sharing the details. We are trying to replicate the same at our end and will update this thread as soon as possible on the same.

Thanks.

1 Answer

0 votes

Hi Shehab,

Thanks for writing to us.We will definitely try to resove the same.

We are trying to reproduce the same on our end. So regarding the callBack listener, Yet I will found the following scenrio that I need to confirm like :

  1. Its happening only when the app crashes Or Its the general scenerio when application is in pause state or and we resume it again
  2. It will also depends how you are attaching callback listeners by creating a separate class of Connection , Zone and Notification listener and attaching that calls object references in MainActivity.
  3. Each and every class gets the callBack on which callBack listenere are added.
  4. Where you are adding and removing callBack listeners in activity lifecycle methods

Please let me know on which Activity lifecycle method you are adding and removing the listener, meanwhile we are reproducing the same

Thanks & Regards

Vishnu Garg

AppWarp Support Team

answered Nov 25, 2015 by Vishnu Garg (674 points)
It only happens when I don't disconnect manually, I couldn't reproduce this with the latest version of the ApiSDK for Android, I also might have been using the Java-SDK for android instead of the Android SDK (would this be a problem)? and would the Client be persisted in a different way in the Android SDK than in the JAVA SDK?
I would suggest to use latest version of Android SDK. And If you don't disconnect it manually user will remain on server for specific time after that Server disconnect the same. Its is useful feature of connection resiliency.
I can confirm that this happens with the latest Android SDK if the app crashes, and disconnect is not triggered, the next time I open the app I see that all the old request listeners are still persisted, here's an interesting piece of log.:

https://gist.github.com/shehabic/8d2a47b86fd451c81b03

Notice: I used reflection to get such data via:

https://gist.github.com/shehabic/908798a6bb691a6eb773 (If you'd like me to remove this I will)


But I also noticed connection error 1, then error 6 when trying to connect again.
My current work around would be to reflect and cleanup all the old listeners that are persisting for some reason that I don't know.

Also notice that my app has 1 Activity (so far) and multiple fragments and the WarpClient is a local Member of the Activity Class, I really don't know how this activity crashes and is destroyed, then the client is persisted
So WarpClient is signleton object whenEver you resume the app and try to add callBack listener again  then it will add the object reference again if it is new Object. thats why you are getting three callBacks on your connection Listener class.
And whenever you are not disconnecting the user when it leaves, server retain it for some specific time after that disconnect it, in that case you will error code 1 means Auth error,
So without using reflection will you share where you are adding and removing callbacks and how.
Here it is:

MainActivity
https://gist.github.com/shehabic/d74ae813d285f97ef19a

Her's WarpListener
https://gist.github.com/Mohamed-Shehab/d29d289a763481435fdf

(I removed most of the things unrelated to Warp of course)
As you are creating the separate callbacks, and when app crashes happens and app reopened again so previous listener are not removed as we are adding them by creating new obejct WarpListener.So at the second time when you open it again as warp Client is singleton class its already instantiated . And previous callbacks are added and in this we are again adding new Callabacks.
So whenever an event occured WarpClient notify all the observer those are added to it, and you will get notification more than one time.
Actually I know what's happening, but what do you propose for a solution for this, (App Crash) is not the normal case, but it would happen.
We are taking as it input and try to resolve how can we remove unnecessary callback listener on the same class.
For App crash can you please share the exception you are getting, so that we can resolve it at priority level.
Well the crash is not really related to appWarp it's something in the game's logic, I keep fixing bugs/crashes as it appears, but I'm just saying that if it happened for some reason and the user restarted the app, he'll keep adding listeners and then the app will crash, because multiple events will try to trigger different things in the UI, so he restarts more and more and keeps adding new listeners every time, so unless the user explicitly forces closing the app, the problem will persist, for not my hack/work-around is that I do reflection and clear the old listeners when activity onCreate is triggered, but it would be nice to have a public method in your client with something like: removeAllListeners or something similar to avoid such issue.
Yes, We are planning to clean the same whenever any initialization happens, but again we need to test it properly so that we can remove unnecessary callbacks.
Hi again, I updated the original question with a part about how to reproduce easily just in case you needed this, for my app it's a bit more complicated than that as I have a backend for my app I'm not Using App42 for that, but instead a custom-made API, so sharing the code, isn't that simple, it involves many UI and API stuff.
Download Widgets
Welcome to ShepHertz Product line forum, where you can ask questions and receive answers from the community. You can also reach out to us on support@shephertz.com
...