# Running Android App on a Physical Device

**Author**: Matthew Raymer  
**Last Updated**: 2026-02-12  
**Version**: 1.0.0

## Overview

This guide demonstrates how to run the DailyNotification plugin test app on a physical Android device. Physical device testing is essential for validating:

- **Real notification behavior** — Emulators may not accurately simulate notification delivery timing
- **Battery optimization effects** — OEM-specific power management that affects background tasks
- **Actual alarm scheduling** — AlarmManager behavior varies between emulators and real hardware
- **Device reboot persistence** — Boot receivers and alarm recovery

## Prerequisites

### Required Hardware
- **Android phone or tablet** running Android 8.0 (API 26) or higher
- **USB cable** (data-capable, not charge-only)
- **Development computer** with USB port

### Required Software
- **Android SDK** with platform-tools (provides `adb`)
- **Gradle** (via Gradle Wrapper)
- **Node.js** and **npm** (for TypeScript compilation)

### How to Check

| Requirement      | How to check |
|------------------|--------------|
| **Node.js**      | `node --version` (v14+ recommended; test app may require 20+) |
| **npm**          | `npm --version` |
| **Java**         | `java -version` (Java 11+) |
| **ANDROID_HOME** | `echo $ANDROID_HOME` (must be set to your Android SDK root) |
| **adb**          | `adb version` (must be on PATH) |

**Project script:** From the repo root:

```bash
node scripts/check-environment.js
```

## Step 1: Enable Developer Options on Your Phone

Developer Options are hidden by default. To enable them:

### Android 8.0 - 14 (Most Devices)

1. Open **Settings**
2. Scroll down to **About phone** (or **About device**)
3. Find **Build number**
4. **Tap Build number 7 times** rapidly
5. You'll see "You are now a developer!" toast message

### Samsung Devices

1. **Settings** → **About phone** → **Software information**
2. Tap **Build number** 7 times

### Xiaomi/MIUI Devices

1. **Settings** → **About phone**
2. Tap **MIUI version** 7 times

### OnePlus Devices

1. **Settings** → **About phone**
2. Tap **Build number** 7 times

## Step 2: Enable USB Debugging

After enabling Developer Options:

1. Go to **Settings** → **System** → **Developer options**
   - On some phones: **Settings** → **Developer options** directly
2. Scroll to find **USB debugging**
3. Toggle **USB debugging ON**
4. Confirm when prompted

### Optional but Recommended Settings

While in Developer Options, also enable:

- **Stay awake** — Screen stays on while charging (useful during development)
- **Allow mock locations** — If testing location features

## Step 3: Connect and Authorize Your Device

### Physical Connection

1. Connect your phone to your computer via USB
2. On your phone, change USB mode:
   - Pull down notification shade
   - Tap the USB notification ("Charging this device via USB")
   - Select **File transfer / Android Auto** or **PTP** (not "Charge only")

### Authorize Computer

1. On your phone, you'll see a dialog: **"Allow USB debugging?"**
2. Check **"Always allow from this computer"** (recommended)
3. Tap **Allow**

### Verify Connection

```bash
# List connected devices
adb devices

# Expected output:
# List of devices attached
# ABC123DEF456    device
```

**Troubleshooting connection states:**

| State | Meaning | Solution |
|-------|---------|----------|
| `device` | Connected and authorized | Ready to use |
| `unauthorized` | USB debugging not authorized | Check phone for auth dialog |
| `offline` | Connection issues | Unplug, replug, restart adb |
| (empty) | Device not detected | Check USB cable, USB mode |

## Step 4: Build and Install the App

### Option A: Using Build Script (Recommended)

From the `test-apps/daily-notification-test` directory:

```bash
# Build and run on connected device
./scripts/build.sh --run-android
```

### Option B: Manual Build

```bash
# 1. Navigate to test app directory
cd test-apps/daily-notification-test

# 2. Build web assets
npm run build

# 3. Sync with Capacitor
npm run cap:sync:android

# 4. Build APK
cd android
./gradlew :app:assembleDebug

# 5. Install on device
adb install -r app/build/outputs/apk/debug/app-debug.apk

# 6. Launch app
adb shell am start -n org.timesafari.dailynotification.test/.MainActivity
```

### Option C: Using Capacitor CLI

```bash
# Build, install, and launch in one command
npx cap run android --target <device-id>

# Get device ID from:
adb devices
```

## Step 5: Configure Battery Optimization (Critical!)

**This is the most important step for notification testing.** Android OEMs aggressively kill background apps to save battery. Without proper configuration, your alarms and notifications may not fire.

### Disable Battery Optimization for Test App

