-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
base: develop
Are you sure you want to change the base?
WorkManager support #2613
Conversation
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.
699eb3b
to
67ed764
Compare
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 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 |
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.
67ed764
to
e856947
Compare
This enables
WorkManager
tasks via the--worker
p4a option. This is based on the work in #2464, with the following differences: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 theWorkManager
tasks, but I changed it so that each worker has a generated service class. The generated service class is based onRemoteWorkerService
, 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:
--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.PythonWorker
class doesn't implement thegetForegroundInfoAsync()
andgetForegroundInfo()
methods.Currently there's uglyThis isn't ideal, but I think it's fine this way.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.