# Android Physical Device Deployment Guide

**Author**: Matthew Raymer  
**Date**: 2025-02-12  
**Status**: 🎯 **ACTIVE** - Complete guide for deploying TimeSafari to physical Android devices

## Overview

This guide provides comprehensive instructions for building and deploying TimeSafari to physical Android devices for testing and development. Unlike emulator testing, physical device testing requires additional setup for USB connections and network configuration.

## Prerequisites

### Required Tools

1. **Android SDK Platform Tools** (includes `adb`)
   ```bash
   # macOS (Homebrew)
   brew install android-platform-tools
   
   # Or via Android SDK Manager
   sdkmanager "platform-tools"
   ```

2. **Node.js 18+** and npm

3. **Java Development Kit (JDK) 17+**
   ```bash
   # macOS (Homebrew)
   brew install openjdk@17
   
   # Verify installation
   java -version
   ```

### Environment Setup

Add to your shell configuration (`~/.zshrc` or `~/.bashrc`):

```bash
# Android SDK location
export ANDROID_HOME=$HOME/Library/Android/sdk  # macOS default
# export ANDROID_HOME=$HOME/Android/Sdk        # Linux default

export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin
export PATH=$PATH:$ANDROID_HOME/build-tools/34.0.0
```

Reload your shell:

```bash
source ~/.zshrc  # or source ~/.bashrc
```

Verify installation:

```bash
adb version
```

## Device Setup

### Step 1: Enable Developer Options

Developer Options is hidden by default on Android devices. To enable it:

1. Open **Settings** on your Android device
2. Scroll down and tap **About phone** (or **About device**)
3. Find **Build number** and tap it **7 times** rapidly
4. You'll see a message: "You are now a developer!"
5. Go back to Settings - **Developer options** now appears

### Step 2: Enable USB Debugging

1. Go to **Settings** → **Developer options**
2. Enable **USB debugging** (toggle it ON)
3. Optionally enable these helpful options:
   - **Stay awake** - Screen stays on while charging
   - **Install via USB** - Allow app installations via USB

### Step 3: Connect Your Device

1. Connect your Android device to your computer via USB cable
2. On your device, you'll see a prompt: "Allow USB debugging?"
3. Check **"Always allow from this computer"** (recommended)
4. Tap **Allow**

### Step 4: Verify Connection

```bash
# List connected devices
adb devices

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

If you see `unauthorized` instead of `device`, check your phone for the USB debugging authorization prompt.

## Network Configuration for Development

### Understanding the Network Challenge

When running a local development server on your computer:
- **Emulators** use `10.0.2.2` to reach the host machine
- **Physical devices** need your computer's actual LAN IP address

### Step 1: Find Your Computer's IP Address

```bash
# macOS
ipconfig getifaddr en0    # Wi-Fi
# or
ipconfig getifaddr en1    # Ethernet

# Linux
hostname -I | awk '{print $1}'
# or
ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1
```

Example output: `192.168.1.100`

### Step 2: Ensure Same Network

Your Android device and computer **must be on the same Wi-Fi network** for the device to reach your local development servers.

### Step 3: Configure API Endpoints

Create or edit `.env.development` with your computer's IP:

```bash
# .env.development - for physical device testing
VITE_DEFAULT_ENDORSER_API_SERVER=http://192.168.1.100:3000
VITE_DEFAULT_PARTNER_API_SERVER=http://192.168.1.100:3000
VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app
VITE_APP_SERVER=http://192.168.1.100:8080
```

**Important**: Replace `192.168.1.100` with your actual IP address.

### Step 4: Start Your Local Server

If testing against local API servers, ensure they're accessible from the network:

```bash
# Start your API server bound to all interfaces (not just localhost)
# Example for Node.js:
node server.js --host 0.0.0.0

# Or configure your server to listen on 0.0.0.0 instead of 127.0.0.1
```

### Alternative: Use Test/Production Servers

For simpler testing without local servers, use the test environment:

```bash
# Build with test API servers (no local server needed)
npm run build:android:test
```

## Building and Deploying

### Quick Start (Recommended)

```bash
# 1. Verify device is connected
adb devices

# 2. Build and deploy in one command
npm run build:android:debug:run
```

### Step-by-Step Deployment

#### Step 1: Build the App

```bash
# Development build (uses .env.development)
npm run build:android:dev

# Test build (uses test API servers)
npm run build:android:test

# Production build
npm run build:android:prod
```

#### Step 2: Install the APK

```bash
# Install (replace existing if present)
adb install -r android/app/build/outputs/apk/debug/app-debug.apk
```

#### Step 3: Launch the App

```bash
# Start the app
adb shell am start -n app.timesafari.app/app.timesafari.MainActivity
```

### One-Line Deploy Commands

```bash
# Development build + install + launch
npm run build:android:debug:run

# Test build + install + launch
npm run build:android:test:run

# Deploy to connected device (build must exist)
npm run build:android:deploy
```

## Debugging

### View App Logs

```bash
# All logs from your app
adb logcat | grep -E "(TimeSafari|Capacitor)"

# With color highlighting
adb logcat | grep -E "(TimeSafari|Capacitor)" --color=always

# Save logs to file
adb logcat > device-logs.txt
```

### Chrome DevTools (Remote Debugging)

1. Open Chrome on your computer
2. Navigate to `chrome://inspect`
3. Your device should appear under "Remote Target"
4. Click **inspect** to open DevTools for your app

**Requirements**:
- USB debugging must be enabled
- Device must be connected via USB
- App must be a debug build

### Common Log Filters

```bash
# Network-related issues
adb logcat | grep -i "network\|http\|socket"

# JavaScript errors
adb logcat | grep -i "console\|error\|exception"

# Capacitor plugin issues
adb logcat | grep -i "capacitor"

# Detailed app logs
adb logcat -s "TimeSafari:V"
```

## Troubleshooting

### Device Not Detected

**Symptom**: `adb devices` shows nothing or shows `unauthorized`

**Solutions**:

1. **Check USB cable**: Some cables are charge-only. Use a data-capable USB cable.

2. **Revoke USB debugging authorizations** (on device):
   - Settings → Developer options → Revoke USB debugging authorizations
   - Reconnect and re-authorize

3. **Restart ADB server**:
   ```bash
   adb kill-server
   adb start-server
   adb devices
   ```

4. **Try different USB port**: Some USB hubs don't work well with ADB.

5. **Check device USB mode**: Pull down notification shade and ensure USB is set to "File Transfer" or "MTP" mode, not just charging.

### App Can't Connect to Local Server

**Symptom**: App loads but shows network errors or can't reach API

**Solutions**:

1. **Verify IP address**:
   ```bash
   # Make sure you have the right IP
   ipconfig getifaddr en0  # macOS
   ```

2. **Check firewall**: Temporarily disable firewall or add exception for port 3000

3. **Test connectivity from device**:
   - Open Chrome on your Android device
   - Navigate to `http://YOUR_IP:3000`
   - Should see your API response

4. **Verify server is listening on all interfaces**:
   ```bash
   # Should show 0.0.0.0:3000, not 127.0.0.1:3000
   lsof -i :3000
   ```

5. **Same network check**: Ensure phone Wi-Fi and computer are on the same network

### Installation Failed

**Symptom**: `adb install` fails with error

**Common errors and solutions**:

1. **INSTALL_FAILED_UPDATE_INCOMPATIBLE**:
   ```bash
   # Uninstall existing app first
   adb uninstall app.timesafari.app
   adb install android/app/build/outputs/apk/debug/app-debug.apk
   ```

2. **INSTALL_FAILED_INSUFFICIENT_STORAGE**:
   - Free up space on the device
   - Or install to SD card if available

3. **INSTALL_FAILED_USER_RESTRICTED**:
   - Enable "Install via USB" in Developer options
   - On some devices: Settings → Security → Unknown sources

4. **Signature mismatch**:
   ```bash
   # Full clean reinstall
   adb uninstall app.timesafari.app
   npm run clean:android
   npm run build:android:debug
   adb install android/app/build/outputs/apk/debug/app-debug.apk
   ```

