UNPKG

@haykmkrtich/react-native-patriot-native

Version:

[![npm version](https://badge.fury.io/js/%40haykmkrtich%2Freact-native-patriot-native.svg)](https://badge.fury.io/js/%40haykmkrtich%2Freact-native-patriot-native) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.or

280 lines (210 loc) 7.7 kB
# Mobile App Integration Guide ## `@haykmkrtich/react-native-patriot-native` A guide for integrating WearOS watch communication into your React Native mobile app. --- ## Prerequisites | Requirement | Minimum | |---|---| | React Native | >= 0.77.0 (New Architecture / TurboModules) | | Android API | 24+ (Android 7.0) | | Java | 17+ | | Hardware | Paired WearOS watch | | Platform | Android only (iOS calls are rejected) | --- ## 1. Install the Package ```bash npm install @haykmkrtich/react-native-patriot-native # or yarn add @haykmkrtich/react-native-patriot-native ``` No manual linking needed — TurboModule autolinking handles it. After installing, rebuild: ```bash npx react-native clean npx react-native run-android ``` --- ## 2. Exported API ```typescript import { getConnectedDevices, installWatchface, isAppInstalledOnWatch, sendMessageToWatch, } from '@haykmkrtich/react-native-patriot-native'; ``` | Function | Purpose | |---|---| | `getConnectedDevices()` | List all connected WearOS watches | | `installWatchface(packageName, nodeId?)` | Trigger Play Store install on a specific or all watches | | `isAppInstalledOnWatch(packageName)` | Check if an app/capability exists on watches | | `sendMessageToWatch(nodeId, path, data?)` | Send a message to one specific watch | --- ## 3. TypeScript Types ```typescript interface ConnectedDevice { id: string; // Node ID — use this for sendMessageToWatch displayName: string; // e.g. "Galaxy Watch 5" isNearby: boolean; // Bluetooth proximity type: string; // "watch" platform: string; // "wearOS" | "unknown" } interface AppInstallStatus { isInstalled: boolean; // true if found on any watch installedOnNodes: string[]; // node IDs where it's installed } ``` --- ## 4. Common Workflows ### A. Discover Connected Watches ```typescript const devices = await getConnectedDevices(); // Returns ConnectedDevice[] — empty array if nothing connected ``` ### B. Install a Watchface on All Connected Watches Omit the second argument to broadcast to every connected watch. ```typescript await installWatchface('com.example.mywatchface'); // Opens Play Store install prompt on ALL connected watches ``` ### C. Install a Watchface on a Specific Watch Pass the `nodeId` from `getConnectedDevices()` to target one watch. ```typescript const devices = await getConnectedDevices(); if (devices.length === 0) { throw new Error('No watch connected'); } // Target the first (or only) connected watch const watch = devices[0]; await installWatchface('com.example.mywatchface', watch.id); // Opens Play Store install prompt only on that watch ``` ### D. Full Flow: Check Then Install on a Specific Watch ```typescript async function installOnWatch(packageName: string): Promise<void> { // Step 1: Get connected watches const devices = await getConnectedDevices(); if (devices.length === 0) { throw new Error('No watch connected'); } const watch = devices[0]; console.log(`Found: ${watch.displayName}`); // Step 2: (Optional) Check if already installed const status = await isAppInstalledOnWatch(packageName); if (status.isInstalled) { console.log('Already installed, skipping'); return; } // Step 3: Install on that specific watch await installWatchface(packageName, watch.id); // Phone shows a toast, watch shows Play Store install prompt } await installOnWatch('com.example.mywatchface'); ``` ### E. Send a Custom Message to a Specific Watch Use `sendMessageToWatch` to send arbitrary data to a watch node. ```typescript const devices = await getConnectedDevices(); const watch = devices[0]; // path = routing key, data = optional string payload await sendMessageToWatch(watch.id, '/sync-settings', JSON.stringify({ theme: 'dark', })); ``` --- ## 5. Error Handling Every function rejects with an `Error` that has a `.code` property: ```typescript try { await installWatchface('com.example.watchface'); } catch (error: any) { switch (error.code) { case 'NO_NODES': // No watches connected break; case 'INSTALL_FAILED': // WearOS API rejected the install request break; } } ``` | Error Code | Thrown By | Meaning | |---|---|---| | `NO_NODES` | `installWatchface` | No connected WearOS device | | `INSTALL_FAILED` | `installWatchface` | Install request failed | | `DETECTION_FAILED` | `getConnectedDevices` | WearOS API communication error | | `CHECK_FAILED` | `isAppInstalledOnWatch` | Capability query failed | | `MESSAGE_FAILED` | `sendMessageToWatch` | Message delivery failed | Any call on iOS rejects with `"PatriotNative is only supported on Android"`. --- ## 6. Full Example: Install Screen Component ```typescript import React, { useEffect, useState } from 'react'; import { View, Text, Button, Alert, Platform } from 'react-native'; import { getConnectedDevices, installWatchface, isAppInstalledOnWatch, ConnectedDevice, } from '@haykmkrtich/react-native-patriot-native'; const WATCHFACE_PACKAGE = 'com.example.mywatchface'; export function WatchInstallScreen() { const [watch, setWatch] = useState<ConnectedDevice | null>(null); const [installed, setInstalled] = useState(false); const [loading, setLoading] = useState(true); useEffect(() => { if (Platform.OS !== 'android') return; (async () => { try { const devices = await getConnectedDevices(); if (devices.length > 0) { setWatch(devices[0]); const status = await isAppInstalledOnWatch(WATCHFACE_PACKAGE); setInstalled(status.isInstalled); } } catch (e) { console.error(e); } finally { setLoading(false); } })(); }, []); const handleInstall = async () => { try { // Target the specific connected watch by its node ID await installWatchface(WATCHFACE_PACKAGE, watch!.id); Alert.alert('Success', 'Install prompt sent to your watch'); } catch (error: any) { if (error.code === 'NO_NODES') { Alert.alert('Error', 'No watch connected'); } else { Alert.alert('Error', 'Installation failed'); } } }; if (Platform.OS !== 'android') { return <Text>WearOS features are only available on Android</Text>; } if (loading) return <Text>Detecting watch...</Text>; if (!watch) return <Text>No watch connected</Text>; return ( <View> <Text>Connected: {watch.displayName}</Text> <Text>Nearby: {watch.isNearby ? 'Yes' : 'No'}</Text> <Text>Platform: {watch.platform}</Text> {installed ? ( <Text>Watchface already installed</Text> ) : ( <Button title="Install Watchface" onPress={handleInstall} /> )} </View> ); } ``` --- ## 7. Important Notes 1. **Android only** — always gate calls behind `Platform.OS === 'android'` or let the library's built-in check reject gracefully. 2. **`installWatchface` supports targeting** — pass a `nodeId` (from `getConnectedDevices()`) to install on a specific watch, or omit it to broadcast to all connected watches. 3. **Google Play pairing** — for production, the mobile app and WearOS app must share the same package name in Google Play Console. This is a Google requirement, not a library limitation. 4. **Deprecated API** — do NOT use `getConnectedWatchProperties()`. Use `getConnectedDevices()` instead. 5. **All functions are async** — every call returns a `Promise`. Always `await` or handle `.then()/.catch()`. 6. **Rebuild after install** — this is a native module. `npx react-native clean && npx react-native run-android` is required after adding the package. Hot reload alone won't pick it up.