Skip to main content

Implementieren sicherer Offline-Speicherung mit SmartStore

Lernziele

Nachdem Sie diese Lektion abgeschlossen haben, sind Sie in der Lage, die folgenden Aufgaben auszuführen:

  • Erläutern der grundlegenden SmartStore-Begriffe und -Konzepte
  • Verwenden von SmartStore zum Ausgeben von SELECT-Abfragen
  • Registrieren, Auffüllen und Verwalten von SmartStore-Daten auf der bevorzugten Zielplattform (iOS, Android, hybrid, React Native)
  • Verwenden von SmartStore Inspector

Verwenden von SmartStore für die Offline-Speicherung

Die Verbindung von mobilen Geräten kann jederzeit verloren gehen. In Umgebungen wie Krankenhäusern und Flugzeugen sind Verbindungen sogar oftmals verboten. Für solche Situationen ist es wichtig, dass Ihre mobilen Anwendungen weiterhin funktionieren, wenn sie offline gehen. 

Das Mobile SDK umfasst SmartStore, eine sichere Multithread-Lösung für die Offline-Speicherung in mobilen Geräten. Mit SmartStore können Ihre Kunden ihre Daten in einer sicheren Umgebung weiter bearbeiten - auch ohne Verbindung des Geräts. Wenn Sie SmartStore mit Mobile Sync koppeln, können Sie lokale SmartStore-Daten problemlos mit dem Salesforce-Server synchron halten, sobald die Verbindung wieder hergestellt ist.

SmartStore speichert Daten als JSON-Dokumente in einer einfachen Datenbank mit einer einzigen Tabelle. Sie können SmartStore-Daten entweder mit den Mobile SDK-Hilfsmethoden oder mit benutzerdefinierten Abfragen unter Verwendung der Smart SQL-Sprache von SmartStore abrufen.

Soups

SmartStore speichert Offlinedaten in logischen Abschnitten, sogenannten Soups. Ein SmartStore-Soup steht für eine einzelne Tabelle in der vorliegenden SQLite-Datenbank bzw. store und ist in der Regel einem standardmäßigen oder benutzerdefinierten Salesforce-Objekt zugeordnet. Soups enthalten Soup-Elemente. Jedes Element ist ein JSON-Objekt, das eine einzelne Datenbankzeile darstellt. Zur Rationalisierung des Datenzugriffs definieren Sie Indizes für jeden Soup. Diese Indizes verwenden Sie zum Abfragen des Soup, entweder nach den SmartStore-Hilfsmethoden oder mit Smart SQL, der Abfragesprache von SmartStore. SmartStore-Indizes erleichtern zudem die Arbeit durch Unterstützung von Volltextsuchabfragen.

Sie können sich Soups als Tabellen vorstellen und Stores als Datenbanken. Dabei können Sie in einer Anwendung so viele Soups festlegen, wie Sie möchten. Als eigenständige Datensets verfügen Soups über keine vorkonfigurierten Beziehungen zueinander, aber Sie können Smart SQL-Joins verwenden, um eine Abfrage für alle zu starten. In nativen Anwendungen können Sie auch in mehrere Soups in einer Transaktion schreiben.

Hinweis

SmartStore-Daten sind flüchtig. In den meisten Fällen ist die Lebensdauer an den authentifizierten Benutzer und die Status der OAuth-Token gebunden. Wenn sich der Benutzer von der Anwendung abmeldet, löscht SmartStore alle Soup-Daten für den betreffenden Benutzer. Wenn das OAuth-Aktualisierungstoken widerrufen wird oder abläuft, wird der Anwendungsstatus des Benutzers zurückgesetzt und alle Daten in SmartStore werden gelöscht. Bedenken Sie bei der Entwicklung Ihrer Anwendung, dass SmartStore-Daten flüchtig sind, insbesondere dann, wenn in der Organisation eine kurze Lebensdauer für das Aktualisierungstoken festgelegt ist.

Smart SQL

SmartStore unterstützt die Abfragesprache Smart SQL für frei formulierbare SELECT-Anweisungen. Es werden nur SELECT-Anweisungen unterstützt. Smart SQL kombiniert die gesamte SQL SELECT-Grammatik mit besonderer Syntax zum Verweisen auf Soups und Soup-Felder. Diese Vorgehensweise bietet maximale Steuermöglichkeiten und Flexibilität, z. B. die Möglichkeit, Joins zu verwenden.

Syntax

Die Syntax entspricht der normalen SQL SELECT-Spezifikation mit den folgenden Anpassungen:

Verwendung Syntax
Angeben einer Spalte {<soupName>:<path>}
Angeben einer Tabelle {<soupName>}
Verweisen auf die gesamte JSON-Zeichenfolge eines Soup-Eintrags {<soupName>:_soup}
Verweisen auf die interne eines Soup-Eintrags-ID {<soupName>:_soupEntryId}
Verweisen auf das Datum der letzten Änderung {<soupName>:_soupLastModifiedDate}

Beispielabfragen

Betrachten Sie zwei Soups: eine namens "Employees", und eine namens "Departments". Die Employees-Soup enthält Standardfelder wie:

  • Vorname (firstName)
  • Nachname (lastName)
  • Abteilungscode (deptCode)
  • Mitarbeiter-ID (employeeId)
  • Manager-ID (managerId)

Die Departments-Soup enthält:

  • Name (name)
  • Abteilungscode (deptCode)

Nachstehend finden Sie einige Beispiele für einfache Smart SQL-Abfragen mit diesen Soups:

select {employees:firstName}, {employees:lastName} 
 from {employees} order by {employees:lastName}
select {departments:name} 
 from {departments} 
 order by {departments:deptCode}

Joins

Smart SQL ermöglicht auch die Verwendung von Joins. Beispiel:

