Esempi e Casistiche di utilizzo
Copiare un prompt di configurazione con i passaggi di installazione e la guida markdown completa per questo plugin.
Questa guida fornisce esempi pratici per modelli di app Apple Watch comuni utilizzando @capgo/capacitor-watch.
Esempio 1: Tracciatore di salute e fitness
Esempio 1: Tracciatore di salute e fitnessSincronizza i dati di allenamento tra orologio e telefono.
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();Esempio 2: Telecomando per la casa intelligente
Sincronizza i dispositivi della casa intelligente dal tuo orologio.Orologio (SwiftUI)
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();Esempio 3: Centro notifiche
Sottosezione intitolata “Esempio 3: Centro notifiche”Inviare notifiche personalizzate all'orologio.
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) }}Esempio 4: Servizio sincronizzazione dati
Sottosezione intitolata “Esempio 4: Servizio sincronizzazione dati”Sincronizzare i dati tra telefono e orologio.
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 }}Pratiche Ottimali
Sezione intitolata “Pratiche Ottimali”1. Scegli il Metodo di Trasferimento Giusto
Sezione intitolata “1. Scegli il Metodo di Trasferimento Giusto”| Metodo | Caso d'Uso | context:Pagina/Area: Pagina di marketing delle soluzioni Capgo. Ruolo: Etichetta breve o elemento di navigazione. Visualizzato in: pagina soluzioni/cordova-to-capacitor-ai.astro. Chiave di messaggio `solutions_cordova_to_capacitor_ai_table_use_case` (Solutions Cordova To Capacitor Ai Table Use Case). |
|---|---|---|
sendMessage | Consegna | context:Pagina/Area: Pagina di prodotti/prezzi aziendale. Ruolo: Etichetta di interfaccia utente. Chiave di messaggio `enterprise_delivery_label` (Enterprise Delivery Label). |
updateApplicationContext | Interattivo, sensibile al tempo | Immediate (fallisce se non raggiungibile) |
transferUserInfo | Stato corrente dell'applicazione | In attesa, garantito |
2. Gestisci la mancanza di rete con cura
Sezione intitolata “2. Gestisci la mancanza di rete con cura”async 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. Minimizza la dimensione dei dati
Sezione intitolata “3. Minimizza la dimensione dei dati”// Bad - sending large objectsconnector.sendMessage(["user": fullUserObject])
// Good - send only what's neededconnector.sendMessage([ "userId": user.id, "name": user.displayName, "avatarUrl": user.avatarUrl])4. Utilizza gli effetti tattili in modo appropriato
Sezione intitolata “4. Utilizza gli effetti tattili in modo appropriato”import WatchKit
// Success feedbackWKInterfaceDevice.current().play(.success)
// Failure feedbackWKInterfaceDevice.current().play(.failure)
// Navigation feedbackWKInterfaceDevice.current().play(.click)
// NotificationWKInterfaceDevice.current().play(.notification)5. Caching su Watch
Sezione intitolata “5. Caching su Watch”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 }}Esegui i passaggi successivi
Scheda intitolata “Esegui i passaggi successivi”- Configurazione dell'app Watch - Crea la tua prima app per orologio
- API Reference - Completa la documentazione API
- GitHub Repository - Sorgenti e problemi code
Continua da Esempi e Caso d'uso
Scheda intitolata “Continua da Esempi e Caso d'uso”Se stai utilizzando Esempi e Caso d'Uso per pianificare il lavoro del plugin nativo, connettilo con Utilizzo di @capgo/capacitor-watch per la capacità nativa in Utilizzo di @capgo/capacitor-watch, Directory dei Plugin Capgo per il flusso di lavoro del prodotto in Directory dei Plugin Capgo, Plugin Capacitor di Capgo per la dettaglio di implementazione in Plugin Capacitor di Capgo, Aggiunta o Aggiornamento dei Plugin per il dettaglio di implementazione in Aggiunta o Aggiornamento dei Plugin, e Sostituti dei Plugin Enterprise Ionic per il flusso di lavoro del prodotto in Sostituti dei Plugin Enterprise Ionic.