Chapter 4: Mobile & Real-Time Communication

弘益人間 (Hongik Ingan) - "Benefit All Humanity"
Mobile-first design ensures mental healthcare reaches people where they are - in their daily lives, during moments of need, across all socioeconomic strata. Smartphones have become the great equalizer in healthcare access.

4.1 Mobile-First Architecture

Mobile devices have become the primary computing platform for billions of people worldwide. For many, particularly in developing nations and underserved communities, smartphones are the only internet-connected device they own. A mobile-first approach to digital therapeutics is not just convenient - it's essential for equitable access.

Mobile Platform Statistics

Metric Global Data Implication Design Response
Mobile-Only Internet Users 2.5 billion (31% of global population) No desktop/laptop access Full feature parity on mobile
Avg Daily Phone Usage 3-4 hours High engagement opportunity Microlearning, brief interventions
Push Notification Open Rate 7-10% (mental health apps: 15-20%) Effective for reminders Thoughtful notification strategy
Mobile App Retention (Day 30) 5-10% average, 25-35% for health apps Engagement critical Gamification, progress visualization
Offline Usage Scenarios 40% of time in areas with poor connectivity Offline capability essential Local storage, background sync

React Native Technical Stack

The WIA-MENTAL-001 standard recommends React Native for cross-platform mobile development, enabling a single codebase to serve both iOS and Android while maintaining native performance and UX quality.

// Mobile App Architecture

// Core Dependencies
{
  "dependencies": {
    "react": "18.2.0",
    "react-native": "0.72.0",
    "@react-navigation/native": "^6.1.0",
    "@react-navigation/stack": "^6.3.0",
    
    // State Management
    "@reduxjs/toolkit": "^1.9.5",
    "react-redux": "^8.1.0",
    "redux-persist": "^6.0.0",
    
    // Offline & Sync
    "@react-native-async-storage/async-storage": "^1.19.0",
    "@react-native-community/netinfo": "^9.4.0",
    
    // Security
    "react-native-keychain": "^8.1.0",
    "react-native-encrypted-storage": "^4.0.3",
    
    // Health Integration
    "react-native-health": "^1.19.0",
    "@react-native-community/google-fit": "^0.2.0",
    
    // Notifications
    "@react-native-firebase/messaging": "^18.0.0",
    "@react-native-firebase/analytics": "^18.0.0",
    
    // Media
    "react-native-track-player": "^4.0.0",
    "react-native-video": "^5.2.1",
    
    // Biometrics
    "react-native-biometrics": "^3.0.1"
  }
}

// App Structure
interface MobileApp {
  navigation: NavigationContainer;
  store: ReduxStore;
  
  modules: {
    auth: AuthModule;
    therapy: TherapyModule;
    assessment: AssessmentModule;
    progress: ProgressModule;
    messaging: MessagingModule;
    resources: ResourceModule;
  };
  
  services: {
    api: APIService;
    sync: SyncService;
    notifications: NotificationService;
    health: HealthKitService;
    analytics: AnalyticsService;
  };
}

// Offline-First Data Strategy
class OfflineDataManager {
  private localDB: SQLite.Database;
  private syncQueue: SyncOperation[];
  
  async saveTherapySession(session: TherapySession): Promise {
    // Save locally first
    await this.localDB.execute(
      `INSERT INTO therapy_sessions 
       (id, data, synced) 
       VALUES (?, ?, ?)`,
      [session.id, JSON.stringify(session), false]
    );
    
    // Add to sync queue
    this.syncQueue.push({
      type: 'CREATE',
      entity: 'session',
      data: session,
      timestamp: Date.now()
    });
    
    // Attempt immediate sync if online
    if (await this.isOnline()) {
      await this.syncData();
    }
  }
  
  async syncData(): Promise {
    const online = await this.isOnline();
    if (!online) {
      return { success: false, reason: 'offline' };
    }
    
    const operations = [...this.syncQueue];
    const results = [];
    
    for (const op of operations) {
      try {
        await this.executeSync(op);
        await this.markSynced(op);
        this.syncQueue = this.syncQueue.filter(q => q !== op);
        results.push({ op, success: true });
      } catch (error) {
        results.push({ op, success: false, error });
      }
    }
    
    return {
      success: results.every(r => r.success),
      results
    };
  }
  
  private async isOnline(): Promise {
    const netInfo = await NetInfo.fetch();
    return netInfo.isConnected && netInfo.isInternetReachable;
  }
}

4.2 Unique Mobile Features

Mobile platforms offer unique capabilities that can enhance therapeutic interventions beyond what's possible on desktop web applications.

Mobile-Specific Capabilities

