Skip to content

buxkaizhe/ota_prototype

Repository files navigation

OTA WebView Hybrid App Prototype

A complete prototype system demonstrating Over-The-Air (OTA) updates for a Flutter app using a WebView to render a VueJS-based UI with bi-directional JavaScript-to-Flutter native bridge communication.

🏗️ Architecture

┌─────────────────────────────────────────────────────────┐
│                    Flutter App                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │              WebView Container                    │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │         VueJS Web Application              │  │  │
│  │  │  • TypeScript                              │  │  │
│  │  │  • Scanner UI Button                       │  │  │
│  │  │  • Native Bridge (JS → Flutter)            │  │  │
│  │  └────────────────────────────────────────────┘  │  │
│  │                      ↕                            │  │
│  │         JavascriptChannel Bridge                  │  │
│  │                      ↕                            │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │       Flutter Native Layer                 │  │  │
│  │  │  • Native Bridge Handler                   │  │  │
│  │  │  • Mobile Scanner (Camera)                 │  │  │
│  │  │  • OTA Update Service                      │  │  │
│  │  └────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                          ↕
                   Network (HTTP)
                          ↕
┌─────────────────────────────────────────────────────────┐
│              Backend OTA Server                         │
│  • Express.js + TypeScript                              │
│  • Serves version.json                                  │
│  • Serves web assets                                    │
└─────────────────────────────────────────────────────────┘

📁 Project Structure

ota_prototype/
├── webui/                      # VueJS Web App
│   ├── src/
│   │   ├── App.vue            # Main Vue component with scanner UI
│   │   ├── main.ts            # Entry point with bridge setup
│   │   ├── types/
│   │   │   └── native-bridge.d.ts  # TypeScript definitions
│   │   └── style.css
│   ├── index.html
│   ├── package.json
│   ├── vite.config.ts
│   └── tsconfig.json
│
├── flutter_app/               # Flutter Native App
│   ├── lib/
│   │   ├── main.dart          # App entry with OTA check
│   │   ├── screens/
│   │   │   └── webview_screen.dart   # WebView container
│   │   ├── services/
│   │   │   ├── native_bridge.dart    # Bridge handler
│   │   │   └── ota_service.dart      # OTA update logic
│   │   └── widgets/
│   │       └── scanner_overlay.dart   # Scanner UI
│   ├── android/
│   │   └── app/src/main/AndroidManifest.xml  # Permissions
│   ├── ios/
│   │   └── Runner/Info.plist         # iOS permissions
│   ├── pubspec.yaml           # Dependencies
│   └── assets/webui/          # Bundled web assets
│
├── backend/                   # OTA Update Server
│   ├── src/
│   │   └── server.ts          # Express server
│   ├── assets/                # Served web assets
│   │   └── version.json       # Version manifest
│   ├── package.json
│   └── tsconfig.json
│
├── build.sh                   # Build automation script
├── task.md                    # Original specification
└── README.md                  # This file

🚀 Getting Started

Prerequisites

  • Node.js (v18+)
  • Flutter SDK (3.0+)
  • Android Studio / Xcode (for mobile development)

1. Build the VueJS Web App

cd webui
npm install
npm run build

2. Set Up Flutter App

cd flutter_app
flutter pub get

