| 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
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 ? 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? 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() 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? 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. 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)). As you said it may depends on your app. Maybe APP_TERMINATING could me more urgent, and ends faster / asap. Do you have more information ? 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. 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 ) Doesn't persistent require root or special system signing (as far as I can find out about it)? Documentation doesn't specify to be root. Maybe some permission, though/ 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?
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. 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. 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). 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 ? |