Capability Therapeutic Application Technical Implementation Privacy Considerations
Camera & Photos Mood tracking via facial expressions, photo journaling react-native-camera, ML Kit face detection All processing on-device, no photo uploads
Microphone Voice journaling, speech pattern analysis react-native-audio-recorder-player Encrypted local storage, opt-in only
GPS Location Context-aware prompts, activity tracking react-native-geolocation-service Minimal accuracy, general areas only
Accelerometer Physical activity detection, sleep monitoring react-native-sensors Aggregated data only, no raw sensor logs
Health App Integration Sleep, exercise, heart rate data Apple HealthKit, Google Fit User-controlled permissions
Biometric Auth Face ID/Touch ID for secure access react-native-biometrics Device-level, no biometric data stored

Context-Aware Interventions

// Example: Location-based mindfulness prompts
class ContextAwarePrompts {
  private geofences: Geofence[] = [];
  
  async setupGeofences(userId: string): Promise {
    // User defines helpful reminder locations
    this.geofences = [
      {
        id: 'home',
        latitude: 37.7749,
        longitude: -122.4194,
        radius: 100, // meters
        prompt: 'Taking a moment to practice mindfulness?',
        action: 'breathing-exercise'
      },
      {
        id: 'work',
        latitude: 37.7849,
        longitude: -122.4094,
        radius: 200,
        prompt: 'Stressful day? Try a 3-minute breathing space.',
        action: '3-minute-breathing-space'
      }
    ];
    
    await GeofencingService.register(this.geofences);
  }
  
  async onGeofenceEnter(geofenceId: string): Promise {
    const geofence = this.geofences.find(g => g.id === geofenceId);
    if (!geofence) return;
    
    // Check if user wants notifications right now
    const userPrefs = await this.getUserPreferences();
    const now = new Date();
    const hour = now.getHours();
    
    if (userPrefs.quietHoursEnabled && 
        hour >= userPrefs.quietHoursStart || 
        hour < userPrefs.quietHoursEnd) {
      return; // Skip during quiet hours
    }
    
    // Send contextual notification
    await NotificationService.send({
      title: 'Mindfulness Moment',
      body: geofence.prompt,
      action: geofence.action,
      priority: 'default'
    });
  }
}

// Wearable Integration
interface WearableDataService {
  // Fetch health metrics from connected devices
  async getHeartRateData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  async getSleepData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  async getStepsData(
    startDate: Date,
    endDate: Date
  ): Promise;
  
  // Analyze patterns
  analyzeHeartRateVariability(): Promise;
  detectSleepDisturbances(): Promise;
  assessActivityLevel(): Promise;
  
  // Correlate with mental health
  correlateWithMood(
    healthData: HealthMetrics,
    moodData: MoodRating[]
  ): Correlation[];
}

4.3 Real-Time Messaging Architecture

Secure, HIPAA-compliant messaging enables asynchronous communication between patients and therapists, providing a safety net for patients while reducing therapist burden compared to synchronous appointments.

Messaging System Requirements

Messaging Architecture: ═════════════════════════════════ ┌─────────────┐ ┌──────────────┐ │ Patient │◄───────►│ Therapist │ │ Mobile App │ │ Portal │ └──────┬──────┘ └──────┬───────┘ │ │ │ WebSocket (TLS 1.3) │ │ │ ▼ ▼ ┌──────────────────────────────────────┐ │ Message Broker (Redis) │ │ - Real-time delivery │ │ - Presence detection │ │ - Read receipts │ └──────────────┬───────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Message Storage (PostgreSQL) │ │ - End-to-end encrypted │ │ - Audit logs │ │ - Retention policies │ └──────────────┬───────────────────────┘ │ ▼ ┌──────────────────────────────────────┐ │ Crisis Detection AI │ │ - Keyword analysis │ │ - Sentiment analysis │ │ - Suicide risk assessment │ │ - Automatic escalation │ └──────────────────────────────────────┘
interface MessagingService {
  // Send message
  sendMessage(message: MessageData): Promise;
  
  // Retrieve conversation
  getConversation(
    userId: string,
    otherUserId: string,
    pagination: PaginationParams
  ): Promise;
  
  // Real-time subscription
  subscribeToMessages(
    userId: string,
    callback: (message: Message) => void
  ): Subscription;
  
  // Read receipts
  markAsRead(messageId: string): Promise;
  
  // Crisis detection
  analyzeSafetyRisk(content: string): Promise;
  
  // File attachments
  uploadAttachment(file: File): Promise;
}

// End-to-End Encryption Implementation
class E2EEMessaging {
  private userKeyPair: CryptoKeyPair;
  
  async sendEncryptedMessage(
    recipientPublicKey: CryptoKey,
    content: string
  ): Promise {
    // Generate ephemeral symmetric key
    const symmetricKey = await crypto.subtle.generateKey(
      { name: 'AES-GCM', length: 256 },
      true,
      ['encrypt', 'decrypt']
    );
    
    // Encrypt message content
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encryptedContent = await crypto.subtle.encrypt(
      { name: 'AES-GCM', iv },
      symmetricKey,
      new TextEncoder().encode(content)
    );
    
    // Encrypt symmetric key with recipient's public key
    const exportedKey = await crypto.subtle.exportKey('raw', symmetricKey);
    const encryptedKey = await crypto.subtle.encrypt(
      { name: 'RSA-OAEP' },
      recipientPublicKey,
      exportedKey
    );
    
    return {
      encryptedContent: Array.from(new Uint8Array(encryptedContent)),
      encryptedKey: Array.from(new Uint8Array(encryptedKey)),
      iv: Array.from(iv),
      timestamp: Date.now()
    };
  }
  