# Copy web assets to Flutter assets folder
mkdir -p assets/webui
cp -r ../webui/dist/* assets/webui/

3. Start the Backend OTA Server

cd backend
npm install

# Copy web assets to backend
mkdir -p assets
cp -r ../webui/dist/* assets/

# Start server
npm run dev

The server will run on http://localhost:3000

4. Run the Flutter App

cd flutter_app
flutter run

Important: Update the OTA server URL in lib/services/ota_service.dart based on your platform:

  • Android Emulator: http://10.0.2.2:3000
  • iOS Simulator: http://localhost:3000
  • Physical Device: http://<YOUR_COMPUTER_IP>:3000

5. Quick Build (All at Once)

chmod +x build.sh
./build.sh

🔄 How It Works

OTA Update Flow

  1. App Launch: Flutter app checks backend for new version
  2. Version Check: Compares local version with version.json from server
  3. Download: If newer version available, downloads all files
  4. Atomic Replace: Downloads to temp folder, then swaps atomically
  5. Reload: WebView loads updated assets

Native Bridge Communication

JavaScript → Flutter

// In VueJS
window.NativeBridgeChannel.postMessage(
  JSON.stringify({ type: "scanner", action: "open" })
);

Flutter → JavaScript

// In Flutter
controller.runJavaScript(
  "window.onFlutterScanResult('scanned_code_here');"
);

Scanner Feature

  1. User clicks "Scan QR/Barcode" button in VueJS UI
  2. VueJS sends message via NativeBridgeChannel
  3. Flutter receives message and shows camera scanner overlay
  4. User scans code
  5. Flutter sends result back to JavaScript
  6. VueJS displays the scanned code

🔑 Key Features

✅ Implemented

  • VueJS 3 + TypeScript web app
  • Vite build system for optimized assets
  • Flutter WebView integration
  • Bi-directional native bridge
  • Mobile camera scanner (QR/Barcode)
  • OTA update mechanism with version checking
  • Atomic asset replacement
  • Express.js backend server
  • TypeScript throughout
  • Android & iOS support
  • Camera permissions handling
  • Network connectivity for OTA

🎯 Bridge Methods

Type Direction Description
scanner JS → Flutter Opens camera scanner
showDialog JS → Flutter Shows native alert dialog
getDeviceInfo JS → Flutter Requests device information
onFlutterScanResult Flutter → JS Returns scanned code
onFlutterMessage Flutter → JS Generic Flutter response

📱 Permissions

Android (AndroidManifest.xml)

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />

iOS (Info.plist)

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>

🔧 Configuration

Backend Server Ports

Default: 3000

Change in backend/src/server.ts:

const PORT = 3000;

OTA Server URL

Configure in flutter_app/lib/services/ota_service.dart:

static const String _updateUrlBase = 'http://10.0.2.2:3000';

Version Management

Version is stored in version.json:

{
  "version": "1.0.0",
  "timestamp": "2025-11-10T00:00:00.000Z",
  "files": ["index.html", "assets/index.css", "assets/index.js"]
}

🧪 Testing the OTA Flow

  1. Build and run the app with initial assets
  2. Modify the VueJS app (e.g., change button text)
  3. Rebuild: cd webui && npm run build
  4. Update backend assets: cp -r dist/* ../backend/assets/
  5. Update version in backend/assets/version.json
  6. Restart the Flutter app
  7. App should detect and download the update

📦 Dependencies

VueJS App

  • vue ^3.4.0
  • vite ^5.0.0
  • typescript ^5.3.0

Flutter App

  • webview_flutter ^4.4.0
  • mobile_scanner ^3.5.0
  • http ^1.1.0
  • path_provider ^2.1.0
  • shared_preferences ^2.2.0

Backend

  • express ^4.18.0
  • cors ^2.8.5
  • typescript ^5.3.0

🐛 Troubleshooting

WebView Not Loading

  • Check file paths in webview_screen.dart
  • Verify assets are in flutter_app/assets/webui/
  • Check pubspec.yaml includes assets folder

OTA Updates Not Working

  • Verify backend server is running
  • Check network connectivity
  • Verify correct IP/URL for your platform
  • Check version.json is properly formatted

Scanner Not Opening

  • Verify camera permissions are granted
  • Check AndroidManifest.xml and Info.plist
  • Test on physical device (camera not available on emulators)

Bridge Communication Failing

  • Check JavaScript console in WebView
  • Verify JavascriptChannel is registered
  • Ensure JSON.stringify is used for messages

🎓 Learning Resources

📄 License

This is a prototype for educational purposes.

🙏 Acknowledgments

Built following the specification in task.md with complete TypeScript integration and modern best practices.


Ready to test! Follow the Getting Started guide above to build and run the complete system.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors