| name | zepp-os-settings-storage |
| description | Use when persisting data or building settings in a Zepp OS project - saving / loading user preferences or app data so they survive app restart, storing flags like "onboarding completed" or accumulated step / sensor / health totals, building the companion Settings App that runs inside the Zepp phone app (AppSettingsPage with Toggle / Select / Section / Slider components), syncing a value the user picks in the phone Settings UI down to the watch via settingsStorage, or using @zos/storage LocalStorage / @zos/fs on the watch itself. Use even when the wording is generic ("save data locally", "remember the user's choice", "let the user pick options in the phone settings") - Zepp OS has three distinct storage mechanisms (phone settingsStorage, watch LocalStorage, watch @zos/fs) with different scopes and types. Do not use for sensor reads (zepp-os-sensors), UI widgets on the watch (zepp-os-ui), navigation (zepp-os-navigation-lifecycle), or watchface rendering (zepp-os-watchface). |
| compatibility | Zepp OS Settings App (phone) + on-device storage (watch). API_LEVEL 2.0+; @zos/storage LocalStorage requires >=3.0. |
Zepp OS Settings & Storage
Context: Settings App (phone) + on-device storage (watch). Two different storage systems plus a bridge.
API_LEVEL: 2.0+ (@zos/storage LocalStorage is [≥3.0]).
Prereq: runtime contexts — see zepp-os-fundamentals. Phone↔watch transport — see zepp-os-communication.
Three places to persist data — don't confuse them
| Mechanism | Where it lives | Value type | Shared with | Cleared |
|---|
settingsStorage | phone (Zepp app) | strings only | Settings App ↔ Side Service | on app removal |
@zos/storage LocalStorage [≥3.0] | watch | any (key-value) | device app only | on Mini Program uninstall |
@zos/fs | watch | files | device app only | on uninstall |
settingsStorage is not on the watch and @zos/storage is not on the phone. To get a setting from the phone UI onto the watch you go: settings UI → settingsStorage → Side Service change listener → messaging → device (see zepp-os-communication).
Settings App (the phone config screen)
Entry setting/index.js calls AppSettingsPage({ state, build(props) { … } }). build returns UI built from hyperscript component functions (not JSX tags): View, Text, TextInput, Toggle, Select, Slider, Button, Image, Link, Section, Toast, Auth (OAuth), etc.
AppSettingsPage({
build(props) {
return View({ style: { padding: '16px' } }, [
TextInput({
label: 'Name',
onChange: (val) => props.settingsStorage.setItem('name', val),
}),
Toggle({
label: 'Enabled',
value: props.settingsStorage.getItem('enabled') === 'true',
onChange: (v) => props.settingsStorage.setItem('enabled', String(v)),
}),
])
},
})
- Read/write persisted config via
props.settingsStorage (getItem/setItem, strings).
- The Settings App is reactive to
settingsStorage — it re-renders on change; you do not add a change listener there.
- Components take a
style object (CSS-like) and event props (onChange, onClick).
settingsStorage bridge (Settings App ↔ Side Service)
Same store, two sides:
- Settings App:
props.settingsStorage.setItem(key, value) / getItem(key).
- Side Service:
settings.settingsStorage.getItem/setItem, plus addListener('change', ({ key, newValue, oldValue }) => …) to react to edits (only the Side Service needs the listener). Also removeItem, clear, toObject(), length.
This event system is the supported way for the Settings App and Side Service to communicate.
On-device storage (watch)
import { LocalStorage } from '@zos/storage'
const ls = new LocalStorage()
ls.setItem('test', 'value')
const v = ls.getItem('test')
const withDefault = ls.getItem('missing', 'fallback')
ls.removeItem('test'); ls.clear()
For files/larger blobs use @zos/fs (openSync/readSync/writeSync/statSync, Mini Programs write under /data) — full API in references/device-fs.md.
Common Mistakes
- Storing an object in
settingsStorage → values are strings; JSON.stringify on write, JSON.parse on read.
- Confusing
settingsStorage (phone) with @zos/storage (watch) → they're different stores on different devices and don't auto-sync. Bridge via messaging.
- Adding a
change listener in the Settings App → it's already reactive; the listener belongs in the Side Service.
- Forgetting
device:os.local_storage in app.json for @zos/storage.
- Importing
@zos/* device modules in the Settings App → it runs on the phone; it only has settings UI + settingsStorage.
Settings App UI template
Minimal setting/index.js skeleton — adapt sections/fields as needed:
AppSettingsPage({
state: {},
build(props) {
return View({ style: { padding: '16px' } }, [
Section({ title: 'General' }, [
TextInput({
label: 'Name',
value: props.settingsStorage.getItem('name') || '',
onChange: (v) => props.settingsStorage.setItem('name', v),
}),
Toggle({
label: 'Enabled',
value: props.settingsStorage.getItem('enabled') === 'true',
onChange: (v) => props.settingsStorage.setItem('enabled', String(v)),
}),
]),
])
},
})
Reminder: values are strings (JSON.stringify/parse for objects); don't add a change listener here — that belongs in the Side Service.
Reference