  async decryptMessage(
    encrypted: EncryptedMessage
  ): Promise {
    // Decrypt symmetric key with private key
    const decryptedKey = await crypto.subtle.decrypt(
      { name: 'RSA-OAEP' },
      this.userKeyPair.privateKey,
      new Uint8Array(encrypted.encryptedKey)
    );
    
    // Import decrypted symmetric key
    const symmetricKey = await crypto.subtle.importKey(
      'raw',
      decryptedKey,
      { name: 'AES-GCM' },
      false,
      ['decrypt']
    );
    
    // Decrypt message content
    const decryptedContent = await crypto.subtle.decrypt(
      { 
        name: 'AES-GCM', 
        iv: new Uint8Array(encrypted.iv) 
      },
      symmetricKey,
      new Uint8Array(encrypted.encryptedContent)
    );
    
    return new TextDecoder().decode(decryptedContent);
  }
}

// Crisis Keyword Detection
class CrisisDetectionService {
  private crisisKeywords = [
    // Direct suicidal ideation
    'kill myself', 'end my life', 'want to die', 
    'suicide', 'suicidal', 'better off dead',
    
    // Self-harm
    'hurt myself', 'cut myself', 'harm myself',
    
    // Plans/methods
    'pills', 'overdose', 'jump off', 'hanging',
    
    // Hopelessness
    'no point', 'cant go on', 'no way out', 'give up'
  ];
  
  async analyzeMessage(content: string): Promise {
    const lowerContent = content.toLowerCase();
    
    // Check for crisis keywords
    const foundKeywords = this.crisisKeywords.filter(
      keyword => lowerContent.includes(keyword)
    );
    
    if (foundKeywords.length === 0) return null;
    
    // Calculate risk level
    let riskLevel: 'low' | 'medium' | 'high' | 'severe';
    if (foundKeywords.length >= 3) riskLevel = 'severe';
    else if (foundKeywords.length >= 2) riskLevel = 'high';
    else riskLevel = 'medium';
    
    // Enhanced analysis with NLP
    const sentiment = await this.analyzeSentiment(content);
    const context = await this.analyzeContext(content);
    
    if (sentiment.score < -0.8 && context.includesPlan) {
      riskLevel = 'severe';
    }
    
    return {
      riskLevel,
      foundKeywords,
      sentiment,
      context,
      timestamp: new Date(),
      requiresImmediateResponse: riskLevel === 'severe' || riskLevel === 'high',
      recommendedActions: this.getRecommendedActions(riskLevel)
    };
  }
  
  private getRecommendedActions(riskLevel: string): string[] {
    switch (riskLevel) {
      case 'severe':
        return [
          'Immediate therapist notification',
          'Emergency services contact information',
          '988 Suicide & Crisis Lifeline display',
          'Safety plan activation',
          'Emergency contact notification (if authorized)'
        ];
      case 'high':
        return [
          'Urgent therapist notification',
          'Crisis resources display',
          'Safety plan review',
          'Check-in scheduling'
        ];
      default:
        return [
          'Therapist notification',
          'Supportive resources',
          'Coping skills reminder'
        ];
    }
  }
}

4.4 Push Notifications Strategy

Thoughtful push notifications can significantly improve engagement and outcomes. However, poorly designed notifications lead to annoyance, app deletion, and reduced trust.

Notification Best Practices

Notification Type Timing Frequency User Control
Practice Reminders User-scheduled (e.g., daily 9am) Once daily max Full customization: time, days, snooze
Session Follow-ups 24 hours after incomplete session One reminder only Can disable per session type
Assessment Reminders Biweekly at user's preferred time Biweekly Can set preferred day/time
Therapist Messages Immediate Per message Cannot disable (clinical safety)
Progress Milestones Upon achievement As earned Can disable celebrations
Crisis Resources When crisis keywords detected Per crisis event Cannot disable (safety)

Key Takeaways

Review Questions

  1. Why is React Native chosen for the mobile platform over native iOS/Android development or other cross-platform frameworks?
  2. How does the offline-first data strategy work? Describe the process from local storage through sync to the server.
  3. What are three mobile-specific capabilities that enhance therapeutic interventions, and how would you implement them while preserving privacy?
  4. Explain the end-to-end encryption process for secure messaging. Why is a hybrid approach (symmetric + asymmetric) used?
  5. How does the crisis detection system balance sensitivity and specificity? What are the risks of false positives vs. false negatives?
  6. What makes a push notification strategy effective vs. annoying? How should user control be balanced with clinical recommendations?