Status Update
Comments
da...@google.com <da...@google.com> #2
If you are using location, you should be using the permissions API to ensure that you have the permissions you need to track background location before any attempts to use APIs that require that permission.
SystemForegroundService
just provides a convenient entry point for the ListenableWorker
. If you require additional permissions, its the app's responsibility to ask for permissions and check that those permissions are granted.
an...@gmail.com <an...@gmail.com> #3
We are performing location checks before submitting the WorkManager job. However, the problem exists if the location permission is removed by the User after the job has been submitted. The OS is force killing the app (when the location permission is removed), and the OS is trying to restart the SystemForegroundService which then crashes our app immediately on launch. We are not interacting with the WorkManager in this scenario other than initialising it which is necessary on app start, e.g.
val workManagerConfig = Configuration.Builder()
.setWorkerFactory(entryPoints.getWorkerFactory())
.build()
// Initialize WorkManager with the custom configuration.
WorkManager.initialize(context, workManagerConfig)
return WorkManager.getInstance(context)
uc...@google.com <uc...@google.com>
ad...@google.com <ad...@google.com> #4
I think it might be best for now if your foreground worker does not declare that it is a location foreground service and instead it is either a 'short' service or a 'special use' service such that WorkManager's SystemForegroundService
redeliver intent restarts your foreground worker and in it you can check for location permission and then start a real foreground location service.
Meanwhile we have to adapt WorkManager's SystemForegroundService
to Android 14 requirements to have a foreground service type along with its permission runtime check as otherwise many of the types have runtime permissions pre-requisites.
sa...@gmail.com <sa...@gmail.com> #5
Sorry, I just re-read the changes for Android 14, and for this to work elegantly, we will need to change the implementation of SystemForegroundService
to do the right thing.
Will try to land this in the next WorkManager release.
da...@google.com <da...@google.com> #6
ar...@google.com <ar...@google.com> #7
sa...@gmail.com <sa...@gmail.com> #8
da...@google.com <da...@google.com> #9
Hey - We are working on a fix that will prevent WorkManager from crashing when the foreground worker is restarted due to permission loss. Be aware though that WorkManager won't be able to set the app in a foreground state and it is expected for the worker to self check the required permissions and to probably return a Result.failure()
from the work override.
da...@google.com <da...@google.com>
jo...@google.com <jo...@google.com> #10
Branch: androidx-main
commit 4616a739983e6316819dc515057677edf40a41c1
Author: Daniel Santiago Rivera <danysantiago@google.com>
Date: Wed Jul 24 08:59:34 2024
Catch SecurityException in startForeground
In API 34, startForeground() will throw SecurityException if the service type prerequisites are not met. WorkManager won't be able to start the foreground service but the worker is likely to continue and ideally fail once it checks the permission needed to do the actual work. The worker will also be subject to JobScheduler limitations.
This change mitigates the crashing issue of a foreground worker running and the app losing the prerequisite permission, causing the app to restart and due to SystemForegroundService being sticky, it restarting too but failing at startForeground() due to missing permissions.
Bug: 333957914
Test: Manual
Change-Id: I96607f62fdd456290163ee6f2774f9d31c64e79e
M work/work-runtime/src/main/java/androidx/work/impl/foreground/SystemForegroundService.java
[Deleted User] <[Deleted User]> #11
Branch: androidx-main
commit c540fa0564df85fa4e3cfd2d98f532f4120e12d8
Author: Daniel Santiago Rivera <danysantiago@google.com>
Date: Wed Jul 24 09:48:38 2024
Add foreground worker with location
Updates WorkManager integration app to validate Android 14 foreground service type requirements, including the addition for a foreground worker who uses location APIs.
Bug: 333957914
Test: n/a
Change-Id: I9ac76d029ab0f0e4d1256145bdc2e3cb20b27c36
M work/integration-tests/testapp/lint-baseline.xml
M work/integration-tests/testapp/src/main/AndroidManifest.xml
A work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ForegroundLocationWorker.kt
M work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/ForegroundWorker.kt
M work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/MainActivity.kt
M work/integration-tests/testapp/src/main/res/layout/activity_main.xml
M work/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
ma...@gmail.com <ma...@gmail.com> #12
<[ https://android-review.googlesource.com/3190158 :// = > https://android-X-review.android-X-source. com/3190158 and I didn't get my addresses I need <[ Android-X-Developer.com ]> <[Android-X-GloblaleWaybandTelcomPrivateGovSecurityServices.com ] [ Android-X-GlobaleEcosystemEnterprise ]
:// I need everything of this to be Android-X Object script because they are trying to say it's their's and they can't even run it and I need it back ]>
at...@gmail.com <at...@gmail.com> #13
Please do not link to Googler-only links. We external people cannot verify them.
ro...@gmail.com <ro...@gmail.com> #14
Publisher: Cmake
Consumer: ndk-build
Error is that the static library binary is not found. The binary gets available after the error is issued so the first build attempt is always unsuccessful and when the build (not cleaned) ran for the second time, the build would be successful.
da...@gmail.com <da...@gmail.com> #15
da...@google.com <da...@google.com> #16
Error is that the static library binary is not found. The binary gets available after the error is issued so the first build attempt is always unsuccessful and when the build (not cleaned) ran for the second time, the build would be successful.
File a bug with a repro case.
ad...@gmail.com <ad...@gmail.com> #17
Note: Most API libraries that were previously provided by the Support Repository packages (such as the Android Support Library, Constraint Layout, Google Play services, and Firebase) are now instead available from Google's Maven repository. Projects created with Android Studio 3.0 and higher automatically include this repository in the build configuration. If you're using an older project, you must manually add Google's Maven repository to your build.gradle file.
ad...@gmail.com <ad...@gmail.com> #18
From
on 8/12/2021: issue 65362438
This should be addressed as of BumbleBee Canary 10 (see
Description
THE PROBLEM
Gradle offers two options for building C code for use with Android NDK: ndkBuild and cmake. They cannot be mixed.
If your .gradle contains both a externalNativeBuild { ndkBuild { path '...' } } } and a externalNativeBuild { ndkBuild { cmake '...' } } }, it prints the error "A problem occurred configuring project ':appname'. > More than one externalNativeBuild path specified". (I found this error wording unhelpful; when I first encountered it I could not decipher it because (1) the line numbers of neither "path" directive are provided, and (2) due to includes, the two conflicting "path" directives were in different files.)
On paper, Gradle allows for multi-project builds wherein some subprojects are ndkBuild and some are cmake. However, ndkBuild and CMake are isolated in a way which makes such builds in practice broken. Targets/modules from the CMake world cannot be referenced from the ndkBuild world or vice versa, environment variables (say, include paths) can't be passed between the two. The targetsmodules are the most critical problem because they mean you cannot have a CMake subproject as a dependencies {} from an ndkBuild subproject or vice versa. See "A Repro Case" below: ndkBuild subproject A can list CMake subproject B in dependencies {}, *but B will run after A, not before*, which means that A will fail because the outputs of B have not been created yet. It is my theory that this happens because Gradle is not aware of any files which are an output of B and a input of A (because I have not been given a way to describe these files to Gradle), so it will ignore the dependencies {}.
These limitations are not documented. They are not listed in
WHY THIS IS A PROBLEM
There are various libraries which are distributed as source and whose build scripts use either ndkBuild, or CMake. Including both of these in a single project or multi-project build is extremely painful and apparently impossible without compromises. Google is encouraging NDK projects to migrate to CMake, but currently using CMake means cutting oneself off from the body of existing ndkBuild libraries.
The example I personally hit: The Oculus Mobile SDK
EXPECTED BEHAVIOR
First off, the behavior should be documented. If mixing CMake and ndkBuild is not supported, that fact should be findable in the documentation. If there's some recommended workaround, such as a certain way of configuring multi-project builds, this technique should be documented.
It should be possible to make a multi-project build where some subprojects are ndkBuild and some are CMake. dependencies {} should work properly in these cases, and I should not have to resort to directly listing the paths of intermediate build directories such as build/intermediates/cmake. Perhaps you can come up with a better way of achieving this than me, but here is how I would make this work: Both ndkBuild and CMake have the notion of a target (CMake calls these "targets", ndkBuild calls them "Modules"). It should be possible to reference an ndkBuild module as a CMake Target and vice versa. I should be able to say "LOCAL_SHARED_LIBRARIES := buildtest" in a Android.mk if my CMakeLists has a "add_library(buildtest ...)", for example. If I have to do some kind of "LOCAL_MODULE := buildtest" "include ${CMAKE_LIBRARY}" to make this work, that's fine.
It would be wonderful if there were some way to pass a variable (a CMake "SET", an ndkBuild "var :=") between the CMake and ndkBuild worlds. I guess this is less critical since variables *can* be bassed down from gradle to both.
It would be nice if the "more than one path specified" error message was clearer.
A REPRO CASE
Here
I git clone
(export PATH="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin":~/Library/Android/sdk/platform-tools:$PATH ANDROID_HOME=~/Library/Android/sdk GRADLE=`pwd`/gradlew; ($GRADLE build))
When I build, I see "BUILDING CMAKE TEST PROJECT" in the flow, so I know that my CMakeLists is running. You can find this version listed as 45ff8b1ce.
I next make my CMake subproject not just a dependency, but I make the app/ project actually depend on it. I amend app/'s Android.mk to have a PREBUILT_SHARED_LIBRARY module. This is *super* ugly and horrific, it requires me to order things very precisely in the Android.mk and directly reference the build/intermediates folder, but this is the only way I know to do it This version is listed as a2a9607ac65. When I try to build a2a9607ac65, something interesting happens. On my first build, it works fine. I then try "git clean -xffd". This erases all build products. If I build after git cleaning, the build fails. It prints:
Android NDK: ERROR:/Users/mcc/work/gh/other/android-ndk/other-builds/ndkbuild/hello-libs/app/Android.mk:buildtest: LOCAL_SRC_FILES points to a missing file
Android NDK: Check that /Users/mcc/work/gh/other/android-ndk/other-builds/ndkbuild/hello-libs/app/../cmakelib/build/intermediates/cmake/debug/obj/armeabi-v7a/libbuildtest.so exists or that its path is correct
/Users/mcc/Library/Android/sdk/ndk-bundle/build/core/
I then try building the cmakelib subproject standalone, with
(export PATH="/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin":~/Library/Android/sdk/platform-tools:$PATH ANDROID_HOME=~/Library/Android/sdk GRADLE=`pwd`/gradlew; (cd cmakelib && $GRADLE build))
Once I have done this standalone build of the subproject, I am able to build the top level project again.
In other words: The top level build, which depends on the output of cmakelib, is able to build as long as the cmakelib build runs first, either because it ran on a previous run or I built cmakelib separately. Listing :cmakelib as a "dependency" does not cause it to run first, I actually have to invoke gradle twice. I find invoking gradle twice to be an unacceptably scary (and slow!) solution, in addition to which the PREBUILT_SHARED_LIBRARY build code having to reference build/intermediates is unacceptably scary. This overall-unacceptably-scary solution is, as mentioned, the one currently being used in my "lovr-oculus-mobile" project linked above, which is currently shipping, and the README simply asks the user to invoke gradle twice. There appears to be no other way to do it.
CONFIGURATION
Gradle version: If I run gradlew -v I get:
------------------------------------------------------------
Gradle 4.4
------------------------------------------------------------
Build time: 2017-12-06 09:05:06 UTC
Revision: cf7821a6f79f8e2a598df21780e3ff7ce8db2b82
Groovy: 2.4.12
Ant: Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM: 1.8.0_152-release (JetBrains s.r.o 25.152-b01)
OS: Mac OS X 10.13.2 x86_64
Android Plugin Version: My gradle file contains:
compileSdkVersion 21
buildToolsVersion '27.0.3'
minSdkVersion 21
targetSdkVersion 21
Android SDK Tools version: "Select Tools > Android > SDK Manager, click SDK Tools"
"Android SDK Build-Tools" "Version" is blank and "Status" says "Installed"
"Android SDK Platform-Tools" "Version" is "28.0.1" and "Status" is "Installed"
"Android SDK Tools" "Version" is "26.1.1" and "Status" is "Installed"
NDK" "Version" is "18.1.5063045" and "Status" is "Installed"