Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions ushadow/frontend/src/wizards/MobileAppWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,16 +216,19 @@ export default function MobileAppWizard() {
</h3>
</div>
<p className="text-gray-400 text-sm mb-3">
Full features including Bluetooth OMI device support. Requires a Mac for iOS or Android Studio for Android.
Full features including Bluetooth OMI device support. The build scripts automatically check prerequisites and provide helpful error messages.
</p>
<div className="bg-black/30 rounded-lg p-3 font-mono text-sm">
<div className="text-gray-500"># Install dependencies</div>
<div className="text-indigo-300">cd ushadow/mobile && npm install</div>
<div className="text-gray-500 mt-2"># Build and run on device</div>
<div className="text-indigo-300">npx expo run:ios</div>
<div className="text-gray-500"># or</div>
<div className="text-indigo-300">npx expo run:android</div>
<div className="text-gray-500 mt-2"># iOS (Mac only - auto-boots simulator)</div>
<div className="text-indigo-300">npm run ios</div>
<div className="text-gray-500 mt-2"># Android (any platform)</div>
<div className="text-indigo-300">npm run android</div>
</div>
<p className="text-xs text-gray-500 mt-2">
Scripts auto-check for required tools and will guide you if anything is missing.
</p>
</div>

{/* Option 2: Android APK */}
Expand Down Expand Up @@ -291,10 +294,28 @@ export default function MobileAppWizard() {
</div>

{/* Prerequisites Note */}
<div className="p-3 bg-blue-500/10 rounded-lg border border-blue-500/30">
<p className="text-sm text-blue-300">
<strong>Prerequisites:</strong> Node.js 18+, and for development builds: Xcode (iOS) or Android Studio (Android).
See <code className="bg-black/30 px-1 rounded">ushadow/mobile/README.md</code> for detailed setup.
<div className="p-4 bg-blue-500/10 rounded-lg border border-blue-500/30">
<h3 className="text-sm font-medium text-blue-300 mb-2">Prerequisites for Development Builds:</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-3 text-xs">
<div className="space-y-1">
<div className="text-blue-200 font-medium">iOS (Mac only)</div>
<ul className="text-blue-300/80 space-y-0.5 list-disc list-inside">
<li>Xcode (from App Store)</li>
<li>iOS Simulator runtime</li>
<li>Xcode Command Line Tools</li>
</ul>
</div>
<div className="space-y-1">
<div className="text-blue-200 font-medium">Android (any platform)</div>
<ul className="text-blue-300/80 space-y-0.5 list-disc list-inside">
<li>Java JDK 17 (<code className="bg-black/30 px-1 rounded">brew install openjdk@17</code>)</li>
<li>Android Studio + SDK</li>
<li>Emulator or USB device</li>
</ul>
</div>
</div>
<p className="text-xs text-blue-300/60 mt-2">
Run <code className="bg-black/30 px-1 rounded">npm run ios</code> or <code className="bg-black/30 px-1 rounded">npm run android</code> to see exactly what's missing.
</p>
</div>
</div>
Expand Down
66 changes: 63 additions & 3 deletions ushadow/mobile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,45 @@ eas build --profile preview --platform android

#### Development (Recommended)
```bash
# Connect your iOS device via USB
# Trust your computer on the device

npm install
npx expo prebuild --platform ios
cd ios && pod install && cd ..
npx expo run:ios --device
```

#### Running on Physical iPhone

To run on a physical iPhone instead of the simulator, use the `--device` flag:

```bash
npx expo run:ios --device
```

This will show a list of connected devices. You can also specify the device name directly:

```bash
npx expo run:ios --device "iPhone Air"
```

**Prerequisites for physical device:**

1. **Connect via USB** - Connect your iPhone to your Mac with a cable

2. **Trust the computer** - On your iPhone, tap "Trust" when prompted with "Trust This Computer?"

3. **Enable Developer Mode** (iOS 16+) - Go to **Settings → Privacy & Security → Developer Mode** and enable it. Your device will restart.

4. **Apple Developer account** - Sign into Xcode with your Apple ID:
- Open Xcode → Settings → Accounts → Add your Apple ID

5. **Code signing** - First build requires signing setup:
```bash
open ios/*.xcworkspace
```
In Xcode: Select your project → Signing & Capabilities → Select your Team

After initial setup, subsequent builds with `npx expo run:ios --device` will work automatically.

#### Distribution via TestFlight (Easiest for iOS)
1. Apple Developer account ($99/year required)
2. Build with EAS:
Expand Down Expand Up @@ -163,6 +193,36 @@ eas device:create
- Verify URLs don't have trailing slashes
- Try both `ws://` and `wss://` for stream URL

### Android: "SDK location not found"
When running `npx expo run:android`, you may see:
```
SDK location not found. Define a valid SDK location with an ANDROID_HOME
environment variable or by setting the sdk.dir path in your project's
local.properties file
```

**Cause:** The Android build system (Gradle) can't find your Android SDK installation.

**Fix:** Create `android/local.properties` with your SDK path:
```bash
# On macOS (typical Android Studio installation):
echo "sdk.dir=$HOME/Library/Android/sdk" > android/local.properties

# On Linux:
echo "sdk.dir=$HOME/Android/Sdk" > android/local.properties

# On Windows (Git Bash):
echo "sdk.dir=C:\\Users\\YourUsername\\AppData\\Local\\Android\\Sdk" > android/local.properties
```

**Permanent fix:** Add to your shell profile (`~/.zshrc` or `~/.bashrc`):
```bash
export ANDROID_HOME=$HOME/Library/Android/sdk # macOS
export PATH=$PATH:$ANDROID_HOME/platform-tools
```

**Note:** `local.properties` is gitignored because it contains machine-specific paths.

### Build fails
```bash
# Clean and rebuild
Expand Down
1 change: 1 addition & 0 deletions ushadow/mobile/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions ushadow/mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
"scripts": {
"start": "expo start",
"reset-project": "node ./scripts/reset-project.js",
"android": "expo run:android",
"ios": "expo run:ios",
"android": "./scripts/preflight-android.sh && expo run:android",
"android:skip-preflight": "expo run:android",
"ios": "./scripts/preflight-ios.sh && expo run:ios",
"ios:skip-preflight": "expo run:ios",
"web": "expo start --web",
"lint": "expo lint",
"postinstall": "patch-package"
Expand Down
220 changes: 220 additions & 0 deletions ushadow/mobile/scripts/preflight-android.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#!/bin/bash
# Android Preflight Check Script
# Ensures Android development environment is ready before running expo run:android
# Note: We don't use 'set -e' here to ensure error messages are displayed properly

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Android Development Environment Check ║${NC}"
echo -e "${BLUE}║ Tip: Always use 'npm run android' to get these checks ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""

# Check for Java - need to verify it actually works, not just that the command exists
# Android builds require Java because the Android build system (Gradle) runs on the JVM
JAVA_CHECK=$(java -version 2>&1)
if echo "$JAVA_CHECK" | grep -qi "Unable to locate\|not found\|No Java\|error"; then
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ERROR: Java JDK is not installed ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}Why is Java needed?${NC}"
echo " Android apps are built using Gradle, which requires Java to run."
echo " React Native/Expo uses Gradle under the hood to compile your app."
echo ""
echo -e "${YELLOW}How to fix:${NC}"
echo ""
if [[ "$OSTYPE" == "darwin"* ]]; then
echo -e "${GREEN}Option 1 - Homebrew (recommended):${NC}"
echo ""
echo " Step 1: Install OpenJDK 17"
echo -e " ${BLUE}brew install openjdk@17${NC}"
echo ""
echo " Step 2: Link it so the system can find it"
echo -e " ${BLUE}sudo ln -sfn \$(brew --prefix)/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-17.jdk${NC}"
echo ""
echo " Step 3: Restart your terminal, then run:"
echo -e " ${BLUE}npm run android${NC}"
echo ""
echo -e "${GREEN}Option 2 - Download installer:${NC}"
echo " https://adoptium.net/temurin/releases/?version=17"
echo " Download the .pkg file for macOS and run the installer."
else
echo -e "${GREEN}Ubuntu/Debian:${NC}"
echo -e " ${BLUE}sudo apt install openjdk-17-jdk${NC}"
echo ""
echo -e "${GREEN}Or download from:${NC}"
echo " https://adoptium.net/temurin/releases/?version=17"
fi
echo ""
echo -e "${YELLOW}After installing Java, restart your terminal and run: npm run android${NC}"
echo ""
exit 1
fi

# Check Java version
JAVA_VERSION=$(echo "$JAVA_CHECK" | head -1 | cut -d'"' -f2 | cut -d'.' -f1 2>/dev/null || echo "0")
echo -e "${GREEN}Java found: $(echo "$JAVA_CHECK" | head -1)${NC}"

if [ "$JAVA_VERSION" -lt 11 ] 2>/dev/null; then
echo -e "${YELLOW}Warning: Java version $JAVA_VERSION detected. Java 17 is recommended for React Native.${NC}"
fi

# Check for ANDROID_HOME or ANDROID_SDK_ROOT
if [ -z "$ANDROID_HOME" ] && [ -z "$ANDROID_SDK_ROOT" ]; then
# Try common locations
if [ -d "$HOME/Library/Android/sdk" ]; then
export ANDROID_HOME="$HOME/Library/Android/sdk"
echo -e "${YELLOW}ANDROID_HOME not set, using: $ANDROID_HOME${NC}"
elif [ -d "$HOME/Android/Sdk" ]; then
export ANDROID_HOME="$HOME/Android/Sdk"
echo -e "${YELLOW}ANDROID_HOME not set, using: $ANDROID_HOME${NC}"
else
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ERROR: Android SDK not found ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}Why is the Android SDK needed?${NC}"
echo " The Android SDK contains tools to compile and package your app"
echo " for Android devices. It's installed alongside Android Studio."
echo ""
echo -e "${YELLOW}How to fix:${NC}"
echo ""
echo -e "${GREEN}Step 1: Install Android Studio${NC}"
echo " Download from: https://developer.android.com/studio"
echo " Run the installer and complete the setup wizard."
echo ""
echo -e "${GREEN}Step 2: Add environment variables${NC}"
echo " Add these lines to your shell profile (~/.zshrc or ~/.bashrc):"
echo ""
if [[ "$OSTYPE" == "darwin"* ]]; then
echo -e " ${BLUE}export ANDROID_HOME=\$HOME/Library/Android/sdk${NC}"
else
echo -e " ${BLUE}export ANDROID_HOME=\$HOME/Android/Sdk${NC}"
fi
echo -e " ${BLUE}export PATH=\$PATH:\$ANDROID_HOME/emulator${NC}"
echo -e " ${BLUE}export PATH=\$PATH:\$ANDROID_HOME/platform-tools${NC}"
echo ""
echo -e "${GREEN}Step 3: Reload your shell${NC}"
echo -e " ${BLUE}source ~/.zshrc${NC} (or restart your terminal)"
echo ""
echo -e "${YELLOW}Then run: npm run android${NC}"
echo ""
exit 1
fi
else
ANDROID_HOME="${ANDROID_HOME:-$ANDROID_SDK_ROOT}"
fi

echo -e "${GREEN}Android SDK: $ANDROID_HOME${NC}"

# Check for platform-tools (adb)
if [ ! -f "$ANDROID_HOME/platform-tools/adb" ]; then
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ERROR: Android platform-tools (adb) not found ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}Why are platform-tools needed?${NC}"
echo " Platform-tools include 'adb' (Android Debug Bridge), which is used"
echo " to communicate with your Android device or emulator."
echo ""
echo -e "${YELLOW}How to fix:${NC}"
echo " 1. Open Android Studio"
echo " 2. Go to Tools > SDK Manager > SDK Tools tab"
echo " 3. Check 'Android SDK Platform-Tools' and click Apply"
echo ""
exit 1
fi

# Add platform-tools to PATH if not already there
export PATH="$PATH:$ANDROID_HOME/platform-tools"

# Check for connected devices or running emulators
echo ""
echo "Checking for Android devices..."

DEVICES=$("$ANDROID_HOME/platform-tools/adb" devices 2>/dev/null | grep -v "List" | grep -v "^$" || echo "")

if [ -z "$DEVICES" ]; then
echo -e "${YELLOW}No Android devices connected${NC}"
echo ""

# Check if any emulator is available
if [ -d "$ANDROID_HOME/emulator" ] && [ -f "$ANDROID_HOME/emulator/emulator" ]; then
AVDS=$("$ANDROID_HOME/emulator/emulator" -list-avds 2>/dev/null || echo "")

if [ -n "$AVDS" ]; then
echo "Available emulators:"
echo "$AVDS" | while read avd; do echo " - $avd"; done
echo ""

# Try to start the first available emulator
FIRST_AVD=$(echo "$AVDS" | head -1)
echo -e "${BLUE}Starting emulator: $FIRST_AVD${NC}"
"$ANDROID_HOME/emulator/emulator" -avd "$FIRST_AVD" -no-snapshot-load &

echo "Waiting for emulator to boot..."
# Wait for device to be ready (max 60 seconds)
for i in {1..30}; do
sleep 2
BOOT_STATUS=$("$ANDROID_HOME/platform-tools/adb" shell getprop sys.boot_completed 2>/dev/null || echo "")
if [ "$BOOT_STATUS" = "1" ]; then
echo -e "${GREEN}Emulator is ready!${NC}"
break
fi
echo " Still booting... ($i/30)"
done
else
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ERROR: No Android emulators configured ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}You need either an emulator or a physical device to run the app.${NC}"
echo ""
echo -e "${GREEN}Option 1 - Create an emulator:${NC}"
echo " 1. Open Android Studio"
echo " 2. Go to Tools > Device Manager"
echo " 3. Click 'Create Device' and follow the wizard"
echo " 4. Download a system image when prompted (e.g., API 34)"
echo ""
echo -e "${GREEN}Option 2 - Connect a physical device via USB:${NC}"
echo " 1. On your phone: Settings > About Phone"
echo " Tap 'Build Number' 7 times to enable Developer Options"
echo " 2. Go to Settings > Developer Options"
echo " Enable 'USB Debugging'"
echo " 3. Connect your phone via USB cable"
echo " 4. Accept the debugging prompt on your phone"
echo ""
exit 1
fi
else
echo -e "${RED}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${RED}║ ERROR: Android Emulator not installed ║${NC}"
echo -e "${RED}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${YELLOW}How to fix:${NC}"
echo " 1. Open Android Studio"
echo " 2. Go to Tools > SDK Manager > SDK Tools tab"
echo " 3. Check 'Android Emulator' and click Apply"
echo " 4. Then go to Tools > Device Manager to create a virtual device"
echo ""
echo "Or connect a physical Android device via USB (see above)"
exit 1
fi
else
echo -e "${GREEN}Connected devices:${NC}"
echo "$DEVICES" | while read device; do
if [ -n "$device" ]; then
echo " - $device"
fi
done
fi

echo ""
echo -e "${GREEN}=== Android environment ready! ===${NC}"
echo ""