Skip to content

Examples

Seventy-two examples are included under examples/, organized by category.

New to Picodroid? Start with the two guided tutorials below — they walk through building a real app step by step. The rest of the catalog is reference material to copy from.

Tutorials

Companion apps for the step-by-step Tutorials. Build them with the guide open alongside.

ExampleClassDescription
tutorial_screenstutorial_screens.TutorialScreensAppA Home hub that pushes Counter and About screens — Activities, the back stack, lifecycle, and view preservation. Follow Multi-screen app.
tutorial_servicetutorial_service.TutorialServiceAppAn uptime-logging Service that survives navigation, bound from a viewer screen for live snapshots. Follow Background service.

Getting Started

Simple apps to verify your setup and get familiar with the build/flash workflow.

ExampleClassDescription
helloworldhelloworld.HelloWorldPrints “Hello, World!” via Log.i()
blinkyblinky.LedBlinkBlinks the onboard LED on GP25 every 500 ms

Peripherals

Hardware interaction through the picodroid.pio.PeripheralManager API. Reference: Peripherals.

ExampleClassDescription
uartuart.UartEchoConfigures UART0 at 115200 baud and echoes received bytes
i2cdemoi2cdemo.I2cDemoScans the I2C0 bus (SDA=GP4, SCL=GP5) and logs the 7-bit address of every ACKing device
spidemospidemo.SpiDemoFull-duplex loopback over SPI0 (SCK=GP2, MOSI=GP3, MISO=GP0): sends 0x00-0x0F and logs received bytes
adcdemoadcdemo.AdcDemoOpens the ADC on GP26 and takes 5 voltage readings, logging each value
pwmdemopwmdemo.PwmDemoFades the onboard LED on GP25 using PWM at 1 kHz — duty cycle sweeps 0%->100%->0% three times

Filesystem and Preferences

On-device persistent storage via LittleFS (picodroid.io) and the DataStore-style key-value API (picodroid.content.SharedPreferences). Reference: Storage.

ExampleClassDescription
bootcountbootcount.BootCountPersists a boot counter across reboots using picodroid.io.File / FileInputStream / FileOutputStream
prefs_demoprefsdemo.PrefsDemoStores typed key/value settings (String, int, long, boolean) via SharedPreferences.open() / edit().commit()

Networking

TCP/UDP sockets via picodroid.net. On hardware these require a Pico 2 W (--board testbench_rp2350w); under the simulator they hit the host network stack. Reference: Networking.

ExampleClassDescription
netdemonetdemo.NetDemoChecks NetworkInfo, opens a TCP Socket, sends “Hello” to a localhost echo server on port 7000, and logs the response. On hardware it first waits up to 30 s for WiFi join + DHCP — see WiFi & networking setup
netexceptionnetexception.NetExceptionAsserts the typed network-exception taxonomy — ConnectException on a refused loopback port, SocketTimeoutException from ServerSocket.accept() and from a blocked read, and a dotted-quad InetAddress resolve. Fully local: no external server, network, or resolver needed
http_gethttp_get.HttpGetAndroid-style HttpURLConnection demo: performs a GET and a POST against a localhost HTTP/1.1 server, reading the response body through HttpInputStream. On hardware it waits up to 30 s for the network, and BASE_URL must point at an HTTP server reachable on your LAN — see WiFi & networking setup

Sensors

Environmental / hardware sensors exposed through the Android-compatible SensorManager. Reference: Sensors.

ExampleClassDescription
sensordemosensordemo.SensorDemoActivityRegisters a SensorEventListener on the default ambient-temperature sensor (BME688) and logs each reading; requires a [[sensor]] entry in board.toml

Concurrency

Executors and cross-thread dispatch. Reference: api/system.md → Executors.

ExampleClassDescription
executordemoexecutordemo.ExecutorDemoActivityPosts Runnables via both Executors.mainExecutor() and Executors.backgroundExecutor(); verifies main-thread FIFO ordering and cross-pool dispatch

Services

Background components with lifecycle independent of any Activity. Reference: Services & DI; for a guided build see the Background service tutorial.

ExampleClassDescription
servicedemoservicedemo.ServiceDemoAppDrives a CounterService through the full Service v1 lifecycle in one non-UI run: two startService calls (one onCreate, two onStartCommand), bindService with a LocalBinder peek, unbindService, then stopService (triggers onDestroy and the foreground-notification cancel). Uses startForeground(id, Notification)

Language Features

Demonstrate Java language features supported by the JVM interpreter. Reference: Core language.

ExampleClassDescription
inheritinherit.InheritDemoDemonstrates class inheritance, field inheritance, method overriding, and super()
interfacedemointerfacedemo.InterfaceDemoDemonstrates interface dispatch (invokeinterface) with Dog and Cat implementing Speakable
defaultmethodsdefaultmethods.DefaultMethodsDemoTest-harness coverage of interface default methods: resolution without an override, sub-interface overrides (whatever the implements order), I.super.f() in a diamond, defaults reached through abstract and builtin superclasses, defaults calling abstract methods on this, interface static methods, and a user Iterable in a for-each loop
floatdemofloatdemo.FloatDemoDemonstrates float, long, and double arithmetic and type conversions (f2i, i2l, i2d, etc.)
exceptiondemoexceptiondemo.ExceptionDemoDemonstrates throw, try/catch, and custom exception classes
threaddemothreaddemo.ThreadDemoDemonstrates spawning concurrent FreeRTOS tasks via picodroid.concurrent.Thread
mathsdemomathsdemo.MathsDemoDemonstrates integer/long/double arithmetic, bitwise/shift ops, cross-type conversions, tableswitch, instanceof, checkcast, reference arrays, and java.lang.Math
stringdemostringdemo.StringDemoTest-harness coverage of java.lang.String, StringBuilder, and String.format: predicates, search, transforms, valueOf, concat/replace/split/toCharArray/hashCode, "" + obj/append(Object)/valueOf(Object) through toString(), toUpperCase(Locale), plus exhaustive printf-style conversions, flags, widths, and precision
enumdemoenumdemo.EnumDemoDemonstrates Java enum declarations, values(), name(), ordinal(), and switch over enums
trywithresourcesdemotrywithresourcesdemo.TryWithResourcesDemoDemonstrates try-with-resources (AutoCloseable) — opens an ADC pin in a try block and confirms close() is called on exit
lambdademolambdademo.LambdaDemoDemonstrates Java lambdas via invokedynamic: non-capturing, capturing, callbacks, and static method references
anondemoanondemo.AnonDemoDemonstrates anonymous classes implementing interfaces, with local variable capture
clinitdemoclinitdemo.ClinitDemoDemonstrates static class initializers (<clinit>): field initializers, static {} blocks, and cross-class chaining
classlitclasslit.ClassLitClass literals (T.class): demonstrates getName() and that repeated T.class evaluations return the same Class instance
clonedemoclonedemo.CloneDemoObject.clone(): shallow-copy semantics (reference fields stay shared), identity, class preservation, and the canonical (T) super.clone() override inside a Cloneable class
rttidemorttidemo.RttiDemoRuntime type information: instanceof / checkcast over strings, arrays, collections under their interfaces and boxes under Number; transitive superinterfaces; a catchable ClassCastException; the boxed equals / hashCode / compare family; Comparable through Arrays.sort(Object[]); enum identity
syncdemosyncdemo.SyncDemoDemonstrates synchronized blocks (monitorenter/monitorexit) and reentrant locking
threadparitythreadparity.ThreadParityTest-harness coverage of the java.lang.Thread API on picodroid.concurrent.Thread: synchronized methods under real contention, join, sleep/interrupt -> InterruptedException, currentThread().getName(), a second start() -> IllegalThreadStateException, Object.wait/notify producer-consumer, timed wait expiry, subclassed run(), and an uncaught exception routed to a setDefaultUncaughtExceptionHandler
jucdemojucdemo.JucDemoTest-harness coverage of the picodroid.concurrent java.util.concurrent subset: newFixedThreadPool/newSingleThreadExecutor, submit(Runnable)/submit(Callable) and Future.get/cancel/timeout, shutdown/shutdownNow/awaitTermination, contended AtomicInteger/AtomicLong/AtomicBoolean/AtomicReference, and CountDownLatch fan-in (excluded from testbench_rp2040 builds — see the compatibility matrix)
collectionsdemocollectionsdemo.CollectionsDemoTest-harness coverage of java.util.*: ArrayList add/get/set/remove/contains/clear plus Integer/Boolean autoboxing, Arrays.sort/copyOf/fill/toString, Arrays.sort(Object[]) and Collections.sort/reverse over Comparable<T>, explicit Iterator and enhanced for-each over lists/maps, HashMap and HashSet, entrySet()/Map.Entry, the LinkedHashMap/LinkedHashSet aliases and toArray
randomdemorandomdemo.RandomDemoDemonstrates java.util.RandomnextInt, nextLong, nextFloat, seeded reproducibility
clockdemoclockdemo.ClockDemoDemonstrates System.currentTimeMillis() for boot-elapsed wallclock-style timing
langsuitelangsuite.LangSuiteAggregated language-feature test runner — exercises every JVM language feature in one APK
bytecodecoveragebytecodecoverage.BytecodeCoverageJVM bytecode coverage harness — exercises long/double arrays, multianewarray, wide, goto_w, and stack-manipulation opcodes

Kotlin

Kotlin apps compile to the same bytecode and run on the same JVM; a small kotlin-shim supplies the stdlib entry points the compiler emits. What is and is not supported is tabulated in the Android compatibility matrix.

ExampleClassDescription
hellokthellokt.HelloKtThe smallest Kotlin app: a string template, one !! (the Intrinsics.checkNotNull the shim serves), and a SAM lambda for a Java interface
langsuite_ktlangsuitekt.LangSuiteKtKotlin language suite — data classes, sealed classes and when, extension functions, default and named arguments, varargs, null safety, scope functions, lazy/Pair, objects and companions, interface defaults, lambdas, type checks, exceptions, synchronized
langsuite_kt_stdliblangsuitektstdlib.LangSuiteKtStdlibKotlin stdlib suite — collections, maps, sets, arrays, ranges, sorting, strings, and math over the shim
injectdemo_ktinjectdemokt.InjectDemoKtAppThe Kotlin twin of injectdemo: the same compile-time DI graph through kapt — @Inject lateinit var fields, constructor and method injection, Provider<T> / picodroid.di.Lazy<T>, a @Module object with @JvmStatic @Provides and an instance @Module class — across an Application, two Activities, and a Service
gcstress_ktgcstresskt.GcStressKtGC stress through the churn Kotlin codegen mints: per-iteration lambda proxies, Ref$IntRef boxes for captured locals, autoboxing through generic collections, Pair destructuring, string templates, and map entry-view iteration; asserts identity-hashCode slot stability and lambda-capture rooting across collections
picoenvmon_ktpicoenvmonkt.EnvAppThe Kotlin twin of picoenvmon — same screens, Service, RGB LED, and dashboard HTTP server, same @Inject/@Module object graph, written under the class-metadata frugality rules of the Kotlin guide

Graphics and Display

Full graphical UI with touch input, demonstrating the Activity lifecycle and LVGL widget system. Reference: Graphics & UI; see also Embedded gotchas for the UI pitfalls these apps avoid.

ExampleClassDescription
displaydemodisplaydemo.DisplayDemoAppShowcases the full widget set on a 320x240 display: LinearLayout, ScrollView, TextView, Button, ToggleButton, Switch, CheckBox, SeekBar, Spinner, EditText, touch input, event handlers, a moving-average FPS overlay (DisplayDebug.showFps()), and a themed-widgets section using a custom Theme palette with GradientDrawable (gradient header, surface card, pill / ghost buttons)
keydemokeydemo.KeyDemoActivityHardware-button demo: installs an OnKeyListener on a focusable Button and displays each KeyEvent’s action + keycode; requires [[button]] entries in board.toml
callbacktestcallbacktest.CallbackTestActivityRegression harness for widget callback dispatch under both shrink modes — registers a lambda listener on every widget type and synthetically fires its event
dialogdemodialogdemo.DialogDemoAppToast.makeText().show() and AlertDialog.Builder with positive / negative listeners; demonstrates onBackPressed() confirmation pattern
gesturedemogesturedemo.GestureDemoAppGestureDetector with onSingleTap / onLongPress / onFling listeners on a single View
dragdemodragdemo.DragDemoActivityTouch-driven drag using FrameLayout + OnTouchListener; tracks MotionEvent.ACTION_DOWN/MOVE/UP and updates a tile’s absolute position via setPosition(). The only example using FrameLayout for absolute placement (a LinearLayout would re-flow on every layout pass)
animdemoanimdemo.AnimDemoAppview.animate().alpha(…).x(…).rotation(…).scaleX(…).setStartDelay(…).withEndAction(…).start() — to-only property animations (the start value is read from the view, as on Android), easing interpolators, chained end actions, and the View transform getters
keyboarddemokeyboarddemo.KeyboardDemoAppSoft keyboard: both system-on-touch (default) and explicit Keyboard instances bound to EditText. Includes the soft-keyboard polish pass: slide-up animation, OnEditorActionListener for the Done key, dismiss-on-outside-tap
navdemonavdemo.NavDemoAppMulti-Activity back-stack — startActivity() push, finish() pop, lifecycle callbacks (onPause / onStop / onResume)
injectdemoinjectdemo.InjectDemoAppCompile-time DI end to end: @Inject constructor / field / method injection, @Singleton identity across an Application, two Activities and a Service (all injected automatically before onCreate), an unscoped class per injection site, a leaf Activity that only inherits its @Inject members, Foo_Factory.get() from plain code, Provider<T> / Lazy<T> wrappers, a @Module providing an interface and a @Singleton value, and coexistence with a hand-written ApplicationComponent
imagedemoimagedemo.ImageDemoAppImageView.setImageSource("name.png") resolving against the PAPK ASSETS section (v1.1 bundled images). Demonstrates setScaleType / setTint / setScale. See Bundled image assets
pickerdemopickerdemo.PickerDemoAppDatePicker (lv_calendar binding) and TimePicker (lv_roller binding) with 12-hour / AM-PM mode and value-changed listeners
snackbardemosnackbardemo.SnackbarDemoAppSnackbar.make().setAction().show() — toast with a clickable action lozenge, auto-dismiss, click-through-to-listener
swipedemoswipedemo.SwipeDemoAppOnSwipeListener (UP / DOWN / LEFT / RIGHT direction constants) on a single view; SwipeRefreshLayout pull-to-refresh container

Performance and Testing

Benchmarks and stress tests for the JVM runtime and allocator. Reference: System & concurrency (Runtime.gcCount(), Runtime.gcTimeNanos()); for the numbers these probe, see Limits & memory budgets and JVM tunables.

ExampleClassDescription
benchmarkbenchmark.BenchmarkJVM performance benchmark: times int/long/float/double arithmetic, method dispatch, interface dispatch, object allocation, array ops, string ops, and control flow; logs per-category and total elapsed time
perfbenchperfbench.PerfBenchUnified speed + memory benchmark — rolls execution-time and heap-usage measurements into a single composite SCORE for tracking runtime regressions
graphicsbenchgraphicsbench.GraphicsBenchLVGL render-pipeline benchmark — exercises the draw/refresh path across several test cases and reports a composite SCORE
gcstressgcstress.GcStressGC stress test: exercises the mark-sweep collector under object churn, linked chains, circular references, string churn, and array churn; reports cycle count, freed entries, and GC time via picodroid.os.Runtime
heapstressheapstress.HeapStressAllocation/fragmentation stress test exercising the array arena allocator and emergency-GC path
tracedemotracedemo.TraceDemoBytecode-level tracing harness — exercises the JVM’s diagnostic trace mode for verifying interpreter behavior under controlled inputs
bugbashbugbash.BugBashPure-logic regression checks for the 2026-08-30 bug bash — each check names the defect id it pins, proving through real bytecode what the unit tests guard in Rust
bugbash_uibugbashui.BugBashUiAppLifecycle half of the bug-bash regression app — self-driving Activity/Service walk covering finish() idempotence, service bind limits, and pending-op delivery
executorstressexecutorstress.ExecutorStressGC-rooting stress for Runnables in flight in the executor queues: posts lambdas whose only reference is the queued executor word, then forces collections before the queue drains
threadstressthreadstress.ThreadStressConcurrent-allocation stress for the compound-heap atomic sections — three child threads plus the main task churn the shared heap; run under --mem-diag with offensive checks armed

Feature Showcase

End-to-end apps that combine multiple subsystems. These are the closest reference for the layout and structure of a “real” picodroid app.

ExampleClassDescription
picoenvmonpicoenvmon.EnvAppEnvironmental monitor for the Pimoroni Enviro+ Pack. Multi-Activity (HomeActivity, settings, history, network) with a sub-package layout (ui/, service/, net/, hardware/, data/, util/); customizes the global Theme palette in Application.onCreate(); runs a SensorLoggerService ring-buffering BME688 + LTR559 readings; drives an RGB LED. Wired with @Inject / @Singleton throughout — app-scoped ThresholdConfig, Formatter, LatestReadings, RgbLed, NetworkManager, plus SharedPreferences from an @Provides method in EnvModule, injected into every Activity and the Service

Running an Example

Terminal window
./scripts/build.sh --app <name>
./scripts/flash.sh --app <name>

Or test on the host simulator without hardware:

Terminal window
./scripts/sim.sh --app <name>

See Build & flash for full build and flash options.