1. **Settings** → **Apps** → **DailyNotification Test** (or your app name)
2. **Battery** → **Unrestricted** or **Don't optimize**

### Manufacturer-Specific Settings

#### Samsung (One UI)

1. **Settings** → **Battery** → **Background usage limits**
2. Remove app from "Sleeping apps" and "Deep sleeping apps"
3. Add app to "Never sleeping apps"

#### Xiaomi (MIUI)

1. **Settings** → **Apps** → **Manage apps** → Select app
2. Enable **Autostart**
3. **Battery saver** → **No restrictions**
4. **Security** app → **Permissions** → **Autostart** → Enable for app

#### OnePlus (OxygenOS)

1. **Settings** → **Battery** → **Battery optimization**
2. Select app → **Don't optimize**
3. **Settings** → **Apps** → Select app → **Advanced** → **Optimize battery usage** → Off

#### Huawei/Honor (EMUI)

1. **Settings** → **Battery** → **App launch**
2. Disable automatic management for the app
3. Enable all three toggles: Auto-launch, Secondary launch, Run in background

#### Oppo/Realme (ColorOS)

1. **Settings** → **Battery** → **More battery settings**
2. **Optimize battery use** → Select app → **Don't optimize**
3. Enable **Allow auto-start** and **Allow background activity**

### Verify Battery Settings

```bash
# Check if app is whitelisted from battery optimization
adb shell dumpsys deviceidle whitelist

# Should include your package name
```

## Step 6: Monitor Logs

### Real-time Log Streaming

```bash
# All logs from the app
adb logcat | grep -E "DailyNotification|Capacitor|Console"

# Specific tags only
adb logcat -s "DailyNotification" "Capacitor" "Console"

# Clear logs and start fresh
adb logcat -c && adb logcat -s "DailyNotification"
```

### Filter by Log Level

```bash
# Errors only
adb logcat *:E | grep DailyNotification

# Warnings and above
adb logcat *:W | grep DailyNotification

# Verbose (all levels)
adb logcat *:V | grep DailyNotification
```

### Save Logs to File

```bash
# Stream logs to file
adb logcat -s "DailyNotification" > device_logs.txt

# Press Ctrl+C to stop
```

### Check Alarm Scheduling

```bash
# View scheduled alarms (requires root or debuggable build)
adb shell dumpsys alarm | grep -A 5 "org.timesafari"

# View alarm statistics
adb shell dumpsys alarm | grep -i "daily"
```

## Step 7: Testing Notification Features

### Test Immediate Notification

1. Open the app
2. Navigate to notification testing section
3. Trigger an immediate notification
4. Verify it appears in the notification tray

### Test Scheduled Notification

1. Schedule a notification for 1-2 minutes in the future
2. Lock the phone or put app in background
3. Wait for notification to fire
4. Check logs if notification doesn't appear

### Test Alarm Persistence

1. Schedule a notification
2. Reboot the device:
   ```bash
   adb reboot
   ```
3. After reboot, check if alarm was restored:
   ```bash
   adb shell dumpsys alarm | grep -A 5 "org.timesafari"
   ```

### Test Force Stop Recovery

1. Schedule a notification
2. Force stop the app:
   ```bash
   adb shell am force-stop org.timesafari.dailynotification.test
   ```
3. Check if alarms are recovered (implementation dependent)

## Complete Command Sequence

### Quick Start (Copy-Paste Ready)

```bash
# 1. Verify device connection
adb devices

# 2. Navigate to test app
cd test-apps/daily-notification-test

# 3. Build everything
npm run build
npm run cap:sync:android

# 4. Build and install APK
cd android
./gradlew :app:assembleDebug
adb install -r app/build/outputs/apk/debug/app-debug.apk

# 5. Launch app
adb shell am start -n org.timesafari.dailynotification.test/.MainActivity

# 6. Monitor logs (in separate terminal)
adb logcat -s "DailyNotification" "Capacitor" "Console"
```

## Troubleshooting

### Device Not Detected

```bash
# Restart ADB server
adb kill-server
adb start-server
adb devices

# Check USB connection
# - Try different USB cable (use data cable, not charge-only)
# - Try different USB port
# - Check USB mode on phone (should be File transfer, not Charge only)
```

### "Unauthorized" Device

```bash
# Revoke USB debugging authorizations on phone:
# Settings → Developer options → Revoke USB debugging authorizations

# Then reconnect and re-authorize
adb kill-server
adb start-server
# Accept authorization dialog on phone
```

### APK Installation Fails

