UNPKG

capacitor-native-update

Version:
607 lines (483 loc) 14.2 kB
# Quick Start Guide Get up and running with Capacitor Native Update in 5 minutes! This guide covers all three main features: 1. **Live Updates (OTA)** - Push JavaScript/CSS updates instantly 2. **Native App Updates** - Check and install app store updates 3. **App Reviews** - Request in-app ratings and reviews ## Installation ```bash # Install the plugin npm install capacitor-native-update # Sync with native projects npx cap sync ``` ## Basic Setup ### 1. Configure the Plugin **capacitor.config.json**: ```json { "appId": "com.example.app", "appName": "MyApp", "plugins": { "CapacitorNativeUpdate": { "updateUrl": "https://updates.example.com/api/v1", "autoCheck": true, "appStoreId": "123456789" } } } ``` ### 2. Import and Initialize ```typescript import { CapacitorNativeUpdate } from 'capacitor-native-update'; // Initialize on app start export class App { async ngOnInit() { await this.initializeUpdates(); } async initializeUpdates() { // Check for all types of updates await this.checkLiveUpdates(); await this.checkNativeUpdates(); // Set up review prompt for later this.scheduleReviewPrompt(); } } ``` ## Feature 1: Live Updates (OTA) Push updates without app store review! ### Basic Implementation ```typescript import { CapacitorNativeUpdate } from 'capacitor-native-update'; export class LiveUpdateService { async checkAndApplyUpdates() { try { // 1. Check for updates const { available, version } = await CapacitorNativeUpdate.checkForUpdate(); if (!available) { console.log('No updates available'); return; } console.log(`Update ${version} available!`); // 2. Download the update await CapacitorNativeUpdate.downloadUpdate({ onProgress: (progress) => { console.log(`Download: ${progress.percent}%`); }, }); // 3. Apply the update (app will restart) await CapacitorNativeUpdate.applyUpdate(); } catch (error) { console.error('Update failed:', error); } } } ``` ### With User Interface ```typescript export class UpdateUIService { constructor( private alertController: AlertController, private loadingController: LoadingController ) {} async checkForUpdatesWithUI() { const { available, version, notes } = await CapacitorNativeUpdate.checkForUpdate(); if (!available) return; // Show update dialog const alert = await this.alertController.create({ header: 'Update Available', message: `Version ${version} is ready!\n\n${notes || 'Bug fixes and improvements'}`, buttons: [ { text: 'Later', role: 'cancel' }, { text: 'Update Now', handler: () => this.downloadAndInstall(), }, ], }); await alert.present(); } private async downloadAndInstall() { const loading = await this.loadingController.create({ message: 'Downloading update...', }); await loading.present(); try { await CapacitorNativeUpdate.downloadUpdate({ onProgress: (progress) => { loading.message = `Downloading: ${Math.round(progress.percent)}%`; }, }); loading.message = 'Installing...'; await CapacitorNativeUpdate.applyUpdate(); } catch (error) { await loading.dismiss(); // Show error } } } ``` ### Setting Up Update Server Use our example server or implement your own: ```bash # Using example server cd server-example npm install npm start # Upload a bundle curl -X POST http://localhost:3000/api/v1/bundles \ -H "Authorization: Bearer your-token" \ -F "file=@bundle.zip" \ -F "version=1.0.1" \ -F "channel=production" ``` ## Feature 2: Native App Updates Check for app store updates and install them! ### Basic Implementation ```typescript export class NativeUpdateService { async checkForAppStoreUpdates() { try { const result = await CapacitorNativeUpdate.checkAppUpdate(); if (!result.updateAvailable) { console.log('App is up to date'); return; } // Handle based on platform if (Capacitor.getPlatform() === 'android') { await this.handleAndroidUpdate(result); } else if (Capacitor.getPlatform() === 'ios') { await this.handleiOSUpdate(result); } } catch (error) { console.error('Native update check failed:', error); } } private async handleAndroidUpdate(result: any) { if (result.immediateUpdateAllowed) { // Critical update - must install await CapacitorNativeUpdate.startImmediateUpdate(); } else { // Optional update - download in background await CapacitorNativeUpdate.startFlexibleUpdate(); } } private async handleiOSUpdate(result: any) { // iOS can only redirect to App Store const alert = await this.alertController.create({ header: 'Update Available', message: `Version ${result.availableVersion} is available on the App Store`, buttons: [ { text: 'Later', role: 'cancel' }, { text: 'Update', handler: () => CapacitorNativeUpdate.openAppStore(), }, ], }); await alert.present(); } } ``` ### With Progress Tracking (Android) ```typescript export class AndroidUpdateProgress { downloadProgress = 0; async startFlexibleUpdate() { // Start download await CapacitorNativeUpdate.startFlexibleUpdate(); // Track progress CapacitorNativeUpdate.addListener( 'onAppUpdateDownloadProgress', (progress) => { this.downloadProgress = Math.round( (progress.bytesDownloaded / progress.totalBytesToDownload) * 100 ); } ); // Handle completion CapacitorNativeUpdate.addListener('onAppUpdateDownloaded', async () => { const alert = await this.alertController.create({ header: 'Update Ready', message: 'Update has been downloaded. Install now?', buttons: [ { text: 'Later' }, { text: 'Install', handler: () => CapacitorNativeUpdate.completeFlexibleUpdate(), }, ], }); await alert.present(); }); } } ``` ## Feature 3: App Reviews Request ratings without users leaving your app! ### Basic Implementation ```typescript export class AppReviewService { async requestReview() { try { const result = await CapacitorNativeUpdate.requestReview(); if (result.displayed) { console.log('Review prompt shown'); // Track analytics } } catch (error) { console.error('Review request failed:', error); // Fallback to external review } } } ``` ### Smart Review Prompts Only ask at the right moments: ```typescript export class SmartReviewService { private readonly MIN_SESSIONS = 3; private readonly MIN_DAYS_INSTALLED = 3; async checkAndRequestReview() { // Don't ask too early if (!(await this.isGoodTimeToAsk())) { return; } // Two-step approach const enjoying = await this.askIfEnjoying(); if (enjoying) { await CapacitorNativeUpdate.requestReview(); } else { await this.askForFeedback(); } } private async isGoodTimeToAsk(): Promise<boolean> { const sessions = await this.getSessionCount(); const daysSinceInstall = await this.getDaysSinceInstall(); return ( sessions >= this.MIN_SESSIONS && daysSinceInstall >= this.MIN_DAYS_INSTALLED ); } private async askIfEnjoying(): Promise<boolean> { return new Promise((resolve) => { const alert = this.alertController.create({ header: 'Enjoying MyApp?', buttons: [ { text: 'Not really', handler: () => resolve(false), }, { text: 'Yes!', handler: () => resolve(true), }, ], }); alert.present(); }); } } ``` ### Review Triggers Call review prompts at optimal moments: ```typescript export class ReviewTriggers { constructor(private reviewService: SmartReviewService) {} // After completing important task async onTaskCompleted() { const taskCount = await this.getCompletedTasks(); // Every 5 tasks if (taskCount % 5 === 0) { setTimeout(() => { this.reviewService.checkAndRequestReview(); }, 2000); } } // After positive interaction async onPositiveEvent() { await this.reviewService.checkAndRequestReview(); } // On app launch (with conditions) async onAppLaunch() { const lastPrompt = await this.getLastPromptDate(); const daysSince = this.daysSince(lastPrompt); // Max once per month if (daysSince >= 30) { await this.reviewService.checkAndRequestReview(); } } } ``` ## Complete Example Here's everything working together: ```typescript import { Component, OnInit } from '@angular/core'; import { CapacitorNativeUpdate } from 'capacitor-native-update'; import { Capacitor } from '@capacitor/core'; @Component({ selector: 'app-root', templateUrl: 'app.component.html', }) export class AppComponent implements OnInit { constructor( private platform: Platform, private alertCtrl: AlertController ) {} async ngOnInit() { await this.platform.ready(); // Initialize all update features await this.initializeUpdates(); } async initializeUpdates() { // 1. Check for live updates on startup this.checkLiveUpdates(); // 2. Check for native updates periodically this.scheduleNativeUpdateCheck(); // 3. Set up smart review prompts this.initializeReviewPrompts(); } // Live Updates private async checkLiveUpdates() { try { const { available } = await CapacitorNativeUpdate.checkForUpdate(); if (available) { // Auto-download in background await CapacitorNativeUpdate.downloadUpdate(); // Notify user const toast = await this.toastCtrl.create({ message: 'Update ready! Restart to apply.', duration: 5000, buttons: [ { text: 'Restart', handler: () => CapacitorNativeUpdate.applyUpdate(), }, ], }); await toast.present(); } } catch (error) { console.error('Live update check failed:', error); } } // Native Updates private scheduleNativeUpdateCheck() { // Check immediately this.checkNativeUpdates(); // Then check daily setInterval( () => { this.checkNativeUpdates(); }, 24 * 60 * 60 * 1000 ); } private async checkNativeUpdates() { try { const result = await CapacitorNativeUpdate.checkAppUpdate(); if (result.updateAvailable && result.flexibleUpdateAllowed) { // Start background download for Android if (Capacitor.getPlatform() === 'android') { await CapacitorNativeUpdate.startFlexibleUpdate(); } } } catch (error) { console.error('Native update check failed:', error); } } // App Reviews private initializeReviewPrompts() { // Track positive events document.addEventListener('task-completed', () => { this.maybeRequestReview(); }); // Check on app foreground document.addEventListener('resume', () => { this.maybeRequestReview(); }); } private async maybeRequestReview() { const canAsk = await this.canAskForReview(); if (canAsk) { await CapacitorNativeUpdate.requestReview(); await this.markReviewRequested(); } } private async canAskForReview(): Promise<boolean> { // Your conditions here const lastAsked = await this.getLastReviewDate(); const daysSince = this.daysSince(lastAsked); return daysSince > 30; // Once per month max } } ``` ## Testing Your Implementation ### 1. Test Live Updates ```bash # Build your web app npm run build # Create update bundle cd www && zip -r ../update-1.0.1.zip . && cd .. # Upload to test server curl -X POST http://localhost:3000/api/v1/bundles \ -H "Authorization: Bearer test-token" \ -F "file=@update-1.0.1.zip" \ -F "version=1.0.1" # Test in app ``` ### 2. Test Native Updates **Android:** - Upload APK to Internal Test Track - Install older version - Open app to trigger update **iOS:** - Use TestFlight - Install older version - Check for updates in app ### 3. Test App Reviews ```typescript // Enable debug mode await CapacitorNativeUpdate.setReviewDebugMode({ enabled: true }); // Force show review (debug only) await CapacitorNativeUpdate.requestReview({ force: true }); ``` ## What's Next? Now that you have the basics working: 1. **Production Setup**: - Set up a proper update server - Implement bundle signing - Configure update channels 2. **Advanced Features**: - Delta updates for smaller downloads - A/B testing different update strategies - Rollback capabilities 3. **Deep Dive**: - [Live Updates Guide](./LIVE_UPDATES_GUIDE.md) - Complete OTA implementation - [Native Updates Guide](./NATIVE_UPDATES_GUIDE.md) - Platform-specific details - [App Review Guide](./APP_REVIEW_GUIDE.md) - Maximize review rates - [Security Guide](./SECURITY.md) - Best practices - [API Reference](../API.md) - All methods and options ## Troubleshooting ### Live Updates Not Working? ```typescript // Enable debug logging await CapacitorNativeUpdate.setDebugMode({ enabled: true }); // Check configuration const config = await CapacitorNativeUpdate.getConfiguration(); console.log('Update URL:', config.updateUrl); ``` ### Native Updates Not Detected? - Ensure app is published on store - Check version numbers are correct - Verify package name matches ### Reviews Not Showing? - iOS: Limited to 3 times per year by system - Android: May be throttled by Play Store - Both: Won't show in development builds ## Support - 📖 [Documentation](https://github.com/aoneahsan/capacitor-native-update) - 🐛 [Issue Tracker](https://github.com/aoneahsan/capacitor-native-update/issues) - 💬 [Discussions](https://github.com/aoneahsan/capacitor-native-update/discussions) Happy updating! 🚀