Developing a Mobile App for Selling Online Courses
Course app—not just a video player with purchase. Key platform metric—completion rate. User buys course, watches 2 lectures, doesn't return—bad signal for platform, wasted money for user. Technical task: UI that reduces friction on return and prevents progress loss.
Progress, Offline, and Video Player
Progress synchronization. User watches lesson on phone, continues on tablet. progress_position (timestamp in seconds) must sync. Scheme: every 10–15 seconds—background PATCH /progress/{lesson_id} with current position. On lesson open—AVPlayer.seek(to: savedPosition). Optimistic update locally, sync in background via URLSession background task. Conflict (two devices parallel)—take max position.
Offline viewing. Download course for offline viewing—key mobile feature. iOS: AVAssetDownloadTask + AVAssetDownloadURLSession—HLS downloads as offline asset in AVOfflineAssetManager. Android: ExoPlayer DownloadManager with file system caching via SimpleCache. Download progress—URLSessionDownloadDelegate / DownloadManager listener updating UI via Progress / StateFlow.
Storage management: show how much space courses occupy, allow deletion. URLSession.shared.configuration.urlCache unsuitable—need explicit management via URLSessionDownloadTask saving to Documents directory.
Video player. AVPlayerViewController on iOS—standard container, limited customization. Full control—custom overlay over AVPlayerLayer: ±10s rewind buttons, playback speed (0.75x / 1.25x / 1.5x / 2x via player.rate), subtitles via AVMediaCharacteristic.legible. On Android—ExoPlayer with custom PlayerView and DefaultTrackSelector for quality management (360p / 720p / 1080p by network via AdaptiveTrackSelection).
Course Structure and Navigation
Course → Sections → Lessons (video, text, quiz). Local database: Core Data / Room. On app open—quick load structure from cache, background API update. No pagination needed for course structure—it's small.
Quizzes: QuizRepository with questions, answer options, correct answer (only after attempt). Attempts stored locally + synced with server. Retake with cooldown—server decides, client displays remaining time.
Completion certificate—PDF generation on server, download via app, share via UIActivityViewController / Android ShareCompat.IntentBuilder. Add to Apple Wallet as Pass—non-standard but technically doable for "elite" platforms.
IAP and Course Purchase
Course as non-consumable IAP (StoreKit 2 / Play Billing) or subscription for all (auto-renewable). Non-consumable: Product.purchase() → Transaction.currentEntitlements → unlock specific course on server by validated receipt. Restore purchases—mandatory button by App Store Guidelines.
Alternative: web-billing (purchase via site), app only opens bought content. Relevant for platforms with own website—save App Store commission.
Promo codes: SKPaymentQueue.presentCodeRedemptionSheet() on iOS 14+ for App Store offer codes. Android—launchBillingFlow with PromoCode.
Gamification and Retention
Streak—daily visits. Counter stored on server (not client—easy to cheat), shown on home screen. At milestone (7, 30 days)—push notification + in-app celebration (Lottie animation). Streak loss—recovery push "Don't lose progress".
Achievements (badges) for completing X lessons / courses. Profile screen with progress across all courses and badges. Small social proof: "32,000 students completed this course"—fetched from API, not hardcoded.
Stack
Flutter—justified for ed-tech: single codebase, acceptable video player performance via video_player package (native AVPlayer/ExoPlayer under hood), rich ecosystem. React Native—if team already on RN. Native—if AVOfflineAsset integration (iOS) or complex download scenarios critical.
Process
Course structure and progress design → video player + offline loading → IAP / billing integration → quizzes + certificates → gamification → QA (download + offline playback on real devices) → publication.
Timeline Estimates
MVP (video lessons, progress, IAP course purchase): 4–7 weeks. Full platform with offline, quizzes, certificates, streak system, search, iOS + Android: 2–3 months.







