Skip to content

feat(Android): add wifi auto connect demo with AI - #245

Draft
Dao-you wants to merge 8 commits into
mainfrom
add-ntut-8021x-assistant
Draft

feat(Android): add wifi auto connect demo with AI#245
Dao-you wants to merge 8 commits into
mainfrom
add-ntut-8021x-assistant

Conversation

@Dao-you

@Dao-you Dao-you commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an Android-only NTUT-802.1X assistant that:

  • uses WifiNetworkSuggestion as the default path
  • falls back to ACTION_WIFI_ADD_NETWORKS on Android 11+ when suggestion permission is denied or silent refresh can no longer proceed
  • degrades to manual guidance when the platform or device capability is insufficient
  • prompts the user to update the saved system Wi-Fi profile only when the device is using compat mode or suggestion refresh has failed

Implementation

  • Moved Android Wi-Fi integration out of MainActivity into CampusWifiChannelHandler and Ntut8021xProvisioner
  • Added device-local Wi-Fi provisioning state storage for last mode, credential fingerprint, and pending compat prompts
  • Added login-time compat update prompt flow and updated the NTUT Wi‑Fi screen to show normal, compatRetry, and manualOnly states
  • Added repository/widget tests and cross-version emulator validation

Validation

  • flutter analyze
  • flutter test test/repositories/campus_wifi_repository_test.dart test/services/campus_wifi/ntut8021x_auto_reprovision_test.dart test/screens/main/profile/ntut_wifi_screen_test.dart test/screens/welcome/login_screen_test.dart
  • flutter build apk --debug
  • Manual AVD validation on Android 9, 10, 11, 12, and 16 with reinstall between cases to avoid leftover suggestion state

Emulator Results

  • Android 9: manual-only
  • Android 10: tested image behaved as manual-only
  • Android 11: suggestion success, suggestion denied, compat retry UI
  • Android 12: suggestion success and denied reproduced; denied still showed optimistic success copy in this run
  • Android 16: suggestion success, suggestion denied, and full compat fallback flow completed

Notes

  • Android 9 has no automatic path.
  • On the tested Android 10 image, the feature was effectively gated to manual-only behavior.
  • Suggestion approval denial currently still leaves optimistic success copy on some emulator runs even though the system has revoked permission; screenshots will be attached in a PR comment instead of being stored in the branch.

@rileychh-dokploy-riley-ntut-npc

rileychh-dokploy-riley-ntut-npc Bot commented Mar 30, 2026

Copy link
Copy Markdown

Dokploy Preview Deployment

Name Status Preview Updated (UTC)
API Docs ✅ Done Preview URL 2026-05-20T09:56:00.314Z

@github-actions

github-actions Bot commented Mar 30, 2026

Copy link
Copy Markdown

PR Preview Builds

Build Number: 1065
Commit: fb04f5d
Message: Merge remote-tracking branch 'origin/main' into add-ntut-8021x-assistant

Android (Firebase App Distribution)

Install build 1065

@Dao-you
Dao-you force-pushed the add-ntut-8021x-assistant branch from e82ef86 to 4b6cf1a Compare April 3, 2026 10:24
@Dao-you
Dao-you force-pushed the add-ntut-8021x-assistant branch from 4b6cf1a to 896491f Compare April 3, 2026 12:32
@Dao-you
Dao-you force-pushed the add-ntut-8021x-assistant branch from af78b1e to 533d732 Compare April 3, 2026 22:04
@Dao-you Dao-you changed the title feat(Android): [WIP][AI DEMO] add wifi auto connect demo with AI feat(Android): [AI DEMO] add wifi auto connect demo with AI Apr 10, 2026
@Dao-you Dao-you added the deploy:android Deploy Android to Firebase App Distribution label Apr 10, 2026
@Dao-you Dao-you changed the title feat(Android): [AI DEMO] add wifi auto connect demo with AI feat(Android): add wifi auto connect demo with AI Apr 11, 2026
# Conflicts:
#	ios/Podfile.lock
#	lib/i18n/en-US.i18n.yaml
#	lib/i18n/strings.g.dart
#	lib/i18n/strings_en_US.g.dart
#	lib/i18n/strings_zh_TW.g.dart
#	lib/i18n/zh-TW.i18n.yaml
#	lib/repositories/auth_repository.dart
#	lib/router/app_router.dart
#	lib/screens/main/profile/profile_screen.dart
#	pubspec.lock
#	pubspec.yaml

