Android project skeleton and Gradle setup #76
No reviewers
Labels
No labels
area:companion
area:docs
area:shared
area:tooling
area:watchapp
blocker
kind:chore
kind:feature
kind:spike
kind:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/PedalPebble!76
Loading…
Reference in a new issue
No description provided.
Delete branch "area/android-companion-skeleton"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
The Android companion project skeleton:
settings.gradle.ktsat the repository root,companionas a first-level Gradle project with the seven feature modules nested under it
(
:companion:core,:companion:pebble,:companion:location,:companion:sensors,:companion:route,:companion:map,:companion:ride), each building, plus the JVM unit testsource set on
:companion:core.Acceptance criteria (issue #14)
companion/Gradle project builds a debug APK — [VERIFIED], built for real in thissession (
./gradlew :companion:assembleDebug, 31 MBcompanion-debug.apk); see "How I verifiedthis" below for why that's notable.
(Android 12, NFR-C2 / D19). Confirmed against the built APK with
aapt2 dump badging:minSdkVersion:'31' targetSdkVersion:'37' compileSdkVersion='37'.pebble/,location/,sensors/,route/,map/,ride/— all present undercompanion/, all building, dependency graph documented incompanion/README.md.io.rebble.pebblekit2:client:1.3.0incompanion/pebble/build.gradle.kts, and it actually resolves and compiles (not just declared onpaper).
(
./gradlew :companion:core:test): 1 Kotest spec, 1 pass, JUnit Platform XML report atcompanion/core/build/test-results/test/TEST-de.butzei.pedalpebble.core.CoreModuleSpec.xml.Why this shape (docs cross-checked first, per D48)
docs/PROCESS.md§8: #14 is a true critical-path root (gates 51, unblocks #67 CI and #24 GPXimport) — confirmed before starting, not assumed.
docs/TESTING.md§2.2/§3.1: already assumes a Gradle path literally called:companion:coreand describes it as the module the fast lane tests because it has no Android SDK to load. That
is only a valid Gradle path if the repo root is the Gradle root and
companionis a first-levelproject — so that's the layout used here, rather than putting
settings.gradle.ktsinsidecompanion/(which would make the path just:core).companion/coreiskotlin("jvm"), noAndroid plugin, on purpose.
than taken on faith — see below.
companion/pebble/exists and declares the dependency so #4(Spike A, still open) has a module to land in, without the rest of the app depending on the
transport question being settled.
companion/pebble/'sAndroidManifest.xmldeliberately declares nothing yet —the receiver/queries wiring is #4's job once it's actually exercising the transport.
What I verified vs. recalled vs. reasoned (docs/TEAM.md tagging)
[VERIFIED] today, against live sources, not carried over from docs:
io.rebble.pebblekit2:client:1.3.0— HTTP 200 onrepo1.maven.org/maven2/io/rebble/pebblekit2/client/1.3.0/client-1.3.0.pom, packagingaar,Apache-2.0. This confirms D49 rather than reopening it (D48) — no contradiction found, just
independent re-checking since D49 is load-bearing for this PR's module shape.
built-in Kotlin support means no
org.jetbrains.kotlin.androidplugin is applied in any Androidmodule here.
maven-metadata.xmldirectly (the search index lagged and under-reported). Kover matches
docs/TESTING.mdexactly;Kotest has moved from the 6.1.9 TESTING.md recorded on 2026-08-13 to 6.2.4 since — expected drift,
not a document error,
docs/TESTING.mdnot touched.checkDebugAarMetadatafaileda real build, naming Compose 1.12.0 as requiring compileSdk ≥37. Verified
platforms;android-37.0is a real, stable (non-preview) package in Google's own SDK repository XML before relying on it.
core-ktx1.19.0,activity-compose1.13.0,lifecycle-runtime-ktx2.11.0,compose-bom2026.08.00) — last non-alpha/beta/rc entries in Google's Maven metadata, checkedindividually because the metadata's own
<release>tag turned out to point at alphas for severalof these artifacts.
[REASONED]:
de.butzei.pedalpebble— no existing convention in the docs, chosen to matchthe git host; trivially renameable, doesn't block anything downstream.
ridedepends on everything,corehas zero Android deps, etc.) — noissue specifies this beyond naming the six module folders; the graph follows from what each
module's one-line description already implies.
MainActivity— not mandated anywhere I could finddirectly, but
docs/TESTING.md's coverage-exclusion table already says "Compose/Activity/Fragment"in that order, and PebbleKit 2's own
client-uimodule offers a Composable permission dialog(relevant to D51's NFR-S8 requirement) — so Compose is already the path of least resistance for
whoever builds the permission-rationale UI next.
How I verified this (worth knowing for #67 CI)
This sandbox has no Android Studio and, it turns out, no full JDK on
PATH— the systemjavais a JRE only (nojavac). I found a usable JDK 21 via Rider's bundled JBR, but that buildalso has no
jlink, which AGP needs to build a JDK image for desugaring. I ended up downloadinga standalone Temurin JDK 21 to get a real, non-faked green build. None of this is a repo change —
it's flagged here because whatever CI image #67 uses needs a real JDK 21+, not just a
javabinary on
PATH, and that's exactly the kind of thing that's cheap to catch now and annoying todiscover from a red CI run later.
Android SDK components installed to get here:
platforms;android-37.0,build-tools;37.0.0,platform-tools. Full command sequence is in the session log if useful for the CI imagedefinition.
Setup notes for Robert
companion/README.mdhas a Gradle-for-.NET-developers cheat sheet and the module graph. The onething worth reading even if you skim the rest: AGP 9 (this repo uses 9.4.0) removed the need for
the
org.jetbrains.kotlin.androidplugin — if a tutorial you're reading starts a module'sbuild.gradle.ktswith that line, it's now not just extra but wrong to add alongside AGP'sbuilt-in Kotlin support.
Not in this PR
No permissions declared anywhere (background location, Bluetooth, notifications) — each arrives
with the issue implementing the feature it serves, with a rationale string in
values/+values-de/strings.xmlfrom day one. No transport code — that's #4. No route/sensor/map logic —those are their own issues; the modules exist as the place for that logic to land.
https://claude.ai/code/session_01DAoXbRmJUf2uxNYBfdAXPt