select {departments:name}, {employees:firstName} || ' ' || {employees:lastName}  
 from {employees}, {departments}  
 where {departments:deptCode} = {employees:deptCode}  
 order by {departments:name}, {employees:lastName}

Sie können sogar Self-Joins verwenden:

select mgr.{employees:lastName}, e.{employees:lastName}  
 from {employees} as mgr, {employees} as e  
 where mgr.{employees:employeeId} = e.{employees:managerId}
Hinweis

Bei einem JSON1-Index benötigt ein Join eine etwas erweiterte Syntax. Beispiel: statt

select {soup1:path1} from {soup1}, {soup2}

verwenden Sie

select {soup1}.{soup1:path1} from {soup1}, {soup2}

Aggregatfunktionen

Smart SQL unterstützt die Verwendung von Aggregatfunktionen wie:

  • COUNT
  • SUM
  • AVG

Beispiel:

select {account:name}, 
    count({opportunity:name}),
    sum({opportunity:amount}),
    avg({opportunity:amount}),
    {account:id},
    {opportunity:accountid} 
 from {account},
    {opportunity} 
 where {account:id} = {opportunity:accountid} 
 group by {account:name}

Registrieren einer Soup

Sie müssen eine Soup registrieren, damit Sie sie nutzen können. Wenn die Soup nicht vorhanden ist, wird sie bei der Registrierung erstellt. Wenn sie vorhanden ist, erhalten Sie durch die Registrierung Zugriff auf die Soup. Erstellen Sie zum Registrieren von Soups eine JSON-Konfigurationsdatei und laden Sie sie zur Laufzeit. Mithilfe einer einzigen Konfigurationsdatei können Sie alle Soups Ihrer Anwendung definieren. Das Mobile SDK unterstützt Konfigurationsdateien in nativen und hybriden Anwendungen.

Konfigurationsdateien registrieren Soups nur im Standard-Store "User" oder im Standard-Store "Global". Um andere benannte Stores oder externe Stores zu verwenden, können Sie Soups nur mittels SmartStore-APIs registrieren. Das Mobile SDK stellt Methoden zur Verfügung, um den Namen und die Indizes einer Soup zu definieren und sie dann zu registrieren.

Beim Registrieren einer Soup erstellen Sie eine leere benannte Struktur im Arbeitsspeicher, die Daten erwartet. Die Soup wird normalerweise mit Daten aus einer Salesforce-Organisation initialisiert. Verwenden Sie zum Abrufen der Salesforce-Daten den normalen REST-Anforderungsmechanismus des Mobile SDK. Extrahieren Sie die Daten nach dem Empfang einer REST-Antwort aus dem Antwortobjekt und übernehmen Sie die Daten in die Soup.

Bei der Soup-Erstellung können Fehler auftreten. Dafür kommen verschiedene Ursachen infrage, z. B.:

  • Ungültiger oder fehlerhafter Soup-Name
  • Kein Index (mindestens ein Index muss angegeben werden)
  • Andere unerwartete Fehler, z. B. ein Datenbankfehler

Struktur einer Soup

Um eine Soup zu definieren, geben Sie einen Soup-Namen und eine Liste von Indexspezifikationen an. Indizes basieren auf Soup-Feldern. Sie müssen nicht für jedes Feld, das Sie in der Soup speichern, eine Indexspezifikation angeben. Bei Verwendung einer Soup als einfacher Schlüssel/Wert-Speicher verwenden Sie beispielsweise eine einzelne Indexspezifikation des Typs string. Sobald die Soups erstellt sind, verwendet SmartStore die Indizes, um alle Einfüge-, Aktualisierungs- oder Löschvorgänge zu verfolgen.

SmartStore unterstützt die folgenden Indexdatentypen:

  • string
  • integer
  • floating
  • full_text
  • json1

Definieren von Indizes

In nativen und hybriden Anwendungen können Sie Soups mithilfe von Konfigurationsdateien registrieren und deren Indizes definieren. In React Native-Anwendungen verwenden Sie JavaScript-Code. In allen Fällen gelten einige Regeln.

  • Bei Indexpfaden wird Groß-/Kleinschreibung unterschieden. Sie können zusammengesetzte Pfade wie Owner.Name enthalten.
  • Indexeinträge, in denen ein in einem Indexspezifikations-Array angegebenes Feld fehlt, werden im betreffenden Index nicht nachverfolgt.
  • Der Typ des Index gilt nur für den jeweiligen Index. Wenn Sie ein indiziertes Feld abfragen (z. B. select {soup:path} from {soup}), gibt die Abfrage Daten des Typs zurück, der in der Indexspezifikation angegeben wurde.
  • Indexspalten können NULL-Felder enthalten.
  • Ab Mobile SDK 9.1 werden für Felder, die in SELECT- oder WHERE-Klauseln referenziert sind, keine Indexpfade mehr benötigt.
  • Sie können Indexpfade angeben, die auf interne Knoten (keine Blattknoten) zeigen. Sie können interne Pfade mit (Volltext)-Abfragen der Typen like und match verwenden. Wählen Sie den Typ string, wenn Sie interne Knotenpfade definieren. Ziehen Sie z. B. dieses Element in einer Soup namens "spies" in Erwägung:
    {  
       "first_name":"James",
       "last_name":"Bond",
       "address":{  
          "street_number":10,
          "street_name":"downing",
          "city":"london"
       }
     }
    In diesem Fall ist "address" ein interner Knoten, weil er untergeordnete Elemente hat. Über den Index für den Pfad "address" können Sie mit einer Abfrage des Typs like oder match den Wert "city" ("London") in "address" finden. Beispiel:
    SELECT {spies:first_name, spies:last_name} FROM spies WHERE {spies:address} LIKE 'london'

Format der Konfigurationsdatei