@rileychh rileychh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bugs (block-worthy)

  1. Tests don't compile — isDemo is a required AuthRepository arg but is omitted in three test filestest/repositories/auth_repository_test.dart:29, test/repositories/campus_wifi_repository_test.dart:267, test/screens/main/profile/profile_screen_test.dart:116 (Codex + Claude; verified by running flutter analyze, all three report missing_required_argument). login_screen_test.dart:151 correctly passes isDemo: false. CI will fail. Fix: add isDemo: false to each AuthRepository(...)/super(...) call.

  2. Android 10 (API 29) crash path on automatic provisioningandroid/app/src/main/kotlin/club/ntut/tattoo/campuswifi/Ntut8021xProvisioner.kt:291-296 (Codex). provisionNtut8021x only gates on SDK_INT < Q (29), but WifiNetworkSuggestion.Builder.setCredentialSharedWithUser was added in API 30 (R). On real Android 10 devices where suggestion permission is not "disallowed" (the assistant screen would then be in normal mode and canProvisionAutomatically == true), tapping the auto button throws NoSuchMethodError before any result is returned. The PR description's "Android 10 behaved as manual-only" appears to be specific to the emulator image used (its suggestion permission state happened to gate the UI to manualOnly via campus_wifi_repository.dart:450-456). Fix: either guard setCredentialSharedWithUser / setIsInitialAutojoinEnabled with SDK_INT >= R, or refuse suggestion provisioning entirely on API 29 (matches the existing intent — canCompatProvision already requires R).

  3. profile_screen_test.dart asserts a UI entry the production code doesn't rendertest/screens/main/profile/profile_screen_test.dart:62-63 (Codex + Claude). The test expects t.profile.options.ntutWifi ("Connect to NTUT-802.1X") in ProfileScreen, but the production entry was added only to MainHomeScreen (home_screen.dart:52-58). lib/screens/main/profile/profile_screen.dart is unchanged on this branch (git diff main -- lib/screens/main/profile/profile_screen.dart is empty), so the i18n key profile.options.ntutWifi is dead. Decide whether the entry belongs in Profile (then add it) or only on Home (then drop the test + i18n key).

Suggestions / nits (not blockers)

  1. Unused crypto dependency — pubspec.yaml:21 (Claude). crypto: ^3.0.7 is added but grep -r "package:crypto" lib test returns nothing. Likely vestigial from an earlier "credential fingerprint" implementation (the legacy key ntut8021x.lastCredentialFingerprint is still being scrubbed on every state-store read at ntut8021x_state_store.dart:46). Remove the dep.

  2. Reflection on setCaPath is unnecessary on the supported version rangeNtut8021xProvisioner.kt:312-346 (Claude). WifiEnterpriseConfig.setCaPath(String) is a public API since API 26, and provisioning is gated to API ≥ 29. The reflection wrapper, the system_certificate_validation_unavailable path, and supportsSystemCertificateValidation() can be replaced with a direct call — simpler and removes a silent-fail branch.

  3. Auto-reprovision can be silently enabled but never disabledcampus_wifi_platform.dart:247-250 (Claude). Ntut8021xAutoReprovision.enable() is auto-called the first time provisioning succeeds (in both provisionNtut8021x and saveNtut8021xToSystem). There is no disable(), no toggle on the NTUT Wi-Fi screen, no Preferences entry. Users who change their mind have to clear app data. Either add a UI toggle or keep enabling explicit (driven by a checkbox in the prompt/screen).

  4. Ntut8021xStateStore.read() writes on every callntut8021x_state_store.dart:45-46 (Claude). It calls _prefs.remove(_legacyFingerprintKey) on every read (and again on markProvisioned). One-time migration on app startup is enough; doing it on every read churns IPC.

  5. getSuggestionApprovalStatus blocks the Android main thread for up to 500msNtut8021xProvisioner.kt:381-398 (Claude). MethodChannel handlers run on the platform main thread by default, so a 500 ms latch.await here can cause jank or, on bad devices, trigger an ANR-adjacent warning. Consider dispatching provisionNtut8021x on a background executor and posting the MethodChannel.Result back to the main thread.

  6. Plaintext previous password crosses the MethodChannelcampus_wifi_platform.dart:138-148, Ntut8021xProvisioner.kt:76-86 (Claude). Today the previous password is sent across the bridge only to rebuild the old WifiNetworkSuggestion for removeNetworkSuggestions. According to Android docs, WifiManager.removeNetworkSuggestions(emptyList()) removes all suggestions from the calling app — worth verifying and, if it works back to API 29, dropping the previousPassword channel arg entirely so it never leaves the Dart side. Defensible as-is; just a smaller attack surface if avoidable.

  7. _logCampusWifi double-emitscampus_wifi_platform.dart:16-19 (Claude). Calls both dart:developer log() and debugPrint() for every line. Pick one (probably log).

Process note

Codex's headline framed everything as a single "P1 cluster" of compile + crash; Claude's reading confirms its three findings (all verified — items 1, 2, 3 above) and adds seven nits. None of the additions are blockers, but #4 and #5 are zero-cost cleanups worth folding into the same fix-up commit. The most urgent are #1 (CI red), #2 (real-device crash on Android 10), and #3 (CI red).

@Dao-you

Dao-you commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

測試紀錄:
在 Android 16 / OneUI 8.0 上測試
在外部更改密碼並且於 App 內被自動登出 -> 重新登入後,可以背景自動更新 WiFi 的帳號密碼。

倒是發現對於帳號不可登入的情形,App 僅會在觸發網路查詢時確認(並且引導至登入畫面),可能需要重新思考這件事情的 UX。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deploy:android Deploy Android to Firebase App Distribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

導入 ACTION_WIFI_ADD_NETWORKS 作為 NTUT-802.1X 連線的保底與首選機制

2 participants