Skip to content

Home Screen Widget#3

Merged
PhenixStar merged 13 commits intomainfrom
auto-claude/003-home-screen-widget
Feb 6, 2026
Merged

Home Screen Widget#3
PhenixStar merged 13 commits intomainfrom
auto-claude/003-home-screen-widget

Conversation

@PhenixStar
Copy link
Owner

@PhenixStar PhenixStar commented Feb 6, 2026

Create a home screen widget showing ADB connection status with one-tap toggle. Widget should display current IP:port when connected and allow instant copy to clipboard.


Note

Medium Risk
Introduces a new broadcast-driven widget that toggles ADB via root commands and registers a connectivity receiver, so regressions could impact device state and background behavior if broadcasts/receivers misfire.

Overview
Adds a home screen widget that shows current wireless ADB state, surfaces the active IP:port when available, and provides one-tap actions to toggle ADB and copy an adb connect command to the clipboard.

Wires the widget into the app by registering AdbWidgetProvider in AndroidManifest.xml, adding widget metadata/layout/resources, and notifying widgets on ADB state changes from AdbViewModel.toggleAdb() via a local broadcast to keep instances refreshed (also refreshing on connectivity changes).

Written by Cursor Bugbot for commit 333c168. This will update automatically on new commits. Configure here.

PhenixStar and others added 12 commits February 7, 2026 02:00
…ay and action buttons

Created widget_adb_status.xml with:
- Status header (icon + text + toggle button)
- IP:Port display (shown when connected)
- Copy button for quick access
- Placeholder text when disabled
- RemoteViews-compatible views only
- Follows Material Design patterns from fragment_control.xml

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Created ic_widget_adb.xml following app's icon style
- Uses ADB-style design with circle and connectors
- 20dp x 20dp dimensions matching other indicator icons
- White fill color for consistency

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ppWidget

- Created AdbWidgetProvider extending AppWidgetProvider
- Implemented widget lifecycle methods (onUpdate, onEnabled, onDisabled, onDeleted)
- Uses RemoteViews to update widget UI with ADB status
- Displays IP:Port when ADB is enabled
- Shows disabled state when ADB is off
- Uses coroutines pattern from BootReceiver
- Prepared for button click handlers (Phase 2)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
… and display ADB status

Implemented comprehensive widget update mechanism with:

- Asynchronous ADB status fetching using AdbManager.getStatus()
- Proper thread management (IO for data, Main for UI updates)
- Three status states: connected (WiFi + ADB), enabled (ADB only), disabled
- Different toggle button icons (check/close) based on state
- Error handling with fallback error display
- Comprehensive debug logging following AdbManager patterns
- Added missing string resources (status_enabled, status_error)

The widget now correctly displays:
- Status icon with color-coded states (green/orange/gray/red)
- IP:Port when connected via WiFi
- Port-only when ADB enabled but no WiFi
- Placeholder when disabled
- Error state with warning icon on failure

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…nable/disable ADB

- Added onReceive() to handle ACTION_TOGGLE_ADB broadcast
- Implemented handleToggleAdb() to toggle ADB state using AdbManager
- Set up PendingIntent for toggle button in updateWidget()
- Toggle button now enables/disables ADB and updates all widget instances
- Added proper logging for debugging
- Follows AdbManager pattern for enable/disable operations

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…command

- Add ClipboardManager, ClipData, and Toast imports
- Implement handleCopyCommand function to:
  - Fetch current ADB status
  - Format command as 'adb connect IP:PORT'
  - Copy to clipboard
  - Show toast notification
  - Handle error cases (ADB disabled, no WiFi)
- Hook up copy button PendingIntent in updateWidget method
- Follows pattern from ControlFragment.kt

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…nges

Implemented real-time widget updates using LocalBroadcastManager pattern:

Widget Provider Changes:
- Added ACTION_ADB_STATUS_CHANGED broadcast action constant
- Implemented notifyStatusChanged() to broadcast ADB status changes
- Added updateAllWidgets() helper for manual widget refresh
- Enhanced onReceive() to handle ADB status change broadcasts
- Registered/unregistered BroadcastReceiver in onEnabled/onDisabled
- Added updateAllWidgetsInstances() to refresh all widget instances
- Updated handleToggleAdb() to broadcast status changes after successful toggle

ViewModel Integration:
- Modified AdbViewModel.toggleAdb() to broadcast status changes
- Ensures widgets update when ADB is toggled from main app

Pattern followed from AdbService.kt using LocalBroadcastManager for
internal app communication. When ADB is enabled/disabled from anywhere
(main app or widget), all widget instances automatically update.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ddress changes

- Add networkChangeReceiver to listen for connectivity changes
- Register receiver in onEnabled() when first widget is added
- Unregister receiver in onDisabled() when last widget is removed
- Handle CONNECTIVITY_CHANGE broadcast in onReceive()
- Widget now updates automatically when IP address changes (e.g., switching WiFi networks)
- Follows same pattern as existing statusChangeReceiver
- Uses ACCESS_NETWORK_STATE permission (already declared in manifest)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ti-instance support