Hier ist ein theoretisches Beispiel einer JSON-Konfigurationsdatei, die zwei Soups (soup1 und soup2) definiert und den vollen Umfang von Indexdatentypen veranschaulicht.

{  "soups": [
    {
      "soupName": "soup1",
      "indexes": [
        { "path": "stringField1", "type": "string"},
        { "path": "integerField1", "type": "integer"},
        { "path": "floatingField1", "type": "floating"},
        { "path": "json1Field1", "type": "json1"},
        { "path": "ftsField1", "type": "full_text"}
      ]
    },
    {
      "soupName": "soup2",
      "indexes": [
        { "path": "stringField2", "type": "string"},
        { "path": "integerField2", "type": "integer"},
        { "path": "floatingField2", "type": "floating"},
        { "path": "json1Field2", "type": "json1"},
        { "path": "ftsField2", "type": "full_text"}
      ]
    }
  ]
 }

Weitere Informationen zum Registrieren von Soups mittels Code anstatt mittels Konfigurationsdateien finden Sie im Entwicklerhandbuch für das Salesforce Mobile SDK.

Hinweis

Wenn Ihr Code und Ihre Konfigurationsdatei beide eine Soup mit dem gleichen Namen registrieren, ignoriert das Mobile SDK die Definition in der Konfigurationsdatei.

Die folgende Konfigurationsdatei registriert eine einzelne Soup, die auf Account-Datensätzen basiert. Diese Soup indiziert die Felder für Name, ID und Inhaber-ID (übergeordnete ID). Soup-Namen müssen nicht mit dem Namen eines Salesforce-Quellobjekts übereinstimmen, aber eine offensichtliche Anspielung ist normalerweise hilfreich.

{  "soups": [
    {
      "soupName": "account",
      "indexes": [
        { "path": "Name", "type": "string"},
        { "path": "Id", "type": "string"},
        { "path": "OwnerId", "type": "string"}
      ]
    }
  ]
 }

Einfügen oder Aktualisieren von Soup-Einträgen

Zum Einfügen oder Aktualisieren von Soup-Einträgen (wobei SmartStore die jeweilige Aktion bestimmt) verwenden Sie eine upsert-Methode. Beispielsweise kann eine hybride Anwendung eine dieser JavaScript-Versionen verwenden:

navigator.smartStore.upsertSoupEntries(isGlobalStore, soupName, 
    entries[], successCallback, errorCallback)
navigator.smartStore.upsertSoupEntries(storeConfig, soupName, 
    entries[], successCallback, errorCallback)

Sie geben den Namen der Soup, ein Array von Einträgen, die als JSON-Zeichenfolgen formatiert sind, und optionale Erfolgs- und Fehlerrückruffunktionen an. Der einzige Unterschied dieser beiden Methoden ist der erste Parameter. Wenn Ihre Soup in einem benannten Benutzer- oder globalen Store vorhanden ist, verwenden Sie den storeConfig-Parameter, um den Typ des Stores und seinen Namen anzugeben. Beispiel:

{isGlobalStore:true, name:"AcmeSales"}

Wenn Sie den Standard-Store "Global" oder den Store "User" verwenden, können Sie einfach true übergeben, um einen globalen Store anzugeben. Andernfalls können Sie das Argument weglassen. Dieser Parameter ist optional und standardmäßig auf false festgelegt. Sie ist nicht in nativen Methoden vorhanden, die die gleichen Informationen aus zugehörigen Objekten lesen.

Abfragen und Verwalten von SmartStore

Das Mobile SDK für native iOS-Anwendungen bietet Factory-Methoden, die basierend auf Ihrer Eingabe "Abfragespezifikationsobjekte" erstellen. Die Factory-Methoden erstellen Abfragen basierend auf den folgenden WHERE-Operatoren:

  • = (Operator "genau")
  • LIKE
  • MATCH (Volltextsucherweiterung)
  • BETWEEN, <=, >= (Bereichsabfragen)
  • ALLE

Diese Abfrageobjekte verarbeiten einfache, unkomplizierte Abfragen und ersparen Ihnen die Mühe, diese selbst zu schreiben. Bei komplexeren Situationen können Sie Ihre eigene Smart SQL-Abfrage schreiben und an die Smart SQL-Factory-Methode übergeben. Nachdem Sie ein Abfrageobjekt erhalten haben, übergeben Sie es an eine Ausführungsmethode, um die angegebenen Soup-Daten abzurufen.

Verwalten einer Soup

Mitunter möchten Sie nicht genutzte Daten bereinigen oder die Leistung einer Soup verbessern, indem Sie ihre Indizes ändern. Für solche Aufgaben bietet SmartStore eine Reihe von Methoden, die Diagnose-, Wartungs- und Verwaltungsaufgaben ausführen. Mithilfe dieser Methoden können Sie Informationen über eine Soup oder einen Store abrufen, die Struktur einer Soup bearbeiten oder Soups und Stores löschen.

Genauer gesagt, ermöglichen diese Methoden Folgendes:

  • Ermitteln der Größe der zugrunde liegenden Datenbank
  • Ermitteln einer Liste aller Stores (Benutzer oder global)
  • Prüfen, ob eine Soup mit dem angegebenen Namen vorhanden ist
  • Abrufen der Spezifikationen einer Soup und ihres Indexes
  • Ändern der Konfiguration einer Soup
  • Neuindizieren einer Soup
  • Löschen aller Datensätze aus einer Soup
  • Entfernen einer Soup aus dem Store
  • Entfernen eines Stores
  • Entfernen aller Stores (Benutzer oder global)

Diese Methoden sind auf allen Plattformen für alle Anwendungstypen verfügbar.

Verwenden von SmartStore Inspector

Beim Testen ist es hilfreich festzustellen, ob der Code die SmartStore-Daten wie beabsichtigt verarbeitet. Der SmartStore Inspector stellt ein UI-Tool für diesen Zweck zur Verfügung. Sie können damit folgende Aufgaben erledigen:

  • Untersuchen von Soup-Metadaten, z. B. Soup-Namen und Indexspezifikationen einer beliebigen Soup
  • Löschen der Inhalte einer Soup
  • Durchführen von Smart SQL-Abfragen

Am einfachsten ist es, den SmartStore Inspector über das Dialogfeld "Dev Support" zu starten. 

Der Zugriff auf das Menü "Dev Support" hängt von Ihrer Entwicklungsumgebung ab. Um das Dialogfeld zu öffnen, wählen Sie eine der folgenden Optionen.

Android

Wählen Sie eine der folgenden Vorgehensweisen aus:

  • Wenn Ihre Anwendung im Android-Emulator ausgeführt wird, drücken Sie die Tastenkombination Befehlstaste+M (Mac) oder STRG+M (Windows).
  • Führen Sie an einer Systembefehls-Shell Folgendes aus: adb shell input keyevent 82

iOS

  • Verwenden Sie auf einem physischen Gerät die Schüttelgeste, um das Menü "Dev Support" aufzurufen, und wählen Sie dann SmartStore Inspector.
  • Wählen Sie im iOS-Simulator das Menüelement Hardware > Schüttelgeste aus oder drücken Sie die Tastenkombination ^+Befehlstaste+Z.

Verwenden von SmartStore in nativen iOS-Anwendungen

Das Hinzufügen des SmartStore-Moduls zu neuen nativen iOS-Anwendungen erfordert keinen zusätzlichen Aufwand. Jede native forceios-Anwendung, die Sie erstellen, bindet automatisch die SmartStore-Bibliothek ein.

Registrieren von Soups mit einer Konfigurationsdatei

Für native iOS-Anwendungen sucht das Mobile SDK unter / (oberste Ebene) im Bundle "Resources" nach Konfigurationsdateien.

  1. Fügen Sie Ihrem Projekt Konfigurationsdateien hinzu.
    1. Wählen Sie im Xcode-Projektnavigator den Projektknoten aus.
    2. Klicken Sie im Fenster "Editor" auf Build Phases.
    3. Erweitern Sie Copy Bundle Resources.
    4. Klicken Sie auf "+" (Elemente hinzufügen).
    5. Wählen Sie Ihre Soup-Konfigurationsdatei aus. Wenn Sie sich noch nicht in einem Xcode-Projektordner befinden:
      1. Um Ihre Datei in Finder auszuwählen, klicken Sie auf Add Other....
      2. Wenn Sie zum Erstellen von Gruppen aufgefordert werden, klicken Sie auf Finish.
  2. Fügen Sie für jede von Ihnen bereitgestellte Datei eine einzelne Codezeile hinzu.
    • Zum Laden einer userstore.json-Datei verwenden Sie eine der folgenden Möglichkeiten:
      SmartStoreSDKManager.shared().setupUserStoreFromDefaultConfig()
    • Zum Laden einer globalstore.json-Datei verwenden Sie eine der folgenden Möglichkeiten:
      SalesforceManager.shared().setupGlobalStoreFromDefaultConfig()

Füllen einer Soup

Beim Registrieren einer Soup erstellen Sie eine leere benannte Struktur im Arbeitsspeicher, die Daten erwartet. Um die Soup mit Daten aus Salesforce zu füllen, wird der normale REST-Anforderungsmechanismus zum Abrufen der Daten verwendet. Extrahieren Sie die Daten nach dem Empfang einer REST-Antwort aus dem Antwortobjekt und übernehmen Sie die Daten in die Soup. Einzelheiten zur Kodierung finden Sie im Beispiel am Ende dieses iOS-Abschnitts.

Abfragen von Soup-Daten

Unter iOS erstellen Sie Abfragespezifikationsobjekte, indem Sie Klassenmethoden für die SFQuerySpec-Klasse aufrufen. In Objective-C gibt es beispielsweise die newSmartQuerySpec:withPageSize:-Methode ein SFQuerySpec-Objekt zurück, das eine angegebene Smart SQL-Abfragezeichenfolge kapselt:

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select {account:Name} from {account}",
    pageSize: 10)

Der Page Size-Parameter bestimmt die Anzahl der Datensätze, die an jede Ergebnisseite gesendet werden. Diese Methoden bieten mehr Flexibilität als andere Factory-Abfragefunktionen, weil Sie eine eigene Smart SQL SELECT-Anweisung angeben können. Der folgende Code gibt z. B. eine Abfrage aus, die die SQL-Funktion COUNT aufruft: Da COUNT einen Einzelwert zurückgibt, ist die einzig mögliche Seitengröße 1.

Der folgende Code gibt eine Abfrage aus, die die SQL-Funktion COUNT aufruft: Da COUNT einen Einzelwert zurückgibt, ist die einzig mögliche Seitengröße 1.

Um eine Abfrage auszuführen, übergeben Sie Ihr SFQuerySpec-Objekt an die query()-Methode für das SFSmartStore-Objekt.

var querySpec = store.buildSmartQuerySpec(
    smartSql: "select count(*) from {employees}",
    pageSize: 1)

Verwalten einer Soup

Importieren Sie SSmartStore/SFSmartStore.h, wenn Sie Objective-C Soup-Verwaltungs-APIs in einer nativen iOS-Anwendung verwenden möchten. Sie rufen die Soup-Verwaltungsmethoden für eine gemeinsame SFSmartStore-Instanz auf. Sie können die gemeinsame Instanz mithilfe einer der folgenden SFSmartStore-Klassenmethoden ermitteln.

Feststellen der SmartStore-Instanz für den aktuellen Benutzer:

