Add Android on-device debugging support#5012
Merged
Merged
Conversation
Mirrors the iOS on-device-debug flow from #4999 for Android, taking advantage of the fact that Dalvik/ART already speaks JDWP — no desktop proxy needed. The Codename One Maven plugin orchestrates adb: install the APK, mark it as the debug-app, launch the Activity, poll for the PID, forward JDWP onto localhost, and tail logcat. The existing IntelliJ workflow extends: there is now a CN1 Android On-Device Debug + CN1 Attach Android pair under the same On-Device Debug folder as the iOS configs. Pieces: - AndroidGradleBuilder parses a new android.onDeviceDebug build hint that flips the generated manifest to debuggable=true and disables R8/proguard so symbols and locals survive the build. Release builds (anything without the hint) are unaffected. - cn1:android-on-device-debugging — new Mojo that drives the adb session end-to-end, with autodetection of adb from ANDROID_HOME / ANDROID_SDK_ROOT / standard Studio SDK paths / $PATH, optional adb connect <ip:port> for wireless devices (Android 11+ adb pair / adb connect and legacy adb tcpip both covered), APK autodetection from target/, am set-debug-app -w for wait-for- attach, and a logcat stream prefixed [device] for the lifetime of the session. Cleans up adb forward on shutdown. - cn1:buildAndroidOnDeviceDebug — wrapper that force-sets the hint and invokes the existing android-device cloud build, so the IDE menu has a one-click entry that doesn't depend on the project's codenameone_settings.properties. Archetype: - common/codenameone_settings.properties carries the new hint commented out, next to the existing ios.onDeviceDebug.* lines. - .idea/runConfigurations/CN1_Android_OnDeviceDebug.xml — Maven run config that invokes the new Mojo from the project root. - .idea/runConfigurations/CN1_Attach_Android.xml — Remote JVM Debug to localhost:5005, scoped to the -common module. Developer guide: - New On-Device-Debugging-Android.asciidoc chapter: IntelliJ quick start, wireless debugging (both Android 11+ and legacy paths), Maven CLI flow, flag table, source-resolution for both codenameone-core and codenameone-android sources jars, and troubleshooting. Explicitly calls out that JNI C/C++ is out of scope (use Android Studio + LLDB for that, can run alongside). - Advanced-Topics-Under-The-Hood gets an android.onDeviceDebug entry next to the existing android.debug / android.release rows.
Contributor
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Collaborator
Author
|
Compared 20 screenshots: 20 matched. |
Contributor
Cloudflare Preview
|
Three gates failed on the original push: - SpotBugs DE_MIGHT_IGNORE in AndroidOnDeviceDebuggingMojo's shutdown hook (catch-all swallowed every Exception silently). Narrow the catch to MojoFailureException — the only checked exception runAdb can throw — and surface the message to stderr so a stuck adb forward is at least visible at shutdown. Process.destroy() doesn't declare a checked exception, so the surrounding try/catch is no longer needed for that call. - Vale (Microsoft.Contractions + Microsoft.Adverbs) on On-Device-Debugging-Android.adoc: "it is" → "it's"; drop "rarely" by rewriting the command-line-flags lead sentence; drop "silently" from the breakpoint-not-firing troubleshooter. - LanguageTool typo flags: "codepath" → "code path" in the waitForAttach=false note; allowlist "adb", "logcat", and "pidof" in languagetool-accept.txt under a new "Android tooling" section so future Android docs don't re-trip the same rule.
Two follow-ups to the initial hint binding: - Force off android.enableProguard alongside disableR8. ProGuard runs on the non-Gradle-8 legacy path, and even on Gradle 8 it can layer on top of R8 when android.enableProguard=true; either way the user loses method names and locals. The hint now disables both obfuscators so symbols survive the build regardless of which Gradle line the project is on. - Force android.release=false and android.debug=true. Android's manifest is shared between the release and debug variants, so android:debuggable="true" propagates to both. The cloud build also produces both APKs by default (android.release defaults to true). Without this pin, a stray hint left in codenameone_settings.properties would silently ship a release-signed APK marked debuggable=true — a serious security problem since any device that side-loads it would be exposing a JDWP socket. Pinning to debug-only means the release APK is simply not produced when the hint is on, and the developer guide row for the hint now spells that out. Companion change in the BuildDaemon's AndroidGradleBuilder (separate repo) applies the same guard for the cloud build path.
Contributor
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
Vale Microsoft.Contractions flagged the expanded row on the second CI run: "cannot" → "can't", "that is" → "that's". Same fix pattern as the earlier batch of contraction tweaks in the Android chapter.
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Collaborator
Author
|
Compared 110 screenshots: 110 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirrors the iOS on-device-debug flow from #4999 for Android. Since Dalvik/ART already speaks JDWP, no desktop proxy is needed — the Maven plugin just orchestrates
adb.android.onDeviceDebug=trueflips the manifest todebuggable="true"and disables R8/proguard; release builds are unaffected.cn1:android-on-device-debuggingMojo locatesadb, optionallyadb connects a wireless device, installs the APK, sets the debug-app for wait-for-attach, launches the Activity, forwards JDWP ontolocalhost:5005, and streamslogcat --pid=<pid>to the console with a[device]prefix.cn1:buildAndroidOnDeviceDebugwrapper force-sets the hint and triggers the standardandroid-devicecloud build.On-Device-Debugging-Android.asciidoccovers the IntelliJ quick start, wireless debugging (both the Android 11+adb pairflow and the legacyadb tcpipflow), the Maven CLI flow, source resolution for bothcodenameone-coreandcodenameone-androidjars, and a troubleshooting section. The new hint is documented inAdvanced-Topics-Under-The-Hood.asciidocalongside the existingandroid.debug/android.releaserows.JNI C/C++ is explicitly out of scope (JDWP doesn't speak it); the chapter notes that Android Studio's LLDB can attach to the same process alongside this JDWP session for NDK code.
Test plan
cn1app-archetype. Confirm.idea/runConfigurations/CN1_Android_OnDeviceDebug.xmlandCN1_Attach_Android.xmlappear in the On-Device Debug folder, andcommon/codenameone_settings.propertieshas the commentedandroid.onDeviceDebug=trueline.mvn cn1:buildAndroidOnDeviceDebug, install the APK on a USB-connected device, run CN1 Android On-Device Debug, then attach via CN1 Attach Android. Set a breakpoint in user code and confirm it fires after resume.-Dcn1.android.onDeviceDebug.wireless=<ip:port>.-androidmodule code (a native interface impl) and confirm it fires.com.codename1.impl.android.AndroidImplementationand confirm source resolution against thecodenameone-androidsources jar.logcatlines stream into the CN1 Android On-Device Debug run window with a[device]prefix.debuggable="true".🤖 Generated with Claude Code