Für den Schlüssel-Wert-Speicher in Capacitor verwenden Sie @capacitor/preferences Für eine Handvoll kleiner Einstellungen ein SQLite-geschützter Schlüssel-Wert-Speicher für alles Größere oder Mehrfach, und den Schlüsselkasten oder den Keystore für Geheimnisse. Diese Anleitung vergleicht die verfügbaren Optionen auf Capacitor 8, zeigt funktionierende code für jede an und erklärt, wie Sie von einem auf das andere ohne Verlust von Benutzerdaten wechseln können.
Die meisten Apps verwenden letztendlich zwei davon gleichzeitig: Vorzüge oder SQLite für die Anwendungsstate und sichere Speicherung für den Authentifizierungstoken.
Die Optionen im Überblick
localStorage / IndexedDB |
@capacitor/preferences |
SQL-Schnell KeyValueStore |
@capgo/capacitor-data-storage-sqlite |
@capgo/capacitor-native-biometric setData |
|
|---|---|---|---|---|---|
| Unterstützt durch | Webview-Speicher | Einstellungen / SharedPreferences | SQLite-Datei | SQLite-Datei | Schlüsselkette / Keystore |
| Überlebt Speicherbereinigung | Keine Gewähr | Ja | Ja | Ja | Ja |
| Werttypen | Speicherungen (localStorage) | Strings | JSON-Werte, Zahlen, Boolesche Werte, Uint8Array |
Strings | Strings |
| Gutes Größenbereich | Klein | Klein, einige KB pro Wert | Große Werte, viele Schlüssel | Viele Schlüssel | Sehr klein (unter ~8 KB auf Android) |
| Verschlüsselung | Nein | Nein | Optional SQLCipher, Schlüssel aus sicherem Speicher | Optional SQLCipher, Passphrase in Konfiguration | Ja, hardware-gestützt |
| Namensräume | Pro Ursprung | group Option |
store Option |
Tabellen | Schlüsselnamen |
| Abfrage durch Präfix | No | No | List keys | filtervalues |
No |
| Web | Ja | localStorage |
SQLite Wasm (OPFS) | IndexedDB | Keine Geheimnisse |
Wieso 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 auch ändert die Ursprungsadresse, die auf einen anderen, leeren Speicher verweist.
Verwenden Sie sie als Cache, der verschwinden kann. Verwenden Sie eine der native-gestützten Optionen für alles andere.
Option 1: Capacitor Einstellungen für kleine Einstellungen
@capacitor/preferences ist das offizielle Plugin für leichte Schlüssel-Wert-Daten. Auf iOS schreibt es in UserDefaultsauf Android in SharedPreferencesauf der Web in 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, Einblendungsfähigkeit, das letzte ausgewählte Tab, Funktionstaster.
Verwenden Sie es nicht für:
- Geheime Daten. Werte werden in plaintext innerhalb des App-Sandbox gespeichert und sind in Geräte-Backup enthalten.
- Große Werte.
UserDefaultsundSharedPreferencesLaden Sie ihr ganzes Datei in den Speicher. Große JSON-Blobs verlangsamen jede Lese- und Schreiboperation. - Viele Schlüssel müssen Sie durch Präfix auflisten oder löschen.
keys()Rückgabewert ist alles, sodass Sie in JavaScript filtern.
Preferences.configure({ group: 'MyApp' }) Ändert den Namensraum, unter 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-Schlüssel-Wert-Speicher
@capgo/capacitor-fast-sql Einschließlich KeyValueStore Klasse auf Basis seiner SQLite-Verbindung. Es erstellt ein __kv_store Tabelle, behält den Werttyp bei und unterstützt mehrere benannte Speicher in einer Datenbank.
bun add @capgo/capacitor-fast-sql
bunx cap sync
Schnell SQL benötigt zwei native Einstellungen (iOS lokale Netzwerke in Info.plistSQL-Schlüssel-Wert-Speicher benötigt zwei native Einstellungen (iOS lokale Netzwerke in How to use SQLite in a Capacitor app.
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 zurück) null (wenn fehlt) has, remove, clear, keys, close.
Zwei Muster, die man kennen sollte:
Viele Speicher, eine Datenbank. Die store Optionen-Namenräume Schlüssel, also settings, drafts und api-cache Kann leben Seite an Seite und kann unabhängig gelöscht werden.
Nächstes Schlüssel-Wert neben echten Tabellen. Wenn Ihre App bereits die Fast SQL für relationale Daten verwendet, sollten Sie die Verbindung wieder verwenden, 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 Schlüssel-Wert-Blob in etwas wächst, das Sie abfragen möchten (z. B. alle Entwürfe älter als eine Woche), können Sie es in eine richtige Tabelle in derselben Datenbank verschieben.
Verschlüsselte Schlüssel-Wert-Speicherung
KeyValueStore.open nimmt die gleichen Optionen wie FastSQL.connect, einschließ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 native Builds. Die Einrichtung, plus, was zu tun ist, wenn die Schlüssel nach einem Backup-Wiederherstellung verloren geht, ist in Wie man eine SQLite-Datenbank verschlüsselt in Capacitor.
@capgo/capacitor-Daten-Speicher-SQLite
@capgo/capacitor-data-storage-sqlite ist ein dedizierter Schlüssel-Wert-Plugin auf SQLite (ursprünglich von Jean Pierre Quéau, jetzt von Capgo gepflegt). Werte sind Zeichenketten, und es fügt ein paar 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 Mustertext auf der Schlüssel (note% für ein Präfix, %note Für einen Suffix, einfaches Text für enthält). Das Muster wird in die SQL-Anweisung eingefügt, daher sollten Sie nur Filter übergeben, die Sie kontrollieren, nie rohes Benutzerinput.
Im Web verwendet es IndexedDB über localforage, das Sie separat installieren müssen:
bun add localforage
Über seine Verschlüsselung: openStore({ encrypted: true, mode: 'secret' }) verwendet SQLCipher mit einem Passwort von capacitor.config unter plugins.CapgoCapacitorDataStorageSqlite.encryptionSecret. Dieses 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 eine oberflächliche Dateiinspektion, nicht gegen jemanden, der Ihre App auseinanderbaut. Für echte Geheimnisse verwenden Sie einen Schlüssel aus der Schlüsselkette oder dem Keystore, wie im Beispiel von Fast SQL oben.
Fast SQL KeyValueStore oder data-storage-sqlite?
- Wählen Sie Rapid SQL
KeyValueStorefalls Sie typisierte Werte ohne manuelles JSON, binäre Werte, eine Laufzeitverschlüsselungsschlüssel oder bereits Fast SQL für Tabelle verwenden möchten. - Wählen Sie datenspeicher-sqlite Wenn Sie die Tabelle und Filterfunktionen, die JSON-Export- und -Importfunktionen oder die Electron-Unterstützung benötigen.
Option 3: Schlüsselkette und Keystore für Geheimnisse
Auth-Tokens, Refresh-Tokens, API-Schlüssel und Datenbankverschlüsselungsschlüssel sollten in der Plattform-Sicherungsstorage gespeichert werden. @capgo/capacitor-native-biometric (8.6.0 und später) bietet eine allgemeine Schlüssel-Wert-API auf der Basis des iOS-Schlüsselkastens und des Android-Keystores:
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-Keystore-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. Unsere Beitrag zu sicherer Speicherung für Offline-Tokens geht tiefer in die Token-Verwaltung ein.
Denken Sie daran, dass iOS-Schlüsselkasten-Einträge nach dem Entfernen einer App überleben können. Beim ersten Start nach einer frischen Installation löschen Sie veraltete Geheimnisse, wenn Ihre App eine saubere Oberfläche erwartet (speichern Sie einen „erstes Mal durchgeführt“-Flag in Vorzugs-Einstellungen, das bei der Entfernung der App entfernt wird, und löschen Sie Schlüsselkasten-Einträge, wenn es fehlt).
Wählen Sie: Eine Entscheidungsliste
- Handelt es sich um ein Geheimnis? Token, Passwort, PIN, Schlüssel. Verwenden Sie Keychain- oder Keystore-Speicher.
- Ist es ein paar kleine Einstellungen? Benutzen Sie die Vorlieben.
- Ist es viele Einträge, große JSON, Binärdaten oder Cache, den Sie löschen und in Gruppen ablaufen lassen möchten? Benutzen Sie einen SQLite-Speicher für Schlüssel-Wert-Paare.
- Brauchen Sie Filter, Sortierung oder eine Verbindung? It is not key-value data anymore. Create a table, see the SQLite-Anleitung oder verwenden Sie einen typisierten Layer wie Kysely .
Migrieren Sie bestehende Daten zwischen Speichern
Von localStorage Vorlieben zu einem SQLite-Speicher ist eine einmalige Kopie bei der Startzeit. Führen Sie sie vor der Lesezeit der App durch und dokumentieren Sie, dass sie durchgelaufen ist.
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 den sicheren Speicher kopiert werden. Das Belassen eines Tokens in den Vorlieben nach dem Verschieben in den Schlüsselkasten hält die ursprüngliche Exposition aufrecht.
Da dieser code in JavaScript läuft, können Sie ihn mit einem Capgo live update. Das SQLite-Plugin selbst ist native, daher benötigt die Veröffentlichung, die es hinzufügt, eine Speicherbaustelle. Versenden Sie das Plugin zuerst, dann die Migration code.
Schulung und Support
Die Vorliebenwerte sind null nach einer Aktualisierung im Web. Die Ursprungsmethode wurde geändert (Port, Hostname oder Schemes). localStorage ein anderer, leerer Speicher.
Rapid SQL KeyValueStore.open werfen Sie auf iOS. Der lokale HTTP-Kanal ist blockiert. Fügen Sie NSAllowsLocalNetworking zu Info.plist und das native App neu erstellen.
get eine Zeichenkette zurückgibt, an der Sie ein Objekt in der Datenbank erwartet haben. Dieser Plugin speichert nur Zeichenketten. JSON.parse den Wert.
Geheimnisse fehlen nach Wiederherstellung eines Backups auf einem neuen Telefon. Keystore-Schlüssel und Geräte-spezifische Keychain-Elemente werden nicht auf neue Hardware übertragen. Behandeln Sie die sichere Speicherung als eine Cache von Anmeldeinformationen, die Sie erneut abrufen können, indem Sie sich erneut anmelden.
Einstellungen werden nach Neuanmeldung verloren, aber Tokens sind auf iOS noch vorhanden. Erwartet: Die Vorlieben werden mit der App gelöscht, Keychain-Elemente können bleiben. Verwenden Sie das oben genannte Muster für die erste Anwendung.
Zusammenfassung
- Einstellungen: kleine, nicht-sensitive Einstellungen.
- SQLite-Speicher (Schnell SQL
KeyValueStoreoder@capgo/capacitor-data-storage-sqlitevielen oder großen Werten, Cache, Entwürfen, optional verschlüsselt. - Schlüsselkette oder Keystore (
@capgo/capacitor-native-biometricsetDataGeheimnisse und Verschlüsselungsschlüssel.
Plugin-Verweise: Fast SQL-Dokumentation, Daten-Speicherung-SQLite-Dokumentation, und das native biometrische Plugin-Seite.