### App Crashes on Launch

**Symptom**: App opens briefly then closes

**Debug steps**:

1. **Check crash logs**:
   ```bash
   adb logcat | grep -E "FATAL|AndroidRuntime|Exception"
   ```

2. **Clear app data**:
   ```bash
   adb shell pm clear app.timesafari.app
   ```

3. **Reinstall clean**:
   ```bash
   adb uninstall app.timesafari.app
   npm run clean:android
   npm run build:android:debug:run
   ```

### Build Failures

**Symptom**: Build fails before APK is created

**Solutions**:

1. **Asset validation**:
   ```bash
   npm run assets:validate:android
   ```

2. **Clean and rebuild**:
   ```bash
   npm run clean:android
   npm run build:android:debug
   ```

3. **Check Gradle**:
   ```bash
   cd android
   ./gradlew clean --stacktrace
   ./gradlew assembleDebug --stacktrace
   ```

## Wireless Debugging (Optional)

Once initial USB connection is established, you can switch to wireless:

### Enable Wireless Debugging

```bash
# 1. Connect via USB first
adb devices

# 2. Enable TCP/IP mode on port 5555
adb tcpip 5555

# 3. Find device IP (on device: Settings → About → IP address)
# Or:
adb shell ip addr show wlan0

# 4. Connect wirelessly (disconnect USB cable)
adb connect 192.168.1.XXX:5555

# 5. Verify
adb devices
```

### Reconnect After Reboot

```bash
# Device IP may have changed - check it first
adb connect 192.168.1.XXX:5555
```

### Return to USB Mode

```bash
adb usb
```

## Best Practices

### Development Workflow

1. **Keep device connected during development** for quick iteration

2. **Use test builds for most testing**:
   ```bash
   npm run build:android:test:run
   ```
   This avoids local server configuration hassles.

3. **Use Chrome DevTools** for JavaScript debugging - much easier than logcat

4. **Test on multiple devices** if possible - different Android versions behave differently

### Performance Testing

Physical devices give you real-world performance insights that emulators can't:

- **Battery consumption**: Monitor with Settings → Battery
- **Network conditions**: Test on slow/unstable Wi-Fi
- **Memory pressure**: Test with many apps open
- **Touch responsiveness**: Actual finger input vs mouse clicks

### Before Release Testing

Always test on physical devices before any release:

1. Fresh install (not upgrade)
2. Upgrade from previous version
3. Test on lowest supported Android version
4. Test on both phone and tablet if applicable

## Quick Reference

### Essential Commands

```bash
# Check connected devices
adb devices

# Build and run (debug)
npm run build:android:debug:run

# Build and run (test environment)
npm run build:android:test:run

# Install existing APK
adb install -r android/app/build/outputs/apk/debug/app-debug.apk

# Uninstall app
adb uninstall app.timesafari.app

# Launch app
adb shell am start -n app.timesafari.app/app.timesafari.MainActivity

# View logs
adb logcat | grep TimeSafari

# Take screenshot
adb exec-out screencap -p > screenshot.png

# Record screen
adb shell screenrecord /sdcard/demo.mp4
# (Ctrl+C to stop, then pull file)
adb pull /sdcard/demo.mp4
```

### Build Modes Quick Reference

| Command | Environment | API Servers |
|---------|-------------|-------------|
| `npm run build:android:dev` | Development | Local (your IP:3000) |
| `npm run build:android:test` | Test | test-api.endorser.ch |
| `npm run build:android:prod` | Production | api.endorser.ch |

## Conclusion

Physical device testing is essential for:
- ✅ Real-world performance validation
- ✅ Touch and gesture testing
- ✅ Camera and hardware feature testing
- ✅ Network condition testing
- ✅ Battery and resource usage analysis

For emulator-based testing (useful for quick iteration), see [Android Emulator Deployment Guide](android-emulator-deployment-guide.md).

For questions or additional troubleshooting, refer to the main [BUILDING.md](../BUILDING.md) documentation.
