Skip to content

havokentity/android-application-installer

Repository files navigation

Android Application Installer

Android Application Installer

Install APK & AAB files onto Android devices — no SDK required.

Build & Release License: MIT Tauri React Rust TypeScript

macOS Windows Linux

📸 Screenshots

Landscape mode (dark theme)

Landscape mode — dark theme

Landscape mode (light theme)

Landscape mode — light theme

Portrait mode (dark theme)

Portrait mode — compact vertical layout


🛠 Features

📦 Core

  • APK installation — install .apk files directly via ADB
  • AAB installation — install .aab files via bundletool with optional keystore signing
  • AAB → APK extraction — convert .aab to a universal .apk file (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

⚙️ Tools & Setup

  • 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

🎨 Interface

  • 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 shortcutsCmd/Ctrl+O open file, Cmd/Ctrl+I install, Cmd/Ctrl+Shift+I install & run, Cmd/Ctrl+L launch, Cmd/Ctrl+K stop, Cmd/Ctrl+U uninstall, Cmd/Ctrl+E extract 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

🖥️ Cross-Platform

  • macOS — Apple Silicon (ARM64) and Intel (x64)
  • Windows — installer (.msi / -setup.exe) and portable (.exe)
  • Linux.deb and .AppImage

📥 Downloads

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:

  1. Right-click (or Control-click) the app and choose Open
  2. 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"

🚀 Getting Started

Prerequisites

  • An Android device with USB debugging enabled
  • A USB cable (or wireless ADB pairing)

For development only:

Using a Release Build

  1. Download from the Releases page
  2. Open the app
  3. Click Download ADB when prompted
  4. Connect your Android device via USB
  5. Select an APK or AAB file and hit Install

Building from Source

# Install frontend dependencies
npm install

# Run in development mode
npm run tauri dev

# Build for production
npm run tauri build

Build artifacts output to src-tauri/target/release/bundle/.


⚙️ How It Works

Managed Tools

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

AAB Installation Flow

AAB Installation Flow

Custom keystores are supported for signed builds — the app auto-detects key aliases from your keystore file.

UI Layout

UI Layout — Landscape Mode


🗂 Project Structure

Project Structure

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

🔄 CI / CD

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 version

This 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 --tags

Manual 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:

  1. Enroll in the Apple Developer Program ($99/year)
  2. In Keychain Access, create a Developer ID Application certificate
  3. Export it as a .p12 file with a password
  4. Base64-encode it: base64 -i certificate.p12 | pbcopy
  5. Generate an app-specific password for your Apple ID
  6. 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:

  1. CI builds include TAURI_SIGNING_PRIVATE_KEY → Tauri produces .sig files alongside each bundle
  2. After all builds complete, the update-updater-json CI job fetches the .sig files and writes updater.json
  3. updater.json is committed to main and served via GitHub raw URL
  4. 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.key

The 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, and src-tauri/Cargo.toml. Use npm run version to check sync status. See docs/architecture.md for full details.


🛠️ Tech Stack

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)

📄 License

MIT

About

Cross-platform desktop app for installing APK & AAB files onto Android devices — no SDK required. Built with Tauri 2 + React.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors