Exemples et cas d'utilisation
Prêt à copier un prompt de configuration avec les étapes d'installation et le guide markdown complet pour ce plugin.
Ce guide fournit des exemples pratiques pour les modèles d'application d'horloge courants en utilisant @capgo/capacitor-watch. Le TypeScript côté téléphone fonctionne pour les deux iOS et Android; les exemples de UI d'horloge ci-dessous utilisent SwiftUI (Apple Watch). Réfléchissez les mêmes payloads sur Wear OS avec les chemins de la couche de données de la rubrique de configuration de Wear OS.
Exemple 1 : Suivi de santé et de forme physique
Section intitulée « Exemple 1 : Suivi de santé et de forme physique »Sync workout data between watch and phone.
import SwiftUIimport CapgoWatchSDK
struct WorkoutView: View { @ObservedObject var connector = WatchConnector.shared @State private var heartRate: Double = 0 @State private var calories: Double = 0 @State private var isTracking = false
var body: some View { VStack(spacing: 12) { // Heart Rate Display HStack { Image(systemName: "heart.fill") .foregroundColor(.red) Text("\(Int(heartRate)) BPM") .font(.title2) }
// Calories HStack { Image(systemName: "flame.fill") .foregroundColor(.orange) Text("\(Int(calories)) cal") }
// Start/Stop Button Button(isTracking ? "Stop" : "Start") { toggleTracking() } .buttonStyle(.borderedProminent) .tint(isTracking ? .red : .green) } .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in if isTracking { updateMetrics() } } }
private func toggleTracking() { isTracking.toggle() if isTracking { // Notify phone that workout started connector.sendMessage([ "event": "workoutStarted", "timestamp": Date().timeIntervalSince1970 ]) } else { // Send final summary to phone do { try connector.updateApplicationContext([ "workoutComplete": true, "totalCalories": calories, "avgHeartRate": heartRate, "endTime": Date().timeIntervalSince1970 ]) } catch { print("Failed to update context: \(error)") } } }
private func updateMetrics() { // Simulate heart rate (in real app, use HealthKit) heartRate = Double.random(in: 120...160) calories += Double.random(in: 0.1...0.3)
// Send real-time updates if phone is reachable if connector.isReachable { connector.sendMessage([ "heartRate": heartRate, "calories": calories, "timestamp": Date().timeIntervalSince1970 ]) } }}import { CapgoWatch } from '@capgo/capacitor-watch';
class WorkoutTracker { private heartRateData: number[] = []; private totalCalories = 0;
async initialize() { // Listen for real-time workout updates await CapgoWatch.addListener('messageReceived', (event) => { const { heartRate, calories, timestamp } = event.message;
if (heartRate) { this.heartRateData.push(heartRate); this.updateUI(heartRate, calories); }
if (event.message.event === 'workoutStarted') { this.onWorkoutStarted(timestamp); } });
// Listen for workout completion via context await CapgoWatch.addListener('applicationContextReceived', (event) => { if (event.context.workoutComplete) { this.onWorkoutComplete(event.context); } }); }
private onWorkoutStarted(timestamp: number) { console.log('Workout started at:', new Date(timestamp * 1000)); this.heartRateData = []; this.totalCalories = 0; }
private onWorkoutComplete(data: any) { const avgHeartRate = data.avgHeartRate; const totalCalories = data.totalCalories;
// Save to your backend this.saveWorkout({ avgHeartRate, totalCalories, endTime: data.endTime, heartRateHistory: this.heartRateData }); }
private updateUI(heartRate: number, calories: number) { // Update your app's UI document.getElementById('heart-rate')!.textContent = `${Math.round(heartRate)} BPM`; document.getElementById('calories')!.textContent = `${Math.round(calories)} cal`; }
private async saveWorkout(data: any) { // Save to your backend console.log('Saving workout:', data); }}
const tracker = new WorkoutTracker();tracker.initialize();Exemple 2 : Télécommande de la maison intelligente
Exemple 2 : Télécommande de la maison intelligenteControl smart home devices from your watch.
import SwiftUIimport CapgoWatchSDK
struct SmartHomeView: View { @ObservedObject var connector = WatchConnector.shared @State private var devices: [SmartDevice] = [] @State private var isLoading = false
var body: some View { NavigationView { Group { if isLoading { ProgressView("Loading...") } else if devices.isEmpty { Text("No devices") .foregroundColor(.secondary) } else { List(devices) { device in DeviceRow(device: device, onToggle: { toggleDevice(device) }) } } } .navigationTitle("Home") .toolbar { Button(action: refreshDevices) { Image(systemName: "arrow.clockwise") } } } .onAppear { refreshDevices() } .onChange(of: connector.lastMessage) { message in handleMessage(message) } }
private func refreshDevices() { guard connector.isReachable else { // Load from cached context loadFromContext() return }
isLoading = true connector.sendMessage(["action": "getDevices"]) { reply in DispatchQueue.main.async { isLoading = false if let deviceList = reply["devices"] as? [[String: Any]] { devices = deviceList.compactMap { SmartDevice(from: $0) } } } } }
private func toggleDevice(_ device: SmartDevice) { connector.sendMessage([ "action": "toggleDevice", "deviceId": device.id, "newState": !device.isOn ]) { reply in DispatchQueue.main.async { if reply["success"] as? Bool == true { // Update local state if let index = devices.firstIndex(where: { $0.id == device.id }) { devices[index].isOn.toggle() } } } } }
private func loadFromContext() { if let deviceList = connector.applicationContext["devices"] as? [[String: Any]] { devices = deviceList.compactMap { SmartDevice(from: $0) } } }
private func handleMessage(_ message: [String: Any]) { // Handle push updates from phone if let update = message["deviceUpdate"] as? [String: Any], let deviceId = update["id"] as? String, let isOn = update["isOn"] as? Bool { if let index = devices.firstIndex(where: { $0.id == deviceId }) { devices[index].isOn = isOn } } }}
struct SmartDevice: Identifiable { let id: String let name: String let type: String var isOn: Bool
init?(from dict: [String: Any]) { guard let id = dict["id"] as? String, let name = dict["name"] as? String, let type = dict["type"] as? String, let isOn = dict["isOn"] as? Bool else { return nil } self.id = id self.name = name self.type = type self.isOn = isOn }}
struct DeviceRow: View { let device: SmartDevice let onToggle: () -> Void
var body: some View { HStack { Image(systemName: iconName) .foregroundColor(device.isOn ? .yellow : .gray) Text(device.name) Spacer() Toggle("", isOn: .constant(device.isOn)) .labelsHidden() .onTapGesture { onToggle() } } }
var iconName: String { switch device.type { case "light": return device.isOn ? "lightbulb.fill" : "lightbulb" case "thermostat": return "thermometer" case "lock": return device.isOn ? "lock.fill" : "lock.open" default: return "power" } }}import { CapgoWatch } from '@capgo/capacitor-watch';
interface SmartDevice { id: string; name: string; type: string; isOn: boolean;}
class SmartHomeController { private devices: SmartDevice[] = [];
async initialize() { // Handle requests from watch await CapgoWatch.addListener('messageReceivedWithReply', async (event) => { const { action, deviceId, newState } = event.message;
let response: any = { success: false };
switch (action) { case 'getDevices': response = { devices: this.devices }; break;
case 'toggleDevice': const success = await this.toggleDevice(deviceId, newState); response = { success }; break; }
await CapgoWatch.replyToMessage({ callbackId: event.callbackId, data: response }); });
// Load initial devices await this.loadDevices();
// Keep watch updated with device states await this.syncDevicesToWatch(); }
private async loadDevices() { // Load from your smart home API this.devices = [ { id: '1', name: 'Living Room', type: 'light', isOn: true }, { id: '2', name: 'Bedroom', type: 'light', isOn: false }, { id: '3', name: 'Thermostat', type: 'thermostat', isOn: true }, { id: '4', name: 'Front Door', type: 'lock', isOn: true } ]; }
private async toggleDevice(deviceId: string, newState: boolean): Promise<boolean> { try { // Call your smart home API const device = this.devices.find(d => d.id === deviceId); if (device) { device.isOn = newState;
// Push update to watch const info = await CapgoWatch.getInfo(); if (info.isReachable) { await CapgoWatch.sendMessage({ data: { deviceUpdate: { id: deviceId, isOn: newState } } }); } return true; } return false; } catch (error) { console.error('Failed to toggle device:', error); return false; } }
private async syncDevicesToWatch() { // Update application context for offline access await CapgoWatch.updateApplicationContext({ context: { devices: this.devices } }); }
// Call this when devices change on the phone async onDeviceStateChanged(deviceId: string, isOn: boolean) { const device = this.devices.find(d => d.id === deviceId); if (device) { device.isOn = isOn; await this.syncDevicesToWatch(); } }}
const controller = new SmartHomeController();controller.initialize();Exemple 3 : Centre de notifications
Section intitulée « Exemple 3 : Centre de notifications »Envoyez des notifications personnalisées à votre montre.
import { CapgoWatch } from '@capgo/capacitor-watch';
class NotificationService { async sendNotification(title: string, body: string, data?: any) { const info = await CapgoWatch.getInfo();
if (info.isReachable) { // Send immediately if watch is reachable await CapgoWatch.sendMessage({ data: { type: 'notification', title, body, data, timestamp: Date.now() } }); } else { // Queue for later delivery await CapgoWatch.transferUserInfo({ userInfo: { type: 'notification', title, body, data, timestamp: Date.now() } }); } }
async sendUrgentAlert(message: string) { // Use sendMessage for urgent alerts (requires watch to be reachable) const info = await CapgoWatch.getInfo();
if (!info.isReachable) { console.warn('Watch not reachable for urgent alert'); return false; }
await CapgoWatch.sendMessage({ data: { type: 'urgentAlert', message, haptic: 'warning', timestamp: Date.now() } });
return true; }}
// Usageconst notifications = new NotificationService();
// Regular notification (queued if watch unavailable)await notifications.sendNotification( 'Order Update', 'Your order has shipped!', { orderId: '12345' });
// Urgent alert (requires watch to be active)const sent = await notifications.sendUrgentAlert('Security alert: New login detected');import SwiftUIimport WatchKitimport CapgoWatchSDK
struct NotificationView: View { @ObservedObject var connector = WatchConnector.shared @State private var notifications: [WatchNotification] = [] @State private var showAlert = false @State private var alertMessage = ""
var body: some View { NavigationView { List(notifications) { notification in NotificationRow(notification: notification) } .navigationTitle("Notifications") } .onReceive(connector.$lastMessage) { message in handleMessage(message) } .alert("Alert", isPresented: $showAlert) { Button("OK") { } } message: { Text(alertMessage) } }
private func handleMessage(_ message: [String: Any]) { guard let type = message["type"] as? String else { return }
switch type { case "notification": let notification = WatchNotification( id: UUID().uuidString, title: message["title"] as? String ?? "", body: message["body"] as? String ?? "", timestamp: Date(timeIntervalSince1970: (message["timestamp"] as? Double ?? 0) / 1000) ) notifications.insert(notification, at: 0)
// Play haptic WKInterfaceDevice.current().play(.notification)
case "urgentAlert": alertMessage = message["message"] as? String ?? "Alert" showAlert = true
// Play strong haptic for urgent alerts if let hapticType = message["haptic"] as? String { switch hapticType { case "warning": WKInterfaceDevice.current().play(.notification) DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { WKInterfaceDevice.current().play(.notification) } default: WKInterfaceDevice.current().play(.notification) } }
default: break } }}
struct WatchNotification: Identifiable { let id: String let title: String let body: String let timestamp: Date}
struct NotificationRow: View { let notification: WatchNotification
var body: some View { VStack(alignment: .leading, spacing: 4) { Text(notification.title) .font(.headline) Text(notification.body) .font(.caption) .foregroundColor(.secondary) Text(notification.timestamp, style: .relative) .font(.caption2) .foregroundColor(.secondary) } .padding(.vertical, 4) }}Exemple 4 : Service de synchronisation de données
Exemple 4 : Service de synchronisation de donnéesMaintenez les données synchronisées entre téléphone et montre.
import { CapgoWatch } from '@capgo/capacitor-watch';
class DataSyncService { private syncQueue: any[] = []; private isSyncing = false;
async initialize() { // Listen for sync requests from watch await CapgoWatch.addListener('messageReceivedWithReply', async (event) => { if (event.message.action === 'sync') { const data = await this.getDataForSync(event.message.lastSyncTime); await CapgoWatch.replyToMessage({ callbackId: event.callbackId, data: { items: data, syncTime: Date.now() } }); } });
// Listen for data from watch await CapgoWatch.addListener('userInfoReceived', (event) => { this.handleWatchData(event.userInfo); });
// Monitor connectivity for sync opportunities await CapgoWatch.addListener('reachabilityChanged', (event) => { if (event.isReachable && this.syncQueue.length > 0) { this.processSyncQueue(); } }); }
// Push important data to watch (guaranteed delivery) async pushToWatch(data: any) { await CapgoWatch.transferUserInfo({ userInfo: { type: 'dataUpdate', data, timestamp: Date.now() } }); }
// Update shared state (latest value only) async updateSharedState(state: any) { await CapgoWatch.updateApplicationContext({ context: { ...state, lastUpdated: Date.now() } }); }
// Queue data for sync when watch becomes available queueForSync(data: any) { this.syncQueue.push(data); this.attemptSync(); }
private async attemptSync() { const info = await CapgoWatch.getInfo(); if (info.isReachable) { await this.processSyncQueue(); } }
private async processSyncQueue() { if (this.isSyncing || this.syncQueue.length === 0) return;
this.isSyncing = true;
while (this.syncQueue.length > 0) { const item = this.syncQueue.shift(); await CapgoWatch.transferUserInfo({ userInfo: item }); }
this.isSyncing = false; }
private async getDataForSync(lastSyncTime: number): Promise<any[]> { // Return data modified since lastSyncTime // This would query your database/API return []; }
private handleWatchData(data: any) { console.log('Received from watch:', data); // Process and save data from watch }}Meilleures pratiques
Section intitulée « Bonnes Pratiques »1. Choisissez le bon mode de transfert
Section intitulée « 1. Choisissez le bon mode de transfert »| Méthode | Utilisation | context |
|---|---|---|
sendMessage | Interactif, sensible à l'époque | Immédiat (échoue si inatteignable) |
updateApplicationContext | État d'application actuel | Dernière valeur uniquement |
transferUserInfo | Interactif, sensible à la durée | Immédiat (échoue si inatteignable ) |
2. Gérer l'État Hors Ligne
Gérer l'arrêt en ligne avec grâceasync function smartSend(data: any, important: boolean) { const info = await CapgoWatch.getInfo();
if (info.isReachable) { // Send immediately await CapgoWatch.sendMessage({ data }); } else if (important) { // Queue for later await CapgoWatch.transferUserInfo({ userInfo: data }); } else { // Update context (will be available when watch opens app) await CapgoWatch.updateApplicationContext({ context: data }); }}3. Réduire la taille des données
Section intitulée « 3. Réduire la taille des données »// Bad - sending large objectsconnector.sendMessage(["user": fullUserObject])
// Good - send only what's neededconnector.sendMessage([ "userId": user.id, "name": user.displayName, "avatarUrl": user.avatarUrl])4. Utiliser les haptiques de manière appropriée
Titre : 4. Utiliser les Haptiques de Manière Appropriateimport WatchKit
// Success feedbackWKInterfaceDevice.current().play(.success)
// Failure feedbackWKInterfaceDevice.current().play(.failure)
// Navigation feedbackWKInterfaceDevice.current().play(.click)
// NotificationWKInterfaceDevice.current().play(.notification)5. Mettre en cache sur Montre
Section intitulée « 5. Mettre en cache sur Montre »class DataCache { private let defaults = UserDefaults.standard
func save(_ data: [String: Any], forKey key: String) { if let encoded = try? JSONSerialization.data(withJSONObject: data) { defaults.set(encoded, forKey: key) } }
func load(forKey key: String) -> [String: Any]? { guard let data = defaults.data(forKey: key), let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] else { return nil } return dict }}Étapes suivantes
Section intitulée « Étapes suivantes »- Création d'une application watchOS - Configuration de l'Apple Watch
- Création d'une application Wear OS - Configuration du module Wear OS
- Référence du API - Documentation complète de API
- GitHub Répertoire de dépôt - Source de code et problèmes
Continuez avec les Exemples & Utilisations
Section intitulée « Continuez avec les Exemples & Utilisations »Si vous utilisez Exemples et Cas d'Utilisation pour planifier le travail de plugin natif, connectez-l’avec En utilisant @capgo/capacitor-watch pour la capacité native dans En utilisant @capgo/capacitor-watch, __Répertoire de Plugin Capgo pour le flux de travail du produit dans __Répertoire de Plugin Capgo, __Plugins Capacitor par Capgo pour le détail d'implémentation dans __Plugins Capacitor par Capgo, Ajouter ou Mettre à Jour les Plugins pour le détail d'implémentation dans Ajouter ou Mettre à Jour les Plugins, et Alternatives aux Plugins d'Entreprise Ionic pour le flux de travail du produit dans les alternatives d'extension d'entreprise d'Ionic.