How to end SDLActivity correctly

Hello World,

I’m trying to find a way to end my android App correctly, which is native and based on SDLActivity.
Ending the hard way via homebutton always works. But now I want to implement an exitbutton in my app which enables the user to end it more elegant.

So when the button has been triggered, I’m cleaning all up, killing all my singletons and leave my mainloop. Then I “return 0” out of “int main(int argc, char* argv[])”. That’s all on native side.
The app ends seemingly. But when I press homebutton on my device, I can see that the app is still there on standby. [Shocked]
If I try to open it, it crashes and there comes the black screen with “… has been stoped”.
And only then the app is really gone.

This is not elegant. :?

Can anyone help me ?

Thanx in advance,

Michael

Hi,

Android apps are not automatically unloaded even after the onDestroyed()
callback, e.g. when they are in the destroyed lifecycle state. They will
only be removed from memory if more recently started apps would require
memory themselfes. This is probably intentional to have a faster re-start of
apps.

As a consequence, all code needs to be “re-startable”, e.g. not relying on
static initialization which is only executed when the code/the library is
initially loaded into memory. (There was also a posting to this list where a
method is described that removes this requirement from native code, but it
means more effort to place all your code into an additional native library
which you unload upon onDestroy())

I guess that in your case the app successfully enters the “destroyed” state,
but upon restart sth. goes wrong because some code does not work when being
called a 2nd time. You should see that in the stacktrace when your app
crashes.

Regards,

Daniel

---------- P?vodn? zpr?va ----------
Od: Edition Cham??leon
Komu: sdl at lists.libsdl.org
Datum: 14. 12. 2016 16:46:35
P?edm?t: [SDL] How to end SDLActivity correctly

"

Hello World,

I’m trying to find a way to end my android App correctly, which is native
and based on SDLActivity.
Ending the hard way via homebutton always works. But now I want to implement
an exitbutton in my app which enables the user to end it more elegant.

So when the button has been triggered, I’m cleaning all up, killing all my
singletons and leave my mainloop. Then I “return 0” out of “int main(int
argc, char* argv[])”. That’s all on native side.
The app ends seemingly. But when I press homebutton on my device, I can see
that the app is still there on standby. Shocked
If I try to open it, it crashes and there comes the black screen with “…
has been stoped”.
And only then the app is really gone.

This is not elegant. Confused

Can anyone help me ?

Thanx in advance,

Michael_______________________________________________
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
"

1 Like

I’d like to add some logcat:

on 03.004 my native is ending “int main” and SDLActivity jumps in “handleNativeExit()” (sounds and feels right)
but on 03.014 it jumps in “onPause()” [Shocked] (why is that?)
on 03.404 the app is seemingly closed ( but as I wrote it’s only seemingly = the app is still standby )

using homebutton to see standby apps and so on … is all after 03.404

