Technical Documentation: plainhub/plain-app
βΉοΈ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference
Overview (`README.md`)
PlainApp
PlainApp is a free, open-source Android app that turns your phone into a self-hosted management hub you can access from any web browser on the same network β no accounts, no cloud, no subscriptions. Whether you need to transfer files, read SMS, browse photos, or mirror your screen, PlainApp puts full control back in your hands.
Why PlainApp?
Most phone-management tools either route your data through their own servers, lock features behind subscriptions, or plague you with ads. PlainApp is different:
- 100% local β your data never leaves your network
- End-to-end encrypted β every connection is secured with TLS + XChaCha20-Poly1305
- Completely free and ad-free β no purchases, no upsells, ever
- Fully open-source β audit the code, build your own binary, or contribute
Features
π Web-Based Phone Management
Open a browser on any desktop or laptop connected to the same Wi-Fi network and get a full dashboard to manage your Android device β no app installation required on the computer side. Supports PWA so you can pin it to your desktop like a native app.
| Category | What you can do |
|---|---|
| Files | Browse internal storage, SD card, and USB drives; upload, download, rename, delete |
| Media | View and manage photos, videos, and audio; stream them directly in the browser |
| Contacts | View, search, and manage your contacts |
| SMS & Calls | Read messages and call logs; send SMS from your desktop |
| Apps | List installed apps and export APKs |
| Notifications | Mirror phone notifications to the browser in real time |
| Screen Mirror | Live-stream the phone screen to the browser with audio and remote control support |
| Device Info | Check battery, storage, network, and system details |
π± Built-in Android Tools
PlainApp is also a capable standalone app β not just a server:
- Markdown Notes β write and organize notes with a clean editor
- RSS Reader β follow your favorite websites with a distraction-free reader
- Video & Audio Player β full-featured media player with playlist support
- TV Cast β cast media to any DLNA/Chromecast-compatible TV
- Peer-to-Peer Chat & File Sharing β share files and messages directly between devices without a server
- Pomodoro Timer β stay focused with a built-in work timer
- Sound Meter β measure ambient noise levels in real time
π Privacy & Security
- Zero data sent to any third-party server
- All traffic between phone and browser is encrypted (TLS + XChaCha20-Poly1305)
- No account registration required
Video: https://www.youtube.com/watch?v=TjRhC8pSQ6Q
Reddit: https://www.reddit.com/r/plainapp
Discord: https://discord.gg/RQWcS6DEEe
QQ Group: 812409393
How PlainApp Compares
| Feature | PlainApp | AirDroid | KDE Connect | AnExplorer | Pushbullet |
|---|---|---|---|---|---|
| Open source | β | β | β | β | β |
| 100% local / no cloud required | β | β οΈ partial | β | β | β |
| End-to-end encrypted (local) | β | β οΈ paid | β | β | β |
| Ad-free | β | β οΈ paid | β | β οΈ paid | β οΈ paid |
| Free all features | β | β οΈ freemium | β | β οΈ freemium | β οΈ freemium |
| Web browser access (no desktop app needed) | β | β | β | β | β |
| File manager (browser UI) | β | β | β οΈ limited | β | β |
| SMS from desktop | β | β | β | β | β |
| Screen mirroring | β | β | β | β | β |
| Media streaming in browser | β | β οΈ limited | β | β | β |
| Notification mirroring | β | β | β | β | β |
| Built-in RSS reader | β | β | β | β | β |
| Markdown notes | β | β | β | β | β |
| P2P chat & file sharing | β | β οΈ paid | β | β | β οΈ limited |
| TV casting (DLNA/Chromecast) | β | β | β | β | β |
| PWA support | β | β | β | β | β |
| No account required | β | β | β | β | β |
β Fully supported β οΈ Partially supported or requires paid plan β Not supported
Donations :heart:
This project needs you! If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, feel free to donate.
Your donation is highly appreciated. Thank you!
Use WeChat to scan the code
Screenshots
Android App
Web Dashboard
Compatibility
PlainApp requires Android 9.0 or higher.
FAQ
Support
PlainApp is fully open-source.
If you have any doubts, you're free to review the code, build your own version, or simply choose not to use it.
If you run into issues, feel free to open a GitHub issue β I'm always happy to help.
Please donβt leave a one-star review without giving it a fair try.
Work on plain-core
Keep plain-core next to this repository. Run from this repository root.
./scripts/core local # Use local plain-core
./scripts/core local --off # Stop using local paths
./scripts/core update # Lock this project to the latest remote commitBuild
- Generate
release.jksfile under$rootProject/appfolder.
keytool -genkeypair -v -keystore ./app/release.jks -alias release -keyalg RSA -keysize 4096 -validity 36500- Create
keystore.propertiesfile with following content under$rootProjectfolder.
storePassword=
keyPassword=
keyAlias=release
storeFile=release.jksOverview (`plain-common/README.md`)
plain-common
Reusable Kotlin Multiplatform code extracted from PlainApp. Source packages are
kept unchanged under com.ismartcoding.plain.
The module includes common helpers, crypto, extensions, logcat,
and XML/RSS support. Supporting sources are included here so this module
has no dependency on the host application.
BLE protocol and native codec adapters belong to plain-rs features. Platform GATT adapters stay in the host shared module. This Kotlin library contains no BLE source.
Maven coordinates
implementation("com.ismartcoding:plain-common:0.1.7")Add the public GitHub Pages Maven repository to the consuming project's
repositories:
maven {
url = uri("https://plainhub.github.io/plain-app/maven")
}Then add the dependency shown above. Releases use tags namedplain-common-v<version>; the default local version can be changed with-PplainCommonVersion=β¦.
Publishing
The Publish plain-common GitHub Actions workflow builds the KMP publications
and adds the Maven files to the dedicated maven branch under maven/ when aplain-common-v<version> tag is pushed. The workflow also syncs policy.html and terms.html from main so their existing public URLs stay available. It can also be run manually with a
version number. The workflow uses its temporary GITHUB_TOKEN; no publishing
credentials are stored in the repository.
For a local Maven cache, run ./gradlew :plain-common:publishToMavenLocal.
Overview (`plain-ui/README.md`)
plain-ui
Shared Compose Multiplatform components in com.ismartcoding.plain.ui.
This is the component selection entry point for PlainApp and PlainNet (plain-router-app).
Before editing UI, choose the scene below, open its compiled example, and read the actual component signature. Pages compose existing components and connect state and events.
| Scene | Use | Compiled example |
|---|---|---|
| Page and top bar | PScaffold + PTopAppBar |
ComponentShowcasePage |
| Primary, outlined, text action | PFilledButton, POutlinedButton, PTextButton; size via ButtonSize, role via ButtonType |
Button states |
| Text input, password, validation | PTextField; choose enabled and readOnly independently |
Form states |
| Single choice between a few options | PSegmentedButtons |
Segmented buttons |
| Cards, list rows, banners, filters, removable chips | PCard, PListItem, PBanner, PFilterChip, PInputChip |
Component showcase |
| Bottom sheet | PModalBottomSheet + PBottomSheetTopAppBar; primary actions use PSheetPrimaryActionsCard, overflow uses PSheetActionCard |
FileInfoBottomSheet |
| Confirmation and input dialog | Host confirmActionAsync / DialogHelper, TextFieldDialog, RadioDialog; selection rows use PDialogRadioRow |
DialogHelper |
| Icon with label below | PIconTextSmallButton for compact toolbar; PIconTextActionButton for shortcuts; PSheetPrimaryAction for sheet actions |
State showcase |
| Boolean / radio / simple icon control | Official Material3 Switch, RadioButton, IconButton; use host icon shortcuts when applicable |
Dark theme choices |
| Media seek, animated waveform, countdown | PlayerSlider, WaveSlider, CircularTimer |
PomodoroPage |
| Large document, scan, drag selection, fast scroll, pull refresh | CodeEditor, QrCodeScanner, gridDragSelect, fastscroll and pullrefresh packages |
TextFilePage |
The first eight scenes require the existing project components. Basic layout (Box, Row, Column), text, images and controls in the official-control row can use Compose directly. Specialized editor, scanner and gesture engines keep their own behavior; inspect their contracts before extending them. Host dialog helpers use each application's resources and state, and stay outside this library.
Use AppTheme as the complete theme entry. Keep the brand palette, soft dark text and AMOLED behavior; dynamic color is excluded. Shapes come from the theme: medium for ordinary cards/inputs, large for prominent preview/banner containers, smaller roles for nested surfaces, and CircleShape for capsules/discs. Exact dynamic geometry belongs to its specialized implementation. Brand sizes are defined in Shapes, not Material default sizes.
Public layout components accept a root modifier. Actions use onClick, enabled and onDismissRequest. Required actions have no default empty callback; optional actions are nullable and create no click target when absent. Each distinct public component has its own file; overloads of the same component may share it. Code comments use English and explain only non-obvious decisions.
Read parameter behavior in the source: PScaffold consumes horizontal insets and passes only top/bottom padding to content; PTextField renders its own error message; PInputChip.onClose determines whether the close target exists (onClick = null makes the whole chip a remove action); PListItem.dimmed is visual dimming and its two title extension slots are mutually exclusive. Sheet primary rows accept at most four actions, including in RTL. Button loading prevents interaction while preserving label width. Do not recreate these policies in business pages.
Run bash scripts/check-ui.sh from plain-app or plain-router-app after UI changes, followed by the host application's build. The shared Kotlin PSI checker resolves explicit imports, aliases, wildcard imports and fully qualified calls; it ignores comments and strings, rejects new raw Material page/sheet/button/form calls and literal shapes, and checks public library layout contracts. It generates the component symbol index under the applicationβs build/reports/ui-check/ from source. Legacy business occurrences are frozen by exact file, function, symbol and count in each application's scripts/ui-component-baseline.tsv; entries name remaining migration debt or specialized geometry. Do not add entries to get a new violation through. Delete an entry when migrating its owner. No package-wide exclusion is supported.
This syntax check does not perform whole-program type inference or detect an arbitrary layout recreating a component. Compiler checks, the scene index, examples and review remain necessary. The showcase includes disabled/loading/error/read-only states and RTL/large-text controls; device checks must also cover light, dark, AMOLED, TalkBack, keyboard and neighboring touch targets. Performance changes need release traces before claiming a measured speedup.
Maven coordinate: com.ismartcoding:plain-ui, repository https://plainhub.github.io/plain-app/maven.
The Publish plain-ui workflow publishes tagged plain-ui-v<version> releases on the dedicated maven branch. Consumers must upgrade after publication; local cross-project validation can selectively substitute plain-ui, preserving their own plain-common version.
--- METRICS ---
- Files Extracted: 3
- Estimated Token Budget: ~4055 tokens
- Canonical Reference: https://codewiki.google/github.com/plainhub/plain-app