beeware / toga

A Python native, OS native GUI toolkit.
https://toga.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
4.35k stars 671 forks source link

Implement on mobile: App.exit, App.on_exit, and Window.close #1623

Open mhsmith opened 2 years ago

mhsmith commented 2 years ago

Like Android (#1622), the iOS backend does not implement the exit method.

freakboy3742 commented 2 years ago

This was at least partially intentional, as mobile apps don't really have a "quit/exit" concept that is analogous to desktop apps. I was actually a little surprised to see that exit() wasn't marked @not_required_on('mobile').

AFAIK, iOS doesn't even have an API for "quit app" - I guess we could manufacture one with a SIGINT or similar, but that's not really "expected" iOS behavior.

So - I'm not sure what the right solution is here. Keeping the API but making it a no-op is a little weird; we should perhaps improve the logging message to lean into the "you shouldn't be doing this" messaging; or we could completely remove the entry point on mobile.

As a comparison datapoint: Cordova/PhoneGap doesn't support Quit on iOS; it's a no-op (same as it is here).

mhsmith commented 1 year ago

From #1622:

Does "App exit" even make sense in an Android context? As noted on https://github.com/beeware/toga/issues/1623, iOS explicitly doesn't have a concept of an app exiting; it may suspend or go to sleep, but you'll never see an iOS app that has a "quit app" button. I don't have a lot of "daily driver" experience with Android, but I haven't seen an app with a "Quit" button - is this something that should even exist?

A user-visible quit command isn't part of the standard style on Android either. However, if someone makes an app on the desktop which happens to have an exit button, and then tries running it on mobile (which is exactly what happened in #1622), isn't it better for it to work rather than do nothing? It's certainly possible to implement the method in a reasonable way: simply close all activities, then exit the process.

It looks like neither iOS nor Android implements Window.close either, so a Toga app can't even end a single activity programmatically. That should certainly be fixed.

I suggest we come back to this when we're ready to start thinking about multi-window apps on mobile.

freakboy3742 commented 1 year ago

I'm not sure I agree that implementing an API in a way that violates the HIG for the platform is desirable. I'd almost argue that exposing App.exit() at all is a bug. Apps should definitely expose a "platform appropriate" way to exit (i.e., a Quit menu option, or behavior tied to closing the main app window); but that doesn't mean that a public API for invoking exit should exist. The aim of Toga should be to produce apps that adhere to native HIG and platform expectations, and sometimes that means not exposing functionality in favour of capturing the "higher level" concept. In this case, there's definitely a need to allow for "on exit" logic; but it doesn't mean we should actively encourage people to put a big "Quit me" button in the middle of their app.

Window.close is a slightly different issue, as that ties into what multiple-window apps "mean" on mobile.

However, in both cases, I agree that we can put a pin in this discussion until we get to dealing with multi-window apps etc.

mhsmith commented 1 year ago

See https://github.com/beeware/toga/issues/1803 for discussion about on_exit.

mhsmith commented 8 months ago

As far as I know, this has still not been implemented.

From #2419 by @greenshelll:

What is the problem or limitation you are having?

As far as im aware of, currently, using the back button for the android immediately closes the app. The on_exit handler doesnt work. Are there any work arounds we could use at the moment? if its possible.

As things are now, the simplicity is alright, but I feel like this functionality is necessary.

Describe the solution you'd like

Exactly how on_exit handler and exit() method would work in windows. It would be helpful to have an onDestroy handler for the app, as the 'Back' button serves as a core and standard navigation control for android.

I would like to use it for navigation purposes (more specifically, changing to previous screens) and saving operations (autosave changes).

freakboy3742 commented 8 months ago

While I agree that there's an opportunity to hook into the Android onDestroy activity lifecycle event (and, for that matter, all the other events in the Activity lifecycle), it's worth noting that the onDestroy event is fundamentally different to a Windows "exit" event.

On Windows, the exit event is a request, and can be rejected by the handler - that's how you implement an "Are you sure?" dialog on exit. On Android, you're being informed that the app is shutting down. There's no way (that I'm aware of) to prevent OnDestroy for happening or completing. At the very least, this needs to be flagged in documentation, as it's a significant platform deviation.

It's also worth noting that hitting the "back" button on Android isn't necessarily a "Destroy". It's more likely to be an onStop, indicating that the activity is running, but not in the foreground. It won't be destroyed until the OS decides that is appropriate (which isn't complete predictable). I agree that Toga's on_exit handler best maps to onDelete - the final point in app lifecycle - but that means the obvious implementation of what @greenshelll has described won't actually have the desired behavior. An additional set of lifecycle events for "resume" and "stop" (for which there are iOS equivalents; there's arguably a mapping for "wake from sleep" behavior on desktop) will be required to implement the requested behavior.

mhsmith commented 8 months ago

There's no way to reject onStop or onDestroy, but there is a way to intercept the back button itself with the [onBackPressed](https://developer.android.com/reference/android/app/Activity#onBackPressed()) method, which may be useful.

mhsmith commented 1 month ago