var store = SmartStore.shared(withName: storeName)

Feststellen der SmartStore-Instanz für einen bestimmten Benutzer:

var store = SmartStore.shared(withName: storeName, forUserAccount: user)

Rufen Sie beispielsweise die removeSoup:-Verwaltungsmethode auf:

self.store = [SFSmartStore sharedStoreWithName:kDefaultSmartStoreName];
 if ([self.store soupExists:@"Accounts"]) {
    [self.store removeSoup:@"Accounts"];
 }

Beispiel

In diesem Beispiel erstellen Sie eine Swift-Anwendung. Die native Swift-Vorlage für forceios beinhaltet bereits eine SmartStore-Implementierung, sodass ihre Einrichtung lediglich überprüft werden muss. 

  1. Erstellen Sie mithilfe von forceios ein natives Swift-Projekt, das dem folgenden Beispiel ähnelt:
    $ forceios create Enter your application type (native_swift or native, leave empty for native_swift):<Press RETURN>
    Enter your application name:<Enter any name you like>
    Enter your package name:com.myapps.ios
    Enter your organization name (Acme, Inc.):MyApps.com
    Enter output directory for your app (leave empty for the current directory):<Press RETURN or enter a directory name>
  2. Öffnen Sie die Datei .xcworkspace Ihrer Anwendung in Xcode.
  3. Blenden Sie im Projektordner Supporting Files ein.
  4. Öffnen Sie die Datei userstore.json und überprüfen Sie die SmartStore-Konfiguration.
  5. Um die Konfigurationsdatei zum Paket der kompilierten Anwendung hinzuzufügen, referenziert die Vorlage diese Dateien in den Projekteinstellungen.
    1. Wählen Sie im Xcode-Projektnavigator den obersten Projektknoten aus.
    2. Klicken Sie im Fenster "Editor" auf Build Phases.
    3. Erweitern Sie Copy Bundle Resources.
    4. Die Datei userstore.json muss in der Liste enthalten sein.
  6. Wählen Sie im Quellcodeordner Ihres Projekts Classes/SceneDelegate.swift aus.
  7. Suchen Sie in der scene(_:willConnectTo:options:)-Methode den Aufruf setupRootViewController().
  8. Um sehen zu können, wohin die SmartStore-Konfigurationsdateien geladen werden, klicken Sie bei gedrückter Strg-Taste auf setupRootViewController() und wählen Sie Jump to Definition (Zur Definition springen) aus.

So zeigen Sie die SmartStore-Konfiguration der Awendung zur Laufzeit an: 

  1. Starten Sie die Anwendung.
  2. Nachdem Sie sich erfolgreich bei der Anwendung angemeldet und sich autorisiert haben, zeigen Sie das Menü "Dev Tools" an.
    1. Geben Sie Kontrolltaste+Befehlstaste+Z ein, wenn Sie den iOS-Emulator verwenden, oder schütteln Sie Ihr iOS-Gerät.
    2. Klicken Sie auf Inspect SmartStore.
    3. Um Ihre Soups und die Menge der Datensätze aufzulisten, klicken Sie auf Soups.

Verwenden von SmartStore in nativen Android-Anwendungen

Standardmäßig enthalten alle nativen forcedroid-Anwendungen SmartStore- und Mobile Sync-Bibliotheken. Für ältere Android-Anwendungen sind aber eventuell einige benutzerdefinierte Setup-Schritte erforderlich.

  1. Öffnen Sie in Ihrem für Android erstellten Projekt die Datei MainApplication.java.
  2. Fügen Sie die folgende Importanweisung hinzu, falls sie nicht bereits vorhanden ist:
    import com.salesforce.androidsdk.mobilesync.app.MobileSyncSDKManager;
  3. Suchen Sie die Zeile mit dem Aufruf von initNative(). Beispiel:
    SalesforceSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);
  4. Wird initNative() für SalesforceSDKManager aufgerufen, ändern Sie SalesforceSDKManager in MobileSyncSDKManager:
    MobileSyncSDKManager.initNative(getApplicationContext(), new NativeKeyImpl(), MainActivity.class);

Registrieren von Soups mit einer Konfigurationsdatei

  1. Legen Sie Ihre Soup-Konfigurationsdateien im Projektordner /res/raw/ ab.
  2. Fügen Sie für jede von Ihnen bereitgestellte Datei eine einzelne Codezeile hinzu.
    • Zum Laden der Datei userstore.json verwenden Sie
      SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
    • Zum Laden der Datei "globalstore.json" verwenden Sie
      SmartStoreSDKManager.getInstance().setupGlobalStoreFromDefaultConfig();

Füllen einer Soup

Beim Registrieren einer Soup erstellen Sie eine leere benannte Struktur im Arbeitsspeicher, die Daten erwartet. Um die Soup mit Daten aus Salesforce zu füllen, wird der normale REST-Anforderungsmechanismus zum Abrufen der Daten verwendet. Extrahieren Sie die Daten nach dem Empfang einer REST-Antwort aus dem Antwortobjekt und übernehmen Sie die Daten in die Soup:

public void populateAccounts() throws UnsupportedEncodingException {
    final RestRequest restRequest =
        RestRequest.getRequestForQuery(
            ApiVersionStrings.getVersionNumber(SalesforceSDKManager.getInstance().getAppContext()), 
            "SELECT Name, Id, OwnerId FROM Account");
    client.sendAsync(restRequest, new RestClient.AsyncRequestCallback() {
        @Override
        public void onSuccess(RestRequest request, RestResponse result) {
            result.consumeQuietly(); // always call before switching to main thread (unlike here)
            try {
                JSONArray records = result.asJSONObject().getJSONArray("records");
                insertAccounts(records);
            } catch (Exception e) {
                onError(e);
            } finally {
                Log.println(Log.INFO, "REST Success!", "\nSmartStore insertion successful");
            }
        }
        @Override
        public void onError(Exception e)
        {
            Log.e(TAG, e.getLocalizedMessage());
        }
    });
 }
