Skip to content

fix(android): load widget classes from datastore, not unauthenticated HTTP - #653

Merged
ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/android-query-classes-from-datastore
Aug 24, 2026
Merged

fix(android): load widget classes from datastore, not unauthenticated HTTP#653
ErikBjare merged 2 commits into
ActivityWatch:masterfrom
TimeToBuildBob:fix/android-query-classes-from-datastore

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Problem

The Android homescreen widget's androidQuery categorized events with default category rules even when the user had custom classes. Totals matched the Activity view (same events) but per-category rows did not. That's ActivityWatch/aw-android#142.

0xbrayo already called it: "the categorization might be falling back to the default categories when creating a AW client fails." Confirmed.

Cause

androidQuery fetched settings.classes over HTTP via AwClient::new("127.0.0.1", 5600, ...) without an API key. Android enables dashboard API-key auth by default (ensureDashboardApiKey). That GET either:

  1. 401s because the widget/JNI path does not send Authorization: Bearer …, or
  2. fails to connect because the widget process does not start the HTTP server — it queries the datastore via JNI directly.

Both paths logged a warning and silently used default_classes(). The Activity view (WebView) has the token, so it used the user's custom classes.

A third failure mode: parsing used Vec<aw_models::Class> which requires id: i32. The webui payload treats id as optional, so a successful HTTP response could still fail to parse and fall back to defaults.

Fix

Tests

cargo test -p aw-client-rust --lib classes — 8 passed, including:

  • custom classes without id are used (not defaults)
  • null / empty / invalid JSON fall back to defaults
  • double-encoded string is decoded
  • webui-shaped payload with id + data parses

Follow-up (aw-android)

This does not ship in the Play build until ActivityWatch/aw-android bumps aw-server-rust. After merge I'll open that bump plus Kotlin getSetting for startOfDay. Users whose custom classes only live in WebView localStorage (older bundled webui) still need one Settings save — or a localStorage → settings.classes migration — so the datastore has something to read.

Does not close ActivityWatch/aw-android#142 on its own.

Not overlapping with #652

#652 only changes dirs::db_path / create_config call sites in this file. This PR is the androidQuery class-loading path.

… HTTP

androidQuery fetched settings.classes via AwClient to localhost:5600 without
an API key. Android enables dashboard auth by default, so that GET 401'd
(or failed when the HTTP server wasn't running) and silently fell back to
default_classes(). The Activity view uses the user's custom classes, so
per-category widget times diverged while totals still matched.

Read settings.classes from the datastore the JNI query already has, parse
them through a shared helper (optional id, double-encoded JSON), and add
getSetting() so widget/worker code can do the same for startOfDay.

ActivityWatch/aw-android#142
@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

Greptile Summary

The PR makes Android widget queries load category classes directly from the datastore and adds a JNI settings reader for native widget and worker code.

  • Parses webui-compatible class settings, including optional IDs and double-encoded JSON.
  • Shares settings-key namespacing between the HTTP API and Android JNI.
  • Adds parser, key-mapping, and dotted-key API coverage.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
aw-client-rust/src/classes.rs Adds resilient parsing of stored category classes and focused coverage for supported and fallback payloads.
aw-server/src/android/mod.rs Replaces the unauthenticated HTTP class lookup with direct datastore access and adds the JNI settings reader.
aw-server/src/endpoints/settings.rs Extracts shared settings-key namespacing while preserving dotted keys and the existing length limit.
aw-server/src/endpoints/mod.rs Exposes the shared key helper only to the Android build.
aw-server/tests/api.rs Confirms that dotted setting keys remain retrievable through the HTTP API.

Sequence Diagram

sequenceDiagram
    participant Widget as Android widget
    participant JNI as Rust JNI bridge
    participant Store as Datastore
    participant Query as Android query
    Widget->>JNI: androidQuery(...)
    JNI->>Store: get settings.classes
    Store-->>JNI: Raw JSON value
    JNI->>JNI: Parse class rules or use defaults
    JNI->>Query: Run canonical query with classes
    Query-->>Widget: Categorized activity results
    Widget->>JNI: getSetting(key)
    JNI->>JNI: settings_datastore_key(key)
    JNI->>Store: get settings.key
    Store-->>Widget: Raw JSON value or null
Loading

Reviews (2): Last reviewed commit: "fix(android): allow dotted keys in getSe..." | Re-trigger Greptile

Comment thread aw-server/src/android/mod.rs Outdated
@codecov

codecov Bot commented Aug 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.32%. Comparing base (656f3c9) to head (5a68d9a).
⚠️ Report is 88 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #653      +/-   ##
==========================================
+ Coverage   70.81%   78.32%   +7.51%     
==========================================
  Files          51       65      +14     
  Lines        2916     5408    +2492     
==========================================
+ Hits         2065     4236    +2171     
- Misses        851     1172     +321     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Greptile 4/5: getSetting rejected keys containing '.' while
GET /api/0/settings/<key> accepts them, so JNI returned null for
values the HTTP API could retrieve.

Share settings_datastore_key between the HTTP handler and JNI.
@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

@greptileai review

@TimeToBuildBob

Copy link
Copy Markdown
Contributor Author

CI-green and mergeable (Greptile 5/5) — waiting only on a maintainer click.

This PR is ready to merge, but the bot has pull-only access to this repo and can't self-merge — surfacing it here so it isn't lost. The monitoring loop will stop re-flagging it now that this note is posted.

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.

[feature request] widget on homescreen

2 participants