Covers USB debugging setup, battery optimization settings for major OEMs (Samsung, Xiaomi, OnePlus, Huawei, Oppo), log monitoring, and troubleshooting. Complements EMULATOR_GUIDE for real-device validation.
520 lines
13 KiB
Markdown
520 lines
13 KiB
Markdown
# 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 com.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 "com.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 "com.timesafari"
|
|
```
|
|
|
|
### Test Force Stop Recovery
|
|
|
|
1. Schedule a notification
|
|
2. Force stop the app:
|
|
```bash
|
|
adb shell am force-stop com.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 com.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 com.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 "com.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 "com.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 com.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 com.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. 📱
|