We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4682

Summary: SDL app gets closed in the background?
Product: SDL Reporter: superfury
Component: *don't know*Assignee: Sylvain <sylvain.becker>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2    
Version: don't know   
Hardware: All   
OS: Android (All)   

Description superfury 2019-06-21 20:39:00 UTC
For some reason, running my Android SDL2 app in the background(either delaying huge chunks of 1 second or running without rendering video) for a longer time often makes Android close the app(sending a SDL_APP_TERMINATING event)?

The app doesn't use lots of memory(~20MB without soundfont or ~150MB with soundfont MIDI emulation). But that shouldn't affect it? The SDL_APP_LOWMEMORY event is ignored, because my app doesn't support serializing the whole state at all.

Anyone knows why Android closes the background app? The device has 4GB memory(~2GB when excluding what seems to be reserved memory, according to the optimizer tool in the Android settings), so it shouldn't run out of memory that easily?

Perhaps audio rendering is an issue? Afaik that shouldn't cause problems?
Comment 1 Sylvain 2019-06-22 06:36:27 UTC
SDL_APP_TERMINATING is send when onDestroy() is called by the Android-OS (not the app exiting).

Do you receive also a SDL_APP_LOWMEMORY ? This is also sent by the Android-OS. And probably you should do something is you have one.


Maybe you can check the doc:
https://developer.android.com/reference/android/app/Application.html#onLowMemory()