```bash
# Error: INSTALL_FAILED_UPDATE_INCOMPATIBLE
# Solution: Uninstall existing app first
adb uninstall org.timesafari.dailynotification.test
adb install app/build/outputs/apk/debug/app-debug.apk

# Error: INSTALL_FAILED_USER_RESTRICTED
# Solution: Enable "Install via USB" in Developer options
```

### Notifications Not Appearing

1. **Check notification permissions:**
   ```bash
   adb shell dumpsys notification | grep -A 10 "org.timesafari"
   ```

2. **Check battery optimization:**
   - Ensure app is set to "Unrestricted" or "Don't optimize"
   - Check manufacturer-specific settings (see Step 5)

3. **Check Do Not Disturb:**
   - Ensure DND is off, or app is allowed through DND

4. **Check notification channel:**
   ```bash
   adb shell dumpsys notification | grep -B 5 -A 10 "channel"
   ```

### Alarms Not Firing

1. **Check if alarms are scheduled:**
   ```bash
   adb shell dumpsys alarm | grep -A 10 "org.timesafari"
   ```

2. **Check Doze mode:**
   ```bash
   # Check current Doze state
   adb shell dumpsys deviceidle
   
   # Force device out of Doze for testing
   adb shell dumpsys deviceidle unforce
   ```

3. **Check exact alarm permission (Android 12+):**
   ```bash
   adb shell appops get org.timesafari.dailynotification.test SCHEDULE_EXACT_ALARM
   ```

### Build Failures

```bash
# Clean build
cd android
./gradlew clean
./gradlew :app:assembleDebug

# If still failing, clean Gradle cache
rm -rf ~/.gradle/caches
./gradlew :app:assembleDebug
```

## Benefits of Physical Device Testing

### Advantages Over Emulator

- ✅ **Accurate notification timing** — Real hardware scheduler behavior
- ✅ **Real battery optimization** — Test against actual OEM restrictions
- ✅ **True Doze mode** — Emulators simulate but don't fully replicate
- ✅ **Boot receiver testing** — Actual device reboot behavior
- ✅ **Performance metrics** — Real CPU/memory usage
- ✅ **User experience** — How notifications actually feel

### When to Use Physical Device

- **Final validation** — Before release
- **Notification timing tests** — Alarm accuracy verification
- **Battery impact testing** — Real power consumption
- **Reboot persistence tests** — Boot receiver validation
- **OEM-specific testing** — Samsung, Xiaomi, etc. quirks

### When Emulator is Sufficient

- **Basic functionality** — Core feature development
- **UI testing** — Layout and interaction testing
- **Quick iteration** — Fast build-test cycles
- **CI/CD pipelines** — Automated testing

## Multiple Device Management

### List All Connected Devices

```bash
adb devices -l

# Example output:
# ABC123DEF456    device usb:1-1 product:walleye model:Pixel_2 device:walleye
# XYZ789GHI012    device usb:1-2 product:star2lte model:SM_G965F device:star2lte
```

### Target Specific Device

```bash
# Install on specific device
adb -s ABC123DEF456 install -r app/build/outputs/apk/debug/app-debug.apk

# View logs from specific device
adb -s ABC123DEF456 logcat -s "DailyNotification"

# Launch app on specific device
adb -s ABC123DEF456 shell am start -n org.timesafari.dailynotification.test/.MainActivity
```

## Wireless ADB (Optional)

For cable-free development after initial setup:

```bash
# 1. Connect device via USB first
# 2. Enable TCP/IP mode on port 5555
adb tcpip 5555

# 3. Find device IP (Settings → About phone → Status → IP address)
# Or:
adb shell ip addr show wlan0 | grep inet

# 4. Disconnect USB and connect wirelessly
adb connect 192.168.1.100:5555

# 5. Verify connection
adb devices
# Should show: 192.168.1.100:5555    device
```

**Note:** Wireless ADB is slower than USB and may disconnect. Use USB for large APK transfers.

## Next Steps

### Testing Workflow

1. **Build** → Make changes, rebuild APK
2. **Install** → Push to device with `adb install -r`
3. **Test** → Exercise notification features
4. **Monitor** → Watch logs for issues
5. **Iterate** → Fix and repeat

### Recommended Test Sequence

1. ✅ Immediate notification display
2. ✅ Scheduled notification (1-2 min delay)
3. ✅ App backgrounded notification
4. ✅ Screen off notification
5. ✅ Device reboot alarm persistence
6. ✅ Force stop recovery (if implemented)
7. ✅ Battery optimization scenarios

---

**Physical device testing is essential for production-quality notification behavior.** While emulators are great for development, only real hardware reveals the true behavior of Android's notification and alarm systems. 📱
