Android app crashes sporadically when resuming

83 views
Skip to first unread message

Christoph Dietze

unread,
Feb 14, 2014, 7:31:15 PM2/14/14
to pl...@googlegroups.com
Hola!

I cannot reproduce this bug yet. It happened 4 times so far, always immediately after resuming the App.

What seems to happen is that a Transition is being completed that wants to remove the old top layer which is not found and playn crashes.

I am not sure if it's an application or a playn or a tripleplay problem.

I paused the app many times in mid-transition but had no luck in reproducing it.

I used proguard so the stacktrace looks a bit messy because of the deobfuscation.
java.lang.UnsupportedOperationException: Could not remove Layer because it is not a child of the GroupLayer
at playn
.core.GroupLayerImpl.int add(playn.core.GroupLayer,playn.core.AbstractLayer)(Unknown Source)
                             
void remove$64617f06(playn.core.AbstractLayer)
                             
void removeAll$5719e7f()
                             playn
.core.Layer hitTest(playn.core.GroupLayer,pythagoras.f.Point)
                             
int depthChanged$2ddf7efb(playn.core.Layer,float)
                             
void remove(int)
                             
int findChild(playn.core.AbstractLayer,float)
                             
int findInsertion(float)
at playn
.core.gl.GroupLayerGL.void remove(playn.core.Layer)(Unknown Source)
                             
void removeAll()
                              playn
.core.Layer hitTestDefault(pythagoras.f.Point)
at tripleplay
.game.ScreenStack.int size()(Unknown Source)
                               
void hide(tripleplay.game.Screen)
at tripleplay
.game.ScreenStack$2.void onComplete()(Unknown Source)
at tripleplay
.game.ScreenStack$Transitor.void complete()(Unknown Source)
at tripleplay
.game.ScreenStack$Transitor.void update(int)(Unknown Source)
                                         
void paint(playn.core.util.Clock)
                                         
void onComplete()
at tripleplay
.game.ScreenStack.void push(tripleplay.game.Screen)(Unknown Source)
                               
void push(java.lang.Iterable)
                               
void replace(tripleplay.game.Screen,tripleplay.game.ScreenStack$Transition)
                               
void update(int)
                               
void paint(playn.core.util.Clock)
                               tripleplay
.game.ScreenStack$Transition defaultPushTransition()
                               
void transition(tripleplay.game.ScreenStack$Transitor)
                               
void handleError(java.lang.RuntimeException)
at creek
.playn.core.CreekGame.void init()(Unknown Source)
                             
void update(int)
                             
void paint(float)
                             
long access$002(creek.playn.core.CreekGame,long)
                              com
.google.common.base.Optional access$100(creek.playn.core.CreekGame)
                              com
.google.common.base.Optional access$102(creek.playn.core.CreekGame,com.google.common.base.Optional)
at playn
.core.Game$Default.void tick(int)(Unknown Source)
at playn
.android.AndroidPlatform.void update()(Unknown Source)
at playn
.android.GameViewGL$1.void onDrawFrame(javax.microedition.khronos.opengles.GL10)(Unknown Source)
at android
.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1523)
at android
.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

Any ideas?

Brigt Vik

unread,
Feb 15, 2014, 5:22:24 AM2/15/14
to pl...@googlegroups.com
You haven't been able to reproduce it reliably, so this may not be all that helpful, but you could at least add a try-catch around the remove operation and put a breakpoint or extra logging statements whenever an UnsupportedOperationException is thrown.

Alternatively, you could change the PlayN code to silently ignore remove calls where the layer is not a child, rather than throw that exception (the same way an ArrayList will accept remove calls for objects not stored in it). Chances are that you'll want to discover what is actually happening to the layers rather than "bury" the problem though - there's no telling what weirdness could arise from whatever is happening.

Christoph Dietze