Created comprehensive integration test infrastructure:
- integration-test-lifecycle.md: 7 detailed test cases covering widget lifecycle
- TESTING_QUICKSTART.md: 15-minute quick-start guide for essential tests
- Test cases verify: lifecycle callbacks, multi-instance sync, selective removal,
  real-time updates, network changes, reboot persistence, and stress testing
- Documentation includes logcat patterns, pass/fail criteria, and troubleshooting
- Build verification passed

Ready for manual execution on Android device/emulator (API 26+)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…tatus updates

Created comprehensive integration test documentation for widget actions and status updates:
- integration-test-actions.md: 9 detailed test cases covering toggle button, copy button, real-time updates, network changes
- Updated TESTING_QUICKSTART.md with 5 additional quick tests for widget actions (Tests 6-10)
- Test cases verify: ADB enable/disable toggle, clipboard copy functionality, WiFi network changes, multi-widget action synchronization
- End-to-end verification includes error handling and real-time status updates from main app
- Combined with lifecycle tests (subtask-4-1), provides complete widget test coverage (16 total test cases)
- All tests include expected logcat patterns, troubleshooting guides, and pass/fail criteria
- Build verification passed successfully

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c891f14b16

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +133 to +136
LocalBroadcastManager.getInstance(context).registerReceiver(
statusChangeReceiver!!,
IntentFilter(ACTION_ADB_STATUS_CHANGED)
)

Choose a reason for hiding this comment

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

P2 Badge Avoid dynamic receivers on AppWidgetProvider instance

Registering dynamic receivers from onEnabled() via LocalBroadcastManager (and similarly for the connectivity receiver) ties their lifecycle to a single AppWidgetProvider instance, but the system recreates provider instances for each broadcast. If the process is killed and later revived, onEnabled() is not called again, so the LocalBroadcastManager receiver is never re-registered and widget updates stop; conversely onDisabled() may run on a different instance, leaving the original receivers registered and leaking callbacks. This can lead to stale widgets or duplicate updates after process restarts. Consider moving these broadcasts to manifest-registered receivers or a separate BroadcastReceiver/Service with a stable lifecycle.

Useful? React with 👍 / 👎.

context.registerReceiver(networkChangeReceiver!!, networkFilter)
Log.d(TAG, "onEnabled: Network change receiver registered")
}
}
Copy link

Choose a reason for hiding this comment

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

Receiver variables lost between AppWidgetProvider instances causing leak

High Severity

The statusChangeReceiver and networkChangeReceiver are stored as instance variables, but AppWidgetProvider extends BroadcastReceiver and Android creates a new instance for each broadcast. When onEnabled registers receivers and stores references in instance variables, these references are lost when the instance is garbage collected. When onDisabled is later called on a different instance, the variables are null, so receivers are never unregistered, causing a resource leak.

Additional Locations (1)

Fix in Cursor Fix in Web

"created_at": "2026-02-05T12:56:49.824459",
"project_hash": "0d6be561318e22002fe7a184fb411324",
"inherited_from": "D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb"
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

Development tooling files accidentally committed to repository

Low Severity

Local development and tooling configuration files have been committed to the repository. These files contain Windows-specific absolute paths like D:\\AI\\Android\\APK\\Android-Apps\\apps\\wirelessadb, build session status, and permission settings. While .auto-claude/ is correctly added to .gitignore, these root-level .auto-claude-* and .claude_settings.json files are not ignored and shouldn't be part of the committed codebase.

Additional Locations (2)

Fix in Cursor Fix in Web

} catch (innerE: Exception) {
Log.e(TAG, "updateWidget: Failed to show error state", innerE)
}
}
Copy link

Choose a reason for hiding this comment

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

Error state leaves toggle button visible but non-functional

Medium Severity

When updateWidget catches an exception, the error handling creates errorViews and sets up the error state display, but doesn't call setOnClickPendingIntent for the toggle button. The toggle button is always visible in the header section of the layout, so after an error it appears clickable but does nothing. The normal update path (lines 365-375) correctly sets up click handlers, but the error path omits them entirely.

Fix in Cursor Fix in Web

@PhenixStar PhenixStar merged commit 22b3441 into main Feb 6, 2026
2 of 4 checks passed
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds)
}
context.sendBroadcast(intent)
}
Copy link

Choose a reason for hiding this comment

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

Unused companion object method never called

Low Severity

The updateAllWidgets companion object method is defined but never called anywhere in the codebase. This method sends a proper system broadcast that would actually reach the widget's onReceive(), unlike notifyStatusChanged which uses LocalBroadcastManager. The presence of this unused method alongside the broken notifyStatusChanged approach suggests the intended widget update mechanism was never properly connected.

Fix in Cursor Fix in Web

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.

1 participant