/**
 * Inserts accounts into the accounts soup.
 *
 * @param accounts Accounts.
 */
 public void insertAccounts(JSONArray accounts)
 {
    try {
        if (accounts != null) {
            for (int i = 0; i < accounts.length(); i++) {
                if (accounts.get(i) != null) {
                    try {
                        smartStore.upsert("Accounts", accounts.getJSONObject(i));
                    }
                    catch (JSONException exc) {
                        Log.e(TAG, "Error occurred while attempting to insert account. "
                                +  "Please verify validity of JSON data set.");
                    }
                }
            }
        }
    }
    catch (JSONException e) {
        Log.e(TAG, "Error occurred while attempting to insert accounts. "
                + "Please verify validity of JSON data set.");
    }
 }

Abfragen von Soup-Daten mit Smart SQL

Unter Android erstellen Sie Abfragespezifikationsobjekte, indem Sie statische Factory-Methoden für die QuerySpec-Klasse aufrufen. Beispielsweise erzeugt die buildSmartQuerySpec-Methode ein Smart SQL-Objekt, das eine angegebene Abfragezeichenfolge kapselt:

public static QuerySpec buildSmartQuerySpec(String smartSql, int pageSize)

Zum Ausführen der Abfrage übergeben Sie das zurückgegebene QuerySpec-Objekt an die SmartStore.query()-Methode. Diese Funktion bietet mehr Flexibilität als andere Factory-Abfragefunktionen, weil Sie eine eigene Smart SQL SELECT-Anweisung angeben können. Der pageSize-Parameter bestimmt die Anzahl der Datensätze, die an jede Ergebnisseite gesendet werden.

Um eine Abfrage über ein QuerySpec-Objekt auszuführen, übergeben Sie es an die query()-Methode für das SmartStore-Objekt. Der folgende Code gibt eine Abfrage aus, die die SQL-Funktion COUNT aufruft: Da COUNT einen Einzelwert zurückgibt, ist die einzig mögliche Seitengröße 1.

try {
    JSONArray result =
        store.query(QuerySpec.buildSmartQuerySpec(
            "select count(*) from {Accounts}", 1), 0);
    // result should be [[ n ]] if there are n employees
    Log.println(Log.INFO, "REST Success!", "\nFound " + 
        result.getString(0) + " accounts.");
 } catch (JSONException e) {
    Log.e(TAG, "Error occurred while counting the number of account records. "
        +  "Please verify validity of JSON data set.");
 }

Verwalten einer Soup

Wenn Sie Soup-Verwaltungs-APIs in einer nativen Android-Anwendung verwenden möchten, rufen Sie Methoden für die gemeinsame SmartStore-Instanz auf:

SmartStore smartStore = 
    SmartStoreSDKManager.getInstance().getSmartStore();
 smartStore.clearSoup("user1Soup");

