<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #35435 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [ ] If paths of existing endpoints are modified without backwards compatibility, checked the frontend/CLI for any necessary changes ## Testing - [ ] Added/updated automated tests - [ ] Where appropriate, [automated tests simulate multiple hosts and test for host isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing) (updates to one hosts's records do not affect another) - [ ] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [ ] Confirmed that the fix is not expected to adversely impact load test results - [ ] Alerted the release DRI if additional load testing is needed ## Database migrations - [ ] Checked schema for all modified table for columns that will auto-update timestamps during migration. - [ ] Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects. - [ ] Ensured the correct collation is explicitly set for character columns (`COLLATE utf8mb4_unicode_ci`). ## New Fleet configuration settings - [ ] Setting(s) is/are explicitly excluded from GitOps If you didn't check the box above, follow this checklist for GitOps-enabled settings: - [ ] Verified that the setting is exported via `fleetctl generate-gitops` - [ ] Verified the setting is documented in a separate PR to [the GitOps documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485) - [ ] Verified that the setting is cleared on the server if it is not supplied in a YAML file (or that it is documented as being optional) - [ ] Verified that any relevant UI is disabled when GitOps mode is enabled ## fleetd/orbit/Fleet Desktop - [ ] Verified compatibility with the latest released version of Fleet (see [Must rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md)) - [ ] If the change applies to only one platform, confirmed that `runtime.GOOS` is used as needed to isolate changes - [ ] Verified that fleetd runs on macOS, Linux and Windows - [ ] Verified auto-update works from the released version of component to the new version (see [tools/tuf/test](../tools/tuf/test/README.md)) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Added enrollment workflow with support for configuring enrollment credentials and base URL * Integrated certificate management with ability to view device certificates and details * Added device permissions display to the app interface * Enabled managed configuration support for remote policy management * **Chores** * Updated build configuration and dependencies for enhanced serialization capabilities <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com>
Fleet Android agent
- Requirements
- Building the project
- Deploying via Android MDM
- Running tests
- Code quality
- Troubleshooting
Requirements
- JDK 17 or later - Set
JAVA_HOMEenvironment variable - Android SDK - Gradle finds it via:
local.propertiesfile withsdk.dir(auto-created by Android Studio) ✅ Recommended- OR
ANDROID_HOME/ANDROID_SDK_ROOTenvironment variables - Install via Android Studio (easiest)
- Or install command-line tools
- Requires SDK Platform API 33+ and Build Tools 34.0.0+
Building the project
Debug build
./gradlew assembleDebug
Output: app/build/outputs/apk/debug/app-debug.apk
Release build
./gradlew assembleRelease
Output: app/build/outputs/apk/release/app-release.apk
Note: By default (without signing configuration), this creates an unsigned APK not suitable for distribution.
Signing release builds
Signing configuration is already set up in build.gradle.kts. You just need to provide the keystore and credentials.
One-time setup per developer/machine:
- Create a keystore:
keytool -genkey -v -keystore keystore.jks \
-alias fleet-android \
-keyalg RSA -keysize 2048 -validity 10000
You'll be prompted for:
- Password (enter twice for confirmation) - This will be used for both keystore and key
- Your name, organization, location, etc.
- Create
keystore.propertiesfile in theandroid/directory:
storeFile=path/to/keystore.jks
storePassword=your-password
keyAlias=fleet-android
keyPassword=your-password
Note: Use the same password you entered during keystore creation for both storePassword and keyPassword.
- Build signed release:
# APK (for direct distribution)
./gradlew assembleRelease
# AAB (for Google Play Store)
./gradlew bundleRelease
Output:
- APK:
app/build/outputs/apk/release/app-release.apk - AAB:
app/build/outputs/bundle/release/app-release.aab
Verify signing:
# APK - use apksigner (in SDK build-tools)
# Find your SDK and build-tools version:
grep sdk.dir local.properties
ls "$(grep sdk.dir local.properties | cut -d= -f2)/build-tools/"
# Then verify:
<sdk-path>/build-tools/<version>/apksigner verify --verbose app/build/outputs/apk/release/app-release.apk
# AAB - use jarsigner (included with JDK)
jarsigner -verify app/build/outputs/bundle/release/app-release.aab
Deploying via Android MDM (development)
This feature is behind the feature flag FLEET_DEV_ANDROID_AGENT_PACKAGE. Requires FLEET_DEV_ANDROID_GOOGLE_SERVICE_CREDENTIALS to be set in your workarea.
- Set the feature flag on your Fleet server:
export FLEET_DEV_ANDROID_AGENT_PACKAGE=com.fleetdm.agent.private.<yourname>
- Change the
applicationIdinapp/build.gradle.kts:
defaultConfig {
applicationId = "com.fleetdm.agent.private.<yourname>"
// ...
}
-
Build a signed release (AAB) using the instructions above.
-
Get the Google Play URL:
# Run from top-level directory of the working tree
go run tools/android/android.go --command enterprises.webTokens.create --enterprise_id '<your-enterprise-id>'
-
Upload your signed app in the Private apps tab using the URL from the previous step.
-
Wait ~10 minutes for Google Play to process the upload.
-
Enroll your Android device.
The agent should start installing shortly. Check Google Play in your Work profile. If it shows as pending, try restarting the device.
Full build with tests
./gradlew build
This runs:
- Compilation (debug + release)
- Unit tests
- Android Lint
- Spotless formatting checks (automatic)
Running tests
Unit tests (JVM)
./gradlew test
Instrumented tests (requires emulator/device)
./gradlew connectedDebugAndroidTest
Code quality
Formatting with Spotless (ktlint)
Check formatting:
./gradlew spotlessCheck
Auto-fix formatting issues:
./gradlew spotlessApply
Note: Spotless checks run automatically during ./gradlew build. Run spotlessApply to fix issues before committing.
Static analysis with Detekt
Run manually:
./gradlew detekt
Note: Detekt does NOT run automatically in local builds (only in CI). Run manually when needed.
Dependencies
See gradle/libs.versions.toml for complete list.
Development workflow
- Before committing: Run
./gradlew spotlessApplyto fix formatting - Local verification: Run
./gradlew buildto ensure everything passes - Optional: Run
./gradlew detektfor static analysis - Push: CI will run all checks automatically
Troubleshooting
Clean build:
./gradlew clean build
Delete device from Android MDM:
- Delete Work profile on Android device
- Using
tools/android/android.go, delete the device and delete the associated policy (as of 2025/11/21, Fleet server does not do this)