Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WorkManager support #2613

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
Open

WorkManager support #2613

wants to merge 11 commits into from

Conversation

dbnicholson
Copy link
Contributor

@dbnicholson dbnicholson commented Jun 1, 2022

This enables WorkManager tasks via the --worker p4a option. This is based on the work in #2464, with the following differences:

  • Support is added in the common bootstrap rather than the service_library bootstrap so it can be used by p4a apps. I believe it should still work in the service_library context, but I haven't tested.
  • I removed the bound service addition. That might still be useful, but my goal was to support WorkManager tasks, and that wasn't needed. I believe in WIP: workmanager and bound services support #2464 they were using the bound service as the target for the WorkManager tasks, but I changed it so that each worker has a generated service class. The generated service class is based on RemoteWorkerService, which itself implements a bound service.

An important thing to note is that since p4a only supports one python interpreter per process (see #2609), the work task is always run in a separate process via a RemoteListenableWorker. That seems to work well except that I couldn't get cancellation to work. The downside of this approach is that the androidx work-multiprocess release including this support requires SDK 30.

The bulk of the work is in the "Support WorkManager tasks" commit. Everything before that is preparation, which could be split out into a separate PR if that's preferred.

There are still a couple things I haven't completed:

  • I added a --worker test in the on-device tests, but it's only being run in the flask webview app. It would be good to be able to test it in the kivy app, too.
  • I haven't tested foreground handling and the PythonWorker class doesn't implement the getForegroundInfoAsync() and getForegroundInfo() methods.
  • Documentation
  • Currently there's ugly WorkManager.initialize call in the generated worker service since the androidx startup handling doesn't seem to work on remote processes. It seems to work, but I don't think it's the right way to do it. This isn't ideal, but I think it's fine this way.

zworkb and others added 5 commits August 2, 2022 10:00
This is currently unused, but without passing back the status the Java
classes have no way of knowing whether the native code succeeded or not.
This code is compiled into a shared library and not an executable where
the C `main` entry point is used. The only entry points actually used
are the symbols called by the JNI. Rename this "main" function to
`run_python` to avoid confusion. This also allows changing the interface
without breaking the standard C `main` interface. This could be used to
pass in the Python entry point without using environment variables, for
example.

The exception is in the sdl2 bootstrap where `PythonActivity` extends
`SDLActivity`. `SDLActivity` calls `SDL_main` as the native entry point.
This was working before because the SDL headers define `main` as
`SDL_main`. Instead of relying on that, just implement `SDL_main` as a
wrapper around `run_python` when needed.
This will be reused for WorkManager task entry points in a later commit.
Adding python code to call `sys.exit` was added to workaround issues
with restarting apps. However, that actually exits the entire
application. In some scenarios that might be wrong, so provide a
conditional to skip calling `sys.exit`.
These are cosmetic but they make it easier to use flake8 to find issues
when hacking on the app.
@dbnicholson
Copy link
Contributor Author

I fleshed this out some more and got cancellation to work. It turns out that I was just doing it wrong and blocking on the python thread in the worker. That's wrong as it doesn't allow the future to be returned and WorkManager doesn't get it until the python process has completed.

Otherwise, I spent some time trying to make sure the worker service always exits since you can get strange errors if you run python more than once in a process. That works most of the time, but sometimes if you cancel work and then run work to completion it won't exit since the service is still bound from the cancelled work. I think you'd need to address #2610 so that the python thread could be stopped without killing the whole process.

Lastly, I have some work in progress on getForegroundInfoAsync(), but I ran out of time right now to complete it. I might be able to get to that in the next week.

dbnicholson and others added 6 commits August 3, 2022 15:37
Now that the on-device test app is configured to build an AAB and AAR in
addition to an APK, looking at the default options for the for the APK
might be wrong. Try to figure out the target before looking at the
options.
This should make it easier to track state than using globals.
The androidx WorkManager component allows simple handling of tasks in
Android apps. Furthermore, in Android 12, WorkManager tasks are the
preferred way to run foreground services when the app is in the
background.

Since the python interpreter integration only allows running one python
interpreter per process, this uses a `RemoteListenableWorker` to run the
tasks on a service in a separate process. Unfortunately, that's only
available since the work-multiprocess 2.6.0 release, which requires SDK
30.

Co-authored-by: Robert Niederreiter <office@squarewave.at>
Co-authored-by: Philipp Auersperg <phil@bluedynamics.com>
Exercise the `--worker` option in the on-device test app. This requires
raising the SDK version to 30.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants