4242import android .opengl .GLSurfaceView ;
4343import android .os .Handler ;
4444import android .util .AttributeSet ;
45+ import android .view .View ;
4546import android .widget .RelativeLayout ;
4647import android .widget .Toast ;
4748import androidx .annotation .NonNull ;
@@ -239,11 +240,7 @@ public void startRenderer(int delayMillis) {
239240 }
240241
241242 private void removeGLSurfaceView () {
242- ((Activity ) getContext ()).runOnUiThread (() -> {
243- if (glSurfaceView != null ) {
244- JmeSurfaceView .this .removeView (glSurfaceView );
245- }
246- });
243+ ((Activity ) getContext ()).runOnUiThread (() -> JmeSurfaceView .this .removeView (glSurfaceView ));
247244 }
248245
249246 @ Override
@@ -265,19 +262,34 @@ public void handleError(String errorMsg, Throwable throwable) {
265262 public void onStateChanged (@ NonNull LifecycleOwner source , @ NonNull Lifecycle .Event event ) {
266263 switch (event ) {
267264 case ON_DESTROY :
268- /*destroy only if the policy flag is enabled*/
269- if ( destructionPolicy == DestructionPolicy . DESTROY_WHEN_FINISH ) {
270- legacyApplication . stop (! isGLThreadPaused ());
271- }
265+ // activity is off the foreground stack
266+ // activity is being destructed completely as a result of Activity#finish()
267+ // this is a killable automata state!
268+ jmeSurfaceViewLogger . log ( Level . INFO , "Hosting Activity has been destructed." );
272269 break ;
273270 case ON_PAUSE :
274- loseFocus ();
271+ // activity is still on the foreground stack but not
272+ // on the topmost level or before transition to stopped/hidden or destroyed state
273+ // as a result of dispatch to Activity#finish()
274+ // activity is no longer visible and is out of foreground
275+ if (((Activity ) getContext ()).isFinishing ()) {
276+ if (destructionPolicy == DestructionPolicy .DESTROY_WHEN_FINISH ) {
277+ legacyApplication .stop (!isGLThreadPaused ());
278+ } else if (destructionPolicy == DestructionPolicy .KEEP_WHEN_FINISH ) {
279+ jmeSurfaceViewLogger .log (Level .INFO , "Context stops, but game is still running." );
280+ }
281+ } else {
282+ loseFocus ();
283+ }
275284 break ;
276285 case ON_RESUME :
286+ // activity is back to the topmost of the
287+ // foreground stack
277288 gainFocus ();
278289 break ;
279290 case ON_STOP :
280- jmeSurfaceViewLogger .log (Level .INFO , "Context stops, but game is still running" );
291+ // activity is out off the foreground stack or being destructed by a finishing dispatch
292+ // this is a killable automata state!
281293 break ;
282294 }
283295 }
@@ -405,11 +417,12 @@ public void loseFocus() {
405417 @ Override
406418 public void destroy () {
407419 /*skip the destroy block if the invoking instance is null*/
408- if (legacyApplication == null ) {
409- return ;
420+ if (glSurfaceView != null ) {
421+ removeGLSurfaceView ();
422+ }
423+ if (legacyApplication != null ) {
424+ legacyApplication .destroy ();
410425 }
411- removeGLSurfaceView ();
412- legacyApplication .destroy ();
413426 /*help the Dalvik Garbage collector to destruct the pointers, by making them nullptr*/
414427 /*context instances*/
415428 legacyApplication = null ;
@@ -430,10 +443,10 @@ public void destroy() {
430443 onRendererCompleted = null ;
431444 onExceptionThrown = null ;
432445 onLayoutDrawn = null ;
433- /*nullifying the static memory (pushing zero to registers to prepare for a clean use)*/
434446 GameState .setLegacyApplication (null );
435447 GameState .setFirstUpdatePassed (false );
436- jmeSurfaceViewLogger .log (Level .INFO , "Context and Game have been destructed" );
448+ JmeAndroidSystem .setView (null );
449+ jmeSurfaceViewLogger .log (Level .INFO , "Context and Game have been destructed." );
437450 }
438451
439452 @ Override
@@ -516,11 +529,13 @@ public void bindAppStateToActivityLifeCycle(final boolean condition) {
516529 /*register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
517530 if (getContext () instanceof LifecycleOwner ) {
518531 ((LifecycleOwner ) getContext ()).getLifecycle ().addObserver (JmeSurfaceView .this );
532+ jmeSurfaceViewLogger .log (Level .INFO , "Command binding SurfaceView to the Activity Lifecycle." );
519533 }
520534 } else {
521535 /*un-register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner*/
522536 if (getContext () instanceof LifecycleOwner ) {
523537 ((LifecycleOwner ) getContext ()).getLifecycle ().removeObserver (JmeSurfaceView .this );
538+ jmeSurfaceViewLogger .log (Level .INFO , "Command removing SurfaceView from the Activity Lifecycle." );
524539 }
525540 }
526541 }
@@ -917,7 +932,7 @@ public void setShowErrorDialog(boolean showErrorDialog) {
917932 }
918933
919934 /**
920- * Determines whether the app context would be destructed
935+ * Determines whether the app context would be destructed as a result of dispatching {@link Activity#finish()}
921936 * with the holder activity context in case of {@link DestructionPolicy#DESTROY_WHEN_FINISH} or be
922937 * spared for a second use in case of {@link DestructionPolicy#KEEP_WHEN_FINISH}.
923938 * Default value is : {@link DestructionPolicy#DESTROY_WHEN_FINISH}.
@@ -926,12 +941,14 @@ public void setShowErrorDialog(boolean showErrorDialog) {
926941 */
927942 public enum DestructionPolicy {
928943 /**
929- * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication}).
944+ * Finishes the game context with the activity context (ignores the static memory {@link GameState#legacyApplication})
945+ * as a result of dispatching {@link Activity#finish()}.
930946 */
931947 DESTROY_WHEN_FINISH ,
932948 /**
933949 * Spares the game context inside a static memory {@link GameState#legacyApplication}
934- * when the activity context is destroyed, but the app stills in the background.
950+ * when the activity context is destroyed dispatching {@link Activity#finish()}, but the {@link android.app.Application}
951+ * stills in the background.
935952 */
936953 KEEP_WHEN_FINISH
937954 }
0 commit comments