Sie können SmartStore-Unterstützung ganz einfach zu einer nativen forcedroid-Anwendung hinzufügen. Lassen Sie uns die JSON-Importdatei so neu konfigurieren, dass zwei Soups erstellt werden, eine für jede sObject-Abfrage. Wir können dann die Soups zur gleichen Zeit wie die Listenansicht auffüllen.

  1. Öffnen Sie Ihr Projektverzeichnis in Android Studio.
  2. Erstellen Sie im Ordner app/res einen Ordner namens "raw".
  3. Klicken Sie mit der rechten Maustaste auf app/res/raw und wählen Sie New > File aus. Nennen Sie die Datei userstore.json.
  4. Fügen Sie der neuen Datei folgenden Text hinzu:
    { "soups": [
        {
        "soupName": "Account",
        "indexes": [
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        },
        {
        "soupName": "Contact",
        "indexes": [ 
            { "path": "Name", "type": "string"},
            { "path": "Id", "type": "string"},
            { "path": "OwnerId", "type": "string"},
            ]
        }
     ]}
  5. Öffnen Sie MainActivity.java und importieren Sie diese Dateien:
    import com.salesforce.androidsdk.smartstore.app.SmartStoreSDKManager;
     import com.salesforce.androidsdk.smartstore.store.IndexSpec;
     import com.salesforce.androidsdk.smartstore.store.QuerySpec;
     import com.salesforce.androidsdk.smartstore.store.SmartStore;
     import com.salesforce.androidsdk.smartstore.ui.SmartStoreInspectorActivity;
  6. Deklarieren Sie am Anfang der MainActivity-Klasse eine private Variable, die auf die gemeinsam genutzte SmartStore-Instanz zeigt, und eine weitere, um zu verfolgen, welches sObject wir bearbeiten:
    private SmartStore smartStore;private String objectType;
  7. Importieren Sie in der onCreate(Bundle savedInstanceState)-Methode die Soup-Definitionen aus Ihrer Datei userstore.json:
    smartStore = SmartStoreSDKManager.getInstance().getSmartStore();
     if (!smartStore.hasSoup("Account") && !smartStore.hasSoup("Contact")) {
        SmartStoreSDKManager.getInstance().setupUserStoreFromDefaultConfig();
     } else {
        // Delete existing records in preparation for new server data
        smartStore.clearSoup("Account");
        smartStore.clearSoup("Contact");
     }
  8. Löschen Sie aus der onFetchContactsClick(View v)-Methode die Soup "Contact", um doppelte Datensätze zu vermeiden:
    smartStore.clearSoup("Contact");
    objectType = "Contact";
  9. Löschen Sie aus der onFetchAccountsClick(View v)-Methode die Soup "Account", um doppelte Datensätze zu vermeiden:
    smartStore.clearSoup("Account");
    objectType = "Account";
  10. Rufen Sie in der client.sendAsync()-Methode upsert() in der for-Schleife auf, die die JSON-Antwort in das listAdapter-Objekt einfügt:
    for (int i = 0; i < records.length(); i++) {
         listAdapter.add(records.getJSONObject(i).getString("Name"));
        try {
             smartStore.upsert((objectType, records.getJSONObject(i));
         } catch (Exception e) {
             onError(e);
         }
    }
  11. Starten Sie die Anwendung und überprüfen Sie dann das Ergebnis im Menü "Dev Tools".
    • Drücken Sie zum Einblenden des Menüs Befehltstaste+M (Mac) oder STRG+M (Windows).
    • Klicken Sie auf Inspect SmartStore.
    • Um eine Liste Ihrer Soups und die Anzahl der Datensätze in jeder Soup zu sehen, klicken Sie auf Soups.
  12. Hinweis: Wenn "Query: No soups found" angezeigt wird, liegt wahrscheinlich ein Fehler in der Datei userstore.json vor.

Sie haben bisher zwei SmartStore-Soups erstellt und aufgefüllt, die aber zu diesem Zeitpunkt noch keinen sinnvollen Zweck erfüllen. In der Praxis erstellen Sie eine Bearbeitungsoberfläche für die Listen "Account" und "Kontakt" und übernehmen dann die Änderungen des Kunden in SmartStore. Wenn das Gerät des Kunden wieder eine Verbindung herstellt, können Sie Änderungen auf dem Server mit Mobile Sync zusammenführen.

Verwenden von SmartStore in Hybrid-Anwendungen

Registrieren von Soups mit einer Konfigurationsdatei

In Hybrid-Anwendungen lädt das Mobile SDK SmartStore-Konfigurationsdateien automatisch. Sie sind dafür verantwortlich, dass Konfigurationsdateien wie folgt am gewünschten Speicherort abgelegt werden:

  1. Kopieren Sie die Konfigurationsdatei in das www/-Verzeichnis auf oberster Ebene Ihres Hybridprojekts (z. B. in MyProject/www/).
  2. Wechseln Sie in einem Terminalfenster oder an der Windows-Eingabeaufforderung über cd zu Ihrem Projektverzeichnis (z. B. MyProject/).
  3. Führen Sie cordova prepare aus.

Füllen einer Soup

Um Salesforce-Datensätze abzurufen, verwenden hybride Anwendungen die Standardfunktion force.query() aus der JavaScript-Bibliothek. Mit dem Erfolgsrückruf können Sie die Daten aus dem Datensatz in die Soup einfügen bzw. die Daten aktualisieren.

force.query("SELECT Name,Id FROM Contact", 
    onSuccessSfdcContacts, onErrorSfdc); 
var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    response.records.forEach(function(contact, i) {
           entries.push(contact);
    });
    if (entries.length > 0) {
        sfSmartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
         onErrorUpsert);
    }
 }
function onErrorSfdc(param) {
    logToConsole()("onErrorSfdc: " + param);
 }
function onErrorUpsert(param) {
    logToConsole()("onErrorUpsert: " + param);
 }

Abfragen von Soup-Daten mit Smart SQL

In Hybrid-Anwendungen erstellen Sie Abfragespezifikationsobjekte, indem Sie Funktionen für das SmartStore-Objekt des Plug-Ins com.salesforce.plugin.smartstore aufrufen. Die buildSmartQuerySpec()-Funktion führt beispielsweise eine Smart SQL-Abfrage aus:

smartstore.buildSmartQuerySpec(smartSql, [pageSize])

Dabei ist smartSql die Abfrage, die ausgeführt werden soll. Diese Funktion bietet mehr Flexibilität als andere Factory-Abfragefunktionen, weil Sie eine eigene SELECT-Anweisung angeben können. pageSize ist optional (Standardwert ist 10).

Der folgende Code gibt eine Abfrage aus, die die Smart SQL-Funktion COUNT für eine Soup namens "employees" aufruft:

var querySpec = 
    navigator.smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
