PLEASE REPORT ANY ISSUES TO mycap@vumc.org
This project enables seamless integration of custom web‑based Active Tasks into the MyCap app using a ZIP‑packed website and an embedded WebView. It provides:
- StartScreen: Pick or download a ZIP archive containing your task’s static website.
- WebViewScreen: Extracts and displays the
index.htmlfrom the ZIP, sets up a JavaScript bridge to receive JSON data viawindow.flutter_inappwebview.callHandler('returnData', ...). - ResultsScreen: Presents received data—rendering images, flagging large text, and expanding nested structures.
This repository is framework‑agnostic: you do not need Flutter installed to understand how your web task should be built and packaged.
MyCap allows researchers to embed custom Active Tasks—interactive, offline‑capable web apps—into their study apps. When the user completes an activity on the webpage, your code calls:
window.flutter_inappwebview.callHandler('returnData', JSON.stringify({ /* structured payload */ }));The host app intercepts this handler, parses the JSON, and navigates to a native results display.
Your Flutter host injects two objects into the page after load:
-
URL Parameters via
window.searchParams:// Already injected by host const urlParams = window.searchParams || new URLSearchParams(window.location.search); console.log(Object.fromEntries(urlParams.entries()));
-
Flutter Map via
window.flutterQueryParams:// Injected JSON from Dart side const injected = window.flutterQueryParams || {}; console.log(injected);
Merge them into your config:
const config = {
identifier: injected.identifier || urlParams.get('identifier') || 'defaultIdentifier',
lengthOfTest: parseInt(injected.length_of_test)
|| parseInt(urlParams.get('length_of_test'))
|| 3,
intendedUseDescription: injected.intendedUseDescription
|| urlParams.get('intendedUseDescription')
|| 'Welcome to the Custom Active Task Demo.'
};-
No External Network Calls
- Bundle all scripts, styles, fonts, and media. No CDNs.
-
Entry Point
- Include an
index.html(root or subfolder). The app finds the first one (ignoring__MACOSX).
- Include an
-
JavaScript Data Return
function submitText(text) { const payload = JSON.stringify({ text }); window.flutter_inappwebview.callHandler('returnData', payload); }
-
File Uploads & Media
canvas.toBlob(blob => { const reader = new FileReader(); reader.onloadend = () => { const payload = JSON.stringify({ image: reader.result }); window.flutter_inappwebview.callHandler('returnData', payload); }; reader.readAsDataURL(blob); }, 'image/png');
-
Offline Capability
- All assets load from relative paths inside the ZIP.
-
Error Handling
const payload = JSON.stringify({ error: true, message: '...'}); window.flutter_inappwebview.callHandler('returnData', payload);
- Select or Download ZIP → copy into app docs.
- Extract & Locate → unzip and find
index.html. - WebView Load with file:// URL and file-access permissions.
- Inject Parameters via
evaluateJavascript(handled in host). - Receive Data in your Dart
addJavaScriptHandler('returnData', ...). - Display Results natively.
lib/
├─ StartScreen # ZIP selection or download
├─ WebViewScreen # Extraction, WebView load, JS↔native bridge
└─ ResultsScreen # Native rendering of returned JSON data
__MACOSX— ignore.index.html— entry point.returnData— JS channel name.file://— protocol for local assets.data:— Base64 data URIs.logs— captured console messages.error— boolean flag in payload.
How is my task installed? Host unzips and loads offline.
Why local? Offline support and performance.
What can I send back? Any JSON‑serializable structure; Base64 for binaries.
Languages Supported
| Code | Native Name | English Name |
|---|---|---|
| en | English | English |
| bn | বাংলা | Bengali |
| pt | Português | Portuguese |
| fr | Français | French |
| de | Deutsch | German |
| ht | Kreyòl Ayisyen | Haitian Creole |
| hi | हिन्दी | Hindi |
| it | Italiano | Italian |
| ja | 日本語 | Japanese |
| ko | 한국어 | Korean |
| pa | ਪੰਜਾਬੀ | Punjabi |
| zh | 中文 | Chinese |
| es | Español | Spanish |
| ar | العربية | Arabic |
| fil | Tagalog | Filipino |
| uk | Українська | Ukrainian |
| ur | اردو | Urdu |
| vi | Tiếng Việt | Vietnamese |
| default | English | English |
-
Install Flutter SDK (Windows/macOS).
-
Configure Android (SDK, licenses) or iOS (Xcode, CocoaPods).
-
Clone repo and run:
flutter pub get cd ios && pod install && cd .. flutter run
If you want to build and test the host integration using Flutter, follow these steps for Windows and macOS. This assumes you have administrator or sudo privileges.
- Git installed on your machine.
- An IDE such as VS Code, Android Studio, or IntelliJ with Flutter plugins.
- For Android: Android SDK, Android Studio, and an Android device/emulator.
- For iOS (macOS only): Xcode and an iOS device/simulator.
-
Download the Flutter SDK ZIP from https://docs.flutter.dev/get-started/install/windows.
-
Extract the ZIP to
C:\src\flutter(avoid paths with spaces). -
Add
C:\src\flutter\binto your PATH environment variable. -
Run in PowerShell:
flutter doctor
-
Download the Flutter SDK ZIP from https://docs.flutter.dev/get-started/install/macos.
-
Extract the ZIP:
cd ~/Downloads unzip flutter_macos_*.zip mv flutter ~/flutter
-
Add to your PATH in
~/.zshrcor~/.bash_profile:export PATH="$PATH:$HOME/flutter/bin"
-
Run:
flutter doctor
Resolve any issues reported by flutter doctor (missing dependencies, license agreements, etc.).
-
In Android Studio, open SDK Manager: install SDK Platform (latest stable), Android SDK Tools, and Android Emulator.
-
Accept all licenses:
flutter doctor --android-licenses
-
Start an emulator or connect a physical device.
-
Open Xcode and install any additional components if prompted.
-
In a terminal, run:
sudo gem install cocoapods flutter doctor
-
If using a simulator, start it from Xcode → Devices & Simulators.
# Clone the repo
git clone git@github.com:vanderbilt-redcap/mycap-at-test.git
cd mycap-at-test
# Get dependencies
flutter pub get
# For iOS (macOS only)
cd ios
pod install
cd ..
# Run on Android emulator or device\ flutter run -d chrome # for webview testing in browser
flutter run # default device
# Or run on iOS simulator (macOS only)
flutter run -d iosYour Flutter app will launch, showing the StartScreen. From there, you can select or download a ZIP and test your Active Task integration end‑to‑end.
This app was last tested successfully on:
- Flutter 3.41.2
- Xcode 26.3
- Android Studio Panda 1 | 2025.3.1 Patch 1
- iPhone 15 Pro Max with iOS 26.3
With this setup, you can craft rich, interactive tasks in any web framework and integrate them seamlessly into MyCap. We have included a sample ZIP file in the assets directory to demonstrate the expected structure and functionality, feel free to study this working example in order to build your own custom Active Tasks.