Landscape mode — dark theme
Landscape mode — light theme
Portrait mode — compact vertical layout
- APK installation — install
.apkfiles directly via ADB - AAB installation — install
.aabfiles via bundletool with optional keystore signing - AAB → APK extraction — convert
.aabto a universal.apkfile (no device required) - Auto-updater — checks for updates on launch and prompts to download, install, and relaunch automatically
- Package management — launch or uninstall apps by package name
- Auto package name detection — extracts the package name from APK and AAB files automatically
- Zero dependencies — downloads ADB, bundletool, and Java JRE on demand (no Android SDK or system Java needed)
- Update reminders — notifies when managed tools are 30+ days old (never auto-downloads without consent)
- Visual status indicators — flashing red borders when tools are missing or no device is connected
- Drag & drop — drag APK or AAB files from Finder / Explorer directly into the app; supports multiple files for batch install
- Batch file install — select or drop multiple APK/AAB files and install them sequentially across all target devices with per-file progress
- Device info — Android version, API level, and free storage shown below the device dropdown and in the device selector
- Keyboard shortcuts —
Cmd/Ctrl+Oopen file,Cmd/Ctrl+Iinstall,Cmd/Ctrl+Shift+Iinstall & run,Cmd/Ctrl+Llaunch,Cmd/Ctrl+Kstop,Cmd/Ctrl+Uuninstall,Cmd/Ctrl+Eextract APK - Toast notifications — auto-dismissing success/error/warning/info toasts for key events (install, launch, stop, uninstall, ADB detection, extraction)
- Landscape & Portrait modes — toggle between a wide two-panel layout and a compact vertical layout
- Dark & Light themes — switch themes with one click; preference is saved across sessions
- Collapsible sections — Device, Tools, and AAB Settings collapse when not needed, expand when they need attention
- Draggable panel divider — resize the log panel width in landscape mode; width is remembered
- Smart auto-collapse — Device section collapses once a device is connected, Tools section collapses once everything is installed
- Inline action buttons — Install, Launch, and Uninstall buttons live on the Device header, always accessible
- Auto device refresh — devices poll every 8 seconds and on window focus; new connections are detected automatically
- Multi-device install — install to all connected devices at once with a single checkbox
- Log copy — copy the full activity log to your clipboard for troubleshooting
- Recent files — quickly re-select recently used APK/AAB files and keystores
- Version display — app version shown in the header so you always know what build you're running
- Dynamic title bar — window title updates to show the currently selected filename
- macOS — Apple Silicon (ARM64) and Intel (x64)
- Windows — installer (
.msi/-setup.exe) and portable (.exe) - Linux —
.deband.AppImage
Grab the latest release from the Releases page.
| Platform | Files |
|---|---|
| 🍎 macOS (Apple Silicon) | .dmg |
| 🍎 macOS (Intel) | .dmg |
| 🪟 Windows (Installer) | .msi, -setup.exe |
| 🪟 Windows (Portable) | -portable.exe |
| 🐧 Linux | .deb, .AppImage |
🍎 macOS users — first launch: Since the app is not notarized with Apple, macOS will show "cannot be opened because the developer cannot be verified" on first launch. To open it:
- Right-click (or Control-click) the app and choose Open
- Click Open in the confirmation dialog
You only need to do this once — macOS remembers your choice.
Alternatively, go to System Settings → Privacy & Security and click Open Anyway next to the app's name.
Still seeing "App is damaged"?
If you downloaded a release prior to v1.6.0, remove the quarantine flag manually:
xattr -cr "/Applications/Android Application Installer.app"
- An Android device with USB debugging enabled
- A USB cable (or wireless ADB pairing)
For development only:
- Download from the Releases page
- Open the app
- Click Download ADB when prompted
- Connect your Android device via USB
- Select an APK or AAB file and hit Install
# Install frontend dependencies
npm install
# Run in development mode
npm run tauri dev
# Build for production
npm run tauri buildBuild artifacts output to src-tauri/target/release/bundle/.
The app downloads and manages its own tools — nothing is installed system-wide.
| Tool | Source | Purpose |
|---|---|---|
| ADB | Google Platform-Tools | Communicate with Android devices |
| bundletool | GitHub Releases | Convert .aab → .apks and install |
| Java JRE 21 | Eclipse Temurin | Required to run bundletool |
Custom keystores are supported for signed builds — the app auto-detects key aliases from your keystore file.
Text version
├── src/ # React frontend
│ ├── App.tsx # Main application component
│ ├── App.css # Styles (themes, layouts)
│ ├── api.ts # Typed IPC layer (wraps all Tauri invoke calls)
│ ├── types.ts # TypeScript interfaces
│ ├── helpers.ts # Utility functions
│ ├── main.tsx # React entry point
│ ├── components/
│ │ ├── AppHeader.tsx # Header with title & version
│ │ ├── FileSection.tsx # File selection & AAB extraction
│ │ ├── DeviceSection.tsx # Device selection & actions
│ │ ├── AabSettingsSection.tsx # AAB signing settings
│ │ ├── ToolsSection.tsx # Tools setup & stale banner
│ │ ├── LogPanel.tsx # Activity log panel
│ │ ├── Toolbar.tsx # Layout & theme toggles
│ │ ├── Toast.tsx # Toast notification system
│ │ ├── EasterEggOverlay.tsx # Easter egg overlay
│ │ └── StatusIndicators.tsx # StatusDot & LogIcon
│ ├── hooks/
│ │ ├── useAabSettings.ts # AAB signing state & detection
│ │ ├── useDeviceState.ts # Device list & selection
│ │ ├── useFileState.ts # File selection & drag-drop
│ │ ├── useToolsState.ts # Tool download & status
│ │ ├── useUpdater.ts # Auto-updater logic
│ │ ├── useLayout.ts # Layout state & persistence
│ │ ├── useKeyboardShortcuts.ts # Keyboard shortcuts
│ │ └── useEasterEgg.ts # Easter egg hook
│ └── __tests__/ # Unit tests (vitest)
│
├── src-tauri/ # Rust backend (Tauri)
│ ├── src/
│ │ ├── main.rs # App entry point
│ │ ├── lib.rs # Tauri command registry
│ │ ├── adb.rs # ADB ops, install, extract APK
│ │ ├── cmd.rs # Command execution utilities
│ │ ├── java.rs # Java & bundletool detection
│ │ ├── package.rs # Package name extraction
│ │ └── tools/ # Managed tool downloads
│ │ ├── mod.rs # Module root
│ │ ├── config.rs # Tool config persistence
│ │ ├── download.rs # Download & extract logic
│ │ ├── paths.rs # Platform-specific paths
│ │ ├── recent.rs # Recent files tracking
│ │ └── status.rs # Tool status & staleness
│ ├── Cargo.toml # Rust dependencies
│ ├── tauri.conf.json # Tauri app config
│ └── capabilities/ # Tauri permissions
│
├── scripts/ # Developer tooling
│ ├── bump-version.mjs # Version sync script
│ ├── release.mjs # Release automation
│ ├── publish-release.mjs # Publish GitHub release drafts
│ ├── update-changelog.mjs # Auto-generate changelog
│ ├── generate-updater-json.mjs # Build updater.json from release assets (CI)
│ └── lib/
│ └── categorize-commits.mjs # Commit categorization
│
├── .github/workflows/
│ └── build.yml # CI: build & release
├── CHANGES.md # Version changelog
├── updater.json # Auto-updater manifest (CI-generated)
├── index.html # HTML entry point
├── vite.config.ts # Vite configuration
├── tsconfig.json # TypeScript config
└── package.json # npm scripts & deps
The GitHub Actions workflow builds for macOS (ARM64 + x64), Windows (x64), and Linux (x64).
Automatic release — use the release script:
npm run release:patch # 1.1.2 → 1.1.3 + commit + tag + push
npm run release:minor # 1.1.2 → 1.2.0
npm run release:major # 1.1.2 → 2.0.0
npm run release -- 2.0.0 # set exact versionThis bumps the version in all config files, commits, tags, and pushes — the tag triggers the CI build automatically.
Manual tag (without the script):
npm run version -- 1.2.0 # bump version files
git add -A && git commit -m "release: v1.2.0"
git tag v1.2.0
git push --tagsManual build — trigger from the Actions tab (artifacts downloadable without creating a release).
🍎 macOS Code Signing & Notarization
By default, macOS builds are ad-hoc signed — this is free, requires no Apple account, and prevents the "app is damaged" error. Users will see an "unidentified developer" dialog that they can bypass with right-click → Open.
To eliminate all Gatekeeper warnings (app opens with zero prompts), configure full Developer ID signing and notarization by adding these GitHub repository secrets (Settings → Secrets and variables → Actions):
| Secret | Description |
|---|---|
APPLE_CERTIFICATE |
Base64-encoded .p12 Developer ID certificate |
APPLE_CERTIFICATE_PASSWORD |
Password for the .p12 file |
APPLE_SIGNING_IDENTITY |
e.g. Developer ID Application: Your Name (TEAM_ID) |
APPLE_ID |
Your Apple ID email |
APPLE_PASSWORD |
App-specific password (not your Apple ID password) |
APPLE_TEAM_ID |
Your 10-character Apple Developer Team ID |
Steps to set up:
- Enroll in the Apple Developer Program ($99/year)
- In Keychain Access, create a Developer ID Application certificate
- Export it as a
.p12file with a password - Base64-encode it:
base64 -i certificate.p12 | pbcopy - Generate an app-specific password for your Apple ID
- Add all six secrets to your GitHub repository
Once configured, the CI workflow will automatically sign and notarize macOS builds. Without these secrets, ad-hoc signing is used as the fallback (right-click → Open still required).
🔄 Auto-Updater Signing
The app includes an auto-updater that checks for new versions on launch. Updates are cryptographically signed with Ed25519 to prevent tampering.
Required secret (must be set for signed updates to work):
| Secret | Description |
|---|---|
TAURI_SIGNING_PRIVATE_KEY |
Ed25519 private key generated by npx tauri signer generate |
TAURI_SIGNING_PRIVATE_KEY_PASSWORD |
Password for the private key (optional, if key was generated without one) |
How it works:
- CI builds include
TAURI_SIGNING_PRIVATE_KEY→ Tauri produces.sigfiles alongside each bundle - After all builds complete, the
update-updater-jsonCI job fetches the.sigfiles and writesupdater.json updater.jsonis committed tomainand served via GitHub raw URL- The app checks this URL on launch → if a newer version exists, the user sees an update prompt
Generating the key pair:
npx tauri signer generate -w ~/.tauri/android-application-installer.keyThe public key is already embedded in tauri.conf.json. Only the private key needs to be added as a GitHub secret.
Version management: The app version is stored in
package.json,src-tauri/tauri.conf.json, andsrc-tauri/Cargo.toml. Usenpm run versionto check sync status. See docs/architecture.md for full details.
| Component | Technology |
|---|---|
| Framework | Tauri 2 |
| Backend | Rust |
| Frontend | React 19 + TypeScript |
| Styling | CSS3 (Modular & Themed) |
| Icons | Lucide React |
| Build Tool | Vite 6 |
| Testing | Vitest + React Testing Library |
| HTTP Client | reqwest (Rust) |