navigator.smartstore.runSmartQuery(querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Verwalten einer Soup

Jede Soup-Verwaltungsfunktion in JavaScript verwendet zwei Rückmeldungsfunktionen: eine Erfolgsrückmeldungsfunktion, die die angeforderten Daten zurückgibt, und eine Fehlerrückmeldungsfunktion. Erfolgsrückmeldungen hängen von den jeweils verwendeten Soup-Verwaltungsfunktionen ab. Fehlerrückmeldungen übernehmen ein einzelnes Argument, das eine Zeichenfolge mit der Fehlerbeschreibung enthält. Sie können beispielsweise wie folgt eine Fehlerrückmeldungsfunktion definieren:

function(e) { alert(“ERROR:“ + e);}

Um eine Soup-Verwaltungsfunktion in JavaScript aufzurufen, müssen Sie zuerst das Cordova-Plug-in aufrufen, um das SmartStore-Objekt zu initialisieren. Anschließend rufen Sie mithilfe des SmartStore-Objekts die Soup-Verwaltungsfunktion auf. Im folgenden Beispiel werden benannte Rückmeldungsfunktionen diskret definiert. Sie können sie jedoch auch inline und anonym definieren.

var sfSmartstore = function() {
    return cordova.require("com.salesforce.plugin.smartstore");};
function onSuccessRemoveSoup(param) {
    logToConsole()("onSuccessRemoveSoup: " + param);
    $("#div_soup_status_line").html("Soup removed: " 
        + SAMPLE_SOUP_NAME);
 }
function onErrorRemoveSoup(param) {
    logToConsole()("onErrorRemoveSoup: " + param);
    $("#div_soup_status_line").html("removeSoup ERROR");
 }
sfSmartstore().removeSoup(SAMPLE_SOUP_NAME,
     onSuccessRemoveSoup, 
     onErrorRemoveSoup);

Verwenden von SmartStore in React Native-Anwendungen

React Native-Anwendungen haben viel mit hybriden Anwendungen gemeinsam. In der Regel teilen sich die SmartStore-Funktionen für beide Plattformen identische Signaturen. Allerdings gibt es einige signifikante Unterschiede.

  • React Native-Anwendungen nutzen ES2015 JavaScript-Code. Sie können zwar die gleiche JavaScript-Syntax wie in hybriden Anwendungen verwenden, aber auch die Vorteile der neuen optimierten Codierungskonventionen nutzen.
  • Neben JavaScript unterstützen React Native-Anwendungen auch TypeScript für statische Eingaben. Sie können auswählen, wie viel oder wie wenig Sie verwenden, oder ob Sie TypeScript überhaupt verwenden möchten.
  • In React Native verwendet SmartStore backbone.js nicht.
  • Sie können in React Native keine Cordova-Hybridbibliotheken oder Plug-Ins verwenden. Stattdessen importieren Sie React Native SmartStore-Module.

Um die SmartStore-API zu verwenden, importieren Sie das smartstore-Modul. Um die Salesforce-API zu verwenden – vor allem für Abfragen zum Abrufen von Salesforce-Datensätzen – importieren Sie das net-Modul. Sie können beide Module in einer einzelnen Anweisung importieren:

import {net, smartstore} from 'react-native-force';

Registrieren einer Soup

Bei React Native verwenden Sie JavaScript-Code statt der Konfigurationsdateien, um SmartStore-Soups einzurichten. Beispiel:

smartstore.registerSoup(false,
    "contacts", 
    [ {path:"Id", type:"string"}, 
    {path:"FirstName", type:"full_text"}, 
    {path:"LastName", type:"full_text"},    
    {path:"__local__", type:"string"} ],
    () => syncDown()
 );

Füllen einer Soup

Um Ihre Soup mit Salesforce-Daten aufzufüllen, beginnen Sie mit der Abfrage nach Datensätzen über die Standard-API von Salesforce. Das net-Modul bietet eine Reihe von Wrapper-Funktionen, die die Netzwerkaufrufe vereinfachen. Sie übergeben einen Query-String sowie Erfolgs- und Fehlerrückrufe. Im Erfolgsrückruf verwenden Sie das smartstore-Modul, um Datensätze aus der Abfrageantwort in Ihre Soup hochzuladen. (Wenn Ihnen diese Vorgehensweise bekannt vorkommt, müssen Sie den Hybrid-Abschnitt gelesen haben!)

net.query("SELECT Name,Id FROM Contact", 
        onSuccessSfdcContacts, onErrorSfdc);

Hier ein Beispiel eines Erfolgsrückrufs.

function onSuccessSfdcContacts(response) {
    logToConsole()("onSuccessSfdcContacts: received " + 
        response.totalSize + “ contacts");
    var entries = [];
    $.each(response.records, function(i, contact) {
           entries.push(contact);
           logToConsole()("name: " + contact.Name);
    });
    if (entries.length > 0) {
        smartstore().upsertSoupEntries(CONTACTS_SOUP_NAME,
            entries,
            function(items) {
                var statusTxt = "upserted: " + items.length + 
                    " contacts";
                logToConsole()(statusTxt);
            }, 
            onErrorUpsert);
    }
 }

Abfragen von Soup-Daten mit Smart SQL

In React Native erstellen Sie Abfragespezifikationsobjekte, indem Sie Funktionen für das smartstore-Modul aufrufen. Die buildSmartQuerySpec()-Funktion erstellt beispielsweise ein Smart SQL-Abfrageobjekt:

buildSmartQuerySpec(smartSql, [pageSize])

Bei dieser Funktion ist smartSql die Abfrage, die ausgeführt werden soll. Diese Funktion bietet mehr Flexibilität als andere Factory-Abfragefunktionen, weil Sie eine eigene SELECT-Anweisung angeben können. pageSize ist optional (Standardwert ist 10).

Nachdem Sie das SmartQuery-Objekt erstellt haben, übergeben Sie es an die runSmartQuery()-Funktion, die einen Erfolgsrückruf zur Verarbeitung der Antwort bereitstellt. Der folgende Code dient zum Erstellen und Ausführen einer Abfrage, die die SQL-Funktion COUNT aufruft.

var querySpec = 
    smartstore.buildSmartQuerySpec(
        "select count(*) from {employees}", 1);
// Note that the first parameter--a storeConfig object, or a Boolean indicating whether to use 
// the default global store or the default user store--is required in React Native apps
// but is optional in hybrid apps
smartstore.runSmartQuery(false, querySpec, function(cursor) { 
    // result should be [[ n ]] if there are n employees
 });

Verwenden von SmartStore-Verwaltungsfunktionen

Soup-Verwaltungsfunktionen folgen dem gleichen Muster wie andere React Native-Funktionen. Sie definieren Erfolgs- und Fehlerrückrufe und rufen die Funktion für das smartstore-Modul auf. Die Anzahl der an den Erfolgsrückruf übergebenen Parameter kann je nach Funktion variieren. Fehlerrückrufe verwenden stets nur ein Zeichenfolgenargument zur Fehlerbeschreibung.

Ressourcen

Teilen Sie Ihr Trailhead-Feedback über die Salesforce-Hilfe.

Wir würden uns sehr freuen, von Ihren Erfahrungen mit Trailhead zu hören: Sie können jetzt jederzeit über die Salesforce-Hilfe auf das neue Feedback-Formular zugreifen.

Weitere Infos Weiter zu "Feedback teilen"