spine_libgdx version: 3.8.55
libgdx version: 1.9.10
We have a spine box embedded in a fragment via AndroidFragmentApplication(https://github.com/libgdx/libgdx/blob/master/backends/gdx-backend-android/src/com/badlogic/gdx/backends/android/AndroidFragmentApplication.java)
When an activity containing this fragment is in the foreground and the device is quickly turned on/off, one of two things happens frequently:
1) The app will crash with log messages similar to these:
2019-12-17 16:21:30.756 187-203/? E/SurfaceFlinger: Permission Denial: can't openGlobalTransaction pid=12382, uid<=10099
2019-12-17 16:21:30.756 12382-12444/<APP> E/BpSurfaceComposerClient: Failed to transact (-1)
2019-12-17 16:21:30.756 187-1175/? E/SurfaceFlinger: Permission Denial: can't openGlobalTransaction pid=12382, uid<=10099
2019-12-17 16:21:30.756 12382-12444/<APP> E/BpSurfaceComposerClient: Failed to transact (-1)
2019-12-17 16:21:35.953 396-411/system_process W/ActivityManager: Activity pause timeout for ActivityRecord{482aeae u0 <APP>/.<APP LIBGDX ACTIVITY> t118}
2019-12-17 16:21:36.727 12382-12382/<APP> I/AppLifecycleTracker: App transition to foreground
2019-12-17 16:21:36.767 12382-12382/<APP> I/AndroidInput: sensor listener setup
2019-12-17 16:21:36.778 12382-12444/<APP> I/AndroidGraphics: resumed
019-12-17 16:21:45.875 12382-12382/<APP> E/AndroidGraphics: waiting for pause synchronization took too long; assuming deadlock and killing
2019-12-17 16:22:47.816 12509-12509/<APP> E/ActivityThread: Performing stop of activity that is already stopped: {<APP>/<APP MAIN ACTIVITY>}
java.lang.RuntimeException: Performing stop of activity that is already stopped: {<APP>/<APP>.MainActivity}
at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:3996)
at android.app.ActivityThread.handleStopActivity(ActivityThread.java:4084)
at android.app.ActivityThread.-wrap24(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1622)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
2019-12-17 16:22:47.816 12509-12509/<APP> E/ActivityThread: ActivityClientRecord{paused=true, stopped=true, hideForNow=false, startsNotResumed=false, isForward=true, pendingConfigChanges=0, onlyLocalRequest=false, preserveWindow=false, Activity{resumed=false, stopped=true, finished=false, destroyed=false, startedActivity=true, temporaryPause=false, changingConfigurations=false}}
or,
2) The app will resume mostly correctly, except in the fragment that is supposed to be rendering the character in Spine, there will be two copies of the character rendered on the screen; the one in front animating correctly, and one behind that is frozen.
2019-12-17 14:39:21.362 187-187/? D/SurfaceFlinger: duplicate layer name: changing SurfaceView - <APP>/<APP MAIN ACTIVITY> to SurfaceView - <APP>/<APP LIBGDX ACTIVITY>#1
2019-12-17 14:39:21.362 187-187/? D/SurfaceFlinger: duplicate layer name: changing Background for - SurfaceView - <APP>/<APP LIBGDX ACTIVITY> to Background for - SurfaceView - <APP>/<APP LIBGDX ACTIVITY>#1
2019-12-17 14:39:21.363 10068-10187/<APP> W/GLSurfaceView: Warning, !readyToDraw() but waiting for draw finished! Early reporting draw finished.
2019-12-17 14:39:21.364 187-251/? E/SurfaceFlinger: Failed to find layer (SurfaceView - <APP>/<APP LIBGDX ACTIVITY>#0) in layer parent (no-parent).
2019-12-17 14:39:21.364 187-203/? E/SurfaceFlinger: Failed to find layer (Background for - SurfaceView - <APP>/<APP LIBGDX ACTIVITY> in layer parent (no-parent).
2019-12-17 14:39:21.373 187-187/? D/SurfaceFlinger: Set power mode=2, type=0 flinger=0x7f6105e000
2019-12-17 14:39:21.373 396-408/system_process I/ActivityManager: Activity reported stop, but no longer stopping: ActivityRecord{87af700 u0 <APP>/<APP LIBGDX ACTIVITY> t114}
We suspect that there may be some resources that are not being correctly cleaned up on pause/destroy, and any pointers as to what that might be would be helpful.
For reference, our use of spine is pretty simple:
public final class MyAdapter extends ApplicationAdapter {
private OrthographicCamera camera;
private PolygonSpriteBatch batch;
private SkeletonRenderer renderer;
private SpineFiles spineFiles;
private TextureAtlas atlas;
private Skeleton skeleton;
private AnimationState animationState;
@Override
public void create() {
camera = new OrthographicCamera();
batch = new PolygonSpriteBatch();
renderer = new SkeletonRenderer();
renderer.setPremultipliedAlpha(true);
created = true;
loadSpineFiles();
}
@Override
public void render() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
if (skeleton != null) {
animationState.update(Gdx.graphics.getDeltaTime()); // Update the animation time.
animationState.apply(skeleton);
skeleton.updateWorldTransform();
camera.update();
batch.getProjectionMatrix().set(camera.combined);
batch.begin();
renderer.draw(batch, skeleton); // Draw the skeleton images.
batch.end();
}
}
@Override
public void dispose() {
batch.dispose();
created = false;
if (atlas != null) {
atlas.dispose();
}
}
private void loadSpineFiles() {
atlas = new TextureAtlas(spineFiles.atlasFile());
SkeletonJson json = new SkeletonJson(atlas);
SkeletonData skeletonData = json.readSkeletonData(spineFiles.jsonFile());
skeleton = new Skeleton(skeletonData);
AnimationStateData stateData = new AnimationStateData(skeletonData);
animationState = new AnimationState(stateData);
animationState.setTimeScale(1);
}