Do you have a Log ?
Comment 2 superfury 2019-06-23 16:16:15 UTC
Then what is the difference between SDL_APP_TERMINATING and SDL_QUIT? I always thought they were supposed to do the same: save any need-to-be-saved state and terminate the app?
Comment 3 Sylvain 2019-06-23 16:19:00 UTC
User vs OS request:

 SDL_events.h:

 59     /* Application events */
 60     SDL_QUIT           = 0x100, /**< User-requested quit */
 
 62     /* These application events have special meaning on iOS, see README-ios.md for details */
 63     SDL_APP_TERMINATING,        /**< The application is being terminated by the OS
 64                                      Called on iOS in applicationWillTerminate()
 65                                      Called on Android in onDestroy()
Comment 4 superfury 2019-06-23 16:25:42 UTC
So, pressing the close button in the task list of Android will generate a SDL_QUIT event, while only the OS will use SDL_APP_TERMINATING?

Does the SDL_APP_TERMINATING need to be honoured(acted like SDL_QUIT) if that's so? Does the main loop and memory data need to be released(all the way until SDL_Quit) when SDL_APP_TERMINATING is received? Or can I just ignore it, to keep running until the user requests the app go quit directly?
Comment 5 Sylvain 2019-06-23 16:30:17 UTC
A little different: 

If you kill your app from the close button in the task list of Android, 
you won't see anything. App is destroyed without telling you.


If the Os decide to kill your app, it calls onDestroy(), and SDL sends you an APP_TERMINATING.
After receiving this event, a few ms after, your app is destroyed.
so when you get APP_TERMINATING, save whatever is needed and try to exit cleanly quickly.
Comment 6 superfury 2019-06-23 16:42:43 UTC
Then, acting on it like SDL_QUIT does is the right action? SDL_QUIT makes thr main thread stop(through a binary semaphore protected global variable) what it's doing, free all allocated memory, stop the libraries(SDL_NET) and call SDL_Quit after that. You say a few milliseconds, but I don't know if my app can even do that. When saving it's settings in the .ini file, it takes a few seconds on my Windows computer to save it, due to continuous rewriting the file to and from a temorarily file(keeps copying the file to it for each added row, then deleting it after copying it back etc.). But maybe that's not an issue for flash memory? On Windows, that takes about 5-7 seconds(in it's file explorer, it see the .tmp file keep appearing and disappearing while it's building said file(only when settings have changed)).
Comment 7 Sylvain 2019-06-23 20:22:05 UTC
As you said it may depends on your app. Maybe APP_TERMINATING could me more urgent, and ends faster / asap.
Comment 8 Sylvain 2020-10-07 07:12:11 UTC
Do you have more information ?
Comment 9 superfury 2020-10-07 09:03:08 UTC
I don't know if the low memory event is reported by the OS (the app doesn't log it, just ), but the app doesn't support saving structures to disk. It's mostly responding like a touch screen Windows PC, although using a few special event handlers etc. for Android compatibility.

Should low memory always be logged, even in released builds?

Currently low memory is ignored and both SDL_APP_TERMINATING and SDL_QUIT request the app to quit(and save settings). The same as what happens on Windows and PSP with the close button.
Comment 10 Sylvain 2020-10-07 09:20:32 UTC
I suggest you to add traces in the Activity lifecycle methods (eg onStart onPause onStop onDestroy + lowMemory) - actually most of this function have one.

Run a long test in background, while saving the ADB log cat. (grep PID + package name). So that you see what's going one.


you can also test to add 'persistent' to true in your AndroidManifest.xml

 https://developer.android.com/guide/topics/manifest/application-element#persistent


Maybe you need something different than an Activity but a Service ( 
https://developer.android.com/guide/components/services )
Comment 11 superfury 2020-10-07 09:59:05 UTC
Doesn't persistent require root or special system signing (as far as I can find out about it)?
Comment 12 Sylvain 2020-10-07 10:33:03 UTC
Documentation doesn't specify to be root.
Maybe some permission, though/
Comment 13 superfury 2020-10-07 11:27:55 UTC
Tried making some code for it in my current SDL2 project.

This is what I've gotten so far:
<START OF CODE>
package com.unipcemu.app;

import org.libsdl.app.SDLActivity;
import android.content.Intent;
import android.app.PendingIntent;
import android.app.Notification;
import java.lang.Boolean;
import android.os.Build;
import android.app.Service;
import android.os.Bundle;

public class UniPCemuActivity extends SDLActivity {
	Intent notificationIntent = null;
	PendingIntent pendingIntent = null;
	Notification notification = null;
	Boolean isForeground = false;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState); //Passthrough!
	}

	protected void onPause ()
	{
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) //Valid to use?
		{
			if (notification == null) //Not set yet?
			{
				this.notificationIntent = new Intent(this, UniPCemuActivity.class);
				this.pendingIntent = PendingIntent.getActivity(this, 0, this.notificationIntent, 0);

				this.notification =
						new Notification.Builder(this, "UniPCemu_channel")
								.setContentTitle("UniPCemu")
								.setContentText("UniPCemu is running in the background.")
								.setContentIntent(pendingIntent)
								.setTicker("tickertext")
								.build();
			}

			// Notification ID cannot be 0.
			startForeground(1, this.notification);
			this.isForeground = true;
		}
		super.onPause(); //Passthrough!
	}
	protected void onResume ()
	{
		if (this.isForeground)
		{
			stopForeground();
			this.isForeground = false;
		}
		super.onResume(); //Passthrough!
	}
	protected void onDestroy ()
	{
		if (this.isForeground)
		{
			stopForeground();
			this.isForeground = false;
		}
		super.onDestroy(); //Passthrough!
	}
}
<END OF CODE>

It keeps telling me that startForeground(and probably stopForeground as well) isn't defined or recognised?
Comment 14 Sylvain 2020-10-07 11:58:56 UTC
This is different from an Activity, this is a "service".
https://developer.android.com/reference/android/app/Service#local-service-sample
You need to extends.

It won't allow you to render stuffs or replace the SDLActivity, but may help you to keep something running in background without been killed by OS. 

Not sure if this is really what you want, maybe previous ideas would help to debug SDL.
Comment 15 superfury 2020-10-07 12:11:04 UTC
Well, not using SDL to use a backgrounded activity would defeat the whole purpose of SDL, wouldn't it? It would still need to run on multiple platforms after all(which is why I use SDL in the first place, for running it on PSP(1.2) and SDL2 for all other platforms(Windows, Linux, Android)).

The app seems to run fine (as far as I can currently tell, with playing a slow rendering(lots of latency in audio rendering due to being backgrounded, less when foregrounded) MIDI file rendering in the background(of a few minutes length(some Touhou song(Angel's Legend from TH01), at ~50-70% realtime speed.

The song now seems to finish properly, instead of ending prematurely(because the emulator is requested to terminate by the OS). Don't know if it's just a little longer or actually permanently running now.
Comment 16 superfury 2020-10-07 12:13:32 UTC
Nope. It still got terminated on the second try trying to render the song in the background(start player, background the app, put phone in standby mode, let it play).
Comment 17 Sylvain 2020-10-07 12:20:25 UTC
Do you have any ADB log ? does it crash ?


What about replacing playing a song, with just doing some SDL_Delay() so that you're sure the audio isn't crashing ?