Für den Schlüssel-Wert-Speicher in Capacitor verwenden Sie @capacitor/preferences Für einige wenige kleine Einstellungen einen SQLite-gestützten Schlüssel-Wert-Speicher, für alles Größere oder Mehrfaches die Schlüsselkette oder den Keystore für Geheimnisse. Diese Anleitung vergleicht die verfügbaren Optionen auf Capacitor 8, zeigt funktionierende code für jeden und erklärt, wie Sie von einem auf einen anderen ohne Verlust von Benutzerdaten wechseln können.
Die meisten Apps verwenden letztendlich zwei davon gleichzeitig: Einstellungen oder SQLite für den Anwendungsstatus und sichere Speicherung für den Authentifizierungs-Token.
Die Optionen im Überblick
localStorage / IndexedDB |
@capacitor/preferences |
SQL-Datenbank KeyValueStore |
@capgo/capacitor-data-storage-sqlite |
@capgo/capacitor-native-biometric setData |
|
|---|---|---|---|---|---|
| Unterstützt durch | Speicherung in der WebView | Benutzereinstellungen / SharedPreferences | SQLite-Datei | SQLite-Datei | Schlüsselkette / Keystore |
| Überlebt den Speicherbereinigung des Betriebssystems | Keine Garantie | Ja | Ja | Ja | Ja |
| Werttypen | Zeichenketten (localStorage) | Zeichenketten | JSON-Werte, Zahlen, Boolesche Werte, Uint8Array |
Zeichenketten | Zeichenketten |
| Eine gute Größe | Klein | Klein, einige KB pro Wert | __CAPGO_KEEP_0__ große Werte, viele Schlüssel | Viele Schlüssel | Sehr klein (unter ~8 KB auf Android) |
| Encryption | No | No | Optional SQLCipher, Schlüssel aus sicherem Speicher | Optional SQLCipher, Passwort in Konfiguration | __CAPGO_KEEP_0__ Ja, hardware-gestützt |
| Namespaces | Pro Origin | group option |
store Option |
Tabellen | Schlüsselnamen |
| Nach Präfix suchen | Nein | Nein | List keys | filtervalues |
Nein |
| Web | Ja | localStorage |
SQLite Wasm (OPFS) | IndexedDB | Not für Geheimnisse |
Warum nicht localStorage
localStorage and IndexedDB work inside a Capacitor WebView, but the data belongs to the WebView, not to your app’s native storage. The OS can reclaim WebView storage when the device runs low on space, and Capacitor’s own documentation recommends against relying on it for data you cannot lose. Changing the app’s hostname or scheme in capacitor.config Verwende sie als Cache, der verschwinden kann. Verwende eine der native-gestützten Optionen für alles andere.
Verwenden Sie sie als Cache, der verschwinden kann. Verwenden Sie eine der native-gestützten Optionen für alles andere.
Option 1: Capacitor Preferences for small settings
@capacitor/preferences ist das offizielle Plugin für leichte Schlüssel-Wert-Daten. Auf iOS schreibt es in UserDefaultsauf der Web in SharedPreferencesauf der Webplattform localStorage.
bun add @capacitor/preferences
bunx cap sync
import { Preferences } from '@capacitor/preferences';
interface Settings {
theme: 'light' | 'dark' | 'system';
fontScale: number;
}
const DEFAULTS: Settings = { theme: 'system', fontScale: 1 };
export async function loadSettings(): Promise<Settings> {
const { value } = await Preferences.get({ key: 'settings' });
return value ? { ...DEFAULTS, ...JSON.parse(value) } : DEFAULTS;
}
export async function saveSettings(settings: Settings): Promise<void> {
await Preferences.set({ key: 'settings', value: JSON.stringify(settings) });
}
Verwenden Sie es für: Thema, Sprache, Einstellungen für die Einrichtung, den letzten ausgewählten Tab, Funktionstasten.
Option 2: __CAPGO_KEEP_0__ SQLite für größere Datenmengen
- Secrets. Werte werden in plaintext innerhalb des App-Sandboxes gespeichert und sind in Geräte-Backup-Dateien enthalten.
- Große Werte.
UserDefaultsundSharedPreferencesladen ihren gesamten Dateiinhalt in den Arbeitsspeicher. Große JSON-Blobs verlangsamen jeden Lesen und Schreiben. - Viele Schlüssel, die Sie auflisten oder durch Präfix löschen müssen.
keys()erstellt alles zurück, sodass Sie in JavaScript filtern müssen.
Preferences.configure({ group: 'MyApp' }) ändert den Namensraum, in dem die Schlüssel gespeichert sind. Der Standardgruppe ist CapacitorStorage.
Option 2: Ein SQLite-Schlüssel-Wert-Speicher
Einmal Sie API-Caches, Entwürfe, Offline-Queues oder Hunderte von Einträgen gespeichert haben, ist ein SQLite-Datei ein besseres Zuhause. Es handhabt große Werte, Schreibvorgänge sind atomar und Sie können es verschlüsseln.
SQL-Datenbank-Schlüssel-Wert-Speicher
@capgo/capacitor-fast-sql einschließt eine KeyValueStore Klasse auf der oberen Ebene seiner SQLite-Verbindung. Es erstellt eine __kv_store table, behält die Wertetypen bei und unterstützt mehrere benannte Speicher in einer Datenbank.
bun add @capgo/capacitor-fast-sql
bunx cap sync
Fast SQL benötigt zwei native Einstellungen (iOS lokale Netzwerke in Info.plist, eine localhost-Textregel auf Android). Sie werden in "Wie man SQLite in einer Capacitor-App verwendet".
import { KeyValueStore } from '@capgo/capacitor-fast-sql';
const cache = await KeyValueStore.open({ database: 'app', store: 'api-cache' });
// Objects, arrays, numbers, booleans, null and Uint8Array are stored as-is
await cache.set('user:42', { id: 42, name: 'Ada', roles: ['admin'] });
await cache.set('lastSync', Date.now());
const user = (await cache.get('user:42')) as { id: number; name: string } | null;
const exists = await cache.has('lastSync');
const allKeys = await cache.keys();
await cache.remove('user:42');
await cache.clear(); // only clears the 'api-cache' store
await cache.close();
API-Zusammenfassung: open(options), fromConnection(connection, store), set, get (gibt null wenn fehlend), has, remove, clear, keys, close.
Zwei Muster, die man kennen sollte:
Viele Speicher, eine Datenbank. Die store Optionen räumen die Namensräume auf, so dass settings, drafts und api-cache können nebeneinander leben und unabhängig voneinander gelöscht werden.
Wertepaar neben echten Tabellen. Wenn Ihre App bereits mit Fast SQL für relationale Daten arbeitet, sollten Sie die Verbindung wiederholen, anstatt eine zweite zu öffnen:
import { FastSQL, KeyValueStore } from '@capgo/capacitor-fast-sql';
const db = await FastSQL.connect({ database: 'app' });
const drafts = await KeyValueStore.fromConnection(db, 'drafts');
// You own `db`: drafts.close() does not disconnect it
Später, wenn ein Wertepaar-Wertobjekt in etwas wächst, das Sie befragen möchten (z. B. alle Entwürfe älter als eine Woche), können Sie es in eine richtige Tabelle in derselben Datenbank verschieben.
Verschlüsselter Wertepaar-Speicher
KeyValueStore.open nimmt die gleichen Optionen wie FastSQL.connecteinschließlich encrypted und encryptionKey auf iOS und Android:
import { KeyValueStore } from '@capgo/capacitor-fast-sql';
import { NativeBiometric } from '@capgo/capacitor-native-biometric';
async function getKey(): Promise<string> {
const { isSaved } = await NativeBiometric.isDataSaved({ key: 'kv.key' });
if (isSaved) return (await NativeBiometric.getData({ key: 'kv.key' })).value;
const bytes = crypto.getRandomValues(new Uint8Array(32));
const key = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
await NativeBiometric.setData({ key: 'kv.key', value: key });
return key;
}
const secureStore = await KeyValueStore.open({
database: 'secure-kv',
encrypted: true,
encryptionKey: await getKey(),
});
Dies erfordert SQLCipher in den nativen Builds. Die Einrichtung, plus, was zu tun ist, wenn die Schlüssel nach einem Backup-Wiederherstellungsprozess verloren gehen, ist in Wie man eine SQLite-Datenbank verschlüsselt in Capacitor.
in @capgo/capacitor-data-storage-sqlite
@capgo/capacitor-data-storage-sqlite ist ein dediziertes Schlüssel-Wert-Plugin auf SQLite (ursprünglich von Jean Pierre Quéau, jetzt von Capgo) gepflegt. Werte sind Zeichenketten, und es fügt einige Extras hinzu: mehrere Tabellen pro Speicher, Präfix- und Suffix-Filterung und JSON-Import- und -Export.
bun add @capgo/capacitor-data-storage-sqlite
bunx cap sync
import { CapgoCapacitorDataStorageSqlite as Store } from '@capgo/capacitor-data-storage-sqlite';
await Store.openStore({ database: 'appStore', table: 'settings' });
await Store.set({ key: 'locale', value: 'fr' });
await Store.set({ key: 'profile', value: JSON.stringify({ name: 'Ada' }) });
const { value } = await Store.get({ key: 'locale' });
const { result: hasProfile } = await Store.iskey({ key: 'profile' });
const { keys } = await Store.keys();
// Switch table inside the same store
await Store.setTable({ table: 'drafts' });
const { values } = await Store.filtervalues({ filter: 'note%' }); // values whose key starts with "note"
await Store.remove({ key: 'note-1' });
await Store.clear(); // clears the current table
filtervalues wirkt den Filter als SQL LIKE Muster auf dem Schlüssel (note% für ein Präfix, %note für ein Suffix, plain Text für enthält). Das Muster wird in die SQL-Zeichenkette eingefügt, also passen Sie nur Filter, die Sie kontrollieren, nie Rohdaten von Benutzern.
Auf dem Web verwendet es IndexedDB über localforagewelches Sie separat installieren:
bun add localforage
Über seine Verschlüsselung: openStore({ encrypted: true, mode: 'secret' }) verwendet SQLCipher mit einem Passwort von capacitor.config unter plugins.CapgoCapacitorDataStorageSqlite.encryptionSecretDas Passwort wird in Ihrem App-Bundle verschifft, und wenn Sie es nicht setzen, fällt der Plugin auf ein eingebautes Standard zurück. Behandeln Sie dies als Schutz gegen zufällige Datei-Inspektion, nicht gegen jemanden, der Ihre App auseinandernimmt. Für echte Geheimnisse verwenden Sie einen Schlüssel aus der Keychain oder Keystore, wie im Beispiel von Fast SQL oben.
Fast SQL KeyValueStore oder data-storage-sqlite?
- Wählen Sie Schnell SQL
KeyValueStoreWenn Sie getippte Werte ohne manuelles JSON, binäre Werte, eine Laufzeitverschlüsselungsschlüssel oder bereits Schnell SQL für Tabellen verwenden möchten. - Wählen Sie daten-speicher-sqlite Wenn Sie die Tabelle und Filterfunktionen, die JSON-Export- und -Importfunktionen oder die Electron-Unterstützung benötigen.
Option 3: Schlüsselkette und Schlüsselkasten für Geheimnisse
Auth-Tokens, Refresh-Tokens, API-Schlüssel und Datenbankverschlüsselungsschlüssel sollten in der Plattform-Sicherheitspeicherung gespeichert werden. @capgo/capacitor-native-biometric (8.6.0 und später) bietet eine generische Schlüssel-Wert-API auf der Basis der iOS-Schlüsselkette und Android-Schlüsselkasten:
bun add @capgo/capacitor-native-biometric
bunx cap sync
import { AccessControl, NativeBiometric } from '@capgo/capacitor-native-biometric';
// Silent read and write
await NativeBiometric.setData({ key: 'session.refreshToken', value: token });
const { value: refreshToken } = await NativeBiometric.getData({ key: 'session.refreshToken' });
// Require Face ID / Touch ID / fingerprint to read
await NativeBiometric.setData({
key: 'wallet.pin',
value: pin,
accessControl: AccessControl.BIOMETRY_ANY,
});
const { value: secretPin } = await NativeBiometric.getSecureData({
key: 'wallet.pin',
reason: 'Confirm it is you',
});
await NativeBiometric.deleteData({ key: 'session.refreshToken' });
Halten Sie die Werte klein. Die Plugin-Dokumentation besagt, dass die Android-Schlüsselkasten-gestützte Verschlüsselung am besten unter etwa 8 KB pro Wert funktioniert. Wenn Sie viel Daten schützen müssen, speichern Sie einen zufälligen Schlüssel hier und verwenden Sie ihn, um eine SQLite-Datenbank zu verschlüsseln. Unser Beitrag zu sicherer Speicherung für Offline-Tokens geht tiefer in die Token-Verwaltung ein.
Denken Sie daran, dass Keychain-Einträge auf iOS länger leben können als eine App-Entfernung. Beim ersten Start nach einer frischen Installation, löschen Sie veraltete Geheimnisse, wenn Ihre App eine saubere Tafel erwartet (speichern Sie ein "erstes Mal durchgeführt"-Flag in Vorzugsstellungen, das bei der Entfernung entfernt wird, und löschen Sie Keychain-Einträge, wenn es fehlt).
Wählen Sie: eine Entscheidungsliste
- Ist es ein Geheimnis? Token, Passwort, PIN, Schlüssel. Verwenden Sie Keychain- oder Keystore-Speicher.
- Ist es ein paar kleine Einstellungen? Verwenden Sie Vorzugsstellungen.
- Ist es viele Einträge, große JSON, binäre Daten oder einen Cache, den Sie in Gruppen löschen und ablaufen lassen möchten? Verwenden Sie einen SQLite-Speicher für Schlüssel-Wert-Paare.
- Brauchen Sie Filter, Sortierung oder eine Verbindung? Es ist keine Key-Value-Datenbank mehr. Erstellen Sie eine Tabelle, sehen Sie sich an. SQLite-Leitfaden , oder verwenden Sie einen getypten Layer wie Abfrage.
Migrieren von bestehenden Daten zwischen Speichern
Von localStorage or Preferences to a SQLite store is a one-time copy at startup. Do it before the rest of the app reads data, and record that it ran.
import { Preferences } from '@capacitor/preferences';
import { KeyValueStore, type KeyValueValue } from '@capgo/capacitor-fast-sql';
export async function migrateToSqliteStore(): Promise<KeyValueStore> {
const kv = await KeyValueStore.open({ database: 'app', store: 'settings' });
if (await kv.has('__migrated_v1')) return kv;
const { keys } = await Preferences.keys();
for (const key of keys) {
const { value } = await Preferences.get({ key });
if (value === null) continue;
let parsed: KeyValueValue = value;
try {
parsed = JSON.parse(value) as KeyValueValue;
} catch {
// keep plain strings as strings
}
await kv.set(key, parsed);
}
// Also copy from localStorage if older versions used it
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key && !(await kv.has(key))) {
await kv.set(key, localStorage.getItem(key));
}
}
await kv.set('__migrated_v1', true);
// Remove the old copies only after a release or two, once you are confident
return kv;
}
Entfernen Sie Geheimnisse aus dem alten Speicher, sobald sie in sichere Speicherung kopiert wurden. Bleiben Sie ein Token in Einstellungen nach dem Umzug in die Schlüsselkette, um die ursprüngliche Exposition.
Da diese code in JavaScript läuft, können Sie es mit einem Capgo live update ausliefern. Der SQLite-Plugin selbst ist native, daher benötigt die Release, die es hinzufügt, eine Speicherbaustelle. Versenden Sie das Plugin zuerst, dann die Migration code.
Fehlerbehebung
Einstellungen sind null nach einer Aktualisierung im Web. Die Ursprungsadresse wurde (Port, Hostname oder Scheme) geändert, also localStorage ist ein anderer, leerer Speicher.
Schnelles SQL KeyValueStore.open wirft auf iOS. Der lokale HTTP-Kanal ist blockiert. Fügen Sie NSAllowsLocalNetworking zu Info.plist und bauen Sie die native App neu.
get gibt eine Zeichenkette zurück, an der Sie ein Objekt in data-storage-sqlite erwartet haben. Dieser Plugin speichert nur Zeichenketten. JSON.parse den Wert.
Geheime Daten fehlen nach Wiederherstellung eines Backups auf einem neuen Telefon. Keystore-Schlüssel und Geräte-schlechte Keychain-Elemente werden nicht auf neue Hardware übertragen. Behandeln Sie die sichere Speicherung als eine Cache von Anmeldeinformationen, die Sie erneut durch Anmeldung wiederherstellen können.
Einstellungen verloren nach Neuinstallation, aber Token sind auf iOS noch vorhanden. Erfahrung: Die Einstellungen werden mit der App gelöscht, Schlüsseltaste-Elemente können bleiben. Verwenden Sie das oben stehende Flag-Muster für die ersten Starts.
Zusammenfassung
- Einstellungen: kleine, nicht sensitive Einstellungen.
- SQLite-Speicher für Schlüssel-Werte (Schnell SQL)
KeyValueStoreoder@capgo/capacitor-data-storage-sqliteViele oder große Werte, Cache, Entwürfe, optional verschlüsselt. - SQLite-Speicher für Schlüssel-Werte (Schnell SQL) oder
@capgo/capacitor-native-biometricsetDataGeheimnisse und Verschlüsselungsschlüssel.
Schlüsselkette oder Keystore ( Schnelles SQL, Daten-Speicherung-SQLite-Dokumentation, und das native biometrischer Plugin-Seite.