unread,
Feb 16, 2014, 11:01:03 AM2/16/14
to pl...@googlegroups.com
The problem hasn't shown up again. I assume is it gone forever.
just kidding, of course :(

I guess I will take the route you describe and add more log statements to trace the circumstances.


On Sat, Feb 15, 2014 at 11:22 AM, Brigt Vik <bov...@gmail.com> wrote:
You haven't been able to reproduce it reliably, so this may not be all that helpful, but you could at least add a try-catch around the remove operation and put a breakpoint or extra logging statements whenever an UnsupportedOperationException is thrown.

Alternatively, you could change the PlayN code to silently ignore remove calls where the layer is not a child, rather than throw that exception (the same way an ArrayList will accept remove calls for objects not stored in it). Chances are that you'll want to discover what is actually happening to the layers rather than "bury" the problem though - there's no telling what weirdness could arise from whatever is happening.

--
 
---
You received this message because you are subscribed to a topic in the Google Groups "PlayN" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/playn/nv7gFrVRDTw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to playn+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Michael Bayne

unread,
Feb 17, 2014, 1:10:15 PM2/17/14
to pl...@googlegroups.com
On Fri, Feb 14, 2014 at 4:31 PM, Christoph Dietze
<christop...@gmail.com> wrote:
> Any ideas?

Are you manually removing screen layers anywhere or calling
removeAll() on graphics().rootLayer() or anything like that?

Otherwise, I dunno. I've not seen this error in any of my games that
use TPGame and a screen stack.

-- m...@samskivert.com

Christoph Dietze

unread,
Mar 2, 2014, 7:42:19 AM3/2/14
to pl...@googlegroups.com
I have now been able to reproduce the exception (thanks to the amazon app test):
  1. Install and launch the app.
  2. Push any screen.
  3. Hibernate the device, and change the orientation.
  4. Unlock the device.
  5. The app Force Closes. 
The problem is that after rotation the Android Activity is initialized again: onCreate is called resulting in Game.init() being called again. This would just mean the app is restarting but I put the ScreenStack into a static variable (just like https://github.com/threerings/atlantis). So the problem was that a new game was using an old ScreenStack...

Here is the unobfuscated stacktrace:

03-02 12:31:43.898: E/AndroidRuntime(3299): java.lang.UnsupportedOperationException: Could not remove Layer because it is not a child of the GroupLayer
03-02 12:31:43.898: E/AndroidRuntime(3299): at playn.core.GroupLayerImpl.remove(GroupLayerImpl.java:80)
03-02 12:31:43.898: E/AndroidRuntime(3299): at playn.core.gl.GroupLayerGL.remove(GroupLayerGL.java:119)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack.hide(ScreenStack.java:333)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack$2.onComplete(ScreenStack.java:107)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack$Transitor.complete(ScreenStack.java:415)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack.transition(ScreenStack.java:351)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack.push(ScreenStack.java:106)
03-02 12:31:43.898: E/AndroidRuntime(3299): at tripleplay.game.ScreenStack.push(ScreenStack.java:93)
03-02 12:31:43.898: E/AndroidRuntime(3299): at creek.playn.core.CreekGame.init(CreekGame.java:68)
03-02 12:31:43.898: E/AndroidRuntime(3299): at playn.android.AndroidPlatform.run(AndroidPlatform.java:158)
03-02 12:31:43.898: E/AndroidRuntime(3299): at playn.core.PlayN.run(PlayN.java:74)
03-02 12:31:43.898: E/AndroidRuntime(3299): at creek.playn.android.CreekActivity.main(CreekActivity.java:44)
03-02 12:31:43.898: E/AndroidRuntime(3299): at playn.android.GameViewGL$3.run(GameViewGL.java:103)
03-02 12:31:43.898: E/AndroidRuntime(3299): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1463)
03-02 12:31:43.898: E/AndroidRuntime(3299): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

I changed the ScreenStack into an instance variable of Game and now it's not crashing anymore :-)

However, I wonder if restarting the App in these circumstances is really necessary!?

Michael Bayne

unread,
Mar 2, 2014, 1:06:03 PM3/2/14
to pl...@googlegroups.com
On Sun, Mar 2, 2014 at 4:42 AM, Christoph Dietze
<christop...@gmail.com> wrote:
> However, I wonder if restarting the App in these circumstances is really
> necessary!?

Welcome to the wonderful world of Android development where bad design
and buggy vendor implementations conspire to make your life hell.

Indeed, restarting the app seems like a really stupid thing to do in
these circumstances, but that's what Android does. Yay! I think it's
because they originally didn't have an orientation change
notification, so the only way to "tell" your activity that orientation
changed was to restart it. Genius! So now they try to preserve that
backwards compatible behavior unless you go out of your way to tell it
not to.

You can mostly get it to stop restarting your activity by ensuring
that you've specified that you want notifications for orientation
changes, but I've also seen phone-specific bugs where those
notifications are not delivered and the OS just restarts your activity
anyway, and I don't know how to work around that.

Be sure that your <activtity> tag in AndroidManifest.xml has

android:configChanges="keyboardHidden|orientation|screenSize"

and I also recommend having:

android:launchMode="singleTask"

because that minimizes other surprises. You should also be sure to
have a reasonably high targetSdkVersion in your <uses-sdk> tag because
that also sometimes triggers non-stupid behavior. AFAIK, there's no
downside to having the latest possible SDK there, so 19 is the one you
want currently. Though 18 is the highest I've ever used, so you may
want to use that to be conservative.

-- m...@samskivert.com

Christoph Dietze

unread,
Mar 3, 2014, 4:27:16 PM3/3/14
to pl...@googlegroups.com
I was missing the screenSize in android:configChanges. After I added that the app does not restart anymore! Yeeha!

Thanks! Also for the other advice!
Reply all
Reply to author
Forward
0 new messages