451 lines
12 KiB
Markdown
451 lines
12 KiB
Markdown
# Running Android App in Standalone Emulator (Without Android Studio)
|
||
|
||
**Author**: Matthew Raymer
|
||
**Last Updated**: 2026-02-05
|
||
**Version**: 1.1.0
|
||
|
||
## Overview
|
||
|
||
This guide demonstrates how to run the DailyNotification plugin test app in a standalone Android emulator without using Android Studio. This method is useful for development, CI/CD pipelines, and resource-constrained environments.
|
||
|
||
## Prerequisites
|
||
|
||
### Required Software
|
||
- **Android SDK** with command line tools
|
||
- **Android Emulator** (`emulator` command)
|
||
- **ADB** (Android Debug Bridge)
|
||
- **Gradle** (via Gradle Wrapper)
|
||
- **Node.js** and **npm** (for TypeScript compilation)
|
||
|
||
### System Requirements
|
||
- **RAM**: 4GB minimum, 8GB recommended
|
||
- **Storage**: 2GB free space for emulator
|
||
- **OS**: Linux, macOS, or Windows with WSL
|
||
|
||
## Checking and Installing Prerequisites
|
||
|
||
### How to check
|
||
|
||
Run these in a terminal. If a command is missing or a check fails, use the install steps below.
|
||
|
||
| Requirement | How to check |
|
||
|------------------|--------------|
|
||
| **Node.js** | `node --version` (v14+ recommended; test app may require 20+) |
|
||
| **npm** | `npm --version` |
|
||
| **Java** | `java -version` (Java 11+; build scripts expect 11+) |
|
||
| **ANDROID_HOME** | `echo $ANDROID_HOME` (must be set to your Android SDK root) |
|
||
| **adb** | `adb version` (must be on PATH; usually `$ANDROID_HOME/platform-tools/adb`) |
|
||
| **emulator** | `emulator -version` (must be on PATH; usually `$ANDROID_HOME/emulator/emulator`) |
|
||
| **At least one AVD** | `emulator -list-avds` (must list at least one device name) |
|
||
|
||
**Project script:** From the repo root you can run:
|
||
|
||
```bash
|
||
node scripts/check-environment.js
|
||
```
|
||
|
||
This checks Node, npm, Java, and `ANDROID_HOME`. It does **not** check `adb`, `emulator`, or AVDs—verify those manually as above.
|
||
|
||
### How to install
|
||
|
||
- **Node.js and npm**
|
||
- Install from [nodejs.org](https://nodejs.org/) (LTS), or on macOS: `brew install node`.
|
||
|
||
- **Java (JDK 11+)**
|
||
- macOS: `brew install openjdk@17` and follow the caveats to link (e.g. `sudo ln -sfn $(brew --prefix)/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-17.jdk`).
|
||
- Or install [Eclipse Temurin](https://adoptium.net/) / [Oracle JDK](https://www.oracle.com/java/technologies/downloads/) and ensure `java` and `javac` are on your PATH.
|
||
|
||
- **Android SDK (without Android Studio)**
|
||
1. Download the [Command-line tools only](https://developer.android.com/studio#command-tools) package for your OS.
|
||
2. Create an SDK directory, e.g. `mkdir -p ~/android-sdk` and extract the zip so that you have `~/android-sdk/cmdline-tools/latest/` (the `bin` folder with `sdkmanager` and `avdmanager` must be inside `cmdline-tools/latest/`).
|
||
3. Set environment variables (add to `~/.zshrc` or `~/.bashrc`):
|
||
|
||
```bash
|
||
export ANDROID_HOME=$HOME/android-sdk
|
||
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator
|
||
```
|
||
|
||
4. Install required SDK packages (accept licenses when prompted):
|
||
|
||
```bash
|
||
sdkmanager "platform-tools"
|
||
sdkmanager "emulator"
|
||
sdkmanager "platforms;android-35"
|
||
sdkmanager "build-tools;35.0.0"
|
||
```
|
||
|
||
Install a system image that matches your host CPU:
|
||
- **Apple Silicon (M1/M2/M3, aarch64):** `sdkmanager "system-images;android-35;google_apis;arm64-v8a"`
|
||
- **Intel Mac / Windows / Linux (x86_64):** `sdkmanager "system-images;android-35;google_apis;x86_64"`
|
||
|
||
5. Create at least one AVD (use the same image type you installed):
|
||
|
||
**Apple Silicon:**
|
||
```bash
|
||
avdmanager create avd -n Pixel8_API35 -k "system-images;android-35;google_apis;arm64-v8a" -d "pixel_8"
|
||
```
|
||
|
||
**Intel / x86_64:**
|
||
```bash
|
||
avdmanager create avd -n Pixel8_API35 -k "system-images;android-35;google_apis;x86_64" -d "pixel_8"
|
||
```
|
||
|
||
Then start the emulator with: `emulator -avd Pixel8_API35 -no-snapshot-load &` and use `adb wait-for-device` before building/installing the app.
|
||
|
||
- **Gradle**
|
||
The project uses the Gradle Wrapper (`gradlew`) inside the app’s `android` directory. No separate Gradle install is needed.
|
||
|
||
After installing, run the checks again to confirm `adb`, `emulator`, and `emulator -list-avds` work.
|
||
|
||
## Step-by-Step Process
|
||
|
||
### 1. Check Available Emulators
|
||
|
||
```bash
|
||
# List available Android Virtual Devices (AVDs)
|
||
emulator -list-avds
|
||
|
||
# Example output:
|
||
# Pixel8_API35
|
||
```
|
||
|
||
### 2. Start the Emulator
|
||
|
||
```bash
|
||
# Start emulator in background (recommended)
|
||
emulator -avd Pixel8_API35 -no-snapshot-load &
|
||
|
||
# Alternative: Start in foreground
|
||
emulator -avd Pixel8_API35
|
||
```
|
||
|
||
**Flags Explained:**
|
||
- `-avd Pixel8_API35` - Specifies the AVD to use
|
||
- `-no-snapshot-load` - Forces fresh boot (recommended for testing)
|
||
- `&` - Runs in background (optional)
|
||
|
||
### 3. Wait for Emulator to Boot
|
||
|
||
```bash
|
||
# Wait for emulator to be ready
|
||
adb wait-for-device
|
||
|
||
# Verify emulator is running
|
||
adb devices
|
||
|
||
# Example output:
|
||
# List of devices attached
|
||
# emulator-5554 device
|
||
```
|
||
|
||
### 4. Build the Plugin and Test App
|
||
|
||
```bash
|
||
# Navigate to project directory
|
||
cd /path/to/daily-notification-plugin
|
||
|
||
# Build TypeScript and native code
|
||
./scripts/build-native.sh --platform android
|
||
```
|
||
|
||
**What this does:**
|
||
- Compiles TypeScript to JavaScript
|
||
- Builds Android native code
|
||
- Creates plugin AAR files
|
||
- Builds test app APK
|
||
|
||
### 5. Build Debug APK (Required for Installation)
|
||
|
||
```bash
|
||
# Navigate to Android directory
|
||
cd android
|
||
|
||
# Build debug version (includes debug signing)
|
||
./gradlew :app:assembleDebug
|
||
```
|
||
|
||
**Why Debug APK:**
|
||
- **Debug signing** - Automatically signed for installation
|
||
- **No certificates needed** - Uses default debug keystore
|
||
- **Faster builds** - No optimization, faster compilation
|
||
|
||
### 6. Install APK on Emulator
|
||
|
||
```bash
|
||
# Install the debug APK
|
||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||
|
||
# Alternative: Install with replacement
|
||
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||
```
|
||
|
||
**Installation Options:**
|
||
- `adb install` - Install new app
|
||
- `adb install -r` - Replace existing app
|
||
- `adb install -t` - Allow test APKs
|
||
|
||
### 7. Launch the App
|
||
|
||
```bash
|
||
# Launch the app
|
||
adb shell am start -n org.timesafari.dailynotification/.MainActivity
|
||
|
||
# Alternative: Launch with specific intent
|
||
adb shell am start -a android.intent.action.MAIN -n org.timesafari.dailynotification/.MainActivity
|
||
```
|
||
|
||
### 8. Monitor App Logs
|
||
|
||
```bash
|
||
# View all logs
|
||
adb logcat
|
||
|
||
# Filter for specific tags
|
||
adb logcat -s "Capacitor" "DailyNotification" "Console"
|
||
|
||
# View logs for specific process
|
||
adb logcat --pid=<PID>
|
||
|
||
# Clear logs and view new ones
|
||
adb logcat -c && adb logcat
|
||
```
|
||
|
||
## Complete Command Sequence
|
||
|
||
### Quick Start (Copy-Paste Ready)
|
||
|
||
```bash
|
||
# 1. Start emulator
|
||
emulator -avd Pixel8_API35 -no-snapshot-load &
|
||
|
||
# 2. Wait for emulator
|
||
adb wait-for-device
|
||
|
||
# 3. Build everything
|
||
./scripts/build-native.sh --platform android
|
||
|
||
# 4. Build debug APK
|
||
cd android && ./gradlew :app:assembleDebug
|
||
|
||
# 5. Install APK
|
||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||
|
||
# 6. Launch app
|
||
adb shell am start -n org.timesafari.dailynotification/.MainActivity
|
||
|
||
# 7. Monitor logs
|
||
adb logcat -s "Capacitor" "DailyNotification" "Console"
|
||
```
|
||
|
||
## Alternative Methods
|
||
|
||
### Method 1: Using Capacitor CLI
|
||
|
||
```bash
|
||
# Build and run in one command
|
||
npx cap run android
|
||
|
||
# This will:
|
||
# - Build the plugin
|
||
# - Sync web assets
|
||
# - Build and install APK
|
||
# - Launch the app
|
||
```
|
||
|
||
### Method 2: Direct Gradle Commands
|
||
|
||
```bash
|
||
# Build and install directly
|
||
cd android
|
||
./gradlew :app:assembleDebug
|
||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||
adb shell am start -n org.timesafari.dailynotification/.MainActivity
|
||
```
|
||
|
||
### Method 3: Using Monkey (Alternative Launch)
|
||
|
||
```bash
|
||
# Install and launch with Monkey
|
||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||
adb shell monkey -p org.timesafari.dailynotification -c android.intent.category.LAUNCHER 1
|
||
```
|
||
|
||
## Troubleshooting
|
||
|
||
### Common Issues
|
||
|
||
#### Emulator Won't Start
|
||
```bash
|
||
# Check available AVDs
|
||
emulator -list-avds
|
||
|
||
# Check emulator process
|
||
ps aux | grep emulator
|
||
|
||
# Kill existing emulator
|
||
pkill -f emulator
|
||
|
||
# Start with verbose logging
|
||
emulator -avd Pixel8_API35 -verbose
|
||
```
|
||
|
||
#### "x86_64 is not supported by the QEMU2 emulator on aarch64 host"
|
||
On Apple Silicon (M1/M2/M3), the emulator cannot run x86_64 system images. Use an ARM64 image and AVD instead:
|
||
|
||
```bash
|
||
sdkmanager "system-images;android-35;google_apis;arm64-v8a"
|
||
avdmanager delete avd -n Pixel8_API35 # if you already created an x86_64 AVD
|
||
avdmanager create avd -n Pixel8_API35 -k "system-images;android-35;google_apis;arm64-v8a" -d "pixel_8"
|
||
emulator -avd Pixel8_API35 -no-snapshot-load
|
||
```
|
||
|
||
#### ADB Connection Issues
|
||
```bash
|
||
# Check ADB connection
|
||
adb devices
|
||
|
||
# Restart ADB server
|
||
adb kill-server
|
||
adb start-server
|
||
|
||
# Check ADB version
|
||
adb version
|
||
```
|
||
|
||
#### APK Installation Fails
|
||
```bash
|
||
# Check if app is already installed
|
||
adb shell pm list packages | grep timesafari
|
||
|
||
# Uninstall existing app
|
||
adb uninstall org.timesafari.dailynotification
|
||
|
||
# Install with force
|
||
adb install -r -t app/build/outputs/apk/debug/app-debug.apk
|
||
```
|
||
|
||
#### Build Failures
|
||
```bash
|
||
# Clean build
|
||
cd android && ./gradlew clean
|
||
|
||
# Rebuild
|
||
./gradlew :app:assembleDebug
|
||
|
||
# Check Gradle daemon
|
||
./gradlew --status
|
||
```
|
||
|
||
### Performance Optimization
|
||
|
||
#### Emulator Performance
|
||
```bash
|
||
# Start with hardware acceleration
|
||
emulator -avd Pixel8_API35 -accel on
|
||
|
||
# Start with specific RAM allocation
|
||
emulator -avd Pixel8_API35 -memory 2048
|
||
|
||
# Start with GPU acceleration
|
||
emulator -avd Pixel8_API35 -gpu host
|
||
```
|
||
|
||
#### Build Performance
|
||
```bash
|
||
# Enable Gradle daemon
|
||
echo "org.gradle.daemon=true" >> ~/.gradle/gradle.properties
|
||
|
||
# Increase memory
|
||
echo "org.gradle.jvmargs=-Xmx4g" >> ~/.gradle/gradle.properties
|
||
|
||
# Enable parallel builds
|
||
echo "org.gradle.parallel=true" >> ~/.gradle/gradle.properties
|
||
```
|
||
|
||
## Expected Results
|
||
|
||
### Successful App Launch
|
||
When the app launches successfully, you should see:
|
||
|
||
```bash
|
||
# ADB output
|
||
Starting: Intent { cmp=org.timesafari.dailynotification/.MainActivity }
|
||
|
||
# Logcat output
|
||
D Capacitor: Starting BridgeActivity
|
||
D Capacitor: Registering plugin instance: CapacitorCookies
|
||
D Capacitor: Registering plugin instance: WebView
|
||
D Capacitor: Registering plugin instance: CapacitorHttp
|
||
D Capacitor: Loading app at https://localhost
|
||
D Capacitor: App started
|
||
D Capacitor: App resumed
|
||
I Capacitor/Console: Script loading...
|
||
I Capacitor/Console: Creating mock DailyNotification plugin...
|
||
I Capacitor/Console: Functions attached to window: [object Object]
|
||
```
|
||
|
||
### App Interface
|
||
The app should display:
|
||
- **Title**: "🔔 DailyNotification Plugin Test"
|
||
- **Three buttons**: "Test Plugin", "Configure Plugin", "Check Status"
|
||
- **Status area**: Shows test results and plugin status
|
||
|
||
## Benefits of Standalone Approach
|
||
|
||
### Advantages
|
||
- ✅ **No Android Studio** - Pure command line workflow
|
||
- ✅ **Faster startup** - No IDE overhead
|
||
- ✅ **CI/CD friendly** - Works in automated environments
|
||
- ✅ **Resource efficient** - Lower memory usage
|
||
- ✅ **Scriptable** - Can be automated
|
||
- ✅ **Remote development** - Works over SSH
|
||
|
||
### Use Cases
|
||
- **Development** - Quick testing and iteration
|
||
- **CI/CD pipelines** - Automated testing
|
||
- **Remote development** - SSH-based development
|
||
- **Resource-constrained environments** - Low-spec machines
|
||
- **Team environments** - Shared development servers
|
||
|
||
## Integration with Development Workflow
|
||
|
||
### Daily Development
|
||
```bash
|
||
# Quick test cycle
|
||
./scripts/build-native.sh --platform android
|
||
cd android && ./gradlew :app:assembleDebug
|
||
adb install -r app/build/outputs/apk/debug/app-debug.apk
|
||
adb shell am start -n org.timesafari.dailynotification/.MainActivity
|
||
```
|
||
|
||
### Automated Testing
|
||
```bash
|
||
# CI/CD pipeline
|
||
emulator -avd Pixel8_API35 -no-snapshot-load &
|
||
adb wait-for-device
|
||
./scripts/build-native.sh --platform android
|
||
cd android && ./gradlew :app:assembleDebug
|
||
adb install app/build/outputs/apk/debug/app-debug.apk
|
||
adb shell am start -n org.timesafari.dailynotification/.MainActivity
|
||
# Run tests...
|
||
```
|
||
|
||
## Next Steps
|
||
|
||
### Testing the App
|
||
1. **Click "Test Plugin"** - Tests the mock plugin implementation
|
||
2. **Click "Configure Plugin"** - Tests plugin configuration
|
||
3. **Click "Check Status"** - Tests plugin status retrieval
|
||
4. **Monitor logs** - Check for any errors or issues
|
||
|
||
### Development Workflow
|
||
1. **Make changes** - Edit plugin code or test app
|
||
2. **Rebuild** - Run the build commands
|
||
3. **Reinstall** - Install updated APK
|
||
4. **Test** - Launch and test functionality
|
||
5. **Iterate** - Repeat as needed
|
||
|
||
---
|
||
|
||
**This method provides a complete standalone Android development environment without requiring Android Studio!** 🎉
|