Code:
12-14 17:02:03.004: V/Mw(3679): I: 342 ,T: 0 > MwAppUpdater::~MwAppUpdater end.
12-14 17:02:03.004: V/SDL(3679): class SDLSurface public void surfaceChanged : Native thread finished +++++++++++++++++++++++++++++++++++++++++++++
12-14 17:02:03.004: V/SDL(3679): SDLActivity.java public static void handleNativeExit() reached
12-14 17:02:03.014: V/Mw(3679): ECActivity onPause() reached
12-14 17:02:03.014: V/SDL(3679): SDLActivity.java protected void onPause() reached
12-14 17:02:03.014: V/SDL(3679): SDLActivity.java public static void handleNativeExit() end.
12-14 17:02:03.014: V/SDL(3679): SDLActivity.java public static void handlePause() jumping to native SDLActivity.nativePause().
12-14 17:02:03.014: V/SDL(3679): nativePause()
12-14 17:02:03.014: V/SDL(3679): SDLActivity.java public static void handlePause() returning from native SDLActivity.nativePause().
12-14 17:02:03.014: I/SensorManagerA(3679): getReportingMode :: sensor.mType = 1
12-14 17:02:03.024: D/SensorManager(3679): unregisterListener ::
12-14 17:02:03.024: V/SDL(3679): SDLActivity.java protected void onPause() end.
12-14 17:02:03.024: V/Mw(3679): ECActivity onPause() end
12-14 17:02:03.204: V/SDL(3679): surfaceDestroyed()
12-14 17:02:03.364: W/IInputConnectionWrapper(3679): showStatusIcon on inactive InputConnection
12-14 17:02:03.404: V/Mw(3679): ECActivity onDestroy() reached
12-14 17:02:03.404: V/SDL(3679): SDLActivity.java protected void onDestroy() reached
12-14 17:02:03.404: V/SDL(3679): SDLActivity.java protected void onDestroy() end.
12-14 17:02:03.404: V/Mw(3679): ECActivity onDestroy() end
12-14 17:02:21.614: V/Mw(3679): ECActivity.java protected void onCreate(Bundle savedInstanceState) reached
12-14 17:02:21.614: V/SDL(3679): SDLActivity.java protected void onCreate(Bundle savedInstanceState) reached with singleton:null
12-14 17:02:21.624: V/SDL(3679): SDLActivity.java protected void onCreate(Bundle savedInstanceState) end.
12-14 17:02:21.624: V/Mw(3679): ECActivity.java private void initMw() reached
12-14 17:02:21.624: V/Mw(3679): Java_org_libsdl_app_SDLActivity_SendAssManToNative reached
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18621 > native routine for assetmanagertransfere reached
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18621 > JNICALL Java_org_libsdl_app_SDLActivity_SendAssManToNativ : loaded assetmanager
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18621 > Trying to jump into TAssReader and set AAssetManager mgr
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18621 > Loaded Assetmanager in nativ MwAndroidAssetReader!
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18621 > The Assetmanager is set in TAssReader
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > Java_de_editionchamaeleon_ECApp_ECActivity_SendScreenSizeToNative: Setting ScreenSize in NativCode : 960 , 540
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::MwAppConst() reached
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::MwAppConst() init MwGELib version 1.0.1
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::CalcLevelSize() reached
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::CalcLevelSize() end
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::MwAppConst() end
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::SetDeviceScreenSize reached with 960,540
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::CalcBestScaledScreenSize reached
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::CalcBestScaledScreenSize end
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18622 > MwAppConst::SetDeviceScreenSize end
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18623 > Java_de_editionchamaeleon_ECApp_ECActivity_SetLanguage: result: de
12-14 17:02:21.624: V/Mw(3679): I: 342 ,T: 18623 > Java_de_editionchamaeleon_ECApp_ECActivity_SetLanguage: Setting TCons::InitLanguage: de
12-14 17:02:21.624: V/Mw(3679): ECActivity.java private void initMw() end
12-14 17:02:21.624: V/Mw(3679): ECActivity.java protected void onCreate(Bundle savedInstanceState) end.
12-14 17:02:21.624: V/SDL(3679): SDLActivity.java protected void onResume() reached
12-14 17:02:21.624: V/SDL(3679): SDLActivity.java public static void handleResume() reached
12-14 17:02:21.624: V/SDL(3679): SDLActivity.java public static void handleResume() end.
12-14 17:02:21.624: V/SDL(3679): SDLActivity.java protected void onResume() end.
12-14 17:02:21.664: V/SDL(3679): surfaceCreated()
12-14 17:02:21.664: V/SDL(3679): surfaceChanged()
12-14 17:02:21.664: V/SDL(3679): pixel format RGB_565
12-14 17:02:21.664: V/SDL(3679): Window size:960x540
12-14 17:02:21.664: I/SensorManagerA(3679): getReportingMode :: sensor.mType = 1
12-14 17:02:21.674: D/SensorManager(3679): registerListener :: 0, MPU-6K Accelerometer, 20000, 0,
12-14 17:02:21.674: I/SDL(3679): SDL_Android_Init()
12-14 17:02:21.674: I/SDL(3679): SDL_Android_Init() finished!
12-14 17:02:21.674: V/Mw(3679): I: 342 ,T: 18673 > Reached main()!
12-14 17:02:21.674: V/Mw(3679): I: 342 ,T: 18673 > MwAppUpdater::InitGame reached.
12-14 17:02:21.674: A/libc(3679): Fatal signal 11 (SIGSEGV) at 0x400eb1c8 (code=2), thread 3751 (SDLThread)
12-14 17:02:21.704: V/SDL(3679): SDLActivity.java public static void handleResume() reached
12-14 17:02:21.704: V/SDL(3679): SDLActivity.java public static void handleResume() end.

Hi Daniel,

thank you for your fast answer. Resuming my app, when it is paused via homebutton works fine. But the exitbutton that I want to implement should kill the app complete and shut it down.
As I wrote I’m killing all of my native app, when the exitbutton is triggered by the user, therefore it isn’t restartable anymore. Is that a wrong way?
Michael

You cannot completely “exit” an Activity on Android (like on Windows or
other OSes where exit() resp. return from main unloads the program from
memory). Android will decide for itself whether and when to remove an
Activity from memory. Think of it like files that an OS will cache in memory
for performance reasons - Android does the same with Activities.

An Activity being in the “destroyed” state should however not behave
differently when started, compared to an Activity that has not been started
before. And yes, Android apps should always be restartable, because you’ll
never know whether the app was removed from memory in the meantime. This
might need special attention (like no static initialization in native code,
and SDLActivity re-initializing some fields upon onDestroy() already, which
looks strange but is correct).

---------- P?vodn? zpr?va ----------
Od: Edition Cham??leon
Komu: sdl at lists.libsdl.org
Datum: 14. 12. 2016 17:15:31
P?edm?t: Re: [SDL] How to end SDLActivity correctly

"

Hi Daniel,

thank you for your fast answer. Resuming my app, when it is paused via
homebutton works fine. But the exitbutton that I want to implement should
kill the app complete and shut it down.
As I wrote I’m killing all of my native app, when the exitbutton is
triggered by the user, therefore it isn’t restartable anymore. Is that a
wrong way?
Michael_______________________________________________
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
"

You can use exit() the same way as you use it on other OSes, and it will
kill all activities and services currently running in the calling
process (by default, there is one process for all activities and
services, but using the android:process attribute in AndroidManifest.xml
you can put different components of your application into different
processes - but you won’t need it most of the time).

If you’re making a game with the traditional singleton lifecycle, it’s
perfectly fine to use exit() and other per-process things such as global
variables, while using the singleTask launch mode to maintain only one
activity for your game (the activity basically being the drawing surface
and input interface). It’s simply not possible to respect the Android
lifecycle with everything being local to activity and saved/restored
during configuration changes (mostly you can even skip configuration
changes at all using the android:configChanges attribute, and/or only
handle special cases such as font size changes) when you have a game any
more complex than Pong or whatever anyway.

It’s just not how you should design regular apps. Games rarely need the
activity-based interaction model, so the singleton architecture is both
acceptable and a common practice.

SDL is designed in the way that allows having multiple activities and
services of the same application running simultaneously, so it doesn’t
kill the process by itself, but rather notifies the application code
that an exit was performed. So it’s the application’s responsibility to
handle the quit event as it needs it to be handled - and if you need to
kill the whole process, nothing can stop you from killing the whole process.On 14/12/2016 20:28, hardcoredaniel wrote:

You cannot completely “exit” an Activity on Android (like on Windows
or other OSes where exit() resp. return from main unloads the program
from memory). Android will decide for itself whether and when to
remove an Activity from memory. Think of it like files that an OS will
cache in memory for performance reasons - Android does the same with
Activities.

An Activity being in the “destroyed” state should however not behave
differently when started, compared to an Activity that has not been
started before. And yes, Android apps should always be restartable,
because you’ll never know whether the app was removed from memory in
the meantime. This might need special attention (like no static
initialization in native code, and SDLActivity re-initializing some
fields upon onDestroy() already, which looks strange but is correct).

---------- P?vodn? zpr?va ----------
Od: Edition Cham??leon
Komu: sdl at lists.libsdl.org
Datum: 14. 12. 2016 17:15:31
P?edm?t: Re: [SDL] How to end SDLActivity correctly

Hi Daniel,

thank you for your fast answer. Resuming my app, when it is paused
via homebutton works fine. But the exitbutton that I want to
implement should kill the app complete and shut it down.
As I wrote I'm killing all of my native app, when the exitbutton
is triggered by the user, therefore it isn't restartable anymore.
Is that a wrong way?
Michael
_______________________________________________
SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I always use exit(1); when I want to terminate the app. It works quite well.
Return after the main loop doesn’t work well, sometimes it will crash the next time the app is started.